diff options
Diffstat (limited to 'include/net')
96 files changed, 3210 insertions, 1155 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 757a17638b1b..089a09d001d1 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -46,7 +46,8 @@ struct prefix_info { #include <net/if_inet6.h> #include <net/ipv6.h> -#define IN6_ADDR_HSIZE 16 +#define IN6_ADDR_HSIZE_SHIFT 4 +#define IN6_ADDR_HSIZE (1 << IN6_ADDR_HSIZE_SHIFT) extern int addrconf_init(void); extern void addrconf_cleanup(void); @@ -92,7 +93,7 @@ extern void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr); static inline unsigned long addrconf_timeout_fixup(u32 timeout, - unsigned unit) + unsigned int unit) { if (timeout == 0xffffffff) return ~0UL; @@ -131,9 +132,9 @@ extern int ipv6_sock_mc_join(struct sock *sk, int ifindex, extern int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr); extern void ipv6_sock_mc_close(struct sock *sk); -extern int inet6_mc_check(struct sock *sk, - const struct in6_addr *mc_addr, - const struct in6_addr *src_addr); +extern bool inet6_mc_check(struct sock *sk, + const struct in6_addr *mc_addr, + const struct in6_addr *src_addr); extern int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr); extern int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr); @@ -146,10 +147,10 @@ extern void ipv6_mc_init_dev(struct inet6_dev *idev); extern void ipv6_mc_destroy_dev(struct inet6_dev *idev); extern void addrconf_dad_failure(struct inet6_ifaddr *ifp); -extern int ipv6_chk_mcast_addr(struct net_device *dev, - const struct in6_addr *group, - const struct in6_addr *src_addr); -extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr); +extern bool ipv6_chk_mcast_addr(struct net_device *dev, + const struct in6_addr *group, + const struct in6_addr *src_addr); +extern bool ipv6_is_mld(struct sk_buff *skb, int nexthdr); extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao); @@ -163,8 +164,8 @@ extern void ipv6_sock_ac_close(struct sock *sk); extern int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); extern int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); -extern int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, - const struct in6_addr *addr); +extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, + const struct in6_addr *addr); /* Device notifier */ diff --git a/include/net/af_unix.h b/include/net/af_unix.h index ca68e2cef230..b5f8988e4283 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -14,15 +14,16 @@ extern struct sock *unix_get_socket(struct file *filp); extern struct sock *unix_peer_get(struct sock *); #define UNIX_HASH_SIZE 256 +#define UNIX_HASH_BITS 8 extern unsigned int unix_tot_inflight; extern spinlock_t unix_table_lock; -extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; +extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; struct unix_address { atomic_t refcnt; int len; - unsigned hash; + unsigned int hash; struct sockaddr_un name[0]; }; diff --git a/include/net/arp.h b/include/net/arp.h index 4a1f3fb562eb..7f7df93f37cd 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -15,24 +15,31 @@ static inline u32 arp_hashfn(u32 key, const struct net_device *dev, u32 hash_rnd return val * hash_rnd; } -static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key) +static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key) { - struct neigh_hash_table *nht; + struct neigh_hash_table *nht = rcu_dereference_bh(arp_tbl.nht); struct neighbour *n; u32 hash_val; - rcu_read_lock_bh(); - nht = rcu_dereference_bh(arp_tbl.nht); hash_val = arp_hashfn(key, dev, nht->hash_rnd[0]) >> (32 - nht->hash_shift); for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); n != NULL; n = rcu_dereference_bh(n->next)) { - if (n->dev == dev && *(u32 *)n->primary_key == key) { - if (!atomic_inc_not_zero(&n->refcnt)) - n = NULL; - break; - } + if (n->dev == dev && *(u32 *)n->primary_key == key) + return n; } + + return NULL; +} + +static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key) +{ + struct neighbour *n; + + rcu_read_lock_bh(); + n = __ipv4_neigh_lookup_noref(dev, key); + if (n && !atomic_inc_not_zero(&n->refcnt)) + n = NULL; rcu_read_unlock_bh(); return n; diff --git a/include/net/ax25.h b/include/net/ax25.h index 94e09d361bb1..5d2352154cf6 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h @@ -215,7 +215,7 @@ typedef struct ax25_dev { struct ax25_dev *next; struct net_device *dev; struct net_device *forward; - struct ctl_table *systable; + struct ctl_table_header *sysheader; int values[AX25_MAX_VALUES]; #if defined(CONFIG_AX25_DAMA_SLAVE) || defined(CONFIG_AX25_DAMA_MASTER) ax25_dama_info dama; @@ -441,11 +441,11 @@ extern void ax25_uid_free(void); /* sysctl_net_ax25.c */ #ifdef CONFIG_SYSCTL -extern void ax25_register_sysctl(void); -extern void ax25_unregister_sysctl(void); +extern int ax25_register_dev_sysctl(ax25_dev *ax25_dev); +extern void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev); #else -static inline void ax25_register_sysctl(void) {}; -static inline void ax25_unregister_sysctl(void) {}; +static inline int ax25_register_dev_sysctl(ax25_dev *ax25_dev) { return 0; } +static inline void ax25_unregister_dev_sysctl(ax25_dev *ax25_dev) {} #endif /* CONFIG_SYSCTL */ #endif diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h new file mode 100644 index 000000000000..6a76e0a0705e --- /dev/null +++ b/include/net/bluetooth/a2mp.h @@ -0,0 +1,126 @@ +/* + Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved. + Copyright (c) 2011,2012 Intel Corp. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 and + only version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +*/ + +#ifndef __A2MP_H +#define __A2MP_H + +#include <net/bluetooth/l2cap.h> + +#define A2MP_FEAT_EXT 0x8000 + +struct amp_mgr { + struct l2cap_conn *l2cap_conn; + struct l2cap_chan *a2mp_chan; + struct kref kref; + __u8 ident; + __u8 handle; + unsigned long flags; +}; + +struct a2mp_cmd { + __u8 code; + __u8 ident; + __le16 len; + __u8 data[0]; +} __packed; + +/* A2MP command codes */ +#define A2MP_COMMAND_REJ 0x01 +struct a2mp_cmd_rej { + __le16 reason; + __u8 data[0]; +} __packed; + +#define A2MP_DISCOVER_REQ 0x02 +struct a2mp_discov_req { + __le16 mtu; + __le16 ext_feat; +} __packed; + +struct a2mp_cl { + __u8 id; + __u8 type; + __u8 status; +} __packed; + +#define A2MP_DISCOVER_RSP 0x03 +struct a2mp_discov_rsp { + __le16 mtu; + __le16 ext_feat; + struct a2mp_cl cl[0]; +} __packed; + +#define A2MP_CHANGE_NOTIFY 0x04 +#define A2MP_CHANGE_RSP 0x05 + +#define A2MP_GETINFO_REQ 0x06 +struct a2mp_info_req { + __u8 id; +} __packed; + +#define A2MP_GETINFO_RSP 0x07 +struct a2mp_info_rsp { + __u8 id; + __u8 status; + __le32 total_bw; + __le32 max_bw; + __le32 min_latency; + __le16 pal_cap; + __le16 assoc_size; +} __packed; + +#define A2MP_GETAMPASSOC_REQ 0x08 +struct a2mp_amp_assoc_req { + __u8 id; +} __packed; + +#define A2MP_GETAMPASSOC_RSP 0x09 +struct a2mp_amp_assoc_rsp { + __u8 id; + __u8 status; + __u8 amp_assoc[0]; +} __packed; + +#define A2MP_CREATEPHYSLINK_REQ 0x0A +#define A2MP_DISCONNPHYSLINK_REQ 0x0C +struct a2mp_physlink_req { + __u8 local_id; + __u8 remote_id; + __u8 amp_assoc[0]; +} __packed; + +#define A2MP_CREATEPHYSLINK_RSP 0x0B +#define A2MP_DISCONNPHYSLINK_RSP 0x0D +struct a2mp_physlink_rsp { + __u8 local_id; + __u8 remote_id; + __u8 status; +} __packed; + +/* A2MP response status */ +#define A2MP_STATUS_SUCCESS 0x00 +#define A2MP_STATUS_INVALID_CTRL_ID 0x01 +#define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02 +#define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02 +#define A2MP_STATUS_COLLISION_OCCURED 0x03 +#define A2MP_STATUS_DISCONN_REQ_RECVD 0x04 +#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 +#define A2MP_STATUS_SECURITY_VIOLATION 0x06 + +void amp_mgr_get(struct amp_mgr *mgr); +int amp_mgr_put(struct amp_mgr *mgr); +struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, + struct sk_buff *skb); + +#endif /* __A2MP_H */ diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 262ebd1747d4..565d4bee1e49 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -1,4 +1,4 @@ -/* +/* BlueZ - Bluetooth protocol stack for Linux Copyright (C) 2000-2001 Qualcomm Incorporated @@ -12,22 +12,19 @@ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. */ #ifndef __BLUETOOTH_H #define __BLUETOOTH_H -#include <asm/types.h> -#include <asm/byteorder.h> -#include <linux/list.h> #include <linux/poll.h> #include <net/sock.h> @@ -163,8 +160,13 @@ typedef struct { __u8 b[6]; } __packed bdaddr_t; -#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}}) -#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}}) +/* BD Address type */ +#define BDADDR_BREDR 0x00 +#define BDADDR_LE_PUBLIC 0x01 +#define BDADDR_LE_RANDOM 0x02 + +#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0} }) +#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff} }) /* Copy, swap, convert BD Address */ static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2) @@ -178,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src) void baswap(bdaddr_t *dst, bdaddr_t *src); char *batostr(bdaddr_t *ba); -bdaddr_t *strtoba(char *str); /* Common socket structures and functions */ @@ -190,7 +191,12 @@ struct bt_sock { bdaddr_t dst; struct list_head accept_q; struct sock *parent; - u32 defer_setup; + unsigned long flags; +}; + +enum { + BT_SK_DEFER_SETUP, + BT_SK_SUSPEND, }; struct bt_sock_list { @@ -206,7 +212,7 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags); int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags); -uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait); +uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait); int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); @@ -215,14 +221,24 @@ void bt_accept_unlink(struct sock *sk); struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock); /* Skb helpers */ +struct l2cap_ctrl { + unsigned int sframe:1, + poll:1, + final:1, + fcs:1, + sar:2, + super:2; + __u16 reqseq; + __u16 txseq; + __u8 retries; +}; + struct bt_skb_cb { __u8 pkt_type; __u8 incoming; __u16 expect; - __u16 tx_seq; - __u8 retries; - __u8 sar; __u8 force_active; + struct l2cap_ctrl control; }; #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) @@ -230,7 +246,8 @@ static inline struct sk_buff *bt_skb_alloc(unsigned int len, gfp_t how) { struct sk_buff *skb; - if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) { + skb = alloc_skb(len + BT_SKB_RESERVE, how); + if (skb) { skb_reserve(skb, BT_SKB_RESERVE); bt_cb(skb)->incoming = 0; } @@ -242,12 +259,11 @@ static inline struct sk_buff *bt_skb_send_alloc(struct sock *sk, { struct sk_buff *skb; - release_sock(sk); - if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) { + skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err); + if (skb) { skb_reserve(skb, BT_SKB_RESERVE); bt_cb(skb)->incoming = 0; } - lock_sock(sk); if (!skb && *err) return NULL; diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index d47e523c9d83..ccd723e0f783 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -30,6 +30,9 @@ #define HCI_MAX_EVENT_SIZE 260 #define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4) +#define HCI_LINK_KEY_SIZE 16 +#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) + /* HCI dev events */ #define HCI_DEV_REG 1 #define HCI_DEV_UNREG 2 @@ -56,9 +59,12 @@ #define HCI_BREDR 0x00 #define HCI_AMP 0x01 +/* First BR/EDR Controller shall have ID = 0 */ +#define HCI_BREDR_ID 0 + /* HCI device quirks */ enum { - HCI_QUIRK_NO_RESET, + HCI_QUIRK_RESET_ON_CLOSE, HCI_QUIRK_RAW_DEVICE, HCI_QUIRK_FIXUP_BUFFER_SIZE }; @@ -102,6 +108,7 @@ enum { HCI_DISCOVERABLE, HCI_LINK_SECURITY, HCI_PENDING_CLASS, + HCI_PERIODIC_INQ, }; /* HCI ioctl defines */ @@ -132,13 +139,12 @@ enum { #define HCIINQUIRY _IOR('H', 240, int) /* HCI timeouts */ -#define HCI_CONNECT_TIMEOUT (40000) /* 40 seconds */ -#define HCI_DISCONN_TIMEOUT (2000) /* 2 seconds */ -#define HCI_PAIRING_TIMEOUT (60000) /* 60 seconds */ -#define HCI_IDLE_TIMEOUT (6000) /* 6 seconds */ -#define HCI_INIT_TIMEOUT (10000) /* 10 seconds */ -#define HCI_CMD_TIMEOUT (1000) /* 1 seconds */ -#define HCI_ACL_TX_TIMEOUT (45000) /* 45 seconds */ +#define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ +#define HCI_PAIRING_TIMEOUT msecs_to_jiffies(60000) /* 60 seconds */ +#define HCI_INIT_TIMEOUT msecs_to_jiffies(10000) /* 10 seconds */ +#define HCI_CMD_TIMEOUT msecs_to_jiffies(1000) /* 1 second */ +#define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */ +#define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ /* HCI data types */ #define HCI_COMMAND_PKT 0x01 @@ -324,6 +330,8 @@ struct hci_cp_inquiry { #define HCI_OP_INQUIRY_CANCEL 0x0402 +#define HCI_OP_PERIODIC_INQ 0x0403 + #define HCI_OP_EXIT_PERIODIC_INQ 0x0404 #define HCI_OP_CREATE_CONN 0x0405 @@ -368,7 +376,7 @@ struct hci_cp_reject_conn_req { #define HCI_OP_LINK_KEY_REPLY 0x040b struct hci_cp_link_key_reply { bdaddr_t bdaddr; - __u8 link_key[16]; + __u8 link_key[HCI_LINK_KEY_SIZE]; } __packed; #define HCI_OP_LINK_KEY_NEG_REPLY 0x040c @@ -520,6 +528,28 @@ struct hci_cp_io_capability_neg_reply { __u8 reason; } __packed; +#define HCI_OP_CREATE_PHY_LINK 0x0435 +struct hci_cp_create_phy_link { + __u8 phy_handle; + __u8 key_len; + __u8 key_type; + __u8 key[HCI_AMP_LINK_KEY_SIZE]; +} __packed; + +#define HCI_OP_ACCEPT_PHY_LINK 0x0436 +struct hci_cp_accept_phy_link { + __u8 phy_handle; + __u8 key_len; + __u8 key_type; + __u8 key[HCI_AMP_LINK_KEY_SIZE]; +} __packed; + +#define HCI_OP_DISCONN_PHY_LINK 0x0437 +struct hci_cp_disconn_phy_link { + __u8 phy_handle; + __u8 reason; +} __packed; + #define HCI_OP_SNIFF_MODE 0x0803 struct hci_cp_sniff_mode { __le16 handle; @@ -717,6 +747,10 @@ struct hci_rp_read_local_oob_data { } __packed; #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 +struct hci_rp_read_inq_rsp_tx_power { + __u8 status; + __s8 tx_power; +} __packed; #define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 struct hci_rp_read_flow_control_mode { @@ -811,6 +845,31 @@ struct hci_rp_read_local_amp_info { __le32 be_flush_to; } __packed; +#define HCI_OP_READ_LOCAL_AMP_ASSOC 0x140a +struct hci_cp_read_local_amp_assoc { + __u8 phy_handle; + __le16 len_so_far; + __le16 max_len; +} __packed; +struct hci_rp_read_local_amp_assoc { + __u8 status; + __u8 phy_handle; + __le16 rem_len; + __u8 frag[0]; +} __packed; + +#define HCI_OP_WRITE_REMOTE_AMP_ASSOC 0x140b +struct hci_cp_write_remote_amp_assoc { + __u8 phy_handle; + __le16 len_so_far; + __le16 rem_len; + __u8 frag[0]; +} __packed; +struct hci_rp_write_remote_amp_assoc { + __u8 status; + __u8 phy_handle; +} __packed; + #define HCI_OP_LE_SET_EVENT_MASK 0x2001 struct hci_cp_le_set_event_mask { __u8 mask[8]; @@ -1041,7 +1100,7 @@ struct hci_ev_link_key_req { #define HCI_EV_LINK_KEY_NOTIFY 0x18 struct hci_ev_link_key_notify { bdaddr_t bdaddr; - __u8 link_key[16]; + __u8 link_key[HCI_LINK_KEY_SIZE]; __u8 key_type; } __packed; @@ -1137,6 +1196,12 @@ struct extended_inquiry_info { __u8 data[240]; } __packed; +#define HCI_EV_KEY_REFRESH_COMPLETE 0x30 +struct hci_ev_key_refresh_complete { + __u8 status; + __le16 handle; +} __packed; + #define HCI_EV_IO_CAPA_REQUEST 0x31 struct hci_ev_io_capa_request { bdaddr_t bdaddr; @@ -1183,6 +1248,39 @@ struct hci_ev_le_meta { __u8 subevent; } __packed; +#define HCI_EV_PHY_LINK_COMPLETE 0x40 +struct hci_ev_phy_link_complete { + __u8 status; + __u8 phy_handle; +} __packed; + +#define HCI_EV_CHANNEL_SELECTED 0x41 +struct hci_ev_channel_selected { + __u8 phy_handle; +} __packed; + +#define HCI_EV_DISCONN_PHY_LINK_COMPLETE 0x42 +struct hci_ev_disconn_phy_link_complete { + __u8 status; + __u8 phy_handle; + __u8 reason; +} __packed; + +#define HCI_EV_LOGICAL_LINK_COMPLETE 0x45 +struct hci_ev_logical_link_complete { + __u8 status; + __le16 handle; + __u8 phy_handle; + __u8 flow_spec_id; +} __packed; + +#define HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE 0x46 +struct hci_ev_disconn_logical_link_complete { + __u8 status; + __le16 handle; + __u8 reason; +} __packed; + #define HCI_EV_NUM_COMP_BLOCKS 0x48 struct hci_comp_blocks_info { __le16 handle; @@ -1283,7 +1381,6 @@ struct hci_sco_hdr { __u8 dlen; } __packed; -#include <linux/skbuff.h> static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb) { return (struct hci_event_hdr *) skb->data; @@ -1300,12 +1397,12 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb) } /* Command opcode pack/unpack */ -#define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10)) +#define hci_opcode_pack(ogf, ocf) ((__u16) ((ocf & 0x03ff)|(ogf << 10))) #define hci_opcode_ogf(op) (op >> 10) #define hci_opcode_ocf(op) (op & 0x03ff) /* ACL handle and flags pack/unpack */ -#define hci_handle_pack(h, f) (__u16) ((h & 0x0fff)|(f << 12)) +#define hci_handle_pack(h, f) ((__u16) ((h & 0x0fff)|(f << 12))) #define hci_handle(h) (h & 0x0fff) #define hci_flags(h) (h >> 12) @@ -1431,6 +1528,5 @@ struct hci_inquiry_req { #define IREQ_CACHE_FLUSH 0x0001 extern bool enable_hs; -extern bool enable_le; #endif /* __HCI_H */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index db1c5df45224..475b8c04ba52 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -25,7 +25,6 @@ #ifndef __HCI_CORE_H #define __HCI_CORE_H -#include <linux/interrupt.h> #include <net/bluetooth/hci.h> /* HCI priority */ @@ -65,7 +64,7 @@ struct discovery_state { DISCOVERY_RESOLVING, DISCOVERY_STOPPING, } state; - struct list_head all; /* All devices found during inquiry */ + struct list_head all; /* All devices found during inquiry */ struct list_head unknown; /* Name state not known */ struct list_head resolve; /* Name needs to be resolved */ __u32 timestamp; @@ -105,7 +104,7 @@ struct link_key { struct list_head list; bdaddr_t bdaddr; u8 type; - u8 val[16]; + u8 val[HCI_LINK_KEY_SIZE]; u8 pin_len; }; @@ -155,9 +154,14 @@ struct hci_dev { __u16 hci_rev; __u8 lmp_ver; __u16 manufacturer; - __le16 lmp_subver; + __u16 lmp_subver; __u16 voice_setting; __u8 io_capability; + __s8 inq_tx_power; + __u16 devid_source; + __u16 devid_vendor; + __u16 devid_product; + __u16 devid_version; __u16 pkt_type; __u16 esco_type; @@ -250,9 +254,6 @@ struct hci_dev { struct list_head remote_oob_data; - struct list_head adv_entries; - struct delayed_work adv_work; - struct hci_dev_stats stat; struct sk_buff_head driver_init; @@ -263,7 +264,6 @@ struct hci_dev { struct dentry *debugfs; - struct device *parent; struct device dev; struct rfkill *rfkill; @@ -332,6 +332,7 @@ struct hci_conn { void *l2cap_data; void *sco_data; void *smp_conn; + struct amp_mgr *amp_mgr; struct hci_conn *link; @@ -359,7 +360,8 @@ extern int l2cap_connect_cfm(struct hci_conn *hcon, u8 status); extern int l2cap_disconn_ind(struct hci_conn *hcon); extern int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); -extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); +extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, + u16 flags); extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status); @@ -428,8 +430,8 @@ enum { static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; - return (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && - test_bit(HCI_CONN_SSP_ENABLED, &conn->flags)); + return test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && + test_bit(HCI_CONN_SSP_ENABLED, &conn->flags); } static inline void hci_conn_hash_init(struct hci_dev *hdev) @@ -571,7 +573,7 @@ int hci_chan_del(struct hci_chan *chan); void hci_chan_list_flush(struct hci_conn *conn); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u8 sec_level, __u8 auth_type); + __u8 dst_type, __u8 sec_level, __u8 auth_type); int hci_conn_check_link_mode(struct hci_conn *conn); int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); @@ -585,18 +587,24 @@ void hci_conn_put_device(struct hci_conn *conn); static inline void hci_conn_hold(struct hci_conn *conn) { + BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt), + atomic_read(&conn->refcnt) + 1); + atomic_inc(&conn->refcnt); cancel_delayed_work(&conn->disc_work); } static inline void hci_conn_put(struct hci_conn *conn) { + BT_DBG("hcon %p refcnt %d -> %d", conn, atomic_read(&conn->refcnt), + atomic_read(&conn->refcnt) - 1); + if (atomic_dec_and_test(&conn->refcnt)) { unsigned long timeo; if (conn->type == ACL_LINK || conn->type == LE_LINK) { del_timer(&conn->idle_timer); if (conn->state == BT_CONNECTED) { - timeo = msecs_to_jiffies(conn->disc_timeout); + timeo = conn->disc_timeout; if (!conn->out) timeo *= 2; } else { @@ -639,6 +647,19 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) dev_set_drvdata(&hdev->dev, data); } +/* hci_dev_list shall be locked */ +static inline uint8_t __hci_num_ctrl(void) +{ + uint8_t count = 0; + struct list_head *p; + + list_for_each(p, &hci_dev_list) { + count++; + } + + return count; +} + struct hci_dev *hci_dev_get(int index); struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); @@ -660,7 +681,8 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); int hci_inquiry(void __user *arg); -struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr); +struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, + bdaddr_t *bdaddr); int hci_blacklist_clear(struct hci_dev *hdev); int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); @@ -673,8 +695,8 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, - int new_key, u8 authenticated, u8 tk[16], u8 enc_size, u16 ediv, - u8 rand[8]); + int new_key, u8 authenticated, u8 tk[16], u8 enc_size, + __le16 ediv, u8 rand[8]); struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type); int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr); @@ -688,14 +710,6 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, u8 *randomizer); int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); -#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */ -int hci_adv_entries_clear(struct hci_dev *hdev); -struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr); -int hci_add_adv_entry(struct hci_dev *hdev, - struct hci_ev_le_advertising_info *ev); - -void hci_del_off_timer(struct hci_dev *hdev); - void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); int hci_recv_frame(struct sk_buff *skb); @@ -709,7 +723,7 @@ void hci_conn_init_sysfs(struct hci_conn *conn); void hci_conn_add_sysfs(struct hci_conn *conn); void hci_conn_del_sysfs(struct hci_conn *conn); -#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev)) +#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev)) /* ----- LMP capabilities ----- */ #define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH) @@ -933,6 +947,23 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) return false; } +static inline size_t eir_get_length(u8 *eir, size_t eir_len) +{ + size_t parsed = 0; + + while (parsed < eir_len) { + u8 field_len = eir[0]; + + if (field_len == 0) + return parsed; + + parsed += field_len + 1; + eir += field_len + 1; + } + + return eir_len; +} + static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, u8 data_len) { @@ -961,17 +992,12 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb); void hci_sock_dev_event(struct hci_dev *hdev, int event); /* Management interface */ -#define MGMT_ADDR_BREDR 0x00 -#define MGMT_ADDR_LE_PUBLIC 0x01 -#define MGMT_ADDR_LE_RANDOM 0x02 -#define MGMT_ADDR_INVALID 0xff - -#define DISCOV_TYPE_BREDR (BIT(MGMT_ADDR_BREDR)) -#define DISCOV_TYPE_LE (BIT(MGMT_ADDR_LE_PUBLIC) | \ - BIT(MGMT_ADDR_LE_RANDOM)) -#define DISCOV_TYPE_INTERLEAVED (BIT(MGMT_ADDR_BREDR) | \ - BIT(MGMT_ADDR_LE_PUBLIC) | \ - BIT(MGMT_ADDR_LE_RANDOM)) +#define DISCOV_TYPE_BREDR (BIT(BDADDR_BREDR)) +#define DISCOV_TYPE_LE (BIT(BDADDR_LE_PUBLIC) | \ + BIT(BDADDR_LE_RANDOM)) +#define DISCOV_TYPE_INTERLEAVED (BIT(BDADDR_BREDR) | \ + BIT(BDADDR_LE_PUBLIC) | \ + BIT(BDADDR_LE_RANDOM)) int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); int mgmt_index_added(struct hci_dev *hdev); @@ -1067,12 +1093,12 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, u16 to_multiplier); void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], __u8 ltk[16]); -void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]); -void hci_le_ltk_neg_reply(struct hci_conn *conn); - int hci_do_inquiry(struct hci_dev *hdev, u8 length); int hci_cancel_inquiry(struct hci_dev *hdev); int hci_le_scan(struct hci_dev *hdev, u8 type, u16 interval, u16 window, int timeout); +int hci_cancel_le_scan(struct hci_dev *hdev); + +u8 bdaddr_to_le(u8 bdaddr_type); #endif /* __HCI_CORE_H */ diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 9b242c6bf55b..a7679f8913d2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -40,10 +40,11 @@ #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ #define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */ #define L2CAP_DEFAULT_ACK_TO 200 -#define L2CAP_LE_DEFAULT_MTU 23 #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF #define L2CAP_DEFAULT_ACC_LAT 0xFFFFFFFF +#define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */ +#define L2CAP_LE_MIN_MTU 23 #define L2CAP_DISC_TIMEOUT msecs_to_jiffies(100) #define L2CAP_DISC_REJ_TIMEOUT msecs_to_jiffies(5000) @@ -51,12 +52,15 @@ #define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000) #define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000) +#define L2CAP_A2MP_DEFAULT_MTU 670 + /* L2CAP socket address */ struct sockaddr_l2 { sa_family_t l2_family; __le16 l2_psm; bdaddr_t l2_bdaddr; __le16 l2_cid; + __u8 l2_bdaddr_type; }; /* L2CAP socket options */ @@ -139,6 +143,8 @@ struct l2cap_conninfo { #define L2CAP_CTRL_TXSEQ_SHIFT 1 #define L2CAP_CTRL_SUPER_SHIFT 2 +#define L2CAP_CTRL_POLL_SHIFT 4 +#define L2CAP_CTRL_FINAL_SHIFT 7 #define L2CAP_CTRL_REQSEQ_SHIFT 8 #define L2CAP_CTRL_SAR_SHIFT 14 @@ -152,9 +158,11 @@ struct l2cap_conninfo { #define L2CAP_EXT_CTRL_FINAL 0x00000002 #define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */ +#define L2CAP_EXT_CTRL_FINAL_SHIFT 1 #define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2 #define L2CAP_EXT_CTRL_SAR_SHIFT 16 #define L2CAP_EXT_CTRL_SUPER_SHIFT 16 +#define L2CAP_EXT_CTRL_POLL_SHIFT 18 #define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18 /* L2CAP Supervisory Function */ @@ -186,6 +194,8 @@ struct l2cap_hdr { #define L2CAP_FCS_SIZE 2 #define L2CAP_SDULEN_SIZE 2 #define L2CAP_PSMLEN_SIZE 2 +#define L2CAP_ENH_CTRL_SIZE 2 +#define L2CAP_EXT_CTRL_SIZE 4 struct l2cap_cmd_hdr { __u8 code; @@ -221,9 +231,14 @@ struct l2cap_conn_rsp { __le16 status; } __packed; +/* protocol/service multiplexer (PSM) */ +#define L2CAP_PSM_SDP 0x0001 +#define L2CAP_PSM_RFCOMM 0x0003 + /* channel indentifier */ #define L2CAP_CID_SIGNALING 0x0001 #define L2CAP_CID_CONN_LESS 0x0002 +#define L2CAP_CID_A2MP 0x0003 #define L2CAP_CID_LE_DATA 0x0004 #define L2CAP_CID_LE_SIGNALING 0x0005 #define L2CAP_CID_SMP 0x0006 @@ -263,6 +278,9 @@ struct l2cap_conf_rsp { #define L2CAP_CONF_PENDING 0x0004 #define L2CAP_CONF_EFS_REJECT 0x0005 +/* configuration req/rsp continuation flag */ +#define L2CAP_CONF_FLAG_CONTINUATION 0x0001 + struct l2cap_conf_opt { __u8 type; __u8 len; @@ -401,11 +419,16 @@ struct l2cap_conn_param_update_rsp { #define L2CAP_CONN_PARAM_REJECTED 0x0001 /* ----- L2CAP channels and connections ----- */ -struct srej_list { - __u16 tx_seq; - struct list_head list; +struct l2cap_seq_list { + __u16 head; + __u16 tail; + __u16 mask; + __u16 *list; }; +#define L2CAP_SEQ_LIST_CLEAR 0xFFFF +#define L2CAP_SEQ_LIST_TAIL 0x8000 + struct l2cap_chan { struct sock *sk; @@ -441,11 +464,15 @@ struct l2cap_chan { __u16 tx_win; __u16 tx_win_max; + __u16 ack_win; __u8 max_tx; __u16 retrans_timeout; __u16 monitor_timeout; __u16 mps; + __u8 tx_state; + __u8 rx_state; + unsigned long conf_state; unsigned long conn_state; unsigned long flags; @@ -454,12 +481,12 @@ struct l2cap_chan { __u16 expected_ack_seq; __u16 expected_tx_seq; __u16 buffer_seq; - __u16 buffer_seq_srej; __u16 srej_save_reqseq; + __u16 last_acked_seq; __u16 frames_sent; __u16 unacked_frames; __u8 retry_count; - __u8 num_acked; + __u16 srej_queue_next; __u16 sdu_len; struct sk_buff *sdu; struct sk_buff *sdu_last_frag; @@ -490,7 +517,8 @@ struct l2cap_chan { struct sk_buff *tx_send_head; struct sk_buff_head tx_q; struct sk_buff_head srej_q; - struct list_head srej_l; + struct l2cap_seq_list srej_list; + struct l2cap_seq_list retrans_list; struct list_head list; struct list_head global_l; @@ -503,13 +531,16 @@ struct l2cap_chan { struct l2cap_ops { char *name; - struct l2cap_chan *(*new_connection) (void *data); - int (*recv) (void *data, struct sk_buff *skb); - void (*close) (void *data); - void (*state_change) (void *data, int state); + struct l2cap_chan *(*new_connection) (struct l2cap_chan *chan); + int (*recv) (struct l2cap_chan * chan, + struct sk_buff *skb); + void (*teardown) (struct l2cap_chan *chan, int err); + void (*close) (struct l2cap_chan *chan); + void (*state_change) (struct l2cap_chan *chan, + int state); + void (*ready) (struct l2cap_chan *chan); struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, - unsigned long len, int nb, int *err); - + unsigned long len, int nb); }; struct l2cap_conn { @@ -551,6 +582,7 @@ struct l2cap_conn { #define L2CAP_CHAN_RAW 1 #define L2CAP_CHAN_CONN_LESS 2 #define L2CAP_CHAN_CONN_ORIENTED 3 +#define L2CAP_CHAN_CONN_FIX_A2MP 4 /* ----- L2CAP socket info ----- */ #define l2cap_pi(sk) ((struct l2cap_pinfo *) sk) @@ -573,6 +605,7 @@ enum { CONF_EWS_RECV, CONF_LOC_CONF_PEND, CONF_REM_CONF_PEND, + CONF_NOT_COMPLETE, }; #define L2CAP_CONF_MAX_CONF_REQ 2 @@ -600,13 +633,55 @@ enum { FLAG_EFS_ENABLE, }; +enum { + L2CAP_TX_STATE_XMIT, + L2CAP_TX_STATE_WAIT_F, +}; + +enum { + L2CAP_RX_STATE_RECV, + L2CAP_RX_STATE_SREJ_SENT, +}; + +enum { + L2CAP_TXSEQ_EXPECTED, + L2CAP_TXSEQ_EXPECTED_SREJ, + L2CAP_TXSEQ_UNEXPECTED, + L2CAP_TXSEQ_UNEXPECTED_SREJ, + L2CAP_TXSEQ_DUPLICATE, + L2CAP_TXSEQ_DUPLICATE_SREJ, + L2CAP_TXSEQ_INVALID, + L2CAP_TXSEQ_INVALID_IGNORE, +}; + +enum { + L2CAP_EV_DATA_REQUEST, + L2CAP_EV_LOCAL_BUSY_DETECTED, + L2CAP_EV_LOCAL_BUSY_CLEAR, + L2CAP_EV_RECV_REQSEQ_AND_FBIT, + L2CAP_EV_RECV_FBIT, + L2CAP_EV_RETRANS_TO, + L2CAP_EV_MONITOR_TO, + L2CAP_EV_EXPLICIT_POLL, + L2CAP_EV_RECV_IFRAME, + L2CAP_EV_RECV_RR, + L2CAP_EV_RECV_REJ, + L2CAP_EV_RECV_RNR, + L2CAP_EV_RECV_SREJ, + L2CAP_EV_RECV_FRAME, +}; + static inline void l2cap_chan_hold(struct l2cap_chan *c) { + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + atomic_inc(&c->refcnt); } static inline void l2cap_chan_put(struct l2cap_chan *c) { + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + if (atomic_dec_and_test(&c->refcnt)) kfree(c); } @@ -622,21 +697,26 @@ static inline void l2cap_chan_unlock(struct l2cap_chan *chan) } static inline void l2cap_set_timer(struct l2cap_chan *chan, - struct delayed_work *work, long timeout) + struct delayed_work *work, long timeout) { BT_DBG("chan %p state %s timeout %ld", chan, - state_to_string(chan->state), timeout); + state_to_string(chan->state), timeout); + /* If delayed work cancelled do not hold(chan) + since it is already done with previous set_timer */ if (!cancel_delayed_work(work)) l2cap_chan_hold(chan); + schedule_delayed_work(work, timeout); } static inline bool l2cap_clear_timer(struct l2cap_chan *chan, - struct delayed_work *work) + struct delayed_work *work) { bool ret; + /* put(chan) if delayed work cancelled otherwise it + is done in delayed work function */ ret = cancel_delayed_work(work); if (ret) l2cap_chan_put(chan); @@ -646,11 +726,7 @@ static inline bool l2cap_clear_timer(struct l2cap_chan *chan, #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) -#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \ - msecs_to_jiffies(L2CAP_DEFAULT_RETRANS_TO)); #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) -#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \ - msecs_to_jiffies(L2CAP_DEFAULT_MONITOR_TO)); #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ msecs_to_jiffies(L2CAP_DEFAULT_ACK_TO)); @@ -658,13 +734,10 @@ static inline bool l2cap_clear_timer(struct l2cap_chan *chan, static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) { - int offset; - - offset = (seq1 - seq2) % (chan->tx_win_max + 1); - if (offset < 0) - offset += (chan->tx_win_max + 1); - - return offset; + if (seq1 >= seq2) + return seq1 - seq2; + else + return chan->tx_win_max + 1 - seq2 + seq1; } static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq) @@ -672,173 +745,17 @@ static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq) return (seq + 1) % (chan->tx_win_max + 1); } -static inline int l2cap_tx_window_full(struct l2cap_chan *ch) -{ - int sub; - - sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64; - - if (sub < 0) - sub += 64; - - return sub == ch->remote_tx_win; -} - -static inline __u16 __get_reqseq(struct l2cap_chan *chan, __u32 ctrl) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (ctrl & L2CAP_EXT_CTRL_REQSEQ) >> - L2CAP_EXT_CTRL_REQSEQ_SHIFT; - else - return (ctrl & L2CAP_CTRL_REQSEQ) >> L2CAP_CTRL_REQSEQ_SHIFT; -} - -static inline __u32 __set_reqseq(struct l2cap_chan *chan, __u32 reqseq) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (reqseq << L2CAP_EXT_CTRL_REQSEQ_SHIFT) & - L2CAP_EXT_CTRL_REQSEQ; - else - return (reqseq << L2CAP_CTRL_REQSEQ_SHIFT) & L2CAP_CTRL_REQSEQ; -} - -static inline __u16 __get_txseq(struct l2cap_chan *chan, __u32 ctrl) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (ctrl & L2CAP_EXT_CTRL_TXSEQ) >> - L2CAP_EXT_CTRL_TXSEQ_SHIFT; - else - return (ctrl & L2CAP_CTRL_TXSEQ) >> L2CAP_CTRL_TXSEQ_SHIFT; -} - -static inline __u32 __set_txseq(struct l2cap_chan *chan, __u32 txseq) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (txseq << L2CAP_EXT_CTRL_TXSEQ_SHIFT) & - L2CAP_EXT_CTRL_TXSEQ; - else - return (txseq << L2CAP_CTRL_TXSEQ_SHIFT) & L2CAP_CTRL_TXSEQ; -} - -static inline bool __is_sframe(struct l2cap_chan *chan, __u32 ctrl) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return ctrl & L2CAP_EXT_CTRL_FRAME_TYPE; - else - return ctrl & L2CAP_CTRL_FRAME_TYPE; -} - -static inline __u32 __set_sframe(struct l2cap_chan *chan) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return L2CAP_EXT_CTRL_FRAME_TYPE; - else - return L2CAP_CTRL_FRAME_TYPE; -} - -static inline __u8 __get_ctrl_sar(struct l2cap_chan *chan, __u32 ctrl) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (ctrl & L2CAP_EXT_CTRL_SAR) >> L2CAP_EXT_CTRL_SAR_SHIFT; - else - return (ctrl & L2CAP_CTRL_SAR) >> L2CAP_CTRL_SAR_SHIFT; -} - -static inline __u32 __set_ctrl_sar(struct l2cap_chan *chan, __u32 sar) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (sar << L2CAP_EXT_CTRL_SAR_SHIFT) & L2CAP_EXT_CTRL_SAR; - else - return (sar << L2CAP_CTRL_SAR_SHIFT) & L2CAP_CTRL_SAR; -} - -static inline bool __is_sar_start(struct l2cap_chan *chan, __u32 ctrl) -{ - return __get_ctrl_sar(chan, ctrl) == L2CAP_SAR_START; -} - -static inline __u32 __get_sar_mask(struct l2cap_chan *chan) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return L2CAP_EXT_CTRL_SAR; - else - return L2CAP_CTRL_SAR; -} - -static inline __u8 __get_ctrl_super(struct l2cap_chan *chan, __u32 ctrl) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (ctrl & L2CAP_EXT_CTRL_SUPERVISE) >> - L2CAP_EXT_CTRL_SUPER_SHIFT; - else - return (ctrl & L2CAP_CTRL_SUPERVISE) >> L2CAP_CTRL_SUPER_SHIFT; -} - -static inline __u32 __set_ctrl_super(struct l2cap_chan *chan, __u32 super) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return (super << L2CAP_EXT_CTRL_SUPER_SHIFT) & - L2CAP_EXT_CTRL_SUPERVISE; - else - return (super << L2CAP_CTRL_SUPER_SHIFT) & - L2CAP_CTRL_SUPERVISE; -} - -static inline __u32 __set_ctrl_final(struct l2cap_chan *chan) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return L2CAP_EXT_CTRL_FINAL; - else - return L2CAP_CTRL_FINAL; -} - -static inline bool __is_ctrl_final(struct l2cap_chan *chan, __u32 ctrl) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return ctrl & L2CAP_EXT_CTRL_FINAL; - else - return ctrl & L2CAP_CTRL_FINAL; -} - -static inline __u32 __set_ctrl_poll(struct l2cap_chan *chan) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return L2CAP_EXT_CTRL_POLL; - else - return L2CAP_CTRL_POLL; -} - -static inline bool __is_ctrl_poll(struct l2cap_chan *chan, __u32 ctrl) -{ - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return ctrl & L2CAP_EXT_CTRL_POLL; - else - return ctrl & L2CAP_CTRL_POLL; -} - -static inline __u32 __get_control(struct l2cap_chan *chan, void *p) +static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan) { - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return get_unaligned_le32(p); - else - return get_unaligned_le16(p); + return NULL; } -static inline void __put_control(struct l2cap_chan *chan, __u32 control, - void *p) +static inline void l2cap_chan_no_teardown(struct l2cap_chan *chan, int err) { - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return put_unaligned_le32(control, p); - else - return put_unaligned_le16(control, p); } -static inline __u8 __ctrl_size(struct l2cap_chan *chan) +static inline void l2cap_chan_no_ready(struct l2cap_chan *chan) { - if (test_bit(FLAG_EXT_CTRL, &chan->flags)) - return L2CAP_EXT_HDR_SIZE - L2CAP_HDR_SIZE; - else - return L2CAP_ENH_HDR_SIZE - L2CAP_HDR_SIZE; } extern bool disable_ertm; @@ -852,14 +769,18 @@ int __l2cap_wait_ack(struct sock *sk); int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); -struct l2cap_chan *l2cap_chan_create(struct sock *sk); +struct l2cap_chan *l2cap_chan_create(void); void l2cap_chan_close(struct l2cap_chan *chan, int reason); void l2cap_chan_destroy(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, - bdaddr_t *dst); + bdaddr_t *dst, u8 dst_type); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u32 priority); void l2cap_chan_busy(struct l2cap_chan *chan, int busy); int l2cap_chan_check_security(struct l2cap_chan *chan); +void l2cap_chan_set_defaults(struct l2cap_chan *chan); +int l2cap_ertm_init(struct l2cap_chan *chan); +void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); +void l2cap_chan_del(struct l2cap_chan *chan, int err); #endif /* __L2CAP_H */ diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index ebfd91fc20f8..4348ee8bda69 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -341,6 +341,15 @@ struct mgmt_cp_unblock_device { } __packed; #define MGMT_UNBLOCK_DEVICE_SIZE MGMT_ADDR_INFO_SIZE +#define MGMT_OP_SET_DEVICE_ID 0x0028 +struct mgmt_cp_set_device_id { + __le16 source; + __le16 vendor; + __le16 product; + __le16 version; +} __packed; +#define MGMT_SET_DEVICE_ID_SIZE 8 + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -435,7 +444,7 @@ struct mgmt_ev_auth_failed { struct mgmt_ev_device_found { struct mgmt_addr_info addr; __s8 rssi; - __u8 flags[4]; + __le32 flags; __le16 eir_len; __u8 eir[0]; } __packed; diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h index 7b3acdd29134..ca356a734920 100644 --- a/include/net/bluetooth/smp.h +++ b/include/net/bluetooth/smp.h @@ -77,7 +77,7 @@ struct smp_cmd_encrypt_info { #define SMP_CMD_MASTER_IDENT 0x07 struct smp_cmd_master_ident { - __u16 ediv; + __le16 ediv; __u8 rand[8]; } __packed; diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h index 6db8ecf52aa2..bcb9cc3ce98b 100644 --- a/include/net/caif/caif_hsi.h +++ b/include/net/caif/caif_hsi.h @@ -93,25 +93,25 @@ struct cfhsi_desc { #endif /* Structure implemented by the CAIF HSI driver. */ -struct cfhsi_drv { - void (*tx_done_cb) (struct cfhsi_drv *drv); - void (*rx_done_cb) (struct cfhsi_drv *drv); - void (*wake_up_cb) (struct cfhsi_drv *drv); - void (*wake_down_cb) (struct cfhsi_drv *drv); +struct cfhsi_cb_ops { + void (*tx_done_cb) (struct cfhsi_cb_ops *drv); + void (*rx_done_cb) (struct cfhsi_cb_ops *drv); + void (*wake_up_cb) (struct cfhsi_cb_ops *drv); + void (*wake_down_cb) (struct cfhsi_cb_ops *drv); }; /* Structure implemented by HSI device. */ -struct cfhsi_dev { - int (*cfhsi_up) (struct cfhsi_dev *dev); - int (*cfhsi_down) (struct cfhsi_dev *dev); - int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_dev *dev); - int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_dev *dev); - int (*cfhsi_wake_up) (struct cfhsi_dev *dev); - int (*cfhsi_wake_down) (struct cfhsi_dev *dev); - int (*cfhsi_get_peer_wake) (struct cfhsi_dev *dev, bool *status); - int (*cfhsi_fifo_occupancy)(struct cfhsi_dev *dev, size_t *occupancy); - int (*cfhsi_rx_cancel)(struct cfhsi_dev *dev); - struct cfhsi_drv *drv; +struct cfhsi_ops { + int (*cfhsi_up) (struct cfhsi_ops *dev); + int (*cfhsi_down) (struct cfhsi_ops *dev); + int (*cfhsi_tx) (u8 *ptr, int len, struct cfhsi_ops *dev); + int (*cfhsi_rx) (u8 *ptr, int len, struct cfhsi_ops *dev); + int (*cfhsi_wake_up) (struct cfhsi_ops *dev); + int (*cfhsi_wake_down) (struct cfhsi_ops *dev); + int (*cfhsi_get_peer_wake) (struct cfhsi_ops *dev, bool *status); + int (*cfhsi_fifo_occupancy) (struct cfhsi_ops *dev, size_t *occupancy); + int (*cfhsi_rx_cancel)(struct cfhsi_ops *dev); + struct cfhsi_cb_ops *cb_ops; }; /* Structure holds status of received CAIF frames processing */ @@ -123,17 +123,35 @@ struct cfhsi_rx_state { bool piggy_desc; }; +/* Priority mapping */ +enum { + CFHSI_PRIO_CTL = 0, + CFHSI_PRIO_VI, + CFHSI_PRIO_VO, + CFHSI_PRIO_BEBK, + CFHSI_PRIO_LAST, +}; + +struct cfhsi_config { + u32 inactivity_timeout; + u32 aggregation_timeout; + u32 head_align; + u32 tail_align; + u32 q_high_mark; + u32 q_low_mark; +}; + /* Structure implemented by CAIF HSI drivers. */ struct cfhsi { struct caif_dev_common cfdev; struct net_device *ndev; struct platform_device *pdev; - struct sk_buff_head qhead; - struct cfhsi_drv drv; - struct cfhsi_dev *dev; + struct sk_buff_head qhead[CFHSI_PRIO_LAST]; + struct cfhsi_cb_ops cb_ops; + struct cfhsi_ops *ops; int tx_state; struct cfhsi_rx_state rx_state; - unsigned long inactivity_timeout; + struct cfhsi_config cfg; int rx_len; u8 *rx_ptr; u8 *tx_buf; @@ -141,8 +159,6 @@ struct cfhsi { u8 *rx_flip_buf; spinlock_t lock; int flow_off_sent; - u32 q_low_mark; - u32 q_high_mark; struct list_head list; struct work_struct wake_up_work; struct work_struct wake_down_work; @@ -151,11 +167,35 @@ struct cfhsi { wait_queue_head_t wake_up_wait; wait_queue_head_t wake_down_wait; wait_queue_head_t flush_fifo_wait; - struct timer_list timer; + struct timer_list inactivity_timer; struct timer_list rx_slowpath_timer; + + /* TX aggregation */ + int aggregation_len; + struct timer_list aggregation_timer; + unsigned long bits; }; - extern struct platform_driver cfhsi_driver; +/** + * enum ifla_caif_hsi - CAIF HSI NetlinkRT parameters. + * @IFLA_CAIF_HSI_INACTIVITY_TOUT: Inactivity timeout before + * taking the HSI wakeline down, in milliseconds. + * When using RT Netlink to create, destroy or configure a CAIF HSI interface, + * enum ifla_caif_hsi is used to specify the configuration attributes. + */ +enum ifla_caif_hsi { + __IFLA_CAIF_HSI_UNSPEC, + __IFLA_CAIF_HSI_INACTIVITY_TOUT, + __IFLA_CAIF_HSI_AGGREGATION_TOUT, + __IFLA_CAIF_HSI_HEAD_ALIGN, + __IFLA_CAIF_HSI_TAIL_ALIGN, + __IFLA_CAIF_HSI_QHIGH_WATERMARK, + __IFLA_CAIF_HSI_QLOW_WATERMARK, + __IFLA_CAIF_HSI_MAX +}; + +extern struct cfhsi_ops *cfhsi_get_ops(void); + #endif /* CAIF_HSI_H_ */ diff --git a/include/net/caif/cfpkt.h b/include/net/caif/cfpkt.h index 6bd200a4754a..83a89ba3005b 100644 --- a/include/net/caif/cfpkt.h +++ b/include/net/caif/cfpkt.h @@ -188,11 +188,18 @@ struct cfpkt *cfpkt_fromnative(enum caif_direction dir, void *nativepkt); */ void *cfpkt_tonative(struct cfpkt *pkt); - /* * Returns packet information for a packet. * pkt Packet to get info from; * @return Packet information */ struct caif_payload_info *cfpkt_info(struct cfpkt *pkt); + +/** cfpkt_set_prio - set priority for a CAIF packet. + * + * @pkt: The CAIF packet to be adjusted. + * @prio: one of TC_PRIO_ constants. + */ +void cfpkt_set_prio(struct cfpkt *pkt, int prio); + #endif /* CFPKT_H_ */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 83d800c31e3c..493fa0c79005 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -70,11 +70,13 @@ * * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) + * @IEEE80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) * @IEEE80211_NUM_BANDS: number of defined bands */ enum ieee80211_band { IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ, IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ, + IEEE80211_BAND_60GHZ = NL80211_BAND_60GHZ, /* keep last */ IEEE80211_NUM_BANDS @@ -211,6 +213,22 @@ struct ieee80211_sta_ht_cap { }; /** + * struct ieee80211_sta_vht_cap - STA's VHT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11ac VHT capabilities for an STA. + * + * @vht_supported: is VHT supported by the STA + * @cap: VHT capabilities map as described in 802.11ac spec + * @vht_mcs: Supported VHT MCS rates + */ +struct ieee80211_sta_vht_cap { + bool vht_supported; + u32 cap; /* use IEEE80211_VHT_CAP_ */ + struct ieee80211_vht_mcs_info vht_mcs; +}; + +/** * struct ieee80211_supported_band - frequency band definition * * This structure describes a frequency band a wiphy @@ -233,6 +251,7 @@ struct ieee80211_supported_band { int n_channels; int n_bitrates; struct ieee80211_sta_ht_cap ht_cap; + struct ieee80211_sta_vht_cap vht_cap; }; /* @@ -404,6 +423,8 @@ struct cfg80211_beacon_data { * * Used to configure an AP interface. * + * @channel: the channel to start the AP on + * @channel_type: the channel type to use * @beacon: beacon data * @beacon_interval: beacon interval * @dtim_period: DTIM period @@ -417,6 +438,9 @@ struct cfg80211_beacon_data { * @inactivity_timeout: time in seconds to determine station's inactivity. */ struct cfg80211_ap_settings { + struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type; + struct cfg80211_beacon_data beacon; int beacon_interval, dtim_period; @@ -521,6 +545,7 @@ struct station_parameters { * @STATION_INFO_ASSOC_REQ_IES: @assoc_req_ies filled * @STATION_INFO_STA_FLAGS: @sta_flags filled * @STATION_INFO_BEACON_LOSS_COUNT: @beacon_loss_count filled + * @STATION_INFO_T_OFFSET: @t_offset filled */ enum station_info_flags { STATION_INFO_INACTIVE_TIME = 1<<0, @@ -542,7 +567,8 @@ enum station_info_flags { STATION_INFO_CONNECTED_TIME = 1<<16, STATION_INFO_ASSOC_REQ_IES = 1<<17, STATION_INFO_STA_FLAGS = 1<<18, - STATION_INFO_BEACON_LOSS_COUNT = 1<<19 + STATION_INFO_BEACON_LOSS_COUNT = 1<<19, + STATION_INFO_T_OFFSET = 1<<20, }; /** @@ -554,11 +580,13 @@ enum station_info_flags { * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval + * @RATE_INFO_FLAGS_60G: 60gHz MCS */ enum rate_info_flags { RATE_INFO_FLAGS_MCS = 1<<0, RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, RATE_INFO_FLAGS_SHORT_GI = 1<<2, + RATE_INFO_FLAGS_60G = 1<<3, }; /** @@ -620,10 +648,10 @@ struct sta_bss_parameters { * @llid: mesh local link id * @plid: mesh peer link id * @plink_state: mesh peer link state - * @signal: the signal strength, type depends on the wiphy's signal_type - NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. - * @signal_avg: avg signal strength, type depends on the wiphy's signal_type - NOTE: For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. + * @signal: The signal strength, type depends on the wiphy's signal_type. + * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. + * @signal_avg: Average signal strength, type depends on the wiphy's signal_type. + * For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_. * @txrate: current unicast bitrate from this station * @rxrate: current unicast bitrate to this station * @rx_packets: packets received from this station @@ -643,6 +671,7 @@ struct sta_bss_parameters { * @assoc_req_ies_len: Length of assoc_req_ies buffer in octets. * @sta_flags: station flags mask & values * @beacon_loss_count: Number of times beacon loss event has triggered. + * @t_offset: Time offset of the station relative to this host. */ struct station_info { u32 filled; @@ -671,6 +700,7 @@ struct station_info { size_t assoc_req_ies_len; u32 beacon_loss_count; + s64 t_offset; /* * Note: Add a new enum station_info_flags value for each new field and @@ -781,46 +811,104 @@ struct bss_parameters { int ht_opmode; }; -/* +/** * struct mesh_config - 802.11s mesh configuration * * These parameters can be changed while the mesh is active. + * + * @dot11MeshRetryTimeout: the initial retry timeout in millisecond units used + * by the Mesh Peering Open message + * @dot11MeshConfirmTimeout: the initial retry timeout in millisecond units + * used by the Mesh Peering Open message + * @dot11MeshHoldingTimeout: the confirm timeout in millisecond units used by + * the mesh peering management to close a mesh peering + * @dot11MeshMaxPeerLinks: the maximum number of peer links allowed on this + * mesh interface + * @dot11MeshMaxRetries: the maximum number of peer link open retries that can + * be sent to establish a new peer link instance in a mesh + * @dot11MeshTTL: the value of TTL field set at a source mesh STA + * @element_ttl: the value of TTL field set at a mesh STA for path selection + * elements + * @auto_open_plinks: whether we should automatically open peer links when we + * detect compatible mesh peers + * @dot11MeshNbrOffsetMaxNeighbor: the maximum number of neighbors to + * synchronize to for 11s default synchronization method + * @dot11MeshHWMPmaxPREQretries: the number of action frames containing a PREQ + * that an originator mesh STA can send to a particular path target + * @path_refresh_time: how frequently to refresh mesh paths in milliseconds + * @min_discovery_timeout: the minimum length of time to wait until giving up on + * a path discovery in milliseconds + * @dot11MeshHWMPactivePathTimeout: the time (in TUs) for which mesh STAs + * receiving a PREQ shall consider the forwarding information from the + * root to be valid. (TU = time unit) + * @dot11MeshHWMPpreqMinInterval: the minimum interval of time (in TUs) during + * which a mesh STA can send only one action frame containing a PREQ + * element + * @dot11MeshHWMPperrMinInterval: the minimum interval of time (in TUs) during + * which a mesh STA can send only one Action frame containing a PERR + * element + * @dot11MeshHWMPnetDiameterTraversalTime: the interval of time (in TUs) that + * it takes for an HWMP information element to propagate across the mesh + * @dot11MeshHWMPRootMode: the configuration of a mesh STA as root mesh STA + * @dot11MeshHWMPRannInterval: the interval of time (in TUs) between root + * announcements are transmitted + * @dot11MeshGateAnnouncementProtocol: whether to advertise that this mesh + * station has access to a broader network beyond the MBSS. (This is + * missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol set to true + * only means that the station will announce others it's a mesh gate, but + * not necessarily using the gate announcement protocol. Still keeping the + * same nomenclature to be in sync with the spec) + * @dot11MeshForwarding: whether the Mesh STA is forwarding or non-forwarding + * entity (default is TRUE - forwarding entity) + * @rssi_threshold: the threshold for average signal strength of candidate + * station to establish a peer link + * @ht_opmode: mesh HT protection mode + * + * @dot11MeshHWMPactivePathToRootTimeout: The time (in TUs) for which mesh STAs + * receiving a proactive PREQ shall consider the forwarding information to + * the root mesh STA to be valid. + * + * @dot11MeshHWMProotInterval: The interval of time (in TUs) between proactive + * PREQs are transmitted. + * @dot11MeshHWMPconfirmationInterval: The minimum interval of time (in TUs) + * during which a mesh STA can send only one Action frame containing + * a PREQ element for root path confirmation. */ struct mesh_config { - /* Timeouts in ms */ - /* Mesh plink management parameters */ u16 dot11MeshRetryTimeout; u16 dot11MeshConfirmTimeout; u16 dot11MeshHoldingTimeout; u16 dot11MeshMaxPeerLinks; - u8 dot11MeshMaxRetries; - u8 dot11MeshTTL; - /* ttl used in path selection information elements */ - u8 element_ttl; + u8 dot11MeshMaxRetries; + u8 dot11MeshTTL; + u8 element_ttl; bool auto_open_plinks; - /* HWMP parameters */ - u8 dot11MeshHWMPmaxPREQretries; + u32 dot11MeshNbrOffsetMaxNeighbor; + u8 dot11MeshHWMPmaxPREQretries; u32 path_refresh_time; u16 min_discovery_timeout; u32 dot11MeshHWMPactivePathTimeout; u16 dot11MeshHWMPpreqMinInterval; u16 dot11MeshHWMPperrMinInterval; u16 dot11MeshHWMPnetDiameterTraversalTime; - u8 dot11MeshHWMPRootMode; + u8 dot11MeshHWMPRootMode; u16 dot11MeshHWMPRannInterval; - /* This is missnamed in draft 12.0: dot11MeshGateAnnouncementProtocol - * set to true only means that the station will announce others it's a - * mesh gate, but not necessarily using the gate announcement protocol. - * Still keeping the same nomenclature to be in sync with the spec. */ - bool dot11MeshGateAnnouncementProtocol; + bool dot11MeshGateAnnouncementProtocol; bool dot11MeshForwarding; s32 rssi_threshold; + u16 ht_opmode; + u32 dot11MeshHWMPactivePathToRootTimeout; + u16 dot11MeshHWMProotInterval; + u16 dot11MeshHWMPconfirmationInterval; }; /** * struct mesh_setup - 802.11s mesh setup configuration + * @channel: the channel to start the mesh network on + * @channel_type: the channel type to use * @mesh_id: the mesh ID * @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes + * @sync_method: which synchronization method to use * @path_sel_proto: which path selection protocol to use * @path_metric: which metric to use * @ie: vendor information elements (optional) @@ -832,10 +920,13 @@ struct mesh_config { * These parameters are fixed when the mesh is created. */ struct mesh_setup { + struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type; const u8 *mesh_id; u8 mesh_id_len; - u8 path_sel_proto; - u8 path_metric; + u8 sync_method; + u8 path_sel_proto; + u8 path_metric; const u8 *ie; u8 ie_len; bool is_authenticated; @@ -845,7 +936,7 @@ struct mesh_setup { /** * struct ieee80211_txq_params - TX queue parameters - * @queue: TX queue identifier (NL80211_TXQ_Q_*) + * @ac: AC identifier * @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled * @cwmin: Minimum contention window [a value of the form 2^n-1 in the range * 1..32767] @@ -854,7 +945,7 @@ struct mesh_setup { * @aifs: Arbitration interframe space [0..255] */ struct ieee80211_txq_params { - enum nl80211_txq_q queue; + enum nl80211_ac ac; u16 txop; u16 cwmin; u16 cwmax; @@ -908,7 +999,7 @@ struct cfg80211_ssid { * @ie_len: length of ie in octets * @rates: bitmap of rates to advertise for each band * @wiphy: the wiphy this was for - * @dev: the interface + * @wdev: the wireless device to scan for * @aborted: (internal) scan request was notified as aborted * @no_cck: used to send probe requests at non CCK rate in 2GHz band */ @@ -921,9 +1012,10 @@ struct cfg80211_scan_request { u32 rates[IEEE80211_NUM_BANDS]; + struct wireless_dev *wdev; + /* internal */ struct wiphy *wiphy; - struct net_device *dev; bool aborted; bool no_cck; @@ -957,6 +1049,7 @@ struct cfg80211_match_set { * @wiphy: the wiphy this was for * @dev: the interface * @channels: channels to scan + * @rssi_thold: don't report scan results below this threshold (in s32 dBm) */ struct cfg80211_sched_scan_request { struct cfg80211_ssid *ssids; @@ -967,6 +1060,7 @@ struct cfg80211_sched_scan_request { size_t ie_len; struct cfg80211_match_set *match_sets; int n_match_sets; + s32 rssi_thold; /* internal */ struct wiphy *wiphy; @@ -1336,13 +1430,16 @@ struct cfg80211_gtk_rekey_data { * be %NULL or contain the enabled Wake-on-Wireless triggers that are * configured for the device. * @resume: wiphy device needs to be resumed + * @set_wakeup: Called when WoWLAN is enabled/disabled, use this callback + * to call device_set_wakeup_enable() to enable/disable wakeup from + * the device. * * @add_virtual_intf: create a new virtual interface with the given name, * must set the struct wireless_dev's iftype. Beware: You must create - * the new netdev in the wiphy's network namespace! Returns the netdev, - * or an ERR_PTR. + * the new netdev in the wiphy's network namespace! Returns the struct + * wireless_dev, or an ERR_PTR. * - * @del_virtual_intf: remove the virtual interface determined by ifindex. + * @del_virtual_intf: remove the virtual interface * * @change_virtual_intf: change type/configuration of virtual interface, * keep the struct wireless_dev's iftype updated. @@ -1399,14 +1496,14 @@ struct cfg80211_gtk_rekey_data { * * @set_txq_params: Set TX queue parameters * - * @set_channel: Set channel for a given wireless interface. Some devices - * may support multi-channel operation (by channel hopping) so cfg80211 - * doesn't verify much. Note, however, that the passed netdev may be - * %NULL as well if the user requested changing the channel for the - * device itself, or for a monitor interface. - * @get_channel: Get the current operating channel, should return %NULL if - * there's no single defined operating channel if for example the - * device implements channel hopping for multi-channel virtual interfaces. + * @libertas_set_mesh_channel: Only for backward compatibility for libertas, + * as it doesn't implement join_mesh and needs to set the channel to + * join the mesh instead. + * + * @set_monitor_channel: Set the monitor mode channel for the device. If other + * interfaces are active this callback should reject the configuration. + * If no interfaces are active or the device is down, the channel should + * be stored for when a monitor interface becomes active. * * @scan: Request to do a scan. If returning zero, the scan request is given * the driver, and will be valid until passed to cfg80211_scan_done(). @@ -1476,6 +1573,8 @@ struct cfg80211_gtk_rekey_data { * @set_power_mgmt: Configure WLAN power management. A timeout value of -1 * allows the driver to adjust the dynamic ps timeout value. * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. + * @set_cqm_txe_config: Configure connection quality monitor TX error + * thresholds. * @sched_scan_start: Tell the driver to start a scheduled scan. * @sched_scan_stop: Tell the driver to stop an ongoing scheduled * scan. The driver_initiated flag specifies whether the driver @@ -1503,17 +1602,33 @@ struct cfg80211_gtk_rekey_data { * later passes to cfg80211_probe_status(). * * @set_noack_map: Set the NoAck Map for the TIDs. + * + * @get_et_sset_count: Ethtool API to get string-set count. + * See @ethtool_ops.get_sset_count + * + * @get_et_stats: Ethtool API to get a set of u64 stats. + * See @ethtool_ops.get_ethtool_stats + * + * @get_et_strings: Ethtool API to get a set of strings to describe stats + * and perhaps other supported types of ethtool data-sets. + * See @ethtool_ops.get_strings + * + * @get_channel: Get the current operating channel for the virtual interface. + * For monitor interfaces, it should return %NULL unless there's a single + * current monitoring channel. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); int (*resume)(struct wiphy *wiphy); - - struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, - char *name, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params); - int (*del_virtual_intf)(struct wiphy *wiphy, struct net_device *dev); + void (*set_wakeup)(struct wiphy *wiphy, bool enabled); + + struct wireless_dev * (*add_virtual_intf)(struct wiphy *wiphy, + char *name, + enum nl80211_iftype type, + u32 *flags, + struct vif_params *params); + int (*del_virtual_intf)(struct wiphy *wiphy, + struct wireless_dev *wdev); int (*change_virtual_intf)(struct wiphy *wiphy, struct net_device *dev, enum nl80211_iftype type, u32 *flags, @@ -1582,11 +1697,15 @@ struct cfg80211_ops { int (*set_txq_params)(struct wiphy *wiphy, struct net_device *dev, struct ieee80211_txq_params *params); - int (*set_channel)(struct wiphy *wiphy, struct net_device *dev, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type); + int (*libertas_set_mesh_channel)(struct wiphy *wiphy, + struct net_device *dev, + struct ieee80211_channel *chan); + + int (*set_monitor_channel)(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); - int (*scan)(struct wiphy *wiphy, struct net_device *dev, + int (*scan)(struct wiphy *wiphy, struct cfg80211_scan_request *request); int (*auth)(struct wiphy *wiphy, struct net_device *dev, @@ -1640,23 +1759,23 @@ struct cfg80211_ops { int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev); int (*remain_on_channel)(struct wiphy *wiphy, - struct net_device *dev, + struct wireless_dev *wdev, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, unsigned int duration, u64 *cookie); int (*cancel_remain_on_channel)(struct wiphy *wiphy, - struct net_device *dev, + struct wireless_dev *wdev, u64 cookie); - int (*mgmt_tx)(struct wiphy *wiphy, struct net_device *dev, + int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev, struct ieee80211_channel *chan, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, const u8 *buf, size_t len, bool no_cck, bool dont_wait_for_ack, u64 *cookie); int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy, - struct net_device *dev, + struct wireless_dev *wdev, u64 cookie); int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, @@ -1666,8 +1785,12 @@ struct cfg80211_ops { struct net_device *dev, s32 rssi_thold, u32 rssi_hyst); + int (*set_cqm_txe_config)(struct wiphy *wiphy, + struct net_device *dev, + u32 rate, u32 pkts, u32 intvl); + void (*mgmt_frame_register)(struct wiphy *wiphy, - struct net_device *dev, + struct wireless_dev *wdev, u16 frame_type, bool reg); int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant); @@ -1698,7 +1821,17 @@ struct cfg80211_ops { struct net_device *dev, u16 noack_map); - struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy); + int (*get_et_sset_count)(struct wiphy *wiphy, + struct net_device *dev, int sset); + void (*get_et_stats)(struct wiphy *wiphy, struct net_device *dev, + struct ethtool_stats *stats, u64 *data); + void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev, + u32 sset, u8 *data); + + struct ieee80211_channel * + (*get_channel)(struct wiphy *wiphy, + struct wireless_dev *wdev, + enum nl80211_channel_type *type); }; /* @@ -1732,10 +1865,6 @@ struct cfg80211_ops { * hints read the documenation for regulatory_hint_found_beacon() * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this * wiphy at all - * @WIPHY_FLAG_ENFORCE_COMBINATIONS: Set this flag to enforce interface - * combinations for this device. This flag is used for backward - * compatibility only until all drivers advertise combinations and - * they will always be enforced. * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled * by default -- this flag will be set depending on the kernel's default * on wiphy_new(), but can be changed by the driver if it has a good @@ -1780,7 +1909,7 @@ enum wiphy_flags { WIPHY_FLAG_IBSS_RSN = BIT(8), WIPHY_FLAG_MESH_AUTH = BIT(10), WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), - WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12), + /* use hole at 12 */ WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13), WIPHY_FLAG_AP_UAPSD = BIT(14), WIPHY_FLAG_SUPPORTS_TDLS = BIT(15), @@ -2056,7 +2185,9 @@ struct wiphy { char fw_version[ETHTOOL_BUSINFO_LEN]; u32 hw_version; +#ifdef CONFIG_PM struct wiphy_wowlan_support wowlan; +#endif u16 max_remain_on_channel_duration; @@ -2223,20 +2354,31 @@ struct cfg80211_internal_bss; struct cfg80211_cached_keys; /** - * struct wireless_dev - wireless per-netdev state + * struct wireless_dev - wireless device state * - * This structure must be allocated by the driver/stack - * that uses the ieee80211_ptr field in struct net_device - * (this is intentional so it can be allocated along with - * the netdev.) + * For netdevs, this structure must be allocated by the driver + * that uses the ieee80211_ptr field in struct net_device (this + * is intentional so it can be allocated along with the netdev.) + * It need not be registered then as netdev registration will + * be intercepted by cfg80211 to see the new wireless device. + * + * For non-netdev uses, it must also be allocated by the driver + * in response to the cfg80211 callbacks that require it, as + * there's no netdev registration in that case it may not be + * allocated outside of callback operations that return it. * * @wiphy: pointer to hardware description * @iftype: interface type * @list: (private) Used to collect the interfaces - * @netdev: (private) Used to reference back to the netdev + * @netdev: (private) Used to reference back to the netdev, may be %NULL + * @identifier: (private) Identifier used in nl80211 to identify this + * wireless device if it has no netdev * @current_bss: (private) Used by the internal configuration code * @channel: (private) Used by the internal configuration code to track - * user-set AP, monitor and WDS channels for wireless extensions + * the user-set AP, monitor and WDS channel + * @preset_chan: (private) Used by the internal configuration code to + * track the channel to be used for AP later + * @preset_chantype: (private) the corresponding channel type * @bssid: (private) Used by the internal configuration code * @ssid: (private) Used by the internal configuration code * @ssid_len: (private) Used by the internal configuration code @@ -2262,6 +2404,8 @@ struct wireless_dev { struct list_head list; struct net_device *netdev; + u32 identifier; + struct list_head mgmt_registrations; spinlock_t mgmt_registrations_lock; @@ -2286,8 +2430,14 @@ struct wireless_dev { spinlock_t event_lock; struct cfg80211_internal_bss *current_bss; /* associated / joined */ + struct ieee80211_channel *preset_chan; + enum nl80211_channel_type preset_chantype; + + /* for AP and mesh channel tracking */ struct ieee80211_channel *channel; + bool ibss_fixed; + bool ps; int ps_timeout; @@ -3142,7 +3292,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, /** * cfg80211_ready_on_channel - notification of remain_on_channel start - * @dev: network device + * @wdev: wireless device * @cookie: the request cookie * @chan: The current channel (from remain_on_channel request) * @channel_type: Channel type @@ -3150,21 +3300,20 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason, * channel * @gfp: allocation flags */ -void cfg80211_ready_on_channel(struct net_device *dev, u64 cookie, +void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, unsigned int duration, gfp_t gfp); /** * cfg80211_remain_on_channel_expired - remain_on_channel duration expired - * @dev: network device + * @wdev: wireless device * @cookie: the request cookie * @chan: The current channel (from remain_on_channel request) * @channel_type: Channel type * @gfp: allocation flags */ -void cfg80211_remain_on_channel_expired(struct net_device *dev, - u64 cookie, +void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie, struct ieee80211_channel *chan, enum nl80211_channel_type channel_type, gfp_t gfp); @@ -3192,7 +3341,7 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); /** * cfg80211_rx_mgmt - notification of received, unprocessed management frame - * @dev: network device + * @wdev: wireless device receiving the frame * @freq: Frequency on which the frame was received in MHz * @sig_dbm: signal strength in mBm, or 0 if unknown * @buf: Management frame (header + body) @@ -3207,12 +3356,12 @@ void cfg80211_del_sta(struct net_device *dev, const u8 *mac_addr, gfp_t gfp); * This function is called whenever an Action frame is received for a station * mode interface, but is not processed in kernel. */ -bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm, +bool cfg80211_rx_mgmt(struct wireless_dev *wdev, int freq, int sig_dbm, const u8 *buf, size_t len, gfp_t gfp); /** * cfg80211_mgmt_tx_status - notification of TX status for management frame - * @dev: network device + * @wdev: wireless device receiving the frame * @cookie: Cookie returned by cfg80211_ops::mgmt_tx() * @buf: Management frame (header + body) * @len: length of the frame data @@ -3223,7 +3372,7 @@ bool cfg80211_rx_mgmt(struct net_device *dev, int freq, int sig_dbm, * transmitted with cfg80211_ops::mgmt_tx() to report the TX status of the * transmission attempt. */ -void cfg80211_mgmt_tx_status(struct net_device *dev, u64 cookie, +void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, const u8 *buf, size_t len, bool ack, gfp_t gfp); @@ -3253,6 +3402,21 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev, const u8 *peer, u32 num_packets, gfp_t gfp); /** + * cfg80211_cqm_txe_notify - TX error rate event + * @dev: network device + * @peer: peer's MAC address + * @num_packets: how many packets were lost + * @rate: % of packets which failed transmission + * @intvl: interval (in s) over which the TX failure threshold was breached. + * @gfp: context flags + * + * Notify userspace when configured % TX failures over number of packets in a + * given interval is exceeded. + */ +void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer, + u32 num_packets, u32 rate, u32 intvl, gfp_t gfp); + +/** * cfg80211_gtk_rekey_notify - notify userspace about driver rekeying * @dev: network device * @bssid: BSSID of AP (to avoid races) @@ -3332,15 +3496,29 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, const u8 *frame, size_t len, int freq, int sig_dbm, gfp_t gfp); -/* +/** * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used * @wiphy: the wiphy * @chan: main channel * @channel_type: HT mode + * + * This function returns true if there is no secondary channel or the secondary + * channel can be used for beaconing (i.e. is not a radar channel etc.) + */ +bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); + +/* + * cfg80211_ch_switch_notify - update wdev channel and notify userspace + * @dev: the device which switched channels + * @freq: new channel frequency (in MHz) + * @type: channel type + * + * Acquires wdev_lock, so must only be called from sleepable driver context! */ -int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type); +void cfg80211_ch_switch_notify(struct net_device *dev, int freq, + enum nl80211_channel_type type); /* * cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units) @@ -3348,7 +3526,7 @@ int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, * * return 0 if MCS index >= 32 */ -u16 cfg80211_calculate_bitrate(struct rate_info *rate); +u32 cfg80211_calculate_bitrate(struct rate_info *rate); /* Logging, debugging and troubleshooting/diagnostic helpers. */ diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 9808877c2ab9..a7a683e30b64 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -42,6 +42,7 @@ #include <net/netlabel.h> #include <net/request_sock.h> #include <linux/atomic.h> +#include <asm/unaligned.h> /* known doi values */ #define CIPSO_V4_DOI_UNKNOWN 0x00000000 @@ -285,7 +286,33 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, static inline int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) { - return -ENOSYS; + unsigned char *opt = *option; + unsigned char err_offset = 0; + u8 opt_len = opt[1]; + u8 opt_iter; + + if (opt_len < 8) { + err_offset = 1; + goto out; + } + + if (get_unaligned_be32(&opt[2]) == 0) { + err_offset = 2; + goto out; + } + + for (opt_iter = 6; opt_iter < opt_len;) { + if (opt[opt_iter + 1] > (opt_len - opt_iter)) { + err_offset = opt_iter + 1; + goto out; + } + opt_iter += opt[opt_iter + 1]; + } + +out: + *option = opt + err_offset; + return err_offset; + } #endif /* CONFIG_NETLABEL */ diff --git a/include/net/codel.h b/include/net/codel.h new file mode 100644 index 000000000000..550debfc2403 --- /dev/null +++ b/include/net/codel.h @@ -0,0 +1,342 @@ +#ifndef __NET_SCHED_CODEL_H +#define __NET_SCHED_CODEL_H + +/* + * Codel - The Controlled-Delay Active Queue Management algorithm + * + * Copyright (C) 2011-2012 Kathleen Nichols <nichols@pollere.com> + * Copyright (C) 2011-2012 Van Jacobson <van@pollere.net> + * Copyright (C) 2012 Michael D. Taht <dave.taht@bufferbloat.net> + * Copyright (C) 2012 Eric Dumazet <edumazet@google.com> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * Alternatively, provided that this notice is retained in full, this + * software may be distributed under the terms of the GNU General + * Public License ("GPL") version 2, in which case the provisions of the + * GPL apply INSTEAD OF those given above. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + */ + +#include <linux/types.h> +#include <linux/ktime.h> +#include <linux/skbuff.h> +#include <net/pkt_sched.h> +#include <net/inet_ecn.h> +#include <linux/reciprocal_div.h> + +/* Controlling Queue Delay (CoDel) algorithm + * ========================================= + * Source : Kathleen Nichols and Van Jacobson + * http://queue.acm.org/detail.cfm?id=2209336 + * + * Implemented on linux by Dave Taht and Eric Dumazet + */ + + +/* CoDel uses a 1024 nsec clock, encoded in u32 + * This gives a range of 2199 seconds, because of signed compares + */ +typedef u32 codel_time_t; +typedef s32 codel_tdiff_t; +#define CODEL_SHIFT 10 +#define MS2TIME(a) ((a * NSEC_PER_MSEC) >> CODEL_SHIFT) + +static inline codel_time_t codel_get_time(void) +{ + u64 ns = ktime_to_ns(ktime_get()); + + return ns >> CODEL_SHIFT; +} + +#define codel_time_after(a, b) ((s32)(a) - (s32)(b) > 0) +#define codel_time_after_eq(a, b) ((s32)(a) - (s32)(b) >= 0) +#define codel_time_before(a, b) ((s32)(a) - (s32)(b) < 0) +#define codel_time_before_eq(a, b) ((s32)(a) - (s32)(b) <= 0) + +/* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */ +struct codel_skb_cb { + codel_time_t enqueue_time; +}; + +static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb) +{ + qdisc_cb_private_validate(skb, sizeof(struct codel_skb_cb)); + return (struct codel_skb_cb *)qdisc_skb_cb(skb)->data; +} + +static codel_time_t codel_get_enqueue_time(const struct sk_buff *skb) +{ + return get_codel_cb(skb)->enqueue_time; +} + +static void codel_set_enqueue_time(struct sk_buff *skb) +{ + get_codel_cb(skb)->enqueue_time = codel_get_time(); +} + +static inline u32 codel_time_to_us(codel_time_t val) +{ + u64 valns = ((u64)val << CODEL_SHIFT); + + do_div(valns, NSEC_PER_USEC); + return (u32)valns; +} + +/** + * struct codel_params - contains codel parameters + * @target: target queue size (in time units) + * @interval: width of moving time window + * @ecn: is Explicit Congestion Notification enabled + */ +struct codel_params { + codel_time_t target; + codel_time_t interval; + bool ecn; +}; + +/** + * struct codel_vars - contains codel variables + * @count: how many drops we've done since the last time we + * entered dropping state + * @lastcount: count at entry to dropping state + * @dropping: set to true if in dropping state + * @rec_inv_sqrt: reciprocal value of sqrt(count) >> 1 + * @first_above_time: when we went (or will go) continuously above target + * for interval + * @drop_next: time to drop next packet, or when we dropped last + * @ldelay: sojourn time of last dequeued packet + */ +struct codel_vars { + u32 count; + u32 lastcount; + bool dropping; + u16 rec_inv_sqrt; + codel_time_t first_above_time; + codel_time_t drop_next; + codel_time_t ldelay; +}; + +#define REC_INV_SQRT_BITS (8 * sizeof(u16)) /* or sizeof_in_bits(rec_inv_sqrt) */ +/* needed shift to get a Q0.32 number from rec_inv_sqrt */ +#define REC_INV_SQRT_SHIFT (32 - REC_INV_SQRT_BITS) + +/** + * struct codel_stats - contains codel shared variables and stats + * @maxpacket: largest packet we've seen so far + * @drop_count: temp count of dropped packets in dequeue() + * ecn_mark: number of packets we ECN marked instead of dropping + */ +struct codel_stats { + u32 maxpacket; + u32 drop_count; + u32 ecn_mark; +}; + +static void codel_params_init(struct codel_params *params) +{ + params->interval = MS2TIME(100); + params->target = MS2TIME(5); + params->ecn = false; +} + +static void codel_vars_init(struct codel_vars *vars) +{ + memset(vars, 0, sizeof(*vars)); +} + +static void codel_stats_init(struct codel_stats *stats) +{ + stats->maxpacket = 256; +} + +/* + * http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Iterative_methods_for_reciprocal_square_roots + * new_invsqrt = (invsqrt / 2) * (3 - count * invsqrt^2) + * + * Here, invsqrt is a fixed point number (< 1.0), 32bit mantissa, aka Q0.32 + */ +static void codel_Newton_step(struct codel_vars *vars) +{ + u32 invsqrt = ((u32)vars->rec_inv_sqrt) << REC_INV_SQRT_SHIFT; + u32 invsqrt2 = ((u64)invsqrt * invsqrt) >> 32; + u64 val = (3LL << 32) - ((u64)vars->count * invsqrt2); + + val >>= 2; /* avoid overflow in following multiply */ + val = (val * invsqrt) >> (32 - 2 + 1); + + vars->rec_inv_sqrt = val >> REC_INV_SQRT_SHIFT; +} + +/* + * CoDel control_law is t + interval/sqrt(count) + * We maintain in rec_inv_sqrt the reciprocal value of sqrt(count) to avoid + * both sqrt() and divide operation. + */ +static codel_time_t codel_control_law(codel_time_t t, + codel_time_t interval, + u32 rec_inv_sqrt) +{ + return t + reciprocal_divide(interval, rec_inv_sqrt << REC_INV_SQRT_SHIFT); +} + + +static bool codel_should_drop(const struct sk_buff *skb, + struct Qdisc *sch, + struct codel_vars *vars, + struct codel_params *params, + struct codel_stats *stats, + codel_time_t now) +{ + bool ok_to_drop; + + if (!skb) { + vars->first_above_time = 0; + return false; + } + + vars->ldelay = now - codel_get_enqueue_time(skb); + sch->qstats.backlog -= qdisc_pkt_len(skb); + + if (unlikely(qdisc_pkt_len(skb) > stats->maxpacket)) + stats->maxpacket = qdisc_pkt_len(skb); + + if (codel_time_before(vars->ldelay, params->target) || + sch->qstats.backlog <= stats->maxpacket) { + /* went below - stay below for at least interval */ + vars->first_above_time = 0; + return false; + } + ok_to_drop = false; + if (vars->first_above_time == 0) { + /* just went above from below. If we stay above + * for at least interval we'll say it's ok to drop + */ + vars->first_above_time = now + params->interval; + } else if (codel_time_after(now, vars->first_above_time)) { + ok_to_drop = true; + } + return ok_to_drop; +} + +typedef struct sk_buff * (*codel_skb_dequeue_t)(struct codel_vars *vars, + struct Qdisc *sch); + +static struct sk_buff *codel_dequeue(struct Qdisc *sch, + struct codel_params *params, + struct codel_vars *vars, + struct codel_stats *stats, + codel_skb_dequeue_t dequeue_func) +{ + struct sk_buff *skb = dequeue_func(vars, sch); + codel_time_t now; + bool drop; + + if (!skb) { + vars->dropping = false; + return skb; + } + now = codel_get_time(); + drop = codel_should_drop(skb, sch, vars, params, stats, now); + if (vars->dropping) { + if (!drop) { + /* sojourn time below target - leave dropping state */ + vars->dropping = false; + } else if (codel_time_after_eq(now, vars->drop_next)) { + /* It's time for the next drop. Drop the current + * packet and dequeue the next. The dequeue might + * take us out of dropping state. + * If not, schedule the next drop. + * A large backlog might result in drop rates so high + * that the next drop should happen now, + * hence the while loop. + */ + while (vars->dropping && + codel_time_after_eq(now, vars->drop_next)) { + vars->count++; /* dont care of possible wrap + * since there is no more divide + */ + codel_Newton_step(vars); + if (params->ecn && INET_ECN_set_ce(skb)) { + stats->ecn_mark++; + vars->drop_next = + codel_control_law(vars->drop_next, + params->interval, + vars->rec_inv_sqrt); + goto end; + } + qdisc_drop(skb, sch); + stats->drop_count++; + skb = dequeue_func(vars, sch); + if (!codel_should_drop(skb, sch, + vars, params, stats, now)) { + /* leave dropping state */ + vars->dropping = false; + } else { + /* and schedule the next drop */ + vars->drop_next = + codel_control_law(vars->drop_next, + params->interval, + vars->rec_inv_sqrt); + } + } + } + } else if (drop) { + if (params->ecn && INET_ECN_set_ce(skb)) { + stats->ecn_mark++; + } else { + qdisc_drop(skb, sch); + stats->drop_count++; + + skb = dequeue_func(vars, sch); + drop = codel_should_drop(skb, sch, vars, params, + stats, now); + } + vars->dropping = true; + /* if min went above target close to when we last went below it + * assume that the drop rate that controlled the queue on the + * last cycle is a good starting point to control it now. + */ + if (codel_time_before(now - vars->drop_next, + 16 * params->interval)) { + vars->count = (vars->count - vars->lastcount) | 1; + /* we dont care if rec_inv_sqrt approximation + * is not very precise : + * Next Newton steps will correct it quadratically. + */ + codel_Newton_step(vars); + } else { + vars->count = 1; + vars->rec_inv_sqrt = ~0U >> REC_INV_SQRT_SHIFT; + } + vars->lastcount = vars->count; + vars->drop_next = codel_control_law(now, params->interval, + vars->rec_inv_sqrt); + } +end: + return skb; +} +#endif diff --git a/include/net/compat.h b/include/net/compat.h index a974ae92d182..6e9565324989 100644 --- a/include/net/compat.h +++ b/include/net/compat.h @@ -42,12 +42,12 @@ extern int compat_sock_get_timestampns(struct sock *, struct timespec __user *); extern int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *); extern int verify_compat_iovec(struct msghdr *, struct iovec *, struct sockaddr_storage *, int); -extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned); +extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsigned int); extern asmlinkage long compat_sys_sendmmsg(int, struct compat_mmsghdr __user *, - unsigned, unsigned); -extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); + unsigned int, unsigned int); +extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned int); extern asmlinkage long compat_sys_recvmmsg(int, struct compat_mmsghdr __user *, - unsigned, unsigned, + unsigned int, unsigned int, struct compat_timespec __user *); extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h index f55c980d8e23..fc5d5dcebb00 100644 --- a/include/net/dcbnl.h +++ b/include/net/dcbnl.h @@ -48,6 +48,8 @@ struct dcbnl_rtnl_ops { /* IEEE 802.1Qaz std */ int (*ieee_getets) (struct net_device *, struct ieee_ets *); int (*ieee_setets) (struct net_device *, struct ieee_ets *); + int (*ieee_getmaxrate) (struct net_device *, struct ieee_maxrate *); + int (*ieee_setmaxrate) (struct net_device *, struct ieee_maxrate *); int (*ieee_getpfc) (struct net_device *, struct ieee_pfc *); int (*ieee_setpfc) (struct net_device *, struct ieee_pfc *); int (*ieee_getapp) (struct net_device *, struct dcb_app *); diff --git a/include/net/dn.h b/include/net/dn.h index 814af0b9387d..c88bf4ebd330 100644 --- a/include/net/dn.h +++ b/include/net/dn.h @@ -199,7 +199,7 @@ static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp) fld->fld_dport = scp->addrrem; } -extern unsigned dn_mss_from_pmtu(struct net_device *dev, int mtu); +extern unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu); #define DN_MENUVER_ACC 0x01 #define DN_MENUVER_USR 0x02 diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h index 782ef7cb4930..1ee9d4bda30d 100644 --- a/include/net/dn_fib.h +++ b/include/net/dn_fib.h @@ -31,7 +31,7 @@ struct dn_fib_res { struct dn_fib_nh { struct net_device *nh_dev; - unsigned nh_flags; + unsigned int nh_flags; unsigned char nh_scope; int nh_weight; int nh_power; @@ -45,7 +45,7 @@ struct dn_fib_info { int fib_treeref; atomic_t fib_clntref; int fib_dead; - unsigned fib_flags; + unsigned int fib_flags; int fib_protocol; __le16 fib_prefsrc; __u32 fib_priority; @@ -140,7 +140,7 @@ extern void dn_fib_table_cleanup(void); */ extern void dn_fib_rules_init(void); extern void dn_fib_rules_cleanup(void); -extern unsigned dnet_addr_type(__le16 addr); +extern unsigned int dnet_addr_type(__le16 addr); extern int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res); extern int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb); diff --git a/include/net/dn_route.h b/include/net/dn_route.h index 81712cfa1ddf..4f7d6a182381 100644 --- a/include/net/dn_route.h +++ b/include/net/dn_route.h @@ -67,6 +67,8 @@ extern void dn_rt_cache_flush(int delay); struct dn_route { struct dst_entry dst; + struct neighbour *n; + struct flowidn fld; __le16 rt_saddr; @@ -76,8 +78,8 @@ struct dn_route { __le16 rt_src_map; __le16 rt_dst_map; - unsigned rt_flags; - unsigned rt_type; + unsigned int rt_flags; + unsigned int rt_type; }; static inline bool dn_is_input_route(struct dn_route *rt) diff --git a/include/net/dst.h b/include/net/dst.h index bed833d9796a..baf597890064 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -42,16 +42,16 @@ struct dst_entry { struct dst_entry *from; }; struct dst_entry *path; - struct neighbour __rcu *_neighbour; + void *__pad0; #ifdef CONFIG_XFRM struct xfrm_state *xfrm; #else void *__pad1; #endif - int (*input)(struct sk_buff*); - int (*output)(struct sk_buff*); + int (*input)(struct sk_buff *); + int (*output)(struct sk_buff *); - int flags; + unsigned short flags; #define DST_HOST 0x0001 #define DST_NOXFRM 0x0002 #define DST_NOPOLICY 0x0004 @@ -60,9 +60,25 @@ struct dst_entry { #define DST_NOCOUNT 0x0020 #define DST_NOPEER 0x0040 #define DST_FAKE_RTABLE 0x0080 +#define DST_XFRM_TUNNEL 0x0100 + + unsigned short pending_confirm; short error; + + /* A non-zero value of dst->obsolete forces by-hand validation + * of the route entry. Positive values are set by the generic + * dst layer to indicate that the entry has been forcefully + * destroyed. + * + * Negative values are used by the implementation layer code to + * force invocation of the dst_ops->check() method. + */ short obsolete; +#define DST_OBSOLETE_NONE 0 +#define DST_OBSOLETE_DEAD 2 +#define DST_OBSOLETE_FORCE_CHK -1 +#define DST_OBSOLETE_KILL -2 unsigned short header_len; /* more space at head required */ unsigned short trailer_len; /* space to reserve at tail */ #ifdef CONFIG_IP_ROUTE_CLASSID @@ -93,21 +109,6 @@ struct dst_entry { }; }; -static inline struct neighbour *dst_get_neighbour_noref(struct dst_entry *dst) -{ - return rcu_dereference(dst->_neighbour); -} - -static inline struct neighbour *dst_get_neighbour_noref_raw(struct dst_entry *dst) -{ - return rcu_dereference_raw(dst->_neighbour); -} - -static inline void dst_set_neighbour(struct dst_entry *dst, struct neighbour *neigh) -{ - rcu_assign_pointer(dst->_neighbour, neigh); -} - extern u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old); extern const u32 dst_default_metrics[RTAX_MAX]; @@ -221,12 +222,6 @@ static inline unsigned long dst_metric_rtt(const struct dst_entry *dst, int metr return msecs_to_jiffies(dst_metric(dst, metric)); } -static inline void set_dst_metric_rtt(struct dst_entry *dst, int metric, - unsigned long rtt) -{ - dst_metric_set(dst, metric, jiffies_to_msecs(rtt)); -} - static inline u32 dst_allfrag(const struct dst_entry *dst) { @@ -240,7 +235,7 @@ dst_metric_locked(const struct dst_entry *dst, int metric) return dst_metric(dst, RTAX_LOCK) & (1<<metric); } -static inline void dst_hold(struct dst_entry * dst) +static inline void dst_hold(struct dst_entry *dst) { /* * If your kernel compilation stops here, please check @@ -263,8 +258,7 @@ static inline void dst_use_noref(struct dst_entry *dst, unsigned long time) dst->lastuse = time; } -static inline -struct dst_entry * dst_clone(struct dst_entry * dst) +static inline struct dst_entry *dst_clone(struct dst_entry *dst) { if (dst) atomic_inc(&dst->__refcnt); @@ -370,14 +364,15 @@ static inline struct dst_entry *skb_dst_pop(struct sk_buff *skb) } extern int dst_discard(struct sk_buff *skb); -extern void *dst_alloc(struct dst_ops * ops, struct net_device *dev, - int initial_ref, int initial_obsolete, int flags); -extern void __dst_free(struct dst_entry * dst); -extern struct dst_entry *dst_destroy(struct dst_entry * dst); +extern void *dst_alloc(struct dst_ops *ops, struct net_device *dev, + int initial_ref, int initial_obsolete, + unsigned short flags); +extern void __dst_free(struct dst_entry *dst); +extern struct dst_entry *dst_destroy(struct dst_entry *dst); -static inline void dst_free(struct dst_entry * dst) +static inline void dst_free(struct dst_entry *dst) { - if (dst->obsolete > 1) + if (dst->obsolete > 0) return; if (!atomic_read(&dst->__refcnt)) { dst = dst_destroy(dst); @@ -395,19 +390,35 @@ static inline void dst_rcu_free(struct rcu_head *head) static inline void dst_confirm(struct dst_entry *dst) { - if (dst) { - struct neighbour *n; + dst->pending_confirm = 1; +} - rcu_read_lock(); - n = dst_get_neighbour_noref(dst); - neigh_confirm(n); - rcu_read_unlock(); +static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n, + struct sk_buff *skb) +{ + struct hh_cache *hh; + + if (unlikely(dst->pending_confirm)) { + n->confirmed = jiffies; + dst->pending_confirm = 0; } + + hh = &n->hh; + if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) + return neigh_hh_output(hh, skb); + else + return n->output(n, skb); } static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr) { - return dst->ops->neigh_lookup(dst, daddr); + return dst->ops->neigh_lookup(dst, NULL, daddr); +} + +static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst, + struct sk_buff *skb) +{ + return dst->ops->neigh_lookup(dst, skb, NULL); } static inline void dst_link_failure(struct sk_buff *skb) diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h index e1c2ee0eef47..2f26dfb8450e 100644 --- a/include/net/dst_ops.h +++ b/include/net/dst_ops.h @@ -8,11 +8,12 @@ struct dst_entry; struct kmem_cachep; struct net_device; struct sk_buff; +struct sock; struct dst_ops { unsigned short family; __be16 protocol; - unsigned gc_thresh; + unsigned int gc_thresh; int (*gc)(struct dst_ops *ops); struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); @@ -24,9 +25,14 @@ struct dst_ops { struct net_device *dev, int how); struct dst_entry * (*negative_advice)(struct dst_entry *); void (*link_failure)(struct sk_buff *); - void (*update_pmtu)(struct dst_entry *dst, u32 mtu); + void (*update_pmtu)(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb, u32 mtu); + void (*redirect)(struct dst_entry *dst, struct sock *sk, + struct sk_buff *skb); int (*local_out)(struct sk_buff *skb); - struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, const void *daddr); + struct neighbour * (*neigh_lookup)(const struct dst_entry *dst, + struct sk_buff *skb, + const void *daddr); struct kmem_cache *kmem_cachep; diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 075f1e3a0fed..e361f4882426 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -52,6 +52,7 @@ struct fib_rules_ops { struct sk_buff *, struct fib_rule_hdr *, struct nlattr **); + void (*delete)(struct fib_rule *); int (*compare)(struct fib_rule *, struct fib_rule_hdr *, struct nlattr **); diff --git a/include/net/flow.h b/include/net/flow.h index 6c469dbdb917..e1dd5082ec7e 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -20,8 +20,7 @@ struct flowi_common { __u8 flowic_proto; __u8 flowic_flags; #define FLOWI_FLAG_ANYSRC 0x01 -#define FLOWI_FLAG_PRECOW_METRICS 0x02 -#define FLOWI_FLAG_CAN_SLEEP 0x04 +#define FLOWI_FLAG_CAN_SLEEP 0x02 __u32 flowic_secid; }; diff --git a/include/net/genetlink.h b/include/net/genetlink.h index ccb68880abf5..48905cd3884c 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -5,6 +5,8 @@ #include <net/netlink.h> #include <net/net_namespace.h> +#define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN) + /** * struct genl_multicast_group - generic netlink multicast group * @name: name of the multicast group, names are per-family diff --git a/include/net/icmp.h b/include/net/icmp.h index 75d615649071..9ac2524d1402 100644 --- a/include/net/icmp.h +++ b/include/net/icmp.h @@ -25,7 +25,7 @@ struct icmp_err { int errno; - unsigned fatal:1; + unsigned int fatal:1; }; extern const struct icmp_err icmp_err_convert[]; @@ -41,7 +41,6 @@ struct net; extern void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info); extern int icmp_rcv(struct sk_buff *skb); -extern int icmp_ioctl(struct sock *sk, int cmd, unsigned long arg); extern int icmp_init(void); extern void icmp_out_count(struct net *net, unsigned char type); diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h index 57430555487a..d104c882fc29 100644 --- a/include/net/ieee802154_netdev.h +++ b/include/net/ieee802154_netdev.h @@ -1,7 +1,7 @@ /* * An interface between IEEE802.15.4 device and rest of the kernel. * - * Copyright (C) 2007, 2008, 2009 Siemens AG + * Copyright (C) 2007-2012 Siemens AG * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 @@ -21,11 +21,14 @@ * Maxim Gorbachyov <maxim.gorbachev@siemens.com> * Maxim Osipov <maxim.osipov@siemens.com> * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> + * Alexander Smirnov <alex.bluesman.smirnov@gmail.com> */ #ifndef IEEE802154_NETDEVICE_H #define IEEE802154_NETDEVICE_H +#include <net/af_ieee802154.h> + /* * A control block of skb passed between the ARPHRD_IEEE802154 device * and other stack parts. @@ -110,12 +113,26 @@ struct ieee802154_mlme_ops { u8 (*get_bsn)(const struct net_device *dev); }; -static inline struct ieee802154_mlme_ops *ieee802154_mlme_ops( - const struct net_device *dev) +/* The IEEE 802.15.4 standard defines 2 type of the devices: + * - FFD - full functionality device + * - RFD - reduce functionality device + * + * So 2 sets of mlme operations are needed + */ +struct ieee802154_reduced_mlme_ops { + struct wpan_phy *(*get_phy)(const struct net_device *dev); +}; + +static inline struct ieee802154_mlme_ops * +ieee802154_mlme_ops(const struct net_device *dev) { return dev->ml_priv; } -#endif - +static inline struct ieee802154_reduced_mlme_ops * +ieee802154_reduced_mlme_ops(const struct net_device *dev) +{ + return dev->ml_priv; +} +#endif diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h index 51a7031b4aa3..93563221d29a 100644 --- a/include/net/if_inet6.h +++ b/include/net/if_inet6.h @@ -120,7 +120,7 @@ struct ifmcaddr6 { unsigned char mca_crcount; unsigned long mca_sfcount[2]; struct timer_list mca_timer; - unsigned mca_flags; + unsigned int mca_flags; int mca_users; atomic_t mca_refcnt; spinlock_t mca_lock; @@ -209,60 +209,6 @@ static inline void ipv6_eth_mc_map(const struct in6_addr *addr, char *buf) memcpy(buf + 2, &addr->s6_addr32[3], sizeof(__u32)); } -static inline void ipv6_tr_mc_map(const struct in6_addr *addr, char *buf) -{ - /* All nodes FF01::1, FF02::1, FF02::1:FFxx:xxxx */ - - if (((addr->s6_addr[0] == 0xFF) && - ((addr->s6_addr[1] == 0x01) || (addr->s6_addr[1] == 0x02)) && - (addr->s6_addr16[1] == 0) && - (addr->s6_addr32[1] == 0) && - (addr->s6_addr32[2] == 0) && - (addr->s6_addr16[6] == 0) && - (addr->s6_addr[15] == 1)) || - ((addr->s6_addr[0] == 0xFF) && - (addr->s6_addr[1] == 0x02) && - (addr->s6_addr16[1] == 0) && - (addr->s6_addr32[1] == 0) && - (addr->s6_addr16[4] == 0) && - (addr->s6_addr[10] == 0) && - (addr->s6_addr[11] == 1) && - (addr->s6_addr[12] == 0xff))) - { - buf[0]=0xC0; - buf[1]=0x00; - buf[2]=0x01; - buf[3]=0x00; - buf[4]=0x00; - buf[5]=0x00; - /* All routers FF0x::2 */ - } else if ((addr->s6_addr[0] ==0xff) && - ((addr->s6_addr[1] & 0xF0) == 0) && - (addr->s6_addr16[1] == 0) && - (addr->s6_addr32[1] == 0) && - (addr->s6_addr32[2] == 0) && - (addr->s6_addr16[6] == 0) && - (addr->s6_addr[15] == 2)) - { - buf[0]=0xC0; - buf[1]=0x00; - buf[2]=0x02; - buf[3]=0x00; - buf[4]=0x00; - buf[5]=0x00; - } else { - unsigned char i ; - - i = addr->s6_addr[15] & 7 ; - buf[0]=0xC0; - buf[1]=0x00; - buf[2]=0x00; - buf[3]=0x01 << i ; - buf[4]=0x00; - buf[5]=0x00; - } -} - static inline void ipv6_arcnet_mc_map(const struct in6_addr *addr, char *buf) { buf[0] = 0x00; diff --git a/include/net/inet6_connection_sock.h b/include/net/inet6_connection_sock.h index 3207e58ee019..04642c920431 100644 --- a/include/net/inet6_connection_sock.h +++ b/include/net/inet6_connection_sock.h @@ -23,9 +23,10 @@ struct sock; struct sockaddr; extern int inet6_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb); + const struct inet_bind_bucket *tb, bool relax); extern struct dst_entry* inet6_csk_route_req(struct sock *sk, + struct flowi6 *fl6, const struct request_sock *req); extern struct request_sock *inet6_csk_search_req(const struct sock *sk, @@ -42,4 +43,6 @@ extern void inet6_csk_reqsk_queue_hash_add(struct sock *sk, extern void inet6_csk_addr2sockaddr(struct sock *sk, struct sockaddr *uaddr); extern int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl); + +extern struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu); #endif /* _INET6_CONNECTION_SOCK_H */ diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 00cbb4384c79..9e34c877a770 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -96,14 +96,15 @@ static inline struct sock *__inet6_lookup_skb(struct inet_hashinfo *hashinfo, const __be16 sport, const __be16 dport) { - struct sock *sk; + struct sock *sk = skb_steal_sock(skb); - if (unlikely(sk = skb_steal_sock(skb))) + if (sk) return sk; - else return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, - &ipv6_hdr(skb)->saddr, sport, - &ipv6_hdr(skb)->daddr, ntohs(dport), - inet6_iif(skb)); + + return __inet6_lookup(dev_net(skb_dst(skb)->dev), hashinfo, + &ipv6_hdr(skb)->saddr, sport, + &ipv6_hdr(skb)->daddr, ntohs(dport), + inet6_iif(skb)); } extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo, diff --git a/include/net/inet_common.h b/include/net/inet_common.h index 22fac9892b16..234008782c8c 100644 --- a/include/net/inet_common.h +++ b/include/net/inet_common.h @@ -14,9 +14,11 @@ struct sockaddr; struct socket; extern int inet_release(struct socket *sock); -extern int inet_stream_connect(struct socket *sock, struct sockaddr * uaddr, +extern int inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags); -extern int inet_dgram_connect(struct socket *sock, struct sockaddr * uaddr, +extern int __inet_stream_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags); +extern int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags); extern int inet_accept(struct socket *sock, struct socket *newsock, int flags); extern int inet_sendmsg(struct kiocb *iocb, struct socket *sock, diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index dbf9aab34c82..5ee66f517b4f 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -43,8 +43,8 @@ struct inet_connection_sock_af_ops { struct sock *(*syn_recv_sock)(struct sock *sk, struct sk_buff *skb, struct request_sock *req, struct dst_entry *dst); - struct inet_peer *(*get_peer)(struct sock *sk, bool *release_it); u16 net_header_len; + u16 net_frag_header_len; u16 sockaddr_len; int (*setsockopt)(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); @@ -60,7 +60,7 @@ struct inet_connection_sock_af_ops { #endif void (*addr2sockaddr)(struct sock *sk, struct sockaddr *); int (*bind_conflict)(const struct sock *sk, - const struct inet_bind_bucket *tb); + const struct inet_bind_bucket *tb, bool relax); }; /** inet_connection_sock - INET connection oriented sock @@ -245,7 +245,7 @@ extern struct request_sock *inet_csk_search_req(const struct sock *sk, const __be32 raddr, const __be32 laddr); extern int inet_csk_bind_conflict(const struct sock *sk, - const struct inet_bind_bucket *tb); + const struct inet_bind_bucket *tb, bool relax); extern int inet_csk_get_port(struct sock *sk, unsigned short snum); extern struct dst_entry* inet_csk_route_req(struct sock *sk, @@ -336,4 +336,6 @@ extern int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, char __user *optval, int __user *optlen); extern int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); + +extern struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); #endif /* _INET_CONNECTION_SOCK_H */ diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index 16ff29a7bb30..2431cf83aeca 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h @@ -46,8 +46,7 @@ struct inet_frags { void *arg); void (*destructor)(struct inet_frag_queue *); void (*skb_free)(struct sk_buff *); - int (*match)(struct inet_frag_queue *q, - void *arg); + bool (*match)(struct inet_frag_queue *q, void *arg); void (*frag_expire)(unsigned long data); }; diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 808fc5f76b03..54be0287eb98 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h @@ -379,10 +379,10 @@ static inline struct sock *__inet_lookup_skb(struct inet_hashinfo *hashinfo, const __be16 sport, const __be16 dport) { - struct sock *sk; + struct sock *sk = skb_steal_sock(skb); const struct iphdr *iph = ip_hdr(skb); - if (unlikely(sk = skb_steal_sock(skb))) + if (sk) return sk; else return __inet_lookup(dev_net(skb_dst(skb)->dev), hashinfo, diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index ae17e1352d7e..83b567fe1941 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -172,6 +172,7 @@ struct inet_sock { int uc_index; int mc_index; __be32 mc_addr; + int rx_dst_ifindex; struct ip_mc_socklist __rcu *mc_list; struct inet_cork_full cork; }; @@ -245,9 +246,16 @@ static inline __u8 inet_sk_flowi_flags(const struct sock *sk) if (inet_sk(sk)->transparent || inet_sk(sk)->hdrincl) flags |= FLOWI_FLAG_ANYSRC; - if (sk->sk_protocol == IPPROTO_TCP) - flags |= FLOWI_FLAG_PRECOW_METRICS; return flags; } +static inline void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + + dst_hold(dst); + sk->sk_rx_dst = dst; + inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; +} + #endif /* _INET_SOCK_H */ diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index b94765e38e80..53f464d7cddc 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -36,22 +36,19 @@ struct inet_peer { u32 metrics[RTAX_MAX]; u32 rate_tokens; /* rate limiting for ICMP */ unsigned long rate_last; - unsigned long pmtu_expires; - u32 pmtu_orig; - u32 pmtu_learned; - struct inetpeer_addr_base redirect_learned; - struct list_head gc_list; + union { + struct list_head gc_list; + struct rcu_head gc_rcu; + }; /* * Once inet_peer is queued for deletion (refcnt == -1), following fields - * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp + * are not available: rid, ip_id_count * We can share memory with rcu_head to help keep inet_peer small. */ union { struct { atomic_t rid; /* Frag reception counter */ atomic_t ip_id_count; /* IP ID for the next packet */ - __u32 tcp_ts; - __u32 tcp_ts_stamp; }; struct rcu_head rcu; struct inet_peer *gc_next; @@ -62,6 +59,69 @@ struct inet_peer { atomic_t refcnt; }; +struct inet_peer_base { + struct inet_peer __rcu *root; + seqlock_t lock; + u32 flush_seq; + int total; +}; + +#define INETPEER_BASE_BIT 0x1UL + +static inline struct inet_peer *inetpeer_ptr(unsigned long val) +{ + BUG_ON(val & INETPEER_BASE_BIT); + return (struct inet_peer *) val; +} + +static inline struct inet_peer_base *inetpeer_base_ptr(unsigned long val) +{ + if (!(val & INETPEER_BASE_BIT)) + return NULL; + val &= ~INETPEER_BASE_BIT; + return (struct inet_peer_base *) val; +} + +static inline bool inetpeer_ptr_is_peer(unsigned long val) +{ + return !(val & INETPEER_BASE_BIT); +} + +static inline void __inetpeer_ptr_set_peer(unsigned long *val, struct inet_peer *peer) +{ + /* This implicitly clears INETPEER_BASE_BIT */ + *val = (unsigned long) peer; +} + +static inline bool inetpeer_ptr_set_peer(unsigned long *ptr, struct inet_peer *peer) +{ + unsigned long val = (unsigned long) peer; + unsigned long orig = *ptr; + + if (!(orig & INETPEER_BASE_BIT) || + cmpxchg(ptr, orig, val) != orig) + return false; + return true; +} + +static inline void inetpeer_init_ptr(unsigned long *ptr, struct inet_peer_base *base) +{ + *ptr = (unsigned long) base | INETPEER_BASE_BIT; +} + +static inline void inetpeer_transfer_peer(unsigned long *to, unsigned long *from) +{ + unsigned long val = *from; + + *to = val; + if (inetpeer_ptr_is_peer(val)) { + struct inet_peer *peer = inetpeer_ptr(val); + atomic_inc(&peer->refcnt); + } +} + +extern void inet_peer_base_init(struct inet_peer_base *); + void inet_initpeers(void) __init; #define INETPEER_METRICS_NEW (~(u32) 0) @@ -72,31 +132,38 @@ static inline bool inet_metrics_new(const struct inet_peer *p) } /* can be called with or without local BH being disabled */ -struct inet_peer *inet_getpeer(const struct inetpeer_addr *daddr, int create); +struct inet_peer *inet_getpeer(struct inet_peer_base *base, + const struct inetpeer_addr *daddr, + int create); -static inline struct inet_peer *inet_getpeer_v4(__be32 v4daddr, int create) +static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base, + __be32 v4daddr, + int create) { struct inetpeer_addr daddr; daddr.addr.a4 = v4daddr; daddr.family = AF_INET; - return inet_getpeer(&daddr, create); + return inet_getpeer(base, &daddr, create); } -static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr, int create) +static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base, + const struct in6_addr *v6daddr, + int create) { struct inetpeer_addr daddr; *(struct in6_addr *)daddr.addr.a6 = *v6daddr; daddr.family = AF_INET6; - return inet_getpeer(&daddr, create); + return inet_getpeer(base, &daddr, create); } /* can be called from BH context or outside */ extern void inet_putpeer(struct inet_peer *p); extern bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout); -extern void inetpeer_invalidate_tree(int family); +extern void inetpeer_invalidate_tree(struct inet_peer_base *); +extern void inetpeer_invalidate_family(int family); /* * temporary check to make sure we dont access rid, ip_id_count, tcp_ts, diff --git a/include/net/ip.h b/include/net/ip.h index b53d65f24f7b..bd5e444a19ce 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -141,23 +141,6 @@ static inline struct sk_buff *ip_finish_skb(struct sock *sk, struct flowi4 *fl4) extern int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len); -/* - * Map a multicast IP onto multicast MAC for type Token Ring. - * This conforms to RFC1469 Option 2 Multicasting i.e. - * using a functional address to transmit / receive - * multicast packets. - */ - -static inline void ip_tr_mc_map(__be32 addr, char *buf) -{ - buf[0]=0xC0; - buf[1]=0x00; - buf[2]=0x00; - buf[3]=0x04; - buf[4]=0x00; - buf[5]=0x00; -} - struct ip_reply_arg { struct kvec iov[1]; int flags; @@ -175,8 +158,9 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg) return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0; } -void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, - const struct ip_reply_arg *arg, unsigned int len); +void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, + __be32 saddr, const struct ip_reply_arg *arg, + unsigned int len); struct ipv4_config { int log_martians; @@ -222,14 +206,14 @@ static inline int inet_is_reserved_local_port(int port) extern int sysctl_ip_nonlocal_bind; -extern struct ctl_path net_core_path[]; -extern struct ctl_path net_ipv4_ctl_path[]; - /* From inetpeer.c */ extern int inet_peer_threshold; extern int inet_peer_minttl; extern int inet_peer_maxttl; +/* From ip_input.c */ +extern int sysctl_ip_early_demux; + /* From ip_output.c */ extern int sysctl_ip_dynaddr; diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 0ae759a6c76e..0fedbd8d747a 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -86,6 +86,8 @@ struct fib6_table; struct rt6_info { struct dst_entry dst; + struct neighbour *n; + /* * Tail elements of dst_entry (__refcnt etc.) * and these elements (rarely used in hot path) are in @@ -107,7 +109,7 @@ struct rt6_info { u32 rt6i_peer_genid; struct inet6_dev *rt6i_idev; - struct inet_peer *rt6i_peer; + unsigned long _rt6i_peer; #ifdef CONFIG_XFRM u32 rt6i_flow_cache_genid; @@ -118,6 +120,36 @@ struct rt6_info { u8 rt6i_protocol; }; +static inline struct inet_peer *rt6_peer_ptr(struct rt6_info *rt) +{ + return inetpeer_ptr(rt->_rt6i_peer); +} + +static inline bool rt6_has_peer(struct rt6_info *rt) +{ + return inetpeer_ptr_is_peer(rt->_rt6i_peer); +} + +static inline void __rt6_set_peer(struct rt6_info *rt, struct inet_peer *peer) +{ + __inetpeer_ptr_set_peer(&rt->_rt6i_peer, peer); +} + +static inline bool rt6_set_peer(struct rt6_info *rt, struct inet_peer *peer) +{ + return inetpeer_ptr_set_peer(&rt->_rt6i_peer, peer); +} + +static inline void rt6_init_peer(struct rt6_info *rt, struct inet_peer_base *base) +{ + inetpeer_init_ptr(&rt->_rt6i_peer, base); +} + +static inline void rt6_transfer_peer(struct rt6_info *rt, struct rt6_info *ort) +{ + inetpeer_transfer_peer(&rt->_rt6i_peer, &ort->_rt6i_peer); +} + static inline struct inet6_dev *ip6_dst_idev(struct dst_entry *dst) { return ((struct rt6_info *)dst)->rt6i_idev; @@ -207,6 +239,7 @@ struct fib6_table { u32 tb6_id; rwlock_t tb6_lock; struct fib6_node tb6_root; + struct inet_peer_base tb6_peers; }; #define RT6_TABLE_UNSPEC RT_TABLE_UNSPEC diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 2ad92ca4e6f3..5fa2af00634a 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -53,16 +53,25 @@ static inline unsigned int rt6_flags2srcprefs(int flags) return (flags >> 3) & 7; } -extern void rt6_bind_peer(struct rt6_info *rt, - int create); +extern void rt6_bind_peer(struct rt6_info *rt, int create); + +static inline struct inet_peer *__rt6_get_peer(struct rt6_info *rt, int create) +{ + if (rt6_has_peer(rt)) + return rt6_peer_ptr(rt); + + rt6_bind_peer(rt, create); + return (rt6_has_peer(rt) ? rt6_peer_ptr(rt) : NULL); +} static inline struct inet_peer *rt6_get_peer(struct rt6_info *rt) { - if (rt->rt6i_peer) - return rt->rt6i_peer; + return __rt6_get_peer(rt, 0); +} - rt6_bind_peer(rt, 0); - return rt->rt6i_peer; +static inline struct inet_peer *rt6_get_peer_create(struct rt6_info *rt) +{ + return __rt6_get_peer(rt, 1); } extern void ip6_route_input(struct sk_buff *skb); @@ -124,17 +133,12 @@ extern int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, const struct in6_addr *gwaddr); -extern void rt6_redirect(const struct in6_addr *dest, - const struct in6_addr *src, - const struct in6_addr *saddr, - struct neighbour *neigh, - u8 *lladdr, - int on_link); - -extern void rt6_pmtu_discovery(const struct in6_addr *daddr, - const struct in6_addr *saddr, - struct net_device *dev, - u32 pmtu); +extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu, + int oif, u32 mark); +extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, + __be32 mtu); +extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark); +extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk); struct netlink_callback; @@ -146,7 +150,7 @@ struct rt6_rtnl_dump_arg { extern int rt6_dump_route(struct rt6_info *rt, void *p_arg); extern void rt6_ifdown(struct net *net, struct net_device *dev); -extern void rt6_mtu_change(struct net_device *dev, unsigned mtu); +extern void rt6_mtu_change(struct net_device *dev, unsigned int mtu); extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); @@ -154,7 +158,8 @@ extern void rt6_remove_prefsrc(struct inet6_ifaddr *ifp); * Store a destination cache entry in a socket */ static inline void __ip6_dst_store(struct sock *sk, struct dst_entry *dst, - struct in6_addr *daddr, struct in6_addr *saddr) + const struct in6_addr *daddr, + const struct in6_addr *saddr) { struct ipv6_pinfo *np = inet6_sk(sk); struct rt6_info *rt = (struct rt6_info *) dst; @@ -175,7 +180,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, spin_unlock(&sk->sk_dst_lock); } -static inline int ipv6_unicast_destination(struct sk_buff *skb) +static inline bool ipv6_unicast_destination(const struct sk_buff *skb) { struct rt6_info *rt = (struct rt6_info *) skb_dst(skb); diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index fc73e667b50e..358fb86f57eb 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h @@ -9,6 +9,8 @@ #define IP6_TNL_F_CAP_XMIT 0x10000 /* capable of receiving packets */ #define IP6_TNL_F_CAP_RCV 0x20000 +/* determine capability on a per-packet basis */ +#define IP6_TNL_F_CAP_PER_PACKET 0x40000 /* IPv6 tunnel */ diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 10422ef14e28..926142ed8d7a 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -18,7 +18,10 @@ #include <net/flow.h> #include <linux/seq_file.h> +#include <linux/rcupdate.h> #include <net/fib_rules.h> +#include <net/inetpeer.h> +#include <linux/percpu.h> struct fib_config { u8 fc_dst_len; @@ -44,12 +47,30 @@ struct fib_config { }; struct fib_info; +struct rtable; + +struct fib_nh_exception { + struct fib_nh_exception __rcu *fnhe_next; + __be32 fnhe_daddr; + u32 fnhe_pmtu; + __be32 fnhe_gw; + unsigned long fnhe_expires; + struct rtable __rcu *fnhe_rth; + unsigned long fnhe_stamp; +}; + +struct fnhe_hash_bucket { + struct fib_nh_exception __rcu *chain; +}; + +#define FNHE_HASH_SIZE 2048 +#define FNHE_RECLAIM_DEPTH 5 struct fib_nh { struct net_device *nh_dev; struct hlist_node nh_hash; struct fib_info *nh_parent; - unsigned nh_flags; + unsigned int nh_flags; unsigned char nh_scope; #ifdef CONFIG_IP_ROUTE_MULTIPATH int nh_weight; @@ -62,6 +83,9 @@ struct fib_nh { __be32 nh_gw; __be32 nh_saddr; int nh_saddr_genid; + struct rtable __rcu * __percpu *nh_pcpu_rth_output; + struct rtable __rcu *nh_rth_input; + struct fnhe_hash_bucket *nh_exceptions; }; /* @@ -74,7 +98,7 @@ struct fib_info { struct net *fib_net; int fib_treeref; atomic_t fib_clntref; - unsigned fib_flags; + unsigned int fib_flags; unsigned char fib_dead; unsigned char fib_protocol; unsigned char fib_scope; @@ -105,12 +129,10 @@ struct fib_result { unsigned char nh_sel; unsigned char type; unsigned char scope; + u32 tclassid; struct fib_info *fi; struct fib_table *table; struct list_head *fa_head; -#ifdef CONFIG_IP_MULTIPLE_TABLES - struct fib_rule *r; -#endif }; struct fib_result_nl { @@ -157,11 +179,11 @@ extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh); FIB_RES_SADDR(net, res)) struct fib_table { - struct hlist_node tb_hlist; - u32 tb_id; - int tb_default; - int tb_num_default; - unsigned long tb_data[0]; + struct hlist_node tb_hlist; + u32 tb_id; + int tb_default; + int tb_num_default; + unsigned long tb_data[0]; }; extern int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, @@ -214,24 +236,55 @@ static inline int fib_lookup(struct net *net, const struct flowi4 *flp, extern int __net_init fib4_rules_init(struct net *net); extern void __net_exit fib4_rules_exit(struct net *net); -#ifdef CONFIG_IP_ROUTE_CLASSID -extern u32 fib_rules_tclass(const struct fib_result *res); -#endif - -extern int fib_lookup(struct net *n, struct flowi4 *flp, struct fib_result *res); - extern struct fib_table *fib_new_table(struct net *net, u32 id); extern struct fib_table *fib_get_table(struct net *net, u32 id); +extern int __fib_lookup(struct net *net, struct flowi4 *flp, + struct fib_result *res); + +static inline int fib_lookup(struct net *net, struct flowi4 *flp, + struct fib_result *res) +{ + if (!net->ipv4.fib_has_custom_rules) { + res->tclassid = 0; + if (net->ipv4.fib_local && + !fib_table_lookup(net->ipv4.fib_local, flp, res, + FIB_LOOKUP_NOREF)) + return 0; + if (net->ipv4.fib_main && + !fib_table_lookup(net->ipv4.fib_main, flp, res, + FIB_LOOKUP_NOREF)) + return 0; + if (net->ipv4.fib_default && + !fib_table_lookup(net->ipv4.fib_default, flp, res, + FIB_LOOKUP_NOREF)) + return 0; + return -ENETUNREACH; + } + return __fib_lookup(net, flp, res); +} + #endif /* CONFIG_IP_MULTIPLE_TABLES */ /* Exported by fib_frontend.c */ extern const struct nla_policy rtm_ipv4_policy[]; extern void ip_fib_init(void); +extern __be32 fib_compute_spec_dst(struct sk_buff *skb); extern int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, int oif, struct net_device *dev, - __be32 *spec_dst, u32 *itag); + struct in_device *idev, u32 *itag); extern void fib_select_default(struct fib_result *res); +#ifdef CONFIG_IP_ROUTE_CLASSID +static inline int fib_num_tclassid_users(struct net *net) +{ + return net->ipv4.fib_num_tclassid_users; +} +#else +static inline int fib_num_tclassid_users(struct net *net) +{ + return 0; +} +#endif /* Exported by fib_semantics.c */ extern int ip_fib_check_default(__be32 gw, struct net_device *dev); @@ -253,7 +306,7 @@ static inline void fib_combine_itag(u32 *itag, const struct fib_result *res) #endif *itag = FIB_RES_NH(*res).nh_tclassid<<16; #ifdef CONFIG_IP_MULTIPLE_TABLES - rtag = fib_rules_tclass(res); + rtag = res->tclassid; if (*itag == 0) *itag = (rtag<<16); *itag |= (rtag>>16); diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 72522f087375..95374d1696a1 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -10,7 +10,6 @@ #include <asm/types.h> /* for __uXX types */ -#include <linux/sysctl.h> /* for ctl_path */ #include <linux/list.h> /* for struct list_head */ #include <linux/spinlock.h> /* for struct rwlock_t */ #include <linux/atomic.h> /* for struct atomic_t */ @@ -505,6 +504,7 @@ struct ip_vs_conn { * state transition triggerd * synchronization */ + unsigned long sync_endtime; /* jiffies + sent_retries */ /* Control members */ struct ip_vs_conn *control; /* Master control connection */ @@ -580,8 +580,8 @@ struct ip_vs_service_user_kern { /* virtual service options */ char *sched_name; char *pe_name; - unsigned flags; /* virtual service flags */ - unsigned timeout; /* persistent timeout in sec */ + unsigned int flags; /* virtual service flags */ + unsigned int timeout; /* persistent timeout in sec */ u32 netmask; /* persistent netmask */ }; @@ -592,7 +592,7 @@ struct ip_vs_dest_user_kern { u16 port; /* real server options */ - unsigned conn_flags; /* connection flags */ + unsigned int conn_flags; /* connection flags */ int weight; /* destination weight */ /* thresholds for active connections */ @@ -616,8 +616,8 @@ struct ip_vs_service { union nf_inet_addr addr; /* IP address for virtual service */ __be16 port; /* port number for the service */ __u32 fwmark; /* firewall mark of the service */ - unsigned flags; /* service status flags */ - unsigned timeout; /* persistent timeout in ticks */ + unsigned int flags; /* service status flags */ + unsigned int timeout; /* persistent timeout in ticks */ __be32 netmask; /* grouping granularity */ struct net *net; @@ -647,7 +647,7 @@ struct ip_vs_dest { u16 af; /* address family */ __be16 port; /* port number of the server */ union nf_inet_addr addr; /* IP address of the server */ - volatile unsigned flags; /* dest status flags */ + volatile unsigned int flags; /* dest status flags */ atomic_t conn_flags; /* flags to copy to conn */ atomic_t weight; /* server weight */ @@ -784,6 +784,16 @@ struct ip_vs_app { void (*timeout_change)(struct ip_vs_app *app, int flags); }; +struct ipvs_master_sync_state { + struct list_head sync_queue; + struct ip_vs_sync_buff *sync_buff; + int sync_queue_len; + unsigned int sync_queue_delay; + struct task_struct *master_thread; + struct delayed_work master_wakeup_work; + struct netns_ipvs *ipvs; +}; + /* IPVS in network namespace */ struct netns_ipvs { int gen; /* Generation */ @@ -870,10 +880,15 @@ struct netns_ipvs { #endif int sysctl_snat_reroute; int sysctl_sync_ver; + int sysctl_sync_ports; + int sysctl_sync_qlen_max; + int sysctl_sync_sock_size; int sysctl_cache_bypass; int sysctl_expire_nodest_conn; int sysctl_expire_quiescent_template; int sysctl_sync_threshold[2]; + unsigned int sysctl_sync_refresh_period; + int sysctl_sync_retries; int sysctl_nat_icmp_send; /* ip_vs_lblc */ @@ -889,13 +904,11 @@ struct netns_ipvs { spinlock_t est_lock; struct timer_list est_timer; /* Estimation timer */ /* ip_vs_sync */ - struct list_head sync_queue; spinlock_t sync_lock; - struct ip_vs_sync_buff *sync_buff; + struct ipvs_master_sync_state *ms; spinlock_t sync_buff_lock; - struct sockaddr_in sync_mcast_addr; - struct task_struct *master_thread; - struct task_struct *backup_thread; + struct task_struct **backup_threads; + int threads_mask; int send_mesg_maxlen; int recv_mesg_maxlen; volatile int sync_state; @@ -912,6 +925,14 @@ struct netns_ipvs { #define DEFAULT_SYNC_THRESHOLD 3 #define DEFAULT_SYNC_PERIOD 50 #define DEFAULT_SYNC_VER 1 +#define DEFAULT_SYNC_REFRESH_PERIOD (0U * HZ) +#define DEFAULT_SYNC_RETRIES 0 +#define IPVS_SYNC_WAKEUP_RATE 8 +#define IPVS_SYNC_QLEN_MAX (IPVS_SYNC_WAKEUP_RATE * 4) +#define IPVS_SYNC_SEND_DELAY (HZ / 50) +#define IPVS_SYNC_CHECK_PERIOD HZ +#define IPVS_SYNC_FLUSH_TIME (HZ * 2) +#define IPVS_SYNC_PORTS_MAX (1 << 6) #ifdef CONFIG_SYSCTL @@ -922,7 +943,17 @@ static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs) static inline int sysctl_sync_period(struct netns_ipvs *ipvs) { - return ipvs->sysctl_sync_threshold[1]; + return ACCESS_ONCE(ipvs->sysctl_sync_threshold[1]); +} + +static inline unsigned int sysctl_sync_refresh_period(struct netns_ipvs *ipvs) +{ + return ACCESS_ONCE(ipvs->sysctl_sync_refresh_period); +} + +static inline int sysctl_sync_retries(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_sync_retries; } static inline int sysctl_sync_ver(struct netns_ipvs *ipvs) @@ -930,6 +961,21 @@ static inline int sysctl_sync_ver(struct netns_ipvs *ipvs) return ipvs->sysctl_sync_ver; } +static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) +{ + return ACCESS_ONCE(ipvs->sysctl_sync_ports); +} + +static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_sync_qlen_max; +} + +static inline int sysctl_sync_sock_size(struct netns_ipvs *ipvs) +{ + return ipvs->sysctl_sync_sock_size; +} + #else static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs) @@ -942,18 +988,43 @@ static inline int sysctl_sync_period(struct netns_ipvs *ipvs) return DEFAULT_SYNC_PERIOD; } +static inline unsigned int sysctl_sync_refresh_period(struct netns_ipvs *ipvs) +{ + return DEFAULT_SYNC_REFRESH_PERIOD; +} + +static inline int sysctl_sync_retries(struct netns_ipvs *ipvs) +{ + return DEFAULT_SYNC_RETRIES & 3; +} + static inline int sysctl_sync_ver(struct netns_ipvs *ipvs) { return DEFAULT_SYNC_VER; } +static inline int sysctl_sync_ports(struct netns_ipvs *ipvs) +{ + return 1; +} + +static inline int sysctl_sync_qlen_max(struct netns_ipvs *ipvs) +{ + return IPVS_SYNC_QLEN_MAX; +} + +static inline int sysctl_sync_sock_size(struct netns_ipvs *ipvs) +{ + return 0; +} + #endif /* * IPVS core functions * (from ip_vs_core.c) */ -extern const char *ip_vs_proto_name(unsigned proto); +extern const char *ip_vs_proto_name(unsigned int proto); extern void ip_vs_init_hash_table(struct list_head *table, int rows); #define IP_VS_INIT_HASH_TABLE(t) ip_vs_init_hash_table((t), ARRAY_SIZE((t))) @@ -1014,7 +1085,7 @@ extern void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport); struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, const union nf_inet_addr *daddr, - __be16 dport, unsigned flags, + __be16 dport, unsigned int flags, struct ip_vs_dest *dest, __u32 fwmark); extern void ip_vs_conn_expire_now(struct ip_vs_conn *cp); @@ -1184,10 +1255,8 @@ extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg); * IPVS control data and functions (from ip_vs_ctl.c) */ extern struct ip_vs_stats ip_vs_stats; -extern const struct ctl_path net_vs_ctl_path[]; extern int sysctl_ip_vs_sync_ver; -extern void ip_vs_sync_switch_mode(struct net *net, int mode); extern struct ip_vs_service * ip_vs_service_get(struct net *net, int af, __u32 fwmark, __u16 protocol, const union nf_inet_addr *vaddr, __be16 vport); @@ -1221,7 +1290,7 @@ extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp); extern int start_sync_thread(struct net *net, int state, char *mcast_ifn, __u8 syncid); extern int stop_sync_thread(struct net *net, int state); -extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp); +extern void ip_vs_sync_conn(struct net *net, struct ip_vs_conn *cp, int pkts); /* @@ -1356,7 +1425,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb) struct nf_conn *ct = nf_ct_get(skb, &ctinfo); if (!ct || !nf_ct_is_untracked(ct)) { - nf_reset(skb); + nf_conntrack_put(skb->nfct); skb->nfct = &nf_ct_untracked_get()->ct_general; skb->nfctinfo = IP_CT_NEW; nf_conntrack_get(skb->nfct); diff --git a/include/net/ipip.h b/include/net/ipip.h index a32654d52730..a93cf6d7e94b 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -54,8 +54,10 @@ struct ip_tunnel_prl_entry { \ err = ip_local_out(skb); \ if (likely(net_xmit_eval(err) == 0)) { \ + u64_stats_update_begin(&(stats1)->syncp); \ (stats1)->tx_bytes += pkt_len; \ (stats1)->tx_packets++; \ + u64_stats_update_end(&(stats1)->syncp); \ } else { \ (stats2)->tx_errors++; \ (stats2)->tx_aborted_errors++; \ diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e4170a22fc6f..01c34b363a34 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -113,7 +113,6 @@ struct frag_hdr { /* sysctls */ extern int sysctl_mld_max_msf; -extern struct ctl_path net_ipv6_ctl_path[]; #define _DEVINC(net, statname, modifier, idev, field) \ ({ \ @@ -252,6 +251,8 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) atomic_dec(&fl->users); } +extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); + extern int ip6_ra_control(struct sock *sk, int sel); extern int ipv6_parse_hopopts(struct sk_buff *skb); @@ -264,7 +265,7 @@ extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_t struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space, struct ipv6_txoptions *opt); -extern int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb); +extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb); int ip6_frag_nqueues(struct net *net); int ip6_frag_mem(struct net *net); @@ -299,14 +300,23 @@ static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr return memcmp(a1, a2, sizeof(struct in6_addr)); } -static inline int +static inline bool ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m, const struct in6_addr *a2) { +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 + const unsigned long *ul1 = (const unsigned long *)a1; + const unsigned long *ulm = (const unsigned long *)m; + const unsigned long *ul2 = (const unsigned long *)a2; + + return !!(((ul1[0] ^ ul2[0]) & ulm[0]) | + ((ul1[1] ^ ul2[1]) & ulm[1])); +#else return !!(((a1->s6_addr32[0] ^ a2->s6_addr32[0]) & m->s6_addr32[0]) | ((a1->s6_addr32[1] ^ a2->s6_addr32[1]) & m->s6_addr32[1]) | ((a1->s6_addr32[2] ^ a2->s6_addr32[2]) & m->s6_addr32[2]) | ((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3])); +#endif } static inline void ipv6_addr_prefix(struct in6_addr *pfx, @@ -333,36 +343,43 @@ static inline void ipv6_addr_set(struct in6_addr *addr, addr->s6_addr32[3] = w4; } -static inline int ipv6_addr_equal(const struct in6_addr *a1, - const struct in6_addr *a2) +static inline bool ipv6_addr_equal(const struct in6_addr *a1, + const struct in6_addr *a2) { +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 + const unsigned long *ul1 = (const unsigned long *)a1; + const unsigned long *ul2 = (const unsigned long *)a2; + + return ((ul1[0] ^ ul2[0]) | (ul1[1] ^ ul2[1])) == 0UL; +#else return ((a1->s6_addr32[0] ^ a2->s6_addr32[0]) | (a1->s6_addr32[1] ^ a2->s6_addr32[1]) | (a1->s6_addr32[2] ^ a2->s6_addr32[2]) | (a1->s6_addr32[3] ^ a2->s6_addr32[3])) == 0; +#endif } -static inline int __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2, - unsigned int prefixlen) +static inline bool __ipv6_prefix_equal(const __be32 *a1, const __be32 *a2, + unsigned int prefixlen) { - unsigned pdw, pbi; + unsigned int pdw, pbi; /* check complete u32 in prefix */ pdw = prefixlen >> 5; if (pdw && memcmp(a1, a2, pdw << 2)) - return 0; + return false; /* check incomplete u32 in prefix */ pbi = prefixlen & 0x1f; if (pbi && ((a1[pdw] ^ a2[pdw]) & htonl((0xffffffff) << (32 - pbi)))) - return 0; + return false; - return 1; + return true; } -static inline int ipv6_prefix_equal(const struct in6_addr *a1, - const struct in6_addr *a2, - unsigned int prefixlen) +static inline bool ipv6_prefix_equal(const struct in6_addr *a1, + const struct in6_addr *a2, + unsigned int prefixlen) { return __ipv6_prefix_equal(a1->s6_addr32, a2->s6_addr32, prefixlen); @@ -388,21 +405,40 @@ struct ip6_create_arg { }; void ip6_frag_init(struct inet_frag_queue *q, void *a); -int ip6_frag_match(struct inet_frag_queue *q, void *a); +bool ip6_frag_match(struct inet_frag_queue *q, void *a); -static inline int ipv6_addr_any(const struct in6_addr *a) +static inline bool ipv6_addr_any(const struct in6_addr *a) { +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 + const unsigned long *ul = (const unsigned long *)a; + + return (ul[0] | ul[1]) == 0UL; +#else return (a->s6_addr32[0] | a->s6_addr32[1] | a->s6_addr32[2] | a->s6_addr32[3]) == 0; +#endif +} + +static inline u32 ipv6_addr_hash(const struct in6_addr *a) +{ +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 + const unsigned long *ul = (const unsigned long *)a; + unsigned long x = ul[0] ^ ul[1]; + + return (u32)(x ^ (x >> 32)); +#else + return (__force u32)(a->s6_addr32[0] ^ a->s6_addr32[1] ^ + a->s6_addr32[2] ^ a->s6_addr32[3]); +#endif } -static inline int ipv6_addr_loopback(const struct in6_addr *a) +static inline bool ipv6_addr_loopback(const struct in6_addr *a) { return (a->s6_addr32[0] | a->s6_addr32[1] | a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0; } -static inline int ipv6_addr_v4mapped(const struct in6_addr *a) +static inline bool ipv6_addr_v4mapped(const struct in6_addr *a) { return (a->s6_addr32[0] | a->s6_addr32[1] | (a->s6_addr32[2] ^ htonl(0x0000ffff))) == 0; @@ -412,7 +448,7 @@ static inline int ipv6_addr_v4mapped(const struct in6_addr *a) * Check for a RFC 4843 ORCHID address * (Overlay Routable Cryptographic Hash Identifiers) */ -static inline int ipv6_addr_orchid(const struct in6_addr *a) +static inline bool ipv6_addr_orchid(const struct in6_addr *a) { return (a->s6_addr32[0] & htonl(0xfffffff0)) == htonl(0x20010010); } @@ -560,7 +596,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb, extern int ipv6_skip_exthdr(const struct sk_buff *, int start, u8 *nexthdrp, __be16 *frag_offp); -extern int ipv6_ext_hdr(u8 nexthdr); +extern bool ipv6_ext_hdr(u8 nexthdr); extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); @@ -661,8 +697,6 @@ extern struct ctl_table *ipv6_icmp_sysctl_init(struct net *net); extern struct ctl_table *ipv6_route_sysctl_init(struct net *net); extern int ipv6_sysctl_register(void); extern void ipv6_sysctl_unregister(void); -extern int ipv6_static_sysctl_register(void); -extern void ipv6_static_sysctl_unregister(void); #endif #endif /* _NET_IPV6_H */ diff --git a/include/net/lapb.h b/include/net/lapb.h index fd2bf572ee1d..df892a94f2c6 100644 --- a/include/net/lapb.h +++ b/include/net/lapb.h @@ -149,4 +149,10 @@ extern int lapb_t1timer_running(struct lapb_cb *lapb); */ #define LAPB_DEBUG 0 +#define lapb_dbg(level, fmt, ...) \ +do { \ + if (level < LAPB_DEBUG) \ + pr_debug(fmt, ##__VA_ARGS__); \ +} while (0) + #endif diff --git a/include/net/llc_c_ev.h b/include/net/llc_c_ev.h index 23a409381fa9..6ca3113df39e 100644 --- a/include/net/llc_c_ev.h +++ b/include/net/llc_c_ev.h @@ -264,6 +264,6 @@ extern int llc_conn_ev_qlfy_set_status_rst_done(struct sock *sk, static __inline__ int llc_conn_space(struct sock *sk, struct sk_buff *skb) { return atomic_read(&sk->sk_rmem_alloc) + skb->truesize < - (unsigned)sk->sk_rcvbuf; + (unsigned int)sk->sk_rcvbuf; } #endif /* LLC_C_EV_H */ diff --git a/include/net/llc_pdu.h b/include/net/llc_pdu.h index f57e7d46a453..5a93d13ac95c 100644 --- a/include/net/llc_pdu.h +++ b/include/net/llc_pdu.h @@ -13,7 +13,6 @@ */ #include <linux/if_ether.h> -#include <linux/if_tr.h> /* Lengths of frame formats */ #define LLC_PDU_LEN_I 4 /* header and 2 control bytes */ @@ -253,10 +252,6 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa) { if (skb->protocol == htons(ETH_P_802_2)) memcpy(sa, eth_hdr(skb)->h_source, ETH_ALEN); - else if (skb->protocol == htons(ETH_P_TR_802_2)) { - memcpy(sa, tr_hdr(skb)->saddr, ETH_ALEN); - *sa &= 0x7F; - } } /** @@ -270,8 +265,6 @@ static inline void llc_pdu_decode_da(struct sk_buff *skb, u8 *da) { if (skb->protocol == htons(ETH_P_802_2)) memcpy(da, eth_hdr(skb)->h_dest, ETH_ALEN); - else if (skb->protocol == htons(ETH_P_TR_802_2)) - memcpy(da, tr_hdr(skb)->daddr, ETH_ALEN); } /** diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 9210bdc7bd8d..bb86aa6f98dd 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -95,9 +95,11 @@ struct device; * @IEEE80211_MAX_QUEUES: Maximum number of regular device queues. */ enum ieee80211_max_queues { - IEEE80211_MAX_QUEUES = 4, + IEEE80211_MAX_QUEUES = 16, }; +#define IEEE80211_INVAL_HW_QUEUE 0xff + /** * enum ieee80211_ac_numbers - AC numbers as used in mac80211 * @IEEE80211_AC_VO: voice @@ -231,8 +233,10 @@ enum ieee80211_rssi_event { * valid in station mode only while @assoc is true and if also * requested by %IEEE80211_HW_NEED_DTIM_PERIOD (cf. also hw conf * @ps_dtim_period) - * @last_tsf: last beacon's/probe response's TSF timestamp (could be old + * @sync_tsf: last beacon's/probe response's TSF timestamp (could be old * as it may have been received during scanning long ago) + * @sync_device_ts: the device timestamp corresponding to the sync_tsf, + * the driver/device can use this to calculate synchronisation * @beacon_int: beacon interval * @assoc_capability: capabilities taken from assoc resp * @basic_rates: bitmap of basic rates, each bit stands for an @@ -244,7 +248,7 @@ enum ieee80211_rssi_event { * @channel_type: Channel type for this BSS -- the hardware might be * configured for HT40+ while this BSS only uses no-HT, for * example. - * @ht_operation_mode: HT operation mode (like in &struct ieee80211_ht_info). + * @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation. * This field is only valid when the channel type is one of the HT types. * @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value * implies disabled @@ -279,7 +283,8 @@ struct ieee80211_bss_conf { u8 dtim_period; u16 beacon_int; u16 assoc_capability; - u64 last_tsf; + u64 sync_tsf; + u32 sync_device_ts; u32 basic_rates; int mcast_rate[IEEE80211_NUM_BANDS]; u16 ht_operation_mode; @@ -473,7 +478,7 @@ enum mac80211_rate_control_flags { #define IEEE80211_TX_INFO_RATE_DRIVER_DATA_SIZE 24 /* maximum number of rate stages */ -#define IEEE80211_TX_MAX_RATES 5 +#define IEEE80211_TX_MAX_RATES 4 /** * struct ieee80211_tx_rate - rate selection/status @@ -522,7 +527,7 @@ struct ieee80211_tx_rate { * * @flags: transmit info flags, defined above * @band: the band to transmit on (use for checking for races) - * @antenna_sel_tx: antenna to use, 0 for automatic diversity + * @hw_queue: HW queue to put the frame on, skb_get_queue_mapping() gives the AC * @ack_frame_id: internal frame ID for TX status, used internally * @control: union for control data * @status: union for status data @@ -538,7 +543,7 @@ struct ieee80211_tx_info { u32 flags; u8 band; - u8 antenna_sel_tx; + u8 hw_queue; u16 ack_frame_id; @@ -561,10 +566,11 @@ struct ieee80211_tx_info { } control; struct { struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES]; - u8 ampdu_ack_len; int ack_signal; + u8 ampdu_ack_len; u8 ampdu_len; - /* 15 bytes free */ + u8 antenna; + /* 21 bytes free */ } status; struct { struct ieee80211_tx_rate driver_rates[ @@ -631,7 +637,7 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) info->status.rates[i].count = 0; BUILD_BUG_ON( - offsetof(struct ieee80211_tx_info, status.ampdu_ack_len) != 23); + offsetof(struct ieee80211_tx_info, status.ack_signal) != 20); memset(&info->status.ampdu_ack_len, 0, sizeof(struct ieee80211_tx_info) - offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); @@ -664,6 +670,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) * @RX_FLAG_SHORT_GI: Short guard interval was used * @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present. * Valid only for data frames (mainly A-MPDU) + * @RX_FLAG_HT_GF: This frame was received in a HT-greenfield transmission, if + * the driver fills this value it should add %IEEE80211_RADIOTAP_MCS_HAVE_FMT + * to hw.radiotap_mcs_details to advertise that fact */ enum mac80211_rx_flags { RX_FLAG_MMIC_ERROR = 1<<0, @@ -678,6 +687,7 @@ enum mac80211_rx_flags { RX_FLAG_40MHZ = 1<<10, RX_FLAG_SHORT_GI = 1<<11, RX_FLAG_NO_SIGNAL_VAL = 1<<12, + RX_FLAG_HT_GF = 1<<13, }; /** @@ -689,6 +699,8 @@ enum mac80211_rx_flags { * * @mactime: value in microseconds of the 64-bit Time Synchronization Function * (TSF) timer when the first data symbol (MPDU) arrived at the hardware. + * @device_timestamp: arbitrary timestamp for the device, mac80211 doesn't use + * it but can store it and pass it back to the driver for synchronisation * @band: the active band when this frame was received * @freq: frequency the radio was tuned to when receiving this frame, in MHz * @signal: signal strength when receiving this frame, either in dBm, in dB or @@ -702,13 +714,14 @@ enum mac80211_rx_flags { */ struct ieee80211_rx_status { u64 mactime; - enum ieee80211_band band; - int freq; - int signal; - int antenna; - int rate_idx; - int flag; - unsigned int rx_flags; + u32 device_timestamp; + u16 flag; + u16 freq; + u8 rate_idx; + u8 rx_flags; + u8 band; + u8 antenna; + s8 signal; }; /** @@ -888,6 +901,8 @@ enum ieee80211_vif_flags { * these need to be set (or cleared) when the interface is added * or, if supported by the driver, the interface type is changed * at runtime, mac80211 will never touch this field + * @hw_queue: hardware queue for each AC + * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only * @drv_priv: data area for driver use, will always be aligned to * sizeof(void *). */ @@ -896,7 +911,12 @@ struct ieee80211_vif { struct ieee80211_bss_conf bss_conf; u8 addr[ETH_ALEN]; bool p2p; + + u8 cab_queue; + u8 hw_queue[IEEE80211_NUM_ACS]; + u32 driver_flags; + /* must be last */ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); }; @@ -929,7 +949,7 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif) * CCMP key if it requires CCMP encryption of management frames (MFP) to * be done in software. * @IEEE80211_KEY_FLAG_PUT_IV_SPACE: This flag should be set by the driver - * for a CCMP key if space should be prepared for the IV, but the IV + * if space should be prepared for the IV, but the IV * itself should not be generated. Do not set together with * @IEEE80211_KEY_FLAG_GENERATE_IV on the same key. */ @@ -1174,6 +1194,15 @@ enum sta_notify_cmd { * @IEEE80211_HW_SCAN_WHILE_IDLE: The device can do hw scan while * being idle (i.e. mac80211 doesn't have to go idle-off during the * the scan). + * + * @IEEE80211_HW_WANT_MONITOR_VIF: The driver would like to be informed of + * a virtual monitor interface when monitor interfaces are the only + * active interfaces. + * + * @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface + * queue mapping in order to use different queues (not just one per AC) + * for different virtual interfaces. See the doc section on HW queue + * control for more details. */ enum ieee80211_hw_flags { IEEE80211_HW_HAS_RATE_CONTROL = 1<<0, @@ -1190,13 +1219,13 @@ enum ieee80211_hw_flags { IEEE80211_HW_PS_NULLFUNC_STACK = 1<<11, IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12, IEEE80211_HW_MFP_CAPABLE = 1<<13, - /* reuse bit 14 */ + IEEE80211_HW_WANT_MONITOR_VIF = 1<<14, IEEE80211_HW_SUPPORTS_STATIC_SMPS = 1<<15, IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS = 1<<16, IEEE80211_HW_SUPPORTS_UAPSD = 1<<17, IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18, IEEE80211_HW_CONNECTION_MONITOR = 1<<19, - /* reuse bit 20 */ + IEEE80211_HW_QUEUE_CONTROL = 1<<20, IEEE80211_HW_SUPPORTS_PER_STA_GTK = 1<<21, IEEE80211_HW_AP_LINK_PS = 1<<22, IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23, @@ -1266,6 +1295,18 @@ enum ieee80211_hw_flags { * @max_tx_aggregation_subframes: maximum number of subframes in an * aggregate an HT driver will transmit, used by the peer as a * hint to size its reorder buffer. + * + * @offchannel_tx_hw_queue: HW queue ID to use for offchannel TX + * (if %IEEE80211_HW_QUEUE_CONTROL is set) + * + * @radiotap_mcs_details: lists which MCS information can the HW + * reports, by default it is set to _MCS, _GI and _BW but doesn't + * include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only + * adding _BW is supported today. + * + * @netdev_features: netdev features to be set in each netdev created + * from this HW. Note only HW checksum features are currently + * compatible with mac80211. Other feature bits will be rejected. */ struct ieee80211_hw { struct ieee80211_conf conf; @@ -1286,6 +1327,9 @@ struct ieee80211_hw { u8 max_rate_tries; u8 max_rx_aggregation_subframes; u8 max_tx_aggregation_subframes; + u8 offchannel_tx_hw_queue; + u8 radiotap_mcs_details; + netdev_features_t netdev_features; }; /** @@ -1694,6 +1738,61 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb); */ /** + * DOC: HW queue control + * + * Before HW queue control was introduced, mac80211 only had a single static + * assignment of per-interface AC software queues to hardware queues. This + * was problematic for a few reasons: + * 1) off-channel transmissions might get stuck behind other frames + * 2) multiple virtual interfaces couldn't be handled correctly + * 3) after-DTIM frames could get stuck behind other frames + * + * To solve this, hardware typically uses multiple different queues for all + * the different usages, and this needs to be propagated into mac80211 so it + * won't have the same problem with the software queues. + * + * Therefore, mac80211 now offers the %IEEE80211_HW_QUEUE_CONTROL capability + * flag that tells it that the driver implements its own queue control. To do + * so, the driver will set up the various queues in each &struct ieee80211_vif + * and the offchannel queue in &struct ieee80211_hw. In response, mac80211 will + * use those queue IDs in the hw_queue field of &struct ieee80211_tx_info and + * if necessary will queue the frame on the right software queue that mirrors + * the hardware queue. + * Additionally, the driver has to then use these HW queue IDs for the queue + * management functions (ieee80211_stop_queue() et al.) + * + * The driver is free to set up the queue mappings as needed, multiple virtual + * interfaces may map to the same hardware queues if needed. The setup has to + * happen during add_interface or change_interface callbacks. For example, a + * driver supporting station+station and station+AP modes might decide to have + * 10 hardware queues to handle different scenarios: + * + * 4 AC HW queues for 1st vif: 0, 1, 2, 3 + * 4 AC HW queues for 2nd vif: 4, 5, 6, 7 + * after-DTIM queue for AP: 8 + * off-channel queue: 9 + * + * It would then set up the hardware like this: + * hw.offchannel_tx_hw_queue = 9 + * + * and the first virtual interface that is added as follows: + * vif.hw_queue[IEEE80211_AC_VO] = 0 + * vif.hw_queue[IEEE80211_AC_VI] = 1 + * vif.hw_queue[IEEE80211_AC_BE] = 2 + * vif.hw_queue[IEEE80211_AC_BK] = 3 + * vif.cab_queue = 8 // if AP mode, otherwise %IEEE80211_INVAL_HW_QUEUE + * and the second virtual interface with 4-7. + * + * If queue 6 gets full, for example, mac80211 would only stop the second + * virtual interface's BE queue since virtual interface queues are per AC. + * + * Note that the vif.cab_queue value should be set to %IEEE80211_INVAL_HW_QUEUE + * whenever the queue is not used (i.e. the interface is not in AP mode) if the + * queue could potentially be shared since mac80211 will look at cab_queue when + * a queue is stopped/woken even if the interface is not in AP mode. + */ + +/** * enum ieee80211_filter_flags - hardware filter flags * * These flags determine what the filter in hardware should be @@ -1780,6 +1879,18 @@ enum ieee80211_frame_release_type { }; /** + * enum ieee80211_rate_control_changed - flags to indicate what changed + * + * @IEEE80211_RC_BW_CHANGED: The bandwidth that can be used to transmit + * to this station changed. + * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed. + */ +enum ieee80211_rate_control_changed { + IEEE80211_RC_BW_CHANGED = BIT(0), + IEEE80211_RC_SMPS_CHANGED = BIT(1), +}; + +/** * struct ieee80211_ops - callbacks from mac80211 to the driver * * This structure contains various callbacks that the driver may @@ -1791,19 +1902,6 @@ enum ieee80211_frame_release_type { * The low-level driver should send the frame out based on * configuration in the TX control data. This handler should, * preferably, never fail and stop queues appropriately. - * This must be implemented if @tx_frags is not. - * Must be atomic. - * - * @tx_frags: Called to transmit multiple fragments of a single MSDU. - * This handler must consume all fragments, sending out some of - * them only is useless and it can't ask for some of them to be - * queued again. If the frame is not fragmented the queue has a - * single SKB only. To avoid issues with the networking stack - * when TX status is reported the frames should be removed from - * the skb queue. - * If this is used, the tx_info @vif and @sta pointers will be - * invalid -- you must not use them in that case. - * This must be implemented if @tx isn't. * Must be atomic. * * @start: Called before the first netdevice attached to the hardware @@ -1840,6 +1938,11 @@ enum ieee80211_frame_release_type { * to also unregister the device. If it returns 1, then mac80211 * will also go through the regular complete restart on resume. * + * @set_wakeup: Enable or disable wakeup when WoWLAN configuration is + * modified. The reason is that device_set_wakeup_enable() is + * supposed to be called when the configuration changes, not only + * in suspend(). + * * @add_interface: Called when a netdevice attached to the hardware is * enabled. Because it is not called for monitor mode devices, @start * and @stop must be implemented. @@ -1980,6 +2083,14 @@ enum ieee80211_frame_release_type { * up the list of states. * The callback can sleep. * + * @sta_rc_update: Notifies the driver of changes to the bitrates that can be + * used to transmit to the station. The changes are advertised with bits + * from &enum ieee80211_rate_control_changed and the values are reflected + * in the station data. This callback should only be used when the driver + * uses hardware rate control (%IEEE80211_HW_HAS_RATE_CONTROL) since + * otherwise the rate control algorithm is notified directly. + * Must be atomic. + * * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), * bursting) for a hardware TX queue. * Returns a negative error code on failure. @@ -2070,7 +2181,10 @@ enum ieee80211_frame_release_type { * offload. Frames to transmit on the off-channel channel are transmitted * normally except for the %IEEE80211_TX_CTL_TX_OFFCHAN flag. When the * duration (which will always be non-zero) expires, the driver must call - * ieee80211_remain_on_channel_expired(). This callback may sleep. + * ieee80211_remain_on_channel_expired(). + * Note that this callback may be called while the device is in IDLE and + * must be accepted in this case. + * This callback may sleep. * @cancel_remain_on_channel: Requests that an ongoing off-channel period is * aborted before it expires. This callback may sleep. * @@ -2125,16 +2239,38 @@ enum ieee80211_frame_release_type { * The @tids parameter is a bitmap and tells the driver which TIDs the * frames will be on; it will at most have two bits set. * This callback must be atomic. + * + * @get_et_sset_count: Ethtool API to get string-set count. + * + * @get_et_stats: Ethtool API to get a set of u64 stats. + * + * @get_et_strings: Ethtool API to get a set of strings to describe stats + * and perhaps other supported types of ethtool data-sets. + * + * @get_rssi: Get current signal strength in dBm, the function is optional + * and can sleep. + * + * @mgd_prepare_tx: Prepare for transmitting a management frame for association + * before associated. In multi-channel scenarios, a virtual interface is + * bound to a channel before it is associated, but as it isn't associated + * yet it need not necessarily be given airtime, in particular since any + * transmission to a P2P GO needs to be synchronized against the GO's + * powersave state. mac80211 will call this function before transmitting a + * management frame prior to having successfully associated to allow the + * driver to give it channel time for the transmission, to get a response + * and to be able to synchronize with the GO. + * The callback will be called before each transmission and upon return + * mac80211 will transmit the frame right away. + * The callback is optional and can (should!) sleep. */ struct ieee80211_ops { void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); - void (*tx_frags)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - struct ieee80211_sta *sta, struct sk_buff_head *skbs); int (*start)(struct ieee80211_hw *hw); void (*stop)(struct ieee80211_hw *hw); #ifdef CONFIG_PM int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); int (*resume)(struct ieee80211_hw *hw); + void (*set_wakeup)(struct ieee80211_hw *hw, bool enabled); #endif int (*add_interface)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); @@ -2196,8 +2332,12 @@ struct ieee80211_ops { struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state); + void (*sta_rc_update)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + u32 changed); int (*conf_tx)(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, u16 queue, + struct ieee80211_vif *vif, u16 ac, const struct ieee80211_tx_queue_params *params); u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif); void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, @@ -2250,6 +2390,20 @@ struct ieee80211_ops { u16 tids, int num_frames, enum ieee80211_frame_release_type reason, bool more_data); + + int (*get_et_sset_count)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, int sset); + void (*get_et_stats)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ethtool_stats *stats, u64 *data); + void (*get_et_strings)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + u32 sset, u8 *data); + int (*get_rssi)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, s8 *rssi_dbm); + + void (*mgd_prepare_tx)(struct ieee80211_hw *hw, + struct ieee80211_vif *vif); }; /** @@ -2836,6 +2990,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, * ieee80211_generic_frame_duration - Calculate the duration field for a frame * @hw: pointer obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @band: the band to calculate the frame duration on * @frame_len: the length of the frame. * @rate: the rate at which the frame is going to be transmitted. * @@ -2844,6 +2999,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, */ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum ieee80211_band band, size_t frame_len, struct ieee80211_rate *rate); @@ -3420,16 +3576,6 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, gfp_t gfp); /** - * ieee80211_get_operstate - get the operstate of the vif - * - * @vif: &struct ieee80211_vif pointer from the add_interface callback. - * - * The driver might need to know the operstate of the net_device - * (specifically, whether the link is IF_OPER_UP after resume) - */ -unsigned char ieee80211_get_operstate(struct ieee80211_vif *vif); - -/** * ieee80211_chswitch_done - Complete channel switch process * @vif: &struct ieee80211_vif pointer from the add_interface callback. * @success: make the channel switch successful or not @@ -3452,22 +3598,6 @@ void ieee80211_request_smps(struct ieee80211_vif *vif, enum ieee80211_smps_mode smps_mode); /** - * ieee80211_key_removed - disable hw acceleration for key - * @key_conf: The key hw acceleration should be disabled for - * - * This allows drivers to indicate that the given key has been - * removed from hardware acceleration, due to a new key that - * was added. Don't use this if the key can continue to be used - * for TX, if the key restriction is on RX only it is permitted - * to keep the key for TX only and not call this function. - * - * Due to locking constraints, it may only be called during - * @set_key. This function must be allowed to sleep, and the - * key it tries to disable may still be used until it returns. - */ -void ieee80211_key_removed(struct ieee80211_key_conf *key_conf); - -/** * ieee80211_ready_on_channel - notification of remain-on-channel start * @hw: pointer as obtained from ieee80211_alloc_hw() */ @@ -3512,19 +3642,6 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn); /* Rate control API */ /** - * enum rate_control_changed - flags to indicate which parameter changed - * - * @IEEE80211_RC_HT_CHANGED: The HT parameters of the operating channel have - * changed, rate control algorithm can update its internal state if needed. - * @IEEE80211_RC_SMPS_CHANGED: The SMPS state of the station changed, the rate - * control algorithm needs to adjust accordingly. - */ -enum rate_control_changed { - IEEE80211_RC_HT_CHANGED = BIT(0), - IEEE80211_RC_SMPS_CHANGED = BIT(1), -}; - -/** * struct ieee80211_tx_rate_control - rate control information for/from RC algo * * @hw: The hardware the algorithm is invoked for. @@ -3569,9 +3686,8 @@ struct rate_control_ops { void (*rate_init)(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta); void (*rate_update)(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, - void *priv_sta, u32 changed, - enum nl80211_channel_type oper_chan_type); + struct ieee80211_sta *sta, void *priv_sta, + u32 changed); void (*free_sta)(void *priv, struct ieee80211_sta *sta, void *priv_sta); @@ -3706,8 +3822,14 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif, void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif); -int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb); +/** + * ieee80211_ave_rssi - report the average rssi for the specified interface + * + * @vif: the specified virtual interface + * + * This function return the average rssi value for the requested interface. + * It assumes that the given vif is valid. + */ +int ieee80211_ave_rssi(struct ieee80211_vif *vif); -int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, - struct sk_buff *skb); #endif /* MAC80211_H */ diff --git a/include/net/mac802154.h b/include/net/mac802154.h new file mode 100644 index 000000000000..d0d11df9cba1 --- /dev/null +++ b/include/net/mac802154.h @@ -0,0 +1,144 @@ +/* + * IEEE802.15.4-2003 specification + * + * Copyright (C) 2007-2012 Siemens AG + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef NET_MAC802154_H +#define NET_MAC802154_H + +#include <net/af_ieee802154.h> + +/* General MAC frame format: + * 2 bytes: Frame Control + * 1 byte: Sequence Number + * 20 bytes: Addressing fields + * 14 bytes: Auxiliary Security Header + */ +#define MAC802154_FRAME_HARD_HEADER_LEN (2 + 1 + 20 + 14) + +/* The following flags are used to indicate changed address settings from + * the stack to the hardware. + */ + +/* indicates that the Short Address changed */ +#define IEEE802515_AFILT_SADDR_CHANGED 0x00000001 +/* indicates that the IEEE Address changed */ +#define IEEE802515_AFILT_IEEEADDR_CHANGED 0x00000002 +/* indicates that the PAN ID changed */ +#define IEEE802515_AFILT_PANID_CHANGED 0x00000004 +/* indicates that PAN Coordinator status changed */ +#define IEEE802515_AFILT_PANC_CHANGED 0x00000008 + +struct ieee802154_hw_addr_filt { + __le16 pan_id; /* Each independent PAN selects a unique + * identifier. This PAN id allows communication + * between devices within a network using short + * addresses and enables transmissions between + * devices across independent networks. + */ + __le16 short_addr; + u8 ieee_addr[IEEE802154_ADDR_LEN]; + u8 pan_coord; +}; + +struct ieee802154_dev { + /* filled by the driver */ + int extra_tx_headroom; + u32 flags; + struct device *parent; + + /* filled by mac802154 core */ + struct ieee802154_hw_addr_filt hw_filt; + void *priv; + struct wpan_phy *phy; +}; + +/* Checksum is in hardware and is omitted from a packet + * + * These following flags are used to indicate hardware capabilities to + * the stack. Generally, flags here should have their meaning + * done in a way that the simplest hardware doesn't need setting + * any particular flags. There are some exceptions to this rule, + * however, so you are advised to review these flags carefully. + */ + +/* Indicates that receiver omits FCS and xmitter will add FCS on it's own. */ +#define IEEE802154_HW_OMIT_CKSUM 0x00000001 +/* Indicates that receiver will autorespond with ACK frames. */ +#define IEEE802154_HW_AACK 0x00000002 + +/* struct ieee802154_ops - callbacks from mac802154 to the driver + * + * This structure contains various callbacks that the driver may + * handle or, in some cases, must handle, for example to transmit + * a frame. + * + * start: Handler that 802.15.4 module calls for device initialization. + * This function is called before the first interface is attached. + * + * stop: Handler that 802.15.4 module calls for device cleanup. + * This function is called after the last interface is removed. + * + * xmit: Handler that 802.15.4 module calls for each transmitted frame. + * skb cntains the buffer starting from the IEEE 802.15.4 header. + * The low-level driver should send the frame based on available + * configuration. + * This function should return zero or negative errno. Called with + * pib_lock held. + * + * ed: Handler that 802.15.4 module calls for Energy Detection. + * This function should place the value for detected energy + * (usually device-dependant) in the level pointer and return + * either zero or negative errno. Called with pib_lock held. + * + * set_channel: + * Set radio for listening on specific channel. + * Set the device for listening on specified channel. + * Returns either zero, or negative errno. Called with pib_lock held. + * + * set_hw_addr_filt: + * Set radio for listening on specific address. + * Set the device for listening on specified address. + * Returns either zero, or negative errno. + */ +struct ieee802154_ops { + struct module *owner; + int (*start)(struct ieee802154_dev *dev); + void (*stop)(struct ieee802154_dev *dev); + int (*xmit)(struct ieee802154_dev *dev, + struct sk_buff *skb); + int (*ed)(struct ieee802154_dev *dev, u8 *level); + int (*set_channel)(struct ieee802154_dev *dev, + int page, + int channel); + int (*set_hw_addr_filt)(struct ieee802154_dev *dev, + struct ieee802154_hw_addr_filt *filt, + unsigned long changed); + int (*ieee_addr)(struct ieee802154_dev *dev, + u8 addr[IEEE802154_ADDR_LEN]); +}; + +/* Basic interface to register ieee802154 device */ +struct ieee802154_dev * +ieee802154_alloc_device(size_t priv_data_lex, struct ieee802154_ops *ops); +void ieee802154_free_device(struct ieee802154_dev *dev); +int ieee802154_register_device(struct ieee802154_dev *dev); +void ieee802154_unregister_device(struct ieee802154_dev *dev); + +void ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb, + u8 lqi); + +#endif /* NET_MAC802154_H */ diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 6f9c25a76cd1..96a3b5c03e37 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -34,6 +34,7 @@ enum { __ND_OPT_ARRAY_MAX, ND_OPT_ROUTE_INFO = 24, /* RFC4191 */ ND_OPT_RDNSS = 25, /* RFC5006 */ + ND_OPT_DNSSL = 31, /* RFC6106 */ __ND_OPT_MAX }; @@ -46,6 +47,8 @@ enum { #include <linux/icmpv6.h> #include <linux/in6.h> #include <linux/types.h> +#include <linux/if_arp.h> +#include <linux/netdevice.h> #include <net/neighbour.h> @@ -79,6 +82,54 @@ struct nd_opt_hdr { __u8 nd_opt_len; } __packed; +/* ND options */ +struct ndisc_options { + struct nd_opt_hdr *nd_opt_array[__ND_OPT_ARRAY_MAX]; +#ifdef CONFIG_IPV6_ROUTE_INFO + struct nd_opt_hdr *nd_opts_ri; + struct nd_opt_hdr *nd_opts_ri_end; +#endif + struct nd_opt_hdr *nd_useropts; + struct nd_opt_hdr *nd_useropts_end; +}; + +#define nd_opts_src_lladdr nd_opt_array[ND_OPT_SOURCE_LL_ADDR] +#define nd_opts_tgt_lladdr nd_opt_array[ND_OPT_TARGET_LL_ADDR] +#define nd_opts_pi nd_opt_array[ND_OPT_PREFIX_INFO] +#define nd_opts_pi_end nd_opt_array[__ND_OPT_PREFIX_INFO_END] +#define nd_opts_rh nd_opt_array[ND_OPT_REDIRECT_HDR] +#define nd_opts_mtu nd_opt_array[ND_OPT_MTU] + +#define NDISC_OPT_SPACE(len) (((len)+2+7)&~7) + +extern struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, + struct ndisc_options *ndopts); + +/* + * Return the padding between the option length and the start of the + * link addr. Currently only IP-over-InfiniBand needs this, although + * if RFC 3831 IPv6-over-Fibre Channel is ever implemented it may + * also need a pad of 2. + */ +static int ndisc_addr_option_pad(unsigned short type) +{ + switch (type) { + case ARPHRD_INFINIBAND: return 2; + default: return 0; + } +} + +static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, + struct net_device *dev) +{ + u8 *lladdr = (u8 *)(p + 1); + int lladdrlen = p->nd_opt_len << 3; + int prepad = ndisc_addr_option_pad(dev->type); + if (lladdrlen != NDISC_OPT_SPACE(dev->addr_len + prepad)) + return NULL; + return lladdr + prepad; +} + static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd) { const u32 *p32 = pkey; diff --git a/include/net/neighbour.h b/include/net/neighbour.h index 34c996f46181..344d8988842a 100644 --- a/include/net/neighbour.h +++ b/include/net/neighbour.h @@ -195,7 +195,6 @@ static inline void *neighbour_priv(const struct neighbour *n) #define NEIGH_UPDATE_F_ADMIN 0x80000000 extern void neigh_table_init(struct neigh_table *tbl); -extern void neigh_table_init_no_netlink(struct neigh_table *tbl); extern int neigh_table_clear(struct neigh_table *tbl); extern struct neighbour * neigh_lookup(struct neigh_table *tbl, const void *pkey, @@ -203,9 +202,16 @@ extern struct neighbour * neigh_lookup(struct neigh_table *tbl, extern struct neighbour * neigh_lookup_nodev(struct neigh_table *tbl, struct net *net, const void *pkey); -extern struct neighbour * neigh_create(struct neigh_table *tbl, +extern struct neighbour * __neigh_create(struct neigh_table *tbl, + const void *pkey, + struct net_device *dev, + bool want_ref); +static inline struct neighbour *neigh_create(struct neigh_table *tbl, const void *pkey, - struct net_device *dev); + struct net_device *dev) +{ + return __neigh_create(tbl, pkey, dev, true); +} extern void neigh_destroy(struct neighbour *neigh); extern int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb); extern int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, @@ -303,12 +309,6 @@ static inline struct neighbour * neigh_clone(struct neighbour *neigh) #define neigh_hold(n) atomic_inc(&(n)->refcnt) -static inline void neigh_confirm(struct neighbour *neigh) -{ - if (neigh) - neigh->confirmed = jiffies; -} - static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) { unsigned long now = jiffies; @@ -323,7 +323,7 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb) #ifdef CONFIG_BRIDGE_NETFILTER static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) { - unsigned seq, hh_alen; + unsigned int seq, hh_alen; do { seq = read_seqbegin(&hh->hh_lock); @@ -336,7 +336,7 @@ static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) { - unsigned seq; + unsigned int seq; int hh_len; do { @@ -352,15 +352,6 @@ static inline int neigh_hh_output(struct hh_cache *hh, struct sk_buff *skb) return dev_queue_xmit(skb); } -static inline int neigh_output(struct neighbour *n, struct sk_buff *skb) -{ - struct hh_cache *hh = &n->hh; - if ((n->nud_state & NUD_CONNECTED) && hh->hh_len) - return neigh_hh_output(hh, skb); - else - return n->output(n, skb); -} - static inline struct neighbour * __neigh_lookup(struct neigh_table *tbl, const void *pkey, struct net_device *dev, int creat) { diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index ee547c149810..ae1cd6c9ba52 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -101,6 +101,7 @@ struct net { struct netns_xfrm xfrm; #endif struct netns_ipvs *ipvs; + struct sock *diag_nlsk; }; @@ -279,14 +280,25 @@ extern void unregister_pernet_subsys(struct pernet_operations *); extern int register_pernet_device(struct pernet_operations *); extern void unregister_pernet_device(struct pernet_operations *); -struct ctl_path; struct ctl_table; struct ctl_table_header; -extern struct ctl_table_header *register_net_sysctl_table(struct net *net, - const struct ctl_path *path, struct ctl_table *table); -extern struct ctl_table_header *register_net_sysctl_rotable( - const struct ctl_path *path, struct ctl_table *table); +#ifdef CONFIG_SYSCTL +extern int net_sysctl_init(void); +extern struct ctl_table_header *register_net_sysctl(struct net *net, + const char *path, struct ctl_table *table); extern void unregister_net_sysctl_table(struct ctl_table_header *header); +#else +static inline int net_sysctl_init(void) { return 0; } +static inline struct ctl_table_header *register_net_sysctl(struct net *net, + const char *path, struct ctl_table *table) +{ + return NULL; +} +static inline void unregister_net_sysctl_table(struct ctl_table_header *header) +{ +} +#endif + #endif /* __NET_NET_NAMESPACE_H */ diff --git a/include/net/netevent.h b/include/net/netevent.h index 086f8a5b59dc..3ce4988c9c08 100644 --- a/include/net/netevent.h +++ b/include/net/netevent.h @@ -12,10 +12,14 @@ */ struct dst_entry; +struct neighbour; struct netevent_redirect { struct dst_entry *old; + struct neighbour *old_neigh; struct dst_entry *new; + struct neighbour *new_neigh; + const void *daddr; }; enum netevent_notif_type { diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index ab86036bbf0c..f1494feba79f 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -39,36 +39,6 @@ union nf_conntrack_expect_proto { /* insert expect proto private data here */ }; -/* Add protocol helper include file here */ -#include <linux/netfilter/nf_conntrack_ftp.h> -#include <linux/netfilter/nf_conntrack_pptp.h> -#include <linux/netfilter/nf_conntrack_h323.h> -#include <linux/netfilter/nf_conntrack_sane.h> -#include <linux/netfilter/nf_conntrack_sip.h> - -/* per conntrack: application helper private data */ -union nf_conntrack_help { - /* insert conntrack helper private data (master) here */ -#if defined(CONFIG_NF_CONNTRACK_FTP) || defined(CONFIG_NF_CONNTRACK_FTP_MODULE) - struct nf_ct_ftp_master ct_ftp_info; -#endif -#if defined(CONFIG_NF_CONNTRACK_PPTP) || \ - defined(CONFIG_NF_CONNTRACK_PPTP_MODULE) - struct nf_ct_pptp_master ct_pptp_info; -#endif -#if defined(CONFIG_NF_CONNTRACK_H323) || \ - defined(CONFIG_NF_CONNTRACK_H323_MODULE) - struct nf_ct_h323_master ct_h323_info; -#endif -#if defined(CONFIG_NF_CONNTRACK_SANE) || \ - defined(CONFIG_NF_CONNTRACK_SANE_MODULE) - struct nf_ct_sane_master ct_sane_info; -#endif -#if defined(CONFIG_NF_CONNTRACK_SIP) || defined(CONFIG_NF_CONNTRACK_SIP_MODULE) - struct nf_ct_sip_master ct_sip_info; -#endif -}; - #include <linux/types.h> #include <linux/skbuff.h> #include <linux/timer.h> @@ -89,12 +59,13 @@ struct nf_conn_help { /* Helper. if any */ struct nf_conntrack_helper __rcu *helper; - union nf_conntrack_help help; - struct hlist_head expectations; /* Current number of expected connections */ u8 expecting[NF_CT_MAX_EXPECT_CLASSES]; + + /* private helper information. */ + char data[]; }; #include <net/netfilter/ipv4/nf_conntrack_ipv4.h> @@ -321,14 +292,8 @@ extern unsigned int nf_conntrack_max; extern unsigned int nf_conntrack_hash_rnd; void init_nf_conntrack_hash_rnd(void); -#define NF_CT_STAT_INC(net, count) \ - __this_cpu_inc((net)->ct.stat->count) -#define NF_CT_STAT_INC_ATOMIC(net, count) \ -do { \ - local_bh_disable(); \ - __this_cpu_inc((net)->ct.stat->count); \ - local_bh_enable(); \ -} while (0) +#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count) +#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) #define MODULE_ALIAS_NFCT_HELPER(helper) \ MODULE_ALIAS("nfct-helper-" helper) diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index aced085132e7..d8f5b9f52169 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -28,8 +28,8 @@ extern unsigned int nf_conntrack_in(struct net *net, extern int nf_conntrack_init(struct net *net); extern void nf_conntrack_cleanup(struct net *net); -extern int nf_conntrack_proto_init(void); -extern void nf_conntrack_proto_fini(void); +extern int nf_conntrack_proto_init(struct net *net); +extern void nf_conntrack_proto_fini(struct net *net); extern bool nf_ct_get_tuple(const struct sk_buff *skb, diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index a88fb6939387..e1ce1048fe5f 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -78,7 +78,7 @@ nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct) struct net *net = nf_ct_net(ct); struct nf_conntrack_ecache *e; - if (net->ct.nf_conntrack_event_cb == NULL) + if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb)) return; e = nf_ct_ecache_find(ct); diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 4619caadd9d1..983f00263243 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h @@ -59,10 +59,12 @@ static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp) return nf_ct_net(exp->master); } +#define NF_CT_EXP_POLICY_NAME_LEN 16 + struct nf_conntrack_expect_policy { unsigned int max_expected; unsigned int timeout; - const char *name; + char name[NF_CT_EXP_POLICY_NAME_LEN]; }; #define NF_CT_EXPECT_CLASS_DEFAULT 0 diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 96755c3798a5..8b4d1fc29096 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -80,10 +80,13 @@ static inline void nf_ct_ext_free(struct nf_conn *ct) } /* Add this type, returns pointer to data or NULL. */ -void * -__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp); +void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id, + size_t var_alloc_len, gfp_t gfp); + #define nf_ct_ext_add(ct, id, gfp) \ - ((id##_TYPE *)__nf_ct_ext_add((ct), (id), (gfp))) + ((id##_TYPE *)__nf_ct_ext_add_length((ct), (id), 0, (gfp))) +#define nf_ct_ext_add_length(ct, id, len, gfp) \ + ((id##_TYPE *)__nf_ct_ext_add_length((ct), (id), (len), (gfp))) #define NF_CT_EXT_F_PREALLOC 0x0001 diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 5767dc242dee..9aad956d1008 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -11,18 +11,27 @@ #define _NF_CONNTRACK_HELPER_H #include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack_extend.h> +#include <net/netfilter/nf_conntrack_expect.h> struct module; +enum nf_ct_helper_flags { + NF_CT_HELPER_F_USERSPACE = (1 << 0), + NF_CT_HELPER_F_CONFIGURED = (1 << 1), +}; + #define NF_CT_HELPER_NAME_LEN 16 struct nf_conntrack_helper { struct hlist_node hnode; /* Internal use. */ - const char *name; /* name of the module */ + char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */ struct module *me; /* pointer to self */ const struct nf_conntrack_expect_policy *expect_policy; + /* length of internal data, ie. sizeof(struct nf_ct_*_master) */ + size_t data_len; + /* Tuple of things we will help (compared against server response) */ struct nf_conntrack_tuple tuple; @@ -35,8 +44,12 @@ struct nf_conntrack_helper { void (*destroy)(struct nf_conn *ct); + int (*from_nlattr)(struct nlattr *attr, struct nf_conn *ct); int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct); unsigned int expect_class_max; + + unsigned int flags; + unsigned int queue_num; /* For user-space helpers. */ }; extern struct nf_conntrack_helper * @@ -48,7 +61,7 @@ nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum); extern int nf_conntrack_helper_register(struct nf_conntrack_helper *); extern void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); -extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp); +extern struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, struct nf_conntrack_helper *helper, gfp_t gfp); extern int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, gfp_t flags); @@ -60,8 +73,17 @@ static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct) return nf_ct_ext_find(ct, NF_CT_EXT_HELPER); } -extern int nf_conntrack_helper_init(void); -extern void nf_conntrack_helper_fini(void); +static inline void *nfct_help_data(const struct nf_conn *ct) +{ + struct nf_conn_help *help; + + help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER); + + return (void *)help->data; +} + +extern int nf_conntrack_helper_init(struct net *net); +extern void nf_conntrack_helper_fini(struct net *net); extern int nf_conntrack_broadcast_help(struct sk_buff *skb, unsigned int protoff, @@ -82,4 +104,7 @@ nf_ct_helper_expectfn_find_by_name(const char *name); struct nf_ct_helper_expectfn * nf_ct_helper_expectfn_find_by_symbol(const void *symbol); +extern struct hlist_head *nf_ct_helper_hash; +extern unsigned int nf_ct_helper_hsize; + #endif /*_NF_CONNTRACK_HELPER_H*/ diff --git a/include/net/netfilter/nf_conntrack_l3proto.h b/include/net/netfilter/nf_conntrack_l3proto.h index e8010f445ae1..6f7c13f4ac03 100644 --- a/include/net/netfilter/nf_conntrack_l3proto.h +++ b/include/net/netfilter/nf_conntrack_l3proto.h @@ -64,11 +64,12 @@ struct nf_conntrack_l3proto { size_t nla_size; #ifdef CONFIG_SYSCTL - struct ctl_table_header *ctl_table_header; - struct ctl_path *ctl_table_path; - struct ctl_table *ctl_table; + const char *ctl_table_path; #endif /* CONFIG_SYSCTL */ + /* Init l3proto pernet data */ + int (*init_net)(struct net *net); + /* Module (if any) which this is connected to. */ struct module *me; }; @@ -76,8 +77,10 @@ struct nf_conntrack_l3proto { extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[AF_MAX]; /* Protocol registration. */ -extern int nf_conntrack_l3proto_register(struct nf_conntrack_l3proto *proto); -extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto); +extern int nf_conntrack_l3proto_register(struct net *net, + struct nf_conntrack_l3proto *proto); +extern void nf_conntrack_l3proto_unregister(struct net *net, + struct nf_conntrack_l3proto *proto); extern struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto); extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p); diff --git a/include/net/netfilter/nf_conntrack_l4proto.h b/include/net/netfilter/nf_conntrack_l4proto.h index 3b572bb20aa2..c3be4aef6bf7 100644 --- a/include/net/netfilter/nf_conntrack_l4proto.h +++ b/include/net/netfilter/nf_conntrack_l4proto.h @@ -12,6 +12,7 @@ #include <linux/netlink.h> #include <net/netlink.h> #include <net/netfilter/nf_conntrack.h> +#include <net/netns/generic.h> struct seq_file; @@ -86,23 +87,21 @@ struct nf_conntrack_l4proto { #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) struct { size_t obj_size; - int (*nlattr_to_obj)(struct nlattr *tb[], void *data); + int (*nlattr_to_obj)(struct nlattr *tb[], + struct net *net, void *data); int (*obj_to_nlattr)(struct sk_buff *skb, const void *data); unsigned int nlattr_max; const struct nla_policy *nla_policy; } ctnl_timeout; #endif + int *net_id; + /* Init l4proto pernet data */ + int (*init_net)(struct net *net, u_int16_t proto); + + /* Return the per-net protocol part. */ + struct nf_proto_net *(*get_net_proto)(struct net *net); -#ifdef CONFIG_SYSCTL - struct ctl_table_header **ctl_table_header; - struct ctl_table *ctl_table; - unsigned int *ctl_table_users; -#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT - struct ctl_table_header *ctl_compat_table_header; - struct ctl_table *ctl_compat_table; -#endif -#endif /* Protocol name */ const char *name; @@ -123,8 +122,18 @@ nf_ct_l4proto_find_get(u_int16_t l3proto, u_int8_t l4proto); extern void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p); /* Protocol registration. */ -extern int nf_conntrack_l4proto_register(struct nf_conntrack_l4proto *proto); -extern void nf_conntrack_l4proto_unregister(struct nf_conntrack_l4proto *proto); +extern int nf_conntrack_l4proto_register(struct net *net, + struct nf_conntrack_l4proto *proto); +extern void nf_conntrack_l4proto_unregister(struct net *net, + struct nf_conntrack_l4proto *proto); + +static inline void nf_ct_kfree_compat_sysctl_table(struct nf_proto_net *pn) +{ +#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) + kfree(pn->ctl_compat_table); + pn->ctl_compat_table = NULL; +#endif +} /* Generic netlink helpers */ extern int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, diff --git a/include/net/netfilter/nf_nat_helper.h b/include/net/netfilter/nf_nat_helper.h index 02bb6c29dc3d..7d8fb7b46c44 100644 --- a/include/net/netfilter/nf_nat_helper.h +++ b/include/net/netfilter/nf_nat_helper.h @@ -54,4 +54,8 @@ extern void nf_nat_follow_master(struct nf_conn *ct, extern s16 nf_nat_get_offset(const struct nf_conn *ct, enum ip_conntrack_dir dir, u32 seq); + +extern void nf_nat_tcp_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, + u32 dir, int off); + #endif diff --git a/include/net/netfilter/nfnetlink_queue.h b/include/net/netfilter/nfnetlink_queue.h new file mode 100644 index 000000000000..86267a529514 --- /dev/null +++ b/include/net/netfilter/nfnetlink_queue.h @@ -0,0 +1,43 @@ +#ifndef _NET_NFNL_QUEUE_H_ +#define _NET_NFNL_QUEUE_H_ + +#include <linux/netfilter/nf_conntrack_common.h> + +struct nf_conn; + +#ifdef CONFIG_NETFILTER_NETLINK_QUEUE_CT +struct nf_conn *nfqnl_ct_get(struct sk_buff *entskb, size_t *size, + enum ip_conntrack_info *ctinfo); +struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb, + const struct nlattr *attr, + enum ip_conntrack_info *ctinfo); +int nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo); +void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, int diff); +#else +inline struct nf_conn * +nfqnl_ct_get(struct sk_buff *entskb, size_t *size, enum ip_conntrack_info *ctinfo) +{ + return NULL; +} + +inline struct nf_conn *nfqnl_ct_parse(const struct sk_buff *skb, + const struct nlattr *attr, + enum ip_conntrack_info *ctinfo) +{ + return NULL; +} + +inline int +nfqnl_ct_put(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info ctinfo) +{ + return 0; +} + +inline void nfqnl_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, + enum ip_conntrack_info ctinfo, int diff) +{ +} +#endif /* NF_CONNTRACK */ +#endif diff --git a/include/net/netlink.h b/include/net/netlink.h index f394fe5d7641..785f37a3b44e 100644 --- a/include/net/netlink.h +++ b/include/net/netlink.h @@ -102,20 +102,6 @@ * nla_put_flag(skb, type) add flag attribute to skb * nla_put_msecs(skb, type, jiffies) add msecs attribute to skb * - * Exceptions Based Attribute Construction: - * NLA_PUT(skb, type, len, data) add attribute to skb - * NLA_PUT_U8(skb, type, value) add u8 attribute to skb - * NLA_PUT_U16(skb, type, value) add u16 attribute to skb - * NLA_PUT_U32(skb, type, value) add u32 attribute to skb - * NLA_PUT_U64(skb, type, value) add u64 attribute to skb - * NLA_PUT_STRING(skb, type, str) add string attribute to skb - * NLA_PUT_FLAG(skb, type) add flag attribute to skb - * NLA_PUT_MSECS(skb, type, jiffies) add msecs attribute to skb - * - * The meaning of these functions is equal to their lower case - * variants but they jump to the label nla_put_failure in case - * of a failure. - * * Nested Attributes Construction: * nla_nest_start(skb, type) start a nested attribute * nla_nest_end(skb, nla) finalize a nested attribute @@ -772,6 +758,39 @@ static inline int nla_put_u16(struct sk_buff *skb, int attrtype, u16 value) } /** + * nla_put_be16 - Add a __be16 netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_be16(struct sk_buff *skb, int attrtype, __be16 value) +{ + return nla_put(skb, attrtype, sizeof(__be16), &value); +} + +/** + * nla_put_net16 - Add 16-bit network byte order netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_net16(struct sk_buff *skb, int attrtype, __be16 value) +{ + return nla_put_be16(skb, attrtype | NLA_F_NET_BYTEORDER, value); +} + +/** + * nla_put_le16 - Add a __le16 netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_le16(struct sk_buff *skb, int attrtype, __le16 value) +{ + return nla_put(skb, attrtype, sizeof(__le16), &value); +} + +/** * nla_put_u32 - Add a u32 netlink attribute to a socket buffer * @skb: socket buffer to add attribute to * @attrtype: attribute type @@ -783,7 +802,40 @@ static inline int nla_put_u32(struct sk_buff *skb, int attrtype, u32 value) } /** - * nla_put_64 - Add a u64 netlink attribute to a socket buffer + * nla_put_be32 - Add a __be32 netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_be32(struct sk_buff *skb, int attrtype, __be32 value) +{ + return nla_put(skb, attrtype, sizeof(__be32), &value); +} + +/** + * nla_put_net32 - Add 32-bit network byte order netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_net32(struct sk_buff *skb, int attrtype, __be32 value) +{ + return nla_put_be32(skb, attrtype | NLA_F_NET_BYTEORDER, value); +} + +/** + * nla_put_le32 - Add a __le32 netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_le32(struct sk_buff *skb, int attrtype, __le32 value) +{ + return nla_put(skb, attrtype, sizeof(__le32), &value); +} + +/** + * nla_put_u64 - Add a u64 netlink attribute to a socket buffer * @skb: socket buffer to add attribute to * @attrtype: attribute type * @value: numeric value @@ -794,6 +846,39 @@ static inline int nla_put_u64(struct sk_buff *skb, int attrtype, u64 value) } /** + * nla_put_be64 - Add a __be64 netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_be64(struct sk_buff *skb, int attrtype, __be64 value) +{ + return nla_put(skb, attrtype, sizeof(__be64), &value); +} + +/** + * nla_put_net64 - Add 64-bit network byte order netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_net64(struct sk_buff *skb, int attrtype, __be64 value) +{ + return nla_put_be64(skb, attrtype | NLA_F_NET_BYTEORDER, value); +} + +/** + * nla_put_le64 - Add a __le64 netlink attribute to a socket buffer + * @skb: socket buffer to add attribute to + * @attrtype: attribute type + * @value: numeric value + */ +static inline int nla_put_le64(struct sk_buff *skb, int attrtype, __le64 value) +{ + return nla_put(skb, attrtype, sizeof(__le64), &value); +} + +/** * nla_put_string - Add a string netlink attribute to a socket buffer * @skb: socket buffer to add attribute to * @attrtype: attribute type @@ -828,60 +913,6 @@ static inline int nla_put_msecs(struct sk_buff *skb, int attrtype, return nla_put(skb, attrtype, sizeof(u64), &tmp); } -#define NLA_PUT(skb, attrtype, attrlen, data) \ - do { \ - if (unlikely(nla_put(skb, attrtype, attrlen, data) < 0)) \ - goto nla_put_failure; \ - } while(0) - -#define NLA_PUT_TYPE(skb, type, attrtype, value) \ - do { \ - type __tmp = value; \ - NLA_PUT(skb, attrtype, sizeof(type), &__tmp); \ - } while(0) - -#define NLA_PUT_U8(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, u8, attrtype, value) - -#define NLA_PUT_U16(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, u16, attrtype, value) - -#define NLA_PUT_LE16(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, __le16, attrtype, value) - -#define NLA_PUT_BE16(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, __be16, attrtype, value) - -#define NLA_PUT_NET16(skb, attrtype, value) \ - NLA_PUT_BE16(skb, attrtype | NLA_F_NET_BYTEORDER, value) - -#define NLA_PUT_U32(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, u32, attrtype, value) - -#define NLA_PUT_BE32(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, __be32, attrtype, value) - -#define NLA_PUT_NET32(skb, attrtype, value) \ - NLA_PUT_BE32(skb, attrtype | NLA_F_NET_BYTEORDER, value) - -#define NLA_PUT_U64(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, u64, attrtype, value) - -#define NLA_PUT_BE64(skb, attrtype, value) \ - NLA_PUT_TYPE(skb, __be64, attrtype, value) - -#define NLA_PUT_NET64(skb, attrtype, value) \ - NLA_PUT_BE64(skb, attrtype | NLA_F_NET_BYTEORDER, value) - -#define NLA_PUT_STRING(skb, attrtype, value) \ - NLA_PUT(skb, attrtype, strlen(value) + 1, value) - -#define NLA_PUT_FLAG(skb, attrtype) \ - NLA_PUT(skb, attrtype, 0, NULL) - -#define NLA_PUT_MSECS(skb, attrtype, jiffies) \ - NLA_PUT_U64(skb, attrtype, jiffies_to_msecs(jiffies)) - /** * nla_get_u32 - return payload of u32 attribute * @nla: u32 netlink attribute diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h index 7a911eca0f18..3aecdc7a84fb 100644 --- a/include/net/netns/conntrack.h +++ b/include/net/netns/conntrack.h @@ -4,10 +4,64 @@ #include <linux/list.h> #include <linux/list_nulls.h> #include <linux/atomic.h> +#include <linux/netfilter/nf_conntrack_tcp.h> struct ctl_table_header; struct nf_conntrack_ecache; +struct nf_proto_net { +#ifdef CONFIG_SYSCTL + struct ctl_table_header *ctl_table_header; + struct ctl_table *ctl_table; +#ifdef CONFIG_NF_CONNTRACK_PROC_COMPAT + struct ctl_table_header *ctl_compat_header; + struct ctl_table *ctl_compat_table; +#endif +#endif + unsigned int users; +}; + +struct nf_generic_net { + struct nf_proto_net pn; + unsigned int timeout; +}; + +struct nf_tcp_net { + struct nf_proto_net pn; + unsigned int timeouts[TCP_CONNTRACK_TIMEOUT_MAX]; + unsigned int tcp_loose; + unsigned int tcp_be_liberal; + unsigned int tcp_max_retrans; +}; + +enum udp_conntrack { + UDP_CT_UNREPLIED, + UDP_CT_REPLIED, + UDP_CT_MAX +}; + +struct nf_udp_net { + struct nf_proto_net pn; + unsigned int timeouts[UDP_CT_MAX]; +}; + +struct nf_icmp_net { + struct nf_proto_net pn; + unsigned int timeout; +}; + +struct nf_ip_net { + struct nf_generic_net generic; + struct nf_tcp_net tcp; + struct nf_udp_net udp; + struct nf_icmp_net icmp; + struct nf_icmp_net icmpv6; +#if defined(CONFIG_SYSCTL) && defined(CONFIG_NF_CONNTRACK_PROC_COMPAT) + struct ctl_table_header *ctl_table_header; + struct ctl_table *ctl_table; +#endif +}; + struct netns_ct { atomic_t count; unsigned int expect_count; @@ -26,11 +80,15 @@ struct netns_ct { int sysctl_tstamp; int sysctl_checksum; unsigned int sysctl_log_invalid; /* Log invalid packets */ + int sysctl_auto_assign_helper; + bool auto_assign_helper_warned; + struct nf_ip_net nf_ct_proto; #ifdef CONFIG_SYSCTL struct ctl_table_header *sysctl_header; struct ctl_table_header *acct_sysctl_header; struct ctl_table_header *tstamp_sysctl_header; struct ctl_table_header *event_sysctl_header; + struct ctl_table_header *helper_sysctl_header; #endif char *slabname; }; diff --git a/include/net/netns/hash.h b/include/net/netns/hash.h index 548d78f2cc47..c06ac58ca107 100644 --- a/include/net/netns/hash.h +++ b/include/net/netns/hash.h @@ -5,7 +5,7 @@ struct net; -static inline unsigned net_hash_mix(struct net *net) +static inline unsigned int net_hash_mix(struct net *net) { #ifdef CONFIG_NET_NS /* diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index bbd023a1c9b9..1474dd65c66f 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -7,10 +7,12 @@ #include <net/inet_frag.h> +struct tcpm_hash_bucket; struct ctl_table_header; struct ipv4_devconf; struct fib_rules_ops; struct hlist_head; +struct fib_table; struct sock; struct netns_ipv4 { @@ -24,13 +26,21 @@ struct netns_ipv4 { struct ipv4_devconf *devconf_dflt; #ifdef CONFIG_IP_MULTIPLE_TABLES struct fib_rules_ops *rules_ops; + bool fib_has_custom_rules; + struct fib_table *fib_local; + struct fib_table *fib_main; + struct fib_table *fib_default; +#endif +#ifdef CONFIG_IP_ROUTE_CLASSID + int fib_num_tclassid_users; #endif struct hlist_head *fib_table_hash; struct sock *fibnl; struct sock **icmp_sk; - struct sock *tcp_sock; - + struct inet_peer_base *peers; + struct tcpm_hash_bucket *tcp_metrics_hash; + unsigned int tcp_metrics_hash_log; struct netns_frags frags; #ifdef CONFIG_NETFILTER struct xt_table *iptable_filter; @@ -51,8 +61,6 @@ struct netns_ipv4 { int sysctl_icmp_ratelimit; int sysctl_icmp_ratemask; int sysctl_icmp_errors_use_inbound_ifaddr; - int sysctl_rt_cache_rebuild_count; - int current_rt_cache_rebuild_count; unsigned int sysctl_ping_group_range[2]; long sysctl_tcp_mem[3]; diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 81abfcb2eb4e..df0a5456a3fd 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h @@ -12,7 +12,9 @@ struct ctl_table_header; struct netns_sysctl_ipv6 { #ifdef CONFIG_SYSCTL - struct ctl_table_header *table; + struct ctl_table_header *hdr; + struct ctl_table_header *route_hdr; + struct ctl_table_header *icmp_hdr; struct ctl_table_header *frags_hdr; #endif int bindv6only; @@ -31,6 +33,7 @@ struct netns_ipv6 { struct netns_sysctl_ipv6 sysctl; struct ipv6_devconf *devconf_all; struct ipv6_devconf *devconf_dflt; + struct inet_peer_base *peers; struct netns_frags frags; #ifdef CONFIG_NETFILTER struct xt_table *ip6table_filter; diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h index d58fdec47597..2719dec6b5a8 100644 --- a/include/net/netprio_cgroup.h +++ b/include/net/netprio_cgroup.h @@ -35,7 +35,7 @@ struct cgroup_netprio_state { extern int net_prio_subsys_id; #endif -extern void sock_update_netprioidx(struct sock *sk); +extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task); #if IS_BUILTIN(CONFIG_NETPRIO_CGROUP) @@ -82,7 +82,7 @@ static inline u32 task_netprioidx(struct task_struct *p) #endif /* CONFIG_NETPRIO_CGROUP */ #else -#define sock_update_netprioidx(sk) +#define sock_update_netprioidx(sk, task) #endif #endif /* _NET_CLS_CGROUP_H */ diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h new file mode 100644 index 000000000000..f5169b04f082 --- /dev/null +++ b/include/net/nfc/hci.h @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2011 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __NET_HCI_H +#define __NET_HCI_H + +#include <linux/skbuff.h> + +#include <net/nfc/nfc.h> + +struct nfc_hci_dev; + +struct nfc_hci_ops { + int (*open) (struct nfc_hci_dev *hdev); + void (*close) (struct nfc_hci_dev *hdev); + int (*hci_ready) (struct nfc_hci_dev *hdev); + int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); + int (*start_poll) (struct nfc_hci_dev *hdev, + u32 im_protocols, u32 tm_protocols); + int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, + struct nfc_target *target); + int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, + struct nfc_target *target); + int (*data_exchange) (struct nfc_hci_dev *hdev, + struct nfc_target *target, + struct sk_buff *skb, struct sk_buff **res_skb); + int (*check_presence)(struct nfc_hci_dev *hdev, + struct nfc_target *target); +}; + +/* Pipes */ +#define NFC_HCI_INVALID_PIPE 0x80 +#define NFC_HCI_LINK_MGMT_PIPE 0x00 +#define NFC_HCI_ADMIN_PIPE 0x01 + +struct nfc_hci_gate { + u8 gate; + u8 pipe; +}; + +#define NFC_HCI_MAX_CUSTOM_GATES 50 +struct nfc_hci_init_data { + u8 gate_count; + struct nfc_hci_gate gates[NFC_HCI_MAX_CUSTOM_GATES]; + char session_id[9]; +}; + +typedef int (*xmit) (struct sk_buff *skb, void *cb_data); + +#define NFC_HCI_MAX_GATES 256 + +struct nfc_hci_dev { + struct nfc_dev *ndev; + + u32 max_data_link_payload; + + struct mutex msg_tx_mutex; + + struct list_head msg_tx_queue; + + struct workqueue_struct *msg_tx_wq; + struct work_struct msg_tx_work; + + struct timer_list cmd_timer; + struct hci_msg *cmd_pending_msg; + + struct sk_buff_head rx_hcp_frags; + + struct workqueue_struct *msg_rx_wq; + struct work_struct msg_rx_work; + + struct sk_buff_head msg_rx_queue; + + struct nfc_hci_ops *ops; + + struct nfc_hci_init_data init_data; + + void *clientdata; + + u8 gate2pipe[NFC_HCI_MAX_GATES]; + + u8 sw_romlib; + u8 sw_patch; + u8 sw_flashlib_major; + u8 sw_flashlib_minor; + + u8 hw_derivative; + u8 hw_version; + u8 hw_mpw; + u8 hw_software; + u8 hw_bsid; +}; + +/* hci device allocation */ +struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops, + struct nfc_hci_init_data *init_data, + u32 protocols, + int tx_headroom, + int tx_tailroom, + int max_link_payload); +void nfc_hci_free_device(struct nfc_hci_dev *hdev); + +int nfc_hci_register_device(struct nfc_hci_dev *hdev); +void nfc_hci_unregister_device(struct nfc_hci_dev *hdev); + +void nfc_hci_set_clientdata(struct nfc_hci_dev *hdev, void *clientdata); +void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev); + +void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err); + +/* Host IDs */ +#define NFC_HCI_HOST_CONTROLLER_ID 0x00 +#define NFC_HCI_TERMINAL_HOST_ID 0x01 +#define NFC_HCI_UICC_HOST_ID 0x02 + +/* Host Controller Gates and registry indexes */ +#define NFC_HCI_ADMIN_GATE 0x00 +#define NFC_HCI_ADMIN_SESSION_IDENTITY 0x01 +#define NFC_HCI_ADMIN_MAX_PIPE 0x02 +#define NFC_HCI_ADMIN_WHITELIST 0x03 +#define NFC_HCI_ADMIN_HOST_LIST 0x04 + +#define NFC_HCI_LOOPBACK_GATE 0x04 + +#define NFC_HCI_ID_MGMT_GATE 0x05 +#define NFC_HCI_ID_MGMT_VERSION_SW 0x01 +#define NFC_HCI_ID_MGMT_VERSION_HW 0x03 +#define NFC_HCI_ID_MGMT_VENDOR_NAME 0x04 +#define NFC_HCI_ID_MGMT_MODEL_ID 0x05 +#define NFC_HCI_ID_MGMT_HCI_VERSION 0x02 +#define NFC_HCI_ID_MGMT_GATES_LIST 0x06 + +#define NFC_HCI_LINK_MGMT_GATE 0x06 +#define NFC_HCI_LINK_MGMT_REC_ERROR 0x01 + +#define NFC_HCI_RF_READER_B_GATE 0x11 +#define NFC_HCI_RF_READER_B_PUPI 0x03 +#define NFC_HCI_RF_READER_B_APPLICATION_DATA 0x04 +#define NFC_HCI_RF_READER_B_AFI 0x02 +#define NFC_HCI_RF_READER_B_HIGHER_LAYER_RESPONSE 0x01 +#define NFC_HCI_RF_READER_B_HIGHER_LAYER_DATA 0x05 + +#define NFC_HCI_RF_READER_A_GATE 0x13 +#define NFC_HCI_RF_READER_A_UID 0x02 +#define NFC_HCI_RF_READER_A_ATQA 0x04 +#define NFC_HCI_RF_READER_A_APPLICATION_DATA 0x05 +#define NFC_HCI_RF_READER_A_SAK 0x03 +#define NFC_HCI_RF_READER_A_FWI_SFGT 0x06 +#define NFC_HCI_RF_READER_A_DATARATE_MAX 0x01 + +#define NFC_HCI_TYPE_A_SEL_PROT(x) (((x) & 0x60) >> 5) +#define NFC_HCI_TYPE_A_SEL_PROT_MIFARE 0 +#define NFC_HCI_TYPE_A_SEL_PROT_ISO14443 1 +#define NFC_HCI_TYPE_A_SEL_PROT_DEP 2 +#define NFC_HCI_TYPE_A_SEL_PROT_ISO14443_DEP 3 + +/* Generic events */ +#define NFC_HCI_EVT_HCI_END_OF_OPERATION 0x01 +#define NFC_HCI_EVT_POST_DATA 0x02 +#define NFC_HCI_EVT_HOT_PLUG 0x03 + +/* Reader RF gates events */ +#define NFC_HCI_EVT_READER_REQUESTED 0x10 +#define NFC_HCI_EVT_END_OPERATION 0x11 + +/* Reader Application gate events */ +#define NFC_HCI_EVT_TARGET_DISCOVERED 0x10 + +/* receiving messages from lower layer */ +void nfc_hci_resp_received(struct nfc_hci_dev *hdev, u8 result, + struct sk_buff *skb); +void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd, + struct sk_buff *skb); +void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, + struct sk_buff *skb); +void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb); + +/* connecting to gates and sending hci instructions */ +int nfc_hci_connect_gate(struct nfc_hci_dev *hdev, u8 dest_host, u8 dest_gate, + u8 pipe); +int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate); +int nfc_hci_disconnect_all_gates(struct nfc_hci_dev *hdev); +int nfc_hci_get_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, + struct sk_buff **skb); +int nfc_hci_set_param(struct nfc_hci_dev *hdev, u8 gate, u8 idx, + const u8 *param, size_t param_len); +int nfc_hci_send_cmd(struct nfc_hci_dev *hdev, u8 gate, u8 cmd, + const u8 *param, size_t param_len, struct sk_buff **skb); +int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, + const u8 *param, size_t param_len); +int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, + const u8 *param, size_t param_len); + +#endif /* __NET_HCI_H */ diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index bac070bf3514..6431f5e39022 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -48,20 +48,26 @@ struct nfc_dev; typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb, int err); +struct nfc_target; + struct nfc_ops { int (*dev_up)(struct nfc_dev *dev); int (*dev_down)(struct nfc_dev *dev); - int (*start_poll)(struct nfc_dev *dev, u32 protocols); + int (*start_poll)(struct nfc_dev *dev, + u32 im_protocols, u32 tm_protocols); void (*stop_poll)(struct nfc_dev *dev); - int (*dep_link_up)(struct nfc_dev *dev, int target_idx, u8 comm_mode, - u8 *gb, size_t gb_len); + int (*dep_link_up)(struct nfc_dev *dev, struct nfc_target *target, + u8 comm_mode, u8 *gb, size_t gb_len); int (*dep_link_down)(struct nfc_dev *dev); - int (*activate_target)(struct nfc_dev *dev, u32 target_idx, + int (*activate_target)(struct nfc_dev *dev, struct nfc_target *target, u32 protocol); - void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx); - int (*data_exchange)(struct nfc_dev *dev, u32 target_idx, + void (*deactivate_target)(struct nfc_dev *dev, + struct nfc_target *target); + int (*im_transceive)(struct nfc_dev *dev, struct nfc_target *target, struct sk_buff *skb, data_exchange_cb_t cb, void *cb_context); + int (*tm_send)(struct nfc_dev *dev, struct sk_buff *skb); + int (*check_presence)(struct nfc_dev *dev, struct nfc_target *target); }; #define NFC_TARGET_IDX_ANY -1 @@ -78,6 +84,8 @@ struct nfc_target { u8 sensb_res[NFC_SENSB_RES_MAXSIZE]; u8 sensf_res_len; u8 sensf_res[NFC_SENSF_RES_MAXSIZE]; + u8 hci_reader_gate; + u8 logical_idx; }; struct nfc_genl_data { @@ -86,23 +94,27 @@ struct nfc_genl_data { }; struct nfc_dev { - unsigned idx; + unsigned int idx; + u32 target_next_idx; struct nfc_target *targets; int n_targets; int targets_generation; - spinlock_t targets_lock; struct device dev; bool dev_up; + u8 rf_mode; bool polling; - bool remote_activated; + struct nfc_target *active_target; bool dep_link_up; - u32 dep_rf_mode; struct nfc_genl_data genl_data; u32 supported_protocols; int tx_headroom; int tx_tailroom; + struct timer_list check_pres_timer; + struct workqueue_struct *check_pres_wq; + struct work_struct check_pres_work; + struct nfc_ops *ops; }; #define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev) @@ -178,11 +190,20 @@ struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gt, u8 gt_len); +u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, size_t *gb_len); int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, int ntargets); +int nfc_target_lost(struct nfc_dev *dev, u32 target_idx); int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, u8 comm_mode, u8 rf_mode); +int nfc_tm_activated(struct nfc_dev *dev, u32 protocol, u8 comm_mode, + u8 *gb, size_t gb_len); +int nfc_tm_deactivated(struct nfc_dev *dev); +int nfc_tm_data_received(struct nfc_dev *dev, struct sk_buff *skb); + +void nfc_driver_failure(struct nfc_dev *dev, int err); + #endif /* __NET_NFC_H */ diff --git a/include/net/nfc/shdlc.h b/include/net/nfc/shdlc.h new file mode 100644 index 000000000000..35e930d2f638 --- /dev/null +++ b/include/net/nfc/shdlc.h @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the + * Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __NFC_SHDLC_H +#define __NFC_SHDLC_H + +struct nfc_shdlc; + +struct nfc_shdlc_ops { + int (*open) (struct nfc_shdlc *shdlc); + void (*close) (struct nfc_shdlc *shdlc); + int (*hci_ready) (struct nfc_shdlc *shdlc); + int (*xmit) (struct nfc_shdlc *shdlc, struct sk_buff *skb); + int (*start_poll) (struct nfc_shdlc *shdlc, + u32 im_protocols, u32 tm_protocols); + int (*target_from_gate) (struct nfc_shdlc *shdlc, u8 gate, + struct nfc_target *target); + int (*complete_target_discovered) (struct nfc_shdlc *shdlc, u8 gate, + struct nfc_target *target); + int (*data_exchange) (struct nfc_shdlc *shdlc, + struct nfc_target *target, + struct sk_buff *skb, struct sk_buff **res_skb); + int (*check_presence)(struct nfc_shdlc *shdlc, + struct nfc_target *target); +}; + +enum shdlc_state { + SHDLC_DISCONNECTED = 0, + SHDLC_CONNECTING = 1, + SHDLC_NEGOCIATING = 2, + SHDLC_CONNECTED = 3 +}; + +struct nfc_shdlc { + struct mutex state_mutex; + enum shdlc_state state; + int hard_fault; + + struct nfc_hci_dev *hdev; + + wait_queue_head_t *connect_wq; + int connect_tries; + int connect_result; + struct timer_list connect_timer;/* aka T3 in spec 10.6.1 */ + + u8 w; /* window size */ + bool srej_support; + + struct timer_list t1_timer; /* send ack timeout */ + bool t1_active; + + struct timer_list t2_timer; /* guard/retransmit timeout */ + bool t2_active; + + int ns; /* next seq num for send */ + int nr; /* next expected seq num for receive */ + int dnr; /* oldest sent unacked seq num */ + + struct sk_buff_head rcv_q; + + struct sk_buff_head send_q; + bool rnr; /* other side is not ready to receive */ + + struct sk_buff_head ack_pending_q; + + struct workqueue_struct *sm_wq; + struct work_struct sm_work; + + struct nfc_shdlc_ops *ops; + + int client_headroom; + int client_tailroom; + + void *clientdata; +}; + +void nfc_shdlc_recv_frame(struct nfc_shdlc *shdlc, struct sk_buff *skb); + +struct nfc_shdlc *nfc_shdlc_allocate(struct nfc_shdlc_ops *ops, + struct nfc_hci_init_data *init_data, + u32 protocols, + int tx_headroom, int tx_tailroom, + int max_link_payload, const char *devname); + +void nfc_shdlc_free(struct nfc_shdlc *shdlc); + +void nfc_shdlc_set_clientdata(struct nfc_shdlc *shdlc, void *clientdata); +void *nfc_shdlc_get_clientdata(struct nfc_shdlc *shdlc); +struct nfc_hci_dev *nfc_shdlc_get_hci_dev(struct nfc_shdlc *shdlc); + +#endif /* __NFC_SHDLC_H */ diff --git a/include/net/phonet/gprs.h b/include/net/phonet/gprs.h index 928daf595beb..bcd525e39a0b 100644 --- a/include/net/phonet/gprs.h +++ b/include/net/phonet/gprs.h @@ -5,7 +5,7 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Author: Rémi Denis-Courmont <remi.denis-courmont@nokia.com> + * Author: Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index fffdc603f4c8..66f5ac370f92 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -107,7 +107,7 @@ extern int tc_classify(struct sk_buff *skb, const struct tcf_proto *tp, /* Calculate maximal size of packet seen by hard_start_xmit routine of this device. */ -static inline unsigned psched_mtu(const struct net_device *dev) +static inline unsigned int psched_mtu(const struct net_device *dev) { return dev->mtu + dev->hard_header_len; } diff --git a/include/net/protocol.h b/include/net/protocol.h index 875f4895b033..929528c73fe8 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -29,11 +29,15 @@ #include <linux/ipv6.h> #endif -#define MAX_INET_PROTOS 256 /* Must be a power of 2 */ - +/* This is one larger than the largest protocol value that can be + * found in an ipv4 or ipv6 header. Since in both cases the protocol + * value is presented in a __u8, this is defined to be 256. + */ +#define MAX_INET_PROTOS 256 /* This is used to register protocols. */ struct net_protocol { + void (*early_demux)(struct sk_buff *skb); int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, u32 info); int (*gso_send_check)(struct sk_buff *skb); @@ -48,6 +52,8 @@ struct net_protocol { #if IS_ENABLED(CONFIG_IPV6) struct inet6_protocol { + void (*early_demux)(struct sk_buff *skb); + int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, diff --git a/include/net/rawv6.h b/include/net/rawv6.h index cf7577234457..e7ea660e4db6 100644 --- a/include/net/rawv6.h +++ b/include/net/rawv6.h @@ -5,7 +5,7 @@ void raw6_icmp_error(struct sk_buff *, int nexthdr, u8 type, u8 code, int inner_offset, __be32); -int raw6_local_deliver(struct sk_buff *, int); +bool raw6_local_deliver(struct sk_buff *, int); extern int rawv6_rcv(struct sock *sk, struct sk_buff *skb); diff --git a/include/net/regulatory.h b/include/net/regulatory.h index a5f79933e211..7dcaa2794fde 100644 --- a/include/net/regulatory.h +++ b/include/net/regulatory.h @@ -52,6 +52,10 @@ enum environment_cap { * DFS master operation on a known DFS region (NL80211_DFS_*), * dfs_region represents that region. Drivers can use this and the * @alpha2 to adjust their device's DFS parameters as required. + * @user_reg_hint_type: if the @initiator was of type + * %NL80211_REGDOM_SET_BY_USER, this classifies the type + * of hint passed. This could be any of the %NL80211_USER_REG_HINT_* + * types. * @intersect: indicates whether the wireless core should intersect * the requested regulatory domain with the presently set regulatory * domain. @@ -70,6 +74,7 @@ enum environment_cap { struct regulatory_request { int wiphy_idx; enum nl80211_reg_initiator initiator; + enum nl80211_user_reg_hint_type user_reg_hint_type; char alpha2[2]; u8 dfs_region; bool intersect; diff --git a/include/net/route.h b/include/net/route.h index b1c0d5b564c2..776a27f1ab78 100644 --- a/include/net/route.h +++ b/include/net/route.h @@ -30,6 +30,7 @@ #include <net/inet_sock.h> #include <linux/in_route.h> #include <linux/rtnetlink.h> +#include <linux/rcupdate.h> #include <linux/route.h> #include <linux/ip.h> #include <linux/cache.h> @@ -40,45 +41,41 @@ #define RT_CONN_FLAGS(sk) (RT_TOS(inet_sk(sk)->tos) | sock_flag(sk, SOCK_LOCALROUTE)) struct fib_nh; -struct inet_peer; struct fib_info; struct rtable { struct dst_entry dst; - /* Lookup key. */ - __be32 rt_key_dst; - __be32 rt_key_src; - int rt_genid; - unsigned rt_flags; + unsigned int rt_flags; __u16 rt_type; - __u8 rt_key_tos; + __u16 rt_is_input; - __be32 rt_dst; /* Path destination */ - __be32 rt_src; /* Path source */ - int rt_route_iif; int rt_iif; - int rt_oif; - __u32 rt_mark; /* Info on neighbour */ __be32 rt_gateway; /* Miscellaneous cached information */ - __be32 rt_spec_dst; /* RFC1122 specific destination */ - u32 rt_peer_genid; - struct inet_peer *peer; /* long-living peer info */ - struct fib_info *fi; /* for client ref to shared metrics */ + u32 rt_pmtu; + + struct list_head rt_uncached; }; static inline bool rt_is_input_route(const struct rtable *rt) { - return rt->rt_route_iif != 0; + return rt->rt_is_input != 0; } static inline bool rt_is_output_route(const struct rtable *rt) { - return rt->rt_route_iif == 0; + return rt->rt_is_input == 0; +} + +static inline __be32 rt_nexthop(const struct rtable *rt, __be32 daddr) +{ + if (rt->rt_gateway) + return rt->rt_gateway; + return daddr; } struct ip_rt_acct { @@ -111,10 +108,8 @@ extern struct ip_rt_acct __percpu *ip_rt_acct; struct in_device; extern int ip_rt_init(void); -extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, - __be32 src, struct net_device *dev); extern void rt_cache_flush(struct net *net, int how); -extern void rt_cache_flush_batch(struct net *net); +extern void rt_flush_dev(struct net_device *dev); extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp); extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp, struct sock *sk); @@ -130,9 +125,9 @@ static inline struct rtable *ip_route_output(struct net *net, __be32 daddr, { struct flowi4 fl4 = { .flowi4_oif = oif, + .flowi4_tos = tos, .daddr = daddr, .saddr = saddr, - .flowi4_tos = tos, }; return ip_route_output_key(net, &fl4); } @@ -166,27 +161,33 @@ static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4 return ip_route_output_key(net, fl4); } -extern int ip_route_input_common(struct sk_buff *skb, __be32 dst, __be32 src, - u8 tos, struct net_device *devin, bool noref); +extern int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, + u8 tos, struct net_device *devin); static inline int ip_route_input(struct sk_buff *skb, __be32 dst, __be32 src, u8 tos, struct net_device *devin) { - return ip_route_input_common(skb, dst, src, tos, devin, false); -} + int err; -static inline int ip_route_input_noref(struct sk_buff *skb, __be32 dst, __be32 src, - u8 tos, struct net_device *devin) -{ - return ip_route_input_common(skb, dst, src, tos, devin, true); + rcu_read_lock(); + err = ip_route_input_noref(skb, dst, src, tos, devin); + if (!err) + skb_dst_force(skb); + rcu_read_unlock(); + + return err; } -extern unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, - unsigned short new_mtu, struct net_device *dev); -extern void ip_rt_send_redirect(struct sk_buff *skb); +extern void ipv4_update_pmtu(struct sk_buff *skb, struct net *net, u32 mtu, + int oif, u32 mark, u8 protocol, int flow_flags); +extern void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu); +extern void ipv4_redirect(struct sk_buff *skb, struct net *net, + int oif, u32 mark, u8 protocol, int flow_flags); +extern void ipv4_sk_redirect(struct sk_buff *skb, struct sock *sk); +extern void ip_rt_send_redirect(struct sk_buff *skb); -extern unsigned inet_addr_type(struct net *net, __be32 addr); -extern unsigned inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr); +extern unsigned int inet_addr_type(struct net *net, __be32 addr); +extern unsigned int inet_dev_addr_type(struct net *net, const struct net_device *dev, __be32 addr); extern void ip_rt_multicast_event(struct in_device *); extern int ip_rt_ioctl(struct net *, unsigned int cmd, void __user *arg); extern void ip_rt_get_source(u8 *src, struct sk_buff *skb, struct rtable *rt); @@ -244,8 +245,6 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst, __be32 if (inet_sk(sk)->transparent) flow_flags |= FLOWI_FLAG_ANYSRC; - if (protocol == IPPROTO_TCP) - flow_flags |= FLOWI_FLAG_PRECOW_METRICS; if (can_sleep) flow_flags |= FLOWI_FLAG_CAN_SLEEP; @@ -294,20 +293,13 @@ static inline struct rtable *ip_route_newports(struct flowi4 *fl4, struct rtable return rt; } -extern void rt_bind_peer(struct rtable *rt, __be32 daddr, int create); - -static inline struct inet_peer *rt_get_peer(struct rtable *rt, __be32 daddr) -{ - if (rt->peer) - return rt->peer; - - rt_bind_peer(rt, daddr, 0); - return rt->peer; -} - static inline int inet_iif(const struct sk_buff *skb) { - return skb_rtable(skb)->rt_iif; + int iif = skb_rtable(skb)->rt_iif; + + if (iif) + return iif; + return skb->skb_iif; } extern int sysctl_ip_default_ttl; diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 370293901971..6b00c4fc4291 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -41,9 +41,13 @@ static inline int rtnl_msg_family(const struct nlmsghdr *nlh) * @get_size: Function to calculate required room for dumping device * specific netlink attributes * @fill_info: Function to dump device specific netlink attributes - * @get_xstats_size: Function to calculate required room for dumping devic + * @get_xstats_size: Function to calculate required room for dumping device * specific statistics * @fill_xstats: Function to dump device specific statistics + * @get_num_tx_queues: Function to determine number of transmit queues + * to create when creating a new device. + * @get_num_rx_queues: Function to determine number of receive queues + * to create when creating a new device. */ struct rtnl_link_ops { struct list_head list; @@ -75,9 +79,8 @@ struct rtnl_link_ops { size_t (*get_xstats_size)(const struct net_device *dev); int (*fill_xstats)(struct sk_buff *skb, const struct net_device *dev); - int (*get_tx_queues)(struct net *net, struct nlattr *tb[], - unsigned int *tx_queues, - unsigned int *real_tx_queues); + unsigned int (*get_num_tx_queues)(void); + unsigned int (*get_num_rx_queues)(void); }; extern int __rtnl_link_register(struct rtnl_link_ops *ops); @@ -94,7 +97,7 @@ extern void rtnl_link_unregister(struct rtnl_link_ops *ops); * @fill_link_af: Function to fill IFLA_AF_SPEC with address family * specific netlink attributes. * @get_link_af_size: Function to calculate size of address family specific - * netlink attributes exlusive the container attribute. + * netlink attributes. * @validate_link_af: Validate a IFLA_AF_SPEC attribute, must check attr * for invalid configuration settings. * @set_link_af: Function to parse a IFLA_AF_SPEC attribute and modify diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 55ce96b53b09..d9611e032418 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -220,13 +220,16 @@ struct tcf_proto { struct qdisc_skb_cb { unsigned int pkt_len; - unsigned char data[24]; + u16 slave_dev_queue_mapping; + u16 _pad; + unsigned char data[20]; }; static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) { struct qdisc_skb_cb *qcb; - BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz); + + BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz); BUILD_BUG_ON(sizeof(qcb->data) < sz); } diff --git a/include/net/scm.h b/include/net/scm.h index d456f4c71a32..079d7887dac1 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -13,7 +13,6 @@ #define SCM_MAX_FD 253 struct scm_fp_list { - struct list_head list; short count; short max; struct file *fp[SCM_MAX_FD]; diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h index 942b864f6135..d053d2e99876 100644 --- a/include/net/sctp/constants.h +++ b/include/net/sctp/constants.h @@ -334,6 +334,7 @@ typedef enum { typedef enum { SCTP_TRANSPORT_UP, SCTP_TRANSPORT_DOWN, + SCTP_TRANSPORT_PF, } sctp_transport_cmd_t; /* These are the address scopes defined mainly for IPv4 addresses diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index a2ef81466b00..ff499640528b 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -162,6 +162,8 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *, void sctp_err_finish(struct sock *, struct sctp_association *); void sctp_icmp_frag_needed(struct sock *, struct sctp_association *, struct sctp_transport *t, __u32 pmtu); +void sctp_icmp_redirect(struct sock *, struct sctp_transport *, + struct sk_buff *); void sctp_icmp_proto_unreachable(struct sock *sk, struct sctp_association *asoc, struct sctp_transport *t); @@ -517,10 +519,10 @@ static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu) return frag; } -static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc) +static inline void sctp_assoc_pending_pmtu(struct sock *sk, struct sctp_association *asoc) { - sctp_assoc_sync_pmtu(asoc); + sctp_assoc_sync_pmtu(sk, asoc); asoc->pmtu_pending = 0; } diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 88949a994538..fc5e60016e37 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -161,6 +161,12 @@ extern struct sctp_globals { int max_retrans_path; int max_retrans_init; + /* Potentially-Failed.Max.Retrans sysctl value + * taken from: + * http://tools.ietf.org/html/draft-nishida-tsvwg-sctp-failover-05 + */ + int pf_retrans; + /* * Policy for preforming sctp/socket accounting * 0 - do socket level accounting, all assocs share sk_sndbuf @@ -258,6 +264,7 @@ extern struct sctp_globals { #define sctp_sndbuf_policy (sctp_globals.sndbuf_policy) #define sctp_rcvbuf_policy (sctp_globals.rcvbuf_policy) #define sctp_max_retrans_path (sctp_globals.max_retrans_path) +#define sctp_pf_retrans (sctp_globals.pf_retrans) #define sctp_max_retrans_init (sctp_globals.max_retrans_init) #define sctp_sack_timeout (sctp_globals.sack_timeout) #define sctp_hb_interval (sctp_globals.hb_interval) @@ -912,6 +919,9 @@ struct sctp_transport { /* Is this structure kfree()able? */ malloced:1; + /* Has this transport moved the ctsn since we last sacked */ + __u32 sack_generation; + struct flowi fl; /* This is the peer's IP address and port. */ @@ -987,10 +997,15 @@ struct sctp_transport { /* This is the max_retrans value for the transport and will * be initialized from the assocs value. This can be changed - * using SCTP_SET_PEER_ADDR_PARAMS socket option. + * using the SCTP_SET_PEER_ADDR_PARAMS socket option. */ __u16 pathmaxrxt; + /* This is the partially failed retrans value for the transport + * and will be initialized from the assocs value. This can be changed + * using the SCTP_PEER_ADDR_THLDS socket option + */ + int pf_retrans; /* PMTU : The current known path MTU. */ __u32 pathmtu; @@ -1088,7 +1103,7 @@ void sctp_transport_burst_limited(struct sctp_transport *); void sctp_transport_burst_reset(struct sctp_transport *); unsigned long sctp_transport_timeout(struct sctp_transport *); void sctp_transport_reset(struct sctp_transport *); -void sctp_transport_update_pmtu(struct sctp_transport *, u32); +void sctp_transport_update_pmtu(struct sock *, struct sctp_transport *, u32); void sctp_transport_immediate_rtx(struct sctp_transport *); @@ -1145,10 +1160,10 @@ struct sctp_outq { /* Data pending that has never been transmitted. */ struct list_head out_chunk_list; - unsigned out_qlen; /* Total length of queued data chunks. */ + unsigned int out_qlen; /* Total length of queued data chunks. */ /* Error of send failed, may used in SCTP_SEND_FAILED event. */ - unsigned error; + unsigned int error; /* These are control chunks we want to send. */ struct list_head control_chunk_list; @@ -1584,6 +1599,7 @@ struct sctp_association { */ __u8 sack_needed; /* Do we need to sack the peer? */ __u32 sack_cnt; + __u32 sack_generation; /* These are capabilities which our peer advertised. */ __u8 ecn_capable:1, /* Can peer do ECN? */ @@ -1660,6 +1676,12 @@ struct sctp_association { */ int max_retrans; + /* This is the partially failed retrans value for the transport + * and will be initialized from the assocs value. This can be + * changed using the SCTP_PEER_ADDR_THLDS socket option + */ + int pf_retrans; + /* Maximum number of times the endpoint will retransmit INIT */ __u16 max_init_attempts; @@ -1999,9 +2021,9 @@ void sctp_assoc_update(struct sctp_association *old, __u32 sctp_association_get_next_tsn(struct sctp_association *); -void sctp_assoc_sync_pmtu(struct sctp_association *); -void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned); -void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned); +void sctp_assoc_sync_pmtu(struct sock *, struct sctp_association *); +void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int); +void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int); void sctp_assoc_set_primary(struct sctp_association *, struct sctp_transport *); void sctp_assoc_del_nonprimary_peers(struct sctp_association *, diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h index e7728bc14ccf..2c5d2b4d5d1e 100644 --- a/include/net/sctp/tsnmap.h +++ b/include/net/sctp/tsnmap.h @@ -117,7 +117,8 @@ void sctp_tsnmap_free(struct sctp_tsnmap *map); int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn); /* Mark this TSN as seen. */ -int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn); +int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn, + struct sctp_transport *trans); /* Mark this TSN and all lower as seen. */ void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn); diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h index 0842ef00b2fe..1b02d7ad453b 100644 --- a/include/net/sctp/user.h +++ b/include/net/sctp/user.h @@ -93,6 +93,7 @@ typedef __s32 sctp_assoc_t; #define SCTP_GET_ASSOC_NUMBER 28 /* Read only */ #define SCTP_GET_ASSOC_ID_LIST 29 /* Read only */ #define SCTP_AUTO_ASCONF 30 +#define SCTP_PEER_ADDR_THLDS 31 /* Internal Socket Options. Some of the sctp library functions are * implemented using these socket options. @@ -649,6 +650,7 @@ struct sctp_paddrinfo { */ enum sctp_spinfo_state { SCTP_INACTIVE, + SCTP_PF, SCTP_ACTIVE, SCTP_UNCONFIRMED, SCTP_UNKNOWN = 0xffff /* Value used for transport state unknown */ @@ -741,4 +743,13 @@ typedef struct { int sd; } sctp_peeloff_arg_t; +/* + * Peer Address Thresholds socket option + */ +struct sctp_paddrthlds { + sctp_assoc_t spt_assoc_id; + struct sockaddr_storage spt_address; + __u16 spt_pathmaxrxt; + __u16 spt_pathpfthld; +}; #endif /* __net_sctp_user_h__ */ diff --git a/include/net/sock.h b/include/net/sock.h index 5a0a58ac4126..b3730239bf18 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -46,6 +46,7 @@ #include <linux/list_nulls.h> #include <linux/timer.h> #include <linux/cache.h> +#include <linux/bitops.h> #include <linux/lockdep.h> #include <linux/netdevice.h> #include <linux/skbuff.h> /* struct sk_buff */ @@ -70,16 +71,16 @@ struct cgroup; struct cgroup_subsys; #ifdef CONFIG_NET -int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss); -void mem_cgroup_sockets_destroy(struct cgroup *cgrp); +int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss); +void mem_cgroup_sockets_destroy(struct mem_cgroup *memcg); #else static inline -int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss) +int mem_cgroup_sockets_init(struct mem_cgroup *memcg, struct cgroup_subsys *ss) { return 0; } static inline -void mem_cgroup_sockets_destroy(struct cgroup *cgrp) +void mem_cgroup_sockets_destroy(struct mem_cgroup *memcg) { } #endif @@ -97,7 +98,7 @@ void mem_cgroup_sockets_destroy(struct cgroup *cgrp) #else /* Validate arguments and do nothing */ static inline __printf(2, 3) -void SOCK_DEBUG(struct sock *sk, const char *msg, ...) +void SOCK_DEBUG(const struct sock *sk, const char *msg, ...) { } #endif @@ -197,6 +198,7 @@ struct cg_proto; * @sk_lock: synchronizer * @sk_rcvbuf: size of receive buffer in bytes * @sk_wq: sock wait queue and async head + * @sk_rx_dst: receive input route used by early tcp demux * @sk_dst_cache: destination cache * @sk_dst_lock: destination cache lock * @sk_policy: flow policy @@ -316,6 +318,7 @@ struct sock { struct xfrm_policy *sk_policy[2]; #endif unsigned long sk_flags; + struct dst_entry *sk_rx_dst; struct dst_entry *sk_dst_cache; spinlock_t sk_dst_lock; atomic_t sk_wmem_alloc; @@ -372,11 +375,22 @@ struct sock { void (*sk_data_ready)(struct sock *sk, int bytes); void (*sk_write_space)(struct sock *sk); void (*sk_error_report)(struct sock *sk); - int (*sk_backlog_rcv)(struct sock *sk, - struct sk_buff *skb); + int (*sk_backlog_rcv)(struct sock *sk, + struct sk_buff *skb); void (*sk_destruct)(struct sock *sk); }; +/* + * SK_CAN_REUSE and SK_NO_REUSE on a socket mean that the socket is OK + * or not whether his port will be reused by someone else. SK_FORCE_REUSE + * on a socket means that the socket will reuse everybody else's port + * without looking at the other's sk_reuse value. + */ + +#define SK_NO_REUSE 0 +#define SK_CAN_REUSE 1 +#define SK_FORCE_REUSE 2 + static inline int sk_peek_offset(struct sock *sk, int flags) { if ((flags & MSG_PEEK) && (sk->sk_peek_off >= 0)) @@ -443,40 +457,40 @@ static inline struct sock *sk_nulls_next(const struct sock *sk) NULL; } -static inline int sk_unhashed(const struct sock *sk) +static inline bool sk_unhashed(const struct sock *sk) { return hlist_unhashed(&sk->sk_node); } -static inline int sk_hashed(const struct sock *sk) +static inline bool sk_hashed(const struct sock *sk) { return !sk_unhashed(sk); } -static __inline__ void sk_node_init(struct hlist_node *node) +static inline void sk_node_init(struct hlist_node *node) { node->pprev = NULL; } -static __inline__ void sk_nulls_node_init(struct hlist_nulls_node *node) +static inline void sk_nulls_node_init(struct hlist_nulls_node *node) { node->pprev = NULL; } -static __inline__ void __sk_del_node(struct sock *sk) +static inline void __sk_del_node(struct sock *sk) { __hlist_del(&sk->sk_node); } /* NB: equivalent to hlist_del_init_rcu */ -static __inline__ int __sk_del_node_init(struct sock *sk) +static inline bool __sk_del_node_init(struct sock *sk) { if (sk_hashed(sk)) { __sk_del_node(sk); sk_node_init(&sk->sk_node); - return 1; + return true; } - return 0; + return false; } /* Grab socket reference count. This operation is valid only @@ -498,9 +512,9 @@ static inline void __sock_put(struct sock *sk) atomic_dec(&sk->sk_refcnt); } -static __inline__ int sk_del_node_init(struct sock *sk) +static inline bool sk_del_node_init(struct sock *sk) { - int rc = __sk_del_node_init(sk); + bool rc = __sk_del_node_init(sk); if (rc) { /* paranoid for a while -acme */ @@ -511,18 +525,18 @@ static __inline__ int sk_del_node_init(struct sock *sk) } #define sk_del_node_init_rcu(sk) sk_del_node_init(sk) -static __inline__ int __sk_nulls_del_node_init_rcu(struct sock *sk) +static inline bool __sk_nulls_del_node_init_rcu(struct sock *sk) { if (sk_hashed(sk)) { hlist_nulls_del_init_rcu(&sk->sk_nulls_node); - return 1; + return true; } - return 0; + return false; } -static __inline__ int sk_nulls_del_node_init_rcu(struct sock *sk) +static inline bool sk_nulls_del_node_init_rcu(struct sock *sk) { - int rc = __sk_nulls_del_node_init_rcu(sk); + bool rc = __sk_nulls_del_node_init_rcu(sk); if (rc) { /* paranoid for a while -acme */ @@ -532,40 +546,40 @@ static __inline__ int sk_nulls_del_node_init_rcu(struct sock *sk) return rc; } -static __inline__ void __sk_add_node(struct sock *sk, struct hlist_head *list) +static inline void __sk_add_node(struct sock *sk, struct hlist_head *list) { hlist_add_head(&sk->sk_node, list); } -static __inline__ void sk_add_node(struct sock *sk, struct hlist_head *list) +static inline void sk_add_node(struct sock *sk, struct hlist_head *list) { sock_hold(sk); __sk_add_node(sk, list); } -static __inline__ void sk_add_node_rcu(struct sock *sk, struct hlist_head *list) +static inline void sk_add_node_rcu(struct sock *sk, struct hlist_head *list) { sock_hold(sk); hlist_add_head_rcu(&sk->sk_node, list); } -static __inline__ void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) +static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) { hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list); } -static __inline__ void sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) +static inline void sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list) { sock_hold(sk); __sk_nulls_add_node_rcu(sk, list); } -static __inline__ void __sk_del_bind_node(struct sock *sk) +static inline void __sk_del_bind_node(struct sock *sk) { __hlist_del(&sk->sk_bind_node); } -static __inline__ void sk_add_bind_node(struct sock *sk, +static inline void sk_add_bind_node(struct sock *sk, struct hlist_head *list) { hlist_add_head(&sk->sk_bind_node, list); @@ -607,6 +621,7 @@ enum sock_flags { SOCK_RCVTSTAMPNS, /* %SO_TIMESTAMPNS setting */ SOCK_LOCALROUTE, /* route locally only, %SO_DONTROUTE setting */ SOCK_QUEUE_SHRUNK, /* write queue has been shrunk recently */ + SOCK_MEMALLOC, /* VM depends on this socket for swapping */ SOCK_TIMESTAMPING_TX_HARDWARE, /* %SOF_TIMESTAMPING_TX_HARDWARE */ SOCK_TIMESTAMPING_TX_SOFTWARE, /* %SOF_TIMESTAMPING_TX_SOFTWARE */ SOCK_TIMESTAMPING_RX_HARDWARE, /* %SOF_TIMESTAMPING_RX_HARDWARE */ @@ -639,11 +654,31 @@ static inline void sock_reset_flag(struct sock *sk, enum sock_flags flag) __clear_bit(flag, &sk->sk_flags); } -static inline int sock_flag(struct sock *sk, enum sock_flags flag) +static inline bool sock_flag(const struct sock *sk, enum sock_flags flag) { return test_bit(flag, &sk->sk_flags); } +#ifdef CONFIG_NET +extern struct static_key memalloc_socks; +static inline int sk_memalloc_socks(void) +{ + return static_key_false(&memalloc_socks); +} +#else + +static inline int sk_memalloc_socks(void) +{ + return 0; +} + +#endif + +static inline gfp_t sk_gfp_atomic(struct sock *sk, gfp_t gfp_mask) +{ + return GFP_ATOMIC | (sk->sk_allocation & __GFP_MEMALLOC); +} + static inline void sk_acceptq_removed(struct sock *sk) { sk->sk_ack_backlog--; @@ -654,7 +689,7 @@ static inline void sk_acceptq_added(struct sock *sk) sk->sk_ack_backlog++; } -static inline int sk_acceptq_is_full(struct sock *sk) +static inline bool sk_acceptq_is_full(const struct sock *sk) { return sk->sk_ack_backlog > sk->sk_max_ack_backlog; } @@ -662,19 +697,19 @@ static inline int sk_acceptq_is_full(struct sock *sk) /* * Compute minimal free write space needed to queue new packets. */ -static inline int sk_stream_min_wspace(struct sock *sk) +static inline int sk_stream_min_wspace(const struct sock *sk) { return sk->sk_wmem_queued >> 1; } -static inline int sk_stream_wspace(struct sock *sk) +static inline int sk_stream_wspace(const struct sock *sk) { return sk->sk_sndbuf - sk->sk_wmem_queued; } extern void sk_stream_write_space(struct sock *sk); -static inline int sk_stream_memory_free(struct sock *sk) +static inline bool sk_stream_memory_free(const struct sock *sk) { return sk->sk_wmem_queued < sk->sk_sndbuf; } @@ -699,17 +734,19 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) * Do not take into account this skb truesize, * to allow even a single big packet to come. */ -static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb) +static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb, + unsigned int limit) { unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc); - return qsize > sk->sk_rcvbuf; + return qsize > limit; } /* The per-socket spinlock must be held here. */ -static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb) +static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *skb, + unsigned int limit) { - if (sk_rcvqueues_full(sk, skb)) + if (sk_rcvqueues_full(sk, skb, limit)) return -ENOBUFS; __sk_add_backlog(sk, skb); @@ -717,8 +754,13 @@ static inline __must_check int sk_add_backlog(struct sock *sk, struct sk_buff *s return 0; } +extern int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb); + static inline int sk_backlog_rcv(struct sock *sk, struct sk_buff *skb) { + if (sk_memalloc_socks() && skb_pfmemalloc(skb)) + return __sk_backlog_rcv(sk, skb); + return sk->sk_backlog_rcv(sk, skb); } @@ -782,6 +824,8 @@ extern int sk_stream_wait_memory(struct sock *sk, long *timeo_p); extern void sk_stream_wait_close(struct sock *sk, long timeo_p); extern int sk_stream_error(struct sock *sk, int flags, int err); extern void sk_stream_kill_queues(struct sock *sk); +extern void sk_set_memalloc(struct sock *sk); +extern void sk_clear_memalloc(struct sock *sk); extern int sk_wait_data(struct sock *sk, long *timeo); @@ -796,26 +840,26 @@ struct module; * transport -> network interface is defined by struct inet_proto */ struct proto { - void (*close)(struct sock *sk, + void (*close)(struct sock *sk, long timeout); int (*connect)(struct sock *sk, - struct sockaddr *uaddr, + struct sockaddr *uaddr, int addr_len); int (*disconnect)(struct sock *sk, int flags); - struct sock * (*accept) (struct sock *sk, int flags, int *err); + struct sock * (*accept)(struct sock *sk, int flags, int *err); int (*ioctl)(struct sock *sk, int cmd, unsigned long arg); int (*init)(struct sock *sk); void (*destroy)(struct sock *sk); void (*shutdown)(struct sock *sk, int how); - int (*setsockopt)(struct sock *sk, int level, + int (*setsockopt)(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); - int (*getsockopt)(struct sock *sk, int level, - int optname, char __user *optval, - int __user *option); + int (*getsockopt)(struct sock *sk, int level, + int optname, char __user *optval, + int __user *option); #ifdef CONFIG_COMPAT int (*compat_setsockopt)(struct sock *sk, int level, @@ -832,16 +876,19 @@ struct proto { struct msghdr *msg, size_t len); int (*recvmsg)(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int noblock, int flags, - int *addr_len); + size_t len, int noblock, int flags, + int *addr_len); int (*sendpage)(struct sock *sk, struct page *page, int offset, size_t size, int flags); - int (*bind)(struct sock *sk, + int (*bind)(struct sock *sk, struct sockaddr *uaddr, int addr_len); - int (*backlog_rcv) (struct sock *sk, + int (*backlog_rcv) (struct sock *sk, struct sk_buff *skb); + void (*release_cb)(struct sock *sk); + void (*mtu_reduced)(struct sock *sk); + /* Keeping track of sk's, looking them up, and port selection methods. */ void (*hash)(struct sock *sk); void (*unhash)(struct sock *sk); @@ -894,26 +941,37 @@ struct proto { #ifdef SOCK_REFCNT_DEBUG atomic_t socks; #endif -#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +#ifdef CONFIG_MEMCG_KMEM /* * cgroup specific init/deinit functions. Called once for all * protocols that implement it, from cgroups populate function. * This function has to setup any files the protocol want to * appear in the kmem cgroup filesystem. */ - int (*init_cgroup)(struct cgroup *cgrp, + int (*init_cgroup)(struct mem_cgroup *memcg, struct cgroup_subsys *ss); - void (*destroy_cgroup)(struct cgroup *cgrp); + void (*destroy_cgroup)(struct mem_cgroup *memcg); struct cg_proto *(*proto_cgroup)(struct mem_cgroup *memcg); #endif }; +/* + * Bits in struct cg_proto.flags + */ +enum cg_proto_flags { + /* Currently active and new sockets should be assigned to cgroups */ + MEMCG_SOCK_ACTIVE, + /* It was ever activated; we must disarm static keys on destruction */ + MEMCG_SOCK_ACTIVATED, +}; + struct cg_proto { void (*enter_memory_pressure)(struct sock *sk); struct res_counter *memory_allocated; /* Current allocated memory. */ struct percpu_counter *sockets_allocated; /* Current number of sockets. */ int *memory_pressure; long *sysctl_mem; + unsigned long flags; /* * memcg field is used to find which memcg we belong directly * Each memcg struct can hold more than one cg_proto, so container_of @@ -929,6 +987,16 @@ struct cg_proto { extern int proto_register(struct proto *prot, int alloc_slab); extern void proto_unregister(struct proto *prot); +static inline bool memcg_proto_active(struct cg_proto *cg_proto) +{ + return test_bit(MEMCG_SOCK_ACTIVE, &cg_proto->flags); +} + +static inline bool memcg_proto_activated(struct cg_proto *cg_proto) +{ + return test_bit(MEMCG_SOCK_ACTIVATED, &cg_proto->flags); +} + #ifdef SOCK_REFCNT_DEBUG static inline void sk_refcnt_debug_inc(struct sock *sk) { @@ -954,7 +1022,7 @@ inline void sk_refcnt_debug_release(const struct sock *sk) #define sk_refcnt_debug_release(sk) do { } while (0) #endif /* SOCK_REFCNT_DEBUG */ -#if defined(CONFIG_CGROUP_MEM_RES_CTLR_KMEM) && defined(CONFIG_NET) +#if defined(CONFIG_MEMCG_KMEM) && defined(CONFIG_NET) extern struct static_key memcg_socket_limit_enabled; static inline struct cg_proto *parent_cg_proto(struct proto *proto, struct cg_proto *cg_proto) @@ -1160,7 +1228,7 @@ proto_memory_pressure(struct proto *prot) extern void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc); extern int sock_prot_inuse_get(struct net *net, struct proto *proto); #else -static void inline sock_prot_inuse_add(struct net *net, struct proto *prot, +static inline void sock_prot_inuse_add(struct net *net, struct proto *prot, int inc) { } @@ -1247,26 +1315,28 @@ static inline int sk_mem_pages(int amt) return (amt + SK_MEM_QUANTUM - 1) >> SK_MEM_QUANTUM_SHIFT; } -static inline int sk_has_account(struct sock *sk) +static inline bool sk_has_account(struct sock *sk) { /* return true if protocol supports memory accounting */ return !!sk->sk_prot->memory_allocated; } -static inline int sk_wmem_schedule(struct sock *sk, int size) +static inline bool sk_wmem_schedule(struct sock *sk, int size) { if (!sk_has_account(sk)) - return 1; + return true; return size <= sk->sk_forward_alloc || __sk_mem_schedule(sk, size, SK_MEM_SEND); } -static inline int sk_rmem_schedule(struct sock *sk, int size) +static inline bool +sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, unsigned int size) { if (!sk_has_account(sk)) - return 1; - return size <= sk->sk_forward_alloc || - __sk_mem_schedule(sk, size, SK_MEM_RECV); + return true; + return size<= sk->sk_forward_alloc || + __sk_mem_schedule(sk, size, SK_MEM_RECV) || + skb_pfmemalloc(skb); } static inline void sk_mem_reclaim(struct sock *sk) @@ -1329,7 +1399,7 @@ static inline void sk_wmem_free_skb(struct sock *sk, struct sk_buff *skb) * Mark both the sk_lock and the sk_lock.slock as a * per-address-family lock class. */ -#define sock_lock_init_class_and_name(sk, sname, skey, name, key) \ +#define sock_lock_init_class_and_name(sk, sname, skey, name, key) \ do { \ sk->sk_lock.owned = 0; \ init_waitqueue_head(&sk->sk_lock.wq); \ @@ -1337,7 +1407,7 @@ do { \ debug_check_no_locks_freed((void *)&(sk)->sk_lock, \ sizeof((sk)->sk_lock)); \ lockdep_set_class_and_name(&(sk)->sk_lock.slock, \ - (skey), (sname)); \ + (skey), (sname)); \ lockdep_init_map(&(sk)->sk_lock.dep_map, (name), (key), 0); \ } while (0) @@ -1391,19 +1461,20 @@ extern struct sk_buff *sock_rmalloc(struct sock *sk, gfp_t priority); extern void sock_wfree(struct sk_buff *skb); extern void sock_rfree(struct sk_buff *skb); +extern void sock_edemux(struct sk_buff *skb); extern int sock_setsockopt(struct socket *sock, int level, int op, char __user *optval, unsigned int optlen); extern int sock_getsockopt(struct socket *sock, int level, - int op, char __user *optval, + int op, char __user *optval, int __user *optlen); -extern struct sk_buff *sock_alloc_send_skb(struct sock *sk, +extern struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, int noblock, int *errcode); -extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk, +extern struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, unsigned long data_len, int noblock, @@ -1425,7 +1496,7 @@ static inline void sock_update_classid(struct sock *sk) * Functions to fill in entries in struct proto_ops when a protocol * does not implement a particular function. */ -extern int sock_no_bind(struct socket *, +extern int sock_no_bind(struct socket *, struct sockaddr *, int); extern int sock_no_connect(struct socket *, struct sockaddr *, int, int); @@ -1454,7 +1525,7 @@ extern int sock_no_mmap(struct file *file, struct vm_area_struct *vma); extern ssize_t sock_no_sendpage(struct socket *sock, struct page *page, - int offset, size_t size, + int offset, size_t size, int flags); /* @@ -1477,7 +1548,7 @@ extern void sk_common_release(struct sock *sk); /* * Default socket callbacks and setup code */ - + /* Initialise core socket variables */ extern void sock_init_data(struct socket *sock, struct sock *sk); @@ -1677,7 +1748,7 @@ extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); -static inline int sk_can_gso(const struct sock *sk) +static inline bool sk_can_gso(const struct sock *sk) { return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); } @@ -1794,7 +1865,7 @@ static inline int sk_rmem_alloc_get(const struct sock *sk) * * Returns true if socket has write or read allocations */ -static inline int sk_has_allocations(const struct sock *sk) +static inline bool sk_has_allocations(const struct sock *sk) { return sk_wmem_alloc_get(sk) || sk_rmem_alloc_get(sk); } @@ -1833,9 +1904,7 @@ static inline int sk_has_allocations(const struct sock *sk) */ static inline bool wq_has_sleeper(struct socket_wq *wq) { - - /* - * We need to be sure we are in sync with the + /* We need to be sure we are in sync with the * add_wait_queue modifications to the wait queue. * * This memory barrier is paired in the sock_poll_wait. @@ -1857,22 +1926,21 @@ static inline void sock_poll_wait(struct file *filp, { if (!poll_does_not_wait(p) && wait_address) { poll_wait(filp, wait_address, p); - /* - * We need to be sure we are in sync with the + /* We need to be sure we are in sync with the * socket flags modification. * * This memory barrier is paired in the wq_has_sleeper. - */ + */ smp_mb(); } } /* - * Queue a received datagram if it will fit. Stream and sequenced + * Queue a received datagram if it will fit. Stream and sequenced * protocols can't normally use this as they need to fit buffers in * and play with them. * - * Inlined as it's very short and called for pretty much every + * Inlined as it's very short and called for pretty much every * packet ever received. */ @@ -1898,10 +1966,10 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) sk_mem_charge(sk, skb->truesize); } -extern void sk_reset_timer(struct sock *sk, struct timer_list* timer, +extern void sk_reset_timer(struct sock *sk, struct timer_list *timer, unsigned long expires); -extern void sk_stop_timer(struct sock *sk, struct timer_list* timer); +extern void sk_stop_timer(struct sock *sk, struct timer_list *timer); extern int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); @@ -1910,7 +1978,7 @@ extern int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb); /* * Recover an error report and clear atomically */ - + static inline int sock_error(struct sock *sk) { int err; @@ -1926,7 +1994,7 @@ static inline unsigned long sock_wspace(struct sock *sk) if (!(sk->sk_shutdown & SEND_SHUTDOWN)) { amt = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc); - if (amt < 0) + if (amt < 0) amt = 0; } return amt; @@ -1970,7 +2038,7 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk) /* * Default write policy as shown to user space via poll/select/SIGIO */ -static inline int sock_writeable(const struct sock *sk) +static inline bool sock_writeable(const struct sock *sk) { return atomic_read(&sk->sk_wmem_alloc) < (sk->sk_sndbuf >> 1); } @@ -1980,12 +2048,12 @@ static inline gfp_t gfp_any(void) return in_softirq() ? GFP_ATOMIC : GFP_KERNEL; } -static inline long sock_rcvtimeo(const struct sock *sk, int noblock) +static inline long sock_rcvtimeo(const struct sock *sk, bool noblock) { return noblock ? 0 : sk->sk_rcvtimeo; } -static inline long sock_sndtimeo(const struct sock *sk, int noblock) +static inline long sock_sndtimeo(const struct sock *sk, bool noblock) { return noblock ? 0 : sk->sk_sndtimeo; } @@ -2008,7 +2076,7 @@ extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk, struct sk_buff *skb); -static __inline__ void +static inline void sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) { ktime_t kt = skb->tstamp; @@ -2049,7 +2117,7 @@ static inline void sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, (1UL << SOCK_RCVTSTAMP) | \ (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE) | \ (1UL << SOCK_TIMESTAMPING_SOFTWARE) | \ - (1UL << SOCK_TIMESTAMPING_RAW_HARDWARE) | \ + (1UL << SOCK_TIMESTAMPING_RAW_HARDWARE) | \ (1UL << SOCK_TIMESTAMPING_SYS_HARDWARE)) if (sk->sk_flags & FLAGS_TS_OR_DROPS) @@ -2078,7 +2146,7 @@ extern int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags); * locked so that the sk_buff queue operation is ok. */ #ifdef CONFIG_NET_DMA -static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early) +static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, bool copied_early) { __skb_unlink(skb, &sk->sk_receive_queue); if (!copied_early) @@ -2087,7 +2155,7 @@ static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_e __skb_queue_tail(&sk->sk_async_wait_queue, skb); } #else -static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, int copied_early) +static inline void sk_eat_skb(struct sock *sk, struct sk_buff *skb, bool copied_early) { __skb_unlink(skb, &sk->sk_receive_queue); __kfree_skb(skb); @@ -2120,7 +2188,7 @@ static inline void sk_change_net(struct sock *sk, struct net *net) static inline struct sock *skb_steal_sock(struct sk_buff *skb) { - if (unlikely(skb->sk)) { + if (skb->sk) { struct sock *sk = skb->sk; skb->destructor = NULL; @@ -2134,8 +2202,8 @@ extern void sock_enable_timestamp(struct sock *sk, int flag); extern int sock_get_timestamp(struct sock *, struct timeval __user *); extern int sock_get_timestampns(struct sock *, struct timespec __user *); -/* - * Enable debug/info messages +/* + * Enable debug/info messages */ extern int net_msg_warn; #define NETDEBUG(fmt, args...) \ diff --git a/include/net/tcp.h b/include/net/tcp.h index f75a04d752cb..e19124b84cd2 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -123,7 +123,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #endif #define TCP_RTO_MAX ((unsigned)(120*HZ)) #define TCP_RTO_MIN ((unsigned)(HZ/5)) -#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC2988bis initial RTO value */ +#define TCP_TIMEOUT_INIT ((unsigned)(1*HZ)) /* RFC6298 2.1 initial RTO value */ #define TCP_TIMEOUT_FALLBACK ((unsigned)(3*HZ)) /* RFC 1122 initial RTO value, now * used as a fallback RTO for the * initial data transmission if no @@ -170,6 +170,11 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ #define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ #define TCPOPT_COOKIE 253 /* Cookie extension (experimental) */ +#define TCPOPT_EXP 254 /* Experimental */ +/* Magic number to be after the option value for sharing TCP + * experimental options. See draft-ietf-tcpm-experimental-options-00.txt + */ +#define TCPOPT_FASTOPEN_MAGIC 0xF989 /* * TCP option lengths @@ -180,6 +185,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); #define TCPOLEN_SACK_PERM 2 #define TCPOLEN_TIMESTAMP 10 #define TCPOLEN_MD5SIG 18 +#define TCPOLEN_EXP_FASTOPEN_BASE 4 #define TCPOLEN_COOKIE_BASE 2 /* Cookie-less header extension */ #define TCPOLEN_COOKIE_PAIR 3 /* Cookie pair header extension */ #define TCPOLEN_COOKIE_MIN (TCPOLEN_COOKIE_BASE+TCP_COOKIE_MIN) @@ -206,6 +212,10 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo); /* TCP initial congestion window as per draft-hkchu-tcpm-initcwnd-01 */ #define TCP_INIT_CWND 10 +/* Bit Flags for sysctl_tcp_fastopen */ +#define TFO_CLIENT_ENABLE 1 +#define TFO_CLIENT_NO_COOKIE 4 /* Data in SYN w/o cookie option */ + extern struct inet_timewait_death_row tcp_death_row; /* sysctl variables for tcp */ @@ -222,6 +232,7 @@ extern int sysctl_tcp_retries1; extern int sysctl_tcp_retries2; extern int sysctl_tcp_orphan_retries; extern int sysctl_tcp_syncookies; +extern int sysctl_tcp_fastopen; extern int sysctl_tcp_retrans_collapse; extern int sysctl_tcp_stdurg; extern int sysctl_tcp_rfc1337; @@ -252,6 +263,9 @@ extern int sysctl_tcp_max_ssthresh; extern int sysctl_tcp_cookie_size; extern int sysctl_tcp_thin_linear_timeouts; extern int sysctl_tcp_thin_dupack; +extern int sysctl_tcp_early_retrans; +extern int sysctl_tcp_limit_output_bytes; +extern int sysctl_tcp_challenge_ack_limit; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; @@ -262,14 +276,14 @@ extern int tcp_memory_pressure; * and worry about wraparound (automatic with unsigned arithmetic). */ -static inline int before(__u32 seq1, __u32 seq2) +static inline bool before(__u32 seq1, __u32 seq2) { return (__s32)(seq1-seq2) < 0; } #define after(seq2, seq1) before(seq1, seq2) /* is s2<=s1<=s3 ? */ -static inline int between(__u32 seq1, __u32 seq2, __u32 seq3) +static inline bool between(__u32 seq1, __u32 seq2, __u32 seq3) { return seq3 - seq2 >= seq1 - seq2; } @@ -304,7 +318,7 @@ static inline void tcp_synq_overflow(struct sock *sk) } /* syncookies: no recent synqueue overflow on this listening socket? */ -static inline int tcp_synq_no_recent_overflow(const struct sock *sk) +static inline bool tcp_synq_no_recent_overflow(const struct sock *sk) { unsigned long last_overflow = tcp_sk(sk)->rx_opt.ts_recent_stamp; return time_after(jiffies, last_overflow + TCP_TIMEOUT_FALLBACK); @@ -320,19 +334,24 @@ extern struct proto tcp_prot; extern void tcp_init_mem(struct net *net); +extern void tcp_tasklet_init(void); + extern void tcp_v4_err(struct sk_buff *skb, u32); extern void tcp_shutdown (struct sock *sk, int how); +extern void tcp_v4_early_demux(struct sk_buff *skb); extern int tcp_v4_rcv(struct sk_buff *skb); -extern struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it); -extern void *tcp_v4_tw_get_peer(struct sock *sk); +extern struct inet_peer *tcp_v4_get_peer(struct sock *sk); extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw); extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t size); extern int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags); +extern void tcp_release_cb(struct sock *sk); +extern void tcp_write_timer_handler(struct sock *sk); +extern void tcp_delack_timer_handler(struct sock *sk); extern int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg); extern int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th, unsigned int len); @@ -366,13 +385,6 @@ static inline void tcp_dec_quickack_mode(struct sock *sk, #define TCP_ECN_DEMAND_CWR 4 #define TCP_ECN_SEEN 8 -static __inline__ void -TCP_ECN_create_request(struct request_sock *req, struct tcphdr *th) -{ - if (sysctl_tcp_ecn && th->ece && th->cwr) - inet_rsk(req)->ecn_ok = 1; -} - enum tcp_tw_status { TCP_TW_SUCCESS = 0, TCP_TW_RST = 1, @@ -389,12 +401,26 @@ extern struct sock * tcp_check_req(struct sock *sk,struct sk_buff *skb, struct request_sock **prev); extern int tcp_child_process(struct sock *parent, struct sock *child, struct sk_buff *skb); -extern int tcp_use_frto(struct sock *sk); +extern bool tcp_use_frto(struct sock *sk); extern void tcp_enter_frto(struct sock *sk); extern void tcp_enter_loss(struct sock *sk, int how); extern void tcp_clear_retrans(struct tcp_sock *tp); extern void tcp_update_metrics(struct sock *sk); +extern void tcp_init_metrics(struct sock *sk); +extern void tcp_metrics_init(void); +extern bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check); +extern bool tcp_remember_stamp(struct sock *sk); +extern bool tcp_tw_remember_stamp(struct inet_timewait_sock *tw); +extern void tcp_fastopen_cache_get(struct sock *sk, u16 *mss, + struct tcp_fastopen_cookie *cookie, + int *syn_loss, unsigned long *last_syn_loss); +extern void tcp_fastopen_cache_set(struct sock *sk, u16 mss, + struct tcp_fastopen_cookie *cookie, + bool syn_lost); +extern void tcp_fetch_timewait_stamp(struct sock *sk, struct dst_entry *dst); +extern void tcp_disable_fack(struct tcp_sock *tp); extern void tcp_close(struct sock *sk, long timeout); +extern void tcp_init_sock(struct sock *sk); extern unsigned int tcp_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait); extern int tcp_getsockopt(struct sock *sk, int level, int optname, @@ -411,7 +437,7 @@ extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len, int nonblock, int flags, int *addr_len); extern void tcp_parse_options(const struct sk_buff *skb, struct tcp_options_received *opt_rx, const u8 **hvpp, - int estab); + int estab, struct tcp_fastopen_cookie *foc); extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th); /* @@ -435,6 +461,9 @@ extern struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, struct request_values *rvp); extern int tcp_disconnect(struct sock *sk, int flags); +void tcp_connect_init(struct sock *sk); +void tcp_finish_connect(struct sock *sk, struct sk_buff *skb); +int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size); /* From syncookies.c */ extern __u32 syncookie_secret[2][16-4+SHA_DIGEST_WORDS]; @@ -472,7 +501,7 @@ static inline __u32 cookie_v6_init_sequence(struct sock *sk, extern void __tcp_push_pending_frames(struct sock *sk, unsigned int cur_mss, int nonagle); -extern int tcp_may_send_now(struct sock *sk); +extern bool tcp_may_send_now(struct sock *sk); extern int tcp_retransmit_skb(struct sock *, struct sk_buff *); extern void tcp_retransmit_timer(struct sock *sk); extern void tcp_xmit_retransmit_queue(struct sock *); @@ -486,15 +515,17 @@ extern int tcp_write_wakeup(struct sock *); extern void tcp_send_fin(struct sock *sk); extern void tcp_send_active_reset(struct sock *sk, gfp_t priority); extern int tcp_send_synack(struct sock *); -extern int tcp_syn_flood_action(struct sock *sk, - const struct sk_buff *skb, - const char *proto); +extern bool tcp_syn_flood_action(struct sock *sk, + const struct sk_buff *skb, + const char *proto); extern void tcp_push_one(struct sock *, unsigned int mss_now); extern void tcp_send_ack(struct sock *sk); extern void tcp_send_delayed_ack(struct sock *sk); /* tcp_input.c */ extern void tcp_cwnd_application_limited(struct sock *sk); +extern void tcp_resume_early_retransmit(struct sock *sk); +extern void tcp_rearm_rto(struct sock *sk); /* tcp_timer.c */ extern void tcp_init_xmit_timers(struct sock *); @@ -540,8 +571,8 @@ extern int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, extern void tcp_initialize_rcv_mss(struct sock *sk); -extern int tcp_mtu_to_mss(const struct sock *sk, int pmtu); -extern int tcp_mss_to_mtu(const struct sock *sk, int mss); +extern int tcp_mtu_to_mss(struct sock *sk, int pmtu); +extern int tcp_mss_to_mtu(struct sock *sk, int mss); extern void tcp_mtup_init(struct sock *sk); extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt); @@ -556,6 +587,8 @@ static inline u32 __tcp_set_rto(const struct tcp_sock *tp) return (tp->srtt >> 3) + tp->rttvar; } +extern void tcp_set_rto(struct sock *sk); + static inline void __tcp_fast_path_on(struct tcp_sock *tp, u32 snd_wnd) { tp->pred_flags = htonl((tp->tcp_header_len << 26) | @@ -609,6 +642,8 @@ static inline u32 tcp_receive_window(const struct tcp_sock *tp) */ extern u32 __tcp_select_window(struct sock *sk); +void tcp_send_window_probe(struct sock *sk); + /* TCP timestamps are only 32-bits, this causes a slight * complication on 64-bit systems since we store a snapshot * of jiffies in the buffer control blocks below. We decided @@ -645,21 +680,38 @@ struct tcp_skb_cb { __u32 end_seq; /* SEQ + FIN + SYN + datalen */ __u32 when; /* used to compute rtt's */ __u8 tcp_flags; /* TCP header flags. (tcp[13]) */ + __u8 sacked; /* State flags for SACK/FACK. */ #define TCPCB_SACKED_ACKED 0x01 /* SKB ACK'd by a SACK block */ #define TCPCB_SACKED_RETRANS 0x02 /* SKB retransmitted */ #define TCPCB_LOST 0x04 /* SKB is lost */ #define TCPCB_TAGBITS 0x07 /* All tag bits */ - __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */ - /* 1 byte hole */ #define TCPCB_EVER_RETRANS 0x80 /* Ever retransmitted frame */ #define TCPCB_RETRANS (TCPCB_SACKED_RETRANS|TCPCB_EVER_RETRANS) + __u8 ip_dsfield; /* IPv4 tos or IPv6 dsfield */ + /* 1 byte hole */ __u32 ack_seq; /* Sequence number ACK'd */ }; #define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0])) +/* RFC3168 : 6.1.1 SYN packets must not have ECT/ECN bits set + * + * If we receive a SYN packet with these bits set, it means a network is + * playing bad games with TOS bits. In order to avoid possible false congestion + * notifications, we disable TCP ECN negociation. + */ +static inline void +TCP_ECN_create_request(struct request_sock *req, const struct sk_buff *skb) +{ + const struct tcphdr *th = tcp_hdr(skb); + + if (sysctl_tcp_ecn && th->ece && th->cwr && + INET_ECN_is_not_ect(TCP_SKB_CB(skb)->ip_dsfield)) + inet_rsk(req)->ecn_ok = 1; +} + /* Due to TSO, an SKB can be composed of multiple actual * packets. To keep these tracked properly, we use this. */ @@ -775,12 +827,12 @@ static inline int tcp_is_sack(const struct tcp_sock *tp) return tp->rx_opt.sack_ok; } -static inline int tcp_is_reno(const struct tcp_sock *tp) +static inline bool tcp_is_reno(const struct tcp_sock *tp) { return !tcp_is_sack(tp); } -static inline int tcp_is_fack(const struct tcp_sock *tp) +static inline bool tcp_is_fack(const struct tcp_sock *tp) { return tp->rx_opt.sack_ok & TCP_FACK_ENABLED; } @@ -790,6 +842,21 @@ static inline void tcp_enable_fack(struct tcp_sock *tp) tp->rx_opt.sack_ok |= TCP_FACK_ENABLED; } +/* TCP early-retransmit (ER) is similar to but more conservative than + * the thin-dupack feature. Enable ER only if thin-dupack is disabled. + */ +static inline void tcp_enable_early_retrans(struct tcp_sock *tp) +{ + tp->do_early_retrans = sysctl_tcp_early_retrans && + !sysctl_tcp_thin_dupack && sysctl_tcp_reordering == 3; + tp->early_retrans_delayed = 0; +} + +static inline void tcp_disable_early_retrans(struct tcp_sock *tp) +{ + tp->do_early_retrans = 0; +} + static inline unsigned int tcp_left_out(const struct tcp_sock *tp) { return tp->sacked_out + tp->lost_out; @@ -867,7 +934,7 @@ static inline u32 tcp_wnd_end(const struct tcp_sock *tp) { return tp->snd_una + tp->snd_wnd; } -extern int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight); +extern bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight); static inline void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss, const struct sk_buff *skb) @@ -910,7 +977,7 @@ static inline __sum16 __tcp_checksum_complete(struct sk_buff *skb) return __skb_checksum_complete(skb); } -static inline int tcp_checksum_complete(struct sk_buff *skb) +static inline bool tcp_checksum_complete(struct sk_buff *skb) { return !skb_csum_unnecessary(skb) && __tcp_checksum_complete(skb); @@ -940,12 +1007,12 @@ static inline void tcp_prequeue_init(struct tcp_sock *tp) * * NOTE: is this not too big to inline? */ -static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) +static inline bool tcp_prequeue(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp = tcp_sk(sk); if (sysctl_tcp_low_latency || !tp->ucopy.task) - return 0; + return false; __skb_queue_tail(&tp->ucopy.prequeue, skb); tp->ucopy.memory += skb->truesize; @@ -969,7 +1036,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) (3 * tcp_rto_min(sk)) / 4, TCP_RTO_MAX); } - return 1; + return true; } @@ -1074,28 +1141,28 @@ static inline int tcp_fin_time(const struct sock *sk) return fin_timeout; } -static inline int tcp_paws_check(const struct tcp_options_received *rx_opt, - int paws_win) +static inline bool tcp_paws_check(const struct tcp_options_received *rx_opt, + int paws_win) { if ((s32)(rx_opt->ts_recent - rx_opt->rcv_tsval) <= paws_win) - return 1; + return true; if (unlikely(get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_24DAYS)) - return 1; + return true; /* * Some OSes send SYN and SYNACK messages with tsval=0 tsecr=0, * then following tcp messages have valid values. Ignore 0 value, * or else 'negative' tsval might forbid us to accept their packets. */ if (!rx_opt->ts_recent) - return 1; - return 0; + return true; + return false; } -static inline int tcp_paws_reject(const struct tcp_options_received *rx_opt, - int rst) +static inline bool tcp_paws_reject(const struct tcp_options_received *rx_opt, + int rst) { if (tcp_paws_check(rx_opt, 0)) - return 0; + return false; /* RST segments are not recommended to carry timestamp, and, if they do, it is recommended to ignore PAWS because @@ -1110,8 +1177,8 @@ static inline int tcp_paws_reject(const struct tcp_options_received *rx_opt, However, we can relax time bounds for RST segments to MSL. */ if (rst && get_seconds() >= rx_opt->ts_recent_stamp + TCP_PAWS_MSL) - return 0; - return 1; + return false; + return true; } static inline void tcp_mib_init(struct net *net) @@ -1226,10 +1293,19 @@ extern void tcp_put_md5sig_pool(void); extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *); extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *, - unsigned header_len); + unsigned int header_len); extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, const struct tcp_md5sig_key *key); +struct tcp_fastopen_request { + /* Fast Open cookie. Size 0 means a cookie request */ + struct tcp_fastopen_cookie cookie; + struct msghdr *data; /* data in MSG_FASTOPEN */ + u16 copied; /* queued in tcp_connect() */ +}; + +void tcp_free_fastopen_req(struct tcp_sock *tp); + /* write queue abstraction */ static inline void tcp_write_queue_purge(struct sock *sk) { @@ -1349,7 +1425,7 @@ static inline void tcp_unlink_write_queue(struct sk_buff *skb, struct sock *sk) __skb_unlink(skb, &sk->sk_write_queue); } -static inline int tcp_write_queue_empty(struct sock *sk) +static inline bool tcp_write_queue_empty(struct sock *sk) { return skb_queue_empty(&sk->sk_write_queue); } @@ -1406,7 +1482,7 @@ static inline void tcp_highest_sack_combine(struct sock *sk, /* Determines whether this is a thin stream (which may suffer from * increased latency). Used to trigger latency-reducing mechanisms. */ -static inline unsigned int tcp_stream_is_thin(struct tcp_sock *tp) +static inline bool tcp_stream_is_thin(struct tcp_sock *tp) { return tp->packets_out < 4 && !tcp_in_initial_slowstart(tp); } diff --git a/include/net/tcp_memcontrol.h b/include/net/tcp_memcontrol.h index 48410ff25c9e..7df18bc43a97 100644 --- a/include/net/tcp_memcontrol.h +++ b/include/net/tcp_memcontrol.h @@ -12,8 +12,8 @@ struct tcp_memcontrol { }; struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg); -int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss); -void tcp_destroy_cgroup(struct cgroup *cgrp); +int tcp_init_cgroup(struct mem_cgroup *memcg, struct cgroup_subsys *ss); +void tcp_destroy_cgroup(struct mem_cgroup *memcg); unsigned long long tcp_max_memory(const struct mem_cgroup *memcg); void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx); #endif /* _TCP_MEMCG_H */ diff --git a/include/net/timewait_sock.h b/include/net/timewait_sock.h index 8d6689cb2c66..68f0ecad6c6e 100644 --- a/include/net/timewait_sock.h +++ b/include/net/timewait_sock.h @@ -22,7 +22,6 @@ struct timewait_sock_ops { int (*twsk_unique)(struct sock *sk, struct sock *sktw, void *twp); void (*twsk_destructor)(struct sock *sk); - void *(*twsk_getpeer)(struct sock *sk); }; static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp) @@ -41,11 +40,4 @@ static inline void twsk_destructor(struct sock *sk) sk->sk_prot->twsk_prot->twsk_destructor(sk); } -static inline void *twsk_getpeer(struct sock *sk) -{ - if (sk->sk_prot->twsk_prot->twsk_getpeer) - return sk->sk_prot->twsk_prot->twsk_getpeer(sk); - return NULL; -} - #endif /* _TIMEWAIT_SOCK_H */ diff --git a/include/net/udp.h b/include/net/udp.h index 5d606d9da9e5..065f379c6503 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -81,7 +81,7 @@ struct udp_table { extern struct udp_table udp_table; extern void udp_table_init(struct udp_table *, const char *); static inline struct udp_hslot *udp_hashslot(struct udp_table *table, - struct net *net, unsigned num) + struct net *net, unsigned int num) { return &table->hash[udp_hashfn(net, num, table->mask)]; } @@ -267,4 +267,8 @@ extern void udp_init(void); extern int udp4_ufo_send_check(struct sk_buff *skb); extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, netdev_features_t features); +extern void udp_encap_enable(void); +#if IS_ENABLED(CONFIG_IPV6) +extern void udpv6_encap_enable(void); +#endif #endif /* _UDP_H */ diff --git a/include/net/wimax.h b/include/net/wimax.h index 322ff4fbdb4a..bbb74f990cab 100644 --- a/include/net/wimax.h +++ b/include/net/wimax.h @@ -423,8 +423,8 @@ struct wimax_dev { int (*op_reset)(struct wimax_dev *wimax_dev); struct rfkill *rfkill; - unsigned rf_hw; - unsigned rf_sw; + unsigned int rf_hw; + unsigned int rf_sw; char name[32]; struct dentry *debugfs_dentry; diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h index ff27f1b078d1..b52bda8d13b1 100644 --- a/include/net/wpan-phy.h +++ b/include/net/wpan-phy.h @@ -25,6 +25,14 @@ #include <linux/mutex.h> #include <linux/bug.h> +/* According to the IEEE 802.15.4 stadard the upper most significant bits of + * the 32-bit channel bitmaps shall be used as an integer value to specify 32 + * possible channel pages. The lower 27 bits of the channel bit map shall be + * used as a bit mask to specify channel numbers within a channel page. + */ +#define WPAN_NUM_CHANNELS 27 +#define WPAN_NUM_PAGES 32 + struct wpan_phy { struct mutex pib_lock; @@ -43,7 +51,7 @@ struct wpan_phy { int idx; struct net_device *(*add_iface)(struct wpan_phy *phy, - const char *name); + const char *name, int type); void (*del_iface)(struct wpan_phy *phy, struct net_device *dev); char priv[0] __attribute__((__aligned__(NETDEV_ALIGN))); diff --git a/include/net/x25.h b/include/net/x25.h index a06119a05129..b4a8a8923128 100644 --- a/include/net/x25.h +++ b/include/net/x25.h @@ -305,7 +305,7 @@ static inline void x25_unregister_sysctl(void) {}; #endif /* CONFIG_SYSCTL */ struct x25_skb_cb { - unsigned flags; + unsigned int flags; }; #define X25_SKB_CB(s) ((struct x25_skb_cb *) ((s)->cb)) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 96239e78e621..d9509eb29b80 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -886,15 +886,15 @@ __be16 xfrm_flowi_dport(const struct flowi *fl, const union flowi_uli *uli) return port; } -extern int xfrm_selector_match(const struct xfrm_selector *sel, - const struct flowi *fl, - unsigned short family); +extern bool xfrm_selector_match(const struct xfrm_selector *sel, + const struct flowi *fl, + unsigned short family); #ifdef CONFIG_SECURITY_NETWORK_XFRM /* If neither has a context --> match * Otherwise, both must have a context and the sids, doi, alg must match */ -static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2) +static inline bool xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2) { return ((!s1 && !s2) || (s1 && s2 && @@ -903,9 +903,9 @@ static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ct (s1->ctx_alg == s2->ctx_alg))); } #else -static inline int xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2) +static inline bool xfrm_sec_ctx_match(struct xfrm_sec_ctx *s1, struct xfrm_sec_ctx *s2) { - return 1; + return true; } #endif @@ -1475,6 +1475,8 @@ extern int xfrm4_output(struct sk_buff *skb); extern int xfrm4_output_finish(struct sk_buff *skb); extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); +extern int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel *handler); +extern int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel *handler); extern int xfrm6_extract_header(struct sk_buff *skb); extern int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb); extern int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi); @@ -1682,12 +1684,11 @@ static inline int xfrm_mark_get(struct nlattr **attrs, struct xfrm_mark *m) static inline int xfrm_mark_put(struct sk_buff *skb, const struct xfrm_mark *m) { - if (m->m | m->v) - NLA_PUT(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m); - return 0; + int ret = 0; -nla_put_failure: - return -1; + if (m->m | m->v) + ret = nla_put(skb, XFRMA_MARK, sizeof(struct xfrm_mark), m); + return ret; } #endif /* _NET_XFRM_H */ |