diff options
Diffstat (limited to 'include/net')
46 files changed, 1323 insertions, 329 deletions
| diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 9e63e76b20e7..df4ef9453384 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 b5f8988e4283..0a996a3517ed 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 6a76e0a0705e..42f21766c538 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 000000000000..7ea3db77ba89 --- /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 ede036977ae8..2554b3f5222a 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 76b2b6bdcf36..45eee08157bb 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 e7d454609881..014a2eaa5389 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 7ed8e356425a..7588ef44ebaf 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 7d5b6000378b..8e6a6b73b9c9 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 b6a6eeb3905f..2581638f4a3d 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 4fd8a4b4b7ee..e5062c955ea6 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 7f0df133d119..c3999632e616 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 54be0287eb98..67a8fa098e3a 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 256c1ed2d69a..a4196cbc84ec 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 ba52c830a7a5..7d658d577368 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 bc1b0fda2b04..652d3d309357 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 8a2a203eb15d..fdc48a94a063 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 5fa2af00634a..27d83183e615 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 ee75ccdf5188..68c69d54d392 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 ddc077c51f32..21947cf4fa46 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 979bf6c13141..5af66b26ebdd 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/irda/irlmp.h b/include/net/irda/irlmp.h index fff11b7fe8a4..591f78631f13 100644 --- a/include/net/irda/irlmp.h +++ b/include/net/irda/irlmp.h @@ -134,7 +134,7 @@ typedef struct {  } CACHE_ENTRY;  /* - *  Information about each registred IrLAP layer + *  Information about each registered IrLAP layer   */  struct lap_cb {  	irda_queue_t queue; /* Must be first */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 82558c8decf8..ee50c5eba50c 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 980d263765cf..7af1ea893038 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 95e646641184..de644bcd8613 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,10 @@ 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 */ + +	unsigned int		proc_inum; +  	struct proc_dir_entry 	*proc_net;  	struct proc_dir_entry 	*proc_net_stat; @@ -126,16 +131,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 f1494feba79f..caca0c4d6b4b 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 bd8eea720f2e..ad14a799fd2e 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 252fd1010b77..fb1c0be38b6d 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 5e5eb1f9f14b..3573a81815ad 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/netprio_cgroup.h b/include/net/netprio_cgroup.h index 2760f4f4ae9b..1d04b6f0fbd4 100644 --- a/include/net/netprio_cgroup.h +++ b/include/net/netprio_cgroup.h @@ -27,7 +27,6 @@ struct netprio_map {  struct cgroup_netprio_state {  	struct cgroup_subsys_state css; -	u32 prioidx;  };  extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task); @@ -36,13 +35,12 @@ extern void sock_update_netprioidx(struct sock *sk, struct task_struct *task);  static inline u32 task_netprioidx(struct task_struct *p)  { -	struct cgroup_netprio_state *state; +	struct cgroup_subsys_state *css;  	u32 idx;  	rcu_read_lock(); -	state = container_of(task_subsys_state(p, net_prio_subsys_id), -			     struct cgroup_netprio_state, css); -	idx = state->prioidx; +	css = task_subsys_state(p, net_prio_subsys_id); +	idx = css->cgroup->id;  	rcu_read_unlock();  	return idx;  } @@ -57,8 +55,7 @@ static inline u32 task_netprioidx(struct task_struct *p)  	rcu_read_lock();  	css = task_subsys_state(p, net_prio_subsys_id);  	if (css) -		idx = container_of(css, -				   struct cgroup_netprio_state, css)->prioidx; +		idx = css->cgroup->id;  	rcu_read_unlock();  	return idx;  } diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index e900072950cb..671953e11575 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 f05b10682c9d..fce80b2f9be7 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 929528c73fe8..047c0476c0a0 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 b01d8dd9ee7c..a51dbd17c2de 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 bc40b633a5c4..2ea40c1b5e00 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 6b00c4fc4291..5a15fabd6a75 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 4616f468d599..1540f9c2fcf4 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 712b3bebeda7..35247271e557 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 d053d2e99876..c29707d654c0 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 9c6414f553f9..7fdf298a47ef 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 b5887e1677e4..2a82d1384706 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 64158aa1bb5f..fdeb85a970fc 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 2e5ee0d8458d..ff1b8ba73ab1 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 1b02d7ad453b..9a0ae091366d 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 c945fba4f543..93a6745bfdb2 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; @@ -213,7 +231,7 @@ struct cg_proto;    *	@sk_sndbuf: size of send buffer in bytes    *	@sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE,    *		   %SO_OOBINLINE settings, %SO_TIMESTAMPING settings -  *	@sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets +  *	@sk_no_check: %SO_NO_CHECK setting, whether or not checkup packets    *	@sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)    *	@sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK)    *	@sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) diff --git a/include/net/tcp.h b/include/net/tcp.h index 4af45e33105d..aed42c785153 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); |