diff options
Diffstat (limited to 'include/net')
68 files changed, 1401 insertions, 398 deletions
| diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h index da84cf920b78..5ab4c9901ccc 100644 --- a/include/net/6lowpan.h +++ b/include/net/6lowpan.h @@ -141,6 +141,16 @@ struct lowpan_dev {  	u8 priv[0] __aligned(sizeof(void *));  }; +struct lowpan_802154_neigh { +	__le16 short_addr; +}; + +static inline +struct lowpan_802154_neigh *lowpan_802154_neigh(void *neigh_priv) +{ +	return neigh_priv; +} +  static inline  struct lowpan_dev *lowpan_dev(const struct net_device *dev)  { @@ -244,6 +254,12 @@ static inline bool lowpan_fetch_skb(struct sk_buff *skb, void *data,  	return false;  } +static inline bool lowpan_802154_is_valid_src_short_addr(__le16 addr) +{ +	/* First bit of addr is multicast, reserved or 802.15.4 specific */ +	return !(addr & cpu_to_le16(0x8000)); +} +  static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,  				       const size_t len)  { diff --git a/include/net/act_api.h b/include/net/act_api.h index 9a9a8edc138f..41e6a24a44b9 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -2,42 +2,14 @@  #define __NET_ACT_API_H  /* - * Public police action API for classifiers/qdiscs - */ + * Public action API for classifiers/qdiscs +*/  #include <net/sch_generic.h>  #include <net/pkt_sched.h>  #include <net/net_namespace.h>  #include <net/netns/generic.h> -struct tcf_common { -	struct hlist_node		tcfc_head; -	u32				tcfc_index; -	int				tcfc_refcnt; -	int				tcfc_bindcnt; -	u32				tcfc_capab; -	int				tcfc_action; -	struct tcf_t			tcfc_tm; -	struct gnet_stats_basic_packed	tcfc_bstats; -	struct gnet_stats_queue		tcfc_qstats; -	struct gnet_stats_rate_est64	tcfc_rate_est; -	spinlock_t			tcfc_lock; -	struct rcu_head			tcfc_rcu; -	struct gnet_stats_basic_cpu __percpu *cpu_bstats; -	struct gnet_stats_queue __percpu *cpu_qstats; -}; -#define tcf_head	common.tcfc_head -#define tcf_index	common.tcfc_index -#define tcf_refcnt	common.tcfc_refcnt -#define tcf_bindcnt	common.tcfc_bindcnt -#define tcf_capab	common.tcfc_capab -#define tcf_action	common.tcfc_action -#define tcf_tm		common.tcfc_tm -#define tcf_bstats	common.tcfc_bstats -#define tcf_qstats	common.tcfc_qstats -#define tcf_rate_est	common.tcfc_rate_est -#define tcf_lock	common.tcfc_lock -#define tcf_rcu		common.tcfc_rcu  struct tcf_hashinfo {  	struct hlist_head	*htab; @@ -46,6 +18,44 @@ struct tcf_hashinfo {  	u32			index;  }; +struct tc_action_ops; + +struct tc_action { +	const struct tc_action_ops	*ops; +	__u32				type; /* for backward compat(TCA_OLD_COMPAT) */ +	__u32				order; +	struct list_head		list; +	struct tcf_hashinfo		*hinfo; + +	struct hlist_node		tcfa_head; +	u32				tcfa_index; +	int				tcfa_refcnt; +	int				tcfa_bindcnt; +	u32				tcfa_capab; +	int				tcfa_action; +	struct tcf_t			tcfa_tm; +	struct gnet_stats_basic_packed	tcfa_bstats; +	struct gnet_stats_queue		tcfa_qstats; +	struct gnet_stats_rate_est64	tcfa_rate_est; +	spinlock_t			tcfa_lock; +	struct rcu_head			tcfa_rcu; +	struct gnet_stats_basic_cpu __percpu *cpu_bstats; +	struct gnet_stats_queue __percpu *cpu_qstats; +}; +#define tcf_act		common.tcfa_act +#define tcf_head	common.tcfa_head +#define tcf_index	common.tcfa_index +#define tcf_refcnt	common.tcfa_refcnt +#define tcf_bindcnt	common.tcfa_bindcnt +#define tcf_capab	common.tcfa_capab +#define tcf_action	common.tcfa_action +#define tcf_tm		common.tcfa_tm +#define tcf_bstats	common.tcfa_bstats +#define tcf_qstats	common.tcfa_qstats +#define tcf_rate_est	common.tcfa_rate_est +#define tcf_lock	common.tcfa_lock +#define tcf_rcu		common.tcfa_rcu +  static inline unsigned int tcf_hash(u32 index, unsigned int hmask)  {  	return index & hmask; @@ -76,16 +86,17 @@ static inline void tcf_lastuse_update(struct tcf_t *tm)  	if (tm->lastuse != now)  		tm->lastuse = now; +	if (unlikely(!tm->firstuse)) +		tm->firstuse = now;  } -struct tc_action { -	void			*priv; -	const struct tc_action_ops	*ops; -	__u32			type; /* for backward compat(TCA_OLD_COMPAT) */ -	__u32			order; -	struct list_head	list; -	struct tcf_hashinfo	*hinfo; -}; +static inline void tcf_tm_dump(struct tcf_t *dtm, const struct tcf_t *stm) +{ +	dtm->install = jiffies_to_clock_t(jiffies - stm->install); +	dtm->lastuse = jiffies_to_clock_t(jiffies - stm->lastuse); +	dtm->firstuse = jiffies_to_clock_t(jiffies - stm->firstuse); +	dtm->expires = jiffies_to_clock_t(stm->expires); +}  #ifdef CONFIG_NET_CLS_ACT @@ -96,16 +107,18 @@ struct tc_action_ops {  	struct list_head head;  	char    kind[IFNAMSIZ];  	__u32   type; /* TBD to match kind */ +	size_t	size;  	struct module		*owner; -	int     (*act)(struct sk_buff *, const struct tc_action *, struct tcf_result *); +	int     (*act)(struct sk_buff *, const struct tc_action *, +		       struct tcf_result *);  	int     (*dump)(struct sk_buff *, struct tc_action *, int, int);  	void	(*cleanup)(struct tc_action *, int bind); -	int     (*lookup)(struct net *, struct tc_action *, u32); +	int     (*lookup)(struct net *, struct tc_action **, u32);  	int     (*init)(struct net *net, struct nlattr *nla, -			struct nlattr *est, struct tc_action *act, int ovr, +			struct nlattr *est, struct tc_action **act, int ovr,  			int bind);  	int     (*walk)(struct net *, struct sk_buff *, -			struct netlink_callback *, int, struct tc_action *); +			struct netlink_callback *, int, const struct tc_action_ops *);  	void	(*stats_update)(struct tc_action *, u64, u32, u64);  }; @@ -115,8 +128,8 @@ struct tc_action_net {  };  static inline -int tc_action_net_init(struct tc_action_net *tn, const struct tc_action_ops *ops, -		       unsigned int mask) +int tc_action_net_init(struct tc_action_net *tn, +		       const struct tc_action_ops *ops, unsigned int mask)  {  	int err = 0; @@ -141,13 +154,14 @@ static inline void tc_action_net_exit(struct tc_action_net *tn)  int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,  		       struct netlink_callback *cb, int type, -		       struct tc_action *a); -int tcf_hash_search(struct tc_action_net *tn, struct tc_action *a, u32 index); +		       const struct tc_action_ops *ops); +int tcf_hash_search(struct tc_action_net *tn, struct tc_action **a, u32 index);  u32 tcf_hash_new_index(struct tc_action_net *tn); -int tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action *a, -		   int bind); +bool tcf_hash_check(struct tc_action_net *tn, u32 index, struct tc_action **a, +		    int bind);  int tcf_hash_create(struct tc_action_net *tn, u32 index, struct nlattr *est, -		    struct tc_action *a, int size, int bind, bool cpustats); +		    struct tc_action **a, const struct tc_action_ops *ops, int bind, +		    bool cpustats);  void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est);  void tcf_hash_insert(struct tc_action_net *tn, struct tc_action *a); @@ -159,7 +173,8 @@ static inline int tcf_hash_release(struct tc_action *a, bool bind)  }  int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops); -int tcf_unregister_action(struct tc_action_ops *a, struct pernet_operations *ops); +int tcf_unregister_action(struct tc_action_ops *a, +			  struct pernet_operations *ops);  int tcf_action_destroy(struct list_head *actions, int bind);  int tcf_action_exec(struct sk_buff *skb, const struct list_head *actions,  		    struct tcf_result *res); @@ -180,6 +195,9 @@ int tcf_action_copy_stats(struct sk_buff *, struct tc_action *, int);  #define tc_for_each_action(_a, _exts) \  	list_for_each_entry(a, &(_exts)->actions, list) +#define tc_single_action(_exts) \ +	(list_is_singular(&(_exts)->actions)) +  static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,  					   u64 packets, u64 lastuse)  { @@ -193,6 +211,7 @@ static inline void tcf_action_stats_update(struct tc_action *a, u64 bytes,  #define tc_no_actions(_exts) true  #define tc_for_each_action(_a, _exts) while ((void)(_a), 0) +#define tc_single_action(_exts) false  #define tcf_action_stats_update(a, bytes, packets, lastuse)  #endif /* CONFIG_NET_CLS_ACT */ diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 730d856683e5..9826d3a9464c 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -94,6 +94,16 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2,  void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr);  void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr); +void addrconf_add_linklocal(struct inet6_dev *idev, +			    const struct in6_addr *addr, u32 flags); + +int addrconf_prefix_rcv_add_addr(struct net *net, struct net_device *dev, +				 const struct prefix_info *pinfo, +				 struct inet6_dev *in6_dev, +				 const struct in6_addr *addr, int addr_type, +				 u32 addr_flags, bool sllao, bool tokenized, +				 __u32 valid_lft, u32 prefered_lft); +  static inline int addrconf_ifid_eui48(u8 *eui, struct net_device *dev)  {  	if (dev->addr_len != ETH_ALEN) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index eefcf3e96421..003b25283407 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -65,7 +65,7 @@  #define HCI_I2C		8  /* HCI controller types */ -#define HCI_BREDR	0x00 +#define HCI_PRIMARY	0x00  #define HCI_AMP		0x01  /* First BR/EDR Controller shall have ID = 0 */ @@ -445,6 +445,7 @@ enum {  /* ---- HCI Error Codes ---- */  #define HCI_ERROR_UNKNOWN_CONN_ID	0x02  #define HCI_ERROR_AUTH_FAILURE		0x05 +#define HCI_ERROR_PIN_OR_KEY_MISSING	0x06  #define HCI_ERROR_MEMORY_EXCEEDED	0x07  #define HCI_ERROR_CONNECTION_TIMEOUT	0x08  #define HCI_ERROR_REJ_LIMITED_RESOURCES	0x0d diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index dc71473462ac..ee7fc47680a1 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -372,6 +372,8 @@ struct hci_dev {  	atomic_t		promisc; +	const char		*hw_info; +	const char		*fw_info;  	struct dentry		*debugfs;  	struct device		dev; @@ -654,6 +656,7 @@ enum {  	HCI_CONN_PARAM_REMOVAL_PEND,  	HCI_CONN_NEW_LINK_KEY,  	HCI_CONN_SCANNING, +	HCI_CONN_AUTH_FAILURE,  };  static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) @@ -1021,6 +1024,10 @@ void hci_unregister_dev(struct hci_dev *hdev);  int hci_suspend_dev(struct hci_dev *hdev);  int hci_resume_dev(struct hci_dev *hdev);  int hci_reset_dev(struct hci_dev *hdev); +int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); +int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb); +void hci_set_hw_info(struct hci_dev *hdev, const char *fmt, ...); +void hci_set_fw_info(struct hci_dev *hdev, const char *fmt, ...);  int hci_dev_open(__u16 dev);  int hci_dev_close(__u16 dev);  int hci_dev_do_close(struct hci_dev *hdev); @@ -1097,9 +1104,6 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance);  void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); -int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); -int hci_recv_diag(struct hci_dev *hdev, struct sk_buff *skb); -  void hci_init_sysfs(struct hci_dev *hdev);  void hci_conn_init_sysfs(struct hci_conn *conn);  void hci_conn_add_sysfs(struct hci_conn *conn); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index ea73e0826aa7..7647964b1efa 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -645,6 +645,7 @@ struct mgmt_ev_device_connected {  #define MGMT_DEV_DISCONN_TIMEOUT	0x01  #define MGMT_DEV_DISCONN_LOCAL_HOST	0x02  #define MGMT_DEV_DISCONN_REMOTE		0x03 +#define MGMT_DEV_DISCONN_AUTH_FAILURE	0x04  #define MGMT_EV_DEVICE_DISCONNECTED	0x000C  struct mgmt_ev_device_disconnected { diff --git a/include/net/bonding.h b/include/net/bonding.h index 791800ddd6d9..6360c259da6d 100644 --- a/include/net/bonding.h +++ b/include/net/bonding.h @@ -34,6 +34,9 @@  #define BOND_DEFAULT_MIIMON	100 +#ifndef __long_aligned +#define __long_aligned __attribute__((aligned((sizeof(long))))) +#endif  /*   * Less bad way to call ioctl from within the kernel; this needs to be   * done some other way to get the call out of interrupt context. @@ -138,7 +141,9 @@ struct bond_params {  	struct reciprocal_value reciprocal_packets_per_slave;  	u16 ad_actor_sys_prio;  	u16 ad_user_port_key; -	u8 ad_actor_system[ETH_ALEN]; + +	/* 2 bytes of padding : see ether_addr_equal_64bits() */ +	u8 ad_actor_system[ETH_ALEN + 2];  };  struct bond_parm_tbl { diff --git a/include/net/calipso.h b/include/net/calipso.h new file mode 100644 index 000000000000..b1b30cd36601 --- /dev/null +++ b/include/net/calipso.h @@ -0,0 +1,91 @@ +/* + * CALIPSO - Common Architecture Label IPv6 Security Option + * + * This is an implementation of the CALIPSO protocol as specified in + * RFC 5570. + * + * Authors: Paul Moore <[email protected]> + *          Huw Davies <[email protected]> + * + */ + +/* + * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 + * (c) Copyright Huw Davies <[email protected]>, 2015 + * + * This program is free software;  you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY;  without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program;  if not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _CALIPSO_H +#define _CALIPSO_H + +#include <linux/types.h> +#include <linux/rcupdate.h> +#include <linux/list.h> +#include <linux/net.h> +#include <linux/skbuff.h> +#include <net/netlabel.h> +#include <net/request_sock.h> +#include <linux/atomic.h> +#include <asm/unaligned.h> + +/* known doi values */ +#define CALIPSO_DOI_UNKNOWN          0x00000000 + +/* doi mapping types */ +#define CALIPSO_MAP_UNKNOWN          0 +#define CALIPSO_MAP_PASS             2 + +/* + * CALIPSO DOI definitions + */ + +/* DOI definition struct */ +struct calipso_doi { +	u32 doi; +	u32 type; + +	atomic_t refcount; +	struct list_head list; +	struct rcu_head rcu; +}; + +/* + * Sysctl Variables + */ +extern int calipso_cache_enabled; +extern int calipso_cache_bucketsize; + +#ifdef CONFIG_NETLABEL +int __init calipso_init(void); +void calipso_exit(void); +bool calipso_validate(const struct sk_buff *skb, const unsigned char *option); +#else +static inline int __init calipso_init(void) +{ +	return 0; +} + +static inline void calipso_exit(void) +{ +} +static inline bool calipso_validate(const struct sk_buff *skb, +				    const unsigned char *option) +{ +	return true; +} +#endif /* CONFIG_NETLABEL */ + +#endif /* _CALIPSO_H */ diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 63921672bed0..9c23f4d33e06 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -330,6 +330,9 @@ struct ieee80211_supported_band {   * in a separate chapter.   */ +#define VHT_MUMIMO_GROUPS_DATA_LEN (WLAN_MEMBERSHIP_LEN +\ +				    WLAN_USER_POSITION_LEN) +  /**   * struct vif_params - describes virtual interface parameters   * @use_4addr: use 4-address frames @@ -339,10 +342,13 @@ struct ieee80211_supported_band {   *	This feature is only fully supported by drivers that enable the   *	%NL80211_FEATURE_MAC_ON_CREATE flag.  Others may support creating   **	only p2p devices with specified MAC. + * @vht_mumimo_groups: MU-MIMO groupID. used for monitoring only + *	 packets belonging to that MU-MIMO groupID.   */  struct vif_params { -       int use_4addr; -       u8 macaddr[ETH_ALEN]; +	int use_4addr; +	u8 macaddr[ETH_ALEN]; +	u8 vht_mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN];  };  /** @@ -774,6 +780,7 @@ enum station_parameters_apply_mask {   *	(bitmask of BIT(NL80211_STA_FLAG_...))   * @listen_interval: listen interval or -1 for no change   * @aid: AID or zero for no change + * @peer_aid: mesh peer AID or zero for no change   * @plink_action: plink action to take   * @plink_state: set the peer link state for a station   * @ht_capa: HT capabilities of station @@ -805,6 +812,7 @@ struct station_parameters {  	u32 sta_modify_mask;  	int listen_interval;  	u16 aid; +	u16 peer_aid;  	u8 supported_rates_len;  	u8 plink_action;  	u8 plink_state; @@ -1418,6 +1426,21 @@ struct cfg80211_ssid {  };  /** + * struct cfg80211_scan_info - information about completed scan + * @scan_start_tsf: scan start time in terms of the TSF of the BSS that the + *	wireless device that requested the scan is connected to. If this + *	information is not available, this field is left zero. + * @tsf_bssid: the BSSID according to which %scan_start_tsf is set. + * @aborted: set to true if the scan was aborted for any reason, + *	userspace will be notified of that + */ +struct cfg80211_scan_info { +	u64 scan_start_tsf; +	u8 tsf_bssid[ETH_ALEN] __aligned(2); +	bool aborted; +}; + +/**   * struct cfg80211_scan_request - scan request description   *   * @ssids: SSIDs to scan for (active scan only) @@ -1427,12 +1450,17 @@ struct cfg80211_ssid {   * @scan_width: channel width for scanning   * @ie: optional information element(s) to add into Probe Request or %NULL   * @ie_len: length of ie in octets + * @duration: how long to listen on each channel, in TUs. If + *	%duration_mandatory is not set, this is the maximum dwell time and + *	the actual dwell time may be shorter. + * @duration_mandatory: if set, the scan duration must be as specified by the + *	%duration field.   * @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 + * @info: (internal) information about completed scan   * @notified: (internal) scan request was notified as done or aborted   * @no_cck: used to send probe requests at non CCK rate in 2GHz band   * @mac_addr: MAC address used with randomisation @@ -1448,6 +1476,8 @@ struct cfg80211_scan_request {  	enum nl80211_bss_scan_width scan_width;  	const u8 *ie;  	size_t ie_len; +	u16 duration; +	bool duration_mandatory;  	u32 flags;  	u32 rates[NUM_NL80211_BANDS]; @@ -1461,7 +1491,8 @@ struct cfg80211_scan_request {  	/* internal */  	struct wiphy *wiphy;  	unsigned long scan_start; -	bool aborted, notified; +	struct cfg80211_scan_info info; +	bool notified;  	bool no_cck;  	/* keep last */ @@ -1594,12 +1625,19 @@ enum cfg80211_signal_type {   *	buffered on the device) and be accurate to about 10ms.   *	If the frame isn't buffered, just passing the return value of   *	ktime_get_boot_ns() is likely appropriate. + * @parent_tsf: the time at the start of reception of the first octet of the + *	timestamp field of the frame. The time is the TSF of the BSS specified + *	by %parent_bssid. + * @parent_bssid: the BSS according to which %parent_tsf is set. This is set to + *	the BSS that requested the scan in which the beacon/probe was received.   */  struct cfg80211_inform_bss {  	struct ieee80211_channel *chan;  	enum nl80211_bss_scan_width scan_width;  	s32 signal;  	u64 boottime_ns; +	u64 parent_tsf; +	u8 parent_bssid[ETH_ALEN] __aligned(2);  };  /** @@ -2367,19 +2405,23 @@ struct cfg80211_qos_map {   *	(invoked with the wireless_dev mutex held)   *   * @connect: Connect to the ESS with the specified parameters. When connected, - *	call cfg80211_connect_result() with status code %WLAN_STATUS_SUCCESS. - *	If the connection fails for some reason, call cfg80211_connect_result() - *	with the status from the AP. The driver is allowed to roam to other - *	BSSes within the ESS when the other BSS matches the connect parameters. - *	When such roaming is initiated by the driver, the driver is expected to - *	verify that the target matches the configured security parameters and - *	to use Reassociation Request frame instead of Association Request frame. - *	The connect function can also be used to request the driver to perform - *	a specific roam when connected to an ESS. In that case, the prev_bssid + *	call cfg80211_connect_result()/cfg80211_connect_bss() with status code + *	%WLAN_STATUS_SUCCESS. If the connection fails for some reason, call + *	cfg80211_connect_result()/cfg80211_connect_bss() with the status code + *	from the AP or cfg80211_connect_timeout() if no frame with status code + *	was received. + *	The driver is allowed to roam to other BSSes within the ESS when the + *	other BSS matches the connect parameters. When such roaming is initiated + *	by the driver, the driver is expected to verify that the target matches + *	the configured security parameters and to use Reassociation Request + *	frame instead of Association Request frame. + *	The connect function can also be used to request the driver to perform a + *	specific roam when connected to an ESS. In that case, the prev_bssid   *	parameter is set to the BSSID of the currently associated BSS as an - *	indication of requesting reassociation. In both the driver-initiated and - *	new connect() call initiated roaming cases, the result of roaming is - *	indicated with a call to cfg80211_roamed() or cfg80211_roamed_bss(). + *	indication of requesting reassociation. + *	In both the driver-initiated and new connect() call initiated roaming + *	cases, the result of roaming is indicated with a call to + *	cfg80211_roamed() or cfg80211_roamed_bss().   *	(invoked with the wireless_dev mutex held)   * @disconnect: Disconnect from the BSS/ESS.   *	(invoked with the wireless_dev mutex held) @@ -3080,6 +3122,24 @@ struct wiphy_vendor_command {  };  /** + * struct wiphy_iftype_ext_capab - extended capabilities per interface type + * @iftype: interface type + * @extended_capabilities: extended capabilities supported by the driver, + *	additional capabilities might be supported by userspace; these are the + *	802.11 extended capabilities ("Extended Capabilities element") and are + *	in the same format as in the information element. See IEEE Std + *	802.11-2012 8.4.2.29 for the defined fields. + * @extended_capabilities_mask: mask of the valid values + * @extended_capabilities_len: length of the extended capabilities + */ +struct wiphy_iftype_ext_capab { +	enum nl80211_iftype iftype; +	const u8 *extended_capabilities; +	const u8 *extended_capabilities_mask; +	u8 extended_capabilities_len; +}; + +/**   * struct wiphy - wireless hardware description   * @reg_notifier: the driver's regulatory notification callback,   *	note that if your driver uses wiphy_apply_custom_regulatory() @@ -3199,9 +3259,14 @@ struct wiphy_vendor_command {   *	additional capabilities might be supported by userspace; these are   *	the 802.11 extended capabilities ("Extended Capabilities element")   *	and are in the same format as in the information element. See - *	802.11-2012 8.4.2.29 for the defined fields. + *	802.11-2012 8.4.2.29 for the defined fields. These are the default + *	extended capabilities to be used if the capabilities are not specified + *	for a specific interface type in iftype_ext_capab.   * @extended_capabilities_mask: mask of the valid values   * @extended_capabilities_len: length of the extended capabilities + * @iftype_ext_capab: array of extended capabilities per interface type + * @num_iftype_ext_capab: number of interface types for which extended + *	capabilities are specified separately.   * @coalesce: packet coalescing support information   *   * @vendor_commands: array of vendor commands supported by the hardware @@ -3301,6 +3366,9 @@ struct wiphy {  	const u8 *extended_capabilities, *extended_capabilities_mask;  	u8 extended_capabilities_len; +	const struct wiphy_iftype_ext_capab *iftype_ext_capab; +	unsigned int num_iftype_ext_capab; +  	/* If multiple wiphys are registered and you're handed e.g.  	 * a regular netdev with assigned ieee80211_ptr, you won't  	 * know whether it points to a wiphy your driver has registered @@ -4031,10 +4099,10 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator);   * cfg80211_scan_done - notify that scan finished   *   * @request: the corresponding scan request - * @aborted: set to true if the scan was aborted for any reason, - *	userspace will be notified of that + * @info: information about the completed scan   */ -void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted); +void cfg80211_scan_done(struct cfg80211_scan_request *request, +			struct cfg80211_scan_info *info);  /**   * cfg80211_sched_scan_results - notify that new scan results are available @@ -4680,7 +4748,7 @@ static inline void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)  void cfg80211_connect_bss(struct net_device *dev, const u8 *bssid,  			  struct cfg80211_bss *bss, const u8 *req_ie,  			  size_t req_ie_len, const u8 *resp_ie, -			  size_t resp_ie_len, u16 status, gfp_t gfp); +			  size_t resp_ie_len, int status, gfp_t gfp);  /**   * cfg80211_connect_result - notify cfg80211 of connection result @@ -4710,6 +4778,29 @@ cfg80211_connect_result(struct net_device *dev, const u8 *bssid,  }  /** + * cfg80211_connect_timeout - notify cfg80211 of connection timeout + * + * @dev: network device + * @bssid: the BSSID of the AP + * @req_ie: association request IEs (maybe be %NULL) + * @req_ie_len: association request IEs length + * @gfp: allocation flags + * + * It should be called by the underlying driver whenever connect() has failed + * in a sequence where no explicit authentication/association rejection was + * received from the AP. This could happen, e.g., due to not being able to send + * out the Authentication or Association Request frame or timing out while + * waiting for the response. + */ +static inline void +cfg80211_connect_timeout(struct net_device *dev, const u8 *bssid, +			 const u8 *req_ie, size_t req_ie_len, gfp_t gfp) +{ +	cfg80211_connect_bss(dev, bssid, NULL, req_ie, req_ie_len, NULL, 0, -1, +			     gfp); +} + +/**   * cfg80211_roamed - notify cfg80211 of roaming   *   * @dev: network device diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 171cd76558fb..795ca4008f72 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -219,9 +219,22 @@ struct wpan_phy {  	struct device dev; +	/* the network namespace this phy lives in currently */ +	possible_net_t _net; +  	char priv[0] __aligned(NETDEV_ALIGN);  }; +static inline struct net *wpan_phy_net(struct wpan_phy *wpan_phy) +{ +	return read_pnet(&wpan_phy->_net); +} + +static inline void wpan_phy_net_set(struct wpan_phy *wpan_phy, struct net *net) +{ +	write_pnet(&wpan_phy->_net, net); +} +  struct ieee802154_addr {  	u8 mode;  	__le16 pan_id; diff --git a/include/net/codel_qdisc.h b/include/net/codel_qdisc.h index 8144d9cd2908..098630f83a55 100644 --- a/include/net/codel_qdisc.h +++ b/include/net/codel_qdisc.h @@ -52,6 +52,7 @@  /* Qdiscs using codel plugin must use codel_skb_cb in their own cb[] */  struct codel_skb_cb {  	codel_time_t enqueue_time; +	unsigned int mem_usage;  };  static struct codel_skb_cb *get_codel_cb(const struct sk_buff *skb) diff --git a/include/net/devlink.h b/include/net/devlink.h index 1d45b61cb320..c99ffe8cef3c 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -90,6 +90,9 @@ struct devlink_ops {  				       u16 tc_index,  				       enum devlink_sb_pool_type pool_type,  				       u32 *p_cur, u32 *p_max); + +	int (*eswitch_mode_get)(struct devlink *devlink, u16 *p_mode); +	int (*eswitch_mode_set)(struct devlink *devlink, u16 mode);  };  static inline void *devlink_priv(struct devlink *devlink) diff --git a/include/net/dsa.h b/include/net/dsa.h index 17c3d37b6779..2217a3f817f8 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -26,11 +26,14 @@ enum dsa_tag_protocol {  	DSA_TAG_PROTO_TRAILER,  	DSA_TAG_PROTO_EDSA,  	DSA_TAG_PROTO_BRCM, +	DSA_TAG_LAST,		/* MUST BE LAST */  };  #define DSA_MAX_SWITCHES	4  #define DSA_MAX_PORTS		12 +#define DSA_RTABLE_NONE		-1 +  struct dsa_chip_data {  	/*  	 * How to access the switch configuration registers. @@ -58,12 +61,11 @@ struct dsa_chip_data {  	struct device_node *port_dn[DSA_MAX_PORTS];  	/* -	 * An array (with nr_chips elements) of which element [a] -	 * indicates which port on this switch should be used to -	 * send packets to that are destined for switch a.  Can be -	 * NULL if there is only one switch chip. +	 * An array of which element [a] indicates which port on this +	 * switch should be used to send packets to that are destined +	 * for switch a. Can be NULL if there is only one switch chip.  	 */ -	s8		*rtable; +	s8		rtable[DSA_MAX_SWITCHES];  };  struct dsa_platform_data { @@ -85,6 +87,17 @@ struct dsa_platform_data {  struct packet_type;  struct dsa_switch_tree { +	struct list_head	list; + +	/* Tree identifier */ +	u32 tree; + +	/* Number of switches attached to this tree */ +	struct kref refcount; + +	/* Has this tree been applied to the hardware? */ +	bool applied; +  	/*  	 * Configuration data for the platform device that owns  	 * this dsa switch tree instance. @@ -100,12 +113,12 @@ struct dsa_switch_tree {  				       struct net_device *dev,  				       struct packet_type *pt,  				       struct net_device *orig_dev); -	enum dsa_tag_protocol	tag_protocol;  	/*  	 * Original copy of the master netdev ethtool_ops  	 */  	struct ethtool_ops	master_ethtool_ops; +	const struct ethtool_ops *master_orig_ethtool_ops;  	/*  	 * The switch and port to which the CPU is attached. @@ -117,6 +130,18 @@ struct dsa_switch_tree {  	 * Data for the individual switch chips.  	 */  	struct dsa_switch	*ds[DSA_MAX_SWITCHES]; + +	/* +	 * Tagging protocol operations for adding and removing an +	 * encapsulation tag. +	 */ +	const struct dsa_device_ops *tag_ops; +}; + +struct dsa_port { +	struct net_device	*netdev; +	struct device_node	*dn; +	unsigned int		ageing_time;  };  struct dsa_switch { @@ -144,6 +169,13 @@ struct dsa_switch {  	 */  	struct dsa_switch_driver	*drv; +	/* +	 * An array of which element [a] indicates which port on this +	 * switch should be used to send packets to that are destined +	 * for switch a. Can be NULL if there is only one switch chip. +	 */ +	s8		rtable[DSA_MAX_SWITCHES]; +  #ifdef CONFIG_NET_DSA_HWMON  	/*  	 * Hardware monitoring information @@ -153,13 +185,19 @@ struct dsa_switch {  #endif  	/* +	 * The lower device this switch uses to talk to the host +	 */ +	struct net_device *master_netdev; + +	/*  	 * Slave mii_bus and devices for the individual ports.  	 */  	u32			dsa_port_mask; +	u32			cpu_port_mask;  	u32			enabled_port_mask;  	u32			phys_mii_mask; +	struct dsa_port		ports[DSA_MAX_PORTS];  	struct mii_bus		*slave_mii_bus; -	struct net_device	*ports[DSA_MAX_PORTS];  };  static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) @@ -174,7 +212,7 @@ static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p)  static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p)  { -	return ds->enabled_port_mask & (1 << p) && ds->ports[p]; +	return ds->enabled_port_mask & (1 << p) && ds->ports[p].netdev;  }  static inline u8 dsa_upstream_port(struct dsa_switch *ds) @@ -190,7 +228,7 @@ static inline u8 dsa_upstream_port(struct dsa_switch *ds)  	if (dst->cpu_switch == ds->index)  		return dst->cpu_port;  	else -		return ds->cd->rtable[dst->cpu_switch]; +		return ds->rtable[dst->cpu_switch];  }  struct switchdev_trans; @@ -292,6 +330,7 @@ struct dsa_switch_driver {  	/*  	 * Bridge integration  	 */ +	int	(*set_ageing_time)(struct dsa_switch *ds, unsigned int msecs);  	int	(*port_bridge_join)(struct dsa_switch *ds, int port,  				    struct net_device *bridge);  	void	(*port_bridge_leave)(struct dsa_switch *ds, int port); @@ -344,4 +383,7 @@ static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst)  {  	return dst->rcv != NULL;  } + +void dsa_unregister_switch(struct dsa_switch *ds); +int dsa_register_switch(struct dsa_switch *ds, struct device_node *np);  #endif diff --git a/include/net/fib_rules.h b/include/net/fib_rules.h index 59160de702b6..456e4a6006ab 100644 --- a/include/net/fib_rules.h +++ b/include/net/fib_rules.h @@ -17,7 +17,8 @@ struct fib_rule {  	u32			flags;  	u32			table;  	u8			action; -	/* 3 bytes hole, try to use */ +	u8			l3mdev; +	/* 2 bytes hole, try to use */  	u32			target;  	__be64			tun_id;  	struct fib_rule __rcu	*ctarget; @@ -36,6 +37,7 @@ struct fib_lookup_arg {  	void			*lookup_ptr;  	void			*result;  	struct fib_rule		*rule; +	u32			table;  	int			flags;  #define FIB_LOOKUP_NOREF		1  #define FIB_LOOKUP_IGNORE_LINKSTATE	2 @@ -89,7 +91,8 @@ struct fib_rules_ops {  	[FRA_TABLE]     = { .type = NLA_U32 }, \  	[FRA_SUPPRESS_PREFIXLEN] = { .type = NLA_U32 }, \  	[FRA_SUPPRESS_IFGROUP] = { .type = NLA_U32 }, \ -	[FRA_GOTO]	= { .type = NLA_U32 } +	[FRA_GOTO]	= { .type = NLA_U32 }, \ +	[FRA_L3MDEV]	= { .type = NLA_U8 }  static inline void fib_rule_get(struct fib_rule *rule)  { @@ -102,6 +105,20 @@ static inline void fib_rule_put(struct fib_rule *rule)  		kfree_rcu(rule, rcu);  } +#ifdef CONFIG_NET_L3_MASTER_DEV +static inline u32 fib_rule_get_table(struct fib_rule *rule, +				     struct fib_lookup_arg *arg) +{ +	return rule->l3mdev ? arg->table : rule->table; +} +#else +static inline u32 fib_rule_get_table(struct fib_rule *rule, +				     struct fib_lookup_arg *arg) +{ +	return rule->table; +} +#endif +  static inline u32 frh_get_table(struct fib_rule_hdr *frh, struct nlattr **nla)  {  	if (nla[FRA_TABLE]) @@ -117,4 +134,7 @@ int fib_rules_lookup(struct fib_rules_ops *, struct flowi *, int flags,  		     struct fib_lookup_arg *);  int fib_default_rule_add(struct fib_rules_ops *, u32 pref, u32 table,  			 u32 flags); + +int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh); +int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh);  #endif diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index 610cd397890e..231e121cc7d9 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h @@ -33,10 +33,12 @@ int gnet_stats_start_copy_compat(struct sk_buff *skb, int type,  				 spinlock_t *lock, struct gnet_dump *d,  				 int padattr); -int gnet_stats_copy_basic(struct gnet_dump *d, +int gnet_stats_copy_basic(const seqcount_t *running, +			  struct gnet_dump *d,  			  struct gnet_stats_basic_cpu __percpu *cpu,  			  struct gnet_stats_basic_packed *b); -void __gnet_stats_copy_basic(struct gnet_stats_basic_packed *bstats, +void __gnet_stats_copy_basic(const seqcount_t *running, +			     struct gnet_stats_basic_packed *bstats,  			     struct gnet_stats_basic_cpu __percpu *cpu,  			     struct gnet_stats_basic_packed *b);  int gnet_stats_copy_rate_est(struct gnet_dump *d, @@ -52,13 +54,15 @@ int gnet_stats_finish_copy(struct gnet_dump *d);  int gen_new_estimator(struct gnet_stats_basic_packed *bstats,  		      struct gnet_stats_basic_cpu __percpu *cpu_bstats,  		      struct gnet_stats_rate_est64 *rate_est, -		      spinlock_t *stats_lock, struct nlattr *opt); +		      spinlock_t *stats_lock, +		      seqcount_t *running, struct nlattr *opt);  void gen_kill_estimator(struct gnet_stats_basic_packed *bstats,  			struct gnet_stats_rate_est64 *rate_est);  int gen_replace_estimator(struct gnet_stats_basic_packed *bstats,  			  struct gnet_stats_basic_cpu __percpu *cpu_bstats,  			  struct gnet_stats_rate_est64 *rate_est, -			  spinlock_t *stats_lock, struct nlattr *opt); +			  spinlock_t *stats_lock, +			  seqcount_t *running, struct nlattr *opt);  bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats,  			  const struct gnet_stats_rate_est64 *rate_est);  #endif diff --git a/include/net/geneve.h b/include/net/geneve.h index cb544a530146..ec0327d4331b 100644 --- a/include/net/geneve.h +++ b/include/net/geneve.h @@ -1,10 +1,7 @@  #ifndef __NET_GENEVE_H  #define __NET_GENEVE_H  1 -#ifdef CONFIG_INET  #include <net/udp_tunnel.h> -#endif -  /* Geneve Header:   *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -62,12 +59,6 @@ struct genevehdr {  	struct geneve_opt options[];  }; -static inline void geneve_get_rx_port(struct net_device *netdev) -{ -	ASSERT_RTNL(); -	call_netdevice_notifiers(NETDEV_OFFLOAD_PUSH_GENEVE, netdev); -} -  #ifdef CONFIG_INET  struct net_device *geneve_dev_create_fb(struct net *net, const char *name,  					u8 name_assign_type, u16 dst_port); diff --git a/include/net/gre.h b/include/net/gre.h index 5dce30a6abe3..7a54a31d1d4c 100644 --- a/include/net/gre.h +++ b/include/net/gre.h @@ -26,7 +26,7 @@ int gre_del_protocol(const struct gre_protocol *proto, u8 version);  struct net_device *gretap_fb_dev_create(struct net *net, const char *name,  				       u8 name_assign_type);  int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, -		     bool *csum_err, __be16 proto); +		     bool *csum_err, __be16 proto, int nhs);  static inline int gre_calc_hlen(__be16 o_flags)  { diff --git a/include/net/gro_cells.h b/include/net/gro_cells.h index cf6c74550baa..d15214d673b2 100644 --- a/include/net/gro_cells.h +++ b/include/net/gro_cells.h @@ -14,27 +14,26 @@ struct gro_cells {  	struct gro_cell __percpu	*cells;  }; -static inline void gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb) +static inline int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)  {  	struct gro_cell *cell;  	struct net_device *dev = skb->dev; -	if (!gcells->cells || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) { -		netif_rx(skb); -		return; -	} +	if (!gcells->cells || skb_cloned(skb) || !(dev->features & NETIF_F_GRO)) +		return netif_rx(skb);  	cell = this_cpu_ptr(gcells->cells);  	if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) {  		atomic_long_inc(&dev->rx_dropped);  		kfree_skb(skb); -		return; +		return NET_RX_DROP;  	}  	__skb_queue_tail(&cell->napi_skbs, skb);  	if (skb_queue_len(&cell->napi_skbs) == 1)  		napi_schedule(&cell->napi); +	return NET_RX_SUCCESS;  }  /* called under BH context */ diff --git a/include/net/gtp.h b/include/net/gtp.h index 894a37b87d63..6398891b99ba 100644 --- a/include/net/gtp.h +++ b/include/net/gtp.h @@ -1,5 +1,5 @@  #ifndef _GTP_H_ -#define _GTP_H +#define _GTP_H_  /* General GTP protocol related definitions. */ diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index 012b1f91f3ec..236a81034fef 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -97,7 +97,12 @@ struct inet_request_sock {  	u32                     ir_mark;  	union {  		struct ip_options_rcu	*opt; -		struct sk_buff		*pktopts; +#if IS_ENABLED(CONFIG_IPV6) +		struct { +			struct ipv6_txoptions	*ipv6_opt; +			struct sk_buff		*pktopts; +		}; +#endif  	};  }; diff --git a/include/net/ip.h b/include/net/ip.h index 37165fba3741..9742b92dc933 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -47,6 +47,7 @@ struct inet_skb_parm {  #define IPSKB_REROUTED		BIT(4)  #define IPSKB_DOREDIRECT	BIT(5)  #define IPSKB_FRAG_PMTU		BIT(6) +#define IPSKB_FRAG_SEGS		BIT(7)  	u16			frag_max_size;  }; @@ -313,10 +314,9 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,  	return min(dst->dev->mtu, IP_MAX_MTU);  } -static inline unsigned int ip_skb_dst_mtu(const struct sk_buff *skb) +static inline unsigned int ip_skb_dst_mtu(struct sock *sk, +					  const struct sk_buff *skb)  { -	struct sock *sk = skb->sk; -  	if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) {  		bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED; diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 54c779416eec..d97305d0e71f 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -18,6 +18,7 @@ struct route_info {  	__u8			prefix[0];	/* 0,8 or 16 */  }; +#include <net/addrconf.h>  #include <net/flow.h>  #include <net/ip6_fib.h>  #include <net/sock.h> @@ -76,6 +77,8 @@ static inline struct dst_entry *ip6_route_output(struct net *net,  struct dst_entry *ip6_route_lookup(struct net *net, struct flowi6 *fl6,  				   int flags); +struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, +			       int ifindex, struct flowi6 *fl6, int flags);  int ip6_route_init(void);  void ip6_route_cleanup(void); @@ -86,9 +89,23 @@ int ip6_route_add(struct fib6_config *cfg);  int ip6_ins_rt(struct rt6_info *);  int ip6_del_rt(struct rt6_info *); -int ip6_route_get_saddr(struct net *net, struct rt6_info *rt, -			const struct in6_addr *daddr, unsigned int prefs, -			struct in6_addr *saddr); +static inline int ip6_route_get_saddr(struct net *net, struct rt6_info *rt, +				      const struct in6_addr *daddr, +				      unsigned int prefs, +				      struct in6_addr *saddr) +{ +	struct inet6_dev *idev = +			rt ? ip6_dst_idev((struct dst_entry *)rt) : NULL; +	int err = 0; + +	if (rt && rt->rt6i_prefsrc.plen) +		*saddr = rt->rt6i_prefsrc.addr; +	else +		err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, +					 daddr, prefs, saddr); + +	return err; +}  struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr,  			    const struct in6_addr *saddr, int oif, int flags); diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h index dbf444428437..a5e7035fb93f 100644 --- a/include/net/ip_tunnels.h +++ b/include/net/ip_tunnels.h @@ -132,6 +132,7 @@ struct ip_tunnel {  	int			ip_tnl_net_id;  	struct gro_cells	gro_cells;  	bool			collect_md; +	bool			ignore_df;  };  #define TUNNEL_CSUM		__cpu_to_be16(0x01) @@ -156,6 +157,7 @@ struct tnl_ptk_info {  	__be16 proto;  	__be32 key;  	__be32 seq; +	int hdr_len;  };  #define PACKET_RCVD	0 diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 11a045281948..8fed1cd78658 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -313,11 +313,19 @@ struct ipv6_txoptions *ipv6_renew_options(struct sock *sk,  					  int newtype,  					  struct ipv6_opt_hdr __user *newopt,  					  int newoptlen); +struct ipv6_txoptions * +ipv6_renew_options_kern(struct sock *sk, +			struct ipv6_txoptions *opt, +			int newtype, +			struct ipv6_opt_hdr *newopt, +			int newoptlen);  struct ipv6_txoptions *ipv6_fixup_options(struct ipv6_txoptions *opt_space,  					  struct ipv6_txoptions *opt);  bool ipv6_opt_accepted(const struct sock *sk, const struct sk_buff *skb,  		       const struct inet6_skb_parm *opt); +struct ipv6_txoptions *ipv6_update_options(struct sock *sk, +					   struct ipv6_txoptions *opt);  static inline bool ipv6_accept_ra(struct inet6_dev *idev)  { @@ -943,7 +951,7 @@ enum {  int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset, int target,  		  unsigned short *fragoff, int *fragflg); -int ipv6_find_tlv(struct sk_buff *skb, int offset, int type); +int ipv6_find_tlv(const struct sk_buff *skb, int offset, int type);  struct in6_addr *fl6_update_dst(struct flowi6 *fl6,  				const struct ipv6_txoptions *opt, diff --git a/include/net/l3mdev.h b/include/net/l3mdev.h index 374388dc01c8..e90095091aa0 100644 --- a/include/net/l3mdev.h +++ b/include/net/l3mdev.h @@ -11,6 +11,8 @@  #ifndef _NET_L3MDEV_H_  #define _NET_L3MDEV_H_ +#include <net/fib_rules.h> +  /**   * struct l3mdev_ops - l3mdev operations   * @@ -36,11 +38,17 @@ struct l3mdev_ops {  	/* IPv6 ops */  	struct dst_entry * (*l3mdev_get_rt6_dst)(const struct net_device *dev, -						 const struct flowi6 *fl6); +						 struct flowi6 *fl6); +	int		   (*l3mdev_get_saddr6)(struct net_device *dev, +						const struct sock *sk, +						struct flowi6 *fl6);  };  #ifdef CONFIG_NET_L3_MASTER_DEV +int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, +			  struct fib_lookup_arg *arg); +  int l3mdev_master_ifindex_rcu(const struct net_device *dev);  static inline int l3mdev_master_ifindex(struct net_device *dev)  { @@ -71,6 +79,31 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)  	return rc;  } +static inline +const struct net_device *l3mdev_master_dev_rcu(const struct net_device *_dev) +{ +	/* netdev_master_upper_dev_get_rcu calls +	 * list_first_or_null_rcu to walk the upper dev list. +	 * list_first_or_null_rcu does not handle a const arg. We aren't +	 * making changes, just want the master device from that list so +	 * typecast to remove the const +	 */ +	struct net_device *dev = (struct net_device *)_dev; +	const struct net_device *master; + +	if (!dev) +		return NULL; + +	if (netif_is_l3_master(dev)) +		master = dev; +	else if (netif_is_l3_slave(dev)) +		master = netdev_master_upper_dev_get_rcu(dev); +	else +		master = NULL; + +	return master; +} +  /* get index of an interface to use for FIB lookups. For devices   * enslaved to an L3 master device FIB lookups are based on the   * master index @@ -134,7 +167,9 @@ static inline bool netif_index_is_l3_master(struct net *net, int ifindex)  int l3mdev_get_saddr(struct net *net, int ifindex, struct flowi4 *fl4); -struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6); +struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6); +int l3mdev_get_saddr6(struct net *net, const struct sock *sk, +		      struct flowi6 *fl6);  static inline  struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto) @@ -180,6 +215,12 @@ static inline int l3mdev_master_ifindex_by_index(struct net *net, int ifindex)  	return 0;  } +static inline +const struct net_device *l3mdev_master_dev_rcu(const struct net_device *dev) +{ +	return NULL; +} +  static inline int l3mdev_fib_oif_rcu(struct net_device *dev)  {  	return dev ? dev->ifindex : 0; @@ -220,11 +261,17 @@ static inline int l3mdev_get_saddr(struct net *net, int ifindex,  }  static inline -struct dst_entry *l3mdev_get_rt6_dst(struct net *net, const struct flowi6 *fl6) +struct dst_entry *l3mdev_get_rt6_dst(struct net *net, struct flowi6 *fl6)  {  	return NULL;  } +static inline int l3mdev_get_saddr6(struct net *net, const struct sock *sk, +				    struct flowi6 *fl6) +{ +	return 0; +} +  static inline  struct sk_buff *l3mdev_ip_rcv(struct sk_buff *skb)  { @@ -236,6 +283,13 @@ struct sk_buff *l3mdev_ip6_rcv(struct sk_buff *skb)  {  	return skb;  } + +static inline +int l3mdev_fib_rule_match(struct net *net, struct flowi *fl, +			  struct fib_lookup_arg *arg) +{ +	return 1; +}  #endif  #endif /* _NET_L3MDEV_H_ */ diff --git a/include/net/mac80211.h b/include/net/mac80211.h index be30b0549b88..b4faadbb4e01 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -21,6 +21,7 @@  #include <linux/skbuff.h>  #include <linux/ieee80211.h>  #include <net/cfg80211.h> +#include <net/codel.h>  #include <asm/unaligned.h>  /** @@ -895,7 +896,18 @@ struct ieee80211_tx_info {  				unsigned long jiffies;  			};  			/* NB: vif can be NULL for injected frames */ -			struct ieee80211_vif *vif; +			union { +				/* NB: vif can be NULL for injected frames */ +				struct ieee80211_vif *vif; + +				/* When packets are enqueued on txq it's easy +				 * to re-construct the vif pointer. There's no +				 * more space in tx_info so it can be used to +				 * store the necessary enqueue time for packet +				 * sojourn time computation. +				 */ +				codel_time_t enqueue_time; +			};  			struct ieee80211_key_conf *hw_key;  			u32 flags;  			/* 4 bytes free */ @@ -2147,9 +2159,6 @@ enum ieee80211_hw_flags {   * @n_cipher_schemes: a size of an array of cipher schemes definitions.   * @cipher_schemes: a pointer to an array of cipher scheme definitions   *	supported by HW. - * - * @txq_ac_max_pending: maximum number of frames per AC pending in all txq - *	entries for a vif.   */  struct ieee80211_hw {  	struct ieee80211_conf conf; @@ -2180,7 +2189,6 @@ struct ieee80211_hw {  	u8 uapsd_max_sp_len;  	u8 n_cipher_schemes;  	const struct ieee80211_cipher_scheme *cipher_schemes; -	int txq_ac_max_pending;  };  static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw, @@ -4689,9 +4697,10 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw);   * any context, including hardirq context.   *   * @hw: the hardware that finished the scan - * @aborted: set to true if scan was aborted + * @info: information about the completed scan   */ -void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); +void ieee80211_scan_completed(struct ieee80211_hw *hw, +			      struct cfg80211_scan_info *info);  /**   * ieee80211_sched_scan_results - got results from scheduled scan diff --git a/include/net/mac802154.h b/include/net/mac802154.h index e465c8551ac3..286824acd008 100644 --- a/include/net/mac802154.h +++ b/include/net/mac802154.h @@ -247,14 +247,123 @@ struct ieee802154_ops {   */  static inline __le16 ieee802154_get_fc_from_skb(const struct sk_buff *skb)  { +	__le16 fc; +  	/* check if we can fc at skb_mac_header of sk buffer */ -	if (unlikely(!skb_mac_header_was_set(skb) || -		     (skb_tail_pointer(skb) - skb_mac_header(skb)) < 2)) { -		WARN_ON(1); +	if (WARN_ON(!skb_mac_header_was_set(skb) || +		    (skb_tail_pointer(skb) - +		     skb_mac_header(skb)) < IEEE802154_FC_LEN))  		return cpu_to_le16(0); + +	memcpy(&fc, skb_mac_header(skb), IEEE802154_FC_LEN); +	return fc; +} + +/** + * ieee802154_skb_dst_pan - get the pointer to destination pan field + * @fc: mac header frame control field + * @skb: skb where the destination pan pointer will be get from + */ +static inline unsigned char *ieee802154_skb_dst_pan(__le16 fc, +						    const struct sk_buff *skb) +{ +	unsigned char *dst_pan; + +	switch (ieee802154_daddr_mode(fc)) { +	case cpu_to_le16(IEEE802154_FCTL_ADDR_NONE): +		dst_pan = NULL; +		break; +	case cpu_to_le16(IEEE802154_FCTL_DADDR_SHORT): +	case cpu_to_le16(IEEE802154_FCTL_DADDR_EXTENDED): +		dst_pan = skb_mac_header(skb) + +			  IEEE802154_FC_LEN + +			  IEEE802154_SEQ_LEN; +		break; +	default: +		WARN_ONCE(1, "invalid addr mode detected"); +		dst_pan = NULL; +		break; +	} + +	return dst_pan; +} + +/** + * ieee802154_skb_src_pan - get the pointer to source pan field + * @fc: mac header frame control field + * @skb: skb where the source pan pointer will be get from + */ +static inline unsigned char *ieee802154_skb_src_pan(__le16 fc, +						    const struct sk_buff *skb) +{ +	unsigned char *src_pan; + +	switch (ieee802154_saddr_mode(fc)) { +	case cpu_to_le16(IEEE802154_FCTL_ADDR_NONE): +		src_pan = NULL; +		break; +	case cpu_to_le16(IEEE802154_FCTL_SADDR_SHORT): +	case cpu_to_le16(IEEE802154_FCTL_SADDR_EXTENDED): +		/* if intra-pan and source addr mode is non none, +		 * then source pan id is equal destination pan id. +		 */ +		if (ieee802154_is_intra_pan(fc)) { +			src_pan = ieee802154_skb_dst_pan(fc, skb); +			break; +		} + +		switch (ieee802154_daddr_mode(fc)) { +		case cpu_to_le16(IEEE802154_FCTL_ADDR_NONE): +			src_pan = skb_mac_header(skb) + +				  IEEE802154_FC_LEN + +				  IEEE802154_SEQ_LEN; +			break; +		case cpu_to_le16(IEEE802154_FCTL_DADDR_SHORT): +			src_pan = skb_mac_header(skb) + +				  IEEE802154_FC_LEN + +				  IEEE802154_SEQ_LEN + +				  IEEE802154_PAN_ID_LEN + +				  IEEE802154_SHORT_ADDR_LEN; +			break; +		case cpu_to_le16(IEEE802154_FCTL_DADDR_EXTENDED): +			src_pan = skb_mac_header(skb) + +				  IEEE802154_FC_LEN + +				  IEEE802154_SEQ_LEN + +				  IEEE802154_PAN_ID_LEN + +				  IEEE802154_EXTENDED_ADDR_LEN; +			break; +		default: +			WARN_ONCE(1, "invalid addr mode detected"); +			src_pan = NULL; +			break; +		} +		break; +	default: +		WARN_ONCE(1, "invalid addr mode detected"); +		src_pan = NULL; +		break;  	} -	return get_unaligned_le16(skb_mac_header(skb)); +	return src_pan; +} + +/** + * ieee802154_skb_is_intra_pan_addressing - checks whenever the mac addressing + *	is an intra pan communication + * @fc: mac header frame control field + * @skb: skb where the source and destination pan should be get from + */ +static inline bool ieee802154_skb_is_intra_pan_addressing(__le16 fc, +							  const struct sk_buff *skb) +{ +	unsigned char *dst_pan = ieee802154_skb_dst_pan(fc, skb), +		      *src_pan = ieee802154_skb_src_pan(fc, skb); + +	/* if one is NULL is no intra pan addressing */ +	if (!dst_pan || !src_pan) +		return false; + +	return !memcmp(dst_pan, src_pan, IEEE802154_PAN_ID_LEN);  }  /** diff --git a/include/net/ncsi.h b/include/net/ncsi.h new file mode 100644 index 000000000000..1dbf42f79750 --- /dev/null +++ b/include/net/ncsi.h @@ -0,0 +1,52 @@ +#ifndef __NET_NCSI_H +#define __NET_NCSI_H + +/* + * The NCSI device states seen from external. More NCSI device states are + * only visible internally (in net/ncsi/internal.h). When the NCSI device + * is registered, it's in ncsi_dev_state_registered state. The state + * ncsi_dev_state_start is used to drive to choose active package and + * channel. After that, its state is changed to ncsi_dev_state_functional. + * + * The state ncsi_dev_state_stop helps to shut down the currently active + * package and channel while ncsi_dev_state_config helps to reconfigure + * them. + */ +enum { +	ncsi_dev_state_registered	= 0x0000, +	ncsi_dev_state_functional	= 0x0100, +	ncsi_dev_state_probe		= 0x0200, +	ncsi_dev_state_config		= 0x0300, +	ncsi_dev_state_suspend		= 0x0400, +}; + +struct ncsi_dev { +	int               state; +	int		  link_up; +	struct net_device *dev; +	void		  (*handler)(struct ncsi_dev *ndev); +}; + +#ifdef CONFIG_NET_NCSI +struct ncsi_dev *ncsi_register_dev(struct net_device *dev, +				   void (*notifier)(struct ncsi_dev *nd)); +int ncsi_start_dev(struct ncsi_dev *nd); +void ncsi_unregister_dev(struct ncsi_dev *nd); +#else /* !CONFIG_NET_NCSI */ +static inline struct ncsi_dev *ncsi_register_dev(struct net_device *dev, +					void (*notifier)(struct ncsi_dev *nd)) +{ +	return NULL; +} + +static inline int ncsi_start_dev(struct ncsi_dev *nd) +{ +	return -ENOTTY; +} + +static inline void ncsi_unregister_dev(struct ncsi_dev *nd) +{ +} +#endif /* CONFIG_NET_NCSI */ + +#endif /* __NET_NCSI_H */ diff --git a/include/net/ndisc.h b/include/net/ndisc.h index 2d8edaad29cb..be1fe2283254 100644 --- a/include/net/ndisc.h +++ b/include/net/ndisc.h @@ -35,6 +35,7 @@ enum {  	ND_OPT_ROUTE_INFO = 24,		/* RFC4191 */  	ND_OPT_RDNSS = 25,		/* RFC5006 */  	ND_OPT_DNSSL = 31,		/* RFC6106 */ +	ND_OPT_6CO = 34,		/* RFC6775 */  	__ND_OPT_MAX  }; @@ -53,11 +54,21 @@ enum {  #include <net/neighbour.h> +/* Set to 3 to get tracing... */ +#define ND_DEBUG 1 + +#define ND_PRINTK(val, level, fmt, ...)				\ +do {								\ +	if (val <= ND_DEBUG)					\ +		net_##level##_ratelimited(fmt, ##__VA_ARGS__);	\ +} while (0) +  struct ctl_table;  struct inet6_dev;  struct net_device;  struct net_proto_family;  struct sk_buff; +struct prefix_info;  extern struct neigh_table nd_tbl; @@ -99,20 +110,201 @@ struct ndisc_options {  #endif  	struct nd_opt_hdr *nd_useropts;  	struct nd_opt_hdr *nd_useropts_end; +#if IS_ENABLED(CONFIG_IEEE802154_6LOWPAN) +	struct nd_opt_hdr *nd_802154_opt_array[ND_OPT_TARGET_LL_ADDR + 1]; +#endif  }; -#define nd_opts_src_lladdr	nd_opt_array[ND_OPT_SOURCE_LL_ADDR] -#define nd_opts_tgt_lladdr	nd_opt_array[ND_OPT_TARGET_LL_ADDR] -#define nd_opts_pi		nd_opt_array[ND_OPT_PREFIX_INFO] -#define nd_opts_pi_end		nd_opt_array[__ND_OPT_PREFIX_INFO_END] -#define nd_opts_rh		nd_opt_array[ND_OPT_REDIRECT_HDR] -#define nd_opts_mtu		nd_opt_array[ND_OPT_MTU] +#define nd_opts_src_lladdr		nd_opt_array[ND_OPT_SOURCE_LL_ADDR] +#define nd_opts_tgt_lladdr		nd_opt_array[ND_OPT_TARGET_LL_ADDR] +#define nd_opts_pi			nd_opt_array[ND_OPT_PREFIX_INFO] +#define nd_opts_pi_end			nd_opt_array[__ND_OPT_PREFIX_INFO_END] +#define nd_opts_rh			nd_opt_array[ND_OPT_REDIRECT_HDR] +#define nd_opts_mtu			nd_opt_array[ND_OPT_MTU] +#define nd_802154_opts_src_lladdr	nd_802154_opt_array[ND_OPT_SOURCE_LL_ADDR] +#define nd_802154_opts_tgt_lladdr	nd_802154_opt_array[ND_OPT_TARGET_LL_ADDR]  #define NDISC_OPT_SPACE(len) (((len)+2+7)&~7) -struct ndisc_options *ndisc_parse_options(u8 *opt, int opt_len, +struct ndisc_options *ndisc_parse_options(const struct net_device *dev, +					  u8 *opt, int opt_len,  					  struct ndisc_options *ndopts); +void __ndisc_fill_addr_option(struct sk_buff *skb, int type, void *data, +			      int data_len, int pad); + +#define NDISC_OPS_REDIRECT_DATA_SPACE	2 + +/* + * This structure defines the hooks for IPv6 neighbour discovery. + * The following hooks can be defined; unless noted otherwise, they are + * optional and can be filled with a null pointer. + * + * int (*is_useropt)(u8 nd_opt_type): + *     This function is called when IPv6 decide RA userspace options. if + *     this function returns 1 then the option given by nd_opt_type will + *     be handled as userspace option additional to the IPv6 options. + * + * int (*parse_options)(const struct net_device *dev, + *			struct nd_opt_hdr *nd_opt, + *			struct ndisc_options *ndopts): + *     This function is called while parsing ndisc ops and put each position + *     as pointer into ndopts. If this function return unequal 0, then this + *     function took care about the ndisc option, if 0 then the IPv6 ndisc + *     option parser will take care about that option. + * + * void (*update)(const struct net_device *dev, struct neighbour *n, + *		  u32 flags, u8 icmp6_type, + *		  const struct ndisc_options *ndopts): + *     This function is called when IPv6 ndisc updates the neighbour cache + *     entry. Additional options which can be updated may be previously + *     parsed by parse_opts callback and accessible over ndopts parameter. + * + * int (*opt_addr_space)(const struct net_device *dev, u8 icmp6_type, + *			 struct neighbour *neigh, u8 *ha_buf, + *			 u8 **ha): + *     This function is called when the necessary option space will be + *     calculated before allocating a skb. The parameters neigh, ha_buf + *     abd ha are available on NDISC_REDIRECT messages only. + * + * void (*fill_addr_option)(const struct net_device *dev, + *			    struct sk_buff *skb, u8 icmp6_type, + *			    const u8 *ha): + *     This function is called when the skb will finally fill the option + *     fields inside skb. NOTE: this callback should fill the option + *     fields to the skb which are previously indicated by opt_space + *     parameter. That means the decision to add such option should + *     not lost between these two callbacks, e.g. protected by interface + *     up state. + * + * void (*prefix_rcv_add_addr)(struct net *net, struct net_device *dev, + *			       const struct prefix_info *pinfo, + *			       struct inet6_dev *in6_dev, + *			       struct in6_addr *addr, + *			       int addr_type, u32 addr_flags, + *			       bool sllao, bool tokenized, + *			       __u32 valid_lft, u32 prefered_lft, + *			       bool dev_addr_generated): + *     This function is called when a RA messages is received with valid + *     PIO option fields and an IPv6 address will be added to the interface + *     for autoconfiguration. The parameter dev_addr_generated reports about + *     if the address was based on dev->dev_addr or not. This can be used + *     to add a second address if link-layer operates with two link layer + *     addresses. E.g. 802.15.4 6LoWPAN. + */ +struct ndisc_ops { +	int	(*is_useropt)(u8 nd_opt_type); +	int	(*parse_options)(const struct net_device *dev, +				 struct nd_opt_hdr *nd_opt, +				 struct ndisc_options *ndopts); +	void	(*update)(const struct net_device *dev, struct neighbour *n, +			  u32 flags, u8 icmp6_type, +			  const struct ndisc_options *ndopts); +	int	(*opt_addr_space)(const struct net_device *dev, u8 icmp6_type, +				  struct neighbour *neigh, u8 *ha_buf, +				  u8 **ha); +	void	(*fill_addr_option)(const struct net_device *dev, +				    struct sk_buff *skb, u8 icmp6_type, +				    const u8 *ha); +	void	(*prefix_rcv_add_addr)(struct net *net, struct net_device *dev, +				       const struct prefix_info *pinfo, +				       struct inet6_dev *in6_dev, +				       struct in6_addr *addr, +				       int addr_type, u32 addr_flags, +				       bool sllao, bool tokenized, +				       __u32 valid_lft, u32 prefered_lft, +				       bool dev_addr_generated); +}; + +#if IS_ENABLED(CONFIG_IPV6) +static inline int ndisc_ops_is_useropt(const struct net_device *dev, +				       u8 nd_opt_type) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->is_useropt) +		return dev->ndisc_ops->is_useropt(nd_opt_type); +	else +		return 0; +} + +static inline int ndisc_ops_parse_options(const struct net_device *dev, +					  struct nd_opt_hdr *nd_opt, +					  struct ndisc_options *ndopts) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->parse_options) +		return dev->ndisc_ops->parse_options(dev, nd_opt, ndopts); +	else +		return 0; +} + +static inline void ndisc_ops_update(const struct net_device *dev, +					  struct neighbour *n, u32 flags, +					  u8 icmp6_type, +					  const struct ndisc_options *ndopts) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->update) +		dev->ndisc_ops->update(dev, n, flags, icmp6_type, ndopts); +} + +static inline int ndisc_ops_opt_addr_space(const struct net_device *dev, +					   u8 icmp6_type) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->opt_addr_space && +	    icmp6_type != NDISC_REDIRECT) +		return dev->ndisc_ops->opt_addr_space(dev, icmp6_type, NULL, +						      NULL, NULL); +	else +		return 0; +} + +static inline int ndisc_ops_redirect_opt_addr_space(const struct net_device *dev, +						    struct neighbour *neigh, +						    u8 *ha_buf, u8 **ha) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->opt_addr_space) +		return dev->ndisc_ops->opt_addr_space(dev, NDISC_REDIRECT, +						      neigh, ha_buf, ha); +	else +		return 0; +} + +static inline void ndisc_ops_fill_addr_option(const struct net_device *dev, +					      struct sk_buff *skb, +					      u8 icmp6_type) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->fill_addr_option && +	    icmp6_type != NDISC_REDIRECT) +		dev->ndisc_ops->fill_addr_option(dev, skb, icmp6_type, NULL); +} + +static inline void ndisc_ops_fill_redirect_addr_option(const struct net_device *dev, +						       struct sk_buff *skb, +						       const u8 *ha) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->fill_addr_option) +		dev->ndisc_ops->fill_addr_option(dev, skb, NDISC_REDIRECT, ha); +} + +static inline void ndisc_ops_prefix_rcv_add_addr(struct net *net, +						 struct net_device *dev, +						 const struct prefix_info *pinfo, +						 struct inet6_dev *in6_dev, +						 struct in6_addr *addr, +						 int addr_type, u32 addr_flags, +						 bool sllao, bool tokenized, +						 __u32 valid_lft, +						 u32 prefered_lft, +						 bool dev_addr_generated) +{ +	if (dev->ndisc_ops && dev->ndisc_ops->prefix_rcv_add_addr) +		dev->ndisc_ops->prefix_rcv_add_addr(net, dev, pinfo, in6_dev, +						    addr, addr_type, +						    addr_flags, sllao, +						    tokenized, valid_lft, +						    prefered_lft, +						    dev_addr_generated); +} +#endif +  /*   * Return the padding between the option length and the start of the   * link addr.  Currently only IP-over-InfiniBand needs this, although @@ -127,23 +319,48 @@ static inline int ndisc_addr_option_pad(unsigned short type)  	}  } -static inline int ndisc_opt_addr_space(struct net_device *dev) +static inline int __ndisc_opt_addr_space(unsigned char addr_len, int pad)  { -	return NDISC_OPT_SPACE(dev->addr_len + -			       ndisc_addr_option_pad(dev->type)); +	return NDISC_OPT_SPACE(addr_len + pad);  } -static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, -				      struct net_device *dev) +#if IS_ENABLED(CONFIG_IPV6) +static inline int ndisc_opt_addr_space(struct net_device *dev, u8 icmp6_type) +{ +	return __ndisc_opt_addr_space(dev->addr_len, +				      ndisc_addr_option_pad(dev->type)) + +		ndisc_ops_opt_addr_space(dev, icmp6_type); +} + +static inline int ndisc_redirect_opt_addr_space(struct net_device *dev, +						struct neighbour *neigh, +						u8 *ops_data_buf, +						u8 **ops_data) +{ +	return __ndisc_opt_addr_space(dev->addr_len, +				      ndisc_addr_option_pad(dev->type)) + +		ndisc_ops_redirect_opt_addr_space(dev, neigh, ops_data_buf, +						  ops_data); +} +#endif + +static inline u8 *__ndisc_opt_addr_data(struct nd_opt_hdr *p, +					unsigned char addr_len, int prepad)  {  	u8 *lladdr = (u8 *)(p + 1);  	int lladdrlen = p->nd_opt_len << 3; -	int prepad = ndisc_addr_option_pad(dev->type); -	if (lladdrlen != ndisc_opt_addr_space(dev)) +	if (lladdrlen != __ndisc_opt_addr_space(addr_len, prepad))  		return NULL;  	return lladdr + prepad;  } +static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, +				      struct net_device *dev) +{ +	return __ndisc_opt_addr_data(p, dev->addr_len, +				     ndisc_addr_option_pad(dev->type)); +} +  static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)  {  	const u32 *p32 = pkey; @@ -194,6 +411,9 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target);  int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev,  		 int dir); +void ndisc_update(const struct net_device *dev, struct neighbour *neigh, +		  const u8 *lladdr, u8 new, u32 flags, u8 icmp6_type, +		  struct ndisc_options *ndopts);  /*   *	IGMP diff --git a/include/net/netevent.h b/include/net/netevent.h index d8bbb38584b6..f440df172b56 100644 --- a/include/net/netevent.h +++ b/include/net/netevent.h @@ -24,6 +24,7 @@ struct netevent_redirect {  enum netevent_notif_type {  	NETEVENT_NEIGH_UPDATE = 1, /* arg is struct neighbour ptr */  	NETEVENT_REDIRECT,	   /* arg is struct netevent_redirect ptr */ +	NETEVENT_DELAY_PROBE_TIME_UPDATE, /* arg is struct neigh_parms ptr */  };  int register_netevent_notifier(struct notifier_block *nb); diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h index dd78bea227c8..445b019c2078 100644 --- a/include/net/netfilter/nf_conntrack.h +++ b/include/net/netfilter/nf_conntrack.h @@ -17,6 +17,7 @@  #include <linux/bitops.h>  #include <linux/compiler.h>  #include <linux/atomic.h> +#include <linux/rhashtable.h>  #include <linux/netfilter/nf_conntrack_tcp.h>  #include <linux/netfilter/nf_conntrack_dccp.h> @@ -85,6 +86,9 @@ struct nf_conn {  	spinlock_t	lock;  	u16		cpu; +#ifdef CONFIG_NF_CONNTRACK_ZONES +	struct nf_conntrack_zone zone; +#endif  	/* XXX should I move this to the tail ? - Y.K */  	/* These are my tuples; original and reply */  	struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX]; @@ -114,6 +118,9 @@ struct nf_conn {  	/* Extensions */  	struct nf_ct_ext *ext; +#if IS_ENABLED(CONFIG_NF_NAT) +	struct rhash_head	nat_bysource; +#endif  	/* Storage reserved for other modules, must be the last member */  	union nf_conntrack_proto proto;  }; @@ -263,12 +270,12 @@ static inline int nf_ct_is_template(const struct nf_conn *ct)  }  /* It's confirmed if it is, or has been in the hash table. */ -static inline int nf_ct_is_confirmed(struct nf_conn *ct) +static inline int nf_ct_is_confirmed(const struct nf_conn *ct)  {  	return test_bit(IPS_CONFIRMED_BIT, &ct->status);  } -static inline int nf_ct_is_dying(struct nf_conn *ct) +static inline int nf_ct_is_dying(const struct nf_conn *ct)  {  	return test_bit(IPS_DYING_BIT, &ct->status);  } @@ -284,9 +291,18 @@ static inline bool nf_is_loopback_packet(const struct sk_buff *skb)  	return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK;  } +/* jiffies until ct expires, 0 if already expired */ +static inline unsigned long nf_ct_expires(const struct nf_conn *ct) +{ +	long timeout = (long)ct->timeout.expires - (long)jiffies; + +	return timeout > 0 ? timeout : 0; +} +  struct kernel_param;  int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp); +int nf_conntrack_hash_resize(unsigned int hashsize);  extern unsigned int nf_conntrack_htable_size;  extern unsigned int nf_conntrack_max; @@ -297,6 +313,7 @@ void nf_ct_tmpl_free(struct nf_conn *tmpl);  #define NF_CT_STAT_INC(net, count)	  __this_cpu_inc((net)->ct.stat->count)  #define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count) +#define NF_CT_STAT_ADD_ATOMIC(net, count, v) this_cpu_add((net)->ct.stat->count, (v))  #define MODULE_ALIAS_NFCT_HELPER(helper) \          MODULE_ALIAS("nfct-helper-" helper) diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h index 3e2f3328945c..79d7ac5c9740 100644 --- a/include/net/netfilter/nf_conntrack_core.h +++ b/include/net/netfilter/nf_conntrack_core.h @@ -51,6 +51,8 @@ bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,  			const struct nf_conntrack_l3proto *l3proto,  			const struct nf_conntrack_l4proto *l4proto); +void nf_conntrack_get_ht(struct hlist_nulls_head **hash, unsigned int *hsize); +  /* Find a connection corresponding to a tuple. */  struct nf_conntrack_tuple_hash *  nf_conntrack_find_get(struct net *net, diff --git a/include/net/netfilter/nf_conntrack_extend.h b/include/net/netfilter/nf_conntrack_extend.h index 55d15049ab2f..1c3035dda31f 100644 --- a/include/net/netfilter/nf_conntrack_extend.h +++ b/include/net/netfilter/nf_conntrack_extend.h @@ -15,9 +15,6 @@ enum nf_ct_ext_id {  #ifdef CONFIG_NF_CONNTRACK_EVENTS  	NF_CT_EXT_ECACHE,  #endif -#ifdef CONFIG_NF_CONNTRACK_ZONES -	NF_CT_EXT_ZONE, -#endif  #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP  	NF_CT_EXT_TSTAMP,  #endif @@ -38,7 +35,6 @@ enum nf_ct_ext_id {  #define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj  #define NF_CT_EXT_ACCT_TYPE struct nf_conn_acct  #define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache -#define NF_CT_EXT_ZONE_TYPE struct nf_conntrack_zone  #define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp  #define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout  #define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels @@ -103,9 +99,6 @@ void *__nf_ct_ext_add_length(struct nf_conn *ct, enum nf_ct_ext_id id,  struct nf_ct_ext_type {  	/* Destroys relationships (can be NULL). */  	void (*destroy)(struct nf_conn *ct); -	/* Called when realloacted (can be NULL). -	   Contents has already been moved. */ -	void (*move)(void *new, void *old);  	enum nf_ct_ext_id id; diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h index 6cf614bc0029..1eaac1f4cd6a 100644 --- a/include/net/netfilter/nf_conntrack_helper.h +++ b/include/net/netfilter/nf_conntrack_helper.h @@ -58,10 +58,25 @@ struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,  struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,  							       u16 l3num,  							       u8 protonum); +void nf_ct_helper_init(struct nf_conntrack_helper *helper, +		       u16 l3num, u16 protonum, const char *name, +		       u16 default_port, u16 spec_port, u32 id, +		       const struct nf_conntrack_expect_policy *exp_pol, +		       u32 expect_class_max, u32 data_len, +		       int (*help)(struct sk_buff *skb, unsigned int protoff, +				   struct nf_conn *ct, +				   enum ip_conntrack_info ctinfo), +		       int (*from_nlattr)(struct nlattr *attr, +					  struct nf_conn *ct), +		       struct module *module);  int nf_conntrack_helper_register(struct nf_conntrack_helper *);  void nf_conntrack_helper_unregister(struct nf_conntrack_helper *); +int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int); +void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *, +				     unsigned int); +  struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct,  					  struct nf_conntrack_helper *helper,  					  gfp_t gfp); diff --git a/include/net/netfilter/nf_conntrack_labels.h b/include/net/netfilter/nf_conntrack_labels.h index c5f8fc736b3d..498814626e28 100644 --- a/include/net/netfilter/nf_conntrack_labels.h +++ b/include/net/netfilter/nf_conntrack_labels.h @@ -10,8 +10,7 @@  #define NF_CT_LABELS_MAX_SIZE ((XT_CONNLABEL_MAXBIT + 1) / BITS_PER_BYTE)  struct nf_conn_labels { -	u8 words; -	unsigned long bits[]; +	unsigned long bits[NF_CT_LABELS_MAX_SIZE / sizeof(long)];  };  static inline struct nf_conn_labels *nf_ct_labels_find(const struct nf_conn *ct) @@ -26,27 +25,18 @@ static inline struct nf_conn_labels *nf_ct_labels_find(const struct nf_conn *ct)  static inline struct nf_conn_labels *nf_ct_labels_ext_add(struct nf_conn *ct)  {  #ifdef CONFIG_NF_CONNTRACK_LABELS -	struct nf_conn_labels *cl_ext;  	struct net *net = nf_ct_net(ct); -	u8 words; -	words = ACCESS_ONCE(net->ct.label_words); -	if (words == 0) +	if (net->ct.labels_used == 0)  		return NULL; -	cl_ext = nf_ct_ext_add_length(ct, NF_CT_EXT_LABELS, -				      words * sizeof(long), GFP_ATOMIC); -	if (cl_ext != NULL) -		cl_ext->words = words; - -	return cl_ext; +	return nf_ct_ext_add_length(ct, NF_CT_EXT_LABELS, +				    sizeof(struct nf_conn_labels), GFP_ATOMIC);  #else  	return NULL;  #endif  } -int nf_connlabel_set(struct nf_conn *ct, u16 bit); -  int nf_connlabels_replace(struct nf_conn *ct,  			  const u32 *data, const u32 *mask, unsigned int words); diff --git a/include/net/netfilter/nf_conntrack_zones.h b/include/net/netfilter/nf_conntrack_zones.h index 4e32512cef32..64a718b60839 100644 --- a/include/net/netfilter/nf_conntrack_zones.h +++ b/include/net/netfilter/nf_conntrack_zones.h @@ -9,12 +9,11 @@  static inline const struct nf_conntrack_zone *  nf_ct_zone(const struct nf_conn *ct)  { -	const struct nf_conntrack_zone *nf_ct_zone = NULL; -  #ifdef CONFIG_NF_CONNTRACK_ZONES -	nf_ct_zone = nf_ct_ext_find(ct, NF_CT_EXT_ZONE); +	return &ct->zone; +#else +	return &nf_ct_zone_dflt;  #endif -	return nf_ct_zone ? nf_ct_zone : &nf_ct_zone_dflt;  }  static inline const struct nf_conntrack_zone * @@ -31,32 +30,22 @@ static inline const struct nf_conntrack_zone *  nf_ct_zone_tmpl(const struct nf_conn *tmpl, const struct sk_buff *skb,  		struct nf_conntrack_zone *tmp)  { -	const struct nf_conntrack_zone *zone; - +#ifdef CONFIG_NF_CONNTRACK_ZONES  	if (!tmpl)  		return &nf_ct_zone_dflt; -	zone = nf_ct_zone(tmpl); -	if (zone->flags & NF_CT_FLAG_MARK) -		zone = nf_ct_zone_init(tmp, skb->mark, zone->dir, 0); - -	return zone; +	if (tmpl->zone.flags & NF_CT_FLAG_MARK) +		return nf_ct_zone_init(tmp, skb->mark, tmpl->zone.dir, 0); +#endif +	return nf_ct_zone(tmpl);  } -static inline int nf_ct_zone_add(struct nf_conn *ct, gfp_t flags, -				 const struct nf_conntrack_zone *info) +static inline void nf_ct_zone_add(struct nf_conn *ct, +				  const struct nf_conntrack_zone *zone)  {  #ifdef CONFIG_NF_CONNTRACK_ZONES -	struct nf_conntrack_zone *nf_ct_zone; - -	nf_ct_zone = nf_ct_ext_add(ct, NF_CT_EXT_ZONE, flags); -	if (!nf_ct_zone) -		return -ENOMEM; - -	nf_ct_zone_init(nf_ct_zone, info->id, info->dir, -			info->flags); +	ct->zone = *zone;  #endif -	return 0;  }  static inline bool nf_ct_zone_matches_dir(const struct nf_conntrack_zone *zone, @@ -68,22 +57,34 @@ static inline bool nf_ct_zone_matches_dir(const struct nf_conntrack_zone *zone,  static inline u16 nf_ct_zone_id(const struct nf_conntrack_zone *zone,  				enum ip_conntrack_dir dir)  { +#ifdef CONFIG_NF_CONNTRACK_ZONES  	return nf_ct_zone_matches_dir(zone, dir) ?  	       zone->id : NF_CT_DEFAULT_ZONE_ID; +#else +	return NF_CT_DEFAULT_ZONE_ID; +#endif  }  static inline bool nf_ct_zone_equal(const struct nf_conn *a,  				    const struct nf_conntrack_zone *b,  				    enum ip_conntrack_dir dir)  { +#ifdef CONFIG_NF_CONNTRACK_ZONES  	return nf_ct_zone_id(nf_ct_zone(a), dir) ==  	       nf_ct_zone_id(b, dir); +#else +	return true; +#endif  }  static inline bool nf_ct_zone_equal_any(const struct nf_conn *a,  					const struct nf_conntrack_zone *b)  { +#ifdef CONFIG_NF_CONNTRACK_ZONES  	return nf_ct_zone(a)->id == b->id; +#else +	return true; +#endif  }  #endif /* IS_ENABLED(CONFIG_NF_CONNTRACK) */  #endif /* _NF_CONNTRACK_ZONES_H */ diff --git a/include/net/netfilter/nf_log.h b/include/net/netfilter/nf_log.h index 57639fca223a..83d855ba6af1 100644 --- a/include/net/netfilter/nf_log.h +++ b/include/net/netfilter/nf_log.h @@ -12,6 +12,9 @@  #define NF_LOG_UID		0x08	/* Log UID owning local socket */  #define NF_LOG_MASK		0x0f +/* This flag indicates that copy_len field in nf_loginfo is set */ +#define NF_LOG_F_COPY_LEN	0x1 +  enum nf_log_type {  	NF_LOG_TYPE_LOG		= 0,  	NF_LOG_TYPE_ULOG, @@ -22,9 +25,13 @@ struct nf_loginfo {  	u_int8_t type;  	union {  		struct { +			/* copy_len will be used iff you set +			 * NF_LOG_F_COPY_LEN in flags +			 */  			u_int32_t copy_len;  			u_int16_t group;  			u_int16_t qthreshold; +			u_int16_t flags;  		} ulog;  		struct {  			u_int8_t level; diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index 344b1ab19220..c327a431a6f3 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h @@ -1,5 +1,6 @@  #ifndef _NF_NAT_H  #define _NF_NAT_H +#include <linux/rhashtable.h>  #include <linux/netfilter_ipv4.h>  #include <linux/netfilter/nf_nat.h>  #include <net/netfilter/nf_conntrack_tuple.h> @@ -29,8 +30,6 @@ struct nf_conn;  /* The structure embedded in the conntrack structure. */  struct nf_conn_nat { -	struct hlist_node bysource; -	struct nf_conn *ct;  	union nf_conntrack_nat_help help;  #if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \      IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6) diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h index 092235458691..f2f13399ce44 100644 --- a/include/net/netfilter/nf_tables.h +++ b/include/net/netfilter/nf_tables.h @@ -167,6 +167,7 @@ struct nft_set_elem {  struct nft_set;  struct nft_set_iter { +	u8		genmask;  	unsigned int	count;  	unsigned int	skip;  	int		err; @@ -235,7 +236,8 @@ struct nft_expr;   *	@features: features supported by the implementation   */  struct nft_set_ops { -	bool				(*lookup)(const struct nft_set *set, +	bool				(*lookup)(const struct net *net, +						  const struct nft_set *set,  						  const u32 *key,  						  const struct nft_set_ext **ext);  	bool				(*update)(struct nft_set *set, @@ -247,11 +249,14 @@ struct nft_set_ops {  						  struct nft_regs *regs,  						  const struct nft_set_ext **ext); -	int				(*insert)(const struct nft_set *set, +	int				(*insert)(const struct net *net, +						  const struct nft_set *set,  						  const struct nft_set_elem *elem); -	void				(*activate)(const struct nft_set *set, +	void				(*activate)(const struct net *net, +						    const struct nft_set *set,  						    const struct nft_set_elem *elem); -	void *				(*deactivate)(const struct nft_set *set, +	void *				(*deactivate)(const struct net *net, +						      const struct nft_set *set,  						      const struct nft_set_elem *elem);  	void				(*remove)(const struct nft_set *set,  						  const struct nft_set_elem *elem); @@ -294,8 +299,8 @@ void nft_unregister_set(struct nft_set_ops *ops);   *	@udlen: user data length   *	@udata: user data   * 	@ops: set ops - * 	@pnet: network namespace   * 	@flags: set flags + *	@genmask: generation mask   * 	@klen: key length   * 	@dlen: data length   * 	@data: private set data @@ -316,8 +321,8 @@ struct nft_set {  	unsigned char			*udata;  	/* runtime data below here */  	const struct nft_set_ops	*ops ____cacheline_aligned; -	possible_net_t			pnet; -	u16				flags; +	u16				flags:14, +					genmask:2;  	u8				klen;  	u8				dlen;  	unsigned char			data[] @@ -335,9 +340,9 @@ static inline struct nft_set *nft_set_container_of(const void *priv)  }  struct nft_set *nf_tables_set_lookup(const struct nft_table *table, -				     const struct nlattr *nla); +				     const struct nlattr *nla, u8 genmask);  struct nft_set *nf_tables_set_lookup_byid(const struct net *net, -					  const struct nlattr *nla); +					  const struct nlattr *nla, u8 genmask);  static inline unsigned long nft_set_gc_interval(const struct nft_set *set)  { @@ -732,7 +737,6 @@ static inline struct nft_userdata *nft_userdata(const struct nft_rule *rule)  enum nft_chain_flags {  	NFT_BASE_CHAIN			= 0x1, -	NFT_CHAIN_INACTIVE		= 0x2,  };  /** @@ -754,7 +758,8 @@ struct nft_chain {  	u64				handle;  	u32				use;  	u16				level; -	u8				flags; +	u8				flags:6, +					genmask:2;  	char				name[NFT_CHAIN_MAXNAMELEN];  }; @@ -796,13 +801,11 @@ struct nft_stats {  };  #define NFT_HOOK_OPS_MAX		2 -#define NFT_BASECHAIN_DISABLED		(1 << 0)  /**   *	struct nft_base_chain - nf_tables base chain   *   *	@ops: netfilter hook ops - *	@pnet: net namespace that this chain belongs to   *	@type: chain type   *	@policy: default policy   *	@stats: per-cpu chain stats @@ -811,7 +814,6 @@ struct nft_stats {   */  struct nft_base_chain {  	struct nf_hook_ops		ops[NFT_HOOK_OPS_MAX]; -	possible_net_t			pnet;  	const struct nf_chain_type	*type;  	u8				policy;  	u8				flags; @@ -838,6 +840,7 @@ unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv);   *	@hgenerator: handle generator state   *	@use: number of chain references to this table   *	@flags: table flag (see enum nft_table_flags) + *	@genmask: generation mask   *	@name: name of the table   */  struct nft_table { @@ -846,7 +849,8 @@ struct nft_table {  	struct list_head		sets;  	u64				hgenerator;  	u32				use; -	u16				flags; +	u16				flags:14, +					genmask:2;  	char				name[NFT_TABLE_MAXNAMELEN];  }; @@ -970,6 +974,32 @@ static inline u8 nft_genmask_cur(const struct net *net)  #define NFT_GENMASK_ANY		((1 << 0) | (1 << 1))  /* + * Generic transaction helpers + */ + +/* Check if this object is currently active. */ +#define nft_is_active(__net, __obj)				\ +	(((__obj)->genmask & nft_genmask_cur(__net)) == 0) + +/* Check if this object is active in the next generation. */ +#define nft_is_active_next(__net, __obj)			\ +	(((__obj)->genmask & nft_genmask_next(__net)) == 0) + +/* This object becomes active in the next generation. */ +#define nft_activate_next(__net, __obj)				\ +	(__obj)->genmask = nft_genmask_cur(__net) + +/* This object becomes inactive in the next generation. */ +#define nft_deactivate_next(__net, __obj)			\ +        (__obj)->genmask = nft_genmask_next(__net) + +/* After committing the ruleset, clear the stale generation bit. */ +#define nft_clear(__net, __obj)					\ +	(__obj)->genmask &= ~nft_genmask_next(__net) +#define nft_active_genmask(__obj, __genmask)			\ +	!((__obj)->genmask & __genmask) + +/*   * Set element transaction helpers   */ @@ -979,10 +1009,11 @@ static inline bool nft_set_elem_active(const struct nft_set_ext *ext,  	return !(ext->genmask & genmask);  } -static inline void nft_set_elem_change_active(const struct nft_set *set, +static inline void nft_set_elem_change_active(const struct net *net, +					      const struct nft_set *set,  					      struct nft_set_ext *ext)  { -	ext->genmask ^= nft_genmask_next(read_pnet(&set->pnet)); +	ext->genmask ^= nft_genmask_next(net);  }  /* diff --git a/include/net/netlabel.h b/include/net/netlabel.h index 7b5a300de7f5..efe98068880f 100644 --- a/include/net/netlabel.h +++ b/include/net/netlabel.h @@ -40,6 +40,7 @@  #include <linux/atomic.h>  struct cipso_v4_doi; +struct calipso_doi;  /*   * NetLabel - A management interface for maintaining network packet label @@ -94,6 +95,8 @@ struct cipso_v4_doi;  #define NETLBL_NLTYPE_UNLABELED_NAME    "NLBL_UNLBL"  #define NETLBL_NLTYPE_ADDRSELECT        6  #define NETLBL_NLTYPE_ADDRSELECT_NAME   "NLBL_ADRSEL" +#define NETLBL_NLTYPE_CALIPSO           7 +#define NETLBL_NLTYPE_CALIPSO_NAME      "NLBL_CALIPSO"  /*   * NetLabel - Kernel API for accessing the network packet label mappings. @@ -216,6 +219,63 @@ struct netlbl_lsm_secattr {  	} attr;  }; +/** + * struct netlbl_calipso_ops - NetLabel CALIPSO operations + * @doi_add: add a CALIPSO DOI + * @doi_free: free a CALIPSO DOI + * @doi_getdef: returns a reference to a DOI + * @doi_putdef: releases a reference of a DOI + * @doi_walk: enumerate the DOI list + * @sock_getattr: retrieve the socket's attr + * @sock_setattr: set the socket's attr + * @sock_delattr: remove the socket's attr + * @req_setattr: set the req socket's attr + * @req_delattr: remove the req socket's attr + * @opt_getattr: retrieve attr from memory block + * @skbuff_optptr: find option in packet + * @skbuff_setattr: set the skbuff's attr + * @skbuff_delattr: remove the skbuff's attr + * @cache_invalidate: invalidate cache + * @cache_add: add cache entry + * + * Description: + * This structure is filled out by the CALIPSO engine and passed + * to the NetLabel core via a call to netlbl_calipso_ops_register(). + * It enables the CALIPSO engine (and hence IPv6) to be compiled + * as a module. + */ +struct netlbl_calipso_ops { +	int (*doi_add)(struct calipso_doi *doi_def, +		       struct netlbl_audit *audit_info); +	void (*doi_free)(struct calipso_doi *doi_def); +	int (*doi_remove)(u32 doi, struct netlbl_audit *audit_info); +	struct calipso_doi *(*doi_getdef)(u32 doi); +	void (*doi_putdef)(struct calipso_doi *doi_def); +	int (*doi_walk)(u32 *skip_cnt, +			int (*callback)(struct calipso_doi *doi_def, void *arg), +			void *cb_arg); +	int (*sock_getattr)(struct sock *sk, +			    struct netlbl_lsm_secattr *secattr); +	int (*sock_setattr)(struct sock *sk, +			    const struct calipso_doi *doi_def, +			    const struct netlbl_lsm_secattr *secattr); +	void (*sock_delattr)(struct sock *sk); +	int (*req_setattr)(struct request_sock *req, +			   const struct calipso_doi *doi_def, +			   const struct netlbl_lsm_secattr *secattr); +	void (*req_delattr)(struct request_sock *req); +	int (*opt_getattr)(const unsigned char *calipso, +			   struct netlbl_lsm_secattr *secattr); +	unsigned char *(*skbuff_optptr)(const struct sk_buff *skb); +	int (*skbuff_setattr)(struct sk_buff *skb, +			      const struct calipso_doi *doi_def, +			      const struct netlbl_lsm_secattr *secattr); +	int (*skbuff_delattr)(struct sk_buff *skb); +	void (*cache_invalidate)(void); +	int (*cache_add)(const unsigned char *calipso_ptr, +			 const struct netlbl_lsm_secattr *secattr); +}; +  /*   * LSM security attribute operations (inline)   */ @@ -385,6 +445,14 @@ int netlbl_cfg_cipsov4_map_add(u32 doi,  			       const struct in_addr *addr,  			       const struct in_addr *mask,  			       struct netlbl_audit *audit_info); +int netlbl_cfg_calipso_add(struct calipso_doi *doi_def, +			   struct netlbl_audit *audit_info); +void netlbl_cfg_calipso_del(u32 doi, struct netlbl_audit *audit_info); +int netlbl_cfg_calipso_map_add(u32 doi, +			       const char *domain, +			       const struct in6_addr *addr, +			       const struct in6_addr *mask, +			       struct netlbl_audit *audit_info);  /*   * LSM security attribute operations   */ @@ -405,6 +473,12 @@ int netlbl_catmap_setlong(struct netlbl_lsm_catmap **catmap,  			  unsigned long bitmap,  			  gfp_t flags); +/* Bitmap functions + */ +int netlbl_bitmap_walk(const unsigned char *bitmap, u32 bitmap_len, +		       u32 offset, u8 state); +void netlbl_bitmap_setbit(unsigned char *bitmap, u32 bit, u8 state); +  /*   * LSM protocol operations (NetLabel LSM/kernel API)   */ @@ -427,13 +501,13 @@ int netlbl_skbuff_setattr(struct sk_buff *skb,  int netlbl_skbuff_getattr(const struct sk_buff *skb,  			  u16 family,  			  struct netlbl_lsm_secattr *secattr); -void netlbl_skbuff_err(struct sk_buff *skb, int error, int gateway); +void netlbl_skbuff_err(struct sk_buff *skb, u16 family, int error, int gateway);  /*   * LSM label mapping cache operations   */  void netlbl_cache_invalidate(void); -int netlbl_cache_add(const struct sk_buff *skb, +int netlbl_cache_add(const struct sk_buff *skb, u16 family,  		     const struct netlbl_lsm_secattr *secattr);  /* @@ -495,6 +569,24 @@ static inline int netlbl_cfg_cipsov4_map_add(u32 doi,  {  	return -ENOSYS;  } +static inline int netlbl_cfg_calipso_add(struct calipso_doi *doi_def, +					 struct netlbl_audit *audit_info) +{ +	return -ENOSYS; +} +static inline void netlbl_cfg_calipso_del(u32 doi, +					  struct netlbl_audit *audit_info) +{ +	return; +} +static inline int netlbl_cfg_calipso_map_add(u32 doi, +					     const char *domain, +					     const struct in6_addr *addr, +					     const struct in6_addr *mask, +					     struct netlbl_audit *audit_info) +{ +	return -ENOSYS; +}  static inline int netlbl_catmap_walk(struct netlbl_lsm_catmap *catmap,  				     u32 offset)  { @@ -586,7 +678,7 @@ static inline void netlbl_cache_invalidate(void)  {  	return;  } -static inline int netlbl_cache_add(const struct sk_buff *skb, +static inline int netlbl_cache_add(const struct sk_buff *skb, u16 family,  				   const struct netlbl_lsm_secattr *secattr)  {  	return 0; @@ -598,4 +690,7 @@ static inline struct audit_buffer *netlbl_audit_start(int type,  }  #endif /* CONFIG_NETLABEL */ +const struct netlbl_calipso_ops * +netlbl_calipso_ops_register(const struct netlbl_calipso_ops *ops); +  #endif /* _NETLABEL_H */ diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h index 0ae101eef0f4..74fa7eb94e72 100644 --- a/include/net/nfc/digital.h +++ b/include/net/nfc/digital.h @@ -220,12 +220,13 @@ struct nfc_digital_dev {  	struct list_head cmd_queue;  	struct mutex cmd_lock; -	struct work_struct poll_work; +	struct delayed_work poll_work;  	u8 curr_protocol;  	u8 curr_rf_tech;  	u8 curr_nfc_dep_pni;  	u8 did; +	u16 dep_rwt;  	u8 local_payload_max;  	u8 remote_payload_max; @@ -237,7 +238,6 @@ struct nfc_digital_dev {  	int nack_count;  	struct sk_buff *saved_skb; -	unsigned int saved_skb_len;  	u16 target_fsc; diff --git a/include/net/nfc/llc.h b/include/net/nfc/llc.h index c25fbdee0d61..7ecb45757897 100644 --- a/include/net/nfc/llc.h +++ b/include/net/nfc/llc.h @@ -37,10 +37,6 @@ struct nfc_llc *nfc_llc_allocate(const char *name, struct nfc_hci_dev *hdev,  				 int tx_tailroom, llc_failure_t llc_failure);  void nfc_llc_free(struct nfc_llc *llc); -void nfc_llc_get_rx_head_tail_room(struct nfc_llc *llc, int *rx_headroom, -				   int *rx_tailroom); - -  int nfc_llc_start(struct nfc_llc *llc);  int nfc_llc_stop(struct nfc_llc *llc);  void nfc_llc_rcv_from_drv(struct nfc_llc *llc, struct sk_buff *skb); diff --git a/include/net/nl802154.h b/include/net/nl802154.h index fcab4de49951..ddcee128f5d9 100644 --- a/include/net/nl802154.h +++ b/include/net/nl802154.h @@ -54,6 +54,8 @@ enum nl802154_commands {  	NL802154_CMD_SET_ACKREQ_DEFAULT, +	NL802154_CMD_SET_WPAN_PHY_NETNS, +  	/* add new commands above here */  #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL @@ -124,6 +126,11 @@ enum nl802154_attrs {  	NL802154_ATTR_ACKREQ_DEFAULT, +	NL802154_ATTR_PAD, + +	NL802154_ATTR_PID, +	NL802154_ATTR_NETNS_FD, +  	/* add attributes here, update the policy in nl802154.c */  #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL @@ -138,8 +145,6 @@ enum nl802154_attrs {  	NL802154_ATTR_SEC_KEY,  #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ -	NL802154_ATTR_PAD, -  	__NL802154_ATTR_AFTER_LAST,  	NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1  }; diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h index 3722dda0199d..6f8d65342d3a 100644 --- a/include/net/pkt_cls.h +++ b/include/net/pkt_cls.h @@ -442,4 +442,15 @@ struct tc_cls_flower_offload {  	struct tcf_exts *exts;  }; +enum tc_matchall_command { +	TC_CLSMATCHALL_REPLACE, +	TC_CLSMATCHALL_DESTROY, +}; + +struct tc_cls_matchall_offload { +	enum tc_matchall_command command; +	struct tcf_exts *exts; +	unsigned long cookie; +}; +  #endif diff --git a/include/net/pkt_sched.h b/include/net/pkt_sched.h index fea53f4d92ca..7caa99b482c6 100644 --- a/include/net/pkt_sched.h +++ b/include/net/pkt_sched.h @@ -67,12 +67,12 @@ struct qdisc_watchdog {  };  void qdisc_watchdog_init(struct qdisc_watchdog *wd, struct Qdisc *qdisc); -void qdisc_watchdog_schedule_ns(struct qdisc_watchdog *wd, u64 expires, bool throttle); +void qdisc_watchdog_schedule_ns(struct qdisc_watchdog *wd, u64 expires);  static inline void qdisc_watchdog_schedule(struct qdisc_watchdog *wd,  					   psched_time_t expires)  { -	qdisc_watchdog_schedule_ns(wd, PSCHED_TICKS2NS(expires), true); +	qdisc_watchdog_schedule_ns(wd, PSCHED_TICKS2NS(expires));  }  void qdisc_watchdog_cancel(struct qdisc_watchdog *wd); diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 006a7b81d758..4113916cc1bb 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -98,10 +98,11 @@ struct rtnl_link_ops {  						   const struct net_device *dev,  						   const struct net_device *slave_dev);  	struct net		*(*get_link_net)(const struct net_device *dev); -	size_t			(*get_linkxstats_size)(const struct net_device *dev); +	size_t			(*get_linkxstats_size)(const struct net_device *dev, +						       int attr);  	int			(*fill_linkxstats)(struct sk_buff *skb,  						   const struct net_device *dev, -						   int *prividx); +						   int *prividx, int attr);  };  int __rtnl_link_register(struct rtnl_link_ops *ops); diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 62d553184e91..909aff2db2b3 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -26,14 +26,6 @@ struct qdisc_rate_table {  enum qdisc_state_t {  	__QDISC_STATE_SCHED,  	__QDISC_STATE_DEACTIVATED, -	__QDISC_STATE_THROTTLED, -}; - -/* - * following bits are only changed while qdisc lock is held - */ -enum qdisc___state_t { -	__QDISC___STATE_RUNNING = 1,  };  struct qdisc_size_table { @@ -45,8 +37,10 @@ struct qdisc_size_table {  };  struct Qdisc { -	int 			(*enqueue)(struct sk_buff *skb, struct Qdisc *dev); -	struct sk_buff *	(*dequeue)(struct Qdisc *dev); +	int 			(*enqueue)(struct sk_buff *skb, +					   struct Qdisc *sch, +					   struct sk_buff **to_free); +	struct sk_buff *	(*dequeue)(struct Qdisc *sch);  	unsigned int		flags;  #define TCQ_F_BUILTIN		1  #define TCQ_F_INGRESS		2 @@ -70,31 +64,25 @@ struct Qdisc {  	struct list_head	list;  	u32			handle;  	u32			parent; -	int			(*reshape_fail)(struct sk_buff *skb, -					struct Qdisc *q); -  	void			*u32_node; -	/* This field is deprecated, but it is still used by CBQ -	 * and it will live until better solution will be invented. -	 */ -	struct Qdisc		*__parent;  	struct netdev_queue	*dev_queue;  	struct gnet_stats_rate_est64	rate_est;  	struct gnet_stats_basic_cpu __percpu *cpu_bstats;  	struct gnet_stats_queue	__percpu *cpu_qstats; -	struct Qdisc		*next_sched; -	struct sk_buff		*gso_skb;  	/*  	 * For performance sake on SMP, we put highly modified fields at the end  	 */ -	unsigned long		state; +	struct sk_buff		*gso_skb ____cacheline_aligned_in_smp;  	struct sk_buff_head	q;  	struct gnet_stats_basic_packed bstats; -	unsigned int		__state; +	seqcount_t		running;  	struct gnet_stats_queue	qstats; +	unsigned long		state; +	struct Qdisc            *next_sched; +	struct sk_buff		*skb_bad_txq;  	struct rcu_head		rcu_head;  	int			padded;  	atomic_t		refcnt; @@ -104,20 +92,24 @@ struct Qdisc {  static inline bool qdisc_is_running(const struct Qdisc *qdisc)  { -	return (qdisc->__state & __QDISC___STATE_RUNNING) ? true : false; +	return (raw_read_seqcount(&qdisc->running) & 1) ? true : false;  }  static inline bool qdisc_run_begin(struct Qdisc *qdisc)  {  	if (qdisc_is_running(qdisc))  		return false; -	qdisc->__state |= __QDISC___STATE_RUNNING; +	/* Variant of write_seqcount_begin() telling lockdep a trylock +	 * was attempted. +	 */ +	raw_write_seqcount_begin(&qdisc->running); +	seqcount_acquire(&qdisc->running.dep_map, 0, 1, _RET_IP_);  	return true;  }  static inline void qdisc_run_end(struct Qdisc *qdisc)  { -	qdisc->__state &= ~__QDISC___STATE_RUNNING; +	write_seqcount_end(&qdisc->running);  }  static inline bool qdisc_may_bulk(const struct Qdisc *qdisc) @@ -135,21 +127,6 @@ static inline int qdisc_avail_bulklimit(const struct netdev_queue *txq)  #endif  } -static inline bool qdisc_is_throttled(const struct Qdisc *qdisc) -{ -	return test_bit(__QDISC_STATE_THROTTLED, &qdisc->state) ? true : false; -} - -static inline void qdisc_throttled(struct Qdisc *qdisc) -{ -	set_bit(__QDISC_STATE_THROTTLED, &qdisc->state); -} - -static inline void qdisc_unthrottled(struct Qdisc *qdisc) -{ -	clear_bit(__QDISC_STATE_THROTTLED, &qdisc->state); -} -  struct Qdisc_class_ops {  	/* Child qdisc manipulation */  	struct netdev_queue *	(*select_queue)(struct Qdisc *, struct tcmsg *); @@ -186,10 +163,11 @@ struct Qdisc_ops {  	char			id[IFNAMSIZ];  	int			priv_size; -	int 			(*enqueue)(struct sk_buff *, struct Qdisc *); +	int 			(*enqueue)(struct sk_buff *skb, +					   struct Qdisc *sch, +					   struct sk_buff **to_free);  	struct sk_buff *	(*dequeue)(struct Qdisc *);  	struct sk_buff *	(*peek)(struct Qdisc *); -	unsigned int		(*drop)(struct Qdisc *);  	int			(*init)(struct Qdisc *, struct nlattr *arg);  	void			(*reset)(struct Qdisc *); @@ -322,6 +300,14 @@ static inline spinlock_t *qdisc_root_sleeping_lock(const struct Qdisc *qdisc)  	return qdisc_lock(root);  } +static inline seqcount_t *qdisc_root_sleeping_running(const struct Qdisc *qdisc) +{ +	struct Qdisc *root = qdisc_root_sleeping(qdisc); + +	ASSERT_RTNL(); +	return &root->running; +} +  static inline struct net_device *qdisc_dev(const struct Qdisc *qdisc)  {  	return qdisc->dev_queue->dev; @@ -517,10 +503,11 @@ static inline void qdisc_calculate_pkt_len(struct sk_buff *skb,  #endif  } -static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch) +static inline int qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch, +				struct sk_buff **to_free)  {  	qdisc_calculate_pkt_len(skb, sch); -	return sch->enqueue(skb, sch); +	return sch->enqueue(skb, sch, to_free);  }  static inline bool qdisc_is_percpu_stats(const struct Qdisc *q) @@ -645,40 +632,36 @@ static inline struct sk_buff *qdisc_dequeue_head(struct Qdisc *sch)  	return __qdisc_dequeue_head(sch, &sch->q);  } +/* Instead of calling kfree_skb() while root qdisc lock is held, + * queue the skb for future freeing at end of __dev_xmit_skb() + */ +static inline void __qdisc_drop(struct sk_buff *skb, struct sk_buff **to_free) +{ +	skb->next = *to_free; +	*to_free = skb; +} +  static inline unsigned int __qdisc_queue_drop_head(struct Qdisc *sch, -					      struct sk_buff_head *list) +						   struct sk_buff_head *list, +						   struct sk_buff **to_free)  {  	struct sk_buff *skb = __skb_dequeue(list);  	if (likely(skb != NULL)) {  		unsigned int len = qdisc_pkt_len(skb); +  		qdisc_qstats_backlog_dec(sch, skb); -		kfree_skb(skb); +		__qdisc_drop(skb, to_free);  		return len;  	}  	return 0;  } -static inline unsigned int qdisc_queue_drop_head(struct Qdisc *sch) -{ -	return __qdisc_queue_drop_head(sch, &sch->q); -} - -static inline struct sk_buff *__qdisc_dequeue_tail(struct Qdisc *sch, -						   struct sk_buff_head *list) -{ -	struct sk_buff *skb = __skb_dequeue_tail(list); - -	if (likely(skb != NULL)) -		qdisc_qstats_backlog_dec(sch, skb); - -	return skb; -} - -static inline struct sk_buff *qdisc_dequeue_tail(struct Qdisc *sch) +static inline unsigned int qdisc_queue_drop_head(struct Qdisc *sch, +						 struct sk_buff **to_free)  { -	return __qdisc_dequeue_tail(sch, &sch->q); +	return __qdisc_queue_drop_head(sch, &sch->q, to_free);  }  static inline struct sk_buff *qdisc_peek_head(struct Qdisc *sch) @@ -718,19 +701,21 @@ static inline struct sk_buff *qdisc_dequeue_peeked(struct Qdisc *sch)  	return skb;  } -static inline void __qdisc_reset_queue(struct Qdisc *sch, -				       struct sk_buff_head *list) +static inline void __qdisc_reset_queue(struct sk_buff_head *list)  {  	/*  	 * We do not know the backlog in bytes of this list, it  	 * is up to the caller to correct it  	 */ -	__skb_queue_purge(list); +	if (!skb_queue_empty(list)) { +		rtnl_kfree_skbs(list->next, list->prev); +		__skb_queue_head_init(list); +	}  }  static inline void qdisc_reset_queue(struct Qdisc *sch)  { -	__qdisc_reset_queue(sch, &sch->q); +	__qdisc_reset_queue(&sch->q);  	sch->qstats.backlog = 0;  } @@ -751,46 +736,19 @@ static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,  	return old;  } -static inline unsigned int __qdisc_queue_drop(struct Qdisc *sch, -					      struct sk_buff_head *list) +static inline void rtnl_qdisc_drop(struct sk_buff *skb, struct Qdisc *sch)  { -	struct sk_buff *skb = __qdisc_dequeue_tail(sch, list); - -	if (likely(skb != NULL)) { -		unsigned int len = qdisc_pkt_len(skb); -		kfree_skb(skb); -		return len; -	} - -	return 0; -} - -static inline unsigned int qdisc_queue_drop(struct Qdisc *sch) -{ -	return __qdisc_queue_drop(sch, &sch->q); -} - -static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch) -{ -	kfree_skb(skb); +	rtnl_kfree_skbs(skb, skb);  	qdisc_qstats_drop(sch); - -	return NET_XMIT_DROP;  } -static inline int qdisc_reshape_fail(struct sk_buff *skb, struct Qdisc *sch) + +static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch, +			     struct sk_buff **to_free)  { +	__qdisc_drop(skb, to_free);  	qdisc_qstats_drop(sch); -#ifdef CONFIG_NET_CLS_ACT -	if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) -		goto drop; - -	return NET_XMIT_SUCCESS; - -drop: -#endif -	kfree_skb(skb);  	return NET_XMIT_DROP;  } diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index b392ac8382f2..632e205ca54b 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -186,6 +186,10 @@ void sctp_assocs_proc_exit(struct net *net);  int sctp_remaddr_proc_init(struct net *net);  void sctp_remaddr_proc_exit(struct net *net); +/* + * sctp/offload.c + */ +int sctp_offload_init(void);  /*   * Module global variables diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 16b013a6191c..ce93c4b10d26 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -59,6 +59,7 @@  #include <linux/workqueue.h>	/* We need tq_struct.	 */  #include <linux/sctp.h>		/* We need sctp* header structs.  */  #include <net/sctp/auth.h>	/* We need auth specific structs */ +#include <net/ip.h>		/* For inet_skb_parm */  /* A convenience structure for handling sockaddr structures.   * We should wean ourselves off this. @@ -566,6 +567,9 @@ struct sctp_chunk {  	/* This points to the sk_buff containing the actual data.  */  	struct sk_buff *skb; +	/* In case of GSO packets, this will store the head one */ +	struct sk_buff *head_skb; +  	/* These are the SCTP headers by reverse order in a packet.  	 * Note that some of these may happen more than once.  In that  	 * case, we point at the "current" one, whatever that means @@ -599,6 +603,16 @@ struct sctp_chunk {  	/* This needs to be recoverable for SCTP_SEND_FAILED events. */  	struct sctp_sndrcvinfo sinfo; +	/* We use this field to record param for prsctp policies, +	 * for TTL policy, it is the time_to_drop of this chunk, +	 * for RTX policy, it is the max_sent_count of this chunk, +	 * for PRIO policy, it is the priority of this chunk. +	 */ +	unsigned long prsctp_param; + +	/* How many times this chunk have been sent, for prsctp RTX policy */ +	int sent_count; +  	/* Which association does this belong to?  */  	struct sctp_association *asoc; @@ -696,6 +710,8 @@ struct sctp_packet {  	size_t overhead;  	/* This is the total size of all chunks INCLUDING padding.  */  	size_t size; +	/* This is the maximum size this packet may have */ +	size_t max_size;  	/* The packet is destined for this transport address.  	 * The function we finally use to pass down to the next lower @@ -1069,12 +1085,36 @@ void sctp_retransmit(struct sctp_outq *, struct sctp_transport *,  		     sctp_retransmit_reason_t);  void sctp_retransmit_mark(struct sctp_outq *, struct sctp_transport *, __u8);  int sctp_outq_uncork(struct sctp_outq *, gfp_t gfp); +void sctp_prsctp_prune(struct sctp_association *asoc, +		       struct sctp_sndrcvinfo *sinfo, int msg_len);  /* Uncork and flush an outqueue.  */  static inline void sctp_outq_cork(struct sctp_outq *q)  {  	q->cork = 1;  } +/* SCTP skb control block. + * sctp_input_cb is currently used on rx and sock rx queue + */ +struct sctp_input_cb { +	union { +		struct inet_skb_parm	h4; +#if IS_ENABLED(CONFIG_IPV6) +		struct inet6_skb_parm	h6; +#endif +	} header; +	struct sctp_chunk *chunk; +	struct sctp_af *af; +}; +#define SCTP_INPUT_CB(__skb)	((struct sctp_input_cb *)&((__skb)->cb[0])) + +static inline const struct sk_buff *sctp_gso_headskb(const struct sk_buff *skb) +{ +	const struct sctp_chunk *chunk = SCTP_INPUT_CB(skb)->chunk; + +	return chunk->head_skb ? : skb; +} +  /* These bind address data fields common between endpoints and associations */  struct sctp_bind_addr { @@ -1251,7 +1291,8 @@ struct sctp_endpoint {  	/* SCTP-AUTH: endpoint shared keys */  	struct list_head endpoint_shared_keys;  	__u16 active_key_id; -	__u8  auth_enable; +	__u8  auth_enable:1, +	      prsctp_enable:1;  };  /* Recover the outter endpoint structure. */ @@ -1843,9 +1884,15 @@ struct sctp_association {  	__u16 active_key_id;  	__u8 need_ecne:1,	/* Need to send an ECNE Chunk? */ -	     temp:1;		/* Is it a temporary association? */ +	     temp:1,		/* Is it a temporary association? */ +	     prsctp_enable:1;  	struct sctp_priv_assoc_stats stats; + +	int sent_cnt_removable; + +	__u64 abandoned_unsent[SCTP_PR_INDEX(MAX) + 1]; +	__u64 abandoned_sent[SCTP_PR_INDEX(MAX) + 1];  }; diff --git a/include/net/sctp/ulpevent.h b/include/net/sctp/ulpevent.h index cccdcfd14973..2c098cd7e7e2 100644 --- a/include/net/sctp/ulpevent.h +++ b/include/net/sctp/ulpevent.h @@ -48,15 +48,15 @@   */  struct sctp_ulpevent {  	struct sctp_association *asoc; -	__u16 stream; -	__u16 ssn; -	__u16 flags; +	struct sctp_chunk *chunk; +	unsigned int rmem_len;  	__u32 ppid;  	__u32 tsn;  	__u32 cumtsn; -	int msg_flags; -	int iif; -	unsigned int rmem_len; +	__u16 stream; +	__u16 ssn; +	__u16 flags; +	__u16 msg_flags;  };  /* Retrieve the skb this event sits inside of. */ diff --git a/include/net/sock.h b/include/net/sock.h index 649d2a8c17fc..ff5be7e8ddea 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1576,7 +1576,13 @@ static inline void sock_put(struct sock *sk)   */  void sock_gen_put(struct sock *sk); -int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested); +int __sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested, +		     unsigned int trim_cap); +static inline int sk_receive_skb(struct sock *sk, struct sk_buff *skb, +				 const int nested) +{ +	return __sk_receive_skb(sk, skb, nested, 1); +}  static inline void sk_tx_queue_set(struct sock *sk, int tx_queue)  { diff --git a/include/net/switchdev.h b/include/net/switchdev.h index 985619a59323..62f6a967a1b7 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -60,7 +60,7 @@ struct switchdev_attr {  		struct netdev_phys_item_id ppid;	/* PORT_PARENT_ID */  		u8 stp_state;				/* PORT_STP_STATE */  		unsigned long brport_flags;		/* PORT_BRIDGE_FLAGS */ -		u32 ageing_time;			/* BRIDGE_AGEING_TIME */ +		clock_t ageing_time;			/* BRIDGE_AGEING_TIME */  		bool vlan_filtering;			/* BRIDGE_VLAN_FILTERING */  	} u;  }; @@ -227,6 +227,8 @@ void switchdev_port_fwd_mark_set(struct net_device *dev,  				 struct net_device *group_dev,  				 bool joining); +bool switchdev_port_same_parent_id(struct net_device *a, +				   struct net_device *b);  #else  static inline void switchdev_deferred_process(void) @@ -351,6 +353,12 @@ static inline void switchdev_port_fwd_mark_set(struct net_device *dev,  {  } +static inline bool switchdev_port_same_parent_id(struct net_device *a, +						 struct net_device *b) +{ +	return false; +} +  #endif  #endif /* _LINUX_SWITCHDEV_H_ */ diff --git a/include/net/tc_act/tc_bpf.h b/include/net/tc_act/tc_bpf.h index 958d69cfb19c..2b94673a3dbc 100644 --- a/include/net/tc_act/tc_bpf.h +++ b/include/net/tc_act/tc_bpf.h @@ -14,7 +14,7 @@  #include <net/act_api.h>  struct tcf_bpf { -	struct tcf_common	common; +	struct tc_action	common;  	struct bpf_prog __rcu	*filter;  	union {  		u32		bpf_fd; @@ -23,7 +23,6 @@ struct tcf_bpf {  	struct sock_filter	*bpf_ops;  	const char		*bpf_name;  }; -#define to_bpf(a) \ -	container_of(a->priv, struct tcf_bpf, common) +#define to_bpf(a) ((struct tcf_bpf *)a)  #endif /* __NET_TC_BPF_H */ diff --git a/include/net/tc_act/tc_connmark.h b/include/net/tc_act/tc_connmark.h index 02caa406611b..59b515d32bb4 100644 --- a/include/net/tc_act/tc_connmark.h +++ b/include/net/tc_act/tc_connmark.h @@ -4,12 +4,11 @@  #include <net/act_api.h>  struct tcf_connmark_info { -	struct tcf_common common; +	struct tc_action common;  	struct net *net;  	u16 zone;  }; -#define to_connmark(a) \ -	container_of(a->priv, struct tcf_connmark_info, common) +#define to_connmark(a) ((struct tcf_connmark_info *)a)  #endif /* __NET_TC_CONNMARK_H */ diff --git a/include/net/tc_act/tc_csum.h b/include/net/tc_act/tc_csum.h index fa8f5fac65e9..f31fb6331a53 100644 --- a/include/net/tc_act/tc_csum.h +++ b/include/net/tc_act/tc_csum.h @@ -5,11 +5,10 @@  #include <net/act_api.h>  struct tcf_csum { -	struct tcf_common common; +	struct tc_action common;  	u32 update_flags;  }; -#define to_tcf_csum(a) \ -	container_of(a->priv,struct tcf_csum,common) +#define to_tcf_csum(a) ((struct tcf_csum *)a)  #endif /* __NET_TC_CSUM_H */ diff --git a/include/net/tc_act/tc_defact.h b/include/net/tc_act/tc_defact.h index 9763dcbb9bc3..d47f040a3bdf 100644 --- a/include/net/tc_act/tc_defact.h +++ b/include/net/tc_act/tc_defact.h @@ -4,11 +4,10 @@  #include <net/act_api.h>  struct tcf_defact { -	struct tcf_common	common; -	u32     		tcfd_datalen; -	void    		*tcfd_defdata; +	struct tc_action	common; +	u32		tcfd_datalen; +	void		*tcfd_defdata;  }; -#define to_defact(a) \ -	container_of(a->priv, struct tcf_defact, common) +#define to_defact(a) ((struct tcf_defact *)a)  #endif /* __NET_TC_DEF_H */ diff --git a/include/net/tc_act/tc_gact.h b/include/net/tc_act/tc_gact.h index 93c520b83d10..b6f173910226 100644 --- a/include/net/tc_act/tc_gact.h +++ b/include/net/tc_act/tc_gact.h @@ -5,7 +5,7 @@  #include <linux/tc_act/tc_gact.h>  struct tcf_gact { -	struct tcf_common	common; +	struct tc_action	common;  #ifdef CONFIG_GACT_PROB  	u16			tcfg_ptype;  	u16			tcfg_pval; @@ -13,8 +13,7 @@ struct tcf_gact {  	atomic_t		packets;  #endif  }; -#define to_gact(a) \ -	container_of(a->priv, struct tcf_gact, common) +#define to_gact(a) ((struct tcf_gact *)a)  static inline bool is_tcf_gact_shot(const struct tc_action *a)  { @@ -24,7 +23,7 @@ static inline bool is_tcf_gact_shot(const struct tc_action *a)  	if (a->ops && a->ops->type != TCA_ACT_GACT)  		return false; -	gact = a->priv; +	gact = to_gact(a);  	if (gact->tcf_action == TC_ACT_SHOT)  		return true; diff --git a/include/net/tc_act/tc_ife.h b/include/net/tc_act/tc_ife.h index dc9a09aefb33..5164bd7a38fb 100644 --- a/include/net/tc_act/tc_ife.h +++ b/include/net/tc_act/tc_ife.h @@ -8,7 +8,7 @@  #define IFE_METAHDRLEN 2  struct tcf_ife_info { -	struct tcf_common common; +	struct tc_action common;  	u8 eth_dst[ETH_ALEN];  	u8 eth_src[ETH_ALEN];  	u16 eth_type; @@ -16,8 +16,7 @@ struct tcf_ife_info {  	/* list of metaids allowed */  	struct list_head metalist;  }; -#define to_ife(a) \ -	container_of(a->priv, struct tcf_ife_info, common) +#define to_ife(a) ((struct tcf_ife_info *)a)  struct tcf_meta_info {  	const struct tcf_meta_ops *ops; @@ -36,7 +35,7 @@ struct tcf_meta_ops {  	int	(*encode)(struct sk_buff *, void *, struct tcf_meta_info *);  	int	(*decode)(struct sk_buff *, void *, u16 len);  	int	(*get)(struct sk_buff *skb, struct tcf_meta_info *mi); -	int	(*alloc)(struct tcf_meta_info *, void *); +	int	(*alloc)(struct tcf_meta_info *, void *, gfp_t);  	void	(*release)(struct tcf_meta_info *);  	int	(*validate)(void *val, int len);  	struct module	*owner; @@ -48,8 +47,8 @@ int ife_get_meta_u32(struct sk_buff *skb, struct tcf_meta_info *mi);  int ife_get_meta_u16(struct sk_buff *skb, struct tcf_meta_info *mi);  int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen,  			const void *dval); -int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval); -int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval); +int ife_alloc_meta_u32(struct tcf_meta_info *mi, void *metaval, gfp_t gfp); +int ife_alloc_meta_u16(struct tcf_meta_info *mi, void *metaval, gfp_t gfp);  int ife_check_meta_u32(u32 metaval, struct tcf_meta_info *mi);  int ife_encode_meta_u32(u32 metaval, void *skbdata, struct tcf_meta_info *mi);  int ife_validate_meta_u32(void *val, int len); diff --git a/include/net/tc_act/tc_ipt.h b/include/net/tc_act/tc_ipt.h index c0f4193f432c..31309766e379 100644 --- a/include/net/tc_act/tc_ipt.h +++ b/include/net/tc_act/tc_ipt.h @@ -6,12 +6,11 @@  struct xt_entry_target;  struct tcf_ipt { -	struct tcf_common	common; +	struct tc_action	common;  	u32			tcfi_hook;  	char			*tcfi_tname;  	struct xt_entry_target	*tcfi_t;  }; -#define to_ipt(a) \ -	container_of(a->priv, struct tcf_ipt, common) +#define to_ipt(a) ((struct tcf_ipt *)a)  #endif /* __NET_TC_IPT_H */ diff --git a/include/net/tc_act/tc_mirred.h b/include/net/tc_act/tc_mirred.h index e891835eb74e..62770add15bd 100644 --- a/include/net/tc_act/tc_mirred.h +++ b/include/net/tc_act/tc_mirred.h @@ -5,15 +5,14 @@  #include <linux/tc_act/tc_mirred.h>  struct tcf_mirred { -	struct tcf_common	common; +	struct tc_action	common;  	int			tcfm_eaction;  	int			tcfm_ifindex;  	int			tcfm_ok_push;  	struct net_device __rcu	*tcfm_dev;  	struct list_head	tcfm_list;  }; -#define to_mirred(a) \ -	container_of(a->priv, struct tcf_mirred, common) +#define to_mirred(a) ((struct tcf_mirred *)a)  static inline bool is_tcf_mirred_redirect(const struct tc_action *a)  { @@ -24,6 +23,15 @@ static inline bool is_tcf_mirred_redirect(const struct tc_action *a)  	return false;  } +static inline bool is_tcf_mirred_mirror(const struct tc_action *a) +{ +#ifdef CONFIG_NET_CLS_ACT +	if (a->ops && a->ops->type == TCA_ACT_MIRRED) +		return to_mirred(a)->tcfm_eaction == TCA_EGRESS_MIRROR; +#endif +	return false; +} +  static inline int tcf_mirred_ifindex(const struct tc_action *a)  {  	return to_mirred(a)->tcfm_ifindex; diff --git a/include/net/tc_act/tc_nat.h b/include/net/tc_act/tc_nat.h index 63d8e9ca9d99..56681a320612 100644 --- a/include/net/tc_act/tc_nat.h +++ b/include/net/tc_act/tc_nat.h @@ -5,7 +5,7 @@  #include <net/act_api.h>  struct tcf_nat { -	struct tcf_common common; +	struct tc_action common;  	__be32 old_addr;  	__be32 new_addr; @@ -13,9 +13,6 @@ struct tcf_nat {  	u32 flags;  }; -static inline struct tcf_nat *to_tcf_nat(struct tc_action *a) -{ -	return container_of(a->priv, struct tcf_nat, common); -} +#define to_tcf_nat(a) ((struct tcf_nat *)a)  #endif /* __NET_TC_NAT_H */ diff --git a/include/net/tc_act/tc_pedit.h b/include/net/tc_act/tc_pedit.h index 5b80998879c7..29e38d6823df 100644 --- a/include/net/tc_act/tc_pedit.h +++ b/include/net/tc_act/tc_pedit.h @@ -4,12 +4,11 @@  #include <net/act_api.h>  struct tcf_pedit { -	struct tcf_common	common; +	struct tc_action	common;  	unsigned char		tcfp_nkeys;  	unsigned char		tcfp_flags;  	struct tc_pedit_key	*tcfp_keys;  }; -#define to_pedit(a) \ -	container_of(a->priv, struct tcf_pedit, common) +#define to_pedit(a) ((struct tcf_pedit *)a)  #endif /* __NET_TC_PED_H */ diff --git a/include/net/tc_act/tc_skbedit.h b/include/net/tc_act/tc_skbedit.h index b496d5ad7d42..5767e9dbcf92 100644 --- a/include/net/tc_act/tc_skbedit.h +++ b/include/net/tc_act/tc_skbedit.h @@ -23,15 +23,14 @@  #include <linux/tc_act/tc_skbedit.h>  struct tcf_skbedit { -	struct tcf_common	common; -	u32			flags; -	u32     		priority; -	u32     		mark; -	u16			queue_mapping; -	/* XXX: 16-bit pad here? */ +	struct tc_action	common; +	u32		flags; +	u32		priority; +	u32		mark; +	u16		queue_mapping; +	u16		ptype;  }; -#define to_skbedit(a) \ -	container_of(a->priv, struct tcf_skbedit, common) +#define to_skbedit(a) ((struct tcf_skbedit *)a)  /* Return true iff action is mark */  static inline bool is_tcf_skbedit_mark(const struct tc_action *a) diff --git a/include/net/tc_act/tc_vlan.h b/include/net/tc_act/tc_vlan.h index 93b70ade1ff3..e29f52e8bdf1 100644 --- a/include/net/tc_act/tc_vlan.h +++ b/include/net/tc_act/tc_vlan.h @@ -16,12 +16,11 @@  #define VLAN_F_PUSH		0x2  struct tcf_vlan { -	struct tcf_common	common; +	struct tc_action	common;  	int			tcfv_action;  	u16			tcfv_push_vid;  	__be16			tcfv_push_proto;  }; -#define to_vlan(a) \ -	container_of(a->priv, struct tcf_vlan, common) +#define to_vlan(a) ((struct tcf_vlan *)a)  #endif /* __NET_TC_VLAN_H */ diff --git a/include/net/tcp.h b/include/net/tcp.h index 0bcc70f4e1fb..c00e7d51bb18 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -589,7 +589,7 @@ static inline int tcp_bound_to_half_wnd(struct tcp_sock *tp, int pktsize)  	 * On the other hand, for extremely large MSS devices, handling  	 * smaller than MSS windows in this way does make sense.  	 */ -	if (tp->max_window >= 512) +	if (tp->max_window > TCP_MSS_DEFAULT)  		cutoff = (tp->max_window >> 1);  	else  		cutoff = tp->max_window; @@ -767,6 +767,7 @@ struct tcp_skb_cb {  	union {  		struct {  			/* There is space for up to 20 bytes */ +			__u32 in_flight;/* Bytes in flight when packet sent */  		} tx;   /* only used for outgoing skbs */  		union {  			struct inet_skb_parm	h4; @@ -859,6 +860,7 @@ union tcp_cc_info;  struct ack_sample {  	u32 pkts_acked;  	s32 rtt_us; +	u32 in_flight;  };  struct tcp_congestion_ops { @@ -1382,7 +1384,7 @@ union tcp_md5sum_block {  /* - pool: digest algorithm, hash description and scratch buffer */  struct tcp_md5sig_pool {  	struct ahash_request	*md5_req; -	union tcp_md5sum_block	md5_blk; +	void			*scratch;  };  /* - functions */ @@ -1418,7 +1420,6 @@ static inline void tcp_put_md5sig_pool(void)  	local_bh_enable();  } -int tcp_md5_hash_header(struct tcp_md5sig_pool *, const struct tcphdr *);  int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, const struct sk_buff *,  			  unsigned int header_len);  int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, diff --git a/include/net/udp.h b/include/net/udp.h index ae07f375370d..8894d7144189 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -160,8 +160,8 @@ void udp_set_csum(bool nocheck, struct sk_buff *skb,  static inline void udp_csum_pull_header(struct sk_buff *skb)  { -	if (skb->ip_summed == CHECKSUM_NONE) -		skb->csum = csum_partial(udp_hdr(skb), sizeof(struct udphdr), +	if (!skb->csum_valid && skb->ip_summed == CHECKSUM_NONE) +		skb->csum = csum_partial(skb->data, sizeof(struct udphdr),  					 skb->csum);  	skb_pull_rcsum(skb, sizeof(struct udphdr));  	UDP_SKB_CB(skb)->cscov -= sizeof(struct udphdr); diff --git a/include/net/udp_tunnel.h b/include/net/udp_tunnel.h index 9d14f707e534..02c5be037451 100644 --- a/include/net/udp_tunnel.h +++ b/include/net/udp_tunnel.h @@ -84,6 +84,46 @@ struct udp_tunnel_sock_cfg {  void setup_udp_tunnel_sock(struct net *net, struct socket *sock,  			   struct udp_tunnel_sock_cfg *sock_cfg); +/* -- List of parsable UDP tunnel types -- + * + * Adding to this list will result in serious debate.  The main issue is + * that this list is essentially a list of workarounds for either poorly + * designed tunnels, or poorly designed device offloads. + * + * The parsing supported via these types should really be used for Rx + * traffic only as the network stack will have already inserted offsets for + * the location of the headers in the skb.  In addition any ports that are + * pushed should be kept within the namespace without leaking to other + * devices such as VFs or other ports on the same device. + * + * It is strongly encouraged to use CHECKSUM_COMPLETE for Rx to avoid the + * need to use this for Rx checksum offload.  It should not be necessary to + * call this function to perform Tx offloads on outgoing traffic. + */ +enum udp_parsable_tunnel_type { +	UDP_TUNNEL_TYPE_VXLAN,		/* RFC 7348 */ +	UDP_TUNNEL_TYPE_GENEVE,		/* draft-ietf-nvo3-geneve */ +	UDP_TUNNEL_TYPE_VXLAN_GPE,	/* draft-ietf-nvo3-vxlan-gpe */ +}; + +struct udp_tunnel_info { +	unsigned short type; +	sa_family_t sa_family; +	__be16 port; +}; + +/* Notify network devices of offloadable types */ +void udp_tunnel_push_rx_port(struct net_device *dev, struct socket *sock, +			     unsigned short type); +void udp_tunnel_notify_add_rx_port(struct socket *sock, unsigned short type); +void udp_tunnel_notify_del_rx_port(struct socket *sock, unsigned short type); + +static inline void udp_tunnel_get_rx_info(struct net_device *dev) +{ +	ASSERT_RTNL(); +	call_netdevice_notifiers(NETDEV_UDP_TUNNEL_PUSH_INFO, dev); +} +  /* Transmit the skb using UDP encapsulation. */  void udp_tunnel_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *skb,  			 __be32 src, __be32 dst, __u8 tos, __u8 ttl, @@ -105,12 +145,14 @@ struct metadata_dst *udp_tun_rx_dst(struct sk_buff *skb, unsigned short family,  				    __be16 flags, __be64 tunnel_id,  				    int md_size); +#ifdef CONFIG_INET  static inline int udp_tunnel_handle_offloads(struct sk_buff *skb, bool udp_csum)  {  	int type = udp_csum ? SKB_GSO_UDP_TUNNEL_CSUM : SKB_GSO_UDP_TUNNEL;  	return iptunnel_handle_offloads(skb, type);  } +#endif  static inline void udp_tunnel_encap_enable(struct socket *sock)  { diff --git a/include/net/vxlan.h b/include/net/vxlan.h index b8803165df91..b96d0360c095 100644 --- a/include/net/vxlan.h +++ b/include/net/vxlan.h @@ -1,13 +1,10 @@  #ifndef __NET_VXLAN_H  #define __NET_VXLAN_H 1 -#include <linux/ip.h> -#include <linux/ipv6.h>  #include <linux/if_vlan.h> -#include <linux/skbuff.h> -#include <linux/netdevice.h> -#include <linux/udp.h> +#include <net/udp_tunnel.h>  #include <net/dst_metadata.h> +#include <net/udp_tunnel.h>  /* VXLAN protocol (RFC 7348) header:   * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ @@ -392,12 +389,6 @@ static inline __be32 vxlan_compute_rco(unsigned int start, unsigned int offset)  	return vni_field;  } -static inline void vxlan_get_rx_port(struct net_device *netdev) -{ -	ASSERT_RTNL(); -	call_netdevice_notifiers(NETDEV_OFFLOAD_PUSH_VXLAN, netdev); -} -  static inline unsigned short vxlan_get_sk_family(struct vxlan_sock *vs)  {  	return vs->sock->sk->sk_family; |