summaryrefslogtreecommitdiffstats
path: root/include/net
diff options
context:
space:
mode:
Diffstat (limited to 'include/net')
-rw-r--r--include/net/9p/9p.h42
-rw-r--r--include/net/9p/client.h8
-rw-r--r--include/net/9p/transport.h10
-rw-r--r--include/net/addrconf.h5
-rw-r--r--include/net/af_unix.h6
-rw-r--r--include/net/arp.h2
-rw-r--r--include/net/atmclip.h7
-rw-r--r--include/net/bluetooth/bluetooth.h58
-rw-r--r--include/net/bluetooth/hci.h93
-rw-r--r--include/net/bluetooth/hci_core.h411
-rw-r--r--include/net/bluetooth/l2cap.h475
-rw-r--r--include/net/bluetooth/mgmt.h251
-rw-r--r--include/net/bluetooth/rfcomm.h1
-rw-r--r--include/net/bluetooth/smp.h23
-rw-r--r--include/net/caif/caif_dev.h21
-rw-r--r--include/net/caif/caif_hsi.h37
-rw-r--r--include/net/caif/caif_layer.h4
-rw-r--r--include/net/caif/caif_spi.h4
-rw-r--r--include/net/caif/cfcnfg.h23
-rw-r--r--include/net/caif/cfserl.h4
-rw-r--r--include/net/cfg80211-wext.h55
-rw-r--r--include/net/cfg80211.h528
-rw-r--r--include/net/dcbevent.h18
-rw-r--r--include/net/dcbnl.h3
-rw-r--r--include/net/dsa.h144
-rw-r--r--include/net/dst.h23
-rw-r--r--include/net/dst_ops.h2
-rw-r--r--include/net/flow.h6
-rw-r--r--include/net/flow_keys.h16
-rw-r--r--include/net/genetlink.h2
-rw-r--r--include/net/icmp.h4
-rw-r--r--include/net/ieee80211_radiotap.h9
-rw-r--r--include/net/ieee802154.h6
-rw-r--r--include/net/if_inet6.h1
-rw-r--r--include/net/inet6_hashtables.h4
-rw-r--r--include/net/inet_connection_sock.h6
-rw-r--r--include/net/inet_ecn.h8
-rw-r--r--include/net/inet_sock.h8
-rw-r--r--include/net/inet_timewait_sock.h17
-rw-r--r--include/net/inetpeer.h3
-rw-r--r--include/net/ip.h20
-rw-r--r--include/net/ip6_fib.h7
-rw-r--r--include/net/ip6_route.h6
-rw-r--r--include/net/ip_vs.h36
-rw-r--r--include/net/ipv6.h25
-rw-r--r--include/net/iucv/af_iucv.h54
-rw-r--r--include/net/iucv/iucv.h36
-rw-r--r--include/net/lapb.h2
-rw-r--r--include/net/lib80211.h6
-rw-r--r--include/net/mac80211.h361
-rw-r--r--include/net/ndisc.h45
-rw-r--r--include/net/neighbour.h17
-rw-r--r--include/net/net_namespace.h2
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_conntrack_acct.h4
-rw-r--r--include/net/netfilter/nf_conntrack_ecache.h19
-rw-r--r--include/net/netfilter/nf_conntrack_expect.h1
-rw-r--r--include/net/netfilter/nf_conntrack_tuple.h26
-rw-r--r--include/net/netfilter/nf_log.h3
-rw-r--r--include/net/netfilter/nf_nat.h34
-rw-r--r--include/net/netfilter/nf_nat_core.h2
-rw-r--r--include/net/netfilter/nf_nat_protocol.h17
-rw-r--r--include/net/netfilter/nf_tproxy_core.h2
-rw-r--r--include/net/netlink.h11
-rw-r--r--include/net/netns/conntrack.h2
-rw-r--r--include/net/netns/ipv4.h1
-rw-r--r--include/net/netns/mib.h6
-rw-r--r--include/net/netns/xfrm.h2
-rw-r--r--include/net/netprio_cgroup.h57
-rw-r--r--include/net/nfc/nci.h313
-rw-r--r--include/net/nfc/nci_core.h183
-rw-r--r--include/net/nfc/nfc.h (renamed from include/net/nfc.h)35
-rw-r--r--include/net/protocol.h12
-rw-r--r--include/net/red.h197
-rw-r--r--include/net/regulatory.h22
-rw-r--r--include/net/route.h4
-rw-r--r--include/net/sch_generic.h25
-rw-r--r--include/net/scm.h5
-rw-r--r--include/net/sctp/sctp.h4
-rw-r--r--include/net/sctp/structs.h10
-rw-r--r--include/net/secure_seq.h2
-rw-r--r--include/net/snmp.h18
-rw-r--r--include/net/sock.h302
-rw-r--r--include/net/tcp.h106
-rw-r--r--include/net/tcp_memcontrol.h19
-rw-r--r--include/net/udp.h25
-rw-r--r--include/net/xfrm.h12
87 files changed, 3446 insertions, 1002 deletions
diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h
index a6326ef8ade..7184853ca36 100644
--- a/include/net/9p/9p.h
+++ b/include/net/9p/9p.h
@@ -63,33 +63,16 @@ enum p9_debug_flags {
#ifdef CONFIG_NET_9P_DEBUG
extern unsigned int p9_debug_level;
-
-#define P9_DPRINTK(level, format, arg...) \
-do { \
- if ((p9_debug_level & level) == level) {\
- if (level == P9_DEBUG_9P) \
- printk(KERN_NOTICE "(%8.8d) " \
- format , task_pid_nr(current) , ## arg); \
- else \
- printk(KERN_NOTICE "-- %s (%d): " \
- format , __func__, task_pid_nr(current) , ## arg); \
- } \
-} while (0)
-
-#define P9_DUMP_PKT(way, pdu) p9pdu_dump(way, pdu)
-
+__printf(3, 4)
+void _p9_debug(enum p9_debug_flags level, const char *func,
+ const char *fmt, ...);
+#define p9_debug(level, fmt, ...) \
+ _p9_debug(level, __func__, fmt, ##__VA_ARGS__)
#else
-#define P9_DPRINTK(level, format, arg...) do { } while (0)
-#define P9_DUMP_PKT(way, pdu) do { } while (0)
+#define p9_debug(level, fmt, ...) \
+ no_printk(fmt, ##__VA_ARGS__)
#endif
-
-#define P9_EPRINTK(level, format, arg...) \
-do { \
- printk(level "9p: %s (%d): " \
- format , __func__, task_pid_nr(current), ## arg); \
-} while (0)
-
/**
* enum p9_msg_t - 9P message types
* @P9_TLERROR: not used
@@ -359,6 +342,9 @@ enum p9_qid_t {
/* Room for readdir header */
#define P9_READDIRHDRSZ 24
+/* size of header for zero copy read/write */
+#define P9_ZC_HDR_SZ 4096
+
/**
* struct p9_qid - file system entity information
* @type: 8-bit type &p9_qid_t
@@ -555,10 +541,6 @@ struct p9_rstatfs {
* @tag: transaction id of the request
* @offset: used by marshalling routines to track current position in buffer
* @capacity: used by marshalling routines to track total malloc'd capacity
- * @pubuf: Payload user buffer given by the caller
- * @pkbuf: Payload kernel buffer given by the caller
- * @pbuf_size: pubuf/pkbuf(only one will be !NULL) size to be read/write.
- * @private: For transport layer's use.
* @sdata: payload
*
* &p9_fcall represents the structure for all 9P RPC
@@ -575,10 +557,6 @@ struct p9_fcall {
size_t offset;
size_t capacity;
- char __user *pubuf;
- char *pkbuf;
- size_t pbuf_size;
- void *private;
u8 *sdata;
};
diff --git a/include/net/9p/client.h b/include/net/9p/client.h
index 55ce72ce986..fc9b90b0c05 100644
--- a/include/net/9p/client.h
+++ b/include/net/9p/client.h
@@ -151,7 +151,7 @@ struct p9_req_t {
struct p9_client {
spinlock_t lock; /* protect client structure */
- int msize;
+ unsigned int msize;
unsigned char proto_version;
struct p9_trans_module *trans_mod;
enum p9_trans_status status;
@@ -240,8 +240,8 @@ int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
u64 offset, u32 count);
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
-int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
- int proto_version);
+int p9dirent_read(struct p9_client *clnt, char *buf, int len,
+ struct p9_dirent *dirent);
struct p9_wstat *p9_client_stat(struct p9_fid *fid);
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);
int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *attr);
@@ -259,7 +259,7 @@ struct p9_req_t *p9_tag_lookup(struct p9_client *, u16);
void p9_client_cb(struct p9_client *c, struct p9_req_t *req);
int p9_parse_header(struct p9_fcall *, int32_t *, int8_t *, int16_t *, int);
-int p9stat_read(char *, int, struct p9_wstat *, int);
+int p9stat_read(struct p9_client *, char *, int, struct p9_wstat *);
void p9stat_free(struct p9_wstat *);
int p9_is_proto_dotu(struct p9_client *clnt);
diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h
index 83531ebeee9..adcbb20f651 100644
--- a/include/net/9p/transport.h
+++ b/include/net/9p/transport.h
@@ -26,13 +26,6 @@
#ifndef NET_9P_TRANSPORT_H
#define NET_9P_TRANSPORT_H
-#define P9_TRANS_PREF_PAYLOAD_MASK 0x1
-
-/* Default. Add Payload to PDU before sending it down to transport layer */
-#define P9_TRANS_PREF_PAYLOAD_DEF 0x0
-/* Send pay load separately to transport layer along with PDU.*/
-#define P9_TRANS_PREF_PAYLOAD_SEP 0x1
-
/**
* struct p9_trans_module - transport module interface
* @list: used to maintain a list of currently available transports
@@ -56,13 +49,14 @@ struct p9_trans_module {
struct list_head list;
char *name; /* name of transport */
int maxsize; /* max message size of transport */
- int pref; /* Preferences of this transport */
int def; /* this transport should be default */
struct module *owner;
int (*create)(struct p9_client *, const char *, char *);
void (*close) (struct p9_client *);
int (*request) (struct p9_client *, struct p9_req_t *req);
int (*cancel) (struct p9_client *, struct p9_req_t *req);
+ int (*zc_request)(struct p9_client *, struct p9_req_t *,
+ char *, char *, int , int, int, int);
};
void v9fs_register_trans(struct p9_trans_module *m);
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 582e4ae7075..f68dce2d8d8 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -8,7 +8,7 @@
#define TEMP_VALID_LIFETIME (7*86400)
#define TEMP_PREFERRED_LIFETIME (86400)
-#define REGEN_MAX_RETRY (5)
+#define REGEN_MAX_RETRY (3)
#define MAX_DESYNC_FACTOR (600)
#define ADDR_CHECK_FREQUENCY (120*HZ)
@@ -151,7 +151,8 @@ extern int ipv6_chk_mcast_addr(struct net_device *dev,
const struct in6_addr *src_addr);
extern int ipv6_is_mld(struct sk_buff *skb, int nexthdr);
-extern void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len);
+extern void addrconf_prefix_rcv(struct net_device *dev,
+ u8 *opt, int len, bool sllao);
/*
* anycast prototypes (anycast.c)
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index 91ab5b01678..5a4e29b168c 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -11,10 +11,13 @@ extern void unix_notinflight(struct file *fp);
extern void unix_gc(void);
extern void wait_for_unix_gc(void);
extern struct sock *unix_get_socket(struct file *filp);
+extern struct sock *unix_peer_get(struct sock *);
#define UNIX_HASH_SIZE 256
extern unsigned int unix_tot_inflight;
+extern spinlock_t unix_table_lock;
+extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
struct unix_address {
atomic_t refcnt;
@@ -63,6 +66,9 @@ struct unix_sock {
#define peer_wait peer_wq.wait
+long unix_inq_len(struct sock *sk);
+long unix_outq_len(struct sock *sk);
+
#ifdef CONFIG_SYSCTL
extern int unix_sysctl_register(struct net *net);
extern void unix_sysctl_unregister(struct net *net);
diff --git a/include/net/arp.h b/include/net/arp.h
index 4979af8b155..0013dc87940 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -23,7 +23,7 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct neigh_table *tbl, str
rcu_read_lock_bh();
nht = rcu_dereference_bh(tbl->nht);
- hash_val = arp_hashfn(key, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
+ 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)) {
diff --git a/include/net/atmclip.h b/include/net/atmclip.h
index 497ef6444a7..5865924d4aa 100644
--- a/include/net/atmclip.h
+++ b/include/net/atmclip.h
@@ -15,7 +15,6 @@
#define CLIP_VCC(vcc) ((struct clip_vcc *) ((vcc)->user_back))
-#define NEIGH2ENTRY(neigh) ((struct atmarp_entry *) (neigh)->primary_key)
struct sk_buff;
@@ -36,24 +35,18 @@ struct clip_vcc {
struct atmarp_entry {
- __be32 ip; /* IP address */
struct clip_vcc *vccs; /* active VCCs; NULL if resolution is
pending */
unsigned long expires; /* entry expiration time */
struct neighbour *neigh; /* neighbour back-pointer */
};
-
#define PRIV(dev) ((struct clip_priv *) netdev_priv(dev))
-
struct clip_priv {
int number; /* for convenience ... */
spinlock_t xoff_lock; /* ensures that pop is atomic (SMP) */
struct net_device *next; /* next CLIP interface */
};
-
-extern struct neigh_table *clip_tbl_hook;
-
#endif
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index e727555d4ee..abaad6ed9b8 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -36,6 +36,11 @@
#define PF_BLUETOOTH AF_BLUETOOTH
#endif
+/* Bluetooth versions */
+#define BLUETOOTH_VER_1_1 1
+#define BLUETOOTH_VER_1_2 2
+#define BLUETOOTH_VER_2_0 3
+
/* Reserv for core and drivers use */
#define BT_SKB_RESERVE 8
@@ -77,7 +82,34 @@ struct bt_power {
#define BT_POWER_FORCE_ACTIVE_OFF 0
#define BT_POWER_FORCE_ACTIVE_ON 1
-__attribute__((format (printf, 2, 3)))
+#define BT_CHANNEL_POLICY 10
+
+/* BR/EDR only (default policy)
+ * AMP controllers cannot be used.
+ * Channel move requests from the remote device are denied.
+ * If the L2CAP channel is currently using AMP, move the channel to BR/EDR.
+ */
+#define BT_CHANNEL_POLICY_BREDR_ONLY 0
+
+/* BR/EDR Preferred
+ * Allow use of AMP controllers.
+ * If the L2CAP channel is currently on AMP, move it to BR/EDR.
+ * Channel move requests from the remote device are allowed.
+ */
+#define BT_CHANNEL_POLICY_BREDR_PREFERRED 1
+
+/* AMP Preferred
+ * Allow use of AMP controllers
+ * If the L2CAP channel is currently on BR/EDR and AMP controller
+ * resources are available, initiate a channel move to AMP.
+ * Channel move requests from the remote device are allowed.
+ * If the L2CAP socket has not been connected yet, try to create
+ * and configure the channel directly on an AMP controller rather
+ * than BR/EDR.
+ */
+#define BT_CHANNEL_POLICY_AMP_PREFERRED 2
+
+__printf(2, 3)
int bt_printk(const char *level, const char *fmt, ...);
#define BT_INFO(fmt, arg...) bt_printk(KERN_INFO, pr_fmt(fmt), ##arg)
@@ -158,7 +190,7 @@ struct bt_skb_cb {
__u8 pkt_type;
__u8 incoming;
__u16 expect;
- __u8 tx_seq;
+ __u16 tx_seq;
__u8 retries;
__u8 sar;
unsigned short channel;
@@ -218,32 +250,10 @@ extern void bt_sysfs_cleanup(void);
extern struct dentry *bt_debugfs;
-#ifdef CONFIG_BT_L2CAP
int l2cap_init(void);
void l2cap_exit(void);
-#else
-static inline int l2cap_init(void)
-{
- return 0;
-}
-
-static inline void l2cap_exit(void)
-{
-}
-#endif
-#ifdef CONFIG_BT_SCO
int sco_init(void);
void sco_exit(void);
-#else
-static inline int sco_init(void)
-{
- return 0;
-}
-
-static inline void sco_exit(void)
-{
-}
-#endif
#endif /* __BLUETOOTH_H */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index be30aabe7b8..5b2fed5eebf 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -88,6 +88,14 @@ enum {
HCI_RESET,
};
+/*
+ * BR/EDR and/or LE controller flags: the flags defined here should represent
+ * states from the controller.
+ */
+enum {
+ HCI_LE_SCAN,
+};
+
/* HCI ioctl defines */
#define HCIDEVUP _IOW('H', 201, int)
#define HCIDEVDOWN _IOW('H', 202, int)
@@ -202,6 +210,7 @@ enum {
#define LMP_EV4 0x01
#define LMP_EV5 0x02
+#define LMP_NO_BREDR 0x20
#define LMP_LE 0x40
#define LMP_SNIFF_SUBR 0x02
@@ -264,6 +273,17 @@ enum {
#define HCI_LK_SMP_IRK 0x82
#define HCI_LK_SMP_CSRK 0x83
+/* ---- HCI Error Codes ---- */
+#define HCI_ERROR_AUTH_FAILURE 0x05
+#define HCI_ERROR_REJ_BAD_ADDR 0x0f
+#define HCI_ERROR_REMOTE_USER_TERM 0x13
+#define HCI_ERROR_LOCAL_HOST_TERM 0x16
+#define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18
+
+/* Flow control modes */
+#define HCI_FLOW_CTL_MODE_PACKET_BASED 0x00
+#define HCI_FLOW_CTL_MODE_BLOCK_BASED 0x01
+
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
@@ -446,6 +466,14 @@ struct hci_rp_user_confirm_reply {
#define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d
+#define HCI_OP_USER_PASSKEY_REPLY 0x042e
+struct hci_cp_user_passkey_reply {
+ bdaddr_t bdaddr;
+ __le32 passkey;
+} __packed;
+
+#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f
+
#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
struct hci_cp_remote_oob_data_reply {
bdaddr_t bdaddr;
@@ -662,6 +690,12 @@ struct hci_rp_read_local_oob_data {
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
+#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66
+struct hci_rp_read_flow_control_mode {
+ __u8 status;
+ __u8 mode;
+} __packed;
+
#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
struct hci_cp_write_le_host_supported {
__u8 le;
@@ -716,6 +750,39 @@ struct hci_rp_read_bd_addr {
bdaddr_t bdaddr;
} __packed;
+#define HCI_OP_READ_DATA_BLOCK_SIZE 0x100a
+struct hci_rp_read_data_block_size {
+ __u8 status;
+ __le16 max_acl_len;
+ __le16 block_len;
+ __le16 num_blocks;
+} __packed;
+
+#define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c
+struct hci_cp_write_page_scan_activity {
+ __le16 interval;
+ __le16 window;
+} __packed;
+
+#define HCI_OP_WRITE_PAGE_SCAN_TYPE 0x0c47
+ #define PAGE_SCAN_TYPE_STANDARD 0x00
+ #define PAGE_SCAN_TYPE_INTERLACED 0x01
+
+#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409
+struct hci_rp_read_local_amp_info {
+ __u8 status;
+ __u8 amp_status;
+ __le32 total_bw;
+ __le32 max_bw;
+ __le32 min_latency;
+ __le32 max_pdu;
+ __u8 amp_type;
+ __le16 pal_cap;
+ __le16 max_assoc_size;
+ __le32 max_flush_to;
+ __le32 be_flush_to;
+} __packed;
+
#define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct hci_cp_le_set_event_mask {
__u8 mask[8];
@@ -728,6 +795,18 @@ struct hci_rp_le_read_buffer_size {
__u8 le_max_pkt;
} __packed;
+#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
+struct hci_cp_le_set_scan_param {
+ __u8 type;
+ __le16 interval;
+ __le16 window;
+ __u8 own_address_type;
+ __u8 filter_policy;
+} __packed;
+
+#define LE_SCANNING_DISABLED 0x00
+#define LE_SCANNING_ENABLED 0x01
+
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
struct hci_cp_le_set_scan_enable {
__u8 enable;
@@ -903,9 +982,14 @@ struct hci_ev_role_change {
} __packed;
#define HCI_EV_NUM_COMP_PKTS 0x13
+struct hci_comp_pkts_info {
+ __le16 handle;
+ __le16 count;
+} __packed;
+
struct hci_ev_num_comp_pkts {
__u8 num_hndl;
- /* variable length part */
+ struct hci_comp_pkts_info handles[0];
} __packed;
#define HCI_EV_MODE_CHANGE 0x14
@@ -1044,6 +1128,11 @@ struct hci_ev_user_confirm_req {
__le32 passkey;
} __packed;
+#define HCI_EV_USER_PASSKEY_REQUEST 0x34
+struct hci_ev_user_passkey_req {
+ bdaddr_t bdaddr;
+} __packed;
+
#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
struct hci_ev_remote_oob_data_request {
bdaddr_t bdaddr;
@@ -1299,4 +1388,6 @@ struct hci_inquiry_req {
};
#define IREQ_CACHE_FLUSH 0x0001
+extern int enable_hs;
+
#endif /* __HCI_H */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8f441b8b296..ea9231f4935 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -28,9 +28,8 @@
#include <linux/interrupt.h>
#include <net/bluetooth/hci.h>
-/* HCI upper protocols */
-#define HCI_PROTO_L2CAP 0
-#define HCI_PROTO_SCO 1
+/* HCI priority */
+#define HCI_PRIO_MAX 7
/* HCI Core structures */
struct inquiry_data {
@@ -51,14 +50,12 @@ struct inquiry_entry {
};
struct inquiry_cache {
- spinlock_t lock;
__u32 timestamp;
struct inquiry_entry *list;
};
struct hci_conn_hash {
struct list_head list;
- spinlock_t lock;
unsigned int acl_num;
unsigned int sco_num;
unsigned int le_num;
@@ -115,7 +112,7 @@ struct adv_entry {
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
- spinlock_t lock;
+ struct mutex lock;
atomic_t refcnt;
char name[8];
@@ -130,7 +127,7 @@ struct hci_dev {
__u8 major_class;
__u8 minor_class;
__u8 features[8];
- __u8 extfeatures[8];
+ __u8 host_features[8];
__u8 commands[64];
__u8 ssp_mode;
__u8 hci_ver;
@@ -150,6 +147,19 @@ struct hci_dev {
__u16 sniff_min_interval;
__u16 sniff_max_interval;
+ __u8 amp_status;
+ __u32 amp_total_bw;
+ __u32 amp_max_bw;
+ __u32 amp_min_latency;
+ __u32 amp_max_pdu;
+ __u8 amp_type;
+ __u16 amp_pal_cap;
+ __u16 amp_assoc_size;
+ __u32 amp_max_flush_to;
+ __u32 amp_be_flush_to;
+
+ __u8 flow_ctl_mode;
+
unsigned int auto_accept_delay;
unsigned long quirks;
@@ -166,6 +176,11 @@ struct hci_dev {
unsigned int sco_pkts;
unsigned int le_pkts;
+ __u16 block_len;
+ __u16 block_mtu;
+ __u16 num_blocks;
+ __u16 block_cnt;
+
unsigned long acl_last_tx;
unsigned long sco_last_tx;
unsigned long le_last_tx;
@@ -173,13 +188,18 @@ struct hci_dev {
struct workqueue_struct *workqueue;
struct work_struct power_on;
- struct work_struct power_off;
- struct timer_list off_timer;
+ struct delayed_work power_off;
+
+ __u16 discov_timeout;
+ struct delayed_work discov_off;
+
+ struct delayed_work service_cache;
struct timer_list cmd_timer;
- struct tasklet_struct cmd_task;
- struct tasklet_struct rx_task;
- struct tasklet_struct tx_task;
+
+ struct work_struct rx_work;
+ struct work_struct cmd_work;
+ struct work_struct tx_work;
struct sk_buff_head rx_q;
struct sk_buff_head raw_q;
@@ -195,7 +215,7 @@ struct hci_dev {
__u16 init_last_cmd;
- struct crypto_blkcipher *tfm;
+ struct list_head mgmt_pending;
struct inquiry_cache inq_cache;
struct hci_conn_hash conn_hash;
@@ -208,7 +228,7 @@ struct hci_dev {
struct list_head remote_oob_data;
struct list_head adv_entries;
- struct timer_list adv_timer;
+ struct delayed_work adv_work;
struct hci_dev_stats stat;
@@ -228,6 +248,8 @@ struct hci_dev {
struct module *owner;
+ unsigned long dev_flags;
+
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
@@ -275,20 +297,19 @@ struct hci_conn {
unsigned int sent;
struct sk_buff_head data_q;
+ struct list_head chan_list;
- struct timer_list disc_timer;
+ struct delayed_work disc_work;
struct timer_list idle_timer;
struct timer_list auto_accept_timer;
- struct work_struct work_add;
- struct work_struct work_del;
-
struct device dev;
atomic_t devref;
struct hci_dev *hdev;
void *l2cap_data;
void *sco_data;
+ void *smp_conn;
struct hci_conn *link;
@@ -297,25 +318,39 @@ struct hci_conn {
void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
};
-extern struct hci_proto *hci_proto[];
+struct hci_chan {
+ struct list_head list;
+
+ struct hci_conn *conn;
+ struct sk_buff_head data_q;
+ unsigned int sent;
+};
+
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock;
extern rwlock_t hci_cb_list_lock;
+/* ----- HCI interface to upper protocols ----- */
+extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+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 sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr);
+extern int sco_connect_cfm(struct hci_conn *hcon, __u8 status);
+extern int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
+extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
+
/* ----- Inquiry cache ----- */
#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
#define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
-#define inquiry_cache_lock(c) spin_lock(&c->lock)
-#define inquiry_cache_unlock(c) spin_unlock(&c->lock)
-#define inquiry_cache_lock_bh(c) spin_lock_bh(&c->lock)
-#define inquiry_cache_unlock_bh(c) spin_unlock_bh(&c->lock)
-
static inline void inquiry_cache_init(struct hci_dev *hdev)
{
struct inquiry_cache *c = &hdev->inq_cache;
- spin_lock_init(&c->lock);
c->list = NULL;
}
@@ -348,21 +383,22 @@ enum {
HCI_CONN_RSWITCH_PEND,
HCI_CONN_MODE_CHANGE_PEND,
HCI_CONN_SCO_SETUP_PEND,
+ HCI_CONN_LE_SMP_PEND,
};
static inline void hci_conn_hash_init(struct hci_dev *hdev)
{
struct hci_conn_hash *h = &hdev->conn_hash;
INIT_LIST_HEAD(&h->list);
- spin_lock_init(&h->lock);
h->acl_num = 0;
h->sco_num = 0;
+ h->le_num = 0;
}
static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- list_add(&c->list, &h->list);
+ list_add_rcu(&c->list, &h->list);
switch (c->type) {
case ACL_LINK:
h->acl_num++;
@@ -380,7 +416,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- list_del(&c->list);
+
+ list_del_rcu(&c->list);
+ synchronize_rcu();
+
switch (c->type) {
case ACL_LINK:
h->acl_num--;
@@ -395,18 +434,38 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
}
}
+static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ switch (type) {
+ case ACL_LINK:
+ return h->acl_num;
+ case LE_LINK:
+ return h->le_num;
+ case SCO_LINK:
+ case ESCO_LINK:
+ return h->sco_num;
+ default:
+ return 0;
+ }
+}
+
static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
__u16 handle)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- struct list_head *p;
struct hci_conn *c;
- list_for_each(p, &h->list) {
- c = list_entry(p, struct hci_conn, list);
- if (c->handle == handle)
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(c, &h->list, list) {
+ if (c->handle == handle) {
+ rcu_read_unlock();
return c;
+ }
}
+ rcu_read_unlock();
+
return NULL;
}
@@ -414,14 +473,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
__u8 type, bdaddr_t *ba)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- struct list_head *p;
struct hci_conn *c;
- list_for_each(p, &h->list) {
- c = list_entry(p, struct hci_conn, list);
- if (c->type == type && !bacmp(&c->dst, ba))
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(c, &h->list, list) {
+ if (c->type == type && !bacmp(&c->dst, ba)) {
+ rcu_read_unlock();
return c;
+ }
}
+
+ rcu_read_unlock();
+
return NULL;
}
@@ -429,14 +493,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
__u8 type, __u16 state)
{
struct hci_conn_hash *h = &hdev->conn_hash;
- struct list_head *p;
struct hci_conn *c;
- list_for_each(p, &h->list) {
- c = list_entry(p, struct hci_conn, list);
- if (c->type == type && c->state == state)
+ rcu_read_lock();
+
+ list_for_each_entry_rcu(c, &h->list, list) {
+ if (c->type == type && c->state == state) {
+ rcu_read_unlock();
return c;
+ }
}
+
+ rcu_read_unlock();
+
return NULL;
}
@@ -451,6 +520,10 @@ int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
+struct hci_chan *hci_chan_create(struct hci_conn *conn);
+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);
int hci_conn_check_link_mode(struct hci_conn *conn);
@@ -460,7 +533,6 @@ int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
-void hci_conn_enter_sniff_mode(struct hci_conn *conn);
void hci_conn_hold_device(struct hci_conn *conn);
void hci_conn_put_device(struct hci_conn *conn);
@@ -468,14 +540,14 @@ void hci_conn_put_device(struct hci_conn *conn);
static inline void hci_conn_hold(struct hci_conn *conn)
{
atomic_inc(&conn->refcnt);
- del_timer(&conn->disc_timer);
+ cancel_delayed_work_sync(&conn->disc_work);
}
static inline void hci_conn_put(struct hci_conn *conn)
{
if (atomic_dec_and_test(&conn->refcnt)) {
unsigned long timeo;
- if (conn->type == ACL_LINK) {
+ 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);
@@ -487,7 +559,9 @@ static inline void hci_conn_put(struct hci_conn *conn)
} else {
timeo = msecs_to_jiffies(10);
}
- mod_timer(&conn->disc_timer, jiffies + timeo);
+ cancel_delayed_work_sync(&conn->disc_work);
+ queue_delayed_work(conn->hdev->workqueue,
+ &conn->disc_work, jiffies + timeo);
}
}
@@ -498,11 +572,15 @@ static inline void __hci_dev_put(struct hci_dev *d)
d->destruct(d);
}
-static inline void hci_dev_put(struct hci_dev *d)
-{
- __hci_dev_put(d);
- module_put(d->owner);
-}
+/*
+ * hci_dev_put and hci_dev_hold are macros to avoid dragging all the
+ * overhead of all the modular infrastructure into this header.
+ */
+#define hci_dev_put(d) \
+do { \
+ __hci_dev_put(d); \
+ module_put(d->owner); \
+} while (0)
static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
{
@@ -510,17 +588,13 @@ static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
return d;
}
-static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
-{
- if (try_module_get(d->owner))
- return __hci_dev_hold(d);
- return NULL;
-}
+#define hci_dev_hold(d) \
+({ \
+ try_module_get(d->owner) ? __hci_dev_hold(d) : NULL; \
+})
-#define hci_dev_lock(d) spin_lock(&d->lock)
-#define hci_dev_unlock(d) spin_unlock(&d->lock)
-#define hci_dev_lock_bh(d) spin_lock_bh(&d->lock)
-#define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock)
+#define hci_dev_lock(d) mutex_lock(&d->lock)
+#define hci_dev_unlock(d) mutex_unlock(&d->lock)
struct hci_dev *hci_dev_get(int index);
struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
@@ -528,7 +602,7 @@ struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
struct hci_dev *hci_alloc_dev(void);
void hci_free_dev(struct hci_dev *hdev);
int hci_register_dev(struct hci_dev *hdev);
-int hci_unregister_dev(struct hci_dev *hdev);
+void hci_unregister_dev(struct hci_dev *hdev);
int hci_suspend_dev(struct hci_dev *hdev);
int hci_resume_dev(struct hci_dev *hdev);
int hci_dev_open(__u16 dev);
@@ -582,8 +656,9 @@ int hci_recv_frame(struct sk_buff *skb);
int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count);
-int hci_register_sysfs(struct hci_dev *hdev);
-void hci_unregister_sysfs(struct hci_dev *hdev);
+void hci_init_sysfs(struct hci_dev *hdev);
+int hci_add_sysfs(struct hci_dev *hdev);
+void hci_del_sysfs(struct hci_dev *hdev);
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);
@@ -601,56 +676,43 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
/* ----- Extended LMP capabilities ----- */
-#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE)
+#define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE)
/* ----- HCI protocols ----- */
-struct hci_proto {
- char *name;
- unsigned int id;
- unsigned long flags;
-
- void *priv;
-
- int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr,
- __u8 type);
- int (*connect_cfm) (struct hci_conn *conn, __u8 status);
- int (*disconn_ind) (struct hci_conn *conn);
- int (*disconn_cfm) (struct hci_conn *conn, __u8 reason);
- int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb,
- __u16 flags);
- int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
- int (*security_cfm) (struct hci_conn *conn, __u8 status,
- __u8 encrypt);
-};
-
static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
__u8 type)
{
- register struct hci_proto *hp;
- int mask = 0;
-
- hp = hci_proto[HCI_PROTO_L2CAP];
- if (hp && hp->connect_ind)
- mask |= hp->connect_ind(hdev, bdaddr, type);
+ switch (type) {
+ case ACL_LINK:
+ return l2cap_connect_ind(hdev, bdaddr);
- hp = hci_proto[HCI_PROTO_SCO];
- if (hp && hp->connect_ind)
- mask |= hp->connect_ind(hdev, bdaddr, type);
+ case SCO_LINK:
+ case ESCO_LINK:
+ return sco_connect_ind(hdev, bdaddr);
- return mask;
+ default:
+ BT_ERR("unknown link type %d", type);
+ return -EINVAL;
+ }
}
static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
{
- register struct hci_proto *hp;
+ switch (conn->type) {
+ case ACL_LINK:
+ case LE_LINK:
+ l2cap_connect_cfm(conn, status);
+ break;
- hp = hci_proto[HCI_PROTO_L2CAP];
- if (hp && hp->connect_cfm)
- hp->connect_cfm(conn, status);
+ case SCO_LINK:
+ case ESCO_LINK:
+ sco_connect_cfm(conn, status);
+ break;
- hp = hci_proto[HCI_PROTO_SCO];
- if (hp && hp->connect_cfm)
- hp->connect_cfm(conn, status);
+ default:
+ BT_ERR("unknown link type %d", conn->type);
+ break;
+ }
if (conn->connect_cfm_cb)
conn->connect_cfm_cb(conn, status);
@@ -658,31 +720,29 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
static inline int hci_proto_disconn_ind(struct hci_conn *conn)
{
- register struct hci_proto *hp;
- int reason = 0x13;
-
- hp = hci_proto[HCI_PROTO_L2CAP];
- if (hp && hp->disconn_ind)
- reason = hp->disconn_ind(conn);
-
- hp = hci_proto[HCI_PROTO_SCO];
- if (hp && hp->disconn_ind)
- reason = hp->disconn_ind(conn);
+ if (conn->type != ACL_LINK && conn->type != LE_LINK)
+ return HCI_ERROR_REMOTE_USER_TERM;
- return reason;
+ return l2cap_disconn_ind(conn);
}
static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
{
- register struct hci_proto *hp;
+ switch (conn->type) {
+ case ACL_LINK:
+ case LE_LINK:
+ l2cap_disconn_cfm(conn, reason);
+ break;
- hp = hci_proto[HCI_PROTO_L2CAP];
- if (hp && hp->disconn_cfm)
- hp->disconn_cfm(conn, reason);
+ case SCO_LINK:
+ case ESCO_LINK:
+ sco_disconn_cfm(conn, reason);
+ break;
- hp = hci_proto[HCI_PROTO_SCO];
- if (hp && hp->disconn_cfm)
- hp->disconn_cfm(conn, reason);
+ default:
+ BT_ERR("unknown link type %d", conn->type);
+ break;
+ }
if (conn->disconn_cfm_cb)
conn->disconn_cfm_cb(conn, reason);
@@ -690,21 +750,16 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
{
- register struct hci_proto *hp;
__u8 encrypt;
+ if (conn->type != ACL_LINK && conn->type != LE_LINK)
+ return;
+
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
return;
encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
-
- hp = hci_proto[HCI_PROTO_L2CAP];
- if (hp && hp->security_cfm)
- hp->security_cfm(conn, status, encrypt);
-
- hp = hci_proto[HCI_PROTO_SCO];
- if (hp && hp->security_cfm)
- hp->security_cfm(conn, status, encrypt);
+ l2cap_security_cfm(conn, status, encrypt);
if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
@@ -713,23 +768,15 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
__u8 encrypt)
{
- register struct hci_proto *hp;
-
- hp = hci_proto[HCI_PROTO_L2CAP];
- if (hp && hp->security_cfm)
- hp->security_cfm(conn, status, encrypt);
+ if (conn->type != ACL_LINK && conn->type != LE_LINK)
+ return;
- hp = hci_proto[HCI_PROTO_SCO];
- if (hp && hp->security_cfm)
- hp->security_cfm(conn, status, encrypt);
+ l2cap_security_cfm(conn, status, encrypt);
if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
}
-int hci_register_proto(struct hci_proto *hproto);
-int hci_unregister_proto(struct hci_proto *hproto);
-
/* ----- HCI callbacks ----- */
struct hci_cb {
struct list_head list;
@@ -754,13 +801,13 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
- read_lock_bh(&hci_cb_list_lock);
+ read_lock(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
- read_unlock_bh(&hci_cb_list_lock);
+ read_unlock(&hci_cb_list_lock);
}
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
@@ -776,26 +823,26 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
hci_proto_encrypt_cfm(conn, status, encrypt);
- read_lock_bh(&hci_cb_list_lock);
+ read_lock(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
- read_unlock_bh(&hci_cb_list_lock);
+ read_unlock(&hci_cb_list_lock);
}
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
{
struct list_head *p;
- read_lock_bh(&hci_cb_list_lock);
+ read_lock(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->key_change_cfm)
cb->key_change_cfm(conn, status);
}
- read_unlock_bh(&hci_cb_list_lock);
+ read_unlock(&hci_cb_list_lock);
}
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
@@ -803,13 +850,13 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
{
struct list_head *p;
- read_lock_bh(&hci_cb_list_lock);
+ read_lock(&hci_cb_list_lock);
list_for_each(p, &hci_cb_list) {
struct hci_cb *cb = list_entry(p, struct hci_cb, list);
if (cb->role_switch_cfm)
cb->role_switch_cfm(conn, status, role);
}
- read_unlock_bh(&hci_cb_list_lock);
+ read_unlock(&hci_cb_list_lock);
}
int hci_register_cb(struct hci_cb *hcb);
@@ -819,7 +866,7 @@ int hci_register_notifier(struct notifier_block *nb);
int hci_unregister_notifier(struct notifier_block *nb);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
-void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
@@ -832,42 +879,63 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
/* Management interface */
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
-int mgmt_index_added(u16 index);
-int mgmt_index_removed(u16 index);
-int mgmt_powered(u16 index, u8 powered);
-int mgmt_discoverable(u16 index, u8 discoverable);
-int mgmt_connectable(u16 index, u8 connectable);
-int mgmt_new_key(u16 index, struct link_key *key, u8 persistent);
-int mgmt_connected(u16 index, bdaddr_t *bdaddr);
-int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
-int mgmt_disconnect_failed(u16 index);
-int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure);
-int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
- u8 confirm_hint);
-int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
+int mgmt_index_added(struct hci_dev *hdev);
+int mgmt_index_removed(struct hci_dev *hdev);
+int mgmt_powered(struct hci_dev *hdev, u8 powered);
+int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
+int mgmt_connectable(struct hci_dev *hdev, u8 connectable);
+int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
+int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
+ u8 persistent);
+int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type);
+int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type);
+int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status);
+int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u8 status);
+int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure);
+int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 status);
+int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 status);
+int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ __le32 value, u8 confirm_hint);
+int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status);
-int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
-int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
+int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 status);
+int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status);
-int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
- u8 *eir);
-int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
-int mgmt_discovering(u16 index, u8 discovering);
+int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev,
+ bdaddr_t *bdaddr, u8 status);
+int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status);
+int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
+int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
+ u8 *randomizer, u8 status);
+int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir);
+int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name);
+int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status);
+int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status);
+int mgmt_discovering(struct hci_dev *hdev, u8 discovering);
+int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
+/* HCI socket flags */
+#define HCI_PI_MGMT_INIT 0
+
struct hci_pinfo {
struct bt_sock bt;
struct hci_dev *hdev;
struct hci_filter filter;
__u32 cmsg_mask;
unsigned short channel;
+ unsigned long flags;
};
/* HCI security filter */
@@ -896,4 +964,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
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);
+
#endif /* __HCI_CORE_H */
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 4f34ad25e75..68f58915069 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -27,20 +27,29 @@
#ifndef __L2CAP_H
#define __L2CAP_H
+#include <asm/unaligned.h>
+
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_MIN_MTU 48
#define L2CAP_DEFAULT_FLUSH_TO 0xffff
#define L2CAP_DEFAULT_TX_WINDOW 63
+#define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF
#define L2CAP_DEFAULT_MAX_TX 3
#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
#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_CONN_TIMEOUT (40000) /* 40 seconds */
-#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
+#define L2CAP_DISC_TIMEOUT (100)
+#define L2CAP_DISC_REJ_TIMEOUT (5000) /* 5 seconds */
+#define L2CAP_ENC_TIMEOUT (5000) /* 5 seconds */
+#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */
+#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
/* L2CAP socket address */
struct sockaddr_l2 {
@@ -88,52 +97,82 @@ struct l2cap_conninfo {
#define L2CAP_ECHO_RSP 0x09
#define L2CAP_INFO_REQ 0x0a
#define L2CAP_INFO_RSP 0x0b
+#define L2CAP_CREATE_CHAN_REQ 0x0c
+#define L2CAP_CREATE_CHAN_RSP 0x0d
+#define L2CAP_MOVE_CHAN_REQ 0x0e
+#define L2CAP_MOVE_CHAN_RSP 0x0f
+#define L2CAP_MOVE_CHAN_CFM 0x10
+#define L2CAP_MOVE_CHAN_CFM_RSP 0x11
#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
-/* L2CAP feature mask */
+/* L2CAP extended feature mask */
#define L2CAP_FEAT_FLOWCTL 0x00000001
#define L2CAP_FEAT_RETRANS 0x00000002
+#define L2CAP_FEAT_BIDIR_QOS 0x00000004
#define L2CAP_FEAT_ERTM 0x00000008
#define L2CAP_FEAT_STREAMING 0x00000010
#define L2CAP_FEAT_FCS 0x00000020
+#define L2CAP_FEAT_EXT_FLOW 0x00000040
#define L2CAP_FEAT_FIXED_CHAN 0x00000080
+#define L2CAP_FEAT_EXT_WINDOW 0x00000100
+#define L2CAP_FEAT_UCD 0x00000200
/* L2CAP checksum option */
#define L2CAP_FCS_NONE 0x00
#define L2CAP_FCS_CRC16 0x01
+/* L2CAP fixed channels */
+#define L2CAP_FC_L2CAP 0x02
+#define L2CAP_FC_A2MP 0x08
+
/* L2CAP Control Field bit masks */
-#define L2CAP_CTRL_SAR 0xC000
-#define L2CAP_CTRL_REQSEQ 0x3F00
-#define L2CAP_CTRL_TXSEQ 0x007E
-#define L2CAP_CTRL_RETRANS 0x0080
-#define L2CAP_CTRL_FINAL 0x0080
-#define L2CAP_CTRL_POLL 0x0010
-#define L2CAP_CTRL_SUPERVISE 0x000C
-#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
-
-#define L2CAP_CTRL_TXSEQ_SHIFT 1
-#define L2CAP_CTRL_REQSEQ_SHIFT 8
-#define L2CAP_CTRL_SAR_SHIFT 14
+#define L2CAP_CTRL_SAR 0xC000
+#define L2CAP_CTRL_REQSEQ 0x3F00
+#define L2CAP_CTRL_TXSEQ 0x007E
+#define L2CAP_CTRL_SUPERVISE 0x000C
+
+#define L2CAP_CTRL_RETRANS 0x0080
+#define L2CAP_CTRL_FINAL 0x0080
+#define L2CAP_CTRL_POLL 0x0010
+#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
+
+#define L2CAP_CTRL_TXSEQ_SHIFT 1
+#define L2CAP_CTRL_SUPER_SHIFT 2
+#define L2CAP_CTRL_REQSEQ_SHIFT 8
+#define L2CAP_CTRL_SAR_SHIFT 14
+
+/* L2CAP Extended Control Field bit mask */
+#define L2CAP_EXT_CTRL_TXSEQ 0xFFFC0000
+#define L2CAP_EXT_CTRL_SAR 0x00030000
+#define L2CAP_EXT_CTRL_SUPERVISE 0x00030000
+#define L2CAP_EXT_CTRL_REQSEQ 0x0000FFFC
+
+#define L2CAP_EXT_CTRL_POLL 0x00040000
+#define L2CAP_EXT_CTRL_FINAL 0x00000002
+#define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */
+
+#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_TXSEQ_SHIFT 18
/* L2CAP Supervisory Function */
-#define L2CAP_SUPER_RCV_READY 0x0000
-#define L2CAP_SUPER_REJECT 0x0004
-#define L2CAP_SUPER_RCV_NOT_READY 0x0008
-#define L2CAP_SUPER_SELECT_REJECT 0x000C
+#define L2CAP_SUPER_RR 0x00
+#define L2CAP_SUPER_REJ 0x01
+#define L2CAP_SUPER_RNR 0x02
+#define L2CAP_SUPER_SREJ 0x03
/* L2CAP Segmentation and Reassembly */
-#define L2CAP_SDU_UNSEGMENTED 0x0000
-#define L2CAP_SDU_START 0x4000
-#define L2CAP_SDU_END 0x8000
-#define L2CAP_SDU_CONTINUE 0xC000
+#define L2CAP_SAR_UNSEGMENTED 0x00
+#define L2CAP_SAR_START 0x01
+#define L2CAP_SAR_END 0x02
+#define L2CAP_SAR_CONTINUE 0x03
/* L2CAP Command rej. reasons */
-#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
-#define L2CAP_REJ_MTU_EXCEEDED 0x0001
-#define L2CAP_REJ_INVALID_CID 0x0002
-
+#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
+#define L2CAP_REJ_MTU_EXCEEDED 0x0001
+#define L2CAP_REJ_INVALID_CID 0x0002
/* L2CAP structures */
struct l2cap_hdr {
@@ -141,6 +180,12 @@ struct l2cap_hdr {
__le16 cid;
} __packed;
#define L2CAP_HDR_SIZE 4
+#define L2CAP_ENH_HDR_SIZE 6
+#define L2CAP_EXT_HDR_SIZE 8
+
+#define L2CAP_FCS_SIZE 2
+#define L2CAP_SDULEN_SIZE 2
+#define L2CAP_PSMLEN_SIZE 2
struct l2cap_cmd_hdr {
__u8 code;
@@ -185,14 +230,15 @@ struct l2cap_conn_rsp {
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
-/* connect result */
+/* connect/create channel results */
#define L2CAP_CR_SUCCESS 0x0000
#define L2CAP_CR_PEND 0x0001
#define L2CAP_CR_BAD_PSM 0x0002
#define L2CAP_CR_SEC_BLOCK 0x0003
#define L2CAP_CR_NO_MEM 0x0004
+#define L2CAP_CR_BAD_AMP 0x0005
-/* connect status */
+/* connect/create channel status */
#define L2CAP_CS_NO_INFO 0x0000
#define L2CAP_CS_AUTHEN_PEND 0x0001
#define L2CAP_CS_AUTHOR_PEND 0x0002
@@ -214,6 +260,8 @@ struct l2cap_conf_rsp {
#define L2CAP_CONF_UNACCEPT 0x0001
#define L2CAP_CONF_REJECT 0x0002
#define L2CAP_CONF_UNKNOWN 0x0003
+#define L2CAP_CONF_PENDING 0x0004
+#define L2CAP_CONF_EFS_REJECT 0x0005
struct l2cap_conf_opt {
__u8 type;
@@ -230,6 +278,8 @@ struct l2cap_conf_opt {
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_FCS 0x05
+#define L2CAP_CONF_EFS 0x06
+#define L2CAP_CONF_EWS 0x07
#define L2CAP_CONF_MAX_SIZE 22
@@ -248,6 +298,21 @@ struct l2cap_conf_rfc {
#define L2CAP_MODE_ERTM 0x03
#define L2CAP_MODE_STREAMING 0x04
+struct l2cap_conf_efs {
+ __u8 id;
+ __u8 stype;
+ __le16 msdu;
+ __le32 sdu_itime;
+ __le32 acc_lat;
+ __le32 flush_to;
+} __packed;
+
+#define L2CAP_SERV_NOTRAFIC 0x00
+#define L2CAP_SERV_BESTEFFORT 0x01
+#define L2CAP_SERV_GUARANTEED 0x02
+
+#define L2CAP_BESTEFFORT_ID 0x01
+
struct l2cap_disconn_req {
__le16 dcid;
__le16 scid;
@@ -268,14 +333,57 @@ struct l2cap_info_rsp {
__u8 data[0];
} __packed;
+struct l2cap_create_chan_req {
+ __le16 psm;
+ __le16 scid;
+ __u8 amp_id;
+} __packed;
+
+struct l2cap_create_chan_rsp {
+ __le16 dcid;
+ __le16 scid;
+ __le16 result;
+ __le16 status;
+} __packed;
+
+struct l2cap_move_chan_req {
+ __le16 icid;
+ __u8 dest_amp_id;
+} __packed;
+
+struct l2cap_move_chan_rsp {
+ __le16 icid;
+ __le16 result;
+} __packed;
+
+#define L2CAP_MR_SUCCESS 0x0000
+#define L2CAP_MR_PEND 0x0001
+#define L2CAP_MR_BAD_ID 0x0002
+#define L2CAP_MR_SAME_ID 0x0003
+#define L2CAP_MR_NOT_SUPP 0x0004
+#define L2CAP_MR_COLLISION 0x0005
+#define L2CAP_MR_NOT_ALLOWED 0x0006
+
+struct l2cap_move_chan_cfm {
+ __le16 icid;
+ __le16 result;
+} __packed;
+
+#define L2CAP_MC_CONFIRMED 0x0000
+#define L2CAP_MC_UNCONFIRMED 0x0001
+
+struct l2cap_move_chan_cfm_rsp {
+ __le16 icid;
+} __packed;
+
/* info type */
-#define L2CAP_IT_CL_MTU 0x0001
-#define L2CAP_IT_FEAT_MASK 0x0002
-#define L2CAP_IT_FIXED_CHAN 0x0003
+#define L2CAP_IT_CL_MTU 0x0001
+#define L2CAP_IT_FEAT_MASK 0x0002
+#define L2CAP_IT_FIXED_CHAN 0x0003
/* info result */
-#define L2CAP_IR_SUCCESS 0x0000
-#define L2CAP_IR_NOTSUPP 0x0001
+#define L2CAP_IR_SUCCESS 0x0000
+#define L2CAP_IR_NOTSUPP 0x0001
struct l2cap_conn_param_update_req {
__le16 min;
@@ -294,7 +402,7 @@ struct l2cap_conn_param_update_rsp {
/* ----- L2CAP channels and connections ----- */
struct srej_list {
- __u8 tx_seq;
+ __u16 tx_seq;
struct list_head list;
};
@@ -316,14 +424,11 @@ struct l2cap_chan {
__u16 flush_to;
__u8 mode;
__u8 chan_type;
+ __u8 chan_policy;
__le16 sport;
__u8 sec_level;
- __u8 role_switch;
- __u8 force_reliable;
- __u8 flushable;
- __u8 force_active;
__u8 ident;
@@ -334,7 +439,8 @@ struct l2cap_chan {
__u8 fcs;
- __u8 tx_win;
+ __u16 tx_win;
+ __u16 tx_win_max;
__u8 max_tx;
__u16 retrans_timeout;
__u16 monitor_timeout;
@@ -342,29 +448,45 @@ struct l2cap_chan {
unsigned long conf_state;
unsigned long conn_state;
-
- __u8 next_tx_seq;
- __u8 expected_ack_seq;
- __u8 expected_tx_seq;
- __u8 buffer_seq;
- __u8 buffer_seq_srej;
- __u8 srej_save_reqseq;
- __u8 frames_sent;
- __u8 unacked_frames;
+ unsigned long flags;
+
+ __u16 next_tx_seq;
+ __u16 expected_ack_seq;
+ __u16 expected_tx_seq;
+ __u16 buffer_seq;
+ __u16 buffer_seq_srej;
+ __u16 srej_save_reqseq;
+ __u16 frames_sent;
+ __u16 unacked_frames;
__u8 retry_count;
__u8 num_acked;
__u16 sdu_len;
- __u16 partial_sdu_len;
struct sk_buff *sdu;
+ struct sk_buff *sdu_last_frag;
- __u8 remote_tx_win;
+ __u16 remote_tx_win;
__u8 remote_max_tx;
__u16 remote_mps;
- struct timer_list chan_timer;
- struct timer_list retrans_timer;
- struct timer_list monitor_timer;
- struct timer_list ack_timer;
+ __u8 local_id;
+ __u8 local_stype;
+ __u16 local_msdu;
+ __u32 local_sdu_itime;
+ __u32 local_acc_lat;
+ __u32 local_flush_to;
+
+ __u8 remote_id;
+ __u8 remote_stype;
+ __u16 remote_msdu;
+ __u32 remote_sdu_itime;
+ __u32 remote_acc_lat;
+ __u32 remote_flush_to;
+
+ struct delayed_work chan_timer;
+ struct delayed_work retrans_timer;
+ struct delayed_work monitor_timer;
+ struct delayed_work ack_timer;
+
struct sk_buff *tx_send_head;
struct sk_buff_head tx_q;
struct sk_buff_head srej_q;
@@ -388,6 +510,7 @@ struct l2cap_ops {
struct l2cap_conn {
struct hci_conn *hcon;
+ struct hci_chan *hchan;
bdaddr_t *dst;
bdaddr_t *src;
@@ -399,7 +522,7 @@ struct l2cap_conn {
__u8 info_state;
__u8 info_ident;
- struct timer_list info_timer;
+ struct delayed_work info_timer;
spinlock_t lock;
@@ -409,17 +532,11 @@ struct l2cap_conn {
__u8 disc_reason;
- __u8 preq[7]; /* SMP Pairing Request */
- __u8 prsp[7]; /* SMP Pairing Response */
- __u8 prnd[16]; /* SMP Pairing Random */
- __u8 pcnf[16]; /* SMP Pairing Confirm */
- __u8 tk[16]; /* SMP Temporary Key */
- __u8 smp_key_size;
-
- struct timer_list security_timer;
+ struct delayed_work security_timer;
+ struct smp_chan *smp_chan;
struct list_head chan_l;
- rwlock_t chan_lock;
+ struct mutex chan_lock;
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
@@ -448,13 +565,15 @@ enum {
CONF_CONNECT_PEND,
CONF_NO_FCS_RECV,
CONF_STATE2_DEVICE,
+ CONF_EWS_RECV,
+ CONF_LOC_CONF_PEND,
+ CONF_REM_CONF_PEND,
};
#define L2CAP_CONF_MAX_CONF_REQ 2
#define L2CAP_CONF_MAX_CONF_RSP 2
enum {
- CONN_SAR_SDU,
CONN_SREJ_SENT,
CONN_WAIT_F,
CONN_SREJ_ACT,
@@ -466,6 +585,44 @@ enum {
CONN_RNR_SENT,
};
+/* Definitions for flags in l2cap_chan */
+enum {
+ FLAG_ROLE_SWITCH,
+ FLAG_FORCE_ACTIVE,
+ FLAG_FORCE_RELIABLE,
+ FLAG_FLUSHABLE,
+ FLAG_EXT_CTRL,
+ FLAG_EFS_ENABLE,
+};
+
+static inline void l2cap_chan_hold(struct l2cap_chan *c)
+{
+ atomic_inc(&c->refcnt);
+}
+
+static inline void l2cap_chan_put(struct l2cap_chan *c)
+{
+ if (atomic_dec_and_test(&c->refcnt))
+ kfree(c);
+}
+
+static inline void l2cap_set_timer(struct l2cap_chan *chan,
+ struct delayed_work *work, long timeout)
+{
+ BT_DBG("chan %p state %d timeout %ld", chan, chan->state, timeout);
+
+ if (!__cancel_delayed_work(work))
+ l2cap_chan_hold(chan);
+ schedule_delayed_work(work, timeout);
+}
+
+static inline void l2cap_clear_timer(struct l2cap_chan *chan,
+ struct delayed_work *work)
+{
+ if (__cancel_delayed_work(work))
+ l2cap_chan_put(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, \
@@ -478,6 +635,22 @@ enum {
L2CAP_DEFAULT_ACK_TO);
#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
+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;
+}
+
+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;
@@ -490,13 +663,164 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
return sub == ch->remote_tx_win;
}
-#define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
-#define __get_reqseq(ctrl) (((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
-#define __is_iframe(ctrl) (!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
-#define __is_sframe(ctrl) ((ctrl) & L2CAP_CTRL_FRAME_TYPE)
-#define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
+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)
+{
+ if (test_bit(FLAG_EXT_CTRL, &chan->flags))
+ return get_unaligned_le32(p);
+ else
+ return get_unaligned_le16(p);
+}
+
+static inline void __put_control(struct l2cap_chan *chan, __u32 control,
+ void *p)
+{
+ 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)
+{
+ 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 int disable_ertm;
+extern bool disable_ertm;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
@@ -510,8 +834,11 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
struct l2cap_chan *l2cap_chan_create(struct sock *sk);
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);
-int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
+inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
+ bdaddr_t *dst);
+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);
#endif /* __L2CAP_H */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 5428fd32cce..be65d341788 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -23,6 +23,23 @@
#define MGMT_INDEX_NONE 0xFFFF
+#define MGMT_STATUS_SUCCESS 0x00
+#define MGMT_STATUS_UNKNOWN_COMMAND 0x01
+#define MGMT_STATUS_NOT_CONNECTED 0x02
+#define MGMT_STATUS_FAILED 0x03
+#define MGMT_STATUS_CONNECT_FAILED 0x04
+#define MGMT_STATUS_AUTH_FAILED 0x05
+#define MGMT_STATUS_NOT_PAIRED 0x06
+#define MGMT_STATUS_NO_RESOURCES 0x07
+#define MGMT_STATUS_TIMEOUT 0x08
+#define MGMT_STATUS_ALREADY_CONNECTED 0x09
+#define MGMT_STATUS_BUSY 0x0a
+#define MGMT_STATUS_REJECTED 0x0b
+#define MGMT_STATUS_NOT_SUPPORTED 0x0c
+#define MGMT_STATUS_INVALID_PARAMS 0x0d
+#define MGMT_STATUS_DISCONNECTED 0x0e
+#define MGMT_STATUS_NOT_POWERED 0x0f
+
struct mgmt_hdr {
__le16 opcode;
__le16 index;
@@ -44,22 +61,29 @@ struct mgmt_rp_read_index_list {
/* Reserve one extra byte for names in management messages so that they
* are always guaranteed to be nul-terminated */
#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
+#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1)
+
+#define MGMT_SETTING_POWERED 0x00000001
+#define MGMT_SETTING_CONNECTABLE 0x00000002
+#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004
+#define MGMT_SETTING_DISCOVERABLE 0x00000008
+#define MGMT_SETTING_PAIRABLE 0x00000010
+#define MGMT_SETTING_LINK_SECURITY 0x00000020
+#define MGMT_SETTING_SSP 0x00000040
+#define MGMT_SETTING_BREDR 0x00000080
+#define MGMT_SETTING_HS 0x00000100
+#define MGMT_SETTING_LE 0x00000200
#define MGMT_OP_READ_INFO 0x0004
struct mgmt_rp_read_info {
- __u8 type;
- __u8 powered;
- __u8 connectable;
- __u8 discoverable;
- __u8 pairable;
- __u8 sec_mode;
bdaddr_t bdaddr;
+ __u8 version;
+ __le16 manufacturer;
+ __le32 supported_settings;
+ __le32 current_settings;
__u8 dev_class[3];
- __u8 features[8];
- __u16 manufacturer;
- __u8 hci_ver;
- __u16 hci_rev;
__u8 name[MGMT_MAX_NAME_LENGTH];
+ __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
} __packed;
struct mgmt_mode {
@@ -69,70 +93,97 @@ struct mgmt_mode {
#define MGMT_OP_SET_POWERED 0x0005
#define MGMT_OP_SET_DISCOVERABLE 0x0006
+struct mgmt_cp_set_discoverable {
+ __u8 val;
+ __u16 timeout;
+} __packed;
#define MGMT_OP_SET_CONNECTABLE 0x0007
-#define MGMT_OP_SET_PAIRABLE 0x0008
+#define MGMT_OP_SET_FAST_CONNECTABLE 0x0008
-#define MGMT_OP_ADD_UUID 0x0009
-struct mgmt_cp_add_uuid {
- __u8 uuid[16];
- __u8 svc_hint;
-} __packed;
+#define MGMT_OP_SET_PAIRABLE 0x0009
-#define MGMT_OP_REMOVE_UUID 0x000A
-struct mgmt_cp_remove_uuid {
- __u8 uuid[16];
-} __packed;
+#define MGMT_OP_SET_LINK_SECURITY 0x000A
+
+#define MGMT_OP_SET_SSP 0x000B
+
+#define MGMT_OP_SET_HS 0x000C
+
+#define MGMT_OP_SET_LE 0x000D
-#define MGMT_OP_SET_DEV_CLASS 0x000B
+#define MGMT_OP_SET_DEV_CLASS 0x000E
struct mgmt_cp_set_dev_class {
__u8 major;
__u8 minor;
} __packed;
-#define MGMT_OP_SET_SERVICE_CACHE 0x000C
-struct mgmt_cp_set_service_cache {
- __u8 enable;
+#define MGMT_OP_SET_LOCAL_NAME 0x000F
+struct mgmt_cp_set_local_name {
+ __u8 name[MGMT_MAX_NAME_LENGTH];
+} __packed;
+
+#define MGMT_OP_ADD_UUID 0x0010
+struct mgmt_cp_add_uuid {
+ __u8 uuid[16];
+ __u8 svc_hint;
+} __packed;
+
+#define MGMT_OP_REMOVE_UUID 0x0011
+struct mgmt_cp_remove_uuid {
+ __u8 uuid[16];
} __packed;
-struct mgmt_key_info {
+struct mgmt_link_key_info {
bdaddr_t bdaddr;
u8 type;
u8 val[16];
u8 pin_len;
- u8 dlen;
- u8 data[0];
} __packed;
-#define MGMT_OP_LOAD_KEYS 0x000D
-struct mgmt_cp_load_keys {
+#define MGMT_OP_LOAD_LINK_KEYS 0x0012
+struct mgmt_cp_load_link_keys {
__u8 debug_keys;
__le16 key_count;
- struct mgmt_key_info keys[0];
+ struct mgmt_link_key_info keys[0];
} __packed;
-#define MGMT_OP_REMOVE_KEY 0x000E
-struct mgmt_cp_remove_key {
+#define MGMT_OP_REMOVE_KEYS 0x0013
+struct mgmt_cp_remove_keys {
bdaddr_t bdaddr;
__u8 disconnect;
} __packed;
+struct mgmt_rp_remove_keys {
+ bdaddr_t bdaddr;
+ __u8 status;
+};
-#define MGMT_OP_DISCONNECT 0x000F
+#define MGMT_OP_DISCONNECT 0x0014
struct mgmt_cp_disconnect {
bdaddr_t bdaddr;
} __packed;
struct mgmt_rp_disconnect {
bdaddr_t bdaddr;
+ __u8 status;
+} __packed;
+
+#define MGMT_ADDR_BREDR 0x00
+#define MGMT_ADDR_LE_PUBLIC 0x01
+#define MGMT_ADDR_LE_RANDOM 0x02
+#define MGMT_ADDR_INVALID 0xff
+
+struct mgmt_addr_info {
+ bdaddr_t bdaddr;
+ __u8 type;
} __packed;
-#define MGMT_OP_GET_CONNECTIONS 0x0010
+#define MGMT_OP_GET_CONNECTIONS 0x0015
struct mgmt_rp_get_connections {
__le16 conn_count;
- bdaddr_t conn[0];
+ struct mgmt_addr_info addr[0];
} __packed;
-#define MGMT_OP_PIN_CODE_REPLY 0x0011
+#define MGMT_OP_PIN_CODE_REPLY 0x0016
struct mgmt_cp_pin_code_reply {
bdaddr_t bdaddr;
__u8 pin_len;
@@ -143,27 +194,27 @@ struct mgmt_rp_pin_code_reply {
uint8_t status;
} __packed;
-#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0012
+#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017
struct mgmt_cp_pin_code_neg_reply {
bdaddr_t bdaddr;
} __packed;
-#define MGMT_OP_SET_IO_CAPABILITY 0x0013
+#define MGMT_OP_SET_IO_CAPABILITY 0x0018
struct mgmt_cp_set_io_capability {
__u8 io_capability;
} __packed;
-#define MGMT_OP_PAIR_DEVICE 0x0014
+#define MGMT_OP_PAIR_DEVICE 0x0019
struct mgmt_cp_pair_device {
- bdaddr_t bdaddr;
+ struct mgmt_addr_info addr;
__u8 io_cap;
} __packed;
struct mgmt_rp_pair_device {
- bdaddr_t bdaddr;
+ struct mgmt_addr_info addr;
__u8 status;
} __packed;
-#define MGMT_OP_USER_CONFIRM_REPLY 0x0015
+#define MGMT_OP_USER_CONFIRM_REPLY 0x001A
struct mgmt_cp_user_confirm_reply {
bdaddr_t bdaddr;
} __packed;
@@ -172,41 +223,67 @@ struct mgmt_rp_user_confirm_reply {
__u8 status;
} __packed;
-#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016
+#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001B
+struct mgmt_cp_user_confirm_neg_reply {
+ bdaddr_t bdaddr;
+} __packed;
-#define MGMT_OP_SET_LOCAL_NAME 0x0017
-struct mgmt_cp_set_local_name {
- __u8 name[MGMT_MAX_NAME_LENGTH];
+#define MGMT_OP_USER_PASSKEY_REPLY 0x001C
+struct mgmt_cp_user_passkey_reply {
+ bdaddr_t bdaddr;
+ __le32 passkey;
+} __packed;
+struct mgmt_rp_user_passkey_reply {
+ bdaddr_t bdaddr;
+ __u8 status;
+} __packed;
+
+#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001D
+struct mgmt_cp_user_passkey_neg_reply {
+ bdaddr_t bdaddr;
} __packed;
-#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018
+#define MGMT_OP_READ_LOCAL_OOB_DATA 0x001E
struct mgmt_rp_read_local_oob_data {
__u8 hash[16];
__u8 randomizer[16];
} __packed;
-#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019
+#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x001F
struct mgmt_cp_add_remote_oob_data {
bdaddr_t bdaddr;
__u8 hash[16];
__u8 randomizer[16];
} __packed;
-#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A
+#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0020
struct mgmt_cp_remove_remote_oob_data {
bdaddr_t bdaddr;
} __packed;
-#define MGMT_OP_START_DISCOVERY 0x001B
+#define MGMT_OP_START_DISCOVERY 0x0021
+struct mgmt_cp_start_discovery {
+ __u8 type;
+} __packed;
+
+#define MGMT_OP_STOP_DISCOVERY 0x0022
-#define MGMT_OP_STOP_DISCOVERY 0x001C
+#define MGMT_OP_CONFIRM_NAME 0x0023
+struct mgmt_cp_confirm_name {
+ bdaddr_t bdaddr;
+ __u8 name_known;
+} __packed;
+struct mgmt_rp_confirm_name {
+ bdaddr_t bdaddr;
+ __u8 status;
+} __packed;
-#define MGMT_OP_BLOCK_DEVICE 0x001D
+#define MGMT_OP_BLOCK_DEVICE 0x0024
struct mgmt_cp_block_device {
bdaddr_t bdaddr;
} __packed;
-#define MGMT_OP_UNBLOCK_DEVICE 0x001E
+#define MGMT_OP_UNBLOCK_DEVICE 0x0025
struct mgmt_cp_unblock_device {
bdaddr_t bdaddr;
} __packed;
@@ -232,72 +309,82 @@ struct mgmt_ev_controller_error {
#define MGMT_EV_INDEX_REMOVED 0x0005
-#define MGMT_EV_POWERED 0x0006
+#define MGMT_EV_NEW_SETTINGS 0x0006
-#define MGMT_EV_DISCOVERABLE 0x0007
-
-#define MGMT_EV_CONNECTABLE 0x0008
+#define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007
+struct mgmt_ev_class_of_dev_changed {
+ __u8 dev_class[3];
+};
-#define MGMT_EV_PAIRABLE 0x0009
+#define MGMT_EV_LOCAL_NAME_CHANGED 0x0008
+struct mgmt_ev_local_name_changed {
+ __u8 name[MGMT_MAX_NAME_LENGTH];
+ __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH];
+} __packed;
-#define MGMT_EV_NEW_KEY 0x000A
-struct mgmt_ev_new_key {
+#define MGMT_EV_NEW_LINK_KEY 0x0009
+struct mgmt_ev_new_link_key {
__u8 store_hint;
- struct mgmt_key_info key;
+ struct mgmt_link_key_info key;
} __packed;
-#define MGMT_EV_CONNECTED 0x000B
-struct mgmt_ev_connected {
- bdaddr_t bdaddr;
-} __packed;
+#define MGMT_EV_CONNECTED 0x000A
-#define MGMT_EV_DISCONNECTED 0x000C
-struct mgmt_ev_disconnected {
- bdaddr_t bdaddr;
-} __packed;
+#define MGMT_EV_DISCONNECTED 0x000B
-#define MGMT_EV_CONNECT_FAILED 0x000D
+#define MGMT_EV_CONNECT_FAILED 0x000C
struct mgmt_ev_connect_failed {
- bdaddr_t bdaddr;
+ struct mgmt_addr_info addr;
__u8 status;
} __packed;
-#define MGMT_EV_PIN_CODE_REQUEST 0x000E
+#define MGMT_EV_PIN_CODE_REQUEST 0x000D
struct mgmt_ev_pin_code_request {
bdaddr_t bdaddr;
__u8 secure;
} __packed;
-#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
+#define MGMT_EV_USER_CONFIRM_REQUEST 0x000E
struct mgmt_ev_user_confirm_request {
bdaddr_t bdaddr;
__u8 confirm_hint;
__le32 value;
} __packed;
+#define MGMT_EV_USER_PASSKEY_REQUEST 0x000F
+struct mgmt_ev_user_passkey_request {
+ bdaddr_t bdaddr;
+} __packed;
+
#define MGMT_EV_AUTH_FAILED 0x0010
struct mgmt_ev_auth_failed {
bdaddr_t bdaddr;
__u8 status;
} __packed;
-#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011
-struct mgmt_ev_local_name_changed {
- __u8 name[MGMT_MAX_NAME_LENGTH];
-} __packed;
-
-#define MGMT_EV_DEVICE_FOUND 0x0012
+#define MGMT_EV_DEVICE_FOUND 0x0011
struct mgmt_ev_device_found {
- bdaddr_t bdaddr;
+ struct mgmt_addr_info addr;
__u8 dev_class[3];
__s8 rssi;
+ __u8 confirm_name;
__u8 eir[HCI_MAX_EIR_LENGTH];
} __packed;
-#define MGMT_EV_REMOTE_NAME 0x0013
+#define MGMT_EV_REMOTE_NAME 0x0012
struct mgmt_ev_remote_name {
bdaddr_t bdaddr;
__u8 name[MGMT_MAX_NAME_LENGTH];
} __packed;
-#define MGMT_EV_DISCOVERING 0x0014
+#define MGMT_EV_DISCOVERING 0x0013
+
+#define MGMT_EV_DEVICE_BLOCKED 0x0014
+struct mgmt_ev_device_blocked {
+ bdaddr_t bdaddr;
+} __packed;
+
+#define MGMT_EV_DEVICE_UNBLOCKED 0x0015
+struct mgmt_ev_device_unblocked {
+ bdaddr_t bdaddr;
+} __packed;
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index d5eee2093b1..e2e3ecad100 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -211,6 +211,7 @@ struct rfcomm_dlc {
#define RFCOMM_AUTH_ACCEPT 6
#define RFCOMM_AUTH_REJECT 7
#define RFCOMM_DEFER_SETUP 8
+#define RFCOMM_ENC_DROP 9
/* Scheduling flags and events */
#define RFCOMM_SCHED_WAKEUP 31
diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h
index 46c45761230..aeaf5fa2b9f 100644
--- a/include/net/bluetooth/smp.h
+++ b/include/net/bluetooth/smp.h
@@ -115,9 +115,32 @@ struct smp_cmd_security_req {
#define SMP_MIN_ENC_KEY_SIZE 7
#define SMP_MAX_ENC_KEY_SIZE 16
+#define SMP_FLAG_TK_VALID 1
+#define SMP_FLAG_CFM_PENDING 2
+#define SMP_FLAG_MITM_AUTH 3
+
+struct smp_chan {
+ struct l2cap_conn *conn;
+ u8 preq[7]; /* SMP Pairing Request */
+ u8 prsp[7]; /* SMP Pairing Response */
+ u8 prnd[16]; /* SMP Pairing Random (local) */
+ u8 rrnd[16]; /* SMP Pairing Random (remote) */
+ u8 pcnf[16]; /* SMP Pairing Confirm */
+ u8 tk[16]; /* SMP Temporary Key */
+ u8 smp_key_size;
+ unsigned long smp_flags;
+ struct crypto_blkcipher *tfm;
+ struct work_struct confirm;
+ struct work_struct random;
+
+};
+
/* SMP Commands */
int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
+int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
+
+void smp_chan_destroy(struct l2cap_conn *conn);
#endif /* __SMP_H */
diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h
index c011281d92c..ef2dd9438bb 100644
--- a/include/net/caif/caif_dev.h
+++ b/include/net/caif/caif_dev.h
@@ -9,6 +9,7 @@
#include <net/caif/caif_layer.h>
#include <net/caif/cfcnfg.h>
+#include <net/caif/caif_device.h>
#include <linux/caif/caif_socket.h>
#include <linux/if.h>
#include <linux/net.h>
@@ -104,4 +105,24 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer,
*/
void caif_free_client(struct cflayer *adap_layer);
+/**
+ * struct caif_enroll_dev - Enroll a net-device as a CAIF Link layer
+ * @dev: Network device to enroll.
+ * @caifdev: Configuration information from CAIF Link Layer
+ * @link_support: Link layer support layer
+ * @head_room: Head room needed by link support layer
+ * @layer: Lowest layer in CAIF stack
+ * @rcv_fun: Receive function for CAIF stack.
+ *
+ * This function enroll a CAIF link layer into CAIF Stack and
+ * expects the interface to be able to handle CAIF payload.
+ * The link_support layer is used to add any Link Layer specific
+ * framing.
+ */
+void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
+ struct cflayer *link_support, int head_room,
+ struct cflayer **layer, int (**rcv_func)(
+ struct sk_buff *, struct net_device *,
+ struct packet_type *, struct net_device *));
+
#endif /* CAIF_DEV_H_ */
diff --git a/include/net/caif/caif_hsi.h b/include/net/caif/caif_hsi.h
index c5dedd87b4c..8d552519ff6 100644
--- a/include/net/caif/caif_hsi.h
+++ b/include/net/caif/caif_hsi.h
@@ -52,8 +52,9 @@ struct cfhsi_desc {
/*
* Maximum bytes transferred in one transfer.
*/
-/* TODO: 4096 is temporary... */
-#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * 4096)
+#define CFHSI_MAX_CAIF_FRAME_SZ 4096
+
+#define CFHSI_MAX_PAYLOAD_SZ (CFHSI_MAX_PKTS * CFHSI_MAX_CAIF_FRAME_SZ)
/* Size of the complete HSI TX buffer. */
#define CFHSI_BUF_SZ_TX (CFHSI_DESC_SZ + CFHSI_MAX_PAYLOAD_SZ)
@@ -75,18 +76,21 @@ struct cfhsi_desc {
#define CFHSI_WAKE_UP_ACK 1
#define CFHSI_WAKE_DOWN_ACK 2
#define CFHSI_AWAKE 3
-#define CFHSI_PENDING_RX 4
-#define CFHSI_SHUTDOWN 6
-#define CFHSI_FLUSH_FIFO 7
+#define CFHSI_WAKELOCK_HELD 4
+#define CFHSI_SHUTDOWN 5
+#define CFHSI_FLUSH_FIFO 6
#ifndef CFHSI_INACTIVITY_TOUT
#define CFHSI_INACTIVITY_TOUT (1 * HZ)
#endif /* CFHSI_INACTIVITY_TOUT */
-#ifndef CFHSI_WAKEUP_TOUT
-#define CFHSI_WAKEUP_TOUT (3 * HZ)
-#endif /* CFHSI_WAKEUP_TOUT */
+#ifndef CFHSI_WAKE_TOUT
+#define CFHSI_WAKE_TOUT (3 * HZ)
+#endif /* CFHSI_WAKE_TOUT */
+#ifndef CFHSI_MAX_RX_RETRIES
+#define CFHSI_MAX_RX_RETRIES (10 * HZ)
+#endif
/* Structure implemented by the CAIF HSI driver. */
struct cfhsi_drv {
@@ -104,11 +108,21 @@ struct cfhsi_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;
};
+/* Structure holds status of received CAIF frames processing */
+struct cfhsi_rx_state {
+ int state;
+ int nfrms;
+ int pld_len;
+ int retries;
+ bool piggy_desc;
+};
+
/* Structure implemented by CAIF HSI drivers. */
struct cfhsi {
struct caif_dev_common cfdev;
@@ -118,7 +132,8 @@ struct cfhsi {
struct cfhsi_drv drv;
struct cfhsi_dev *dev;
int tx_state;
- int rx_state;
+ struct cfhsi_rx_state rx_state;
+ unsigned long inactivity_timeout;
int rx_len;
u8 *rx_ptr;
u8 *tx_buf;
@@ -130,13 +145,13 @@ struct cfhsi {
struct list_head list;
struct work_struct wake_up_work;
struct work_struct wake_down_work;
- struct work_struct rx_done_work;
- struct work_struct tx_done_work;
+ struct work_struct out_of_sync_work;
struct workqueue_struct *wq;
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 rx_slowpath_timer;
unsigned long bits;
};
diff --git a/include/net/caif/caif_layer.h b/include/net/caif/caif_layer.h
index 35bc7883cf9..0f3a39125f9 100644
--- a/include/net/caif/caif_layer.h
+++ b/include/net/caif/caif_layer.h
@@ -121,9 +121,7 @@ enum caif_direction {
* @transmit: Packet transmit funciton.
* @ctrlcmd: Used for control signalling upwards in the stack.
* @modemcmd: Used for control signaling downwards in the stack.
- * @prio: Priority of this layer.
* @id: The identity of this layer
- * @type: The type of this layer
* @name: Name of the layer.
*
* This structure defines the layered structure in CAIF.
@@ -230,9 +228,7 @@ struct cflayer {
*/
int (*modemcmd) (struct cflayer *layr, enum caif_modemcmd ctrl);
- unsigned short prio;
unsigned int id;
- unsigned int type;
char name[CAIF_LAYER_NAME_SZ];
};
diff --git a/include/net/caif/caif_spi.h b/include/net/caif/caif_spi.h
index 87c3d11b8e5..aa6a485b054 100644
--- a/include/net/caif/caif_spi.h
+++ b/include/net/caif/caif_spi.h
@@ -55,8 +55,8 @@
struct cfspi_xfer {
u16 tx_dma_len;
u16 rx_dma_len;
- void *va_tx;
- dma_addr_t pa_tx;
+ void *va_tx[2];
+ dma_addr_t pa_tx[2];
void *va_rx;
dma_addr_t pa_rx;
};
diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h
index 3e93a4a4b67..90b4ff8bad8 100644
--- a/include/net/caif/cfcnfg.h
+++ b/include/net/caif/cfcnfg.h
@@ -14,18 +14,6 @@
struct cfcnfg;
/**
- * enum cfcnfg_phy_type - Types of physical layers defined in CAIF Stack
- *
- * @CFPHYTYPE_FRAG: Fragmented frames physical interface.
- * @CFPHYTYPE_CAIF: Generic CAIF physical interface
- */
-enum cfcnfg_phy_type {
- CFPHYTYPE_FRAG = 1,
- CFPHYTYPE_CAIF,
- CFPHYTYPE_MAX
-};
-
-/**
* enum cfcnfg_phy_preference - Physical preference HW Abstraction
*
* @CFPHYPREF_UNSPECIFIED: Default physical interface
@@ -66,21 +54,20 @@ void cfcnfg_remove(struct cfcnfg *cfg);
* cfcnfg_add_phy_layer() - Adds a physical layer to the CAIF stack.
* @cnfg: Pointer to a CAIF configuration object, created by
* cfcnfg_create().
- * @phy_type: Specifies the type of physical interface, e.g.
- * CFPHYTYPE_FRAG.
* @dev: Pointer to link layer device
* @phy_layer: Specify the physical layer. The transmit function
* MUST be set in the structure.
* @pref: The phy (link layer) preference.
+ * @link_support: Protocol implementation for link layer specific protocol.
* @fcs: Specify if checksum is used in CAIF Framing Layer.
- * @stx: Specify if Start Of Frame eXtention is used.
+ * @head_room: Head space needed by link specific protocol.
*/
-
void
-cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
+cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
struct net_device *dev, struct cflayer *phy_layer,
enum cfcnfg_phy_preference pref,
- bool fcs, bool stx);
+ struct cflayer *link_support,
+ bool fcs, int head_room);
/**
* cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack.
diff --git a/include/net/caif/cfserl.h b/include/net/caif/cfserl.h
index b8374321b36..f121299a342 100644
--- a/include/net/caif/cfserl.h
+++ b/include/net/caif/cfserl.h
@@ -8,5 +8,5 @@
#define CFSERL_H_
#include <net/caif/caif_layer.h>
-struct cflayer *cfserl_create(int type, int instance, bool use_stx);
-#endif /* CFSERL_H_ */
+struct cflayer *cfserl_create(int instance, bool use_stx);
+#endif
diff --git a/include/net/cfg80211-wext.h b/include/net/cfg80211-wext.h
new file mode 100644
index 00000000000..25baddc4fbe
--- /dev/null
+++ b/include/net/cfg80211-wext.h
@@ -0,0 +1,55 @@
+#ifndef __NET_CFG80211_WEXT_H
+#define __NET_CFG80211_WEXT_H
+/*
+ * 802.11 device and configuration interface -- wext handlers
+ *
+ * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
+ *
+ * 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.
+ */
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/iw_handler.h>
+
+/*
+ * Temporary wext handlers & helper functions
+ *
+ * These are used only by drivers that aren't yet fully
+ * converted to cfg80211.
+ */
+int cfg80211_wext_giwname(struct net_device *dev,
+ struct iw_request_info *info,
+ char *name, char *extra);
+int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
+ u32 *mode, char *extra);
+int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
+ u32 *mode, char *extra);
+int cfg80211_wext_siwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu, char *extra);
+int cfg80211_wext_giwscan(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+int cfg80211_wext_giwrange(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_point *data, char *extra);
+int cfg80211_wext_siwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra);
+int cfg80211_wext_giwrts(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *rts, char *extra);
+int cfg80211_wext_siwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra);
+int cfg80211_wext_giwfrag(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *frag, char *extra);
+int cfg80211_wext_giwretry(struct net_device *dev,
+ struct iw_request_info *info,
+ struct iw_param *retry, char *extra);
+
+#endif /* __NET_CFG80211_WEXT_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 401d73bd151..15f4be7d768 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -20,11 +20,6 @@
#include <linux/ieee80211.h>
#include <net/regulatory.h>
-/* remove once we remove the wext stuff */
-#include <net/iw_handler.h>
-#include <linux/wireless.h>
-
-
/**
* DOC: Introduction
*
@@ -339,6 +334,36 @@ struct survey_info {
};
/**
+ * struct cfg80211_crypto_settings - Crypto settings
+ * @wpa_versions: indicates which, if any, WPA versions are enabled
+ * (from enum nl80211_wpa_versions)
+ * @cipher_group: group key cipher suite (or 0 if unset)
+ * @n_ciphers_pairwise: number of AP supported unicast ciphers
+ * @ciphers_pairwise: unicast key cipher suites
+ * @n_akm_suites: number of AKM suites
+ * @akm_suites: AKM suites
+ * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
+ * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
+ * required to assume that the port is unauthorized until authorized by
+ * user space. Otherwise, port is marked authorized by default.
+ * @control_port_ethertype: the control port protocol that should be
+ * allowed through even on unauthorized ports
+ * @control_port_no_encrypt: TRUE to prevent encryption of control port
+ * protocol frames.
+ */
+struct cfg80211_crypto_settings {
+ u32 wpa_versions;
+ u32 cipher_group;
+ int n_ciphers_pairwise;
+ u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES];
+ int n_akm_suites;
+ u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
+ bool control_port;
+ __be16 control_port_ethertype;
+ bool control_port_no_encrypt;
+};
+
+/**
* struct beacon_parameters - beacon parameters
*
* Used to configure the beacon for an interface.
@@ -351,11 +376,42 @@ struct survey_info {
* @dtim_period: DTIM period or zero if not changed
* @head_len: length of @head
* @tail_len: length of @tail
+ * @ssid: SSID to be used in the BSS (note: may be %NULL if not provided from
+ * user space)
+ * @ssid_len: length of @ssid
+ * @hidden_ssid: whether to hide the SSID in Beacon/Probe Response frames
+ * @crypto: crypto settings
+ * @privacy: the BSS uses privacy
+ * @auth_type: Authentication type (algorithm)
+ * @beacon_ies: extra information element(s) to add into Beacon frames or %NULL
+ * @beacon_ies_len: length of beacon_ies in octets
+ * @proberesp_ies: extra information element(s) to add into Probe Response
+ * frames or %NULL
+ * @proberesp_ies_len: length of proberesp_ies in octets
+ * @assocresp_ies: extra information element(s) to add into (Re)Association
+ * Response frames or %NULL
+ * @assocresp_ies_len: length of assocresp_ies in octets
+ * @probe_resp_len: length of probe response template (@probe_resp)
+ * @probe_resp: probe response template (AP mode only)
*/
struct beacon_parameters {
u8 *head, *tail;
int interval, dtim_period;
int head_len, tail_len;
+ const u8 *ssid;
+ size_t ssid_len;
+ enum nl80211_hidden_ssid hidden_ssid;
+ struct cfg80211_crypto_settings crypto;
+ bool privacy;
+ enum nl80211_auth_type auth_type;
+ const u8 *beacon_ies;
+ size_t beacon_ies_len;
+ const u8 *proberesp_ies;
+ size_t proberesp_ies_len;
+ const u8 *assocresp_ies;
+ size_t assocresp_ies_len;
+ int probe_resp_len;
+ u8 *probe_resp;
};
/**
@@ -372,6 +428,17 @@ enum plink_actions {
};
/**
+ * enum station_parameters_apply_mask - station parameter values to apply
+ * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
+ *
+ * Not all station parameters have in-band "no change" signalling,
+ * for those that don't these flags will are used.
+ */
+enum station_parameters_apply_mask {
+ STATION_PARAM_APPLY_UAPSD = BIT(0),
+};
+
+/**
* struct station_parameters - station parameters
*
* Used to change and create a new station.
@@ -389,17 +456,27 @@ enum plink_actions {
* @plink_action: plink action to take
* @plink_state: set the peer link state for a station
* @ht_capa: HT capabilities of station
+ * @uapsd_queues: bitmap of queues configured for uapsd. same format
+ * as the AC bitmap in the QoS info field
+ * @max_sp: max Service Period. same format as the MAX_SP in the
+ * QoS info field (but already shifted down)
+ * @sta_modify_mask: bitmap indicating which parameters changed
+ * (for those that don't have a natural "no change" value),
+ * see &enum station_parameters_apply_mask
*/
struct station_parameters {
u8 *supported_rates;
struct net_device *vlan;
u32 sta_flags_mask, sta_flags_set;
+ u32 sta_modify_mask;
int listen_interval;
u16 aid;
u8 supported_rates_len;
u8 plink_action;
u8 plink_state;
struct ieee80211_ht_cap *ht_capa;
+ u8 uapsd_queues;
+ u8 max_sp;
};
/**
@@ -426,6 +503,9 @@ struct station_parameters {
* @STATION_INFO_RX_BITRATE: @rxrate fields are filled
* @STATION_INFO_BSS_PARAM: @bss_param filled
* @STATION_INFO_CONNECTED_TIME: @connected_time filled
+ * @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
*/
enum station_info_flags {
STATION_INFO_INACTIVE_TIME = 1<<0,
@@ -444,7 +524,10 @@ enum station_info_flags {
STATION_INFO_SIGNAL_AVG = 1<<13,
STATION_INFO_RX_BITRATE = 1<<14,
STATION_INFO_BSS_PARAM = 1<<15,
- STATION_INFO_CONNECTED_TIME = 1<<16
+ 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
};
/**
@@ -536,6 +619,13 @@ struct sta_bss_parameters {
* This number should increase every time the list of stations
* changes, i.e. when a station is added or removed, so that
* userspace can tell whether it got a consistent snapshot.
+ * @assoc_req_ies: IEs from (Re)Association Request.
+ * This is used only when in AP mode with drivers that do not use
+ * user space MLME/SME implementation. The information is provided for
+ * the cfg80211_new_sta() calls to notify user space of the IEs.
+ * @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.
*/
struct station_info {
u32 filled;
@@ -556,8 +646,19 @@ struct station_info {
u32 tx_failed;
u32 rx_dropped_misc;
struct sta_bss_parameters bss_param;
+ struct nl80211_sta_flag_update sta_flags;
int generation;
+
+ const u8 *assoc_req_ies;
+ size_t assoc_req_ies_len;
+
+ u32 beacon_loss_count;
+
+ /*
+ * Note: Add a new enum station_info_flags value for each new field and
+ * use it to check which fields are initialized.
+ */
};
/**
@@ -686,8 +787,15 @@ struct mesh_config {
u16 min_discovery_timeout;
u32 dot11MeshHWMPactivePathTimeout;
u16 dot11MeshHWMPpreqMinInterval;
+ u16 dot11MeshHWMPperrMinInterval;
u16 dot11MeshHWMPnetDiameterTraversalTime;
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;
};
/**
@@ -700,6 +808,7 @@ struct mesh_config {
* @ie_len: length of vendor information elements
* @is_authenticated: this mesh requires authentication
* @is_secure: this mesh uses security
+ * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a]
*
* These parameters are fixed when the mesh is created.
*/
@@ -712,6 +821,7 @@ struct mesh_setup {
u8 ie_len;
bool is_authenticated;
bool is_secure;
+ int mcast_rate[IEEE80211_NUM_BANDS];
};
/**
@@ -781,6 +891,7 @@ struct cfg80211_ssid {
* @wiphy: the wiphy this was for
* @dev: the interface
* @aborted: (internal) scan request was notified as aborted
+ * @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
@@ -795,12 +906,22 @@ struct cfg80211_scan_request {
struct wiphy *wiphy;
struct net_device *dev;
bool aborted;
+ bool no_cck;
/* keep last */
struct ieee80211_channel *channels[0];
};
/**
+ * struct cfg80211_match_set - sets of attributes to match
+ *
+ * @ssid: SSID to be matched
+ */
+struct cfg80211_match_set {
+ struct cfg80211_ssid ssid;
+};
+
+/**
* struct cfg80211_sched_scan_request - scheduled scan request description
*
* @ssids: SSIDs to scan for (passed in the probe_reqs in active scans)
@@ -809,6 +930,11 @@ struct cfg80211_scan_request {
* @interval: interval between each scheduled scan cycle
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
+ * @match_sets: sets of parameters to be matched for a scan result
+ * entry to be considered valid and to be passed to the host
+ * (others are filtered out).
+ * If ommited, all results are passed.
+ * @n_match_sets: number of match sets
* @wiphy: the wiphy this was for
* @dev: the interface
* @channels: channels to scan
@@ -820,6 +946,8 @@ struct cfg80211_sched_scan_request {
u32 interval;
const u8 *ie;
size_t ie_len;
+ struct cfg80211_match_set *match_sets;
+ int n_match_sets;
/* internal */
struct wiphy *wiphy;
@@ -896,36 +1024,6 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
/**
- * struct cfg80211_crypto_settings - Crypto settings
- * @wpa_versions: indicates which, if any, WPA versions are enabled
- * (from enum nl80211_wpa_versions)
- * @cipher_group: group key cipher suite (or 0 if unset)
- * @n_ciphers_pairwise: number of AP supported unicast ciphers
- * @ciphers_pairwise: unicast key cipher suites
- * @n_akm_suites: number of AKM suites
- * @akm_suites: AKM suites
- * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
- * sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
- * required to assume that the port is unauthorized until authorized by
- * user space. Otherwise, port is marked authorized by default.
- * @control_port_ethertype: the control port protocol that should be
- * allowed through even on unauthorized ports
- * @control_port_no_encrypt: TRUE to prevent encryption of control port
- * protocol frames.
- */
-struct cfg80211_crypto_settings {
- u32 wpa_versions;
- u32 cipher_group;
- int n_ciphers_pairwise;
- u32 ciphers_pairwise[NL80211_MAX_NR_CIPHER_SUITES];
- int n_akm_suites;
- u32 akm_suites[NL80211_MAX_NR_AKM_SUITES];
- bool control_port;
- __be16 control_port_ethertype;
- bool control_port_no_encrypt;
-};
-
-/**
* struct cfg80211_auth_request - Authentication request data
*
* This structure provides information needed to complete IEEE 802.11
@@ -954,6 +1052,15 @@ struct cfg80211_auth_request {
};
/**
+ * enum cfg80211_assoc_req_flags - Over-ride default behaviour in association.
+ *
+ * @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n)
+ */
+enum cfg80211_assoc_req_flags {
+ ASSOC_REQ_DISABLE_HT = BIT(0),
+};
+
+/**
* struct cfg80211_assoc_request - (Re)Association request data
*
* This structure provides information needed to complete IEEE 802.11
@@ -964,6 +1071,10 @@ struct cfg80211_auth_request {
* @use_mfp: Use management frame protection (IEEE 802.11w) in this association
* @crypto: crypto settings
* @prev_bssid: previous BSSID, if not %NULL use reassociate frame
+ * @flags: See &enum cfg80211_assoc_req_flags
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Un-supported values will be ignored.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
*/
struct cfg80211_assoc_request {
struct cfg80211_bss *bss;
@@ -971,6 +1082,9 @@ struct cfg80211_assoc_request {
size_t ie_len;
struct cfg80211_crypto_settings crypto;
bool use_mfp;
+ u32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
};
/**
@@ -1040,6 +1154,7 @@ struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
struct ieee80211_channel *channel;
+ enum nl80211_channel_type channel_type;
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
@@ -1069,6 +1184,10 @@ struct cfg80211_ibss_params {
* @key_len: length of WEP key for shared key authentication
* @key_idx: index of WEP key for shared key authentication
* @key: WEP key for shared key authentication
+ * @flags: See &enum cfg80211_assoc_req_flags
+ * @ht_capa: HT Capabilities over-rides. Values set in ht_capa_mask
+ * will be used in ht_capa. Un-supported values will be ignored.
+ * @ht_capa_mask: The bits of ht_capa which are to be used.
*/
struct cfg80211_connect_params {
struct ieee80211_channel *channel;
@@ -1082,6 +1201,9 @@ struct cfg80211_connect_params {
struct cfg80211_crypto_settings crypto;
const u8 *key;
u8 key_len, key_idx;
+ u32 flags;
+ struct ieee80211_ht_cap ht_capa;
+ struct ieee80211_ht_cap ht_capa_mask;
};
/**
@@ -1229,7 +1351,12 @@ struct cfg80211_gtk_rekey_data {
*
* @add_station: Add a new station.
* @del_station: Remove a station; @mac may be NULL to remove all stations.
- * @change_station: Modify a given station.
+ * @change_station: Modify a given station. Note that flags changes are not much
+ * validated in cfg80211, in particular the auth/assoc/authorized flags
+ * might come to the driver in invalid combinations -- make sure to check
+ * them, also against the existing state! Also, supported_rates changes are
+ * not checked in station mode -- drivers need to reject (or ignore) them
+ * for anything but TDLS peers.
* @get_station: get station information for the station identified by @mac
* @dump_station: dump station callback -- resume dump at index @idx
*
@@ -1256,6 +1383,9 @@ struct cfg80211_gtk_rekey_data {
* 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.
*
* @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().
@@ -1283,7 +1413,8 @@ struct cfg80211_gtk_rekey_data {
* have changed. The actual parameter values are available in
* struct wiphy. If returning an error, no value should be changed.
*
- * @set_tx_power: set the transmit power according to the parameters
+ * @set_tx_power: set the transmit power according to the parameters,
+ * the power passed is in mBm, to get dBm use MBM_TO_DBM().
* @get_tx_power: store the current TX power into the dbm variable;
* return 0 if successful
*
@@ -1343,6 +1474,14 @@ struct cfg80211_gtk_rekey_data {
* @set_ringparam: Set tx and rx ring sizes.
*
* @get_ringparam: Get tx and rx ring current and maximum sizes.
+ *
+ * @tdls_mgmt: Transmit a TDLS management frame.
+ * @tdls_oper: Perform a high-level TDLS operation (e.g. TDLS link setup).
+ *
+ * @probe_client: probe an associated client, must return a cookie that it
+ * later passes to cfg80211_probe_status().
+ *
+ * @set_noack_map: Set the NoAck Map for the TIDs.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1419,7 +1558,7 @@ struct cfg80211_ops {
int (*change_bss)(struct wiphy *wiphy, struct net_device *dev,
struct bss_parameters *params);
- int (*set_txq_params)(struct wiphy *wiphy,
+ 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,
@@ -1495,7 +1634,8 @@ struct cfg80211_ops {
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, u64 *cookie);
+ 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,
u64 cookie);
@@ -1525,6 +1665,21 @@ struct cfg80211_ops {
int (*set_rekey_data)(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_gtk_rekey_data *data);
+
+ int (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, u8 action_code, u8 dialog_token,
+ u16 status_code, const u8 *buf, size_t len);
+ int (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
+ u8 *peer, enum nl80211_tdls_operation oper);
+
+ int (*probe_client)(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, u64 *cookie);
+
+ int (*set_noack_map)(struct wiphy *wiphy,
+ struct net_device *dev,
+ u16 noack_map);
+
+ struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy);
};
/*
@@ -1549,7 +1704,9 @@ struct cfg80211_ops {
* regulatory domain no user regulatory domain can enable these channels
* at a later time. This can be used for devices which do not have
* calibration information guaranteed for frequencies or settings
- * outside of its regulatory domain.
+ * outside of its regulatory domain. If used in combination with
+ * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings
+ * will be followed.
* @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure
* that passive scan flags and beaconing flags may not be lifted by
* cfg80211 due to regulatory beacon hints. For more information on beacon
@@ -1574,6 +1731,23 @@ struct cfg80211_ops {
* @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing
* auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH.
* @WIPHY_FLAG_SUPPORTS_SCHED_SCAN: The device supports scheduled scans.
+ * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the
+ * firmware.
+ * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP.
+ * @WIPHY_FLAG_SUPPORTS_TDLS: The device supports TDLS (802.11z) operation.
+ * @WIPHY_FLAG_TDLS_EXTERNAL_SETUP: The device does not handle TDLS (802.11z)
+ * link setup/discovery operations internally. Setup, discovery and
+ * teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
+ * command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
+ * used for asking the driver/firmware to perform a TDLS operation.
+ * @WIPHY_FLAG_HAVE_AP_SME: device integrates AP SME
+ * @WIPHY_FLAG_REPORTS_OBSS: the device will report beacons from other BSSes
+ * when there are virtual interfaces in AP mode by calling
+ * cfg80211_report_obss_beacon().
+ * @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD: When operating as an AP, the device
+ * responds to probe-requests in hardware.
+ * @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
+ * @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
*/
enum wiphy_flags {
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
@@ -1588,6 +1762,15 @@ enum wiphy_flags {
WIPHY_FLAG_MESH_AUTH = BIT(10),
WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11),
WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12),
+ WIPHY_FLAG_SUPPORTS_FW_ROAM = BIT(13),
+ WIPHY_FLAG_AP_UAPSD = BIT(14),
+ WIPHY_FLAG_SUPPORTS_TDLS = BIT(15),
+ WIPHY_FLAG_TDLS_EXTERNAL_SETUP = BIT(16),
+ WIPHY_FLAG_HAVE_AP_SME = BIT(17),
+ WIPHY_FLAG_REPORTS_OBSS = BIT(18),
+ WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(19),
+ WIPHY_FLAG_OFFCHAN_TX = BIT(20),
+ WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(21),
};
/**
@@ -1749,6 +1932,7 @@ struct wiphy_wowlan_support {
* @debugfsdir: debugfs directory used for this wiphy, will be renamed
* automatically on wiphy renames
* @dev: (virtual) struct device for this wiphy
+ * @registered: helps synchronize suspend/resume with wiphy unregister
* @wext: wireless extension handlers
* @priv: driver private data (sized according to wiphy_new() parameter)
* @interface_modes: bitmask of interfaces types valid for this wiphy,
@@ -1759,12 +1943,16 @@ struct wiphy_wowlan_support {
* @software_iftypes: bitmask of software interface types, these are not
* subject to any restrictions since they are purely managed in SW.
* @flags: wiphy flags, see &enum wiphy_flags
+ * @features: features advertised to nl80211, see &enum nl80211_feature_flags.
* @bss_priv_size: each BSS struct has private data allocated with it,
* this variable determines its size
* @max_scan_ssids: maximum number of SSIDs the device can scan for in
* any given scan
* @max_sched_scan_ssids: maximum number of SSIDs the device can scan
* for in any given scheduled scan
+ * @max_match_sets: maximum number of match sets the device can handle
+ * when performing a scheduled scan, 0 if filtering is not
+ * supported.
* @max_scan_ie_len: maximum length of user-controlled IEs device can
* add to probe request frames transmitted during a scan, must not
* include fixed IEs like supported rates
@@ -1794,6 +1982,10 @@ struct wiphy_wowlan_support {
* may request, if implemented.
*
* @wowlan: WoWLAN support information
+ *
+ * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features.
+ * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden.
+ * If null, then none can be over-ridden.
*/
struct wiphy {
/* assign these fields before you register the wiphy */
@@ -1815,13 +2007,16 @@ struct wiphy {
/* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */
u16 interface_modes;
- u32 flags;
+ u32 flags, features;
+
+ u32 ap_sme_capa;
enum cfg80211_signal_type signal_type;
int bss_priv_size;
u8 max_scan_ssids;
u8 max_sched_scan_ssids;
+ u8 max_match_sets;
u16 max_scan_ie_len;
u16 max_sched_scan_ie_len;
@@ -1846,6 +2041,13 @@ struct wiphy {
u32 available_antennas_tx;
u32 available_antennas_rx;
+ /*
+ * Bitmap of supported protocols for probe response offloading
+ * see &enum nl80211_probe_resp_offload_support_attr. Only valid
+ * when the wiphy flag @WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD is set.
+ */
+ u32 probe_resp_offload;
+
/* If multiple wiphys are registered and you're handed e.g.
* a regular netdev with assigned ieee80211_ptr, you won't
* know whether it points to a wiphy your driver has registered
@@ -1873,6 +2075,8 @@ struct wiphy {
/* dir in debugfs: ieee80211/<wiphyname> */
struct dentry *debugfsdir;
+ const struct ieee80211_ht_cap *ht_capa_mod_mask;
+
#ifdef CONFIG_NET_NS
/* the network namespace this phy lives in currently */
struct net *_net;
@@ -2069,6 +2273,8 @@ struct wireless_dev {
int beacon_interval;
+ u32 ap_unexpected_nlpid;
+
#ifdef CONFIG_CFG80211_WEXT
/* wext data */
struct {
@@ -2324,6 +2530,24 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb);
const u8 *cfg80211_find_ie(u8 eid, const u8 *ies, int len);
/**
+ * cfg80211_find_vendor_ie - find vendor specific information element in data
+ *
+ * @oui: vendor OUI
+ * @oui_type: vendor-specific OUI type
+ * @ies: data consisting of IEs
+ * @len: length of data
+ *
+ * This function will return %NULL if the vendor specific element ID
+ * could not be found or if the element is invalid (claims to be
+ * longer than the given data), or a pointer to the first byte
+ * of the requested element, that is the byte containing the
+ * element ID. There are no checks on the element length
+ * other than having to fit into the given data.
+ */
+const u8 *cfg80211_find_vendor_ie(unsigned int oui, u8 oui_type,
+ const u8 *ies, int len);
+
+/**
* DOC: Regulatory enforcement infrastructure
*
* TODO
@@ -2398,113 +2622,6 @@ extern int freq_reg_info(struct wiphy *wiphy,
const struct ieee80211_reg_rule **reg_rule);
/*
- * Temporary wext handlers & helper functions
- *
- * In the future cfg80211 will simply assign the entire wext handler
- * structure to netdevs it manages, but we're not there yet.
- */
-int cfg80211_wext_giwname(struct net_device *dev,
- struct iw_request_info *info,
- char *name, char *extra);
-int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
- u32 *mode, char *extra);
-int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
- u32 *mode, char *extra);
-int cfg80211_wext_siwscan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-int cfg80211_wext_giwscan(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra);
-int cfg80211_wext_siwmlme(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra);
-int cfg80211_wext_giwrange(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra);
-int cfg80211_wext_siwgenie(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra);
-int cfg80211_wext_siwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra);
-int cfg80211_wext_giwauth(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *data, char *extra);
-
-int cfg80211_wext_siwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra);
-int cfg80211_wext_giwfreq(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_freq *freq, char *extra);
-int cfg80211_wext_siwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid);
-int cfg80211_wext_giwessid(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *ssid);
-int cfg80211_wext_siwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra);
-int cfg80211_wext_giwrate(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rate, char *extra);
-
-int cfg80211_wext_siwrts(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rts, char *extra);
-int cfg80211_wext_giwrts(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *rts, char *extra);
-int cfg80211_wext_siwfrag(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *frag, char *extra);
-int cfg80211_wext_giwfrag(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *frag, char *extra);
-int cfg80211_wext_siwretry(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *retry, char *extra);
-int cfg80211_wext_giwretry(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *retry, char *extra);
-int cfg80211_wext_siwencodeext(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *extra);
-int cfg80211_wext_siwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *keybuf);
-int cfg80211_wext_giwencode(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *erq, char *keybuf);
-int cfg80211_wext_siwtxpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *data, char *keybuf);
-int cfg80211_wext_giwtxpower(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *data, char *keybuf);
-struct iw_statistics *cfg80211_wireless_stats(struct net_device *dev);
-
-int cfg80211_wext_siwpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq, char *extra);
-int cfg80211_wext_giwpower(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_param *wrq, char *extra);
-
-int cfg80211_wext_siwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra);
-int cfg80211_wext_giwap(struct net_device *dev,
- struct iw_request_info *info,
- struct sockaddr *ap_addr, char *extra);
-
-int cfg80211_wext_siwpmksa(struct net_device *dev,
- struct iw_request_info *info,
- struct iw_point *data, char *extra);
-
-/*
* callbacks for asynchronous cfg80211 methods, notification
* functions and BSS handling helpers
*/
@@ -2548,8 +2665,10 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
*
* This informs cfg80211 that BSS information was found and
* the BSS should be updated/added.
+ *
+ * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()!
*/
-struct cfg80211_bss*
+struct cfg80211_bss * __must_check
cfg80211_inform_bss_frame(struct wiphy *wiphy,
struct ieee80211_channel *channel,
struct ieee80211_mgmt *mgmt, size_t len,
@@ -2571,8 +2690,10 @@ cfg80211_inform_bss_frame(struct wiphy *wiphy,
*
* This informs cfg80211 that BSS information was found and
* the BSS should be updated/added.
+ *
+ * NOTE: Returns a referenced struct, must be released with cfg80211_put_bss()!
*/
-struct cfg80211_bss*
+struct cfg80211_bss * __must_check
cfg80211_inform_bss(struct wiphy *wiphy,
struct ieee80211_channel *channel,
const u8 *bssid,
@@ -2955,6 +3076,32 @@ void cfg80211_roamed(struct net_device *dev,
const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
/**
+ * cfg80211_roamed_bss - notify cfg80211 of roaming
+ *
+ * @dev: network device
+ * @bss: entry of bss to which STA got roamed
+ * @req_ie: association request IEs (maybe be %NULL)
+ * @req_ie_len: association request IEs length
+ * @resp_ie: association response IEs (may be %NULL)
+ * @resp_ie_len: assoc response IEs length
+ * @gfp: allocation flags
+ *
+ * This is just a wrapper to notify cfg80211 of roaming event with driver
+ * passing bss to avoid a race in timeout of the bss entry. It should be
+ * called by the underlying driver whenever it roamed from one AP to another
+ * while connected. Drivers which have roaming implemented in firmware
+ * may use this function to avoid a race in bss entry timeout where the bss
+ * entry of the new AP is seen in the driver, but gets timed out by the time
+ * it is accessed in __cfg80211_roamed() due to delay in scheduling
+ * rdev->event_work. In case of any failures, the reference is released
+ * either in cfg80211_roamed_bss() or in __cfg80211_romed(), Otherwise,
+ * it will be released while diconneting from the current bss.
+ */
+void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss,
+ const u8 *req_ie, size_t req_ie_len,
+ const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp);
+
+/**
* cfg80211_disconnected - notify cfg80211 that connection was dropped
*
* @dev: network device
@@ -3090,6 +3237,85 @@ void cfg80211_cqm_pktloss_notify(struct net_device *dev,
void cfg80211_gtk_rekey_notify(struct net_device *dev, const u8 *bssid,
const u8 *replay_ctr, gfp_t gfp);
+/**
+ * cfg80211_pmksa_candidate_notify - notify about PMKSA caching candidate
+ * @dev: network device
+ * @index: candidate index (the smaller the index, the higher the priority)
+ * @bssid: BSSID of AP
+ * @preauth: Whether AP advertises support for RSN pre-authentication
+ * @gfp: allocation flags
+ */
+void cfg80211_pmksa_candidate_notify(struct net_device *dev, int index,
+ const u8 *bssid, bool preauth, gfp_t gfp);
+
+/**
+ * cfg80211_rx_spurious_frame - inform userspace about a spurious frame
+ * @dev: The device the frame matched to
+ * @addr: the transmitter address
+ * @gfp: context flags
+ *
+ * This function is used in AP mode (only!) to inform userspace that
+ * a spurious class 3 frame was received, to be able to deauth the
+ * sender.
+ * Returns %true if the frame was passed to userspace (or this failed
+ * for a reason other than not having a subscription.)
+ */
+bool cfg80211_rx_spurious_frame(struct net_device *dev,
+ const u8 *addr, gfp_t gfp);
+
+/**
+ * cfg80211_rx_unexpected_4addr_frame - inform about unexpected WDS frame
+ * @dev: The device the frame matched to
+ * @addr: the transmitter address
+ * @gfp: context flags
+ *
+ * This function is used in AP mode (only!) to inform userspace that
+ * an associated station sent a 4addr frame but that wasn't expected.
+ * It is allowed and desirable to send this event only once for each
+ * station to avoid event flooding.
+ * Returns %true if the frame was passed to userspace (or this failed
+ * for a reason other than not having a subscription.)
+ */
+bool cfg80211_rx_unexpected_4addr_frame(struct net_device *dev,
+ const u8 *addr, gfp_t gfp);
+
+/**
+ * cfg80211_probe_status - notify userspace about probe status
+ * @dev: the device the probe was sent on
+ * @addr: the address of the peer
+ * @cookie: the cookie filled in @probe_client previously
+ * @acked: indicates whether probe was acked or not
+ * @gfp: allocation flags
+ */
+void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
+ u64 cookie, bool acked, gfp_t gfp);
+
+/**
+ * cfg80211_report_obss_beacon - report beacon from other APs
+ * @wiphy: The wiphy that received the beacon
+ * @frame: the frame
+ * @len: length of the frame
+ * @freq: frequency the frame was received on
+ * @gfp: allocation flags
+ *
+ * Use this function to report to userspace when a beacon was
+ * received. It is not useful to call this when there is no
+ * netdev that is in AP/GO mode.
+ */
+void cfg80211_report_obss_beacon(struct wiphy *wiphy,
+ const u8 *frame, size_t len,
+ int freq, 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
+ */
+int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/dcbevent.h b/include/net/dcbevent.h
index bc1e7ef4017..443626ed4cb 100644
--- a/include/net/dcbevent.h
+++ b/include/net/dcbevent.h
@@ -24,8 +24,26 @@ enum dcbevent_notif_type {
DCB_APP_EVENT = 1,
};
+#ifdef CONFIG_DCB
extern int register_dcbevent_notifier(struct notifier_block *nb);
extern int unregister_dcbevent_notifier(struct notifier_block *nb);
extern int call_dcbevent_notifiers(unsigned long val, void *v);
+#else
+static inline int
+register_dcbevent_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int unregister_dcbevent_notifier(struct notifier_block *nb)
+{
+ return 0;
+}
+
+static inline int call_dcbevent_notifiers(unsigned long val, void *v)
+{
+ return 0;
+}
+#endif /* CONFIG_DCB */
#endif
diff --git a/include/net/dcbnl.h b/include/net/dcbnl.h
index f5aa39997f0..2cd66d0be34 100644
--- a/include/net/dcbnl.h
+++ b/include/net/dcbnl.h
@@ -23,9 +23,10 @@
#include <linux/dcbnl.h>
struct dcb_app_type {
- char name[IFNAMSIZ];
+ int ifindex;
struct dcb_app app;
struct list_head list;
+ u8 dcbx;
};
int dcb_setapp(struct net_device *, struct dcb_app *);
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 839f768f9e3..7828ebf99ee 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -11,6 +11,11 @@
#ifndef __LINUX_NET_DSA_H
#define __LINUX_NET_DSA_H
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+
#define DSA_MAX_SWITCHES 4
#define DSA_MAX_PORTS 12
@@ -54,8 +59,143 @@ struct dsa_platform_data {
struct dsa_chip_data *chip;
};
-extern bool dsa_uses_dsa_tags(void *dsa_ptr);
-extern bool dsa_uses_trailer_tags(void *dsa_ptr);
+struct dsa_switch_tree {
+ /*
+ * Configuration data for the platform device that owns
+ * this dsa switch tree instance.
+ */
+ struct dsa_platform_data *pd;
+
+ /*
+ * Reference to network device to use, and which tagging
+ * protocol to use.
+ */
+ struct net_device *master_netdev;
+ __be16 tag_protocol;
+
+ /*
+ * The switch and port to which the CPU is attached.
+ */
+ s8 cpu_switch;
+ s8 cpu_port;
+
+ /*
+ * Link state polling.
+ */
+ int link_poll_needed;
+ struct work_struct link_poll_work;
+ struct timer_list link_poll_timer;
+
+ /*
+ * Data for the individual switch chips.
+ */
+ struct dsa_switch *ds[DSA_MAX_SWITCHES];
+};
+
+struct dsa_switch {
+ /*
+ * Parent switch tree, and switch index.
+ */
+ struct dsa_switch_tree *dst;
+ int index;
+
+ /*
+ * Configuration data for this switch.
+ */
+ struct dsa_chip_data *pd;
+
+ /*
+ * The used switch driver.
+ */
+ struct dsa_switch_driver *drv;
+
+ /*
+ * Reference to mii bus to use.
+ */
+ struct mii_bus *master_mii_bus;
+
+ /*
+ * Slave mii_bus and devices for the individual ports.
+ */
+ u32 dsa_port_mask;
+ u32 phys_port_mask;
+ struct mii_bus *slave_mii_bus;
+ struct net_device *ports[DSA_MAX_PORTS];
+};
+
+static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p)
+{
+ return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port);
+}
+
+static inline u8 dsa_upstream_port(struct dsa_switch *ds)
+{
+ struct dsa_switch_tree *dst = ds->dst;
+
+ /*
+ * If this is the root switch (i.e. the switch that connects
+ * to the CPU), return the cpu port number on this switch.
+ * Else return the (DSA) port number that connects to the
+ * switch that is one hop closer to the cpu.
+ */
+ if (dst->cpu_switch == ds->index)
+ return dst->cpu_port;
+ else
+ return ds->pd->rtable[dst->cpu_switch];
+}
+
+struct dsa_switch_driver {
+ struct list_head list;
+
+ __be16 tag_protocol;
+ int priv_size;
+
+ /*
+ * Probing and setup.
+ */
+ char *(*probe)(struct mii_bus *bus, int sw_addr);
+ int (*setup)(struct dsa_switch *ds);
+ int (*set_addr)(struct dsa_switch *ds, u8 *addr);
+
+ /*
+ * Access to the switch's PHY registers.
+ */
+ int (*phy_read)(struct dsa_switch *ds, int port, int regnum);
+ int (*phy_write)(struct dsa_switch *ds, int port,
+ int regnum, u16 val);
+
+ /*
+ * Link state polling and IRQ handling.
+ */
+ void (*poll_link)(struct dsa_switch *ds);
+
+ /*
+ * ethtool hardware statistics.
+ */
+ void (*get_strings)(struct dsa_switch *ds, int port, uint8_t *data);
+ void (*get_ethtool_stats)(struct dsa_switch *ds,
+ int port, uint64_t *data);
+ int (*get_sset_count)(struct dsa_switch *ds);
+};
+
+void register_switch_driver(struct dsa_switch_driver *type);
+void unregister_switch_driver(struct dsa_switch_driver *type);
+
+/*
+ * The original DSA tag format and some other tag formats have no
+ * ethertype, which means that we need to add a little hack to the
+ * networking receive path to make sure that received frames get
+ * the right ->protocol assigned to them when one of those tag
+ * formats is in use.
+ */
+static inline bool dsa_uses_dsa_tags(struct dsa_switch_tree *dst)
+{
+ return !!(dst->tag_protocol == htons(ETH_P_DSA));
+}
+static inline bool dsa_uses_trailer_tags(struct dsa_switch_tree *dst)
+{
+ return !!(dst->tag_protocol == htons(ETH_P_TRAILER));
+}
#endif
diff --git a/include/net/dst.h b/include/net/dst.h
index 13d507d69dd..344c8dd0287 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -53,6 +53,7 @@ struct dst_entry {
#define DST_NOHASH 0x0008
#define DST_NOCACHE 0x0010
#define DST_NOCOUNT 0x0020
+#define DST_NOPEER 0x0040
short error;
short obsolete;
@@ -86,12 +87,12 @@ struct dst_entry {
};
};
-static inline struct neighbour *dst_get_neighbour(struct dst_entry *dst)
+static inline struct neighbour *dst_get_neighbour_noref(struct dst_entry *dst)
{
return rcu_dereference(dst->_neighbour);
}
-static inline struct neighbour *dst_get_neighbour_raw(struct dst_entry *dst)
+static inline struct neighbour *dst_get_neighbour_noref_raw(struct dst_entry *dst)
{
return rcu_dereference_raw(dst->_neighbour);
}
@@ -205,12 +206,7 @@ dst_feature(const struct dst_entry *dst, u32 feature)
static inline u32 dst_mtu(const struct dst_entry *dst)
{
- u32 mtu = dst_metric_raw(dst, RTAX_MTU);
-
- if (!mtu)
- mtu = dst->ops->default_mtu(dst);
-
- return mtu;
+ return dst->ops->mtu(dst);
}
/* RTT metrics are stored in milliseconds for user ABI, but used as jiffies */
@@ -325,7 +321,14 @@ static inline void skb_dst_force(struct sk_buff *skb)
static inline void __skb_tunnel_rx(struct sk_buff *skb, struct net_device *dev)
{
skb->dev = dev;
- skb->rxhash = 0;
+
+ /*
+ * Clear rxhash so that we can recalulate the hash for the
+ * encapsulated packet, unless we have already determine the hash
+ * over the L4 4-tuple.
+ */
+ if (!skb->l4_rxhash)
+ skb->rxhash = 0;
skb_set_queue_mapping(skb, 0);
skb_dst_drop(skb);
nf_reset(skb);
@@ -390,7 +393,7 @@ static inline void dst_confirm(struct dst_entry *dst)
struct neighbour *n;
rcu_read_lock();
- n = dst_get_neighbour(dst);
+ n = dst_get_neighbour_noref(dst);
neigh_confirm(n);
rcu_read_unlock();
}
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index 9adb99845a5..e1c2ee0eef4 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -17,7 +17,7 @@ struct dst_ops {
int (*gc)(struct dst_ops *ops);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
unsigned int (*default_advmss)(const struct dst_entry *);
- unsigned int (*default_mtu)(const struct dst_entry *);
+ unsigned int (*mtu)(const struct dst_entry *);
u32 * (*cow_metrics)(struct dst_entry *, unsigned long);
void (*destroy)(struct dst_entry *);
void (*ifdown)(struct dst_entry *,
diff --git a/include/net/flow.h b/include/net/flow.h
index a09447749e2..da1f064a81b 100644
--- a/include/net/flow.h
+++ b/include/net/flow.h
@@ -59,8 +59,11 @@ struct flowi4 {
#define flowi4_proto __fl_common.flowic_proto
#define flowi4_flags __fl_common.flowic_flags
#define flowi4_secid __fl_common.flowic_secid
- __be32 daddr;
+
+ /* (saddr,daddr) must be grouped, same order as in IP header */
__be32 saddr;
+ __be32 daddr;
+
union flowi_uli uli;
#define fl4_sport uli.ports.sport
#define fl4_dport uli.ports.dport
@@ -207,6 +210,7 @@ extern struct flow_cache_object *flow_cache_lookup(
u8 dir, flow_resolve_t resolver, void *ctx);
extern void flow_cache_flush(void);
+extern void flow_cache_flush_deferred(void);
extern atomic_t flow_cache_genid;
#endif
diff --git a/include/net/flow_keys.h b/include/net/flow_keys.h
new file mode 100644
index 00000000000..80461c1ae9e
--- /dev/null
+++ b/include/net/flow_keys.h
@@ -0,0 +1,16 @@
+#ifndef _NET_FLOW_KEYS_H
+#define _NET_FLOW_KEYS_H
+
+struct flow_keys {
+ /* (src,dst) must be grouped, in the same way than in IP header */
+ __be32 src;
+ __be32 dst;
+ union {
+ __be32 ports;
+ __be16 port16[2];
+ };
+ u8 ip_proto;
+};
+
+extern bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow);
+#endif
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index 82d8d09faa4..7db32995ccd 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -128,6 +128,8 @@ extern int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
extern void genl_unregister_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
+extern void genl_notify(struct sk_buff *skb, struct net *net, u32 pid,
+ u32 group, struct nlmsghdr *nlh, gfp_t flags);
/**
* genlmsg_put - Add generic netlink header to netlink message
diff --git a/include/net/icmp.h b/include/net/icmp.h
index f0698b955b7..75d61564907 100644
--- a/include/net/icmp.h
+++ b/include/net/icmp.h
@@ -31,8 +31,8 @@ struct icmp_err {
extern const struct icmp_err icmp_err_convert[];
#define ICMP_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmp_statistics, field)
#define ICMP_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.icmp_statistics, field)
-#define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS((net)->mib.icmpmsg_statistics, field+256)
-#define ICMPMSGIN_INC_STATS_BH(net, field) SNMP_INC_STATS_BH((net)->mib.icmpmsg_statistics, field)
+#define ICMPMSGOUT_INC_STATS(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field+256)
+#define ICMPMSGIN_INC_STATS_BH(net, field) SNMP_INC_STATS_ATOMIC_LONG((net)->mib.icmpmsg_statistics, field)
struct dst_entry;
struct net_proto_family;
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index b0be5fb9de1..71392545d0a 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -251,6 +251,7 @@ enum ieee80211_radiotap_type {
* retries */
#define IEEE80211_RADIOTAP_F_TX_CTS 0x0002 /* used cts 'protection' */
#define IEEE80211_RADIOTAP_F_TX_RTS 0x0004 /* used rts/cts handshake */
+#define IEEE80211_RADIOTAP_F_TX_NOACK 0x0008 /* don't expect an ack */
/* For IEEE80211_RADIOTAP_MCS */
@@ -270,14 +271,6 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10
-/* Ugly macro to convert literal channel numbers into their mhz equivalents
- * There are certianly some conditions that will break this (like feeding it '30')
- * but they shouldn't arise since nothing talks on channel 30. */
-#define ieee80211chan2mhz(x) \
- (((x) <= 14) ? \
- (((x) == 14) ? 2484 : ((x) * 5) + 2407) : \
- ((x) + 1000) * 5)
-
/* helpers */
static inline int ieee80211_get_radiotap_len(unsigned char *data)
{
diff --git a/include/net/ieee802154.h b/include/net/ieee802154.h
index d52685defb1..ee59f8b188d 100644
--- a/include/net/ieee802154.h
+++ b/include/net/ieee802154.h
@@ -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 NET_IEEE802154_H
#define NET_IEEE802154_H
+#define IEEE802154_MTU 127
+
#define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */
#define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */
#define IEEE802154_FC_TYPE_ACK 0x2 /* Frame is acknowledgment */
@@ -56,6 +59,9 @@
(((x) & IEEE802154_FC_DAMODE_MASK) >> IEEE802154_FC_DAMODE_SHIFT)
+/* MAC footer size */
+#define IEEE802154_MFR_SIZE 2 /* 2 octets */
+
/* MAC's Command Frames Identifiers */
#define IEEE802154_CMD_ASSOCIATION_REQ 0x01
#define IEEE802154_CMD_ASSOCIATION_RESP 0x02
diff --git a/include/net/if_inet6.h b/include/net/if_inet6.h
index 11cf373970a..51a7031b4aa 100644
--- a/include/net/if_inet6.h
+++ b/include/net/if_inet6.h
@@ -41,6 +41,7 @@ struct inet6_ifaddr {
struct in6_addr addr;
__u32 prefix_len;
+ /* In seconds, relative to tstamp. Expiry is at tstamp + HZ * lft. */
__u32 valid_lft;
__u32 prefered_lft;
atomic_t refcnt;
diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h
index e46674d5dae..00cbb4384c7 100644
--- a/include/net/inet6_hashtables.h
+++ b/include/net/inet6_hashtables.h
@@ -15,7 +15,7 @@
#define _INET6_HASHTABLES_H
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
#include <linux/in6.h>
#include <linux/ipv6.h>
#include <linux/types.h>
@@ -110,5 +110,5 @@ extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo
const struct in6_addr *saddr, const __be16 sport,
const struct in6_addr *daddr, const __be16 dport,
const int dif);
-#endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */
+#endif /* IS_ENABLED(CONFIG_IPV6) */
#endif /* _INET6_HASHTABLES_H */
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index e6db62e756d..dbf9aab34c8 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -143,9 +143,9 @@ static inline void *inet_csk_ca(const struct sock *sk)
return (void *)inet_csk(sk)->icsk_ca_priv;
}
-extern struct sock *inet_csk_clone(struct sock *sk,
- const struct request_sock *req,
- const gfp_t priority);
+extern struct sock *inet_csk_clone_lock(const struct sock *sk,
+ const struct request_sock *req,
+ const gfp_t priority);
enum inet_csk_ack_state_t {
ICSK_ACK_SCHED = 1,
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
index 2fa8d1341a0..2fa14691869 100644
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -30,6 +30,14 @@ static inline int INET_ECN_is_capable(__u8 dsfield)
return dsfield & INET_ECN_ECT_0;
}
+/*
+ * RFC 3168 9.1.1
+ * The full-functionality option for ECN encapsulation is to copy the
+ * ECN codepoint of the inside header to the outside header on
+ * encapsulation if the inside header is not-ECT or ECT, and to set the
+ * ECN codepoint of the outside header to ECT(0) if the ECN codepoint of
+ * the inside header is CE.
+ */
static inline __u8 INET_ECN_encapsulate(__u8 outer, __u8 inner)
{
outer &= ~INET_ECN_MASK;
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index b897d6e6d0a..e3e405106af 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -31,6 +31,7 @@
/** struct ip_options - IP Options
*
* @faddr - Saved first hop address
+ * @nexthop - Saved nexthop address in LSRR and SSRR
* @is_data - Options in __data, rather than skb
* @is_strictroute - Strict source route
* @srr_is_hit - Packet destination addr was our one
@@ -41,6 +42,7 @@
*/
struct ip_options {
__be32 faddr;
+ __be32 nexthop;
unsigned char optlen;
unsigned char srr;
unsigned char rr;
@@ -69,7 +71,7 @@ struct ip_options_data {
struct inet_request_sock {
struct request_sock req;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
u16 inet6_rsk_offset;
#endif
__be16 loc_port;
@@ -137,7 +139,7 @@ struct rtable;
struct inet_sock {
/* sk and pinet6 has to be the first two members of inet_sock */
struct sock sk;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct ipv6_pinfo *pinet6;
#endif
/* Socket demultiplex comparisons on incoming packets. */
@@ -186,7 +188,7 @@ static inline void __inet_sk_copy_descendant(struct sock *sk_to,
memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1,
sk_from->sk_prot->obj_size - ancestor_size);
}
-#if !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE))
+#if !(IS_ENABLED(CONFIG_IPV6))
static inline void inet_sk_copy_descendant(struct sock *sk_to,
const struct sock *sk_from)
{
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index f1a770977c4..ba52c830a7a 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -18,7 +18,6 @@
#include <linux/kmemcheck.h>
#include <linux/list.h>
-#include <linux/module.h>
#include <linux/timer.h>
#include <linux/types.h>
#include <linux/workqueue.h>
@@ -126,13 +125,15 @@ struct inet_timewait_sock {
/* And these are ours. */
unsigned int tw_ipv6only : 1,
tw_transparent : 1,
- tw_pad : 14, /* 14 bits hole */
+ tw_pad : 6, /* 6 bits hole */
+ tw_tos : 8,
tw_ipv6_offset : 16;
kmemcheck_bitfield_end(flags);
unsigned long tw_ttd;
struct inet_bind_bucket *tw_tb;
struct hlist_node tw_death_node;
};
+#define tw_tclass tw_tos
static inline void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
struct hlist_nulls_head *list)
@@ -217,20 +218,12 @@ extern void inet_twsk_purge(struct inet_hashinfo *hashinfo,
static inline
struct net *twsk_net(const struct inet_timewait_sock *twsk)
{
-#ifdef CONFIG_NET_NS
- return rcu_dereference_raw(twsk->tw_net); /* protected by locking, */
- /* reference counting, */
- /* initialization, or RCU. */
-#else
- return &init_net;
-#endif
+ return read_pnet(&twsk->tw_net);
}
static inline
void twsk_net_set(struct inet_timewait_sock *twsk, struct net *net)
{
-#ifdef CONFIG_NET_NS
- rcu_assign_pointer(twsk->tw_net, net);
-#endif
+ write_pnet(&twsk->tw_net, net);
}
#endif /* _INET_TIMEWAIT_SOCK_ */
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 78c83e62218..06b795dd590 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -35,6 +35,7 @@ struct inet_peer {
u32 metrics[RTAX_MAX];
u32 rate_tokens; /* rate limiting for ICMP */
+ int redirect_genid;
unsigned long rate_last;
unsigned long pmtu_expires;
u32 pmtu_orig;
@@ -86,7 +87,7 @@ static inline struct inet_peer *inet_getpeer_v6(const struct in6_addr *v6daddr,
{
struct inetpeer_addr daddr;
- ipv6_addr_copy((struct in6_addr *)daddr.addr.a6, v6daddr);
+ *(struct in6_addr *)daddr.addr.a6 = *v6daddr;
daddr.family = AF_INET6;
return inet_getpeer(&daddr, create);
}
diff --git a/include/net/ip.h b/include/net/ip.h
index aa76c7a4d9c..775009f9eab 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -165,6 +165,7 @@ struct ip_reply_arg {
int csumoffset; /* u16 offset of csum in iov[0].iov_base */
/* -1 if not needed */
int bound_dev_if;
+ u8 tos;
};
#define IP_REPLY_ARG_NOSRCCHECK 1
@@ -175,7 +176,7 @@ static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
}
void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr,
- struct ip_reply_arg *arg, unsigned int len);
+ const struct ip_reply_arg *arg, unsigned int len);
struct ipv4_config {
int log_martians;
@@ -352,14 +353,14 @@ static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast,
memcpy(buf, &naddr, sizeof(naddr));
}
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
#include <linux/ipv6.h>
#endif
static __inline__ void inet_reset_saddr(struct sock *sk)
{
inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
if (sk->sk_family == PF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
@@ -378,7 +379,7 @@ static inline int sk_mc_loop(struct sock *sk)
switch (sk->sk_family) {
case AF_INET:
return inet_sk(sk)->mc_loop;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
case AF_INET6:
return inet6_sk(sk)->mc_loop;
#endif
@@ -406,9 +407,18 @@ enum ip_defrag_users {
IP_DEFRAG_VS_OUT,
IP_DEFRAG_VS_FWD,
IP_DEFRAG_AF_PACKET,
+ IP_DEFRAG_MACVLAN,
};
int ip_defrag(struct sk_buff *skb, u32 user);
+#ifdef CONFIG_INET
+struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user);
+#else
+static inline struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user)
+{
+ return skb;
+}
+#endif
int ip_frag_mem(struct net *net);
int ip_frag_nqueues(struct net *net);
@@ -440,7 +450,7 @@ extern int ip_options_rcv_srr(struct sk_buff *skb);
* Functions provided by ip_sockglue.c
*/
-extern int ip_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
+extern void ipv4_pktinfo_prepare(struct sk_buff *skb);
extern void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb);
extern int ip_cmsg_send(struct net *net,
struct msghdr *msg, struct ipcm_cookie *ipc);
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 5735a0f979c..b26bb810198 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -86,9 +86,6 @@ struct fib6_table;
struct rt6_info {
struct dst_entry dst;
-#define rt6i_dev dst.dev
-#define rt6i_expires dst.expires
-
/*
* Tail elements of dst_entry (__refcnt etc.)
* and these elements (rarely used in hot path) are in
@@ -202,6 +199,10 @@ struct fib6_node *fib6_locate(struct fib6_node *root,
const struct in6_addr *daddr, int dst_len,
const struct in6_addr *saddr, int src_len);
+extern void fib6_clean_all_ro(struct net *net,
+ int (*func)(struct rt6_info *, void *arg),
+ int prune, void *arg);
+
extern void fib6_clean_all(struct net *net,
int (*func)(struct rt6_info *, void *arg),
int prune, void *arg);
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5e91b72fc71..2ad92ca4e6f 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -70,6 +70,8 @@ extern void ip6_route_input(struct sk_buff *skb);
extern struct dst_entry * ip6_route_output(struct net *net,
const struct sock *sk,
struct flowi6 *fl6);
+extern struct dst_entry * ip6_route_lookup(struct net *net,
+ struct flowi6 *fl6, int flags);
extern int ip6_route_init(void);
extern void ip6_route_cleanup(void);
@@ -95,14 +97,14 @@ extern struct rt6_info *rt6_lookup(struct net *net,
extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev,
struct neighbour *neigh,
- const struct in6_addr *addr);
+ struct flowi6 *fl6);
extern int icmp6_dst_gc(void);
extern void fib6_force_start_gc(struct net *net);
extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
const struct in6_addr *addr,
- int anycast);
+ bool anycast);
extern int ip6_dst_hoplimit(struct dst_entry *dst);
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 8fa4430f99c..ebe517f2da9 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -21,7 +21,7 @@
#include <linux/netfilter.h> /* for union nf_inet_addr */
#include <linux/ip.h>
#include <linux/ipv6.h> /* for struct ipv6hdr */
-#include <net/ipv6.h> /* for ipv6_addr_copy */
+#include <net/ipv6.h>
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
#include <net/netfilter/nf_conntrack.h>
#endif
@@ -119,8 +119,8 @@ ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr)
const struct ipv6hdr *iph = nh;
iphdr->len = sizeof(struct ipv6hdr);
iphdr->protocol = iph->nexthdr;
- ipv6_addr_copy(&iphdr->saddr.in6, &iph->saddr);
- ipv6_addr_copy(&iphdr->daddr.in6, &iph->daddr);
+ iphdr->saddr.in6 = iph->saddr;
+ iphdr->daddr.in6 = iph->daddr;
} else
#endif
{
@@ -137,7 +137,7 @@ static inline void ip_vs_addr_copy(int af, union nf_inet_addr *dst,
{
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
- ipv6_addr_copy(&dst->in6, &src->in6);
+ dst->in6 = src->in6;
else
#endif
dst->ip = src->ip;
@@ -425,9 +425,9 @@ struct ip_vs_protocol {
const char *(*state_name)(int state);
- int (*state_transition)(struct ip_vs_conn *cp, int direction,
- const struct sk_buff *skb,
- struct ip_vs_proto_data *pd);
+ void (*state_transition)(struct ip_vs_conn *cp, int direction,
+ const struct sk_buff *skb,
+ struct ip_vs_proto_data *pd);
int (*register_app)(struct net *net, struct ip_vs_app *inc);
@@ -1126,17 +1126,16 @@ int unregister_ip_vs_pe(struct ip_vs_pe *pe);
struct ip_vs_pe *ip_vs_pe_getbyname(const char *name);
struct ip_vs_pe *__ip_vs_pe_getbyname(const char *pe_name);
-static inline void ip_vs_pe_get(const struct ip_vs_pe *pe)
-{
- if (pe && pe->module)
+/*
+ * Use a #define to avoid all of module.h just for these trivial ops
+ */
+#define ip_vs_pe_get(pe) \
+ if (pe && pe->module) \
__module_get(pe->module);
-}
-static inline void ip_vs_pe_put(const struct ip_vs_pe *pe)
-{
- if (pe && pe->module)
+#define ip_vs_pe_put(pe) \
+ if (pe && pe->module) \
module_put(pe->module);
-}
/*
* IPVS protocol functions (from ip_vs_proto.c)
@@ -1208,7 +1207,7 @@ extern void ip_vs_control_cleanup(void);
extern struct ip_vs_dest *
ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr,
__be16 dport, const union nf_inet_addr *vaddr, __be16 vport,
- __u16 protocol, __u32 fwmark);
+ __u16 protocol, __u32 fwmark, __u32 flags);
extern struct ip_vs_dest *ip_vs_try_bind_dest(struct ip_vs_conn *cp);
@@ -1378,7 +1377,7 @@ static inline int ip_vs_conntrack_enabled(struct netns_ipvs *ipvs)
extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
int outin);
-extern int ip_vs_confirm_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp);
+extern int ip_vs_confirm_conntrack(struct sk_buff *skb);
extern void ip_vs_nfct_expect_related(struct sk_buff *skb, struct nf_conn *ct,
struct ip_vs_conn *cp, u_int8_t proto,
const __be16 port, int from_rs);
@@ -1396,8 +1395,7 @@ static inline void ip_vs_update_conntrack(struct sk_buff *skb,
{
}
-static inline int ip_vs_confirm_conntrack(struct sk_buff *skb,
- struct ip_vs_conn *cp)
+static inline int ip_vs_confirm_conntrack(struct sk_buff *skb)
{
return NF_ACCEPT;
}
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 3b5ac1fbff3..e4170a22fc6 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -132,6 +132,15 @@ extern struct ctl_path net_ipv6_ctl_path[];
SNMP_INC_STATS##modifier((net)->mib.statname##_statistics, (field));\
})
+/* per device and per net counters are atomic_long_t */
+#define _DEVINC_ATOMIC_ATOMIC(net, statname, idev, field) \
+({ \
+ struct inet6_dev *_idev = (idev); \
+ if (likely(_idev != NULL)) \
+ SNMP_INC_STATS_ATOMIC_LONG((_idev)->stats.statname##dev, (field)); \
+ SNMP_INC_STATS_ATOMIC_LONG((net)->mib.statname##_statistics, (field));\
+})
+
#define _DEVADD(net, statname, modifier, idev, field, val) \
({ \
struct inet6_dev *_idev = (idev); \
@@ -168,11 +177,11 @@ extern struct ctl_path net_ipv6_ctl_path[];
_DEVINCATOMIC(net, icmpv6, _BH, idev, field)
#define ICMP6MSGOUT_INC_STATS(net, idev, field) \
- _DEVINCATOMIC(net, icmpv6msg, , idev, field +256)
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
#define ICMP6MSGOUT_INC_STATS_BH(net, idev, field) \
- _DEVINCATOMIC(net, icmpv6msg, _BH, idev, field +256)
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field +256)
#define ICMP6MSGIN_INC_STATS_BH(net, idev, field) \
- _DEVINCATOMIC(net, icmpv6msg, _BH, idev, field)
+ _DEVINC_ATOMIC_ATOMIC(net, icmpv6msg, idev, field)
struct ip6_ra_chain {
struct ip6_ra_chain *next;
@@ -300,11 +309,6 @@ ipv6_masked_addr_cmp(const struct in6_addr *a1, const struct in6_addr *m,
((a1->s6_addr32[3] ^ a2->s6_addr32[3]) & m->s6_addr32[3]));
}
-static inline void ipv6_addr_copy(struct in6_addr *a1, const struct in6_addr *a2)
-{
- memcpy(a1, a2, sizeof(struct in6_addr));
-}
-
static inline void ipv6_addr_prefix(struct in6_addr *pfx,
const struct in6_addr *addr,
int plen)
@@ -486,7 +490,8 @@ extern int ip6_rcv_finish(struct sk_buff *skb);
extern int ip6_xmit(struct sock *sk,
struct sk_buff *skb,
struct flowi6 *fl6,
- struct ipv6_txoptions *opt);
+ struct ipv6_txoptions *opt,
+ int tclass);
extern int ip6_nd_hdr(struct sock *sk,
struct sk_buff *skb,
@@ -553,7 +558,7 @@ extern void ipv6_push_frag_opts(struct sk_buff *skb,
u8 *proto);
extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
- u8 *nexthdrp);
+ u8 *nexthdrp, __be16 *frag_offp);
extern int ipv6_ext_hdr(u8 nexthdr);
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
index f82a1e87737..0954ec95915 100644
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -14,6 +14,7 @@
#include <linux/list.h>
#include <linux/poll.h>
#include <linux/socket.h>
+#include <net/iucv/iucv.h>
#ifndef AF_IUCV
#define AF_IUCV 32
@@ -26,13 +27,13 @@ enum {
IUCV_OPEN,
IUCV_BOUND,
IUCV_LISTEN,
- IUCV_SEVERED,
IUCV_DISCONN,
IUCV_CLOSING,
IUCV_CLOSED
};
#define IUCV_QUEUELEN_DEFAULT 65535
+#define IUCV_HIPER_MSGLIM_DEFAULT 128
#define IUCV_CONN_TIMEOUT (HZ * 40)
#define IUCV_DISCONN_TIMEOUT (HZ * 2)
#define IUCV_CONN_IDLE_TIMEOUT (HZ * 60)
@@ -57,8 +58,51 @@ struct sock_msg_q {
spinlock_t lock;
};
+#define AF_IUCV_FLAG_ACK 0x1
+#define AF_IUCV_FLAG_SYN 0x2
+#define AF_IUCV_FLAG_FIN 0x4
+#define AF_IUCV_FLAG_WIN 0x8
+
+struct af_iucv_trans_hdr {
+ u16 magic;
+ u8 version;
+ u8 flags;
+ u16 window;
+ char destNodeID[8];
+ char destUserID[8];
+ char destAppName[16];
+ char srcNodeID[8];
+ char srcUserID[8];
+ char srcAppName[16]; /* => 70 bytes */
+ struct iucv_message iucv_hdr; /* => 33 bytes */
+ u8 pad; /* total 104 bytes */
+} __packed;
+
+enum iucv_tx_notify {
+ /* transmission of skb is completed and was successful */
+ TX_NOTIFY_OK = 0,
+ /* target is unreachable */
+ TX_NOTIFY_UNREACHABLE = 1,
+ /* transfer pending queue full */
+ TX_NOTIFY_TPQFULL = 2,
+ /* general error */
+ TX_NOTIFY_GENERALERROR = 3,
+ /* transmission of skb is pending - may interleave
+ * with TX_NOTIFY_DELAYED_* */
+ TX_NOTIFY_PENDING = 4,
+ /* transmission of skb was done successfully (delayed) */
+ TX_NOTIFY_DELAYED_OK = 5,
+ /* target unreachable (detected delayed) */
+ TX_NOTIFY_DELAYED_UNREACHABLE = 6,
+ /* general error (detected delayed) */
+ TX_NOTIFY_DELAYED_GENERALERROR = 7,
+};
+
#define iucv_sk(__sk) ((struct iucv_sock *) __sk)
+#define AF_IUCV_TRANS_IUCV 0
+#define AF_IUCV_TRANS_HIPER 1
+
struct iucv_sock {
struct sock sk;
char src_user_id[8];
@@ -75,6 +119,13 @@ struct iucv_sock {
unsigned int send_tag;
u8 flags;
u16 msglimit;
+ u16 msglimit_peer;
+ atomic_t msg_sent;
+ atomic_t msg_recv;
+ atomic_t pendings;
+ int transport;
+ void (*sk_txnotify)(struct sk_buff *skb,
+ enum iucv_tx_notify n);
};
/* iucv socket options (SOL_IUCV) */
@@ -94,7 +145,6 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock,
poll_table *wait);
void iucv_sock_link(struct iucv_sock_list *l, struct sock *s);
void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s);
-int iucv_sock_wait_cnt(struct sock *sk, unsigned long timeo);
void iucv_accept_enqueue(struct sock *parent, struct sock *sk);
void iucv_accept_unlink(struct sock *sk);
struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock);
diff --git a/include/net/iucv/iucv.h b/include/net/iucv/iucv.h
index 1121baa9f69..0894ced3195 100644
--- a/include/net/iucv/iucv.h
+++ b/include/net/iucv/iucv.h
@@ -120,7 +120,7 @@ struct iucv_message {
u32 reply_size;
u8 rmmsg[8];
u8 flags;
-};
+} __packed;
/*
* struct iucv_handler
@@ -459,3 +459,37 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
u8 flags, u32 srccls, void *buffer, size_t size,
void *answer, size_t asize, size_t *residual);
+
+struct iucv_interface {
+ int (*message_receive)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, void *buffer, size_t size, size_t *residual);
+ int (*__message_receive)(struct iucv_path *path,
+ struct iucv_message *msg, u8 flags, void *buffer, size_t size,
+ size_t *residual);
+ int (*message_reply)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, void *reply, size_t size);
+ int (*message_reject)(struct iucv_path *path, struct iucv_message *msg);
+ int (*message_send)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, u32 srccls, void *buffer, size_t size);
+ int (*__message_send)(struct iucv_path *path, struct iucv_message *msg,
+ u8 flags, u32 srccls, void *buffer, size_t size);
+ int (*message_send2way)(struct iucv_path *path,
+ struct iucv_message *msg, u8 flags, u32 srccls, void *buffer,
+ size_t size, void *answer, size_t asize, size_t *residual);
+ int (*message_purge)(struct iucv_path *path, struct iucv_message *msg,
+ u32 srccls);
+ int (*path_accept)(struct iucv_path *path, struct iucv_handler *handler,
+ u8 userdata[16], void *private);
+ int (*path_connect)(struct iucv_path *path,
+ struct iucv_handler *handler,
+ u8 userid[8], u8 system[8], u8 userdata[16], void *private);
+ int (*path_quiesce)(struct iucv_path *path, u8 userdata[16]);
+ int (*path_resume)(struct iucv_path *path, u8 userdata[16]);
+ int (*path_sever)(struct iucv_path *path, u8 userdata[16]);
+ int (*iucv_register)(struct iucv_handler *handler, int smp);
+ void (*iucv_unregister)(struct iucv_handler *handler, int smp);
+ struct bus_type *bus;
+ struct device *root;
+};
+
+extern struct iucv_interface iucv_if;
diff --git a/include/net/lapb.h b/include/net/lapb.h
index 96cb5ddaa9f..fd2bf572ee1 100644
--- a/include/net/lapb.h
+++ b/include/net/lapb.h
@@ -95,7 +95,7 @@ struct lapb_cb {
struct sk_buff_head write_queue;
struct sk_buff_head ack_queue;
unsigned char window;
- struct lapb_register_struct callbacks;
+ const struct lapb_register_struct *callbacks;
/* FRMR control information */
struct lapb_frame frmr_data;
diff --git a/include/net/lib80211.h b/include/net/lib80211.h
index b95bbb083ee..d178c26a555 100644
--- a/include/net/lib80211.h
+++ b/include/net/lib80211.h
@@ -25,7 +25,6 @@
#include <linux/types.h>
#include <linux/list.h>
-#include <linux/module.h>
#include <linux/atomic.h>
#include <linux/if.h>
#include <linux/skbuff.h>
@@ -42,6 +41,8 @@ enum {
IEEE80211_CRYPTO_TKIP_COUNTERMEASURES = (1 << 0),
};
+struct module;
+
struct lib80211_crypto_ops {
const char *name;
struct list_head list;
@@ -117,10 +118,7 @@ void lib80211_crypt_info_free(struct lib80211_crypt_info *info);
int lib80211_register_crypto_ops(struct lib80211_crypto_ops *ops);
int lib80211_unregister_crypto_ops(struct lib80211_crypto_ops *ops);
struct lib80211_crypto_ops *lib80211_get_crypto_ops(const char *name);
-void lib80211_crypt_deinit_entries(struct lib80211_crypt_info *, int);
-void lib80211_crypt_deinit_handler(unsigned long);
void lib80211_crypt_delayed_deinit(struct lib80211_crypt_info *info,
struct lib80211_crypt_data **crypt);
-void lib80211_crypt_quiescing(struct lib80211_crypt_info *info);
#endif /* LIB80211_H */
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 9259e97864d..d49928ba5d0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -16,7 +16,6 @@
#include <linux/kernel.h>
#include <linux/if_ether.h>
#include <linux/skbuff.h>
-#include <linux/wireless.h>
#include <linux/device.h>
#include <linux/ieee80211.h>
#include <net/cfg80211.h>
@@ -110,6 +109,7 @@ enum ieee80211_ac_numbers {
IEEE80211_AC_BE = 2,
IEEE80211_AC_BK = 3,
};
+#define IEEE80211_NUM_ACS 4
/**
* struct ieee80211_tx_queue_params - transmit queue configuration
@@ -165,13 +165,15 @@ struct ieee80211_low_level_stats {
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
* that it is only ever disabled for station mode.
* @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
+ * @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
+ * @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
BSS_CHANGED_ERP_CTS_PROT = 1<<1,
BSS_CHANGED_ERP_PREAMBLE = 1<<2,
BSS_CHANGED_ERP_SLOT = 1<<3,
- BSS_CHANGED_HT = 1<<4,
+ BSS_CHANGED_HT = 1<<4,
BSS_CHANGED_BASIC_RATES = 1<<5,
BSS_CHANGED_BEACON_INT = 1<<6,
BSS_CHANGED_BSSID = 1<<7,
@@ -182,6 +184,8 @@ enum ieee80211_bss_change {
BSS_CHANGED_ARP_FILTER = 1<<12,
BSS_CHANGED_QOS = 1<<13,
BSS_CHANGED_IDLE = 1<<14,
+ BSS_CHANGED_SSID = 1<<15,
+ BSS_CHANGED_AP_PROBE_RESP = 1<<16,
/* when adding here, make sure to change ieee80211_reconfig */
};
@@ -255,6 +259,9 @@ enum ieee80211_rssi_event {
* @idle: This interface is idle. There's also a global idle flag in the
* hardware config which may be more appropriate depending on what
* your driver/device needs to do.
+ * @ssid: The SSID of the current vif. Only valid in AP-mode.
+ * @ssid_len: Length of SSID given in @ssid.
+ * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -281,6 +288,9 @@ struct ieee80211_bss_conf {
bool arp_filter_enabled;
bool qos;
bool idle;
+ u8 ssid[IEEE80211_MAX_SSID_LEN];
+ size_t ssid_len;
+ bool hidden_ssid;
};
/**
@@ -331,9 +341,9 @@ struct ieee80211_bss_conf {
* used to indicate that a frame was already retried due to PS
* @IEEE80211_TX_INTFL_DONT_ENCRYPT: completely internal to mac80211,
* used to indicate frame should not be encrypted
- * @IEEE80211_TX_CTL_PSPOLL_RESPONSE: (internal?)
- * This frame is a response to a PS-poll frame and should be sent
- * although the station is in powersave mode.
+ * @IEEE80211_TX_CTL_POLL_RESPONSE: This frame is a response to a poll
+ * frame (PS-Poll or uAPSD) and should be sent although the station
+ * is in powersave mode.
* @IEEE80211_TX_CTL_MORE_FRAMES: More frames will be passed to the
* transmit function after the current frame, this can be used
* by drivers to kick the DMA queue only if unset or when the
@@ -341,8 +351,6 @@ struct ieee80211_bss_conf {
* @IEEE80211_TX_INTFL_RETRANSMISSION: This frame is being retransmitted
* after TX status because the destination was asleep, it must not
* be modified again (no seqno assignment, crypto, etc.)
- * @IEEE80211_TX_INTFL_HAS_RADIOTAP: This frame was injected and still
- * has a radiotap header at skb->data.
* @IEEE80211_TX_INTFL_NL80211_FRAME_TX: Frame was requested through nl80211
* MLME command (internal to mac80211 to figure out whether to send TX
* status to user space)
@@ -356,6 +364,20 @@ struct ieee80211_bss_conf {
* @IEEE80211_TX_INTFL_TKIP_MIC_FAILURE: Marks this packet to be used for TKIP
* testing. It will be sent out with incorrect Michael MIC key to allow
* TKIP countermeasures to be tested.
+ * @IEEE80211_TX_CTL_NO_CCK_RATE: This frame will be sent at non CCK rate.
+ * This flag is actually used for management frame especially for P2P
+ * frames not being sent at CCK rate in 2GHz band.
+ * @IEEE80211_TX_STATUS_EOSP: This packet marks the end of service period,
+ * when its status is reported the service period ends. For frames in
+ * an SP that mac80211 transmits, it is already set; for driver frames
+ * the driver may set this flag. It is also used to do the same for
+ * PS-Poll responses.
+ * @IEEE80211_TX_CTL_USE_MINRATE: This frame will be sent at lowest rate.
+ * This flag is used to send nullfunc frame at minimum rate when
+ * the nullfunc is used for connection monitoring purpose.
+ * @IEEE80211_TX_CTL_DONTFRAG: Don't fragment this packet even if it
+ * would be fragmented by size (this is optional, only used for
+ * monitor injection).
*
* Note: If you have to add new flags to the enumeration, then don't
* forget to update %IEEE80211_TX_TEMPORARY_FLAGS when necessary.
@@ -377,15 +399,19 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_INTFL_NEED_TXPROCESSING = BIT(14),
IEEE80211_TX_INTFL_RETRIED = BIT(15),
IEEE80211_TX_INTFL_DONT_ENCRYPT = BIT(16),
- IEEE80211_TX_CTL_PSPOLL_RESPONSE = BIT(17),
+ IEEE80211_TX_CTL_POLL_RESPONSE = BIT(17),
IEEE80211_TX_CTL_MORE_FRAMES = BIT(18),
IEEE80211_TX_INTFL_RETRANSMISSION = BIT(19),
- IEEE80211_TX_INTFL_HAS_RADIOTAP = BIT(20),
+ /* hole at 20, use later */
IEEE80211_TX_INTFL_NL80211_FRAME_TX = BIT(21),
IEEE80211_TX_CTL_LDPC = BIT(22),
IEEE80211_TX_CTL_STBC = BIT(23) | BIT(24),
IEEE80211_TX_CTL_TX_OFFCHAN = BIT(25),
IEEE80211_TX_INTFL_TKIP_MIC_FAILURE = BIT(26),
+ IEEE80211_TX_CTL_NO_CCK_RATE = BIT(27),
+ IEEE80211_TX_STATUS_EOSP = BIT(28),
+ IEEE80211_TX_CTL_USE_MINRATE = BIT(29),
+ IEEE80211_TX_CTL_DONTFRAG = BIT(30),
};
#define IEEE80211_TX_CTL_STBC_SHIFT 23
@@ -399,9 +425,9 @@ enum mac80211_tx_control_flags {
IEEE80211_TX_CTL_SEND_AFTER_DTIM | IEEE80211_TX_CTL_AMPDU | \
IEEE80211_TX_STAT_TX_FILTERED | IEEE80211_TX_STAT_ACK | \
IEEE80211_TX_STAT_AMPDU | IEEE80211_TX_STAT_AMPDU_NO_BACK | \
- IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_PSPOLL_RESPONSE | \
+ IEEE80211_TX_CTL_RATE_CTRL_PROBE | IEEE80211_TX_CTL_POLL_RESPONSE | \
IEEE80211_TX_CTL_MORE_FRAMES | IEEE80211_TX_CTL_LDPC | \
- IEEE80211_TX_CTL_STBC)
+ IEEE80211_TX_CTL_STBC | IEEE80211_TX_STATUS_EOSP)
/**
* enum mac80211_rate_control_flags - per-rate flags set by the
@@ -494,7 +520,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
- * @pad: padding, ignore
+ * @ack_frame_id: internal frame ID for TX status, used internally
* @control: union for control data
* @status: union for status data
* @driver_data: array of driver_data pointers
@@ -511,8 +537,7 @@ struct ieee80211_tx_info {
u8 antenna_sel_tx;
- /* 2 byte hole */
- u8 pad[2];
+ u16 ack_frame_id;
union {
struct {
@@ -877,6 +902,10 @@ static inline bool ieee80211_vif_is_mesh(struct ieee80211_vif *vif)
* @IEEE80211_KEY_FLAG_SW_MGMT: This flag should be set by the driver for a
* 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
+ * itself should not be generated. Do not set together with
+ * @IEEE80211_KEY_FLAG_GENERATE_IV on the same key.
*/
enum ieee80211_key_flags {
IEEE80211_KEY_FLAG_WMM_STA = 1<<0,
@@ -884,6 +913,7 @@ enum ieee80211_key_flags {
IEEE80211_KEY_FLAG_GENERATE_MMIC= 1<<2,
IEEE80211_KEY_FLAG_PAIRWISE = 1<<3,
IEEE80211_KEY_FLAG_SW_MGMT = 1<<4,
+ IEEE80211_KEY_FLAG_PUT_IV_SPACE = 1<<5,
};
/**
@@ -948,6 +978,9 @@ enum set_key_cmd {
* @wme: indicates whether the STA supports WME. Only valid during AP-mode.
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *), size is determined in hw information.
+ * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
+ * if wme is supported.
+ * @max_sp: max Service Period. Only valid if wme is supported.
*/
struct ieee80211_sta {
u32 supp_rates[IEEE80211_NUM_BANDS];
@@ -955,6 +988,8 @@ struct ieee80211_sta {
u16 aid;
struct ieee80211_sta_ht_cap ht_cap;
bool wme;
+ u8 uapsd_queues;
+ u8 max_sp;
/* must be last */
u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
@@ -1095,6 +1130,10 @@ enum sta_notify_cmd {
* stations based on the PM bit of incoming frames.
* Use ieee80211_start_ps()/ieee8021_end_ps() to manually configure
* the PS mode of connected stations.
+ *
+ * @IEEE80211_HW_TX_AMPDU_SETUP_IN_HW: The device handles TX A-MPDU session
+ * setup strictly in HW. mac80211 should not attempt to do this in
+ * software.
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -1120,6 +1159,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_CQM_RSSI = 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,
};
/**
@@ -1270,6 +1310,16 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
}
/**
+ * ieee80211_free_txskb - free TX skb
+ * @hw: the hardware
+ * @skb: the skb
+ *
+ * Free a transmit skb. Use this funtion when some failure
+ * to transmit happened and thus status cannot be reported.
+ */
+void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+/**
* DOC: Hardware crypto acceleration
*
* mac80211 is capable of taking advantage of many hardware
@@ -1389,7 +1439,7 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
* DOC: Beacon filter support
*
* Some hardware have beacon filter support to reduce host cpu wakeups
- * which will reduce system power consumption. It usuallly works so that
+ * which will reduce system power consumption. It usually works so that
* the firmware creates a checksum of the beacon but omits all constantly
* changing elements (TSF, TIM etc). Whenever the checksum changes the
* beacon is forwarded to the host, otherwise it will be just dropped. That
@@ -1511,6 +1561,95 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw,
*/
/**
+ * DOC: AP support for powersaving clients
+ *
+ * In order to implement AP and P2P GO modes, mac80211 has support for
+ * client powersaving, both "legacy" PS (PS-Poll/null data) and uAPSD.
+ * There currently is no support for sAPSD.
+ *
+ * There is one assumption that mac80211 makes, namely that a client
+ * will not poll with PS-Poll and trigger with uAPSD at the same time.
+ * Both are supported, and both can be used by the same client, but
+ * they can't be used concurrently by the same client. This simplifies
+ * the driver code.
+ *
+ * The first thing to keep in mind is that there is a flag for complete
+ * driver implementation: %IEEE80211_HW_AP_LINK_PS. If this flag is set,
+ * mac80211 expects the driver to handle most of the state machine for
+ * powersaving clients and will ignore the PM bit in incoming frames.
+ * Drivers then use ieee80211_sta_ps_transition() to inform mac80211 of
+ * stations' powersave transitions. In this mode, mac80211 also doesn't
+ * handle PS-Poll/uAPSD.
+ *
+ * In the mode without %IEEE80211_HW_AP_LINK_PS, mac80211 will check the
+ * PM bit in incoming frames for client powersave transitions. When a
+ * station goes to sleep, we will stop transmitting to it. There is,
+ * however, a race condition: a station might go to sleep while there is
+ * data buffered on hardware queues. If the device has support for this
+ * it will reject frames, and the driver should give the frames back to
+ * mac80211 with the %IEEE80211_TX_STAT_TX_FILTERED flag set which will
+ * cause mac80211 to retry the frame when the station wakes up. The
+ * driver is also notified of powersave transitions by calling its
+ * @sta_notify callback.
+ *
+ * When the station is asleep, it has three choices: it can wake up,
+ * it can PS-Poll, or it can possibly start a uAPSD service period.
+ * Waking up is implemented by simply transmitting all buffered (and
+ * filtered) frames to the station. This is the easiest case. When
+ * the station sends a PS-Poll or a uAPSD trigger frame, mac80211
+ * will inform the driver of this with the @allow_buffered_frames
+ * callback; this callback is optional. mac80211 will then transmit
+ * the frames as usual and set the %IEEE80211_TX_CTL_POLL_RESPONSE
+ * on each frame. The last frame in the service period (or the only
+ * response to a PS-Poll) also has %IEEE80211_TX_STATUS_EOSP set to
+ * indicate that it ends the service period; as this frame must have
+ * TX status report it also sets %IEEE80211_TX_CTL_REQ_TX_STATUS.
+ * When TX status is reported for this frame, the service period is
+ * marked has having ended and a new one can be started by the peer.
+ *
+ * Another race condition can happen on some devices like iwlwifi
+ * when there are frames queued for the station and it wakes up
+ * or polls; the frames that are already queued could end up being
+ * transmitted first instead, causing reordering and/or wrong
+ * processing of the EOSP. The cause is that allowing frames to be
+ * transmitted to a certain station is out-of-band communication to
+ * the device. To allow this problem to be solved, the driver can
+ * call ieee80211_sta_block_awake() if frames are buffered when it
+ * is notified that the station went to sleep. When all these frames
+ * have been filtered (see above), it must call the function again
+ * to indicate that the station is no longer blocked.
+ *
+ * If the driver buffers frames in the driver for aggregation in any
+ * way, it must use the ieee80211_sta_set_buffered() call when it is
+ * notified of the station going to sleep to inform mac80211 of any
+ * TIDs that have frames buffered. Note that when a station wakes up
+ * this information is reset (hence the requirement to call it when
+ * informed of the station going to sleep). Then, when a service
+ * period starts for any reason, @release_buffered_frames is called
+ * with the number of frames to be released and which TIDs they are
+ * to come from. In this case, the driver is responsible for setting
+ * the EOSP (for uAPSD) and MORE_DATA bits in the released frames,
+ * to help the @more_data paramter is passed to tell the driver if
+ * there is more data on other TIDs -- the TIDs to release frames
+ * from are ignored since mac80211 doesn't know how many frames the
+ * buffers for those TIDs contain.
+ *
+ * If the driver also implement GO mode, where absence periods may
+ * shorten service periods (or abort PS-Poll responses), it must
+ * filter those response frames except in the case of frames that
+ * are buffered in the driver -- those must remain buffered to avoid
+ * reordering. Because it is possible that no frames are released
+ * in this case, the driver must call ieee80211_sta_eosp_irqsafe()
+ * to indicate to mac80211 that the service period ended anyway.
+ *
+ * Finally, if frames from multiple TIDs are released from mac80211
+ * but the driver might reorder them, it must clear & set the flags
+ * appropriately (only the last frame may have %IEEE80211_TX_STATUS_EOSP)
+ * and also take care of the EOSP and MORE_DATA bits in the frame.
+ * The driver may also use ieee80211_sta_eosp_irqsafe() in this case.
+ */
+
+/**
* enum ieee80211_filter_flags - hardware filter flags
*
* These flags determine what the filter in hardware should be
@@ -1600,6 +1739,17 @@ enum ieee80211_tx_sync_type {
};
/**
+ * enum ieee80211_frame_release_type - frame release reason
+ * @IEEE80211_FRAME_RELEASE_PSPOLL: frame released for PS-Poll
+ * @IEEE80211_FRAME_RELEASE_UAPSD: frame(s) released due to
+ * frame received on trigger-enabled AC
+ */
+enum ieee80211_frame_release_type {
+ IEEE80211_FRAME_RELEASE_PSPOLL,
+ IEEE80211_FRAME_RELEASE_UAPSD,
+};
+
+/**
* struct ieee80211_ops - callbacks from mac80211 to the driver
*
* This structure contains various callbacks that the driver may
@@ -1610,11 +1760,21 @@ enum ieee80211_tx_sync_type {
* skb contains the buffer starting from the IEEE 802.11 header.
* 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, more
- * importantly, however, it must never fail for A-MPDU-queues.
- * This function should return NETDEV_TX_OK except in very
- * limited cases.
- * Must be implemented and atomic.
+ * 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
* is enabled. This should turn on the hardware and must turn on
@@ -1896,11 +2056,6 @@ enum ieee80211_tx_sync_type {
* ieee80211_remain_on_channel_expired(). This callback may sleep.
* @cancel_remain_on_channel: Requests that an ongoing off-channel period is
* aborted before it expires. This callback may sleep.
- * @offchannel_tx: Transmit frame on another channel, wait for a response
- * and return. Reliable TX status must be reported for the frame. If the
- * return value is 1, then the @remain_on_channel will be used with a
- * regular transmission (if supported.)
- * @offchannel_tx_cancel_wait: cancel wait associated with offchannel TX
*
* @set_ringparam: Set tx and rx ring sizes.
*
@@ -1914,9 +2069,50 @@ enum ieee80211_tx_sync_type {
* The callback can sleep.
* @rssi_callback: Notify driver when the average RSSI goes above/below
* thresholds that were registered previously. The callback can sleep.
+ *
+ * @release_buffered_frames: Release buffered frames according to the given
+ * parameters. In the case where the driver buffers some frames for
+ * sleeping stations mac80211 will use this callback to tell the driver
+ * to release some frames, either for PS-poll or uAPSD.
+ * Note that if the @more_data paramter is %false the driver must check
+ * if there are more frames on the given TIDs, and if there are more than
+ * the frames being released then it must still set the more-data bit in
+ * the frame. If the @more_data parameter is %true, then of course the
+ * more-data bit must always be set.
+ * The @tids parameter tells the driver which TIDs to release frames
+ * from, for PS-poll it will always have only a single bit set.
+ * In the case this is used for a PS-poll initiated release, the
+ * @num_frames parameter will always be 1 so code can be shared. In
+ * this case the driver must also set %IEEE80211_TX_STATUS_EOSP flag
+ * on the TX status (and must report TX status) so that the PS-poll
+ * period is properly ended. This is used to avoid sending multiple
+ * responses for a retried PS-poll frame.
+ * In the case this is used for uAPSD, the @num_frames parameter may be
+ * bigger than one, but the driver may send fewer frames (it must send
+ * at least one, however). In this case it is also responsible for
+ * setting the EOSP flag in the QoS header of the frames. Also, when the
+ * service period ends, the driver must set %IEEE80211_TX_STATUS_EOSP
+ * on the last frame in the SP. Alternatively, it may call the function
+ * ieee80211_sta_eosp_irqsafe() to inform mac80211 of the end of the SP.
+ * This callback must be atomic.
+ * @allow_buffered_frames: Prepare device to allow the given number of frames
+ * to go out to the given station. The frames will be sent by mac80211
+ * via the usual TX path after this call. The TX information for frames
+ * released will also have the %IEEE80211_TX_CTL_POLL_RESPONSE flag set
+ * and the last one will also have %IEEE80211_TX_STATUS_EOSP set. In case
+ * frames from multiple TIDs are released and the driver might reorder
+ * them between the TIDs, it must set the %IEEE80211_TX_STATUS_EOSP flag
+ * on the last frame and clear it on all others and also handle the EOSP
+ * bit in the QoS header correctly. Alternatively, it can also call the
+ * ieee80211_sta_eosp_irqsafe() function.
+ * 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.
*/
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
@@ -1986,11 +2182,13 @@ struct ieee80211_ops {
struct ieee80211_sta *sta);
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta);
- int (*conf_tx)(struct ieee80211_hw *hw, u16 queue,
+ int (*conf_tx)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
- u64 (*get_tsf)(struct ieee80211_hw *hw);
- void (*set_tsf)(struct ieee80211_hw *hw, u64 tsf);
- void (*reset_tsf)(struct ieee80211_hw *hw);
+ u64 (*get_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+ void (*set_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ u64 tsf);
+ void (*reset_tsf)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
int (*tx_last_beacon)(struct ieee80211_hw *hw);
int (*ampdu_action)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -2019,11 +2217,6 @@ struct ieee80211_ops {
enum nl80211_channel_type channel_type,
int duration);
int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
- int (*offchannel_tx)(struct ieee80211_hw *hw, struct sk_buff *skb,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
- unsigned int wait);
- int (*offchannel_tx_cancel_wait)(struct ieee80211_hw *hw);
int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
void (*get_ringparam)(struct ieee80211_hw *hw,
u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
@@ -2032,6 +2225,17 @@ struct ieee80211_ops {
const struct cfg80211_bitrate_mask *mask);
void (*rssi_callback)(struct ieee80211_hw *hw,
enum ieee80211_rssi_event rssi_event);
+
+ void (*allow_buffered_frames)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u16 tids, int num_frames,
+ enum ieee80211_frame_release_type reason,
+ bool more_data);
+ void (*release_buffered_frames)(struct ieee80211_hw *hw,
+ struct ieee80211_sta *sta,
+ u16 tids, int num_frames,
+ enum ieee80211_frame_release_type reason,
+ bool more_data);
};
/**
@@ -2346,20 +2550,38 @@ static inline int ieee80211_sta_ps_transition_ni(struct ieee80211_sta *sta,
* The TX headroom reserved by mac80211 for its own tx_status functions.
* This is enough for the radiotap header.
*/
-#define IEEE80211_TX_STATUS_HEADROOM 13
+#define IEEE80211_TX_STATUS_HEADROOM 14
/**
- * ieee80211_sta_set_tim - set the TIM bit for a sleeping station
+ * ieee80211_sta_set_buffered - inform mac80211 about driver-buffered frames
* @sta: &struct ieee80211_sta pointer for the sleeping station
+ * @tid: the TID that has buffered frames
+ * @buffered: indicates whether or not frames are buffered for this TID
*
* If a driver buffers frames for a powersave station instead of passing
- * them back to mac80211 for retransmission, the station needs to be told
- * to wake up using the TIM bitmap in the beacon.
+ * them back to mac80211 for retransmission, the station may still need
+ * to be told that there are buffered frames via the TIM bit.
+ *
+ * This function informs mac80211 whether or not there are frames that are
+ * buffered in the driver for a given TID; mac80211 can then use this data
+ * to set the TIM bit (NOTE: This may call back into the driver's set_tim
+ * call! Beware of the locking!)
+ *
+ * If all frames are released to the station (due to PS-poll or uAPSD)
+ * then the driver needs to inform mac80211 that there no longer are
+ * frames buffered. However, when the station wakes up mac80211 assumes
+ * that all buffered frames will be transmitted and clears this data,
+ * drivers need to make sure they inform mac80211 about all buffered
+ * frames on the sleep transition (sta_notify() with %STA_NOTIFY_SLEEP).
*
- * This function sets the station's TIM bit - it will be cleared when the
- * station wakes up.
+ * Note that technically mac80211 only needs to know this per AC, not per
+ * TID, but since driver buffering will inevitably happen per TID (since
+ * it is related to aggregation) it is easier to make mac80211 map the
+ * TID to the AC as required instead of keeping track in all drivers that
+ * use this API.
*/
-void ieee80211_sta_set_tim(struct ieee80211_sta *sta);
+void ieee80211_sta_set_buffered(struct ieee80211_sta *sta,
+ u8 tid, bool buffered);
/**
* ieee80211_tx_status - transmit status callback
@@ -2467,6 +2689,19 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
}
/**
+ * ieee80211_proberesp_get - retrieve a Probe Response template
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Creates a Probe Response template which can, for example, be uploaded to
+ * hardware. The destination address should be set by the caller.
+ *
+ * Can only be called in AP mode.
+ */
+struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif);
+
+/**
* ieee80211_pspoll_get - retrieve a PS Poll template
* @hw: pointer obtained from ieee80211_alloc_hw().
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
@@ -3017,6 +3252,24 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw,
struct ieee80211_sta *pubsta, bool block);
/**
+ * ieee80211_sta_eosp - notify mac80211 about end of SP
+ * @pubsta: the station
+ *
+ * When a device transmits frames in a way that it can't tell
+ * mac80211 in the TX status about the EOSP, it must clear the
+ * %IEEE80211_TX_STATUS_EOSP bit and call this function instead.
+ * This applies for PS-Poll as well as uAPSD.
+ *
+ * Note that there is no non-_irqsafe version right now as
+ * it wasn't needed, but just like _tx_status() and _rx()
+ * must not be mixed in irqsafe/non-irqsafe versions, this
+ * function must not be mixed with those either. Use the
+ * all irqsafe, or all non-irqsafe, don't mix! If you need
+ * the non-irqsafe version of this, you need to add it.
+ */
+void ieee80211_sta_eosp_irqsafe(struct ieee80211_sta *pubsta);
+
+/**
* ieee80211_iter_keys - iterate keys programmed into the device
* @hw: pointer obtained from ieee80211_alloc_hw()
* @vif: virtual interface to iterate, may be %NULL for all
@@ -3229,6 +3482,19 @@ void ieee80211_remain_on_channel_expired(struct ieee80211_hw *hw);
void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
const u8 *addr);
+/**
+ * ieee80211_send_bar - send a BlockAckReq frame
+ *
+ * can be used to flush pending frames from the peer's aggregation reorder
+ * buffer.
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @ra: the peer's destination address
+ * @tid: the TID of the aggregation session
+ * @ssn: the new starting sequence number for the receiver
+ */
+void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
+
/* Rate control API */
/**
@@ -3236,9 +3502,12 @@ void ieee80211_stop_rx_ba_session(struct ieee80211_vif *vif, u16 ba_rx_bitmap,
*
* @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_HT_CHANGED = BIT(0),
+ IEEE80211_RC_SMPS_CHANGED = BIT(1),
};
/**
@@ -3342,8 +3611,9 @@ rate_lowest_index(struct ieee80211_supported_band *sband,
return i;
/* warn when we cannot find a rate. */
- WARN_ON(1);
+ WARN_ON_ONCE(1);
+ /* and return 0 (the lowest index) */
return 0;
}
@@ -3419,4 +3689,9 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
int rssi_max_thold);
void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
+
+int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb);
+
+int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
+ struct sk_buff *skb);
#endif /* MAC80211_H */
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 62beeb97c4b..e3133c23980 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -79,6 +79,42 @@ struct nd_opt_hdr {
__u8 nd_opt_len;
} __packed;
+static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
+{
+ const u32 *p32 = pkey;
+
+ return (((p32[0] ^ dev->ifindex) * hash_rnd[0]) +
+ (p32[1] * hash_rnd[1]) +
+ (p32[2] * hash_rnd[2]) +
+ (p32[3] * hash_rnd[3]));
+}
+
+static inline struct neighbour *__ipv6_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, const void *pkey)
+{
+ struct neigh_hash_table *nht;
+ const u32 *p32 = pkey;
+ struct neighbour *n;
+ u32 hash_val;
+
+ rcu_read_lock_bh();
+ nht = rcu_dereference_bh(tbl->nht);
+ hash_val = ndisc_hashfn(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
+ for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
+ n != NULL;
+ n = rcu_dereference_bh(n->next)) {
+ u32 *n32 = (u32 *) n->primary_key;
+ if (n->dev == dev &&
+ ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
+ (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0) {
+ if (!atomic_inc_not_zero(&n->refcnt))
+ n = NULL;
+ break;
+ }
+ }
+ rcu_read_unlock_bh();
+
+ return n;
+}
extern int ndisc_init(void);
@@ -145,13 +181,4 @@ int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
extern void inet6_ifinfo_notify(int event,
struct inet6_dev *idev);
-static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const struct in6_addr *addr)
-{
-
- if (dev)
- return __neigh_lookup_errno(&nd_tbl, addr, dev);
-
- return ERR_PTR(-ENODEV);
-}
-
#endif
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 2720884287c..34c996f4618 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -59,7 +59,7 @@ struct neigh_parms {
int reachable_time;
int delay_probe_time;
- int queue_len;
+ int queue_len_bytes;
int ucast_probes;
int app_probes;
int mcast_probes;
@@ -99,6 +99,7 @@ struct neighbour {
rwlock_t lock;
atomic_t refcnt;
struct sk_buff_head arp_queue;
+ unsigned int arp_queue_len_bytes;
struct timer_list timer;
unsigned long used;
atomic_t probes;
@@ -138,10 +139,12 @@ struct pneigh_entry {
* neighbour table manipulation
*/
+#define NEIGH_NUM_HASH_RND 4
+
struct neigh_hash_table {
struct neighbour __rcu **hash_buckets;
unsigned int hash_shift;
- __u32 hash_rnd;
+ __u32 hash_rnd[NEIGH_NUM_HASH_RND];
struct rcu_head rcu;
};
@@ -153,7 +156,7 @@ struct neigh_table {
int key_len;
__u32 (*hash)(const void *pkey,
const struct net_device *dev,
- __u32 hash_rnd);
+ __u32 *hash_rnd);
int (*constructor)(struct neighbour *);
int (*pconstructor)(struct pneigh_entry *);
void (*pdestructor)(struct pneigh_entry *);
@@ -172,12 +175,18 @@ struct neigh_table {
atomic_t entries;
rwlock_t lock;
unsigned long last_rand;
- struct kmem_cache *kmem_cachep;
struct neigh_statistics __percpu *stats;
struct neigh_hash_table __rcu *nht;
struct pneigh_entry **phash_buckets;
};
+#define NEIGH_PRIV_ALIGN sizeof(long long)
+
+static inline void *neighbour_priv(const struct neighbour *n)
+{
+ return (char *)n + ALIGN(sizeof(*n) + n->tbl->key_len, NEIGH_PRIV_ALIGN);
+}
+
/* flags for neigh_update() */
#define NEIGH_UPDATE_F_OVERRIDE 0x00000001
#define NEIGH_UPDATE_F_WEAK_OVERRIDE 0x00000002
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 3bb6fa0eace..ee547c14981 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -77,7 +77,7 @@ struct net {
struct netns_packet packet;
struct netns_unix unx;
struct netns_ipv4 ipv4;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct netns_ipv6 ipv6;
#endif
#if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE)
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index 0b7f05e4a92..8a2b0ae7dbd 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -313,6 +313,8 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK;
}
+struct kernel_param;
+
extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
extern unsigned int nf_conntrack_htable_size;
extern unsigned int nf_conntrack_max;
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h
index 4e9c63a20db..463ae8e1669 100644
--- a/include/net/netfilter/nf_conntrack_acct.h
+++ b/include/net/netfilter/nf_conntrack_acct.h
@@ -15,8 +15,8 @@
#include <net/netfilter/nf_conntrack_extend.h>
struct nf_conn_counter {
- u_int64_t packets;
- u_int64_t bytes;
+ atomic64_t packets;
+ atomic64_t bytes;
};
static inline
diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h
index 4283508b3e1..a88fb693938 100644
--- a/include/net/netfilter/nf_conntrack_ecache.h
+++ b/include/net/netfilter/nf_conntrack_ecache.h
@@ -67,18 +67,18 @@ struct nf_ct_event_notifier {
int (*fcn)(unsigned int events, struct nf_ct_event *item);
};
-extern struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
-extern int nf_conntrack_register_notifier(struct nf_ct_event_notifier *nb);
-extern void nf_conntrack_unregister_notifier(struct nf_ct_event_notifier *nb);
+extern int nf_conntrack_register_notifier(struct net *net, struct nf_ct_event_notifier *nb);
+extern void nf_conntrack_unregister_notifier(struct net *net, struct nf_ct_event_notifier *nb);
extern void nf_ct_deliver_cached_events(struct nf_conn *ct);
static inline void
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 (nf_conntrack_event_cb == NULL)
+ if (net->ct.nf_conntrack_event_cb == NULL)
return;
e = nf_ct_ecache_find(ct);
@@ -95,11 +95,12 @@ nf_conntrack_eventmask_report(unsigned int eventmask,
int report)
{
int ret = 0;
+ struct net *net = nf_ct_net(ct);
struct nf_ct_event_notifier *notify;
struct nf_conntrack_ecache *e;
rcu_read_lock();
- notify = rcu_dereference(nf_conntrack_event_cb);
+ notify = rcu_dereference(net->ct.nf_conntrack_event_cb);
if (notify == NULL)
goto out_unlock;
@@ -164,9 +165,8 @@ struct nf_exp_event_notifier {
int (*fcn)(unsigned int events, struct nf_exp_event *item);
};
-extern struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
-extern int nf_ct_expect_register_notifier(struct nf_exp_event_notifier *nb);
-extern void nf_ct_expect_unregister_notifier(struct nf_exp_event_notifier *nb);
+extern int nf_ct_expect_register_notifier(struct net *net, struct nf_exp_event_notifier *nb);
+extern void nf_ct_expect_unregister_notifier(struct net *net, struct nf_exp_event_notifier *nb);
static inline void
nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
@@ -174,11 +174,12 @@ nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
u32 pid,
int report)
{
+ struct net *net = nf_ct_exp_net(exp);
struct nf_exp_event_notifier *notify;
struct nf_conntrack_ecache *e;
rcu_read_lock();
- notify = rcu_dereference(nf_expect_event_cb);
+ notify = rcu_dereference(net->ct.nf_expect_event_cb);
if (notify == NULL)
goto out_unlock;
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h
index 0f8a8c58753..4619caadd9d 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -91,7 +91,6 @@ static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
void nf_ct_remove_expectations(struct nf_conn *ct);
void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
-void nf_ct_remove_userspace_expectations(void);
/* Allocate space for an expectation: this is mandatory before calling
nf_ct_expect_related. You will have to call put afterwards. */
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h
index 7ca6bdd5bae..aea3f8221be 100644
--- a/include/net/netfilter/nf_conntrack_tuple.h
+++ b/include/net/netfilter/nf_conntrack_tuple.h
@@ -24,32 +24,6 @@
#define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all)
-/* The protocol-specific manipulable parts of the tuple: always in
- network order! */
-union nf_conntrack_man_proto {
- /* Add other protocols here. */
- __be16 all;
-
- struct {
- __be16 port;
- } tcp;
- struct {
- __be16 port;
- } udp;
- struct {
- __be16 id;
- } icmp;
- struct {
- __be16 port;
- } dccp;
- struct {
- __be16 port;
- } sctp;
- struct {
- __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */
- } gre;
-};
-
/* The manipulable part of the tuple. */
struct nf_conntrack_man {
union nf_inet_addr u3;
diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h
index 920997f1aff..e991bd0a27a 100644
--- a/include/net/netfilter/nf_log.h
+++ b/include/net/netfilter/nf_log.h
@@ -53,12 +53,13 @@ int nf_log_bind_pf(u_int8_t pf, const struct nf_logger *logger);
void nf_log_unbind_pf(u_int8_t pf);
/* Calls the registered backend logging function */
+__printf(7, 8)
void nf_log_packet(u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *li,
- const char *fmt, ...) __attribute__ ((format(printf,7,8)));
+ const char *fmt, ...);
#endif /* _NF_LOG_H */
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index 0346b007086..b4de990b55f 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -1,24 +1,18 @@
#ifndef _NF_NAT_H
#define _NF_NAT_H
#include <linux/netfilter_ipv4.h>
+#include <linux/netfilter/nf_nat.h>
#include <net/netfilter/nf_conntrack_tuple.h>
-#define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16
-
enum nf_nat_manip_type {
- IP_NAT_MANIP_SRC,
- IP_NAT_MANIP_DST
+ NF_NAT_MANIP_SRC,
+ NF_NAT_MANIP_DST
};
/* SRC manip occurs POST_ROUTING or LOCAL_IN */
#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \
(hooknum) != NF_INET_LOCAL_IN)
-#define IP_NAT_RANGE_MAP_IPS 1
-#define IP_NAT_RANGE_PROTO_SPECIFIED 2
-#define IP_NAT_RANGE_PROTO_RANDOM 4
-#define IP_NAT_RANGE_PERSISTENT 8
-
/* NAT sequence number modifications */
struct nf_nat_seq {
/* position of the last TCP sequence number modification (if any) */
@@ -28,26 +22,6 @@ struct nf_nat_seq {
int16_t offset_before, offset_after;
};
-/* Single range specification. */
-struct nf_nat_range {
- /* Set to OR of flags above. */
- unsigned int flags;
-
- /* Inclusive: network order. */
- __be32 min_ip, max_ip;
-
- /* Inclusive: network order */
- union nf_conntrack_man_proto min, max;
-};
-
-/* For backwards compat: don't use in modern code. */
-struct nf_nat_multi_range_compat {
- unsigned int rangesize; /* Must be 1. */
-
- /* hangs off end. */
- struct nf_nat_range range[1];
-};
-
#include <linux/list.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
#include <net/netfilter/nf_conntrack_extend.h>
@@ -76,7 +50,7 @@ struct nf_conn_nat {
/* Set up the info structure to map into this range. */
extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
- const struct nf_nat_range *range,
+ const struct nf_nat_ipv4_range *range,
enum nf_nat_manip_type maniptype);
/* Is this tuple already taken? (not by us)*/
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h
index 3dc7b98effe..b13d8d18d59 100644
--- a/include/net/netfilter/nf_nat_core.h
+++ b/include/net/netfilter/nf_nat_core.h
@@ -20,7 +20,7 @@ extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
static inline int nf_nat_initialized(struct nf_conn *ct,
enum nf_nat_manip_type manip)
{
- if (manip == IP_NAT_MANIP_SRC)
+ if (manip == NF_NAT_MANIP_SRC)
return ct->status & IPS_SRC_NAT_DONE;
else
return ct->status & IPS_DST_NAT_DONE;
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h
index 93cc90d28e6..7b0b51165f7 100644
--- a/include/net/netfilter/nf_nat_protocol.h
+++ b/include/net/netfilter/nf_nat_protocol.h
@@ -4,14 +4,12 @@
#include <net/netfilter/nf_nat.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
-struct nf_nat_range;
+struct nf_nat_ipv4_range;
struct nf_nat_protocol {
/* Protocol number. */
unsigned int protonum;
- struct module *me;
-
/* Translate a packet to the target according to manip type.
Return true if succeeded. */
bool (*manip_pkt)(struct sk_buff *skb,
@@ -30,15 +28,12 @@ struct nf_nat_protocol {
possible. Per-protocol part of tuple is initialized to the
incoming packet. */
void (*unique_tuple)(struct nf_conntrack_tuple *tuple,
- const struct nf_nat_range *range,
+ const struct nf_nat_ipv4_range *range,
enum nf_nat_manip_type maniptype,
const struct nf_conn *ct);
- int (*range_to_nlattr)(struct sk_buff *skb,
- const struct nf_nat_range *range);
-
int (*nlattr_to_range)(struct nlattr *tb[],
- struct nf_nat_range *range);
+ struct nf_nat_ipv4_range *range);
};
/* Protocol registration. */
@@ -61,14 +56,12 @@ extern bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
const union nf_conntrack_man_proto *max);
extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
- const struct nf_nat_range *range,
+ const struct nf_nat_ipv4_range *range,
enum nf_nat_manip_type maniptype,
const struct nf_conn *ct,
u_int16_t *rover);
-extern int nf_nat_proto_range_to_nlattr(struct sk_buff *skb,
- const struct nf_nat_range *range);
extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
- struct nf_nat_range *range);
+ struct nf_nat_ipv4_range *range);
#endif /*_NF_NAT_PROTO_H*/
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
index e505358d899..75ca9291cf2 100644
--- a/include/net/netfilter/nf_tproxy_core.h
+++ b/include/net/netfilter/nf_tproxy_core.h
@@ -131,7 +131,7 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
return sk;
}
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
static inline struct sock *
nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
const struct in6_addr *saddr, const struct in6_addr *daddr,
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 98c185441be..cb1f3504687 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -192,8 +192,15 @@ enum {
* NLA_NUL_STRING Maximum length of string (excluding NUL)
* NLA_FLAG Unused
* NLA_BINARY Maximum length of attribute payload
- * NLA_NESTED_COMPAT Exact length of structure payload
- * All other Exact length of attribute payload
+ * NLA_NESTED Don't use `len' field -- length verification is
+ * done by checking len of nested header (or empty)
+ * NLA_NESTED_COMPAT Minimum length of structure payload
+ * NLA_U8, NLA_U16,
+ * NLA_U32, NLA_U64,
+ * NLA_MSECS Leaving the length field zero will verify the
+ * given type fits, using it verifies minimum length
+ * just like "All other"
+ * All other Minimum length of attribute payload
*
* Example:
* static const struct nla_policy my_policy[ATTR_MAX+1] = {
diff --git a/include/net/netns/conntrack.h b/include/net/netns/conntrack.h
index 0249399e51a..7a911eca0f1 100644
--- a/include/net/netns/conntrack.h
+++ b/include/net/netns/conntrack.h
@@ -18,6 +18,8 @@ struct netns_ct {
struct hlist_nulls_head unconfirmed;
struct hlist_nulls_head dying;
struct ip_conntrack_stat __percpu *stat;
+ struct nf_ct_event_notifier __rcu *nf_conntrack_event_cb;
+ struct nf_exp_event_notifier __rcu *nf_expect_event_cb;
int sysctl_events;
unsigned int sysctl_events_retry_timeout;
int sysctl_acct;
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index d786b4fc02a..bbd023a1c9b 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -55,6 +55,7 @@ struct netns_ipv4 {
int current_rt_cache_rebuild_count;
unsigned int sysctl_ping_group_range[2];
+ long sysctl_tcp_mem[3];
atomic_t rt_genid;
atomic_t dev_addr_genid;
diff --git a/include/net/netns/mib.h b/include/net/netns/mib.h
index 0b44112e236..d542a4b28cc 100644
--- a/include/net/netns/mib.h
+++ b/include/net/netns/mib.h
@@ -10,15 +10,15 @@ struct netns_mib {
DEFINE_SNMP_STAT(struct udp_mib, udp_statistics);
DEFINE_SNMP_STAT(struct udp_mib, udplite_statistics);
DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics);
- DEFINE_SNMP_STAT(struct icmpmsg_mib, icmpmsg_statistics);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmpmsg_mib, icmpmsg_statistics);
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct proc_dir_entry *proc_net_devsnmp6;
DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6);
DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6);
DEFINE_SNMP_STAT(struct ipstats_mib, ipv6_statistics);
DEFINE_SNMP_STAT(struct icmpv6_mib, icmpv6_statistics);
- DEFINE_SNMP_STAT(struct icmpv6msg_mib, icmpv6msg_statistics);
+ DEFINE_SNMP_STAT_ATOMIC(struct icmpv6msg_mib, icmpv6msg_statistics);
#endif
#ifdef CONFIG_XFRM_STATISTICS
DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics);
diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h
index 748f91f87cd..5299e69a32a 100644
--- a/include/net/netns/xfrm.h
+++ b/include/net/netns/xfrm.h
@@ -56,7 +56,7 @@ struct netns_xfrm {
#endif
struct dst_ops xfrm4_dst_ops;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct dst_ops xfrm6_dst_ops;
#endif
};
diff --git a/include/net/netprio_cgroup.h b/include/net/netprio_cgroup.h
new file mode 100644
index 00000000000..e503b87c4c1
--- /dev/null
+++ b/include/net/netprio_cgroup.h
@@ -0,0 +1,57 @@
+/*
+ * netprio_cgroup.h Control Group Priority set
+ *
+ *
+ * Authors: Neil Horman <nhorman@tuxdriver.com>
+ *
+ * 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.
+ *
+ */
+
+#ifndef _NETPRIO_CGROUP_H
+#define _NETPRIO_CGROUP_H
+#include <linux/module.h>
+#include <linux/cgroup.h>
+#include <linux/hardirq.h>
+#include <linux/rcupdate.h>
+
+
+struct netprio_map {
+ struct rcu_head rcu;
+ u32 priomap_len;
+ u32 priomap[];
+};
+
+#ifdef CONFIG_CGROUPS
+
+struct cgroup_netprio_state {
+ struct cgroup_subsys_state css;
+ u32 prioidx;
+};
+
+#ifndef CONFIG_NETPRIO_CGROUP
+extern int net_prio_subsys_id;
+#endif
+
+extern void sock_update_netprioidx(struct sock *sk);
+
+static inline struct cgroup_netprio_state
+ *task_netprio_state(struct task_struct *p)
+{
+#if IS_ENABLED(CONFIG_NETPRIO_CGROUP)
+ return container_of(task_subsys_state(p, net_prio_subsys_id),
+ struct cgroup_netprio_state, css);
+#else
+ return NULL;
+#endif
+}
+
+#else
+
+#define sock_update_netprioidx(sk)
+#endif
+
+#endif /* _NET_CLS_CGROUP_H */
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
new file mode 100644
index 00000000000..2be95e2626c
--- /dev/null
+++ b/include/net/nfc/nci.h
@@ -0,0 +1,313 @@
+/*
+ * The NFC Controller Interface is the communication protocol between an
+ * NFC Controller (NFCC) and a Device Host (DH).
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * Written by Ilan Elias <ilane@ti.com>
+ *
+ * Acknowledgements:
+ * This file is based on hci.h, which was written
+ * by Maxim Krasnyansky.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __NCI_H
+#define __NCI_H
+
+/* NCI constants */
+#define NCI_MAX_NUM_MAPPING_CONFIGS 10
+#define NCI_MAX_NUM_RF_CONFIGS 10
+#define NCI_MAX_NUM_CONN 10
+
+/* NCI Status Codes */
+#define NCI_STATUS_OK 0x00
+#define NCI_STATUS_REJECTED 0x01
+#define NCI_STATUS_RF_FRAME_CORRUPTED 0x02
+#define NCI_STATUS_FAILED 0x03
+#define NCI_STATUS_NOT_INITIALIZED 0x04
+#define NCI_STATUS_SYNTAX_ERROR 0x05
+#define NCI_STATUS_SEMANTIC_ERROR 0x06
+#define NCI_STATUS_UNKNOWN_GID 0x07
+#define NCI_STATUS_UNKNOWN_OID 0x08
+#define NCI_STATUS_INVALID_PARAM 0x09
+#define NCI_STATUS_MESSAGE_SIZE_EXCEEDED 0x0a
+/* Discovery Specific Status Codes */
+#define NCI_STATUS_DISCOVERY_ALREADY_STARTED 0xa0
+#define NCI_STATUS_DISCOVERY_TARGET_ACTIVATION_FAILED 0xa1
+#define NCI_STATUS_DISCOVERY_TEAR_DOWN 0xa2
+/* RF Interface Specific Status Codes */
+#define NCI_STATUS_RF_TRANSMISSION_ERROR 0xb0
+#define NCI_STATUS_RF_PROTOCOL_ERROR 0xb1
+#define NCI_STATUS_RF_TIMEOUT_ERROR 0xb2
+/* NFCEE Interface Specific Status Codes */
+#define NCI_STATUS_NFCEE_INTERFACE_ACTIVATION_FAILED 0xc0
+#define NCI_STATUS_NFCEE_TRANSMISSION_ERROR 0xc1
+#define NCI_STATUS_NFCEE_PROTOCOL_ERROR 0xc2
+#define NCI_STATUS_NFCEE_TIMEOUT_ERROR 0xc3
+
+/* NCI RF Technology and Mode */
+#define NCI_NFC_A_PASSIVE_POLL_MODE 0x00
+#define NCI_NFC_B_PASSIVE_POLL_MODE 0x01
+#define NCI_NFC_F_PASSIVE_POLL_MODE 0x02
+#define NCI_NFC_A_ACTIVE_POLL_MODE 0x03
+#define NCI_NFC_F_ACTIVE_POLL_MODE 0x05
+#define NCI_NFC_15693_PASSIVE_POLL_MODE 0x06
+#define NCI_NFC_A_PASSIVE_LISTEN_MODE 0x80
+#define NCI_NFC_B_PASSIVE_LISTEN_MODE 0x81
+#define NCI_NFC_F_PASSIVE_LISTEN_MODE 0x82
+#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
+#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
+#define NCI_NFC_15693_PASSIVE_LISTEN_MODE 0x86
+
+/* NCI RF Technologies */
+#define NCI_NFC_RF_TECHNOLOGY_A 0x00
+#define NCI_NFC_RF_TECHNOLOGY_B 0x01
+#define NCI_NFC_RF_TECHNOLOGY_F 0x02
+#define NCI_NFC_RF_TECHNOLOGY_15693 0x03
+
+/* NCI Bit Rates */
+#define NCI_NFC_BIT_RATE_106 0x00
+#define NCI_NFC_BIT_RATE_212 0x01
+#define NCI_NFC_BIT_RATE_424 0x02
+#define NCI_NFC_BIT_RATE_848 0x03
+#define NCI_NFC_BIT_RATE_1695 0x04
+#define NCI_NFC_BIT_RATE_3390 0x05
+#define NCI_NFC_BIT_RATE_6780 0x06
+
+/* NCI RF Protocols */
+#define NCI_RF_PROTOCOL_UNKNOWN 0x00
+#define NCI_RF_PROTOCOL_T1T 0x01
+#define NCI_RF_PROTOCOL_T2T 0x02
+#define NCI_RF_PROTOCOL_T3T 0x03
+#define NCI_RF_PROTOCOL_ISO_DEP 0x04
+#define NCI_RF_PROTOCOL_NFC_DEP 0x05
+
+/* NCI RF Interfaces */
+#define NCI_RF_INTERFACE_NFCEE_DIRECT 0x00
+#define NCI_RF_INTERFACE_FRAME 0x01
+#define NCI_RF_INTERFACE_ISO_DEP 0x02
+#define NCI_RF_INTERFACE_NFC_DEP 0x03
+
+/* NCI Reset types */
+#define NCI_RESET_TYPE_KEEP_CONFIG 0x00
+#define NCI_RESET_TYPE_RESET_CONFIG 0x01
+
+/* NCI Static RF connection ID */
+#define NCI_STATIC_RF_CONN_ID 0x00
+
+/* NCI Data Flow Control */
+#define NCI_DATA_FLOW_CONTROL_NOT_USED 0xff
+
+/* NCI RF_DISCOVER_MAP_CMD modes */
+#define NCI_DISC_MAP_MODE_POLL 0x01
+#define NCI_DISC_MAP_MODE_LISTEN 0x02
+
+/* NCI Deactivation Type */
+#define NCI_DEACTIVATE_TYPE_IDLE_MODE 0x00
+#define NCI_DEACTIVATE_TYPE_SLEEP_MODE 0x01
+#define NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE 0x02
+#define NCI_DEACTIVATE_TYPE_DISCOVERY 0x03
+
+/* Message Type (MT) */
+#define NCI_MT_DATA_PKT 0x00
+#define NCI_MT_CMD_PKT 0x01
+#define NCI_MT_RSP_PKT 0x02
+#define NCI_MT_NTF_PKT 0x03
+
+#define nci_mt(hdr) (((hdr)[0]>>5)&0x07)
+#define nci_mt_set(hdr, mt) ((hdr)[0] |= (__u8)(((mt)&0x07)<<5))
+
+/* Packet Boundary Flag (PBF) */
+#define NCI_PBF_LAST 0x00
+#define NCI_PBF_CONT 0x01
+
+#define nci_pbf(hdr) (__u8)(((hdr)[0]>>4)&0x01)
+#define nci_pbf_set(hdr, pbf) ((hdr)[0] |= (__u8)(((pbf)&0x01)<<4))
+
+/* Control Opcode manipulation */
+#define nci_opcode_pack(gid, oid) (__u16)((((__u16)((gid)&0x0f))<<8)|\
+ ((__u16)((oid)&0x3f)))
+#define nci_opcode(hdr) nci_opcode_pack(hdr[0], hdr[1])
+#define nci_opcode_gid(op) (__u8)(((op)&0x0f00)>>8)
+#define nci_opcode_oid(op) (__u8)((op)&0x003f)
+
+/* Payload Length */
+#define nci_plen(hdr) (__u8)((hdr)[2])
+
+/* Connection ID */
+#define nci_conn_id(hdr) (__u8)(((hdr)[0])&0x0f)
+
+/* GID values */
+#define NCI_GID_CORE 0x0
+#define NCI_GID_RF_MGMT 0x1
+#define NCI_GID_NFCEE_MGMT 0x2
+#define NCI_GID_PROPRIETARY 0xf
+
+/* ---- NCI Packet structures ---- */
+#define NCI_CTRL_HDR_SIZE 3
+#define NCI_DATA_HDR_SIZE 3
+
+struct nci_ctrl_hdr {
+ __u8 gid; /* MT & PBF & GID */
+ __u8 oid;
+ __u8 plen;
+} __packed;
+
+struct nci_data_hdr {
+ __u8 conn_id; /* MT & PBF & ConnID */
+ __u8 rfu;
+ __u8 plen;
+} __packed;
+
+/* ------------------------ */
+/* ----- NCI Commands ---- */
+/* ------------------------ */
+#define NCI_OP_CORE_RESET_CMD nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_cmd {
+ __u8 reset_type;
+} __packed;
+
+#define NCI_OP_CORE_INIT_CMD nci_opcode_pack(NCI_GID_CORE, 0x01)
+
+#define NCI_OP_RF_DISCOVER_MAP_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+struct disc_map_config {
+ __u8 rf_protocol;
+ __u8 mode;
+ __u8 rf_interface;
+} __packed;
+
+struct nci_rf_disc_map_cmd {
+ __u8 num_mapping_configs;
+ struct disc_map_config mapping_configs
+ [NCI_MAX_NUM_MAPPING_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+struct disc_config {
+ __u8 rf_tech_and_mode;
+ __u8 frequency;
+} __packed;
+
+struct nci_rf_disc_cmd {
+ __u8 num_disc_configs;
+ struct disc_config disc_configs[NCI_MAX_NUM_RF_CONFIGS];
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_CMD nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+struct nci_rf_deactivate_cmd {
+ __u8 type;
+} __packed;
+
+/* ----------------------- */
+/* ---- NCI Responses ---- */
+/* ----------------------- */
+#define NCI_OP_CORE_RESET_RSP nci_opcode_pack(NCI_GID_CORE, 0x00)
+struct nci_core_reset_rsp {
+ __u8 status;
+ __u8 nci_ver;
+ __u8 config_status;
+} __packed;
+
+#define NCI_OP_CORE_INIT_RSP nci_opcode_pack(NCI_GID_CORE, 0x01)
+struct nci_core_init_rsp_1 {
+ __u8 status;
+ __le32 nfcc_features;
+ __u8 num_supported_rf_interfaces;
+ __u8 supported_rf_interfaces[0]; /* variable size array */
+ /* continuted in nci_core_init_rsp_2 */
+} __packed;
+
+struct nci_core_init_rsp_2 {
+ __u8 max_logical_connections;
+ __le16 max_routing_table_size;
+ __u8 max_ctrl_pkt_payload_len;
+ __le16 max_size_for_large_params;
+ __u8 manufact_id;
+ __le32 manufact_specific_info;
+} __packed;
+
+#define NCI_OP_RF_DISCOVER_MAP_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x00)
+
+#define NCI_OP_RF_DISCOVER_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x03)
+
+#define NCI_OP_RF_DEACTIVATE_RSP nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+
+/* --------------------------- */
+/* ---- NCI Notifications ---- */
+/* --------------------------- */
+#define NCI_OP_CORE_CONN_CREDITS_NTF nci_opcode_pack(NCI_GID_CORE, 0x06)
+struct conn_credit_entry {
+ __u8 conn_id;
+ __u8 credits;
+} __packed;
+
+struct nci_core_conn_credit_ntf {
+ __u8 num_entries;
+ struct conn_credit_entry conn_entries[NCI_MAX_NUM_CONN];
+} __packed;
+
+#define NCI_OP_CORE_INTF_ERROR_NTF nci_opcode_pack(NCI_GID_CORE, 0x08)
+struct nci_core_intf_error_ntf {
+ __u8 status;
+ __u8 conn_id;
+} __packed;
+
+#define NCI_OP_RF_INTF_ACTIVATED_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x05)
+struct rf_tech_specific_params_nfca_poll {
+ __u16 sens_res;
+ __u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */
+ __u8 nfcid1[10];
+ __u8 sel_res_len; /* 0 or 1 Bytes */
+ __u8 sel_res;
+} __packed;
+
+struct activation_params_nfca_poll_iso_dep {
+ __u8 rats_res_len;
+ __u8 rats_res[20];
+};
+
+struct nci_rf_intf_activated_ntf {
+ __u8 rf_discovery_id;
+ __u8 rf_interface;
+ __u8 rf_protocol;
+ __u8 activation_rf_tech_and_mode;
+ __u8 max_data_pkt_payload_size;
+ __u8 initial_num_credits;
+ __u8 rf_tech_specific_params_len;
+
+ union {
+ struct rf_tech_specific_params_nfca_poll nfca_poll;
+ } rf_tech_specific_params;
+
+ __u8 data_exch_rf_tech_and_mode;
+ __u8 data_exch_tx_bit_rate;
+ __u8 data_exch_rx_bit_rate;
+ __u8 activation_params_len;
+
+ union {
+ struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
+ } activation_params;
+
+} __packed;
+
+#define NCI_OP_RF_DEACTIVATE_NTF nci_opcode_pack(NCI_GID_RF_MGMT, 0x06)
+struct nci_rf_deactivate_ntf {
+ __u8 type;
+ __u8 reason;
+} __packed;
+
+#endif /* __NCI_H */
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
new file mode 100644
index 00000000000..bccd89e9d4c
--- /dev/null
+++ b/include/net/nfc/nci_core.h
@@ -0,0 +1,183 @@
+/*
+ * The NFC Controller Interface is the communication protocol between an
+ * NFC Controller (NFCC) and a Device Host (DH).
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ *
+ * Written by Ilan Elias <ilane@ti.com>
+ *
+ * Acknowledgements:
+ * This file is based on hci_core.h, which was written
+ * by Maxim Krasnyansky.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __NCI_CORE_H
+#define __NCI_CORE_H
+
+#include <linux/interrupt.h>
+#include <linux/skbuff.h>
+
+#include <net/nfc/nfc.h>
+#include <net/nfc/nci.h>
+
+/* NCI device state */
+enum {
+ NCI_INIT,
+ NCI_UP,
+ NCI_DISCOVERY,
+ NCI_POLL_ACTIVE,
+ NCI_DATA_EXCHANGE,
+};
+
+/* NCI timeouts */
+#define NCI_RESET_TIMEOUT 5000
+#define NCI_INIT_TIMEOUT 5000
+#define NCI_RF_DISC_TIMEOUT 5000
+#define NCI_RF_DEACTIVATE_TIMEOUT 5000
+#define NCI_CMD_TIMEOUT 5000
+
+struct nci_dev;
+
+struct nci_ops {
+ int (*open)(struct nci_dev *ndev);
+ int (*close)(struct nci_dev *ndev);
+ int (*send)(struct sk_buff *skb);
+};
+
+#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
+
+/* NCI Core structures */
+struct nci_dev {
+ struct nfc_dev *nfc_dev;
+ struct nci_ops *ops;
+
+ int tx_headroom;
+ int tx_tailroom;
+
+ unsigned long flags;
+
+ atomic_t cmd_cnt;
+ atomic_t credits_cnt;
+
+ struct timer_list cmd_timer;
+
+ struct workqueue_struct *cmd_wq;
+ struct work_struct cmd_work;
+
+ struct workqueue_struct *rx_wq;
+ struct work_struct rx_work;
+
+ struct workqueue_struct *tx_wq;
+ struct work_struct tx_work;
+
+ struct sk_buff_head cmd_q;
+ struct sk_buff_head rx_q;
+ struct sk_buff_head tx_q;
+
+ struct mutex req_lock;
+ struct completion req_completion;
+ __u32 req_status;
+ __u32 req_result;
+
+ void *driver_data;
+
+ __u32 poll_prots;
+ __u32 target_available_prots;
+ __u32 target_active_prot;
+
+ /* received during NCI_OP_CORE_RESET_RSP */
+ __u8 nci_ver;
+
+ /* received during NCI_OP_CORE_INIT_RSP */
+ __u32 nfcc_features;
+ __u8 num_supported_rf_interfaces;
+ __u8 supported_rf_interfaces
+ [NCI_MAX_SUPPORTED_RF_INTERFACES];
+ __u8 max_logical_connections;
+ __u16 max_routing_table_size;
+ __u8 max_ctrl_pkt_payload_len;
+ __u16 max_size_for_large_params;
+ __u8 manufact_id;
+ __u32 manufact_specific_info;
+
+ /* received during NCI_OP_RF_INTF_ACTIVATED_NTF */
+ __u8 max_data_pkt_payload_size;
+ __u8 initial_num_credits;
+
+ /* stored during nci_data_exchange */
+ data_exchange_cb_t data_exchange_cb;
+ void *data_exchange_cb_context;
+ struct sk_buff *rx_data_reassembly;
+};
+
+/* ----- NCI Devices ----- */
+struct nci_dev *nci_allocate_device(struct nci_ops *ops,
+ __u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
+void nci_free_device(struct nci_dev *ndev);
+int nci_register_device(struct nci_dev *ndev);
+void nci_unregister_device(struct nci_dev *ndev);
+int nci_recv_frame(struct sk_buff *skb);
+
+static inline struct sk_buff *nci_skb_alloc(struct nci_dev *ndev,
+ unsigned int len,
+ gfp_t how)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(len + ndev->tx_headroom + ndev->tx_tailroom, how);
+ if (skb)
+ skb_reserve(skb, ndev->tx_headroom);
+
+ return skb;
+}
+
+static inline void nci_set_parent_dev(struct nci_dev *ndev, struct device *dev)
+{
+ nfc_set_parent_dev(ndev->nfc_dev, dev);
+}
+
+static inline void nci_set_drvdata(struct nci_dev *ndev, void *data)
+{
+ ndev->driver_data = data;
+}
+
+static inline void *nci_get_drvdata(struct nci_dev *ndev)
+{
+ return ndev->driver_data;
+}
+
+void nci_rsp_packet(struct nci_dev *ndev, struct sk_buff *skb);
+void nci_ntf_packet(struct nci_dev *ndev, struct sk_buff *skb);
+void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb);
+int nci_send_cmd(struct nci_dev *ndev, __u16 opcode, __u8 plen, void *payload);
+int nci_send_data(struct nci_dev *ndev, __u8 conn_id, struct sk_buff *skb);
+void nci_data_exchange_complete(struct nci_dev *ndev, struct sk_buff *skb,
+ int err);
+
+/* ----- NCI requests ----- */
+#define NCI_REQ_DONE 0
+#define NCI_REQ_PEND 1
+#define NCI_REQ_CANCELED 2
+
+void nci_req_complete(struct nci_dev *ndev, int result);
+
+/* ----- NCI status code ----- */
+int nci_to_errno(__u8 code);
+
+#endif /* __NCI_CORE_H */
diff --git a/include/net/nfc.h b/include/net/nfc/nfc.h
index cc0130312f7..8696b773a69 100644
--- a/include/net/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -48,8 +48,13 @@ typedef void (*data_exchange_cb_t)(void *context, struct sk_buff *skb,
int err);
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);
void (*stop_poll)(struct nfc_dev *dev);
+ int (*dep_link_up)(struct nfc_dev *dev, int target_idx,
+ u8 comm_mode, u8 rf_mode);
+ int (*dep_link_down)(struct nfc_dev *dev);
int (*activate_target)(struct nfc_dev *dev, u32 target_idx,
u32 protocol);
void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx);
@@ -58,11 +63,17 @@ struct nfc_ops {
void *cb_context);
};
+#define NFC_TARGET_IDX_ANY -1
+#define NFC_MAX_GT_LEN 48
+#define NFC_MAX_NFCID1_LEN 10
+
struct nfc_target {
u32 idx;
u32 supported_protocols;
u16 sens_res;
u8 sel_res;
+ u8 nfcid1_len;
+ u8 nfcid1[NFC_MAX_NFCID1_LEN];
};
struct nfc_genl_data {
@@ -78,10 +89,17 @@ struct nfc_dev {
int targets_generation;
spinlock_t targets_lock;
struct device dev;
+ bool dev_up;
bool polling;
+ bool remote_activated;
+ bool dep_link_up;
+ u32 dep_rf_mode;
struct nfc_genl_data genl_data;
u32 supported_protocols;
+ int tx_headroom;
+ int tx_tailroom;
+
struct nfc_ops *ops;
};
#define to_nfc_dev(_dev) container_of(_dev, struct nfc_dev, dev)
@@ -89,7 +107,9 @@ struct nfc_dev {
extern struct class nfc_class;
struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
- u32 supported_protocols);
+ u32 supported_protocols,
+ int tx_headroom,
+ int tx_tailroom);
/**
* nfc_free_device - free nfc device
@@ -148,9 +168,20 @@ static inline const char *nfc_device_name(struct nfc_dev *dev)
return dev_name(&dev->dev);
}
-struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp);
+struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk,
+ unsigned int flags, unsigned int size,
+ unsigned int *err);
+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, u8 *gt_len);
int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets,
int ntargets);
+int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx,
+ u8 comm_mode, u8 rf_mode);
+
#endif /* __NET_NFC_H */
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 6f7eb800974..875f4895b03 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -25,7 +25,7 @@
#define _PROTOCOL_H
#include <linux/in6.h>
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
#include <linux/ipv6.h>
#endif
@@ -38,7 +38,7 @@ struct net_protocol {
void (*err_handler)(struct sk_buff *skb, u32 info);
int (*gso_send_check)(struct sk_buff *skb);
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
- u32 features);
+ netdev_features_t features);
struct sk_buff **(*gro_receive)(struct sk_buff **head,
struct sk_buff *skb);
int (*gro_complete)(struct sk_buff *skb);
@@ -46,7 +46,7 @@ struct net_protocol {
netns_ok:1;
};
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct inet6_protocol {
int (*handler)(struct sk_buff *skb);
@@ -57,7 +57,7 @@ struct inet6_protocol {
int (*gso_send_check)(struct sk_buff *skb);
struct sk_buff *(*gso_segment)(struct sk_buff *skb,
- u32 features);
+ netdev_features_t features);
struct sk_buff **(*gro_receive)(struct sk_buff **head,
struct sk_buff *skb);
int (*gro_complete)(struct sk_buff *skb);
@@ -91,7 +91,7 @@ struct inet_protosw {
extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
#endif
@@ -100,7 +100,7 @@ extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num)
extern void inet_register_protosw(struct inet_protosw *p);
extern void inet_unregister_protosw(struct inet_protosw *p);
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num);
extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num);
extern int inet6_register_protosw(struct inet_protosw *p);
diff --git a/include/net/red.h b/include/net/red.h
index 3319f16b3be..28068ec614b 100644
--- a/include/net/red.h
+++ b/include/net/red.h
@@ -5,6 +5,7 @@
#include <net/pkt_sched.h>
#include <net/inet_ecn.h>
#include <net/dsfield.h>
+#include <linux/reciprocal_div.h>
/* Random Early Detection (RED) algorithm.
=======================================
@@ -87,6 +88,29 @@
etc.
*/
+/*
+ * Adaptative RED : An Algorithm for Increasing the Robustness of RED's AQM
+ * (Sally FLoyd, Ramakrishna Gummadi, and Scott Shenker) August 2001
+ *
+ * Every 500 ms:
+ * if (avg > target and max_p <= 0.5)
+ * increase max_p : max_p += alpha;
+ * else if (avg < target and max_p >= 0.01)
+ * decrease max_p : max_p *= beta;
+ *
+ * target :[qth_min + 0.4*(qth_min - qth_max),
+ * qth_min + 0.6*(qth_min - qth_max)].
+ * alpha : min(0.01, max_p / 4)
+ * beta : 0.9
+ * max_P is a Q0.32 fixed point number (with 32 bits mantissa)
+ * max_P between 0.01 and 0.5 (1% - 50%) [ Its no longer a negative power of two ]
+ */
+#define RED_ONE_PERCENT ((u32)DIV_ROUND_CLOSEST(1ULL<<32, 100))
+
+#define MAX_P_MIN (1 * RED_ONE_PERCENT)
+#define MAX_P_MAX (50 * RED_ONE_PERCENT)
+#define MAX_P_ALPHA(val) min(MAX_P_MIN, val / 4)
+
#define RED_STAB_SIZE 256
#define RED_STAB_MASK (RED_STAB_SIZE - 1)
@@ -101,82 +125,113 @@ struct red_stats {
struct red_parms {
/* Parameters */
- u32 qth_min; /* Min avg length threshold: A scaled */
- u32 qth_max; /* Max avg length threshold: A scaled */
+ u32 qth_min; /* Min avg length threshold: Wlog scaled */
+ u32 qth_max; /* Max avg length threshold: Wlog scaled */
u32 Scell_max;
- u32 Rmask; /* Cached random mask, see red_rmask */
+ u32 max_P; /* probability, [0 .. 1.0] 32 scaled */
+ u32 max_P_reciprocal; /* reciprocal_value(max_P / qth_delta) */
+ u32 qth_delta; /* max_th - min_th */
+ u32 target_min; /* min_th + 0.4*(max_th - min_th) */
+ u32 target_max; /* min_th + 0.6*(max_th - min_th) */
u8 Scell_log;
u8 Wlog; /* log(W) */
u8 Plog; /* random number bits */
u8 Stab[RED_STAB_SIZE];
+};
+struct red_vars {
/* Variables */
int qcount; /* Number of packets since last random
number generation */
u32 qR; /* Cached random number */
- unsigned long qavg; /* Average queue length: A scaled */
- psched_time_t qidlestart; /* Start of current idle period */
+ unsigned long qavg; /* Average queue length: Wlog scaled */
+ ktime_t qidlestart; /* Start of current idle period */
};
-static inline u32 red_rmask(u8 Plog)
+static inline u32 red_maxp(u8 Plog)
{
- return Plog < 32 ? ((1 << Plog) - 1) : ~0UL;
+ return Plog < 32 ? (~0U >> Plog) : ~0U;
}
-static inline void red_set_parms(struct red_parms *p,
- u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog,
- u8 Scell_log, u8 *stab)
+static inline void red_set_vars(struct red_vars *v)
{
/* Reset average queue length, the value is strictly bound
* to the parameters below, reseting hurts a bit but leaving
* it might result in an unreasonable qavg for a while. --TGR
*/
- p->qavg = 0;
+ v->qavg = 0;
+
+ v->qcount = -1;
+}
+
+static inline void red_set_parms(struct red_parms *p,
+ u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog,
+ u8 Scell_log, u8 *stab, u32 max_P)
+{
+ int delta = qth_max - qth_min;
+ u32 max_p_delta;
- p->qcount = -1;
p->qth_min = qth_min << Wlog;
p->qth_max = qth_max << Wlog;
p->Wlog = Wlog;
p->Plog = Plog;
- p->Rmask = red_rmask(Plog);
+ if (delta < 0)
+ delta = 1;
+ p->qth_delta = delta;
+ if (!max_P) {
+ max_P = red_maxp(Plog);
+ max_P *= delta; /* max_P = (qth_max - qth_min)/2^Plog */
+ }
+ p->max_P = max_P;
+ max_p_delta = max_P / delta;
+ max_p_delta = max(max_p_delta, 1U);
+ p->max_P_reciprocal = reciprocal_value(max_p_delta);
+
+ /* RED Adaptative target :
+ * [min_th + 0.4*(min_th - max_th),
+ * min_th + 0.6*(min_th - max_th)].
+ */
+ delta /= 5;
+ p->target_min = qth_min + 2*delta;
+ p->target_max = qth_min + 3*delta;
+
p->Scell_log = Scell_log;
p->Scell_max = (255 << Scell_log);
- memcpy(p->Stab, stab, sizeof(p->Stab));
+ if (stab)
+ memcpy(p->Stab, stab, sizeof(p->Stab));
}
-static inline int red_is_idling(struct red_parms *p)
+static inline int red_is_idling(const struct red_vars *v)
{
- return p->qidlestart != PSCHED_PASTPERFECT;
+ return v->qidlestart.tv64 != 0;
}
-static inline void red_start_of_idle_period(struct red_parms *p)
+static inline void red_start_of_idle_period(struct red_vars *v)
{
- p->qidlestart = psched_get_time();
+ v->qidlestart = ktime_get();
}
-static inline void red_end_of_idle_period(struct red_parms *p)
+static inline void red_end_of_idle_period(struct red_vars *v)
{
- p->qidlestart = PSCHED_PASTPERFECT;
+ v->qidlestart.tv64 = 0;
}
-static inline void red_restart(struct red_parms *p)
+static inline void red_restart(struct red_vars *v)
{
- red_end_of_idle_period(p);
- p->qavg = 0;
- p->qcount = -1;
+ red_end_of_idle_period(v);
+ v->qavg = 0;
+ v->qcount = -1;
}
-static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p)
+static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms *p,
+ const struct red_vars *v)
{
- psched_time_t now;
- long us_idle;
+ s64 delta = ktime_us_delta(ktime_get(), v->qidlestart);
+ long us_idle = min_t(s64, delta, p->Scell_max);
int shift;
- now = psched_get_time();
- us_idle = psched_tdiff_bounded(now, p->qidlestart, p->Scell_max);
-
/*
* The problem: ideally, average length queue recalcultion should
* be done over constant clock intervals. This is too expensive, so
@@ -200,7 +255,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p)
shift = p->Stab[(us_idle >> p->Scell_log) & RED_STAB_MASK];
if (shift)
- return p->qavg >> shift;
+ return v->qavg >> shift;
else {
/* Approximate initial part of exponent with linear function:
*
@@ -209,16 +264,17 @@ static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p)
* Seems, it is the best solution to
* problem of too coarse exponent tabulation.
*/
- us_idle = (p->qavg * (u64)us_idle) >> p->Scell_log;
+ us_idle = (v->qavg * (u64)us_idle) >> p->Scell_log;
- if (us_idle < (p->qavg >> 1))
- return p->qavg - us_idle;
+ if (us_idle < (v->qavg >> 1))
+ return v->qavg - us_idle;
else
- return p->qavg >> 1;
+ return v->qavg >> 1;
}
}
-static inline unsigned long red_calc_qavg_no_idle_time(struct red_parms *p,
+static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p,
+ const struct red_vars *v,
unsigned int backlog)
{
/*
@@ -230,42 +286,46 @@ static inline unsigned long red_calc_qavg_no_idle_time(struct red_parms *p,
*
* --ANK (980924)
*/
- return p->qavg + (backlog - (p->qavg >> p->Wlog));
+ return v->qavg + (backlog - (v->qavg >> p->Wlog));
}
-static inline unsigned long red_calc_qavg(struct red_parms *p,
+static inline unsigned long red_calc_qavg(const struct red_parms *p,
+ const struct red_vars *v,
unsigned int backlog)
{
- if (!red_is_idling(p))
- return red_calc_qavg_no_idle_time(p, backlog);
+ if (!red_is_idling(v))
+ return red_calc_qavg_no_idle_time(p, v, backlog);
else
- return red_calc_qavg_from_idle_time(p);
+ return red_calc_qavg_from_idle_time(p, v);
}
-static inline u32 red_random(struct red_parms *p)
+
+static inline u32 red_random(const struct red_parms *p)
{
- return net_random() & p->Rmask;
+ return reciprocal_divide(net_random(), p->max_P_reciprocal);
}
-static inline int red_mark_probability(struct red_parms *p, unsigned long qavg)
+static inline int red_mark_probability(const struct red_parms *p,
+ const struct red_vars *v,
+ unsigned long qavg)
{
/* The formula used below causes questions.
- OK. qR is random number in the interval 0..Rmask
+ OK. qR is random number in the interval
+ (0..1/max_P)*(qth_max-qth_min)
i.e. 0..(2^Plog). If we used floating point
arithmetics, it would be: (2^Plog)*rnd_num,
where rnd_num is less 1.
Taking into account, that qavg have fixed
- point at Wlog, and Plog is related to max_P by
- max_P = (qth_max-qth_min)/2^Plog; two lines
+ point at Wlog, two lines
below have the following floating point equivalent:
max_P*(qavg - qth_min)/(qth_max-qth_min) < rnd/qcount
Any questions? --ANK (980924)
*/
- return !(((qavg - p->qth_min) >> p->Wlog) * p->qcount < p->qR);
+ return !(((qavg - p->qth_min) >> p->Wlog) * v->qcount < v->qR);
}
enum {
@@ -274,7 +334,7 @@ enum {
RED_ABOVE_MAX_TRESH,
};
-static inline int red_cmp_thresh(struct red_parms *p, unsigned long qavg)
+static inline int red_cmp_thresh(const struct red_parms *p, unsigned long qavg)
{
if (qavg < p->qth_min)
return RED_BELOW_MIN_THRESH;
@@ -290,27 +350,29 @@ enum {
RED_HARD_MARK,
};
-static inline int red_action(struct red_parms *p, unsigned long qavg)
+static inline int red_action(const struct red_parms *p,
+ struct red_vars *v,
+ unsigned long qavg)
{
switch (red_cmp_thresh(p, qavg)) {
case RED_BELOW_MIN_THRESH:
- p->qcount = -1;
+ v->qcount = -1;
return RED_DONT_MARK;
case RED_BETWEEN_TRESH:
- if (++p->qcount) {
- if (red_mark_probability(p, qavg)) {
- p->qcount = 0;
- p->qR = red_random(p);
+ if (++v->qcount) {
+ if (red_mark_probability(p, v, qavg)) {
+ v->qcount = 0;
+ v->qR = red_random(p);
return RED_PROB_MARK;
}
} else
- p->qR = red_random(p);
+ v->qR = red_random(p);
return RED_DONT_MARK;
case RED_ABOVE_MAX_TRESH:
- p->qcount = -1;
+ v->qcount = -1;
return RED_HARD_MARK;
}
@@ -318,4 +380,25 @@ static inline int red_action(struct red_parms *p, unsigned long qavg)
return RED_DONT_MARK;
}
+static inline void red_adaptative_algo(struct red_parms *p, struct red_vars *v)
+{
+ unsigned long qavg;
+ u32 max_p_delta;
+
+ qavg = v->qavg;
+ if (red_is_idling(v))
+ qavg = red_calc_qavg_from_idle_time(p, v);
+
+ /* p->qavg is fixed point number with point at Wlog */
+ qavg >>= p->Wlog;
+
+ if (qavg > p->target_max && p->max_P <= MAX_P_MAX)
+ p->max_P += MAX_P_ALPHA(p->max_P); /* maxp = maxp + alpha */
+ else if (qavg < p->target_min && p->max_P >= MAX_P_MIN)
+ p->max_P = (p->max_P/10)*9; /* maxp = maxp * Beta */
+
+ max_p_delta = DIV_ROUND_CLOSEST(p->max_P, p->qth_delta);
+ max_p_delta = max(max_p_delta, 1U);
+ p->max_P_reciprocal = reciprocal_value(max_p_delta);
+}
#endif
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index 356d6e3dc20..a5f79933e21 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -3,11 +3,19 @@
/*
* regulatory support structures
*
- * Copyright 2008-2009 Luis R. Rodriguez <lrodriguez@atheros.com>
+ * Copyright 2008-2009 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
*
- * 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.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, 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.
*/
@@ -40,6 +48,10 @@ enum environment_cap {
* 99 - built by driver but a specific alpha2 cannot be determined
* 98 - result of an intersection between two regulatory domains
* 97 - regulatory domain has not yet been configured
+ * @dfs_region: If CRDA responded with a regulatory domain that requires
+ * 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.
* @intersect: indicates whether the wireless core should intersect
* the requested regulatory domain with the presently set regulatory
* domain.
@@ -59,6 +71,7 @@ struct regulatory_request {
int wiphy_idx;
enum nl80211_reg_initiator initiator;
char alpha2[2];
+ u8 dfs_region;
bool intersect;
bool processed;
enum environment_cap country_ie_env;
@@ -85,6 +98,7 @@ struct ieee80211_reg_rule {
struct ieee80211_regdomain {
u32 n_reg_rules;
char alpha2[2];
+ u8 dfs_region;
struct ieee80211_reg_rule reg_rules[];
};
diff --git a/include/net/route.h b/include/net/route.h
index db7b3432f07..91855d185b5 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -71,12 +71,12 @@ struct rtable {
struct fib_info *fi; /* for client ref to shared metrics */
};
-static inline bool rt_is_input_route(struct rtable *rt)
+static inline bool rt_is_input_route(const struct rtable *rt)
{
return rt->rt_route_iif != 0;
}
-static inline bool rt_is_output_route(struct rtable *rt)
+static inline bool rt_is_output_route(const struct rtable *rt)
{
return rt->rt_route_iif == 0;
}
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 4fc88f3ccd5..f6bb08b73ca 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -4,7 +4,6 @@
#include <linux/netdevice.h>
#include <linux/types.h>
#include <linux/rcupdate.h>
-#include <linux/module.h>
#include <linux/pkt_sched.h>
#include <linux/pkt_cls.h>
#include <net/gen_stats.h>
@@ -46,14 +45,14 @@ struct qdisc_size_table {
struct Qdisc {
int (*enqueue)(struct sk_buff *skb, struct Qdisc *dev);
struct sk_buff * (*dequeue)(struct Qdisc *dev);
- unsigned flags;
+ unsigned int flags;
#define TCQ_F_BUILTIN 1
#define TCQ_F_INGRESS 2
#define TCQ_F_CAN_BYPASS 4
#define TCQ_F_MQROOT 8
#define TCQ_F_WARN_NONWC (1 << 16)
int padded;
- struct Qdisc_ops *ops;
+ const struct Qdisc_ops *ops;
struct qdisc_size_table __rcu *stab;
struct list_head list;
u32 handle;
@@ -224,7 +223,7 @@ struct qdisc_skb_cb {
long data[];
};
-static inline int qdisc_qlen(struct Qdisc *q)
+static inline int qdisc_qlen(const struct Qdisc *q)
{
return q->q.qlen;
}
@@ -239,12 +238,12 @@ static inline spinlock_t *qdisc_lock(struct Qdisc *qdisc)
return &qdisc->q.lock;
}
-static inline struct Qdisc *qdisc_root(struct Qdisc *qdisc)
+static inline struct Qdisc *qdisc_root(const struct Qdisc *qdisc)
{
return qdisc->dev_queue->qdisc;
}
-static inline struct Qdisc *qdisc_root_sleeping(struct Qdisc *qdisc)
+static inline struct Qdisc *qdisc_root_sleeping(const struct Qdisc *qdisc)
{
return qdisc->dev_queue->qdisc_sleeping;
}
@@ -260,7 +259,7 @@ static inline struct Qdisc *qdisc_root_sleeping(struct Qdisc *qdisc)
* root. This is enforced by holding the RTNL semaphore, which
* all users of this lock accessor must do.
*/
-static inline spinlock_t *qdisc_root_lock(struct Qdisc *qdisc)
+static inline spinlock_t *qdisc_root_lock(const struct Qdisc *qdisc)
{
struct Qdisc *root = qdisc_root(qdisc);
@@ -268,7 +267,7 @@ static inline spinlock_t *qdisc_root_lock(struct Qdisc *qdisc)
return qdisc_lock(root);
}
-static inline spinlock_t *qdisc_root_sleeping_lock(struct Qdisc *qdisc)
+static inline spinlock_t *qdisc_root_sleeping_lock(const struct Qdisc *qdisc)
{
struct Qdisc *root = qdisc_root_sleeping(qdisc);
@@ -276,17 +275,17 @@ static inline spinlock_t *qdisc_root_sleeping_lock(struct Qdisc *qdisc)
return qdisc_lock(root);
}
-static inline struct net_device *qdisc_dev(struct Qdisc *qdisc)
+static inline struct net_device *qdisc_dev(const struct Qdisc *qdisc)
{
return qdisc->dev_queue->dev;
}
-static inline void sch_tree_lock(struct Qdisc *q)
+static inline void sch_tree_lock(const struct Qdisc *q)
{
spin_lock_bh(qdisc_root_sleeping_lock(q));
}
-static inline void sch_tree_unlock(struct Qdisc *q)
+static inline void sch_tree_unlock(const struct Qdisc *q)
{
spin_unlock_bh(qdisc_root_sleeping_lock(q));
}
@@ -319,7 +318,7 @@ static inline unsigned int qdisc_class_hash(u32 id, u32 mask)
}
static inline struct Qdisc_class_common *
-qdisc_class_find(struct Qdisc_class_hash *hash, u32 id)
+qdisc_class_find(const struct Qdisc_class_hash *hash, u32 id)
{
struct Qdisc_class_common *cl;
struct hlist_node *n;
@@ -393,7 +392,7 @@ static inline bool qdisc_all_tx_empty(const struct net_device *dev)
}
/* Are any of the TX qdiscs changing? */
-static inline bool qdisc_tx_changing(struct net_device *dev)
+static inline bool qdisc_tx_changing(const struct net_device *dev)
{
unsigned int i;
for (i = 0; i < dev->num_tx_queues; i++) {
diff --git a/include/net/scm.h b/include/net/scm.h
index 745460fa2f0..d456f4c71a3 100644
--- a/include/net/scm.h
+++ b/include/net/scm.h
@@ -49,7 +49,7 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,
struct pid *pid, const struct cred *cred)
{
scm->pid = get_pid(pid);
- scm->cred = get_cred(cred);
+ scm->cred = cred ? get_cred(cred) : NULL;
cred_to_ucred(pid, cred, &scm->creds);
}
@@ -73,8 +73,7 @@ static __inline__ void scm_destroy(struct scm_cookie *scm)
static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
struct scm_cookie *scm)
{
- scm_set_cred(scm, task_tgid(current), current_cred());
- scm->fp = NULL;
+ memset(scm, 0, sizeof(*scm));
unix_get_peersec_dgram(sock, scm);
if (msg->msg_controllen <= 0)
return 0;
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 6a72a58cde5..d3685615a8b 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -71,7 +71,7 @@
#include <linux/jiffies.h>
#include <linux/idr.h>
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
#include <net/ip6_route.h>
#endif
@@ -383,7 +383,7 @@ static inline void sctp_sysctl_unregister(void) { return; }
/* Size of Supported Address Parameter for 'x' address types. */
#define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16))
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
void sctp_v6_pf_init(void);
void sctp_v6_pf_exit(void);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index f7d9c3fc06f..88949a99453 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -235,12 +235,15 @@ extern struct sctp_globals {
/* Flag to indicate whether computing and verifying checksum
* is disabled. */
- int checksum_disable;
+ bool checksum_disable;
/* Threshold for rwnd update SACKS. Receive buffer shifted this many
* bits is an indicator of when to send and window update SACK.
*/
int rwnd_update_shift;
+
+ /* Threshold for autoclose timeout, in seconds. */
+ unsigned long max_autoclose;
} sctp_globals;
#define sctp_rto_initial (sctp_globals.rto_initial)
@@ -281,6 +284,7 @@ extern struct sctp_globals {
#define sctp_auth_enable (sctp_globals.auth_enable)
#define sctp_checksum_disable (sctp_globals.checksum_disable)
#define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift)
+#define sctp_max_autoclose (sctp_globals.max_autoclose)
/* SCTP Socket type: UDP or TCP style. */
typedef enum {
@@ -365,7 +369,7 @@ static inline struct sock *sctp_opt2sk(const struct sctp_sock *sp)
return (struct sock *)sp;
}
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct sctp6_sock {
struct sctp_sock sctp;
struct ipv6_pinfo inet6;
@@ -1085,6 +1089,7 @@ 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_immediate_rtx(struct sctp_transport *);
/* This is the structure we use to queue packets as they come into
@@ -1915,6 +1920,7 @@ struct sctp_association {
__u32 addip_serial;
union sctp_addr *asconf_addr_del_pending;
int src_out_of_asoc_ok;
+ struct sctp_transport *new_transport;
/* SCTP AUTH: list of the endpoint shared keys. These
* keys are provided out of band by the user applicaton
diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h
index d97f6892c01..c2e542b27a5 100644
--- a/include/net/secure_seq.h
+++ b/include/net/secure_seq.h
@@ -10,7 +10,7 @@ extern u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
__be16 dport);
extern __u32 secure_tcp_sequence_number(__be32 saddr, __be32 daddr,
__be16 sport, __be16 dport);
-extern __u32 secure_tcpv6_sequence_number(__be32 *saddr, __be32 *daddr,
+extern __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
__be16 sport, __be16 dport);
extern u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
__be16 sport, __be16 dport);
diff --git a/include/net/snmp.h b/include/net/snmp.h
index 8f0f9ac0307..0147b901e79 100644
--- a/include/net/snmp.h
+++ b/include/net/snmp.h
@@ -67,7 +67,7 @@ struct icmp_mib {
#define ICMPMSG_MIB_MAX __ICMPMSG_MIB_MAX
struct icmpmsg_mib {
- unsigned long mibs[ICMPMSG_MIB_MAX];
+ atomic_long_t mibs[ICMPMSG_MIB_MAX];
};
/* ICMP6 (IPv6-ICMP) */
@@ -84,7 +84,7 @@ struct icmpv6_mib_device {
#define ICMP6MSG_MIB_MAX __ICMP6MSG_MIB_MAX
/* per network ns counters */
struct icmpv6msg_mib {
- unsigned long mibs[ICMP6MSG_MIB_MAX];
+ atomic_long_t mibs[ICMP6MSG_MIB_MAX];
};
/* per device counters, (shared on all cpus) */
struct icmpv6msg_mib_device {
@@ -129,33 +129,33 @@ struct linux_xfrm_mib {
__this_cpu_inc(mib[0]->mibs[field])
#define SNMP_INC_STATS_USER(mib, field) \
- irqsafe_cpu_inc(mib[0]->mibs[field])
+ this_cpu_inc(mib[0]->mibs[field])
#define SNMP_INC_STATS_ATOMIC_LONG(mib, field) \
atomic_long_inc(&mib->mibs[field])
#define SNMP_INC_STATS(mib, field) \
- irqsafe_cpu_inc(mib[0]->mibs[field])
+ this_cpu_inc(mib[0]->mibs[field])
#define SNMP_DEC_STATS(mib, field) \
- irqsafe_cpu_dec(mib[0]->mibs[field])
+ this_cpu_dec(mib[0]->mibs[field])
#define SNMP_ADD_STATS_BH(mib, field, addend) \
__this_cpu_add(mib[0]->mibs[field], addend)
#define SNMP_ADD_STATS_USER(mib, field, addend) \
- irqsafe_cpu_add(mib[0]->mibs[field], addend)
+ this_cpu_add(mib[0]->mibs[field], addend)
#define SNMP_ADD_STATS(mib, field, addend) \
- irqsafe_cpu_add(mib[0]->mibs[field], addend)
+ this_cpu_add(mib[0]->mibs[field], addend)
/*
* Use "__typeof__(*mib[0]) *ptr" instead of "__typeof__(mib[0]) ptr"
* to make @ptr a non-percpu pointer.
*/
#define SNMP_UPD_PO_STATS(mib, basefield, addend) \
do { \
- irqsafe_cpu_inc(mib[0]->mibs[basefield##PKTS]); \
- irqsafe_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \
+ this_cpu_inc(mib[0]->mibs[basefield##PKTS]); \
+ this_cpu_add(mib[0]->mibs[basefield##OCTETS], addend); \
} while (0)
#define SNMP_UPD_PO_STATS_BH(mib, basefield, addend) \
do { \
diff --git a/include/net/sock.h b/include/net/sock.h
index 8e4062f165b..bb972d254df 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -46,7 +46,6 @@
#include <linux/list_nulls.h>
#include <linux/timer.h>
#include <linux/cache.h>
-#include <linux/module.h>
#include <linux/lockdep.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h> /* struct sk_buff */
@@ -54,6 +53,8 @@
#include <linux/security.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
+#include <linux/memcontrol.h>
+#include <linux/res_counter.h>
#include <linux/filter.h>
#include <linux/rculist_nulls.h>
@@ -63,6 +64,22 @@
#include <net/dst.h>
#include <net/checksum.h>
+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, struct cgroup_subsys *ss);
+#else
+static inline
+int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss)
+{
+ return 0;
+}
+static inline
+void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss)
+{
+}
+#endif
/*
* This structure really needs to be cleaned up.
* Most of it is for TCP, and not used by any of
@@ -76,8 +93,8 @@
printk(KERN_DEBUG msg); } while (0)
#else
/* Validate arguments and do nothing */
-static inline void __attribute__ ((format (printf, 2, 3)))
-SOCK_DEBUG(struct sock *sk, const char *msg, ...)
+static inline __printf(2, 3)
+void SOCK_DEBUG(struct sock *sk, const char *msg, ...)
{
}
#endif
@@ -168,6 +185,7 @@ struct sock_common {
/* public: */
};
+struct cg_proto;
/**
* struct sock - network layer representation of sockets
* @__sk_common: shared layout with inet_timewait_sock
@@ -228,6 +246,7 @@ struct sock_common {
* @sk_security: used by security modules
* @sk_mark: generic packet mark
* @sk_classid: this socket's cgroup classid
+ * @sk_cgrp: this socket's cgroup-specific proto data
* @sk_write_pending: a write to stream socket waits to start
* @sk_state_change: callback to indicate change in the state of the sock
* @sk_data_ready: callback to indicate there is data to be processed
@@ -307,8 +326,8 @@ struct sock {
kmemcheck_bitfield_end(flags);
int sk_wmem_queued;
gfp_t sk_allocation;
- int sk_route_caps;
- int sk_route_nocaps;
+ netdev_features_t sk_route_caps;
+ netdev_features_t sk_route_nocaps;
int sk_gso_type;
unsigned int sk_gso_max_size;
int sk_rcvlowat;
@@ -321,6 +340,9 @@ struct sock {
unsigned short sk_ack_backlog;
unsigned short sk_max_ack_backlog;
__u32 sk_priority;
+#ifdef CONFIG_CGROUPS
+ __u32 sk_cgrp_prioidx;
+#endif
struct pid *sk_peer_pid;
const struct cred *sk_peer_cred;
long sk_rcvtimeo;
@@ -339,6 +361,7 @@ struct sock {
#endif
__u32 sk_mark;
u32 sk_classid;
+ struct cg_proto *sk_cgrp;
void (*sk_state_change)(struct sock *sk);
void (*sk_data_ready)(struct sock *sk, int bytes);
void (*sk_write_space)(struct sock *sk);
@@ -564,6 +587,7 @@ enum sock_flags {
SOCK_FASYNC, /* fasync() active */
SOCK_RXQ_OVFL,
SOCK_ZEROCOPY, /* buffers from userspace */
+ SOCK_WIFI_STATUS, /* push wifi status to userspace */
};
static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -638,12 +662,14 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb)
/*
* Take into account size of receive queue and backlog queue
+ * 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)
{
unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc);
- return qsize + skb->truesize > sk->sk_rcvbuf;
+ return qsize > sk->sk_rcvbuf;
}
/* The per-socket spinlock must be held here. */
@@ -686,16 +712,25 @@ static inline void sock_rps_reset_flow(const struct sock *sk)
#endif
}
-static inline void sock_rps_save_rxhash(struct sock *sk, u32 rxhash)
+static inline void sock_rps_save_rxhash(struct sock *sk,
+ const struct sk_buff *skb)
{
#ifdef CONFIG_RPS
- if (unlikely(sk->sk_rxhash != rxhash)) {
+ if (unlikely(sk->sk_rxhash != skb->rxhash)) {
sock_rps_reset_flow(sk);
- sk->sk_rxhash = rxhash;
+ sk->sk_rxhash = skb->rxhash;
}
#endif
}
+static inline void sock_rps_reset_rxhash(struct sock *sk)
+{
+#ifdef CONFIG_RPS
+ sock_rps_reset_flow(sk);
+ sk->sk_rxhash = 0;
+#endif
+}
+
#define sk_wait_event(__sk, __timeo, __condition) \
({ int __rc; \
release_sock(__sk); \
@@ -720,6 +755,7 @@ struct request_sock_ops;
struct timewait_sock_ops;
struct inet_hashinfo;
struct raw_hashinfo;
+struct module;
/* Networking protocol blocks we attach to sockets.
* socket layer -> transport layer interface
@@ -824,6 +860,37 @@ struct proto {
#ifdef SOCK_REFCNT_DEBUG
atomic_t socks;
#endif
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_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,
+ struct cgroup_subsys *ss);
+ void (*destroy_cgroup)(struct cgroup *cgrp,
+ struct cgroup_subsys *ss);
+ struct cg_proto *(*proto_cgroup)(struct mem_cgroup *memcg);
+#endif
+};
+
+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;
+ /*
+ * memcg field is used to find which memcg we belong directly
+ * Each memcg struct can hold more than one cg_proto, so container_of
+ * won't really cut.
+ *
+ * The elegant solution would be having an inverse function to
+ * proto_cgroup in struct proto, but that means polluting the structure
+ * for everybody, instead of just for memcg users.
+ */
+ struct mem_cgroup *memcg;
};
extern int proto_register(struct proto *prot, int alloc_slab);
@@ -842,7 +909,7 @@ static inline void sk_refcnt_debug_dec(struct sock *sk)
sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks));
}
-static inline void sk_refcnt_debug_release(const struct sock *sk)
+inline void sk_refcnt_debug_release(const struct sock *sk)
{
if (atomic_read(&sk->sk_refcnt) != 1)
printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n",
@@ -854,6 +921,208 @@ static inline void sk_refcnt_debug_release(const struct sock *sk)
#define sk_refcnt_debug_release(sk) do { } while (0)
#endif /* SOCK_REFCNT_DEBUG */
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM
+extern struct jump_label_key memcg_socket_limit_enabled;
+static inline struct cg_proto *parent_cg_proto(struct proto *proto,
+ struct cg_proto *cg_proto)
+{
+ return proto->proto_cgroup(parent_mem_cgroup(cg_proto->memcg));
+}
+#define mem_cgroup_sockets_enabled static_branch(&memcg_socket_limit_enabled)
+#else
+#define mem_cgroup_sockets_enabled 0
+static inline struct cg_proto *parent_cg_proto(struct proto *proto,
+ struct cg_proto *cg_proto)
+{
+ return NULL;
+}
+#endif
+
+
+static inline bool sk_has_memory_pressure(const struct sock *sk)
+{
+ return sk->sk_prot->memory_pressure != NULL;
+}
+
+static inline bool sk_under_memory_pressure(const struct sock *sk)
+{
+ if (!sk->sk_prot->memory_pressure)
+ return false;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ return !!*sk->sk_cgrp->memory_pressure;
+
+ return !!*sk->sk_prot->memory_pressure;
+}
+
+static inline void sk_leave_memory_pressure(struct sock *sk)
+{
+ int *memory_pressure = sk->sk_prot->memory_pressure;
+
+ if (!memory_pressure)
+ return;
+
+ if (*memory_pressure)
+ *memory_pressure = 0;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+ struct proto *prot = sk->sk_prot;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ if (*cg_proto->memory_pressure)
+ *cg_proto->memory_pressure = 0;
+ }
+
+}
+
+static inline void sk_enter_memory_pressure(struct sock *sk)
+{
+ if (!sk->sk_prot->enter_memory_pressure)
+ return;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+ struct proto *prot = sk->sk_prot;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ cg_proto->enter_memory_pressure(sk);
+ }
+
+ sk->sk_prot->enter_memory_pressure(sk);
+}
+
+static inline long sk_prot_mem_limits(const struct sock *sk, int index)
+{
+ long *prot = sk->sk_prot->sysctl_mem;
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ prot = sk->sk_cgrp->sysctl_mem;
+ return prot[index];
+}
+
+static inline void memcg_memory_allocated_add(struct cg_proto *prot,
+ unsigned long amt,
+ int *parent_status)
+{
+ struct res_counter *fail;
+ int ret;
+
+ ret = res_counter_charge(prot->memory_allocated,
+ amt << PAGE_SHIFT, &fail);
+
+ if (ret < 0)
+ *parent_status = OVER_LIMIT;
+}
+
+static inline void memcg_memory_allocated_sub(struct cg_proto *prot,
+ unsigned long amt)
+{
+ res_counter_uncharge(prot->memory_allocated, amt << PAGE_SHIFT);
+}
+
+static inline u64 memcg_memory_allocated_read(struct cg_proto *prot)
+{
+ u64 ret;
+ ret = res_counter_read_u64(prot->memory_allocated, RES_USAGE);
+ return ret >> PAGE_SHIFT;
+}
+
+static inline long
+sk_memory_allocated(const struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ return memcg_memory_allocated_read(sk->sk_cgrp);
+
+ return atomic_long_read(prot->memory_allocated);
+}
+
+static inline long
+sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ memcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status);
+ /* update the root cgroup regardless */
+ atomic_long_add_return(amt, prot->memory_allocated);
+ return memcg_memory_allocated_read(sk->sk_cgrp);
+ }
+
+ return atomic_long_add_return(amt, prot->memory_allocated);
+}
+
+static inline void
+sk_memory_allocated_sub(struct sock *sk, int amt, int parent_status)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp &&
+ parent_status != OVER_LIMIT) /* Otherwise was uncharged already */
+ memcg_memory_allocated_sub(sk->sk_cgrp, amt);
+
+ atomic_long_sub(amt, prot->memory_allocated);
+}
+
+static inline void sk_sockets_allocated_dec(struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ percpu_counter_dec(cg_proto->sockets_allocated);
+ }
+
+ percpu_counter_dec(prot->sockets_allocated);
+}
+
+static inline void sk_sockets_allocated_inc(struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp) {
+ struct cg_proto *cg_proto = sk->sk_cgrp;
+
+ for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto))
+ percpu_counter_inc(cg_proto->sockets_allocated);
+ }
+
+ percpu_counter_inc(prot->sockets_allocated);
+}
+
+static inline int
+sk_sockets_allocated_read_positive(struct sock *sk)
+{
+ struct proto *prot = sk->sk_prot;
+
+ if (mem_cgroup_sockets_enabled && sk->sk_cgrp)
+ return percpu_counter_sum_positive(sk->sk_cgrp->sockets_allocated);
+
+ return percpu_counter_sum_positive(prot->sockets_allocated);
+}
+
+static inline int
+proto_sockets_allocated_sum_positive(struct proto *prot)
+{
+ return percpu_counter_sum_positive(prot->sockets_allocated);
+}
+
+static inline long
+proto_memory_allocated(struct proto *prot)
+{
+ return atomic_long_read(prot->memory_allocated);
+}
+
+static inline bool
+proto_memory_pressure(struct proto *prot)
+{
+ if (!prot->memory_pressure)
+ return false;
+ return !!*prot->memory_pressure;
+}
+
#ifdef CONFIG_PROC_FS
/* Called with local bh disabled */
@@ -1080,8 +1349,8 @@ extern struct sock *sk_alloc(struct net *net, int family,
struct proto *prot);
extern void sk_free(struct sock *sk);
extern void sk_release_kernel(struct sock *sk);
-extern struct sock *sk_clone(const struct sock *sk,
- const gfp_t priority);
+extern struct sock *sk_clone_lock(const struct sock *sk,
+ const gfp_t priority);
extern struct sk_buff *sock_wmalloc(struct sock *sk,
unsigned long size, int force,
@@ -1384,7 +1653,7 @@ static inline int sk_can_gso(const struct sock *sk)
extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst);
-static inline void sk_nocaps_add(struct sock *sk, int flags)
+static inline void sk_nocaps_add(struct sock *sk, netdev_features_t flags)
{
sk->sk_route_nocaps |= flags;
sk->sk_route_caps &= ~flags;
@@ -1661,7 +1930,7 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk)
page = alloc_pages(sk->sk_allocation, 0);
if (!page) {
- sk->sk_prot->enter_memory_pressure(sk);
+ sk_enter_memory_pressure(sk);
sk_stream_moderate_sndbuf(sk);
}
return page;
@@ -1705,6 +1974,8 @@ static inline int sock_intr_errno(long timeo)
extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
struct sk_buff *skb);
+extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb);
static __inline__ void
sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
@@ -1732,6 +2003,9 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
__sock_recv_timestamp(msg, sk, skb);
else
sk->sk_stamp = kt;
+
+ if (sock_flag(sk, SOCK_WIFI_STATUS) && skb->wifi_acked_valid)
+ __sock_recv_wifi_status(msg, sk, skb);
}
extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
diff --git a/include/net/tcp.h b/include/net/tcp.h
index acc620a4a45..0118ea999f6 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -18,7 +18,6 @@
#ifndef _TCP_H
#define _TCP_H
-#define TCP_DEBUG 1
#define FASTRETRANS_DEBUG 1
#include <linux/list.h>
@@ -45,6 +44,7 @@
#include <net/dst.h>
#include <linux/seq_file.h>
+#include <linux/memcontrol.h>
extern struct inet_hashinfo tcp_hashinfo;
@@ -230,7 +230,6 @@ extern int sysctl_tcp_fack;
extern int sysctl_tcp_reordering;
extern int sysctl_tcp_ecn;
extern int sysctl_tcp_dsack;
-extern long sysctl_tcp_mem[3];
extern int sysctl_tcp_wmem[3];
extern int sysctl_tcp_rmem[3];
extern int sysctl_tcp_app_win;
@@ -286,7 +285,7 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift)
}
if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF &&
- atomic_long_read(&tcp_memory_allocated) > sysctl_tcp_mem[2])
+ sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2))
return true;
return false;
}
@@ -327,9 +326,9 @@ extern int tcp_sendpage(struct sock *sk, struct page *page, int offset,
size_t size, int flags);
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,
- struct tcphdr *th, unsigned len);
+ const struct tcphdr *th, unsigned int len);
extern int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
- struct tcphdr *th, unsigned len);
+ const struct tcphdr *th, unsigned int len);
extern void tcp_rcv_space_adjust(struct sock *sk);
extern void tcp_cleanup_rbuf(struct sock *sk, int copied);
extern int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp);
@@ -356,6 +355,7 @@ static inline void tcp_dec_quickack_mode(struct sock *sk,
#define TCP_ECN_OK 1
#define TCP_ECN_QUEUE_CWR 2
#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)
@@ -400,10 +400,10 @@ extern void tcp_set_keepalive(struct sock *sk, int val);
extern void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req);
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(struct sk_buff *skb,
- struct tcp_options_received *opt_rx, u8 **hvpp,
+extern void tcp_parse_options(const struct sk_buff *skb,
+ struct tcp_options_received *opt_rx, const u8 **hvpp,
int estab);
-extern u8 *tcp_parse_md5sig_option(struct tcphdr *th);
+extern const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
/*
* TCP v4 functions exported for the inet6 API
@@ -449,7 +449,7 @@ extern bool cookie_check_timestamp(struct tcp_options_received *opt, bool *);
/* From net/ipv6/syncookies.c */
extern struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb);
#ifdef CONFIG_SYN_COOKIES
-extern __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb,
+extern __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb,
__u16 *mss);
#else
static inline __u32 cookie_v6_init_sequence(struct sock *sk,
@@ -521,7 +521,7 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)
}
/* tcp.c */
-extern void tcp_get_info(struct sock *, struct tcp_info *);
+extern void tcp_get_info(const struct sock *, struct tcp_info *);
/* Read 'sendfile()'-style from a TCP socket */
typedef int (*sk_read_actor_t)(read_descriptor_t *, struct sk_buff *,
@@ -531,8 +531,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(struct sock *sk, int pmtu);
-extern int tcp_mss_to_mtu(struct sock *sk, int mss);
+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 void tcp_mtup_init(struct sock *sk);
extern void tcp_valid_rtt_meas(struct sock *sk, u32 seq_rtt);
@@ -573,7 +573,7 @@ static inline void tcp_fast_path_check(struct sock *sk)
/* Compute the actual rto_min value */
static inline u32 tcp_rto_min(struct sock *sk)
{
- struct dst_entry *dst = __sk_dst_get(sk);
+ const struct dst_entry *dst = __sk_dst_get(sk);
u32 rto_min = TCP_RTO_MIN;
if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
@@ -628,20 +628,21 @@ extern u32 __tcp_select_window(struct sock *sk);
struct tcp_skb_cb {
union {
struct inet_skb_parm h4;
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct inet6_skb_parm h6;
#endif
} header; /* For incoming frames */
__u32 seq; /* Starting sequence number */
__u32 end_seq; /* SEQ + FIN + SYN + datalen */
__u32 when; /* used to compute rtt's */
- __u8 flags; /* TCP header flags. */
+ __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)
@@ -772,12 +773,12 @@ static inline int tcp_is_reno(const struct tcp_sock *tp)
static inline int tcp_is_fack(const struct tcp_sock *tp)
{
- return tp->rx_opt.sack_ok & 2;
+ return tp->rx_opt.sack_ok & TCP_FACK_ENABLED;
}
static inline void tcp_enable_fack(struct tcp_sock *tp)
{
- tp->rx_opt.sack_ok |= 2;
+ tp->rx_opt.sack_ok |= TCP_FACK_ENABLED;
}
static inline unsigned int tcp_left_out(const struct tcp_sock *tp)
@@ -818,6 +819,7 @@ static inline bool tcp_in_initial_slowstart(const struct tcp_sock *tp)
static inline __u32 tcp_current_ssthresh(const struct sock *sk)
{
const struct tcp_sock *tp = tcp_sk(sk);
+
if ((1 << inet_csk(sk)->icsk_ca_state) & (TCPF_CA_CWR | TCPF_CA_Recovery))
return tp->snd_ssthresh;
else
@@ -830,7 +832,15 @@ static inline __u32 tcp_current_ssthresh(const struct sock *sk)
#define tcp_verify_left_out(tp) WARN_ON(tcp_left_out(tp) > tp->packets_out)
extern void tcp_enter_cwr(struct sock *sk, const int set_ssthresh);
-extern __u32 tcp_init_cwnd(struct tcp_sock *tp, struct dst_entry *dst);
+extern __u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst);
+
+/* The maximum number of MSS of available cwnd for which TSO defers
+ * sending if not using sysctl_tcp_tso_win_divisor.
+ */
+static inline __u32 tcp_max_tso_deferred_mss(const struct tcp_sock *tp)
+{
+ return 3;
+}
/* Slow start with delack produces 3 packets of burst, so that
* it is safe "de facto". This will be the default - same as
@@ -859,7 +869,7 @@ static inline void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss,
static inline void tcp_check_probe_timer(struct sock *sk)
{
- struct tcp_sock *tp = tcp_sk(sk);
+ const struct tcp_sock *tp = tcp_sk(sk);
const struct inet_connection_sock *icsk = inet_csk(sk);
if (!tp->packets_out && !icsk->icsk_pending)
@@ -1142,7 +1152,7 @@ struct tcp6_md5sig_key {
/* - sock block */
struct tcp_md5sig_info {
struct tcp4_md5sig_key *keys4;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct tcp6_md5sig_key *keys6;
u32 entries6;
u32 alloced6;
@@ -1169,7 +1179,7 @@ struct tcp6_pseudohdr {
union tcp_md5sum_block {
struct tcp4_pseudohdr ip4;
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct tcp6_pseudohdr ip6;
#endif
};
@@ -1182,8 +1192,9 @@ struct tcp_md5sig_pool {
/* - functions */
extern int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
- struct sock *sk, struct request_sock *req,
- struct sk_buff *skb);
+ const struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb);
extern struct tcp_md5sig_key * tcp_v4_md5_lookup(struct sock *sk,
struct sock *addr_sk);
extern int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, u8 *newkey,
@@ -1200,17 +1211,17 @@ extern int tcp_v4_md5_do_del(struct sock *sk, __be32 addr);
#define tcp_twsk_md5_key(twsk) NULL
#endif
-extern struct tcp_md5sig_pool * __percpu *tcp_alloc_md5sig_pool(struct sock *);
+extern struct tcp_md5sig_pool __percpu *tcp_alloc_md5sig_pool(struct sock *);
extern void tcp_free_md5sig_pool(void);
extern struct tcp_md5sig_pool *tcp_get_md5sig_pool(void);
extern void tcp_put_md5sig_pool(void);
-extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, struct tcphdr *);
-extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, struct sk_buff *,
+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);
extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
- struct tcp_md5sig_key *key);
+ const struct tcp_md5sig_key *key);
/* write queue abstraction */
static inline void tcp_write_queue_purge(struct sock *sk)
@@ -1223,22 +1234,24 @@ static inline void tcp_write_queue_purge(struct sock *sk)
tcp_clear_all_retrans_hints(tcp_sk(sk));
}
-static inline struct sk_buff *tcp_write_queue_head(struct sock *sk)
+static inline struct sk_buff *tcp_write_queue_head(const struct sock *sk)
{
return skb_peek(&sk->sk_write_queue);
}
-static inline struct sk_buff *tcp_write_queue_tail(struct sock *sk)
+static inline struct sk_buff *tcp_write_queue_tail(const struct sock *sk)
{
return skb_peek_tail(&sk->sk_write_queue);
}
-static inline struct sk_buff *tcp_write_queue_next(struct sock *sk, struct sk_buff *skb)
+static inline struct sk_buff *tcp_write_queue_next(const struct sock *sk,
+ const struct sk_buff *skb)
{
return skb_queue_next(&sk->sk_write_queue, skb);
}
-static inline struct sk_buff *tcp_write_queue_prev(struct sock *sk, struct sk_buff *skb)
+static inline struct sk_buff *tcp_write_queue_prev(const struct sock *sk,
+ const struct sk_buff *skb)
{
return skb_queue_prev(&sk->sk_write_queue, skb);
}
@@ -1252,7 +1265,7 @@ static inline struct sk_buff *tcp_write_queue_prev(struct sock *sk, struct sk_bu
#define tcp_for_write_queue_from_safe(skb, tmp, sk) \
skb_queue_walk_from_safe(&(sk)->sk_write_queue, skb, tmp)
-static inline struct sk_buff *tcp_send_head(struct sock *sk)
+static inline struct sk_buff *tcp_send_head(const struct sock *sk)
{
return sk->sk_send_head;
}
@@ -1263,7 +1276,7 @@ static inline bool tcp_skb_is_last(const struct sock *sk,
return skb_queue_is_last(&sk->sk_write_queue, skb);
}
-static inline void tcp_advance_send_head(struct sock *sk, struct sk_buff *skb)
+static inline void tcp_advance_send_head(struct sock *sk, const struct sk_buff *skb)
{
if (tcp_skb_is_last(sk, skb))
sk->sk_send_head = NULL;
@@ -1398,11 +1411,13 @@ enum tcp_seq_states {
TCP_SEQ_STATE_TIME_WAIT,
};
+int tcp_seq_open(struct inode *inode, struct file *file);
+
struct tcp_seq_afinfo {
- char *name;
- sa_family_t family;
- struct file_operations seq_fops;
- struct seq_operations seq_ops;
+ char *name;
+ sa_family_t family;
+ const struct file_operations *seq_fops;
+ struct seq_operations seq_ops;
};
struct tcp_iter_state {
@@ -1423,7 +1438,8 @@ extern struct request_sock_ops tcp6_request_sock_ops;
extern void tcp_v4_destroy_sock(struct sock *sk);
extern int tcp_v4_gso_send_check(struct sk_buff *skb);
-extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb, u32 features);
+extern struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
+ netdev_features_t features);
extern struct sk_buff **tcp_gro_receive(struct sk_buff **head,
struct sk_buff *skb);
extern struct sk_buff **tcp4_gro_receive(struct sk_buff **head,
@@ -1443,9 +1459,9 @@ struct tcp_sock_af_ops {
struct sock *addr_sk);
int (*calc_md5_hash) (char *location,
struct tcp_md5sig_key *md5,
- struct sock *sk,
- struct request_sock *req,
- struct sk_buff *skb);
+ const struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb);
int (*md5_add) (struct sock *sk,
struct sock *addr_sk,
u8 *newkey,
@@ -1462,9 +1478,9 @@ struct tcp_request_sock_ops {
struct request_sock *req);
int (*calc_md5_hash) (char *location,
struct tcp_md5sig_key *md5,
- struct sock *sk,
- struct request_sock *req,
- struct sk_buff *skb);
+ const struct sock *sk,
+ const struct request_sock *req,
+ const struct sk_buff *skb);
#endif
};
diff --git a/include/net/tcp_memcontrol.h b/include/net/tcp_memcontrol.h
new file mode 100644
index 00000000000..3512082fa90
--- /dev/null
+++ b/include/net/tcp_memcontrol.h
@@ -0,0 +1,19 @@
+#ifndef _TCP_MEMCG_H
+#define _TCP_MEMCG_H
+
+struct tcp_memcontrol {
+ struct cg_proto cg_proto;
+ /* per-cgroup tcp memory pressure knobs */
+ struct res_counter tcp_memory_allocated;
+ struct percpu_counter tcp_sockets_allocated;
+ /* those two are read-mostly, leave them at the end */
+ long tcp_prot_mem[3];
+ int tcp_memory_pressure;
+};
+
+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, struct cgroup_subsys *ss);
+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/udp.h b/include/net/udp.h
index 67ea6fcb3ec..e39592f682c 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -41,7 +41,7 @@
struct udp_skb_cb {
union {
struct inet_skb_parm h4;
-#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
struct inet6_skb_parm h6;
#endif
} header;
@@ -194,9 +194,15 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
__be32 daddr, __be16 dport,
int dif);
+extern struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
+ __be32 daddr, __be16 dport,
+ int dif, struct udp_table *tbl);
extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
const struct in6_addr *daddr, __be16 dport,
int dif);
+extern struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr, __be16 dport,
+ int dif, struct udp_table *tbl);
/*
* SNMP statistics for UDP and UDP-Lite
@@ -217,7 +223,7 @@ extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *sadd
else SNMP_INC_STATS_USER((net)->mib.udp_stats_in6, field); \
} while(0)
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+#if IS_ENABLED(CONFIG_IPV6)
#define UDPX_INC_STATS_BH(sk, field) \
do { \
if ((sk)->sk_family == AF_INET) \
@@ -230,12 +236,14 @@ extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *sadd
#endif
/* /proc */
+int udp_seq_open(struct inode *inode, struct file *file);
+
struct udp_seq_afinfo {
- char *name;
- sa_family_t family;
- struct udp_table *udp_table;
- struct file_operations seq_fops;
- struct seq_operations seq_ops;
+ char *name;
+ sa_family_t family;
+ struct udp_table *udp_table;
+ const struct file_operations *seq_fops;
+ struct seq_operations seq_ops;
};
struct udp_iter_state {
@@ -256,5 +264,6 @@ extern void udp4_proc_exit(void);
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, u32 features);
+extern struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
+ netdev_features_t features);
#endif /* _UDP_H */
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index b203e14d26b..89174e29dca 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -827,6 +827,14 @@ static inline bool addr_match(const void *token1, const void *token2,
return true;
}
+static inline bool addr4_match(__be32 a1, __be32 a2, u8 prefixlen)
+{
+ /* C99 6.5.7 (3): u32 << 32 is undefined behaviour */
+ if (prefixlen == 0)
+ return true;
+ return !((a1 ^ a2) & htonl(0xFFFFFFFFu << (32 - prefixlen)));
+}
+
static __inline__
__be16 xfrm_flowi_sport(const struct flowi *fl, const union flowi_uli *uli)
{
@@ -1209,8 +1217,8 @@ void xfrm_flowi_addr_get(const struct flowi *fl,
memcpy(&daddr->a4, &fl->u.ip4.daddr, sizeof(daddr->a4));
break;
case AF_INET6:
- ipv6_addr_copy((struct in6_addr *)&saddr->a6, &fl->u.ip6.saddr);
- ipv6_addr_copy((struct in6_addr *)&daddr->a6, &fl->u.ip6.daddr);
+ *(struct in6_addr *)saddr->a6 = fl->u.ip6.saddr;
+ *(struct in6_addr *)daddr->a6 = fl->u.ip6.daddr;
break;
}
}