aboutsummaryrefslogtreecommitdiff
path: root/include/net
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 18:07:07 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2012-12-12 18:07:07 -0800
commit6be35c700f742e911ecedd07fcc43d4439922334 (patch)
treeca9f37214d204465fcc2d79c82efd291e357c53c /include/net
parente37aa63e87bd581f9be5555ed0ba83f5295c92fc (diff)
parent520dfe3a3645257bf83660f672c47f8558f3d4c4 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
Pull networking changes from David Miller: 1) Allow to dump, monitor, and change the bridge multicast database using netlink. From Cong Wang. 2) RFC 5961 TCP blind data injection attack mitigation, from Eric Dumazet. 3) Networking user namespace support from Eric W. Biederman. 4) tuntap/virtio-net multiqueue support by Jason Wang. 5) Support for checksum offload of encapsulated packets (basically, tunneled traffic can still be checksummed by HW). From Joseph Gasparakis. 6) Allow BPF filter access to VLAN tags, from Eric Dumazet and Daniel Borkmann. 7) Bridge port parameters over netlink and BPDU blocking support from Stephen Hemminger. 8) Improve data access patterns during inet socket demux by rearranging socket layout, from Eric Dumazet. 9) TIPC protocol updates and cleanups from Ying Xue, Paul Gortmaker, and Jon Maloy. 10) Update TCP socket hash sizing to be more in line with current day realities. The existing heurstics were choosen a decade ago. From Eric Dumazet. 11) Fix races, queue bloat, and excessive wakeups in ATM and associated drivers, from Krzysztof Mazur and David Woodhouse. 12) Support DOVE (Distributed Overlay Virtual Ethernet) extensions in VXLAN driver, from David Stevens. 13) Add "oops_only" mode to netconsole, from Amerigo Wang. 14) Support set and query of VEB/VEPA bridge mode via PF_BRIDGE, also allow DCB netlink to work on namespaces other than the initial namespace. From John Fastabend. 15) Support PTP in the Tigon3 driver, from Matt Carlson. 16) tun/vhost zero copy fixes and improvements, plus turn it on by default, from Michael S. Tsirkin. 17) Support per-association statistics in SCTP, from Michele Baldessari. And many, many, driver updates, cleanups, and improvements. Too numerous to mention individually. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1722 commits) net/mlx4_en: Add support for destination MAC in steering rules net/mlx4_en: Use generic etherdevice.h functions. net: ethtool: Add destination MAC address to flow steering API bridge: add support of adding and deleting mdb entries bridge: notify mdb changes via netlink ndisc: Unexport ndisc_{build,send}_skb(). uapi: add missing netconf.h to export list pkt_sched: avoid requeues if possible solos-pci: fix double-free of TX skb in DMA mode bnx2: Fix accidental reversions. bna: Driver Version Updated to 3.1.2.1 bna: Firmware update bna: Add RX State bna: Rx Page Based Allocation bna: TX Intr Coalescing Fix bna: Tx and Rx Optimizations bna: Code Cleanup and Enhancements ath9k: check pdata variable before dereferencing it ath5k: RX timestamp is reported at end of frame ath9k_htc: RX timestamp is reported at end of frame ...
Diffstat (limited to 'include/net')
-rw-r--r--include/net/addrconf.h3
-rw-r--r--include/net/af_unix.h1
-rw-r--r--include/net/bluetooth/a2mp.h24
-rw-r--r--include/net/bluetooth/amp.h54
-rw-r--r--include/net/bluetooth/bluetooth.h1
-rw-r--r--include/net/bluetooth/hci.h69
-rw-r--r--include/net/bluetooth/hci_core.h123
-rw-r--r--include/net/bluetooth/l2cap.h50
-rw-r--r--include/net/cfg80211.h306
-rw-r--r--include/net/cls_cgroup.h6
-rw-r--r--include/net/gro_cells.h14
-rw-r--r--include/net/ieee80211_radiotap.h24
-rw-r--r--include/net/inet_hashtables.h50
-rw-r--r--include/net/inet_sock.h8
-rw-r--r--include/net/inet_timewait_sock.h7
-rw-r--r--include/net/ip6_checksum.h35
-rw-r--r--include/net/ip6_fib.h20
-rw-r--r--include/net/ip6_route.h3
-rw-r--r--include/net/ip_vs.h195
-rw-r--r--include/net/ipip.h40
-rw-r--r--include/net/ipv6.h19
-rw-r--r--include/net/mac80211.h275
-rw-r--r--include/net/ndisc.h15
-rw-r--r--include/net/net_namespace.h24
-rw-r--r--include/net/netfilter/nf_conntrack.h2
-rw-r--r--include/net/netfilter/nf_nat.h15
-rw-r--r--include/net/netfilter/nf_queue.h8
-rw-r--r--include/net/netns/sctp.h3
-rw-r--r--include/net/nfc/hci.h21
-rw-r--r--include/net/nfc/nfc.h2
-rw-r--r--include/net/protocol.h31
-rw-r--r--include/net/request_sock.h12
-rw-r--r--include/net/route.h9
-rw-r--r--include/net/rtnetlink.h2
-rw-r--r--include/net/sch_generic.h7
-rw-r--r--include/net/sctp/command.h38
-rw-r--r--include/net/sctp/constants.h8
-rw-r--r--include/net/sctp/sctp.h12
-rw-r--r--include/net/sctp/sm.h2
-rw-r--r--include/net/sctp/structs.h39
-rw-r--r--include/net/sctp/ulpqueue.h2
-rw-r--r--include/net/sctp/user.h27
-rw-r--r--include/net/sock.h28
-rw-r--r--include/net/tcp.h1
44 files changed, 1315 insertions, 320 deletions
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 9e63e76b20e..df4ef945338 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -172,6 +172,9 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
extern int register_inet6addr_notifier(struct notifier_block *nb);
extern int unregister_inet6addr_notifier(struct notifier_block *nb);
+extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+ struct ipv6_devconf *devconf);
+
/**
* __in6_dev_get - get inet6_dev pointer from netdevice
* @dev: network device
diff --git a/include/net/af_unix.h b/include/net/af_unix.h
index b5f8988e428..0a996a3517e 100644
--- a/include/net/af_unix.h
+++ b/include/net/af_unix.h
@@ -53,7 +53,6 @@ struct unix_sock {
struct path path;
struct mutex readlock;
struct sock *peer;
- struct sock *other;
struct list_head link;
atomic_long_t inflight;
spinlock_t lock;
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h
index 6a76e0a0705..42f21766c53 100644
--- a/include/net/bluetooth/a2mp.h
+++ b/include/net/bluetooth/a2mp.h
@@ -19,13 +19,25 @@
#define A2MP_FEAT_EXT 0x8000
+enum amp_mgr_state {
+ READ_LOC_AMP_INFO,
+ READ_LOC_AMP_ASSOC,
+ READ_LOC_AMP_ASSOC_FINAL,
+};
+
struct amp_mgr {
+ struct list_head list;
struct l2cap_conn *l2cap_conn;
struct l2cap_chan *a2mp_chan;
+ struct l2cap_chan *bredr_chan;
struct kref kref;
__u8 ident;
__u8 handle;
+ enum amp_mgr_state state;
unsigned long flags;
+
+ struct list_head amp_ctrls;
+ struct mutex amp_ctrls_lock;
};
struct a2mp_cmd {
@@ -118,9 +130,19 @@ struct a2mp_physlink_rsp {
#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05
#define A2MP_STATUS_SECURITY_VIOLATION 0x06
-void amp_mgr_get(struct amp_mgr *mgr);
+extern struct list_head amp_mgr_list;
+extern struct mutex amp_mgr_list_lock;
+
+struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);
int amp_mgr_put(struct amp_mgr *mgr);
+u8 __next_ident(struct amp_mgr *mgr);
struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
struct sk_buff *skb);
+struct amp_mgr *amp_mgr_lookup_by_state(u8 state);
+void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data);
+void a2mp_discover_amp(struct l2cap_chan *chan);
+void a2mp_send_getinfo_rsp(struct hci_dev *hdev);
+void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status);
+void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);
#endif /* __A2MP_H */
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
new file mode 100644
index 00000000000..7ea3db77ba8
--- /dev/null
+++ b/include/net/bluetooth/amp.h
@@ -0,0 +1,54 @@
+/*
+ Copyright (c) 2011,2012 Intel Corp.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#ifndef __AMP_H
+#define __AMP_H
+
+struct amp_ctrl {
+ struct list_head list;
+ struct kref kref;
+ __u8 id;
+ __u16 assoc_len_so_far;
+ __u16 assoc_rem_len;
+ __u16 assoc_len;
+ __u8 *assoc;
+};
+
+int amp_ctrl_put(struct amp_ctrl *ctrl);
+void amp_ctrl_get(struct amp_ctrl *ctrl);
+struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id);
+struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id);
+void amp_ctrl_list_flush(struct amp_mgr *mgr);
+
+struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr,
+ u8 remote_id, bool out);
+
+int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type);
+
+void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle);
+void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr);
+void amp_read_loc_assoc_final_data(struct hci_dev *hdev,
+ struct hci_conn *hcon);
+void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon);
+void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr,
+ struct hci_conn *hcon);
+void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle);
+void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle);
+void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon);
+void amp_create_logical_link(struct l2cap_chan *chan);
+void amp_disconnect_logical_link(struct hci_chan *hchan);
+void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason);
+
+#endif /* __AMP_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index ede036977ae..2554b3f5222 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)
}
void baswap(bdaddr_t *dst, bdaddr_t *src);
-char *batostr(bdaddr_t *ba);
/* Common socket structures and functions */
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 76b2b6bdcf3..45eee08157b 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -33,6 +33,8 @@
#define HCI_LINK_KEY_SIZE 16
#define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE)
+#define HCI_MAX_AMP_ASSOC_SIZE 672
+
/* HCI dev events */
#define HCI_DEV_REG 1
#define HCI_DEV_UNREG 2
@@ -113,6 +115,7 @@ enum {
HCI_SSP_ENABLED,
HCI_HS_ENABLED,
HCI_LE_ENABLED,
+ HCI_LE_PERIPHERAL,
HCI_CONNECTABLE,
HCI_DISCOVERABLE,
HCI_LINK_SECURITY,
@@ -151,7 +154,7 @@ enum {
#define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_PAIRING_TIMEOUT msecs_to_jiffies(60000) /* 60 seconds */
#define HCI_INIT_TIMEOUT msecs_to_jiffies(10000) /* 10 seconds */
-#define HCI_CMD_TIMEOUT msecs_to_jiffies(1000) /* 1 second */
+#define HCI_CMD_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
#define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */
#define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
@@ -196,6 +199,7 @@ enum {
#define ACL_START_NO_FLUSH 0x00
#define ACL_CONT 0x01
#define ACL_START 0x02
+#define ACL_COMPLETE 0x03
#define ACL_ACTIVE_BCAST 0x04
#define ACL_PICO_BCAST 0x08
@@ -205,6 +209,7 @@ enum {
#define ESCO_LINK 0x02
/* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK 0x80
+#define AMP_LINK 0x81
/* LMP features */
#define LMP_3SLOT 0x01
@@ -314,6 +319,9 @@ enum {
#define HCI_FLOW_CTL_MODE_PACKET_BASED 0x00
#define HCI_FLOW_CTL_MODE_BLOCK_BASED 0x01
+/* The core spec defines 127 as the "not available" value */
+#define HCI_TX_POWER_INVALID 127
+
/* Extended Inquiry Response field types */
#define EIR_FLAGS 0x01 /* flags */
#define EIR_UUID16_SOME 0x02 /* 16-bit UUID, more available */
@@ -330,6 +338,13 @@ enum {
#define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */
#define EIR_DEVICE_ID 0x10 /* device ID */
+/* Low Energy Advertising Flags */
+#define LE_AD_LIMITED 0x01 /* Limited Discoverable */
+#define LE_AD_GENERAL 0x02 /* General Discoverable */
+#define LE_AD_NO_BREDR 0x04 /* BR/EDR not supported */
+#define LE_AD_SIM_LE_BREDR_CTRL 0x08 /* Simultaneous LE & BR/EDR Controller */
+#define LE_AD_SIM_LE_BREDR_HOST 0x10 /* Simultaneous LE & BR/EDR Host */
+
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
@@ -556,12 +571,46 @@ struct hci_cp_accept_phy_link {
__u8 key[HCI_AMP_LINK_KEY_SIZE];
} __packed;
-#define HCI_OP_DISCONN_PHY_LINK 0x0437
+#define HCI_OP_DISCONN_PHY_LINK 0x0437
struct hci_cp_disconn_phy_link {
__u8 phy_handle;
__u8 reason;
} __packed;
+struct ext_flow_spec {
+ __u8 id;
+ __u8 stype;
+ __le16 msdu;
+ __le32 sdu_itime;
+ __le32 acc_lat;
+ __le32 flush_to;
+} __packed;
+
+#define HCI_OP_CREATE_LOGICAL_LINK 0x0438
+#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
+struct hci_cp_create_accept_logical_link {
+ __u8 phy_handle;
+ struct ext_flow_spec tx_flow_spec;
+ struct ext_flow_spec rx_flow_spec;
+} __packed;
+
+#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
+struct hci_cp_disconn_logical_link {
+ __le16 log_handle;
+} __packed;
+
+#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
+struct hci_cp_logical_link_cancel {
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+struct hci_rp_logical_link_cancel {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
@@ -894,6 +943,22 @@ struct hci_rp_le_read_buffer_size {
__u8 le_max_pkt;
} __packed;
+#define HCI_OP_LE_READ_ADV_TX_POWER 0x2007
+struct hci_rp_le_read_adv_tx_power {
+ __u8 status;
+ __s8 tx_power;
+} __packed;
+
+#define HCI_MAX_AD_LENGTH 31
+
+#define HCI_OP_LE_SET_ADV_DATA 0x2008
+struct hci_cp_le_set_adv_data {
+ __u8 length;
+ __u8 data[HCI_MAX_AD_LENGTH];
+} __packed;
+
+#define HCI_OP_LE_SET_ADV_ENABLE 0x200a
+
#define HCI_OP_LE_SET_SCAN_PARAM 0x200b
struct hci_cp_le_set_scan_param {
__u8 type;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index e7d45460988..014a2eaa538 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -73,6 +73,7 @@ struct discovery_state {
struct hci_conn_hash {
struct list_head list;
unsigned int acl_num;
+ unsigned int amp_num;
unsigned int sco_num;
unsigned int le_num;
};
@@ -124,6 +125,14 @@ struct le_scan_params {
#define HCI_MAX_SHORT_NAME_LENGTH 10
+struct amp_assoc {
+ __u16 len;
+ __u16 offset;
+ __u16 rem_len;
+ __u16 len_so_far;
+ __u8 data[HCI_MAX_AMP_ASSOC_SIZE];
+};
+
#define NUM_REASSEMBLY 4
struct hci_dev {
struct list_head list;
@@ -177,6 +186,8 @@ struct hci_dev {
__u32 amp_max_flush_to;
__u32 amp_be_flush_to;
+ struct amp_assoc loc_assoc;
+
__u8 flow_ctl_mode;
unsigned int auto_accept_delay;
@@ -252,8 +263,6 @@ struct hci_dev {
struct sk_buff_head driver_init;
- void *core_data;
-
atomic_t promisc;
struct dentry *debugfs;
@@ -269,6 +278,10 @@ struct hci_dev {
struct work_struct le_scan;
struct le_scan_params le_scan_params;
+ __s8 adv_tx_power;
+ __u8 adv_data[HCI_MAX_AD_LENGTH];
+ __u8 adv_data_len;
+
int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev);
int (*flush)(struct hci_dev *hdev);
@@ -277,6 +290,8 @@ struct hci_dev {
int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
};
+#define HCI_PHY_HANDLE(handle) (handle & 0xff)
+
struct hci_conn {
struct list_head list;
@@ -310,6 +325,7 @@ struct hci_conn {
__u8 remote_cap;
__u8 remote_auth;
+ __u8 remote_id;
bool flush_key;
unsigned int sent;
@@ -339,10 +355,11 @@ struct hci_conn {
struct hci_chan {
struct list_head list;
-
+ __u16 handle;
struct hci_conn *conn;
struct sk_buff_head data_q;
unsigned int sent;
+ __u8 state;
};
extern struct list_head hci_dev_list;
@@ -359,7 +376,7 @@ 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_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);
extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);
extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);
extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb);
@@ -438,6 +455,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
case ACL_LINK:
h->acl_num++;
break;
+ case AMP_LINK:
+ h->amp_num++;
+ break;
case LE_LINK:
h->le_num++;
break;
@@ -459,6 +479,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
case ACL_LINK:
h->acl_num--;
break;
+ case AMP_LINK:
+ h->amp_num--;
+ break;
case LE_LINK:
h->le_num--;
break;
@@ -475,6 +498,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)
switch (type) {
case ACL_LINK:
return h->acl_num;
+ case AMP_LINK:
+ return h->amp_num;
case LE_LINK:
return h->le_num;
case SCO_LINK:
@@ -552,10 +577,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
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);
+void hci_conn_accept(struct hci_conn *conn, int mask);
struct hci_chan *hci_chan_create(struct hci_conn *conn);
void hci_chan_del(struct hci_chan *chan);
void hci_chan_list_flush(struct hci_conn *conn);
+struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
__u8 dst_type, __u8 sec_level, __u8 auth_type);
@@ -584,7 +611,10 @@ 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 || conn->type == LE_LINK) {
+
+ switch (conn->type) {
+ case ACL_LINK:
+ case LE_LINK:
del_timer(&conn->idle_timer);
if (conn->state == BT_CONNECTED) {
timeo = conn->disc_timeout;
@@ -593,12 +623,20 @@ static inline void hci_conn_put(struct hci_conn *conn)
} else {
timeo = msecs_to_jiffies(10);
}
- } else {
+ break;
+
+ case AMP_LINK:
+ timeo = conn->disc_timeout;
+ break;
+
+ default:
timeo = msecs_to_jiffies(10);
+ break;
}
+
cancel_delayed_work(&conn->disc_work);
queue_delayed_work(conn->hdev->workqueue,
- &conn->disc_work, timeo);
+ &conn->disc_work, timeo);
}
}
@@ -650,7 +688,7 @@ static inline uint8_t __hci_num_ctrl(void)
}
struct hci_dev *hci_dev_get(int index);
-struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
+struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src);
struct hci_dev *hci_alloc_dev(void);
void hci_free_dev(struct hci_dev *hdev);
@@ -699,6 +737,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
u8 *randomizer);
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
+int hci_update_ad(struct hci_dev *hdev);
+
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
int hci_recv_frame(struct sk_buff *skb);
@@ -715,22 +755,51 @@ void hci_conn_del_sysfs(struct hci_conn *conn);
#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))
/* ----- LMP capabilities ----- */
-#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
+#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
+#define lmp_hold_capable(dev) ((dev)->features[0] & LMP_HOLD)
#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
-#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_park_capable(dev) ((dev)->features[1] & LMP_PARK)
+#define lmp_inq_rssi_capable(dev) ((dev)->features[3] & LMP_RSSI_INQ)
#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
+#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
+#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
+#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC)
+#define lmp_ext_inq_capable(dev) ((dev)->features[6] & LMP_EXT_INQ)
+#define lmp_le_br_capable(dev) !!((dev)->features[6] & LMP_SIMUL_LE_BR)
#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
-#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
-#define lmp_bredr_capable(dev) (!((dev)->features[4] & LMP_NO_BREDR))
+#define lmp_lsto_capable(dev) ((dev)->features[7] & LMP_LSTO)
+#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR)
+#define lmp_ext_feat_capable(dev) ((dev)->features[7] & LMP_EXTFEATURES)
/* ----- Extended LMP capabilities ----- */
-#define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE)
+#define lmp_host_ssp_capable(dev) ((dev)->host_features[0] & LMP_HOST_SSP)
+#define lmp_host_le_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE)
+#define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR)
+
+/* returns true if at least one AMP active */
+static inline bool hci_amp_capable(void)
+{
+ struct hci_dev *hdev;
+ bool ret = false;
+
+ read_lock(&hci_dev_list_lock);
+ list_for_each_entry(hdev, &hci_dev_list, list)
+ if (hdev->amp_type == HCI_AMP &&
+ test_bit(HCI_UP, &hdev->flags))
+ ret = true;
+ read_unlock(&hci_dev_list_lock);
+
+ return ret;
+}
/* ----- HCI protocols ----- */
+#define HCI_PROTO_DEFER 0x01
+
static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
- __u8 type)
+ __u8 type, __u8 *flags)
{
switch (type) {
case ACL_LINK:
@@ -738,7 +807,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
case SCO_LINK:
case ESCO_LINK:
- return sco_connect_ind(hdev, bdaddr);
+ return sco_connect_ind(hdev, bdaddr, flags);
default:
BT_ERR("unknown link type %d", type);
@@ -789,6 +858,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
sco_disconn_cfm(conn, reason);
break;
+ /* L2CAP would be handled for BREDR chan */
+ case AMP_LINK:
+ break;
+
default:
BT_ERR("unknown link type %d", conn->type);
break;
@@ -841,7 +914,7 @@ struct hci_cb {
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
{
- struct list_head *p;
+ struct hci_cb *cb;
__u8 encrypt;
hci_proto_auth_cfm(conn, status);
@@ -852,8 +925,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
@@ -863,7 +935,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
__u8 encrypt)
{
- struct list_head *p;
+ struct hci_cb *cb;
if (conn->sec_level == BT_SECURITY_SDP)
conn->sec_level = BT_SECURITY_LOW;
@@ -874,8 +946,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
hci_proto_encrypt_cfm(conn, status, encrypt);
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
@@ -884,11 +955,10 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
{
- struct list_head *p;
+ struct hci_cb *cb;
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->key_change_cfm)
cb->key_change_cfm(conn, status);
}
@@ -898,11 +968,10 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
__u8 role)
{
- struct list_head *p;
+ struct hci_cb *cb;
read_lock(&hci_cb_list_lock);
- list_for_each(p, &hci_cb_list) {
- struct hci_cb *cb = list_entry(p, struct hci_cb, list);
+ list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->role_switch_cfm)
cb->role_switch_cfm(conn, status, role);
}
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 7ed8e356425..7588ef44eba 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -32,13 +32,14 @@
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_MIN_MTU 48
-#define L2CAP_DEFAULT_FLUSH_TO 0xffff
+#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF
+#define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF
#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_MAX_PDU_SIZE 1492 /* Sized for AMP packet */
#define L2CAP_DEFAULT_ACK_TO 200
#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF
#define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF
@@ -51,6 +52,8 @@
#define L2CAP_ENC_TIMEOUT msecs_to_jiffies(5000)
#define L2CAP_CONN_TIMEOUT msecs_to_jiffies(40000)
#define L2CAP_INFO_TIMEOUT msecs_to_jiffies(4000)
+#define L2CAP_MOVE_TIMEOUT msecs_to_jiffies(4000)
+#define L2CAP_MOVE_ERTX_TIMEOUT msecs_to_jiffies(60000)
#define L2CAP_A2MP_DEFAULT_MTU 670
@@ -433,6 +436,8 @@ struct l2cap_chan {
struct sock *sk;
struct l2cap_conn *conn;
+ struct hci_conn *hs_hcon;
+ struct hci_chan *hs_hchan;
struct kref kref;
__u8 state;
@@ -476,6 +481,12 @@ struct l2cap_chan {
unsigned long conn_state;
unsigned long flags;
+ __u8 remote_amp_id;
+ __u8 local_amp_id;
+ __u8 move_id;
+ __u8 move_state;
+ __u8 move_role;
+
__u16 next_tx_seq;
__u16 expected_ack_seq;
__u16 expected_tx_seq;
@@ -538,6 +549,7 @@ struct l2cap_ops {
void (*state_change) (struct l2cap_chan *chan,
int state);
void (*ready) (struct l2cap_chan *chan);
+ void (*defer) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long len, int nb);
};
@@ -599,7 +611,7 @@ enum {
CONF_MTU_DONE,
CONF_MODE_DONE,
CONF_CONNECT_PEND,
- CONF_NO_FCS_RECV,
+ CONF_RECV_NO_FCS,
CONF_STATE2_DEVICE,
CONF_EWS_RECV,
CONF_LOC_CONF_PEND,
@@ -640,6 +652,9 @@ enum {
enum {
L2CAP_RX_STATE_RECV,
L2CAP_RX_STATE_SREJ_SENT,
+ L2CAP_RX_STATE_MOVE,
+ L2CAP_RX_STATE_WAIT_P,
+ L2CAP_RX_STATE_WAIT_F,
};
enum {
@@ -670,6 +685,25 @@ enum {
L2CAP_EV_RECV_FRAME,
};
+enum {
+ L2CAP_MOVE_ROLE_NONE,
+ L2CAP_MOVE_ROLE_INITIATOR,
+ L2CAP_MOVE_ROLE_RESPONDER,
+};
+
+enum {
+ L2CAP_MOVE_STABLE,
+ L2CAP_MOVE_WAIT_REQ,
+ L2CAP_MOVE_WAIT_RSP,
+ L2CAP_MOVE_WAIT_RSP_SUCCESS,
+ L2CAP_MOVE_WAIT_CONFIRM,
+ L2CAP_MOVE_WAIT_CONFIRM_RSP,
+ L2CAP_MOVE_WAIT_LOGICAL_COMP,
+ L2CAP_MOVE_WAIT_LOGICAL_CFM,
+ L2CAP_MOVE_WAIT_LOCAL_BUSY,
+ L2CAP_MOVE_WAIT_PREPARE,
+};
+
void l2cap_chan_hold(struct l2cap_chan *c);
void l2cap_chan_put(struct l2cap_chan *c);
@@ -745,6 +779,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)
{
}
+static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
+{
+}
+
extern bool disable_ertm;
int l2cap_init_sockets(void);
@@ -767,6 +805,12 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);
void l2cap_chan_set_defaults(struct l2cap_chan *chan);
int l2cap_ertm_init(struct l2cap_chan *chan);
void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
+void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);
void l2cap_chan_del(struct l2cap_chan *chan, int err);
+void l2cap_send_conn_req(struct l2cap_chan *chan);
+void l2cap_move_start(struct l2cap_chan *chan);
+void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan,
+ u8 status);
+void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);
#endif /* __L2CAP_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7d5b6000378..8e6a6b73b9c 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -58,6 +58,8 @@
* structures here describe these capabilities in detail.
*/
+struct wiphy;
+
/*
* wireless hardware capability structures
*/
@@ -306,6 +308,104 @@ struct key_params {
};
/**
+ * struct cfg80211_chan_def - channel definition
+ * @chan: the (control) channel
+ * @width: channel width
+ * @center_freq1: center frequency of first segment
+ * @center_freq2: center frequency of second segment
+ * (only with 80+80 MHz)
+ */
+struct cfg80211_chan_def {
+ struct ieee80211_channel *chan;
+ enum nl80211_chan_width width;
+ u32 center_freq1;
+ u32 center_freq2;
+};
+
+/**
+ * cfg80211_get_chandef_type - return old channel type from chandef
+ * @chandef: the channel definition
+ *
+ * Returns the old channel type (NOHT, HT20, HT40+/-) from a given
+ * chandef, which must have a bandwidth allowing this conversion.
+ */
+static inline enum nl80211_channel_type
+cfg80211_get_chandef_type(const struct cfg80211_chan_def *chandef)
+{
+ switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ return NL80211_CHAN_NO_HT;
+ case NL80211_CHAN_WIDTH_20:
+ return NL80211_CHAN_HT20;
+ case NL80211_CHAN_WIDTH_40:
+ if (chandef->center_freq1 > chandef->chan->center_freq)
+ return NL80211_CHAN_HT40PLUS;
+ return NL80211_CHAN_HT40MINUS;
+ default:
+ WARN_ON(1);
+ return NL80211_CHAN_NO_HT;
+ }
+}
+
+/**
+ * cfg80211_chandef_create - create channel definition using channel type
+ * @chandef: the channel definition struct to fill
+ * @channel: the control channel
+ * @chantype: the channel type
+ *
+ * Given a channel type, create a channel definition.
+ */
+void cfg80211_chandef_create(struct cfg80211_chan_def *chandef,
+ struct ieee80211_channel *channel,
+ enum nl80211_channel_type chantype);
+
+/**
+ * cfg80211_chandef_identical - check if two channel definitions are identical
+ * @chandef1: first channel definition
+ * @chandef2: second channel definition
+ *
+ * Returns %true if the channels defined by the channel definitions are
+ * identical, %false otherwise.
+ */
+static inline bool
+cfg80211_chandef_identical(const struct cfg80211_chan_def *chandef1,
+ const struct cfg80211_chan_def *chandef2)
+{
+ return (chandef1->chan == chandef2->chan &&
+ chandef1->width == chandef2->width &&
+ chandef1->center_freq1 == chandef2->center_freq1 &&
+ chandef1->center_freq2 == chandef2->center_freq2);
+}
+
+/**
+ * cfg80211_chandef_compatible - check if two channel definitions are compatible
+ * @chandef1: first channel definition
+ * @chandef2: second channel definition
+ *
+ * Returns %NULL if the given channel definitions are incompatible,
+ * chandef1 or chandef2 otherwise.
+ */
+const struct cfg80211_chan_def *
+cfg80211_chandef_compatible(const struct cfg80211_chan_def *chandef1,
+ const struct cfg80211_chan_def *chandef2);
+
+/**
+ * cfg80211_chandef_valid - check if a channel definition is valid
+ * @chandef: the channel definition to check
+ */
+bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef);
+
+/**
+ * cfg80211_chandef_usable - check if secondary channels can be used
+ * @wiphy: the wiphy to validate against
+ * @chandef: the channel definition to check
+ * @prohibited_flags: the regulatory chanenl flags that must not be set
+ */
+bool cfg80211_chandef_usable(struct wiphy *wiphy,
+ const struct cfg80211_chan_def *chandef,
+ u32 prohibited_flags);
+
+/**
* enum survey_info_flags - survey information flags
*
* @SURVEY_INFO_NOISE_DBM: noise (in dBm) was filled in
@@ -426,8 +526,7 @@ struct cfg80211_beacon_data {
*
* Used to configure an AP interface.
*
- * @channel: the channel to start the AP on
- * @channel_type: the channel type to use
+ * @chandef: defines the channel to use
* @beacon: beacon data
* @beacon_interval: beacon interval
* @dtim_period: DTIM period
@@ -439,10 +538,11 @@ struct cfg80211_beacon_data {
* @privacy: the BSS uses privacy
* @auth_type: Authentication type (algorithm)
* @inactivity_timeout: time in seconds to determine station's inactivity.
+ * @p2p_ctwindow: P2P CT Window
+ * @p2p_opp_ps: P2P opportunistic PS
*/
struct cfg80211_ap_settings {
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
struct cfg80211_beacon_data beacon;
@@ -454,6 +554,8 @@ struct cfg80211_ap_settings {
bool privacy;
enum nl80211_auth_type auth_type;
int inactivity_timeout;
+ u8 p2p_ctwindow;
+ bool p2p_opp_ps;
};
/**
@@ -498,6 +600,7 @@ enum station_parameters_apply_mask {
* @plink_action: plink action to take
* @plink_state: set the peer link state for a station
* @ht_capa: HT capabilities of station
+ * @vht_capa: VHT 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
@@ -517,6 +620,7 @@ struct station_parameters {
u8 plink_action;
u8 plink_state;
struct ieee80211_ht_cap *ht_capa;
+ struct ieee80211_vht_cap *vht_capa;
u8 uapsd_queues;
u8 max_sp;
};
@@ -580,16 +684,24 @@ enum station_info_flags {
* Used by the driver to indicate the specific rate transmission
* type for 802.11n transmissions.
*
- * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled
- * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission
+ * @RATE_INFO_FLAGS_MCS: mcs field filled with HT MCS
+ * @RATE_INFO_FLAGS_VHT_MCS: mcs field filled with VHT MCS
+ * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 MHz width transmission
+ * @RATE_INFO_FLAGS_80_MHZ_WIDTH: 80 MHz width transmission
+ * @RATE_INFO_FLAGS_80P80_MHZ_WIDTH: 80+80 MHz width transmission
+ * @RATE_INFO_FLAGS_160_MHZ_WIDTH: 160 MHz width transmission
* @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval
- * @RATE_INFO_FLAGS_60G: 60gHz MCS
+ * @RATE_INFO_FLAGS_60G: 60GHz MCS
*/
enum rate_info_flags {
- RATE_INFO_FLAGS_MCS = 1<<0,
- RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1,
- RATE_INFO_FLAGS_SHORT_GI = 1<<2,
- RATE_INFO_FLAGS_60G = 1<<3,
+ RATE_INFO_FLAGS_MCS = BIT(0),
+ RATE_INFO_FLAGS_VHT_MCS = BIT(1),
+ RATE_INFO_FLAGS_40_MHZ_WIDTH = BIT(2),
+ RATE_INFO_FLAGS_80_MHZ_WIDTH = BIT(3),
+ RATE_INFO_FLAGS_80P80_MHZ_WIDTH = BIT(4),
+ RATE_INFO_FLAGS_160_MHZ_WIDTH = BIT(5),
+ RATE_INFO_FLAGS_SHORT_GI = BIT(6),
+ RATE_INFO_FLAGS_60G = BIT(7),
};
/**
@@ -600,11 +712,13 @@ enum rate_info_flags {
* @flags: bitflag of flags from &enum rate_info_flags
* @mcs: mcs index if struct describes a 802.11n bitrate
* @legacy: bitrate in 100kbit/s for 802.11abg
+ * @nss: number of streams (VHT only)
*/
struct rate_info {
u8 flags;
u8 mcs;
u16 legacy;
+ u8 nss;
};
/**
@@ -803,6 +917,8 @@ struct mpath_info {
* @ap_isolate: do not forward packets between connected stations
* @ht_opmode: HT Operation mode
* (u16 = opmode, -1 = do not change)
+ * @p2p_ctwindow: P2P CT Window (-1 = no change)
+ * @p2p_opp_ps: P2P opportunistic PS (-1 = no change)
*/
struct bss_parameters {
int use_cts_prot;
@@ -812,6 +928,7 @@ struct bss_parameters {
u8 basic_rates_len;
int ap_isolate;
int ht_opmode;
+ s8 p2p_ctwindow, p2p_opp_ps;
};
/**
@@ -907,8 +1024,7 @@ struct mesh_config {
/**
* struct mesh_setup - 802.11s mesh setup configuration
- * @channel: the channel to start the mesh network on
- * @channel_type: the channel type to use
+ * @chandef: defines the channel to use
* @mesh_id: the mesh ID
* @mesh_id_len: length of the mesh ID, at least 1 and at most 32 bytes
* @sync_method: which synchronization method to use
@@ -923,8 +1039,7 @@ struct mesh_config {
* These parameters are fixed when the mesh is created.
*/
struct mesh_setup {
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
const u8 *mesh_id;
u8 mesh_id_len;
u8 sync_method;
@@ -955,9 +1070,6 @@ struct ieee80211_txq_params {
u8 aifs;
};
-/* from net/wireless.h */
-struct wiphy;
-
/**
* DOC: Scanning and BSS list handling
*
@@ -1000,8 +1112,10 @@ struct cfg80211_ssid {
* @n_channels: total number of channels to scan
* @ie: optional information element(s) to add into Probe Request or %NULL
* @ie_len: length of ie in octets
+ * @flags: bit field of flags controlling operation
* @rates: bitmap of rates to advertise for each band
* @wiphy: the wiphy this was for
+ * @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
@@ -1012,6 +1126,7 @@ struct cfg80211_scan_request {
u32 n_channels;
const u8 *ie;
size_t ie_len;
+ u32 flags;
u32 rates[IEEE80211_NUM_BANDS];
@@ -1019,6 +1134,7 @@ struct cfg80211_scan_request {
/* internal */
struct wiphy *wiphy;
+ unsigned long scan_start;
bool aborted;
bool no_cck;
@@ -1044,6 +1160,7 @@ struct cfg80211_match_set {
* @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
+ * @flags: bit field of flags controlling operation
* @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).
@@ -1061,6 +1178,7 @@ struct cfg80211_sched_scan_request {
u32 interval;
const u8 *ie;
size_t ie_len;
+ u32 flags;
struct cfg80211_match_set *match_sets;
int n_match_sets;
s32 rssi_thold;
@@ -1068,6 +1186,7 @@ struct cfg80211_sched_scan_request {
/* internal */
struct wiphy *wiphy;
struct net_device *dev;
+ unsigned long scan_start;
/* keep last */
struct ieee80211_channel *channels[0];
@@ -1087,6 +1206,18 @@ enum cfg80211_signal_type {
};
/**
+ * struct cfg80211_bss_ie_data - BSS entry IE data
+ * @rcu_head: internal use, for freeing
+ * @len: length of the IEs
+ * @data: IE data
+ */
+struct cfg80211_bss_ies {
+ struct rcu_head rcu_head;
+ int len;
+ u8 data[];
+};
+
+/**
* struct cfg80211_bss - BSS description
*
* This structure describes a BSS (which may also be a mesh network)
@@ -1097,36 +1228,34 @@ enum cfg80211_signal_type {
* @tsf: timestamp of last received update
* @beacon_interval: the beacon interval as from the frame
* @capability: the capability field in host byte order
- * @information_elements: the information elements (Note that there
+ * @ies: the information elements (Note that there
* is no guarantee that these are well-formed!); this is a pointer to
* either the beacon_ies or proberesp_ies depending on whether Probe
* Response frame has been received
- * @len_information_elements: total length of the information elements
* @beacon_ies: the information elements from the last Beacon frame
- * @len_beacon_ies: total length of the beacon_ies
* @proberesp_ies: the information elements from the last Probe Response frame
- * @len_proberesp_ies: total length of the proberesp_ies
* @signal: signal strength value (type depends on the wiphy's signal_type)
* @free_priv: function pointer to free private data
* @priv: private area for driver use, has at least wiphy->bss_priv_size bytes
*/
struct cfg80211_bss {
+ u64 tsf;
+
struct ieee80211_channel *channel;
- u8 bssid[ETH_ALEN];
- u64 tsf;
+ const struct cfg80211_bss_ies __rcu *ies;
+ const struct cfg80211_bss_ies __rcu *beacon_ies;
+ const struct cfg80211_bss_ies __rcu *proberesp_ies;
+
+ void (*free_priv)(struct cfg80211_bss *bss);
+
+ s32 signal;
+
u16 beacon_interval;
u16 capability;
- u8 *information_elements;
- size_t len_information_elements;
- u8 *beacon_ies;
- size_t len_beacon_ies;
- u8 *proberesp_ies;
- size_t len_proberesp_ies;
- s32 signal;
+ u8 bssid[ETH_ALEN];
- void (*free_priv)(struct cfg80211_bss *bss);
u8 priv[0] __attribute__((__aligned__(sizeof(void *))));
};
@@ -1134,6 +1263,9 @@ struct cfg80211_bss {
* ieee80211_bss_get_ie - find IE with given ID
* @bss: the bss to search
* @ie: the IE ID
+ *
+ * Note that the return value is an RCU-protected pointer, so
+ * rcu_read_lock() must be held when calling this function.
* Returns %NULL if not found.
*/
const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
@@ -1152,6 +1284,9 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
* @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
+ * @sae_data: Non-IE data to use with SAE or %NULL. This starts with
+ * Authentication transaction sequence number field.
+ * @sae_data_len: Length of sae_data buffer in octets
*/
struct cfg80211_auth_request {
struct cfg80211_bss *bss;
@@ -1160,6 +1295,8 @@ struct cfg80211_auth_request {
enum nl80211_auth_type auth_type;
const u8 *key;
u8 key_len, key_idx;
+ const u8 *sae_data;
+ size_t sae_data_len;
};
/**
@@ -1252,8 +1389,7 @@ struct cfg80211_disassoc_request {
* @ssid_len: The length of the SSID, will always be non-zero.
* @bssid: Fixed BSSID requested, maybe be %NULL, if set do not
* search for IBSSs with a different BSSID.
- * @channel: The channel to use if no IBSS can be found to join.
- * @channel_type: channel type (HT mode)
+ * @chandef: defines the channel to use if no other IBSS to join can be found
* @channel_fixed: The channel should be fixed -- do not search for
* IBSSs to join on other channels.
* @ie: information element(s) to include in the beacon
@@ -1271,8 +1407,7 @@ struct cfg80211_disassoc_request {
struct cfg80211_ibss_params {
u8 *ssid;
u8 *bssid;
- struct ieee80211_channel *channel;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
u8 *ie;
u8 ssid_len, ie_len;
u16 beacon_interval;
@@ -1531,13 +1666,19 @@ struct cfg80211_gtk_rekey_data {
* to a merge.
* @leave_ibss: Leave the IBSS.
*
+ * @set_mcast_rate: Set the specified multicast rate (only if vif is in ADHOC or
+ * MESH mode)
+ *
* @set_wiphy_params: Notify that wiphy parameters have changed;
* @changed bitfield (see &enum wiphy_params_flags) describes which values
* 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,
- * the power passed is in mBm, to get dBm use MBM_TO_DBM().
+ * the power passed is in mBm, to get dBm use MBM_TO_DBM(). The
+ * wdev may be %NULL if power was set for the wiphy, and will
+ * always be %NULL unless the driver supports per-vif TX power
+ * (as advertised by the nl80211 feature flag.)
* @get_tx_power: store the current TX power into the dbm variable;
* return 0 if successful
*
@@ -1708,8 +1849,7 @@ struct cfg80211_ops {
struct ieee80211_channel *chan);
int (*set_monitor_channel)(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type);
+ struct cfg80211_chan_def *chandef);
int (*scan)(struct wiphy *wiphy,
struct cfg80211_scan_request *request);
@@ -1732,11 +1872,15 @@ struct cfg80211_ops {
struct cfg80211_ibss_params *params);
int (*leave_ibss)(struct wiphy *wiphy, struct net_device *dev);
+ int (*set_mcast_rate)(struct wiphy *wiphy, struct net_device *dev,
+ int rate[IEEE80211_NUM_BANDS]);
+
int (*set_wiphy_params)(struct wiphy *wiphy, u32 changed);
- int (*set_tx_power)(struct wiphy *wiphy,
+ int (*set_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm);
- int (*get_tx_power)(struct wiphy *wiphy, int *dbm);
+ int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
+ int *dbm);
int (*set_wds_peer)(struct wiphy *wiphy, struct net_device *dev,
const u8 *addr);
@@ -1767,7 +1911,6 @@ struct cfg80211_ops {
int (*remain_on_channel)(struct wiphy *wiphy,
struct wireless_dev *wdev,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration,
u64 *cookie);
int (*cancel_remain_on_channel)(struct wiphy *wiphy,
@@ -1776,10 +1919,8 @@ struct cfg80211_ops {
int (*mgmt_tx)(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
- enum nl80211_channel_type channel_type,
- bool channel_type_valid, unsigned int wait,
- const u8 *buf, size_t len, bool no_cck,
- bool dont_wait_for_ack, u64 *cookie);
+ unsigned int wait, const u8 *buf, size_t len,
+ bool no_cck, bool dont_wait_for_ack, u64 *cookie);
int (*mgmt_tx_cancel_wait)(struct wiphy *wiphy,
struct wireless_dev *wdev,
u64 cookie);
@@ -1834,10 +1975,9 @@ struct cfg80211_ops {
void (*get_et_strings)(struct wiphy *wiphy, struct net_device *dev,
u32 sset, u8 *data);
- struct ieee80211_channel *
- (*get_channel)(struct wiphy *wiphy,
+ int (*get_channel)(struct wiphy *wiphy,
struct wireless_dev *wdev,
- enum nl80211_channel_type *type);
+ struct cfg80211_chan_def *chandef);
int (*start_p2p_device)(struct wiphy *wiphy,
struct wireless_dev *wdev);
@@ -2445,8 +2585,7 @@ struct wireless_dev {
spinlock_t event_lock;
struct cfg80211_internal_bss *current_bss; /* associated / joined */
- struct ieee80211_channel *preset_chan;
- enum nl80211_channel_type preset_chantype;
+ struct cfg80211_chan_def preset_chandef;
/* for AP and mesh channel tracking */
struct ieee80211_channel *channel;
@@ -3326,14 +3465,12 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
* @wdev: wireless device
* @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
* @duration: Duration in milliseconds that the driver intents to remain on the
* channel
* @gfp: allocation flags
*/
void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
unsigned int duration, gfp_t gfp);
/**
@@ -3341,12 +3478,10 @@ void cfg80211_ready_on_channel(struct wireless_dev *wdev, u64 cookie,
* @wdev: wireless device
* @cookie: the request cookie
* @chan: The current channel (from remain_on_channel request)
- * @channel_type: Channel type
* @gfp: allocation flags
*/
void cfg80211_remain_on_channel_expired(struct wireless_dev *wdev, u64 cookie,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
gfp_t gfp);
@@ -3536,7 +3671,6 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
* @len: length of the frame
* @freq: frequency the frame was received on
* @sig_dbm: signal strength in mBm, or 0 if unknown
- * @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
@@ -3544,31 +3678,47 @@ void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
*/
void cfg80211_report_obss_beacon(struct wiphy *wiphy,
const u8 *frame, size_t len,
- int freq, int sig_dbm, gfp_t gfp);
+ int freq, int sig_dbm);
/**
- * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
+ * cfg80211_reg_can_beacon - check if beaconing is allowed
* @wiphy: the wiphy
- * @chan: main channel
- * @channel_type: HT mode
+ * @chandef: the channel definition
*
* This function returns true if there is no secondary channel or the secondary
- * channel can be used for beaconing (i.e. is not a radar channel etc.)
+ * channel(s) can be used for beaconing (i.e. is not a radar channel etc.)
*/
-bool cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
- struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type);
+bool cfg80211_reg_can_beacon(struct wiphy *wiphy,
+ struct cfg80211_chan_def *chandef);
/*
* cfg80211_ch_switch_notify - update wdev channel and notify userspace
* @dev: the device which switched channels
- * @freq: new channel frequency (in MHz)
- * @type: channel type
+ * @chandef: the new channel definition
*
* Acquires wdev_lock, so must only be called from sleepable driver context!
*/
-void cfg80211_ch_switch_notify(struct net_device *dev, int freq,
- enum nl80211_channel_type type);
+void cfg80211_ch_switch_notify(struct net_device *dev,
+ struct cfg80211_chan_def *chandef);
+
+/*
+ * cfg80211_tdls_oper_request - request userspace to perform TDLS operation
+ * @dev: the device on which the operation is requested
+ * @peer: the MAC address of the peer device
+ * @oper: the requested TDLS operation (NL80211_TDLS_SETUP or
+ * NL80211_TDLS_TEARDOWN)
+ * @reason_code: the reason code for teardown request
+ * @gfp: allocation flags
+ *
+ * This function is used to request userspace to perform TDLS operation that
+ * requires knowledge of keys, i.e., link setup or teardown when the AP
+ * connection uses encryption. This is optional mechanism for the driver to use
+ * if it can automatically determine when a TDLS link could be useful (e.g.,
+ * based on traffic and signal strength for a peer).
+ */
+void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer,
+ enum nl80211_tdls_operation oper,
+ u16 reason_code, gfp_t gfp);
/*
* cfg80211_calculate_bitrate - calculate actual bitrate (in 100Kbps units)
@@ -3594,6 +3744,26 @@ u32 cfg80211_calculate_bitrate(struct rate_info *rate);
*/
void cfg80211_unregister_wdev(struct wireless_dev *wdev);
+/**
+ * cfg80211_get_p2p_attr - find and copy a P2P attribute from IE buffer
+ * @ies: the input IE buffer
+ * @len: the input length
+ * @attr: the attribute ID to find
+ * @buf: output buffer, can be %NULL if the data isn't needed, e.g.
+ * if the function is only called to get the needed buffer size
+ * @bufsize: size of the output buffer
+ *
+ * The function finds a given P2P attribute in the (vendor) IEs and
+ * copies its contents to the given buffer.
+ *
+ * The return value is a negative error code (-%EILSEQ or -%ENOENT) if
+ * the data is malformed or the attribute can't be found (respectively),
+ * or the length of the found attribute (which can be zero).
+ */
+int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
+ enum ieee80211_p2p_attr_id attr,
+ u8 *buf, unsigned int bufsize);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/net/cls_cgroup.h b/include/net/cls_cgroup.h
index b6a6eeb3905..2581638f4a3 100644
--- a/include/net/cls_cgroup.h
+++ b/include/net/cls_cgroup.h
@@ -24,12 +24,12 @@ struct cgroup_cls_state
u32 classid;
};
-extern void sock_update_classid(struct sock *sk);
+extern void sock_update_classid(struct sock *sk, struct task_struct *task);
#if IS_BUILTIN(CONFIG_NET_CLS_CGROUP)
static inline u32 task_cls_classid(struct task_struct *p)
{
- int classid;
+ u32 classid;
if (in_interrupt())
return 0;
@@ -61,7 +61,7 @@ static inline u32 task_cls_classid(struct task_struct *p)
}
#endif
#else /* !CGROUP_NET_CLS_CGROUP */
-static inline void sock_update_classid(struct sock *sk)
+static inline void sock_update_classid(struct sock *sk, struct task_struct *task)
{
}
diff --git a/include/net/gro_cells.h b/include/net/gro_cells.h
index 4fd8a4b4b7e..e5062c955ea 100644
--- a/include/net/gro_cells.h
+++ b/include/net/gro_cells.h
@@ -17,7 +17,6 @@ struct gro_cells {
static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
{
- unsigned long flags;
struct gro_cell *cell = gcells->cells;
struct net_device *dev = skb->dev;
@@ -35,32 +34,37 @@ static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *s
return;
}
- spin_lock_irqsave(&cell->napi_skbs.lock, flags);
+ /* We run in BH context */
+ spin_lock(&cell->napi_skbs.lock);
__skb_queue_tail(&cell->napi_skbs, skb);
if (skb_queue_len(&cell->napi_skbs) == 1)
napi_schedule(&cell->napi);
- spin_unlock_irqrestore(&cell->napi_skbs.lock, flags);
+ spin_unlock(&cell->napi_skbs.lock);
}
+/* called unser BH context */
static inline int gro_cell_poll(struct napi_struct *napi, int budget)
{
struct gro_cell *cell = container_of(napi, struct gro_cell, napi);
struct sk_buff *skb;
int work_done = 0;
+ spin_lock(&cell->napi_skbs.lock);
while (work_done < budget) {
- skb = skb_dequeue(&cell->napi_skbs);
+ skb = __skb_dequeue(&cell->napi_skbs);
if (!skb)
break;
-
+ spin_unlock(&cell->napi_skbs.lock);
napi_gro_receive(napi, skb);
work_done++;
+ spin_lock(&cell->napi_skbs.lock);
}
if (work_done < budget)
napi_complete(napi);
+ spin_unlock(&cell->napi_skbs.lock);
return work_done;
}
diff --git a/include/net/ieee80211_radiotap.h b/include/net/ieee80211_radiotap.h
index 7f0df133d11..c3999632e61 100644
--- a/include/net/ieee80211_radiotap.h
+++ b/include/net/ieee80211_radiotap.h
@@ -186,6 +186,10 @@ struct ieee80211_radiotap_header {
* IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless
*
* Contains the AMPDU information for the subframe.
+ *
+ * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16
+ *
+ * Contains VHT information about this frame.
*/
enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_TSFT = 0,
@@ -209,6 +213,7 @@ enum ieee80211_radiotap_type {
IEEE80211_RADIOTAP_MCS = 19,
IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
+ IEEE80211_RADIOTAP_VHT = 21,
/* valid in every it_present bitmap, even vendor namespaces */
IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
@@ -282,6 +287,25 @@ enum ieee80211_radiotap_type {
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010
#define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020
+/* For IEEE80211_RADIOTAP_VHT */
+#define IEEE80211_RADIOTAP_VHT_KNOWN_STBC 0x0001
+#define IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA 0x0002
+#define IEEE80211_RADIOTAP_VHT_KNOWN_GI 0x0004
+#define IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS 0x0008
+#define IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM 0x0010
+#define IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED 0x0020
+#define IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH 0x0040
+#define IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID 0x0080
+#define IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID 0x0100
+
+#define IEEE80211_RADIOTAP_VHT_FLAG_STBC 0x01
+#define IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA 0x02
+#define IEEE80211_RADIOTAP_VHT_FLAG_SGI 0x04
+#define IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 0x08
+#define IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM 0x10
+#define IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED 0x20
+
+
/* helpers */
static inline int ieee80211_get_radiotap_len(unsigned char *data)
{
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 54be0287eb9..67a8fa098e3 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -277,7 +277,6 @@ static inline struct sock *inet_lookup_listener(struct net *net,
On 64bit targets we combine comparisons with pair of adjacent __be32
fields in the same way.
*/
-typedef __u32 __bitwise __portpair;
#ifdef __BIG_ENDIAN
#define INET_COMBINED_PORTS(__sport, __dport) \
((__force __portpair)(((__force __u32)(__be16)(__sport) << 16) | (__u32)(__dport)))
@@ -287,7 +286,6 @@ typedef __u32 __bitwise __portpair;
#endif
#if (BITS_PER_LONG == 64)
-typedef __u64 __bitwise __addrpair;
#ifdef __BIG_ENDIAN
#define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
const __addrpair __name = (__force __addrpair) ( \
@@ -299,30 +297,34 @@ typedef __u64 __bitwise __addrpair;
(((__force __u64)(__be32)(__daddr)) << 32) | \
((__force __u64)(__be32)(__saddr)));
#endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- ((*((__addrpair *)&(inet_sk(__sk)->inet_daddr))) == (__cookie)) && \
- ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- ((*((__addrpair *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) && \
- ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_sk(__sk)->inet_portpair == (__ports)) && \
+ (inet_sk(__sk)->inet_addrpair == (__cookie)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
+#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif)\
+ ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
+ (inet_twsk(__sk)->tw_addrpair == (__cookie)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
#else /* 32-bit arch */
#define INET_ADDR_COOKIE(__name, __saddr, __daddr)
-#define INET_MATCH(__sk, __net, __hash, __cookie, __saddr, __daddr, __ports, __dif) \
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- (inet_sk(__sk)->inet_daddr == (__saddr)) && \
- (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \
- ((*((__portpair *)&(inet_sk(__sk)->inet_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __net, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
- (((__sk)->sk_hash == (__hash)) && net_eq(sock_net(__sk), (__net)) && \
- (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
- (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
- ((*((__portpair *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) && \
- (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
+#define INET_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_sk(__sk)->inet_portpair == (__ports)) && \
+ (inet_sk(__sk)->inet_daddr == (__saddr)) && \
+ (inet_sk(__sk)->inet_rcv_saddr == (__daddr)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
+#define INET_TW_MATCH(__sk, __net, __cookie, __saddr, __daddr, __ports, __dif) \
+ ((inet_twsk(__sk)->tw_portpair == (__ports)) && \
+ (inet_twsk(__sk)->tw_daddr == (__saddr)) && \
+ (inet_twsk(__sk)->tw_rcv_saddr == (__daddr)) && \
+ (!(__sk)->sk_bound_dev_if || \
+ ((__sk)->sk_bound_dev_if == (__dif))) && \
+ net_eq(sock_net(__sk), (__net)))
#endif /* 64-bit arch */
/*
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 256c1ed2d69..a4196cbc84e 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -144,9 +144,11 @@ struct inet_sock {
/* Socket demultiplex comparisons on incoming packets. */
#define inet_daddr sk.__sk_common.skc_daddr
#define inet_rcv_saddr sk.__sk_common.skc_rcv_saddr
+#define inet_addrpair sk.__sk_common.skc_addrpair
+#define inet_dport sk.__sk_common.skc_dport
+#define inet_num sk.__sk_common.skc_num
+#define inet_portpair sk.__sk_common.skc_portpair
- __be16 inet_dport;
- __u16 inet_num;
__be32 inet_saddr;
__s16 uc_ttl;
__u16 cmsg_flags;
@@ -154,6 +156,7 @@ struct inet_sock {
__u16 inet_id;
struct ip_options_rcu __rcu *inet_opt;
+ int rx_dst_ifindex;
__u8 tos;
__u8 min_ttl;
__u8 mc_ttl;
@@ -170,7 +173,6 @@ struct inet_sock {
int uc_index;
int mc_index;
__be32 mc_addr;
- int rx_dst_ifindex;
struct ip_mc_socklist __rcu *mc_list;
struct inet_cork_full cork;
};
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index ba52c830a7a..7d658d57736 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -112,6 +112,11 @@ struct inet_timewait_sock {
#define tw_net __tw_common.skc_net
#define tw_daddr __tw_common.skc_daddr
#define tw_rcv_saddr __tw_common.skc_rcv_saddr
+#define tw_addrpair __tw_common.skc_addrpair
+#define tw_dport __tw_common.skc_dport
+#define tw_num __tw_common.skc_num
+#define tw_portpair __tw_common.skc_portpair
+
int tw_timeout;
volatile unsigned char tw_substate;
unsigned char tw_rcv_wscale;
@@ -119,8 +124,6 @@ struct inet_timewait_sock {
/* Socket demultiplex comparisons on incoming packets. */
/* these three are in inet_sock */
__be16 tw_sport;
- __be16 tw_dport;
- __u16 tw_num;
kmemcheck_bitfield_begin(flags);
/* And these are ours. */
unsigned int tw_ipv6only : 1,
diff --git a/include/net/ip6_checksum.h b/include/net/ip6_checksum.h
index bc1b0fda2b0..652d3d30935 100644
--- a/include/net/ip6_checksum.h
+++ b/include/net/ip6_checksum.h
@@ -31,6 +31,8 @@
#include <net/ip.h>
#include <asm/checksum.h>
#include <linux/in6.h>
+#include <linux/tcp.h>
+#include <linux/ipv6.h>
#ifndef _HAVE_ARCH_IPV6_CSUM
@@ -91,4 +93,37 @@ static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
}
#endif
+
+static __inline__ __sum16 tcp_v6_check(int len,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr,
+ __wsum base)
+{
+ return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base);
+}
+
+static inline void __tcp_v6_send_check(struct sk_buff *skb,
+ const struct in6_addr *saddr,
+ const struct in6_addr *daddr)
+{
+ struct tcphdr *th = tcp_hdr(skb);
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ th->check = ~tcp_v6_check(skb->len, saddr, daddr, 0);
+ skb->csum_start = skb_transport_header(skb) - skb->head;
+ skb->csum_offset = offsetof(struct tcphdr, check);
+ } else {
+ th->check = tcp_v6_check(skb->len, saddr, daddr,
+ csum_partial(th, th->doff << 2,
+ skb->csum));
+ }
+}
+
+static inline void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb)
+{
+ struct ipv6_pinfo *np = inet6_sk(sk);
+
+ __tcp_v6_send_check(skb, &np->saddr, &np->daddr);
+}
+
#endif
diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h
index 8a2a203eb15..fdc48a94a06 100644
--- a/include/net/ip6_fib.h
+++ b/include/net/ip6_fib.h
@@ -47,6 +47,8 @@ struct fib6_config {
unsigned long fc_expires;
struct nlattr *fc_mx;
int fc_mx_len;
+ int fc_mp_len;
+ struct nlattr *fc_mp;
struct nl_info fc_nlinfo;
};
@@ -99,6 +101,14 @@ struct rt6_info {
struct in6_addr rt6i_gateway;
+ /* Multipath routes:
+ * siblings is a list of rt6_info that have the the same metric/weight,
+ * destination, but not the same gateway. nsiblings is just a cache
+ * to speed up lookup.
+ */
+ struct list_head rt6i_siblings;
+ unsigned int rt6i_nsiblings;
+
atomic_t rt6i_ref;
/* These are in a separate cache line. */
@@ -107,7 +117,6 @@ struct rt6_info {
struct rt6key rt6i_src;
struct rt6key rt6i_prefsrc;
u32 rt6i_metric;
- u32 rt6i_peer_genid;
struct inet6_dev *rt6i_idev;
unsigned long _rt6i_peer;
@@ -203,6 +212,15 @@ static inline void rt6_set_from(struct rt6_info *rt, struct rt6_info *from)
dst_hold(new);
}
+static inline void ip6_rt_put(struct rt6_info *rt)
+{
+ /* dst_release() accepts a NULL parameter.
+ * We rely on dst being first structure in struct rt6_info
+ */
+ BUILD_BUG_ON(offsetof(struct rt6_info, dst) != 0);
+ dst_release(&rt->dst);
+}
+
struct fib6_walker_t {
struct list_head lh;
struct fib6_node *root, *node;
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 5fa2af00634..27d83183e61 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -1,9 +1,6 @@
#ifndef _NET_IP6_ROUTE_H
#define _NET_IP6_ROUTE_H
-#define IP6_RT_PRIO_USER 1024
-#define IP6_RT_PRIO_ADDRCONF 256
-
struct route_info {
__u8 type;
__u8 length;
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index ee75ccdf518..68c69d54d39 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -22,7 +22,10 @@
#include <linux/ip.h>
#include <linux/ipv6.h> /* for struct ipv6hdr */
#include <net/ipv6.h>
-#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
+#if IS_ENABLED(CONFIG_IP_VS_IPV6)
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#endif
+#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <net/netfilter/nf_conntrack.h>
#endif
#include <net/net_namespace.h> /* Netw namespace */
@@ -103,30 +106,117 @@ static inline struct net *seq_file_single_net(struct seq_file *seq)
/* Connections' size value needed by ip_vs_ctl.c */
extern int ip_vs_conn_tab_size;
-
struct ip_vs_iphdr {
- int len;
- __u8 protocol;
+ __u32 len; /* IPv4 simply where L4 starts
+ IPv6 where L4 Transport Header starts */
+ __u32 thoff_reasm; /* Transport Header Offset in nfct_reasm skb */
+ __u16 fragoffs; /* IPv6 fragment offset, 0 if first frag (or not frag)*/
+ __s16 protocol;
+ __s32 flags;
union nf_inet_addr saddr;
union nf_inet_addr daddr;
};
+/* Dependency to module: nf_defrag_ipv6 */
+#if defined(CONFIG_NF_DEFRAG_IPV6) || defined(CONFIG_NF_DEFRAG_IPV6_MODULE)
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+ return skb->nfct_reasm;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+ int len, void *buffer,
+ const struct ip_vs_iphdr *ipvsh)
+{
+ if (unlikely(ipvsh->fragoffs && skb_nfct_reasm(skb)))
+ return skb_header_pointer(skb_nfct_reasm(skb),
+ ipvsh->thoff_reasm, len, buffer);
+
+ return skb_header_pointer(skb, offset, len, buffer);
+}
+#else
+static inline struct sk_buff *skb_nfct_reasm(const struct sk_buff *skb)
+{
+ return NULL;
+}
+static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
+ int len, void *buffer,
+ const struct ip_vs_iphdr *ipvsh)
+{
+ return skb_header_pointer(skb, offset, len, buffer);
+}
+#endif
+
static inline void
-ip_vs_fill_iphdr(int af, const void *nh, struct ip_vs_iphdr *iphdr)
+ip_vs_fill_ip4hdr(const void *nh, struct ip_vs_iphdr *iphdr)
+{
+ const struct iphdr *iph = nh;
+
+ iphdr->len = iph->ihl * 4;
+ iphdr->fragoffs = 0;
+ iphdr->protocol = iph->protocol;
+ iphdr->saddr.ip = iph->saddr;
+ iphdr->daddr.ip = iph->daddr;
+}
+
+/* This function handles filling *ip_vs_iphdr, both for IPv4 and IPv6.
+ * IPv6 requires some extra work, as finding proper header position,
+ * depend on the IPv6 extension headers.
+ */
+static inline void
+ip_vs_fill_iph_skb(int af, const struct sk_buff *skb, struct ip_vs_iphdr *iphdr)
{
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6) {
- const struct ipv6hdr *iph = nh;
- iphdr->len = sizeof(struct ipv6hdr);
- iphdr->protocol = iph->nexthdr;
+ const struct ipv6hdr *iph =
+ (struct ipv6hdr *)skb_network_header(skb);
iphdr->saddr.in6 = iph->saddr;
iphdr->daddr.in6 = iph->daddr;
+ /* ipv6_find_hdr() updates len, flags, thoff_reasm */
+ iphdr->thoff_reasm = 0;
+ iphdr->len = 0;
+ iphdr->flags = 0;
+ iphdr->protocol = ipv6_find_hdr(skb, &iphdr->len, -1,
+ &iphdr->fragoffs,
+ &iphdr->flags);
+ /* get proto from re-assembled packet and it's offset */
+ if (skb_nfct_reasm(skb))
+ iphdr->protocol = ipv6_find_hdr(skb_nfct_reasm(skb),
+ &iphdr->thoff_reasm,
+ -1, NULL, NULL);
+
} else
#endif
{
- const struct iphdr *iph = nh;
- iphdr->len = iph->ihl * 4;
- iphdr->protocol = iph->protocol;
+ const struct iphdr *iph =
+ (struct iphdr *)skb_network_header(skb);
+ iphdr->len = iph->ihl * 4;
+ iphdr->fragoffs = 0;
+ iphdr->protocol = iph->protocol;
+ iphdr->saddr.ip = iph->saddr;
+ iphdr->daddr.ip = iph->daddr;
+ }
+}
+
+/* This function is a faster version of ip_vs_fill_iph_skb().
+ * Where we only populate {s,d}addr (and avoid calling ipv6_find_hdr()).
+ * This is used by the some of the ip_vs_*_schedule() functions.
+ * (Mostly done to avoid ABI breakage of external schedulers)
+ */
+static inline void
+ip_vs_fill_iph_addr_only(int af, const struct sk_buff *skb,
+ struct ip_vs_iphdr *iphdr)
+{
+#ifdef CONFIG_IP_VS_IPV6
+ if (af == AF_INET6) {
+ const struct ipv6hdr *iph =
+ (struct ipv6hdr *)skb_network_header(skb);
+ iphdr->saddr.in6 = iph->saddr;
+ iphdr->daddr.in6 = iph->daddr;
+ } else
+#endif
+ {
+ const struct iphdr *iph =
+ (struct iphdr *)skb_network_header(skb);
iphdr->saddr.ip = iph->saddr;
iphdr->daddr.ip = iph->daddr;
}
@@ -165,7 +255,7 @@ static inline const char *ip_vs_dbg_addr(int af, char *buf, size_t buf_len,
int len;
#ifdef CONFIG_IP_VS_IPV6
if (af == AF_INET6)
- len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6]",
+ len = snprintf(&buf[*idx], buf_len - *idx, "[%pI6c]",
&addr->in6) + 1;
else
#endif
@@ -398,27 +488,26 @@ struct ip_vs_protocol {
int (*conn_schedule)(int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd,
- int *verdict, struct ip_vs_conn **cpp);
+ int *verdict, struct ip_vs_conn **cpp,
+ struct ip_vs_iphdr *iph);
struct ip_vs_conn *
(*conn_in_get)(int af,
const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
struct ip_vs_conn *
(*conn_out_get)(int af,
const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
- int (*snat_handler)(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+ int (*snat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
- int (*dnat_handler)(struct sk_buff *skb,
- struct ip_vs_protocol *pp, struct ip_vs_conn *cp);
+ int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
+ struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
int (*csum_check)(int af, struct sk_buff *skb,
struct ip_vs_protocol *pp);
@@ -518,7 +607,7 @@ struct ip_vs_conn {
NF_ACCEPT can be returned when destination is local.
*/
int (*packet_xmit)(struct sk_buff *skb, struct ip_vs_conn *cp,
- struct ip_vs_protocol *pp);
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
/* Note: we can group the following members into a structure,
in order to save more space, and the following members are
@@ -769,13 +858,11 @@ struct ip_vs_app {
struct ip_vs_conn *
(*conn_in_get)(const struct sk_buff *skb, struct ip_vs_app *app,
- const struct iphdr *iph, unsigned int proto_off,
- int inverse);
+ const struct iphdr *iph, int inverse);
struct ip_vs_conn *
(*conn_out_get)(const struct sk_buff *skb, struct ip_vs_app *app,
- const struct iphdr *iph, unsigned int proto_off,
- int inverse);
+ const struct iphdr *iph, int inverse);
int (*state_transition)(struct ip_vs_conn *cp, int direction,
const struct sk_buff *skb,
@@ -1074,14 +1161,12 @@ struct ip_vs_conn *ip_vs_ct_in_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_in_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
struct ip_vs_conn *ip_vs_conn_out_get(const struct ip_vs_conn_param *p);
struct ip_vs_conn * ip_vs_conn_out_get_proto(int af, const struct sk_buff *skb,
const struct ip_vs_iphdr *iph,
- unsigned int proto_off,
int inverse);
/* put back the conn without restarting its timer */
@@ -1254,9 +1339,10 @@ extern struct ip_vs_scheduler *ip_vs_scheduler_get(const char *sched_name);
extern void ip_vs_scheduler_put(struct ip_vs_scheduler *scheduler);
extern struct ip_vs_conn *
ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
- struct ip_vs_proto_data *pd, int *ignored);
+ struct ip_vs_proto_data *pd, int *ignored,
+ struct ip_vs_iphdr *iph);
extern int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
- struct ip_vs_proto_data *pd);
+ struct ip_vs_proto_data *pd, struct ip_vs_iphdr *iph);
extern void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg);
@@ -1315,33 +1401,38 @@ extern void ip_vs_read_estimator(struct ip_vs_stats_user *dst,
/*
* Various IPVS packet transmitters (from ip_vs_xmit.c)
*/
-extern int ip_vs_null_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_bypass_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_null_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, int offset,
+ unsigned int hooknum, struct ip_vs_iphdr *iph);
extern void ip_vs_dst_reset(struct ip_vs_dest *dest);
#ifdef CONFIG_IP_VS_IPV6
-extern int ip_vs_bypass_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_nat_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_tunnel_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_dr_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp);
-extern int ip_vs_icmp_xmit_v6
-(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp,
- int offset, unsigned int hooknum);
+extern int ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp,
+ struct ip_vs_iphdr *iph);
+extern int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);
+extern int ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
+ struct ip_vs_protocol *pp, int offset,
+ unsigned int hooknum, struct ip_vs_iphdr *iph);
#endif
#ifdef CONFIG_SYSCTL
diff --git a/include/net/ipip.h b/include/net/ipip.h
index ddc077c51f3..21947cf4fa4 100644
--- a/include/net/ipip.h
+++ b/include/net/ipip.h
@@ -48,25 +48,27 @@ struct ip_tunnel_prl_entry {
struct rcu_head rcu_head;
};
-#define __IPTUNNEL_XMIT(stats1, stats2) do { \
- int err; \
- int pkt_len = skb->len - skb_transport_offset(skb); \
- \
- skb->ip_summed = CHECKSUM_NONE; \
- ip_select_ident(iph, &rt->dst, NULL); \
- \
- err = ip_local_out(skb); \
- if (likely(net_xmit_eval(err) == 0)) { \
- u64_stats_update_begin(&(stats1)->syncp); \
- (stats1)->tx_bytes += pkt_len; \
- (stats1)->tx_packets++; \
- u64_stats_update_end(&(stats1)->syncp); \
- } else { \
- (stats2)->tx_errors++; \
- (stats2)->tx_aborted_errors++; \
- } \
-} while (0)
+static inline void iptunnel_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ int err;
+ struct iphdr *iph = ip_hdr(skb);
+ int pkt_len = skb->len - skb_transport_offset(skb);
+ struct pcpu_tstats *tstats = this_cpu_ptr(dev->tstats);
-#define IPTUNNEL_XMIT() __IPTUNNEL_XMIT(txq, stats)
+ nf_reset(skb);
+ skb->ip_summed = CHECKSUM_NONE;
+ ip_select_ident(iph, skb_dst(skb), NULL);
+
+ err = ip_local_out(skb);
+ if (likely(net_xmit_eval(err) == 0)) {
+ u64_stats_update_begin(&tstats->syncp);
+ tstats->tx_bytes += pkt_len;
+ tstats->tx_packets++;
+ u64_stats_update_end(&tstats->syncp);
+ } else {
+ dev->stats.tx_errors++;
+ dev->stats.tx_aborted_errors++;
+ }
+}
#endif
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 979bf6c1314..5af66b26ebd 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -271,6 +271,15 @@ struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,
extern bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb);
+static inline bool ipv6_accept_ra(struct inet6_dev *idev)
+{
+ /* If forwarding is enabled, RA are not accepted unless the special
+ * hybrid mode (accept_ra=2) is enabled.
+ */
+ return idev->cnf.forwarding ? idev->cnf.accept_ra == 2 :
+ idev->cnf.accept_ra;
+}
+
#if IS_ENABLED(CONFIG_IPV6)
static inline int ip6_frag_nqueues(struct net *net)
{
@@ -630,6 +639,16 @@ extern int ipv6_skip_exthdr(const struct sk_buff *, int start,
extern bool ipv6_ext_hdr(u8 nexthdr);
+enum {
+ IP6_FH_F_FRAG = (1 << 0),
+ IP6_FH_F_AUTH = (1 << 1),
+ IP6_FH_F_SKIP_RH = (1 << 2),
+};
+
+/* find specified header and get offset to it */
+extern int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
+ int target, unsigned short *fragoff, int *fragflg);
+
extern int ipv6_find_tlv(struct sk_buff *skb, int offset, int type);
extern struct in6_addr *fl6_update_dst(struct flowi6 *fl6,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82558c8decf..ee50c5eba50 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -144,6 +144,39 @@ struct ieee80211_low_level_stats {
};
/**
+ * enum ieee80211_chanctx_change - change flag for channel context
+ * @IEEE80211_CHANCTX_CHANGE_WIDTH: The channel width changed
+ * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed
+ */
+enum ieee80211_chanctx_change {
+ IEEE80211_CHANCTX_CHANGE_WIDTH = BIT(0),
+ IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1),
+};
+
+/**
+ * struct ieee80211_chanctx_conf - channel context that vifs may be tuned to
+ *
+ * This is the driver-visible part. The ieee80211_chanctx
+ * that contains it is visible in mac80211 only.
+ *
+ * @def: the channel definition
+ * @rx_chains_static: The number of RX chains that must always be
+ * active on the channel to receive MIMO transmissions
+ * @rx_chains_dynamic: The number of RX chains that must be enabled
+ * after RTS/CTS handshake to receive SMPS MIMO transmissions;
+ * this will always be >= @rx_chains_static.
+ * @drv_priv: data area for driver use, will always be aligned to
+ * sizeof(void *), size is determined in hw information.
+ */
+struct ieee80211_chanctx_conf {
+ struct cfg80211_chan_def def;
+
+ u8 rx_chains_static, rx_chains_dynamic;
+
+ u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *))));
+};
+
+/**
* enum ieee80211_bss_change - BSS change notification flags
*
* These flags are used with the bss_info_changed() callback
@@ -172,6 +205,9 @@ struct ieee80211_low_level_stats {
* @BSS_CHANGED_SSID: SSID changed for this BSS (AP mode)
* @BSS_CHANGED_AP_PROBE_RESP: Probe Response changed for this BSS (AP mode)
* @BSS_CHANGED_PS: PS changed for this BSS (STA mode)
+ * @BSS_CHANGED_TXPOWER: TX power setting changed for this interface
+ * @BSS_CHANGED_P2P_PS: P2P powersave settings (CTWindow, opportunistic PS)
+ * changed (currently only in P2P client mode, GO mode will be later)
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
@@ -192,6 +228,8 @@ enum ieee80211_bss_change {
BSS_CHANGED_SSID = 1<<15,
BSS_CHANGED_AP_PROBE_RESP = 1<<16,
BSS_CHANGED_PS = 1<<17,
+ BSS_CHANGED_TXPOWER = 1<<18,
+ BSS_CHANGED_P2P_PS = 1<<19,
/* when adding here, make sure to change ieee80211_reconfig */
};
@@ -223,6 +261,7 @@ enum ieee80211_rssi_event {
* @assoc: association status
* @ibss_joined: indicates whether this station is part of an IBSS
* or not
+ * @ibss_creator: indicates if a new IBSS network is being created
* @aid: association ID number, valid only when @assoc is true
* @use_cts_prot: use CTS protection
* @use_short_preamble: use 802.11b short preamble;
@@ -247,9 +286,8 @@ enum ieee80211_rssi_event {
* @mcast_rate: per-band multicast rate index + 1 (0: disabled)
* @bssid: The BSSID for this BSS
* @enable_beacon: whether beaconing should be enabled or not
- * @channel_type: Channel type for this BSS -- the hardware might be
- * configured for HT40+ while this BSS only uses no-HT, for
- * example.
+ * @chandef: Channel definition for this BSS -- the hardware might be
+ * configured a higher bandwidth than this BSS uses, for example.
* @ht_operation_mode: HT operation mode like in &struct ieee80211_ht_operation.
* This field is only valid when the channel type is one of the HT types.
* @cqm_rssi_thold: Connection quality monitor RSSI threshold, a zero value
@@ -273,11 +311,15 @@ enum ieee80211_rssi_event {
* @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.
+ * @txpower: TX power in dBm
+ * @p2p_ctwindow: P2P CTWindow, only for P2P client interfaces
+ * @p2p_oppps: P2P opportunistic PS is enabled
*/
struct ieee80211_bss_conf {
const u8 *bssid;
/* association related data */
bool assoc, ibss_joined;
+ bool ibss_creator;
u16 aid;
/* erp related data */
bool use_cts_prot;
@@ -294,7 +336,7 @@ struct ieee80211_bss_conf {
u16 ht_operation_mode;
s32 cqm_rssi_thold;
u32 cqm_rssi_hyst;
- enum nl80211_channel_type channel_type;
+ struct cfg80211_chan_def chandef;
__be32 arp_addr_list[IEEE80211_BSS_ARP_ADDR_LIST_LEN];
u8 arp_addr_cnt;
bool arp_filter_enabled;
@@ -304,6 +346,9 @@ struct ieee80211_bss_conf {
u8 ssid[IEEE80211_MAX_SSID_LEN];
size_t ssid_len;
bool hidden_ssid;
+ int txpower;
+ u8 p2p_ctwindow;
+ bool p2p_oppps;
};
/**
@@ -454,9 +499,14 @@ enum mac80211_tx_control_flags {
* This is set if the current BSS requires ERP protection.
* @IEEE80211_TX_RC_USE_SHORT_PREAMBLE: Use short preamble.
* @IEEE80211_TX_RC_MCS: HT rate.
+ * @IEEE80211_TX_RC_VHT_MCS: VHT MCS rate, in this case the idx field is split
+ * into a higher 4 bits (Nss) and lower 4 bits (MCS number)
* @IEEE80211_TX_RC_GREEN_FIELD: Indicates whether this rate should be used in
* Greenfield mode.
* @IEEE80211_TX_RC_40_MHZ_WIDTH: Indicates if the Channel Width should be 40 MHz.
+ * @IEEE80211_TX_RC_80_MHZ_WIDTH: Indicates 80 MHz transmission
+ * @IEEE80211_TX_RC_160_MHZ_WIDTH: Indicates 160 MHz transmission
+ * (80+80 isn't supported yet)
* @IEEE80211_TX_RC_DUP_DATA: The frame should be transmitted on both of the
* adjacent 20 MHz channels, if the current channel type is
* NL80211_CHAN_HT40MINUS or NL80211_CHAN_HT40PLUS.
@@ -467,12 +517,15 @@ enum mac80211_rate_control_flags {
IEEE80211_TX_RC_USE_CTS_PROTECT = BIT(1),
IEEE80211_TX_RC_USE_SHORT_PREAMBLE = BIT(2),
- /* rate index is an MCS rate number instead of an index */
+ /* rate index is an HT/VHT MCS instead of an index */
IEEE80211_TX_RC_MCS = BIT(3),
IEEE80211_TX_RC_GREEN_FIELD = BIT(4),
IEEE80211_TX_RC_40_MHZ_WIDTH = BIT(5),
IEEE80211_TX_RC_DUP_DATA = BIT(6),
IEEE80211_TX_RC_SHORT_GI = BIT(7),
+ IEEE80211_TX_RC_VHT_MCS = BIT(8),
+ IEEE80211_TX_RC_80_MHZ_WIDTH = BIT(9),
+ IEEE80211_TX_RC_160_MHZ_WIDTH = BIT(10),
};
@@ -515,10 +568,32 @@ enum mac80211_rate_control_flags {
*/
struct ieee80211_tx_rate {
s8 idx;
- u8 count;
- u8 flags;
+ u16 count:5,
+ flags:11;
} __packed;
+#define IEEE80211_MAX_TX_RETRY 31
+
+static inline void ieee80211_rate_set_vht(struct ieee80211_tx_rate *rate,
+ u8 mcs, u8 nss)
+{
+ WARN_ON(mcs & ~0xF);
+ WARN_ON(nss & ~0x7);
+ rate->idx = (nss << 4) | mcs;
+}
+
+static inline u8
+ieee80211_rate_get_vht_mcs(const struct ieee80211_tx_rate *rate)
+{
+ return rate->idx & 0xF;
+}
+
+static inline u8
+ieee80211_rate_get_vht_nss(const struct ieee80211_tx_rate *rate)
+{
+ return rate->idx >> 4;
+}
+
/**
* struct ieee80211_tx_info - skb transmit information
*
@@ -663,13 +738,20 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
* the frame.
* @RX_FLAG_FAILED_PLCP_CRC: Set this flag if the PCLP check failed on
* the frame.
- * @RX_FLAG_MACTIME_MPDU: The timestamp passed in the RX status (@mactime
+ * @RX_FLAG_MACTIME_START: The timestamp passed in the RX status (@mactime
* field) is valid and contains the time the first symbol of the MPDU
* was received. This is useful in monitor mode and for proper IBSS
* merging.
+ * @RX_FLAG_MACTIME_END: The timestamp passed in the RX status (@mactime
+ * field) is valid and contains the time the last symbol of the MPDU
+ * (including FCS) was received.
* @RX_FLAG_SHORTPRE: Short preamble was used for this frame
* @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
+ * @RX_FLAG_VHT: VHT MCS was used and rate_index is MCS index
* @RX_FLAG_40MHZ: HT40 (40 MHz) was used
+ * @RX_FLAG_80MHZ: 80 MHz was used
+ * @RX_FLAG_80P80MHZ: 80+80 MHz was used
+ * @RX_FLAG_160MHZ: 160 MHz was used
* @RX_FLAG_SHORT_GI: Short guard interval was used
* @RX_FLAG_NO_SIGNAL_VAL: The signal strength value is not present.
* Valid only for data frames (mainly A-MPDU)
@@ -697,7 +779,7 @@ enum mac80211_rx_flags {
RX_FLAG_IV_STRIPPED = BIT(4),
RX_FLAG_FAILED_FCS_CRC = BIT(5),
RX_FLAG_FAILED_PLCP_CRC = BIT(6),
- RX_FLAG_MACTIME_MPDU = BIT(7),
+ RX_FLAG_MACTIME_START = BIT(7),
RX_FLAG_SHORTPRE = BIT(8),
RX_FLAG_HT = BIT(9),
RX_FLAG_40MHZ = BIT(10),
@@ -711,6 +793,11 @@ enum mac80211_rx_flags {
RX_FLAG_AMPDU_IS_LAST = BIT(18),
RX_FLAG_AMPDU_DELIM_CRC_ERROR = BIT(19),
RX_FLAG_AMPDU_DELIM_CRC_KNOWN = BIT(20),
+ RX_FLAG_MACTIME_END = BIT(21),
+ RX_FLAG_VHT = BIT(22),
+ RX_FLAG_80MHZ = BIT(23),
+ RX_FLAG_80P80MHZ = BIT(24),
+ RX_FLAG_160MHZ = BIT(25),
};
/**
@@ -731,25 +818,39 @@ enum mac80211_rx_flags {
* @IEEE80211_HW_SIGNAL_*
* @antenna: antenna used
* @rate_idx: index of data rate into band's supported rates or MCS index if
- * HT rates are use (RX_FLAG_HT)
+ * HT or VHT is used (%RX_FLAG_HT/%RX_FLAG_VHT)
+ * @vht_nss: number of streams (VHT only)
* @flag: %RX_FLAG_*
* @rx_flags: internal RX flags for mac80211
* @ampdu_reference: A-MPDU reference number, must be a different value for
* each A-MPDU but the same for each subframe within one A-MPDU
* @ampdu_delimiter_crc: A-MPDU delimiter CRC
+ * @vendor_radiotap_bitmap: radiotap vendor namespace presence bitmap
+ * @vendor_radiotap_len: radiotap vendor namespace length
+ * @vendor_radiotap_align: radiotap vendor namespace alignment. Note
+ * that the actual data must be at the start of the SKB data
+ * already.
+ * @vendor_radiotap_oui: radiotap vendor namespace OUI
+ * @vendor_radiotap_subns: radiotap vendor sub namespace
*/
struct ieee80211_rx_status {
u64 mactime;
u32 device_timestamp;
u32 ampdu_reference;
u32 flag;
+ u32 vendor_radiotap_bitmap;
+ u16 vendor_radiotap_len;
u16 freq;
u8 rate_idx;
+ u8 vht_nss;
u8 rx_flags;
u8 band;
u8 antenna;
s8 signal;
u8 ampdu_delimiter_crc;
+ u8 vendor_radiotap_align;
+ u8 vendor_radiotap_oui[3];
+ u8 vendor_radiotap_subns;
};
/**
@@ -794,6 +895,8 @@ enum ieee80211_conf_flags {
* @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed
* @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed
* @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed
+ * Note that this is only valid if channel contexts are not used,
+ * otherwise each channel context has the number of chains listed.
*/
enum ieee80211_conf_changed {
IEEE80211_CONF_CHANGE_SMPS = BIT(1),
@@ -845,7 +948,8 @@ enum ieee80211_smps_mode {
* powersave documentation below. This variable is valid only when
* the CONF_PS flag is set.
*
- * @power_level: requested transmit power (in dBm)
+ * @power_level: requested transmit power (in dBm), backward compatibility
+ * value only that is set to the minimum of all interfaces
*
* @channel: the channel to tune to
* @channel_type: the channel (HT) type
@@ -859,7 +963,9 @@ enum ieee80211_smps_mode {
*
* @smps_mode: spatial multiplexing powersave mode; note that
* %IEEE80211_SMPS_STATIC is used when the device is not
- * configured for an HT channel
+ * configured for an HT channel.
+ * Note that this is only valid if channel contexts are not used,
+ * otherwise each channel context has the number of chains listed.
*/
struct ieee80211_conf {
u32 flags;
@@ -931,6 +1037,11 @@ enum ieee80211_vif_flags {
* at runtime, mac80211 will never touch this field
* @hw_queue: hardware queue for each AC
* @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only
+ * @chanctx_conf: The channel context this interface is assigned to, or %NULL
+ * when it is not assigned. This pointer is RCU-protected due to the TX
+ * path needing to access it; even though the netdev carrier will always
+ * be off when it is %NULL there can still be races and packets could be
+ * processed after it switches back to %NULL.
* @drv_priv: data area for driver use, will always be aligned to
* sizeof(void *).
*/
@@ -943,6 +1054,8 @@ struct ieee80211_vif {
u8 cab_queue;
u8 hw_queue[IEEE80211_NUM_ACS];
+ struct ieee80211_chanctx_conf __rcu *chanctx_conf;
+
u32 driver_flags;
/* must be last */
@@ -1076,6 +1189,8 @@ enum ieee80211_sta_state {
* @aid: AID we assigned to the station if we're an AP
* @supp_rates: Bitmap of supported rates (per band)
* @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities
+ * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities
+ * of remote STA. Taking as is.
* @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.
@@ -1088,6 +1203,7 @@ struct ieee80211_sta {
u8 addr[ETH_ALEN];
u16 aid;
struct ieee80211_sta_ht_cap ht_cap;
+ struct ieee80211_sta_vht_cap vht_cap;
bool wme;
u8 uapsd_queues;
u8 max_sp;
@@ -1253,6 +1369,10 @@ struct ieee80211_tx_control {
* @IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF: Use the P2P Device address for any
* P2P Interface. This will be honoured even if more than one interface
* is supported.
+ *
+ * @IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL: On this hardware TX BA session
+ * should be tear down once BAR frame will not be acked.
+ *
*/
enum ieee80211_hw_flags {
IEEE80211_HW_HAS_RATE_CONTROL = 1<<0,
@@ -1281,6 +1401,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_TX_AMPDU_SETUP_IN_HW = 1<<23,
IEEE80211_HW_SCAN_WHILE_IDLE = 1<<24,
IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF = 1<<25,
+ IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL = 1<<26,
};
/**
@@ -1325,6 +1446,8 @@ enum ieee80211_hw_flags {
* within &struct ieee80211_vif.
* @sta_data_size: size (in bytes) of the drv_priv data area
* within &struct ieee80211_sta.
+ * @chanctx_data_size: size (in bytes) of the drv_priv data area
+ * within &struct ieee80211_chanctx_conf.
*
* @max_rates: maximum number of alternate rate retry stages the hw
* can handle.
@@ -1355,6 +1478,10 @@ enum ieee80211_hw_flags {
* include _FMT. Use %IEEE80211_RADIOTAP_MCS_HAVE_* values, only
* adding _BW is supported today.
*
+ * @radiotap_vht_details: lists which VHT MCS information the HW reports,
+ * the default is _GI | _BANDWIDTH.
+ * Use the %IEEE80211_RADIOTAP_VHT_KNOWN_* values.
+ *
* @netdev_features: netdev features to be set in each netdev created
* from this HW. Note only HW checksum features are currently
* compatible with mac80211. Other feature bits will be rejected.
@@ -1369,6 +1496,7 @@ struct ieee80211_hw {
int channel_change_time;
int vif_data_size;
int sta_data_size;
+ int chanctx_data_size;
int napi_weight;
u16 queues;
u16 max_listen_interval;
@@ -1380,6 +1508,7 @@ struct ieee80211_hw {
u8 max_tx_aggregation_subframes;
u8 offchannel_tx_hw_queue;
u8 radiotap_mcs_details;
+ u16 radiotap_vht_details;
netdev_features_t netdev_features;
};
@@ -2126,6 +2255,14 @@ enum ieee80211_rate_control_changed {
* @sta_remove: Notifies low level driver about removal of an associated
* station, AP, IBSS/WDS/mesh peer etc. This callback can sleep.
*
+ * @sta_add_debugfs: Drivers can use this callback to add debugfs files
+ * when a station is added to mac80211's station list. This callback
+ * and @sta_remove_debugfs should be within a CONFIG_MAC80211_DEBUGFS
+ * conditional. This callback can sleep.
+ *
+ * @sta_remove_debugfs: Remove the debugfs files which were added using
+ * @sta_add_debugfs. This callback can sleep.
+ *
* @sta_notify: Notifies low level driver about power state transition of an
* associated station, AP, IBSS/WDS/mesh peer etc. For a VIF operating
* in AP mode, this callback will not be called when the flag
@@ -2317,6 +2454,27 @@ enum ieee80211_rate_control_changed {
* The callback will be called before each transmission and upon return
* mac80211 will transmit the frame right away.
* The callback is optional and can (should!) sleep.
+ *
+ * @add_chanctx: Notifies device driver about new channel context creation.
+ * @remove_chanctx: Notifies device driver about channel context destruction.
+ * @change_chanctx: Notifies device driver about channel context changes that
+ * may happen when combining different virtual interfaces on the same
+ * channel context with different settings
+ * @assign_vif_chanctx: Notifies device driver about channel context being bound
+ * to vif. Possible use is for hw queue remapping.
+ * @unassign_vif_chanctx: Notifies device driver about channel context being
+ * unbound from vif.
+ * @start_ap: Start operation on the AP interface, this is called after all the
+ * information in bss_conf is set and beacon can be retrieved. A channel
+ * context is bound before this is called. Note that if the driver uses
+ * software scan or ROC, this (and @stop_ap) isn't called when the AP is
+ * just "paused" for scanning/ROC, which is indicated by the beacon being
+ * disabled/enabled via @bss_info_changed.
+ * @stop_ap: Stop operation on the AP interface.
+ *
+ * @restart_complete: Called after a call to ieee80211_restart_hw(), when the
+ * reconfiguration has completed. This can help the driver implement the
+ * reconfiguration step. This callback may sleep.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -2342,6 +2500,9 @@ struct ieee80211_ops {
struct ieee80211_bss_conf *info,
u32 changed);
+ int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+ void (*stop_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+
u64 (*prepare_multicast)(struct ieee80211_hw *hw,
struct netdev_hw_addr_list *mc_list);
void (*configure_filter)(struct ieee80211_hw *hw,
@@ -2383,6 +2544,16 @@ struct ieee80211_ops {
struct ieee80211_sta *sta);
int (*sta_remove)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
+#ifdef CONFIG_MAC80211_DEBUGFS
+ void (*sta_add_debugfs)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir);
+ void (*sta_remove_debugfs)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ struct dentry *dir);
+#endif
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta);
int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
@@ -2424,8 +2595,8 @@ struct ieee80211_ops {
int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
int (*remain_on_channel)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
struct ieee80211_channel *chan,
- enum nl80211_channel_type channel_type,
int duration);
int (*cancel_remain_on_channel)(struct ieee80211_hw *hw);
int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
@@ -2461,6 +2632,22 @@ struct ieee80211_ops {
void (*mgd_prepare_tx)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
+
+ int (*add_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+ void (*remove_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx);
+ void (*change_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *ctx,
+ u32 changed);
+ int (*assign_vif_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx);
+ void (*unassign_vif_chanctx)(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_chanctx_conf *ctx);
+
+ void (*restart_complete)(struct ieee80211_hw *hw);
};
/**
@@ -2962,8 +3149,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @ssid: SSID buffer
* @ssid_len: length of SSID
- * @ie: buffer containing all IEs except SSID for the template
- * @ie_len: length of the IE buffer
+ * @tailroom: tailroom to reserve at end of SKB for IEs
*
* Creates a Probe Request template which can, for example, be uploaded to
* hardware.
@@ -2971,7 +3157,7 @@ struct sk_buff *ieee80211_nullfunc_get(struct ieee80211_hw *hw,
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const u8 *ssid, size_t ssid_len,
- const u8 *ie, size_t ie_len);
+ size_t tailroom);
/**
* ieee80211_rts_get - RTS frame generation function
@@ -3145,6 +3331,19 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf,
struct sk_buff *skb, u8 *p2k);
/**
+ * ieee80211_aes_cmac_calculate_k1_k2 - calculate the AES-CMAC sub keys
+ *
+ * This function computes the two AES-CMAC sub-keys, based on the
+ * previously installed master key.
+ *
+ * @keyconf: the parameter passed with the set key
+ * @k1: a buffer to be filled with the 1st sub-key
+ * @k2: a buffer to be filled with the 2nd sub-key
+ */
+void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf,
+ u8 *k1, u8 *k2);
+
+/**
* struct ieee80211_key_seq - key sequence counter
*
* @tkip: TKIP data, containing IV32 and IV16 in host byte order
@@ -3294,6 +3493,21 @@ void ieee80211_sched_scan_results(struct ieee80211_hw *hw);
void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
/**
+ * enum ieee80211_interface_iteration_flags - interface iteration flags
+ * @IEEE80211_IFACE_ITER_NORMAL: Iterate over all interfaces that have
+ * been added to the driver; However, note that during hardware
+ * reconfiguration (after restart_hw) it will iterate over a new
+ * interface and over all the existing interfaces even if they
+ * haven't been re-added to the driver yet.
+ * @IEEE80211_IFACE_ITER_RESUME_ALL: During resume, iterate over all
+ * interfaces, even if they haven't been re-added to the driver yet.
+ */
+enum ieee80211_interface_iteration_flags {
+ IEEE80211_IFACE_ITER_NORMAL = 0,
+ IEEE80211_IFACE_ITER_RESUME_ALL = BIT(0),
+};
+
+/**
* ieee80211_iterate_active_interfaces - iterate active interfaces
*
* This function iterates over the interfaces associated with a given
@@ -3301,13 +3515,15 @@ void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw);
* This function allows the iterator function to sleep, when the iterator
* function is atomic @ieee80211_iterate_active_interfaces_atomic can
* be used.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
*
* @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
* @iterator: the iterator function to call
* @data: first argument of the iterator function
*/
void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
+ u32 iter_flags,
void (*iterator)(void *data, u8 *mac,
struct ieee80211_vif *vif),
void *data);
@@ -3319,13 +3535,15 @@ void ieee80211_iterate_active_interfaces(struct ieee80211_hw *hw,
* hardware that are currently active and calls the callback for them.
* This function requires the iterator callback function to be atomic,
* if that is not desired, use @ieee80211_iterate_active_interfaces instead.
- * Does not iterate over a new interface during add_interface()
+ * Does not iterate over a new interface during add_interface().
*
* @hw: the hardware struct of which the interfaces should be iterated over
+ * @iter_flags: iteration flags, see &enum ieee80211_interface_iteration_flags
* @iterator: the iterator function to call, cannot sleep
* @data: first argument of the iterator function
*/
void ieee80211_iterate_active_interfaces_atomic(struct ieee80211_hw *hw,
+ u32 iter_flags,
void (*iterator)(void *data,
u8 *mac,
struct ieee80211_vif *vif),
@@ -3524,6 +3742,27 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw,
void *iter_data);
/**
+ * ieee80211_iter_chan_contexts_atomic - iterate channel contexts
+ * @hw: pointre obtained from ieee80211_alloc_hw().
+ * @iter: iterator function
+ * @iter_data: data passed to iterator function
+ *
+ * Iterate all active channel contexts. This function is atomic and
+ * doesn't acquire any locks internally that might be held in other
+ * places while calling into the driver.
+ *
+ * The iterator will not find a context that's being added (during
+ * the driver callback to add it) but will find it while it's being
+ * removed.
+ */
+void ieee80211_iter_chan_contexts_atomic(
+ struct ieee80211_hw *hw,
+ void (*iter)(struct ieee80211_hw *hw,
+ struct ieee80211_chanctx_conf *chanctx_conf,
+ void *data),
+ void *iter_data);
+
+/**
* ieee80211_ap_probereq_get - retrieve a Probe Request template
* @hw: pointer obtained from ieee80211_alloc_hw().
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 980d263765c..7af1ea89303 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -190,21 +190,6 @@ extern void ndisc_send_redirect(struct sk_buff *skb,
extern int ndisc_mc_map(const struct in6_addr *addr, char *buf,
struct net_device *dev, int dir);
-extern struct sk_buff *ndisc_build_skb(struct net_device *dev,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h,
- const struct in6_addr *target,
- int llinfo);
-
-extern void ndisc_send_skb(struct sk_buff *skb,
- struct net_device *dev,
- struct neighbour *neigh,
- const struct in6_addr *daddr,
- const struct in6_addr *saddr,
- struct icmp6hdr *icmp6h);
-
-
/*
* IGMP
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 95e64664118..c5a43f56b79 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -23,6 +23,7 @@
#endif
#include <net/netns/xfrm.h>
+struct user_namespace;
struct proc_dir_entry;
struct net_device;
struct sock;
@@ -53,6 +54,8 @@ struct net {
struct list_head cleanup_list; /* namespaces on death row */
struct list_head exit_list; /* Use only net_mutex */
+ struct user_namespace *user_ns; /* Owning user namespace */
+
struct proc_dir_entry *proc_net;
struct proc_dir_entry *proc_net_stat;
@@ -126,16 +129,21 @@ struct net {
/* Init's network namespace */
extern struct net init_net;
-#ifdef CONFIG_NET
-extern struct net *copy_net_ns(unsigned long flags, struct net *net_ns);
-
-#else /* CONFIG_NET */
-static inline struct net *copy_net_ns(unsigned long flags, struct net *net_ns)
+#ifdef CONFIG_NET_NS
+extern struct net *copy_net_ns(unsigned long flags,
+ struct user_namespace *user_ns, struct net *old_net);
+
+#else /* CONFIG_NET_NS */
+#include <linux/sched.h>
+#include <linux/nsproxy.h>
+static inline struct net *copy_net_ns(unsigned long flags,
+ struct user_namespace *user_ns, struct net *old_net)
{
- /* There is nothing to copy so this is a noop */
- return net_ns;
+ if (flags & CLONE_NEWNET)
+ return ERR_PTR(-EINVAL);
+ return old_net;
}
-#endif /* CONFIG_NET */
+#endif /* CONFIG_NET_NS */
extern struct list_head net_namespace_list;
diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index f1494feba79..caca0c4d6b4 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -182,7 +182,7 @@ __nf_conntrack_find(struct net *net, u16 zone,
extern int nf_conntrack_hash_check_insert(struct nf_conn *ct);
extern void nf_ct_delete_from_lists(struct nf_conn *ct);
-extern void nf_ct_insert_dying_list(struct nf_conn *ct);
+extern void nf_ct_dying_timeout(struct nf_conn *ct);
extern void nf_conntrack_flush_report(struct net *net, u32 pid, int report);
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index bd8eea720f2..ad14a799fd2 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -68,4 +68,19 @@ static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
#endif
}
+static inline bool nf_nat_oif_changed(unsigned int hooknum,
+ enum ip_conntrack_info ctinfo,
+ struct nf_conn_nat *nat,
+ const struct net_device *out)
+{
+#if IS_ENABLED(CONFIG_IP_NF_TARGET_MASQUERADE) || \
+ IS_ENABLED(CONFIG_IP6_NF_TARGET_MASQUERADE)
+ return nat->masq_index && hooknum == NF_INET_POST_ROUTING &&
+ CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL &&
+ nat->masq_index != out->ifindex;
+#else
+ return false;
+#endif
+}
+
#endif
diff --git a/include/net/netfilter/nf_queue.h b/include/net/netfilter/nf_queue.h
index 252fd1010b7..fb1c0be38b6 100644
--- a/include/net/netfilter/nf_queue.h
+++ b/include/net/netfilter/nf_queue.h
@@ -21,14 +21,10 @@ struct nf_queue_entry {
struct nf_queue_handler {
int (*outfn)(struct nf_queue_entry *entry,
unsigned int queuenum);
- char *name;
};
-extern int nf_register_queue_handler(u_int8_t pf,
- const struct nf_queue_handler *qh);
-extern int nf_unregister_queue_handler(u_int8_t pf,
- const struct nf_queue_handler *qh);
-extern void nf_unregister_queue_handlers(const struct nf_queue_handler *qh);
+void nf_register_queue_handler(const struct nf_queue_handler *qh);
+void nf_unregister_queue_handler(void);
extern void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
#endif /* _NF_QUEUE_H */
diff --git a/include/net/netns/sctp.h b/include/net/netns/sctp.h
index 5e5eb1f9f14..3573a81815a 100644
--- a/include/net/netns/sctp.h
+++ b/include/net/netns/sctp.h
@@ -62,6 +62,9 @@ struct netns_sctp {
/* Whether Cookie Preservative is enabled(1) or not(0) */
int cookie_preserve_enable;
+ /* The namespace default hmac alg */
+ char *sctp_hmac_alg;
+
/* Valid.Cookie.Life - 60 seconds */
unsigned int valid_cookie_life;
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index e900072950c..671953e1157 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -24,6 +24,12 @@
#include <net/nfc/nfc.h>
+struct nfc_phy_ops {
+ int (*write)(void *dev_id, struct sk_buff *skb);
+ int (*enable)(void *dev_id);
+ void (*disable)(void *dev_id);
+};
+
struct nfc_hci_dev;
struct nfc_hci_ops {
@@ -38,15 +44,21 @@ struct nfc_hci_ops {
int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb);
int (*start_poll) (struct nfc_hci_dev *hdev,
u32 im_protocols, u32 tm_protocols);
+ int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target,
+ u8 comm_mode, u8 *gb, size_t gb_len);
+ int (*dep_link_down)(struct nfc_hci_dev *hdev);
int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target);
int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate,
struct nfc_target *target);
- int (*data_exchange) (struct nfc_hci_dev *hdev,
+ int (*im_transceive) (struct nfc_hci_dev *hdev,
struct nfc_target *target, struct sk_buff *skb,
data_exchange_cb_t cb, void *cb_context);
+ int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb);
int (*check_presence)(struct nfc_hci_dev *hdev,
struct nfc_target *target);
+ void (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event,
+ struct sk_buff *skb);
};
/* Pipes */
@@ -114,6 +126,9 @@ struct nfc_hci_dev {
int async_cb_type;
data_exchange_cb_t async_cb;
void *async_cb_context;
+
+ u8 *gb;
+ size_t gb_len;
};
/* hci device allocation */
@@ -134,6 +149,8 @@ void *nfc_hci_get_clientdata(struct nfc_hci_dev *hdev);
void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err);
+int nfc_hci_result_to_errno(u8 result);
+
/* Host IDs */
#define NFC_HCI_HOST_CONTROLLER_ID 0x00
#define NFC_HCI_TERMINAL_HOST_ID 0x01
@@ -219,5 +236,7 @@ int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response,
const u8 *param, size_t param_len);
int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event,
const u8 *param, size_t param_len);
+int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate);
+u32 nfc_hci_sak_to_protocol(u8 sak);
#endif /* __NET_HCI_H */
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index f05b10682c9..fce80b2f9be 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -95,7 +95,7 @@ struct nfc_genl_data {
};
struct nfc_dev {
- unsigned int idx;
+ int idx;
u32 target_next_idx;
struct nfc_target *targets;
int n_targets;
diff --git a/include/net/protocol.h b/include/net/protocol.h
index 929528c73fe..047c0476c0a 100644
--- a/include/net/protocol.h
+++ b/include/net/protocol.h
@@ -25,9 +25,11 @@
#define _PROTOCOL_H
#include <linux/in6.h>
+#include <linux/skbuff.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <linux/ipv6.h>
#endif
+#include <linux/netdevice.h>
/* This is one larger than the largest protocol value that can be
* found in an ipv4 or ipv6 header. Since in both cases the protocol
@@ -40,12 +42,6 @@ struct net_protocol {
void (*early_demux)(struct sk_buff *skb);
int (*handler)(struct sk_buff *skb);
void (*err_handler)(struct sk_buff *skb, u32 info);
- int (*gso_send_check)(struct sk_buff *skb);
- struct sk_buff *(*gso_segment)(struct sk_buff *skb,
- netdev_features_t features);
- struct sk_buff **(*gro_receive)(struct sk_buff **head,
- struct sk_buff *skb);
- int (*gro_complete)(struct sk_buff *skb);
unsigned int no_policy:1,
netns_ok:1;
};
@@ -60,23 +56,20 @@ struct inet6_protocol {
struct inet6_skb_parm *opt,
u8 type, u8 code, int offset,
__be32 info);
-
- int (*gso_send_check)(struct sk_buff *skb);
- struct sk_buff *(*gso_segment)(struct sk_buff *skb,
- netdev_features_t features);
- struct sk_buff **(*gro_receive)(struct sk_buff **head,
- struct sk_buff *skb);
- int (*gro_complete)(struct sk_buff *skb);
-
unsigned int flags; /* INET6_PROTO_xxx */
};
#define INET6_PROTO_NOPOLICY 0x1
#define INET6_PROTO_FINAL 0x2
-/* This should be set for any extension header which is compatible with GSO. */
-#define INET6_PROTO_GSO_EXTHDR 0x4
#endif
+struct net_offload {
+ struct offload_callbacks callbacks;
+ unsigned int flags; /* Flags used by IPv6 for now */
+};
+/* This should be set for any extension header which is compatible with GSO. */
+#define INET6_PROTO_GSO_EXTHDR 0x1
+
/* This is used to register socket interfaces for IP protocols. */
struct inet_protosw {
struct list_head list;
@@ -96,6 +89,8 @@ struct inet_protosw {
#define INET_PROTOSW_ICSK 0x04 /* Is this an inet_connection_sock? */
extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet_offloads[MAX_INET_PROTOS];
+extern const struct net_offload __rcu *inet6_offloads[MAX_INET_PROTOS];
#if IS_ENABLED(CONFIG_IPV6)
extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
@@ -103,6 +98,8 @@ extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS];
extern int inet_add_protocol(const struct net_protocol *prot, unsigned char num);
extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num);
+extern int inet_add_offload(const struct net_offload *prot, unsigned char num);
+extern int inet_del_offload(const struct net_offload *prot, unsigned char num);
extern void inet_register_protosw(struct inet_protosw *p);
extern void inet_unregister_protosw(struct inet_protosw *p);
@@ -112,5 +109,7 @@ extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char n
extern int inet6_register_protosw(struct inet_protosw *p);
extern void inet6_unregister_protosw(struct inet_protosw *p);
#endif
+extern int inet6_add_offload(const struct net_offload *prot, unsigned char num);
+extern int inet6_del_offload(const struct net_offload *prot, unsigned char num);
#endif /* _PROTOCOL_H */
diff --git a/include/net/request_sock.h b/include/net/request_sock.h
index b01d8dd9ee7..a51dbd17c2d 100644
--- a/include/net/request_sock.h
+++ b/include/net/request_sock.h
@@ -49,13 +49,16 @@ struct request_sock_ops {
struct request_sock *req);
};
+extern int inet_rtx_syn_ack(struct sock *parent, struct request_sock *req);
+
/* struct request_sock - mini sock to represent a connection request
*/
struct request_sock {
struct request_sock *dl_next; /* Must be first member! */
u16 mss;
- u8 retrans;
- u8 cookie_ts; /* syncookie: encode tcpopts in timestamp */
+ u8 num_retrans; /* number of retransmits */
+ u8 cookie_ts:1; /* syncookie: encode tcpopts in timestamp */
+ u8 num_timeout:7; /* number of timeouts */
/* The following two fields can be easily recomputed I think -AK */
u32 window_clamp; /* window clamp at creation time */
u32 rcv_wnd; /* rcv_wnd offered first time */
@@ -231,7 +234,7 @@ static inline int reqsk_queue_removed(struct request_sock_queue *queue,
{
struct listen_sock *lopt = queue->listen_opt;
- if (req->retrans == 0)
+ if (req->num_timeout == 0)
--lopt->qlen_young;
return --lopt->qlen;
@@ -269,7 +272,8 @@ static inline void reqsk_queue_hash_req(struct request_sock_queue *queue,
struct listen_sock *lopt = queue->listen_opt;
req->expires = jiffies + timeout;
- req->retrans = 0;
+ req->num_retrans = 0;
+ req->num_timeout = 0;
req->sk = NULL;
req->dl_next = lopt->syn_table[hash];
diff --git a/include/net/route.h b/include/net/route.h
index bc40b633a5c..2ea40c1b5e0 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -198,10 +198,13 @@ struct in_ifaddr;
extern void fib_add_ifaddr(struct in_ifaddr *);
extern void fib_del_ifaddr(struct in_ifaddr *, struct in_ifaddr *);
-static inline void ip_rt_put(struct rtable * rt)
+static inline void ip_rt_put(struct rtable *rt)
{
- if (rt)
- dst_release(&rt->dst);
+ /* dst_release() accepts a NULL parameter.
+ * We rely on dst being first structure in struct rtable
+ */
+ BUILD_BUG_ON(offsetof(struct rtable, dst) != 0);
+ dst_release(&rt->dst);
}
#define IPTOS_RT_MASK (IPTOS_TOS_MASK & ~3)
diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 6b00c4fc429..5a15fabd6a7 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -125,7 +125,7 @@ extern void rtnl_af_unregister(struct rtnl_af_ops *ops);
extern struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]);
-extern struct net_device *rtnl_create_link(struct net *src_net, struct net *net,
+extern struct net_device *rtnl_create_link(struct net *net,
char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]);
extern int rtnl_configure_link(struct net_device *dev,
const struct ifinfomsg *ifm);
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 4616f468d59..1540f9c2fcf 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -50,6 +50,13 @@ struct Qdisc {
#define TCQ_F_INGRESS 2
#define TCQ_F_CAN_BYPASS 4
#define TCQ_F_MQROOT 8
+#define TCQ_F_ONETXQUEUE 0x10 /* dequeue_skb() can assume all skbs are for
+ * q->dev_queue : It can test
+ * netif_xmit_frozen_or_stopped() before
+ * dequeueing next packet.
+ * Its true for MQ/MQPRIO slaves, or non
+ * multiqueue device.
+ */
#define TCQ_F_WARN_NONWC (1 << 16)
int padded;
const struct Qdisc_ops *ops;
diff --git a/include/net/sctp/command.h b/include/net/sctp/command.h
index 712b3bebeda..35247271e55 100644
--- a/include/net/sctp/command.h
+++ b/include/net/sctp/command.h
@@ -130,8 +130,6 @@ typedef union {
__be16 err;
sctp_state_t state;
sctp_event_timeout_t to;
- unsigned long zero;
- void *ptr;
struct sctp_chunk *chunk;
struct sctp_association *asoc;
struct sctp_transport *transport;
@@ -154,23 +152,15 @@ typedef union {
* which takes an __s32 and returns a sctp_arg_t containing the
* __s32. So, after foo = SCTP_I32(arg), foo.i32 == arg.
*/
-static inline sctp_arg_t SCTP_NULL(void)
-{
- sctp_arg_t retval; retval.ptr = NULL; return retval;
-}
-static inline sctp_arg_t SCTP_NOFORCE(void)
-{
- sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 0; return retval;
-}
-static inline sctp_arg_t SCTP_FORCE(void)
-{
- sctp_arg_t retval = {.zero = 0UL}; retval.i32 = 1; return retval;
-}
#define SCTP_ARG_CONSTRUCTOR(name, type, elt) \
static inline sctp_arg_t \
SCTP_## name (type arg) \
-{ sctp_arg_t retval = {.zero = 0UL}; retval.elt = arg; return retval; }
+{ sctp_arg_t retval;\
+ memset(&retval, 0, sizeof(sctp_arg_t));\
+ retval.elt = arg;\
+ return retval;\
+}
SCTP_ARG_CONSTRUCTOR(I32, __s32, i32)
SCTP_ARG_CONSTRUCTOR(U32, __u32, u32)
@@ -181,7 +171,6 @@ SCTP_ARG_CONSTRUCTOR(ERROR, int, error)
SCTP_ARG_CONSTRUCTOR(PERR, __be16, err) /* protocol error */
SCTP_ARG_CONSTRUCTOR(STATE, sctp_state_t, state)
SCTP_ARG_CONSTRUCTOR(TO, sctp_event_timeout_t, to)
-SCTP_ARG_CONSTRUCTOR(PTR, void *, ptr)
SCTP_ARG_CONSTRUCTOR(CHUNK, struct sctp_chunk *, chunk)
SCTP_ARG_CONSTRUCTOR(ASOC, struct sctp_association *, asoc)
SCTP_ARG_CONSTRUCTOR(TRANSPORT, struct sctp_transport *, transport)
@@ -192,6 +181,23 @@ SCTP_ARG_CONSTRUCTOR(PACKET, struct sctp_packet *, packet)
SCTP_ARG_CONSTRUCTOR(SACKH, sctp_sackhdr_t *, sackh)
SCTP_ARG_CONSTRUCTOR(DATAMSG, struct sctp_datamsg *, msg)
+static inline sctp_arg_t SCTP_FORCE(void)
+{
+ return SCTP_I32(1);
+}
+
+static inline sctp_arg_t SCTP_NOFORCE(void)
+{
+ return SCTP_I32(0);
+}
+
+static inline sctp_arg_t SCTP_NULL(void)
+{
+ sctp_arg_t retval;
+ memset(&retval, 0, sizeof(sctp_arg_t));
+ return retval;
+}
+
typedef struct {
sctp_arg_t obj;
sctp_verb_t verb;
diff --git a/include/net/sctp/constants.h b/include/net/sctp/constants.h
index d053d2e9987..c29707d654c 100644
--- a/include/net/sctp/constants.h
+++ b/include/net/sctp/constants.h
@@ -312,14 +312,6 @@ enum { SCTP_MAX_GABS = 16 };
* functions simpler to write.
*/
-#if defined (CONFIG_SCTP_HMAC_MD5)
-#define SCTP_COOKIE_HMAC_ALG "hmac(md5)"
-#elif defined (CONFIG_SCTP_HMAC_SHA1)
-#define SCTP_COOKIE_HMAC_ALG "hmac(sha1)"
-#else
-#define SCTP_COOKIE_HMAC_ALG NULL
-#endif
-
/* These return values describe the success or failure of a number of
* routines which form the lower interface to SCTP_outqueue.
*/
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 9c6414f553f..7fdf298a47e 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -272,6 +272,18 @@ struct sctp_mib {
unsigned long mibs[SCTP_MIB_MAX];
};
+/* helper function to track stats about max rto and related transport */
+static inline void sctp_max_rto(struct sctp_association *asoc,
+ struct sctp_transport *trans)
+{
+ if (asoc->stats.max_obs_rto < (__u64)trans->rto) {
+ asoc->stats.max_obs_rto = trans->rto;
+ memset(&asoc->stats.obs_rto_ipaddr, 0,
+ sizeof(struct sockaddr_storage));
+ memcpy(&asoc->stats.obs_rto_ipaddr, &trans->ipaddr,
+ trans->af_specific->sockaddr_len);
+ }
+}
/* Print debugging messages. */
#if SCTP_DEBUG
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index b5887e1677e..2a82d138470 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -234,6 +234,8 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *,
const struct sctp_chunk *,
struct sctp_paramhdr *);
+struct sctp_chunk *sctp_make_violation_max_retrans(const struct sctp_association *,
+ const struct sctp_chunk *);
struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *,
const struct sctp_transport *);
struct sctp_chunk *sctp_make_heartbeat_ack(const struct sctp_association *,
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 64158aa1bb5..fdeb85a970f 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -177,6 +177,7 @@ struct sctp_sock {
/* Access to HMAC transform. */
struct crypto_hash *hmac;
+ char *sctp_hmac_alg;
/* What is our base endpointer? */
struct sctp_endpoint *ep;
@@ -948,6 +949,8 @@ struct sctp_transport {
/* 64-bit random number sent with heartbeat. */
__u64 hb_nonce;
+
+ struct rcu_head rcu;
};
struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
@@ -1311,6 +1314,40 @@ struct sctp_inithdr_host {
__u32 initial_tsn;
};
+/* SCTP_GET_ASSOC_STATS counters */
+struct sctp_priv_assoc_stats {
+ /* Maximum observed rto in the association during subsequent
+ * observations. Value is set to 0 if no RTO measurement took place
+ * The transport where the max_rto was observed is returned in
+ * obs_rto_ipaddr
+ */
+ struct sockaddr_storage obs_rto_ipaddr;
+ __u64 max_obs_rto;
+ /* Total In and Out SACKs received and sent */
+ __u64 isacks;
+ __u64 osacks;
+ /* Total In and Out packets received and sent */
+ __u64 opackets;
+ __u64 ipackets;
+ /* Total retransmitted chunks */
+ __u64 rtxchunks;
+ /* TSN received > next expected */
+ __u64 outofseqtsns;
+ /* Duplicate Chunks received */
+ __u64 idupchunks;
+ /* Gap Ack Blocks received */
+ __u64 gapcnt;
+ /* Unordered data chunks sent and received */
+ __u64 ouodchunks;
+ __u64 iuodchunks;
+ /* Ordered data chunks sent and received */
+ __u64 oodchunks;
+ __u64 iodchunks;
+ /* Control chunks sent and received */
+ __u64 octrlchunks;
+ __u64 ictrlchunks;
+};
+
/* RFC2960
*
* 12. Recommended Transmission Control Block (TCB) Parameters
@@ -1829,6 +1866,8 @@ struct sctp_association {
__u8 need_ecne:1, /* Need to send an ECNE Chunk? */
temp:1; /* Is it a temporary association? */
+
+ struct sctp_priv_assoc_stats stats;
};
diff --git a/include/net/sctp/ulpqueue.h b/include/net/sctp/ulpqueue.h
index 2e5ee0d8458..ff1b8ba73ab 100644
--- a/include/net/sctp/ulpqueue.h
+++ b/include/net/sctp/ulpqueue.h
@@ -72,7 +72,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *, struct sctp_ulpevent *ev);
void sctp_ulpq_renege(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
/* Perform partial delivery. */
-void sctp_ulpq_partial_delivery(struct sctp_ulpq *, struct sctp_chunk *, gfp_t);
+void sctp_ulpq_partial_delivery(struct sctp_ulpq *, gfp_t);
/* Abort the partial delivery. */
void sctp_ulpq_abort_pd(struct sctp_ulpq *, gfp_t);
diff --git a/include/net/sctp/user.h b/include/net/sctp/user.h
index 1b02d7ad453..9a0ae091366 100644
--- a/include/net/sctp/user.h
+++ b/include/net/sctp/user.h
@@ -107,6 +107,7 @@ typedef __s32 sctp_assoc_t;
#define SCTP_GET_LOCAL_ADDRS 109 /* Get all local address. */
#define SCTP_SOCKOPT_CONNECTX 110 /* CONNECTX requests. */
#define SCTP_SOCKOPT_CONNECTX3 111 /* CONNECTX requests (updated) */
+#define SCTP_GET_ASSOC_STATS 112 /* Read only */
/*
* 5.2.1 SCTP Initiation Structure (SCTP_INIT)
@@ -719,6 +720,32 @@ struct sctp_getaddrs {
__u8 addrs[0]; /*output, variable size*/
};
+/* A socket user request obtained via SCTP_GET_ASSOC_STATS that retrieves
+ * association stats. All stats are counts except sas_maxrto and
+ * sas_obs_rto_ipaddr. maxrto is the max observed rto + transport since
+ * the last call. Will return 0 when RTO was not update since last call
+ */
+struct sctp_assoc_stats {
+ sctp_assoc_t sas_assoc_id; /* Input */
+ /* Transport of observed max RTO */
+ struct sockaddr_storage sas_obs_rto_ipaddr;
+ __u64 sas_maxrto; /* Maximum Observed RTO for period */
+ __u64 sas_isacks; /* SACKs received */
+ __u64 sas_osacks; /* SACKs sent */
+ __u64 sas_opackets; /* Packets sent */
+ __u64 sas_ipackets; /* Packets received */
+ __u64 sas_rtxchunks; /* Retransmitted Chunks */
+ __u64 sas_outofseqtsns;/* TSN received > next expected */
+ __u64 sas_idupchunks; /* Dups received (ordered+unordered) */
+ __u64 sas_gapcnt; /* Gap Acknowledgements Received */
+ __u64 sas_ouodchunks; /* Unordered data chunks sent */
+ __u64 sas_iuodchunks; /* Unordered data chunks received */
+ __u64 sas_oodchunks; /* Ordered data chunks sent */
+ __u64 sas_iodchunks; /* Ordered data chunks received */
+ __u64 sas_octrlchunks; /* Control chunks sent */
+ __u64 sas_ictrlchunks; /* Control chunks received */
+};
+
/* These are bit fields for msghdr->msg_flags. See section 5.1. */
/* On user space Linux, these live in <bits/socket.h> as an enum. */
enum sctp_msg_flags {
diff --git a/include/net/sock.h b/include/net/sock.h
index c945fba4f54..0a9a01a5b0d 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -126,12 +126,17 @@ struct sock;
struct proto;
struct net;
+typedef __u32 __bitwise __portpair;
+typedef __u64 __bitwise __addrpair;
+
/**
* struct sock_common - minimal network layer representation of sockets
* @skc_daddr: Foreign IPv4 addr
* @skc_rcv_saddr: Bound local IPv4 addr
* @skc_hash: hash value used with various protocol lookup tables
* @skc_u16hashes: two u16 hash values used by UDP lookup tables
+ * @skc_dport: placeholder for inet_dport/tw_dport
+ * @skc_num: placeholder for inet_num/tw_num
* @skc_family: network address family
* @skc_state: Connection state
* @skc_reuse: %SO_REUSEADDR setting
@@ -149,16 +154,29 @@ struct net;
* for struct sock and struct inet_timewait_sock.
*/
struct sock_common {
- /* skc_daddr and skc_rcv_saddr must be grouped :
- * cf INET_MATCH() and INET_TW_MATCH()
+ /* skc_daddr and skc_rcv_saddr must be grouped on a 8 bytes aligned
+ * address on 64bit arches : cf INET_MATCH() and INET_TW_MATCH()
*/
- __be32 skc_daddr;
- __be32 skc_rcv_saddr;
-
+ union {
+ __addrpair skc_addrpair;
+ struct {
+ __be32 skc_daddr;
+ __be32 skc_rcv_saddr;
+ };
+ };
union {
unsigned int skc_hash;
__u16 skc_u16hashes[2];
};
+ /* skc_dport && skc_num must be grouped as well */
+ union {
+ __portpair skc_portpair;
+ struct {
+ __be16 skc_dport;
+ __u16 skc_num;
+ };
+ };
+
unsigned short skc_family;
volatile unsigned char skc_state;
unsigned char skc_reuse;
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 4af45e33105..aed42c78515 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -369,7 +369,6 @@ extern void tcp_shutdown (struct sock *sk, int how);
extern void tcp_v4_early_demux(struct sk_buff *skb);
extern int tcp_v4_rcv(struct sk_buff *skb);
-extern struct inet_peer *tcp_v4_get_peer(struct sock *sk);
extern int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
extern int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t size);