diff options
Diffstat (limited to 'include/net')
30 files changed, 610 insertions, 87 deletions
diff --git a/include/net/af_unix.h b/include/net/af_unix.h index 91ab5b0..63b1781 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -11,10 +11,13 @@ extern void unix_notinflight(struct file *fp); extern void unix_gc(void); extern void wait_for_unix_gc(void); extern struct sock *unix_get_socket(struct file *filp); +extern struct sock *unix_peer_get(struct sock *); #define UNIX_HASH_SIZE 256 extern unsigned int unix_tot_inflight; +extern spinlock_t unix_table_lock; +extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; struct unix_address { atomic_t refcnt; diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 835f3b2..980e59f 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -36,6 +36,11 @@ #define PF_BLUETOOTH AF_BLUETOOTH #endif +/* Bluetooth versions */ +#define BLUETOOTH_VER_1_1 1 +#define BLUETOOTH_VER_1_2 2 +#define BLUETOOTH_VER_2_0 3 + /* Reserv for core and drivers use */ #define BT_SKB_RESERVE 8 diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 139ce2a..67ad984 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -88,6 +88,14 @@ enum { HCI_RESET, }; +/* + * BR/EDR and/or LE controller flags: the flags defined here should represent + * states from the controller. + */ +enum { + HCI_LE_SCAN, +}; + /* HCI ioctl defines */ #define HCIDEVUP _IOW('H', 201, int) #define HCIDEVDOWN _IOW('H', 202, int) @@ -453,6 +461,14 @@ struct hci_rp_user_confirm_reply { #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d +#define HCI_OP_USER_PASSKEY_REPLY 0x042e +struct hci_cp_user_passkey_reply { + bdaddr_t bdaddr; + __le32 passkey; +} __packed; + +#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f + #define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 struct hci_cp_remote_oob_data_reply { bdaddr_t bdaddr; @@ -669,6 +685,12 @@ struct hci_rp_read_local_oob_data { #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 +#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 +struct hci_rp_read_flow_control_mode { + __u8 status; + __u8 mode; +} __packed; + #define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d struct hci_cp_write_le_host_supported { __u8 le; @@ -760,6 +782,15 @@ struct hci_rp_le_read_buffer_size { __u8 le_max_pkt; } __packed; +#define HCI_OP_LE_SET_SCAN_PARAM 0x200b +struct hci_cp_le_set_scan_param { + __u8 type; + __le16 interval; + __le16 window; + __u8 own_address_type; + __u8 filter_policy; +} __packed; + #define HCI_OP_LE_SET_SCAN_ENABLE 0x200c struct hci_cp_le_set_scan_enable { __u8 enable; @@ -1076,6 +1107,11 @@ struct hci_ev_user_confirm_req { __le32 passkey; } __packed; +#define HCI_EV_USER_PASSKEY_REQUEST 0x34 +struct hci_ev_user_passkey_req { + bdaddr_t bdaddr; +} __packed; + #define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 struct hci_ev_remote_oob_data_request { bdaddr_t bdaddr; @@ -1331,4 +1367,6 @@ struct hci_inquiry_req { }; #define IREQ_CACHE_FLUSH 0x0001 +extern int enable_hs; + #endif /* __HCI_H */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index f333e76..ea4395f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -170,6 +170,8 @@ struct hci_dev { __u32 amp_max_flush_to; __u32 amp_be_flush_to; + __u8 flow_ctl_mode; + unsigned int auto_accept_delay; unsigned long quirks; @@ -250,6 +252,8 @@ struct hci_dev { struct module *owner; + unsigned long dev_flags; + int (*open)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); @@ -917,11 +921,13 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable); int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, u8 persistent); -int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); -int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); -int mgmt_disconnect_failed(struct hci_dev *hdev); -int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, - u8 status); +int mgmt_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type); +int mgmt_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type); +int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); +int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, u8 status); int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); @@ -933,14 +939,20 @@ int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); +int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr); +int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 status); +int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, + bdaddr_t *bdaddr, u8 status); int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 status); int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, u8 *randomizer, u8 status); -int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, - u8 *dev_class, s8 rssi, u8 *eir); +int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, u8 *dev_class, s8 rssi, u8 *eir); int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *name); -int mgmt_inquiry_failed(struct hci_dev *hdev, u8 status); +int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status); +int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status); int mgmt_discovering(struct hci_dev *hdev, u8 discovering); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 875021a..72632f1 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -791,8 +791,7 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan) return L2CAP_ENH_HDR_SIZE - L2CAP_HDR_SIZE; } -extern int disable_ertm; -extern int enable_hs; +extern bool disable_ertm; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); @@ -810,5 +809,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u32 priority); void l2cap_chan_busy(struct l2cap_chan *chan, int busy); +int l2cap_chan_check_security(struct l2cap_chan *chan); #endif /* __L2CAP_H */ diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 3e320c9..3b68806 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -23,6 +23,23 @@ #define MGMT_INDEX_NONE 0xFFFF +#define MGMT_STATUS_SUCCESS 0x00 +#define MGMT_STATUS_UNKNOWN_COMMAND 0x01 +#define MGMT_STATUS_NOT_CONNECTED 0x02 +#define MGMT_STATUS_FAILED 0x03 +#define MGMT_STATUS_CONNECT_FAILED 0x04 +#define MGMT_STATUS_AUTH_FAILED 0x05 +#define MGMT_STATUS_NOT_PAIRED 0x06 +#define MGMT_STATUS_NO_RESOURCES 0x07 +#define MGMT_STATUS_TIMEOUT 0x08 +#define MGMT_STATUS_ALREADY_CONNECTED 0x09 +#define MGMT_STATUS_BUSY 0x0a +#define MGMT_STATUS_REJECTED 0x0b +#define MGMT_STATUS_NOT_SUPPORTED 0x0c +#define MGMT_STATUS_INVALID_PARAMS 0x0d +#define MGMT_STATUS_DISCONNECTED 0x0e +#define MGMT_STATUS_NOT_POWERED 0x0f + struct mgmt_hdr { __le16 opcode; __le16 index; @@ -119,6 +136,10 @@ struct mgmt_cp_remove_keys { bdaddr_t bdaddr; __u8 disconnect; } __packed; +struct mgmt_rp_remove_keys { + bdaddr_t bdaddr; + __u8 status; +}; #define MGMT_OP_DISCONNECT 0x000F struct mgmt_cp_disconnect { @@ -126,11 +147,12 @@ struct mgmt_cp_disconnect { } __packed; struct mgmt_rp_disconnect { bdaddr_t bdaddr; + __u8 status; } __packed; #define MGMT_ADDR_BREDR 0x00 -#define MGMT_ADDR_LE 0x01 -#define MGMT_ADDR_BREDR_LE 0x02 +#define MGMT_ADDR_LE_PUBLIC 0x01 +#define MGMT_ADDR_LE_RANDOM 0x02 #define MGMT_ADDR_INVALID 0xff struct mgmt_addr_info { @@ -167,11 +189,11 @@ struct mgmt_cp_set_io_capability { #define MGMT_OP_PAIR_DEVICE 0x0014 struct mgmt_cp_pair_device { - bdaddr_t bdaddr; + struct mgmt_addr_info addr; __u8 io_cap; } __packed; struct mgmt_rp_pair_device { - bdaddr_t bdaddr; + struct mgmt_addr_info addr; __u8 status; } __packed; @@ -210,6 +232,9 @@ struct mgmt_cp_remove_remote_oob_data { } __packed; #define MGMT_OP_START_DISCOVERY 0x001B +struct mgmt_cp_start_discovery { + __u8 type; +} __packed; #define MGMT_OP_STOP_DISCOVERY 0x001C @@ -228,6 +253,17 @@ struct mgmt_cp_set_fast_connectable { __u8 enable; } __packed; +#define MGMT_OP_USER_PASSKEY_REPLY 0x0020 +struct mgmt_cp_user_passkey_reply { + bdaddr_t bdaddr; + __le32 passkey; +} __packed; + +#define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021 +struct mgmt_cp_user_passkey_neg_reply { + bdaddr_t bdaddr; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -322,3 +358,8 @@ struct mgmt_ev_device_blocked { struct mgmt_ev_device_unblocked { bdaddr_t bdaddr; } __packed; + +#define MGMT_EV_USER_PASSKEY_REQUEST 0x0017 +struct mgmt_ev_user_passkey_request { + bdaddr_t bdaddr; +} __packed; diff --git a/include/net/caif/caif_spi.h b/include/net/caif/caif_spi.h index 87c3d11..aa6a485 100644 --- a/include/net/caif/caif_spi.h +++ b/include/net/caif/caif_spi.h @@ -55,8 +55,8 @@ struct cfspi_xfer { u16 tx_dma_len; u16 rx_dma_len; - void *va_tx; - dma_addr_t pa_tx; + void *va_tx[2]; + dma_addr_t pa_tx[2]; void *va_rx; dma_addr_t pa_rx; }; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d5e1891..9f85fca 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -782,6 +782,7 @@ struct mesh_config { u16 min_discovery_timeout; u32 dot11MeshHWMPactivePathTimeout; u16 dot11MeshHWMPpreqMinInterval; + u16 dot11MeshHWMPperrMinInterval; u16 dot11MeshHWMPnetDiameterTraversalTime; u8 dot11MeshHWMPRootMode; u16 dot11MeshHWMPRannInterval; @@ -802,6 +803,7 @@ struct mesh_config { * @ie_len: length of vendor information elements * @is_authenticated: this mesh requires authentication * @is_secure: this mesh uses security + * @mcast_rate: multicat rate for Mesh Node [6Mbps is the default for 802.11a] * * These parameters are fixed when the mesh is created. */ @@ -814,6 +816,7 @@ struct mesh_setup { u8 ie_len; bool is_authenticated; bool is_secure; + int mcast_rate[IEEE80211_NUM_BANDS]; }; /** @@ -1146,6 +1149,7 @@ struct cfg80211_ibss_params { u8 *ssid; u8 *bssid; struct ieee80211_channel *channel; + enum nl80211_channel_type channel_type; u8 *ie; u8 ssid_len, ie_len; u16 beacon_interval; @@ -1342,7 +1346,12 @@ struct cfg80211_gtk_rekey_data { * * @add_station: Add a new station. * @del_station: Remove a station; @mac may be NULL to remove all stations. - * @change_station: Modify a given station. + * @change_station: Modify a given station. Note that flags changes are not much + * validated in cfg80211, in particular the auth/assoc/authorized flags + * might come to the driver in invalid combinations -- make sure to check + * them, also against the existing state! Also, supported_rates changes are + * not checked in station mode -- drivers need to reject (or ignore) them + * for anything but TDLS peers. * @get_station: get station information for the station identified by @mac * @dump_station: dump station callback -- resume dump at index @idx * @@ -1399,7 +1408,8 @@ struct cfg80211_gtk_rekey_data { * have changed. The actual parameter values are available in * struct wiphy. If returning an error, no value should be changed. * - * @set_tx_power: set the transmit power according to the parameters + * @set_tx_power: set the transmit power according to the parameters, + * the power passed is in mBm, to get dBm use MBM_TO_DBM(). * @get_tx_power: store the current TX power into the dbm variable; * return 0 if successful * @@ -1465,6 +1475,8 @@ struct cfg80211_gtk_rekey_data { * * @probe_client: probe an associated client, must return a cookie that it * later passes to cfg80211_probe_status(). + * + * @set_noack_map: Set the NoAck Map for the TIDs. */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1658,6 +1670,10 @@ struct cfg80211_ops { int (*probe_client)(struct wiphy *wiphy, struct net_device *dev, const u8 *peer, u64 *cookie); + int (*set_noack_map)(struct wiphy *wiphy, + struct net_device *dev, + u16 noack_map); + struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy); }; @@ -1683,7 +1699,9 @@ struct cfg80211_ops { * regulatory domain no user regulatory domain can enable these channels * at a later time. This can be used for devices which do not have * calibration information guaranteed for frequencies or settings - * outside of its regulatory domain. + * outside of its regulatory domain. If used in combination with + * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings + * will be followed. * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure * that passive scan flags and beaconing flags may not be lifted by * cfg80211 due to regulatory beacon hints. For more information on beacon @@ -3053,6 +3071,32 @@ void cfg80211_roamed(struct net_device *dev, const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); /** + * cfg80211_roamed_bss - notify cfg80211 of roaming + * + * @dev: network device + * @bss: entry of bss to which STA got roamed + * @req_ie: association request IEs (maybe be %NULL) + * @req_ie_len: association request IEs length + * @resp_ie: association response IEs (may be %NULL) + * @resp_ie_len: assoc response IEs length + * @gfp: allocation flags + * + * This is just a wrapper to notify cfg80211 of roaming event with driver + * passing bss to avoid a race in timeout of the bss entry. It should be + * called by the underlying driver whenever it roamed from one AP to another + * while connected. Drivers which have roaming implemented in firmware + * may use this function to avoid a race in bss entry timeout where the bss + * entry of the new AP is seen in the driver, but gets timed out by the time + * it is accessed in __cfg80211_roamed() due to delay in scheduling + * rdev->event_work. In case of any failures, the reference is released + * either in cfg80211_roamed_bss() or in __cfg80211_romed(), Otherwise, + * it will be released while diconneting from the current bss. + */ +void cfg80211_roamed_bss(struct net_device *dev, struct cfg80211_bss *bss, + const u8 *req_ie, size_t req_ie_len, + const u8 *resp_ie, size_t resp_ie_len, gfp_t gfp); + +/** * cfg80211_disconnected - notify cfg80211 that connection was dropped * * @dev: network device @@ -3257,6 +3301,16 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy, const u8 *frame, size_t len, int freq, gfp_t gfp); +/* + * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used + * @wiphy: the wiphy + * @chan: main channel + * @channel_type: HT mode + */ +int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type); + /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/include/net/dst.h b/include/net/dst.h index 6faec1a..344c8dd 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -53,6 +53,7 @@ struct dst_entry { #define DST_NOHASH 0x0008 #define DST_NOCACHE 0x0010 #define DST_NOCOUNT 0x0020 +#define DST_NOPEER 0x0040 short error; short obsolete; @@ -86,12 +87,12 @@ struct dst_entry { }; }; -static inline struct neighbour *dst_get_neighbour(struct dst_entry *dst) +static inline struct neighbour *dst_get_neighbour_noref(struct dst_entry *dst) { return rcu_dereference(dst->_neighbour); } -static inline struct neighbour *dst_get_neighbour_raw(struct dst_entry *dst) +static inline struct neighbour *dst_get_neighbour_noref_raw(struct dst_entry *dst) { return rcu_dereference_raw(dst->_neighbour); } @@ -392,7 +393,7 @@ static inline void dst_confirm(struct dst_entry *dst) struct neighbour *n; rcu_read_lock(); - n = dst_get_neighbour(dst); + n = dst_get_neighbour_noref(dst); neigh_confirm(n); rcu_read_unlock(); } diff --git a/include/net/flow.h b/include/net/flow.h index 9192d69..da1f064 100644 --- a/include/net/flow.h +++ b/include/net/flow.h @@ -210,6 +210,7 @@ extern struct flow_cache_object *flow_cache_lookup( u8 dir, flow_resolve_t resolver, void *ctx); extern void flow_cache_flush(void); +extern void flow_cache_flush_deferred(void); extern atomic_t flow_cache_genid; #endif diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index e46674d..00cbb43 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -15,7 +15,7 @@ #define _INET6_HASHTABLES_H -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) #include <linux/in6.h> #include <linux/ipv6.h> #include <linux/types.h> @@ -110,5 +110,5 @@ extern struct sock *inet6_lookup(struct net *net, struct inet_hashinfo *hashinfo const struct in6_addr *saddr, const __be16 sport, const struct in6_addr *daddr, const __be16 dport, const int dif); -#endif /* defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) */ +#endif /* IS_ENABLED(CONFIG_IPV6) */ #endif /* _INET6_HASHTABLES_H */ diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index f941964..e3e4051 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -71,7 +71,7 @@ struct ip_options_data { struct inet_request_sock { struct request_sock req; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) u16 inet6_rsk_offset; #endif __be16 loc_port; @@ -139,7 +139,7 @@ struct rtable; struct inet_sock { /* sk and pinet6 has to be the first two members of inet_sock */ struct sock sk; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct ipv6_pinfo *pinet6; #endif /* Socket demultiplex comparisons on incoming packets. */ @@ -188,7 +188,7 @@ static inline void __inet_sk_copy_descendant(struct sock *sk_to, memcpy(inet_sk(sk_to) + 1, inet_sk(sk_from) + 1, sk_from->sk_prot->obj_size - ancestor_size); } -#if !(defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)) +#if !(IS_ENABLED(CONFIG_IPV6)) static inline void inet_sk_copy_descendant(struct sock *sk_to, const struct sock *sk_from) { diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h index e8c25b9..ba52c83 100644 --- a/include/net/inet_timewait_sock.h +++ b/include/net/inet_timewait_sock.h @@ -218,20 +218,12 @@ extern void inet_twsk_purge(struct inet_hashinfo *hashinfo, static inline struct net *twsk_net(const struct inet_timewait_sock *twsk) { -#ifdef CONFIG_NET_NS - return rcu_dereference_raw(twsk->tw_net); /* protected by locking, */ - /* reference counting, */ - /* initialization, or RCU. */ -#else - return &init_net; -#endif + return read_pnet(&twsk->tw_net); } static inline void twsk_net_set(struct inet_timewait_sock *twsk, struct net *net) { -#ifdef CONFIG_NET_NS - rcu_assign_pointer(twsk->tw_net, net); -#endif + write_pnet(&twsk->tw_net, net); } #endif /* _INET_TIMEWAIT_SOCK_ */ diff --git a/include/net/ip.h b/include/net/ip.h index fd1561e..775009f 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -353,14 +353,14 @@ static inline void ip_ipgre_mc_map(__be32 naddr, const unsigned char *broadcast, memcpy(buf, &naddr, sizeof(naddr)); } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) #include <linux/ipv6.h> #endif static __inline__ void inet_reset_saddr(struct sock *sk) { inet_sk(sk)->inet_rcv_saddr = inet_sk(sk)->inet_saddr = 0; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) if (sk->sk_family == PF_INET6) { struct ipv6_pinfo *np = inet6_sk(sk); @@ -379,7 +379,7 @@ static inline int sk_mc_loop(struct sock *sk) switch (sk->sk_family) { case AF_INET: return inet_sk(sk)->mc_loop; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) case AF_INET6: return inet6_sk(sk)->mc_loop; #endif diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 9c9399c..2ad92ca 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -97,14 +97,14 @@ extern struct rt6_info *rt6_lookup(struct net *net, extern struct dst_entry *icmp6_dst_alloc(struct net_device *dev, struct neighbour *neigh, - const struct in6_addr *addr); + struct flowi6 *fl6); extern int icmp6_dst_gc(void); extern void fib6_force_start_gc(struct net *net); extern struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, const struct in6_addr *addr, - int anycast); + bool anycast); extern int ip6_dst_hoplimit(struct dst_entry *dst); diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h index f2419cf..0954ec9 100644 --- a/include/net/iucv/af_iucv.h +++ b/include/net/iucv/af_iucv.h @@ -27,7 +27,6 @@ enum { IUCV_OPEN, IUCV_BOUND, IUCV_LISTEN, - IUCV_SEVERED, IUCV_DISCONN, IUCV_CLOSING, IUCV_CLOSED @@ -146,7 +145,6 @@ unsigned int iucv_sock_poll(struct file *file, struct socket *sock, poll_table *wait); void iucv_sock_link(struct iucv_sock_list *l, struct sock *s); void iucv_sock_unlink(struct iucv_sock_list *l, struct sock *s); -int iucv_sock_wait_cnt(struct sock *sk, unsigned long timeo); void iucv_accept_enqueue(struct sock *parent, struct sock *sk); void iucv_accept_unlink(struct sock *sk); struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock); diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index 3bb6fa0..ee547c1 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -77,7 +77,7 @@ struct net { struct netns_packet packet; struct netns_unix unx; struct netns_ipv4 ipv4; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct netns_ipv6 ipv6; #endif #if defined(CONFIG_IP_DCCP) || defined(CONFIG_IP_DCCP_MODULE) diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h index e505358..75ca929 100644 --- a/include/net/netfilter/nf_tproxy_core.h +++ b/include/net/netfilter/nf_tproxy_core.h @@ -131,7 +131,7 @@ nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, return sk; } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) static inline struct sock * nf_tproxy_get_sock_v6(struct net *net, const u8 protocol, const struct in6_addr *saddr, const struct in6_addr *daddr, diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index d786b4f..bbd023a 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -55,6 +55,7 @@ struct netns_ipv4 { int current_rt_cache_rebuild_count; unsigned int sysctl_ping_group_range[2]; + long sysctl_tcp_mem[3]; atomic_t rt_genid; atomic_t dev_addr_genid; diff --git a/include/net/netns/mib.h b/include/net/netns/mib.h index 30f6728..d542a4b 100644 --- a/include/net/netns/mib.h +++ b/include/net/netns/mib.h @@ -12,7 +12,7 @@ struct netns_mib { DEFINE_SNMP_STAT(struct icmp_mib, icmp_statistics); DEFINE_SNMP_STAT_ATOMIC(struct icmpmsg_mib, icmpmsg_statistics); -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct proc_dir_entry *proc_net_devsnmp6; DEFINE_SNMP_STAT(struct udp_mib, udp_stats_in6); DEFINE_SNMP_STAT(struct udp_mib, udplite_stats_in6); diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 748f91f..5299e69 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -56,7 +56,7 @@ struct netns_xfrm { #endif struct dst_ops xfrm4_dst_ops; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct dst_ops xfrm6_dst_ops; #endif }; diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index 6a7f602..ccfe757 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h @@ -52,6 +52,9 @@ struct nfc_ops { int (*dev_down)(struct nfc_dev *dev); int (*start_poll)(struct nfc_dev *dev, u32 protocols); void (*stop_poll)(struct nfc_dev *dev); + int (*dep_link_up)(struct nfc_dev *dev, int target_idx, + u8 comm_mode, u8 rf_mode); + int (*dep_link_down)(struct nfc_dev *dev); int (*activate_target)(struct nfc_dev *dev, u32 target_idx, u32 protocol); void (*deactivate_target)(struct nfc_dev *dev, u32 target_idx); @@ -60,6 +63,9 @@ struct nfc_ops { void *cb_context); }; +#define NFC_TARGET_IDX_ANY -1 +#define NFC_MAX_GT_LEN 48 + struct nfc_target { u32 idx; u32 supported_protocols; @@ -83,6 +89,8 @@ struct nfc_dev { bool dev_up; bool polling; bool remote_activated; + bool dep_link_up; + u32 dep_rf_mode; struct nfc_genl_data genl_data; u32 supported_protocols; @@ -157,9 +165,20 @@ static inline const char *nfc_device_name(struct nfc_dev *dev) return dev_name(&dev->dev); } -struct sk_buff *nfc_alloc_skb(unsigned int size, gfp_t gfp); +struct sk_buff *nfc_alloc_send_skb(struct nfc_dev *dev, struct sock *sk, + unsigned int flags, unsigned int size, + unsigned int *err); +struct sk_buff *nfc_alloc_recv_skb(unsigned int size, gfp_t gfp); + +int nfc_set_remote_general_bytes(struct nfc_dev *dev, + u8 *gt, u8 gt_len); + +u8 *nfc_get_local_general_bytes(struct nfc_dev *dev, u8 *gt_len); int nfc_targets_found(struct nfc_dev *dev, struct nfc_target *targets, int ntargets); +int nfc_dep_link_is_up(struct nfc_dev *dev, u32 target_idx, + u8 comm_mode, u8 rf_mode); + #endif /* __NET_NFC_H */ diff --git a/include/net/protocol.h b/include/net/protocol.h index e182e13..875f489 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -25,7 +25,7 @@ #define _PROTOCOL_H #include <linux/in6.h> -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) #include <linux/ipv6.h> #endif @@ -46,7 +46,7 @@ struct net_protocol { netns_ok:1; }; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct inet6_protocol { int (*handler)(struct sk_buff *skb); @@ -91,7 +91,7 @@ struct inet_protosw { extern const struct net_protocol __rcu *inet_protos[MAX_INET_PROTOS]; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) extern const struct inet6_protocol __rcu *inet6_protos[MAX_INET_PROTOS]; #endif @@ -100,7 +100,7 @@ extern int inet_del_protocol(const struct net_protocol *prot, unsigned char num) extern void inet_register_protosw(struct inet_protosw *p); extern void inet_unregister_protosw(struct inet_protosw *p); -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) extern int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char num); extern int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char num); extern int inet6_register_protosw(struct inet_protosw *p); diff --git a/include/net/red.h b/include/net/red.h index b72a3b8..ef715a1 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -5,6 +5,7 @@ #include <net/pkt_sched.h> #include <net/inet_ecn.h> #include <net/dsfield.h> +#include <linux/reciprocal_div.h> /* Random Early Detection (RED) algorithm. ======================================= @@ -87,6 +88,29 @@ etc. */ +/* + * Adaptative RED : An Algorithm for Increasing the Robustness of RED's AQM + * (Sally FLoyd, Ramakrishna Gummadi, and Scott Shenker) August 2001 + * + * Every 500 ms: + * if (avg > target and max_p <= 0.5) + * increase max_p : max_p += alpha; + * else if (avg < target and max_p >= 0.01) + * decrease max_p : max_p *= beta; + * + * target :[qth_min + 0.4*(qth_min - qth_max), + * qth_min + 0.6*(qth_min - qth_max)]. + * alpha : min(0.01, max_p / 4) + * beta : 0.9 + * max_P is a Q0.32 fixed point number (with 32 bits mantissa) + * max_P between 0.01 and 0.5 (1% - 50%) [ Its no longer a negative power of two ] + */ +#define RED_ONE_PERCENT ((u32)DIV_ROUND_CLOSEST(1ULL<<32, 100)) + +#define MAX_P_MIN (1 * RED_ONE_PERCENT) +#define MAX_P_MAX (50 * RED_ONE_PERCENT) +#define MAX_P_ALPHA(val) min(MAX_P_MIN, val / 4) + #define RED_STAB_SIZE 256 #define RED_STAB_MASK (RED_STAB_SIZE - 1) @@ -101,10 +125,14 @@ struct red_stats { struct red_parms { /* Parameters */ - u32 qth_min; /* Min avg length threshold: A scaled */ - u32 qth_max; /* Max avg length threshold: A scaled */ + u32 qth_min; /* Min avg length threshold: Wlog scaled */ + u32 qth_max; /* Max avg length threshold: Wlog scaled */ u32 Scell_max; - u32 Rmask; /* Cached random mask, see red_rmask */ + u32 max_P; /* probability, [0 .. 1.0] 32 scaled */ + u32 max_P_reciprocal; /* reciprocal_value(max_P / qth_delta) */ + u32 qth_delta; /* max_th - min_th */ + u32 target_min; /* min_th + 0.4*(max_th - min_th) */ + u32 target_max; /* min_th + 0.6*(max_th - min_th) */ u8 Scell_log; u8 Wlog; /* log(W) */ u8 Plog; /* random number bits */ @@ -115,19 +143,23 @@ struct red_parms { number generation */ u32 qR; /* Cached random number */ - unsigned long qavg; /* Average queue length: A scaled */ + unsigned long qavg; /* Average queue length: Wlog scaled */ ktime_t qidlestart; /* Start of current idle period */ }; -static inline u32 red_rmask(u8 Plog) +static inline u32 red_maxp(u8 Plog) { - return Plog < 32 ? ((1 << Plog) - 1) : ~0UL; + return Plog < 32 ? (~0U >> Plog) : ~0U; } + static inline void red_set_parms(struct red_parms *p, u32 qth_min, u32 qth_max, u8 Wlog, u8 Plog, - u8 Scell_log, u8 *stab) + u8 Scell_log, u8 *stab, u32 max_P) { + int delta = qth_max - qth_min; + u32 max_p_delta; + /* Reset average queue length, the value is strictly bound * to the parameters below, reseting hurts a bit but leaving * it might result in an unreasonable qavg for a while. --TGR @@ -139,14 +171,33 @@ static inline void red_set_parms(struct red_parms *p, p->qth_max = qth_max << Wlog; p->Wlog = Wlog; p->Plog = Plog; - p->Rmask = red_rmask(Plog); + if (delta < 0) + delta = 1; + p->qth_delta = delta; + if (!max_P) { + max_P = red_maxp(Plog); + max_P *= delta; /* max_P = (qth_max - qth_min)/2^Plog */ + } + p->max_P = max_P; + max_p_delta = max_P / delta; + max_p_delta = max(max_p_delta, 1U); + p->max_P_reciprocal = reciprocal_value(max_p_delta); + + /* RED Adaptative target : + * [min_th + 0.4*(min_th - max_th), + * min_th + 0.6*(min_th - max_th)]. + */ + delta /= 5; + p->target_min = qth_min + 2*delta; + p->target_max = qth_min + 3*delta; + p->Scell_log = Scell_log; p->Scell_max = (255 << Scell_log); memcpy(p->Stab, stab, sizeof(p->Stab)); } -static inline int red_is_idling(struct red_parms *p) +static inline int red_is_idling(const struct red_parms *p) { return p->qidlestart.tv64 != 0; } @@ -168,7 +219,7 @@ static inline void red_restart(struct red_parms *p) p->qcount = -1; } -static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) +static inline unsigned long red_calc_qavg_from_idle_time(const struct red_parms *p) { s64 delta = ktime_us_delta(ktime_get(), p->qidlestart); long us_idle = min_t(s64, delta, p->Scell_max); @@ -215,7 +266,7 @@ static inline unsigned long red_calc_qavg_from_idle_time(struct red_parms *p) } } -static inline unsigned long red_calc_qavg_no_idle_time(struct red_parms *p, +static inline unsigned long red_calc_qavg_no_idle_time(const struct red_parms *p, unsigned int backlog) { /* @@ -230,7 +281,7 @@ static inline unsigned long red_calc_qavg_no_idle_time(struct red_parms *p, return p->qavg + (backlog - (p->qavg >> p->Wlog)); } -static inline unsigned long red_calc_qavg(struct red_parms *p, +static inline unsigned long red_calc_qavg(const struct red_parms *p, unsigned int backlog) { if (!red_is_idling(p)) @@ -239,23 +290,24 @@ static inline unsigned long red_calc_qavg(struct red_parms *p, return red_calc_qavg_from_idle_time(p); } -static inline u32 red_random(struct red_parms *p) + +static inline u32 red_random(const struct red_parms *p) { - return net_random() & p->Rmask; + return reciprocal_divide(net_random(), p->max_P_reciprocal); } -static inline int red_mark_probability(struct red_parms *p, unsigned long qavg) +static inline int red_mark_probability(const struct red_parms *p, unsigned long qavg) { /* The formula used below causes questions. - OK. qR is random number in the interval 0..Rmask + OK. qR is random number in the interval + (0..1/max_P)*(qth_max-qth_min) i.e. 0..(2^Plog). If we used floating point arithmetics, it would be: (2^Plog)*rnd_num, where rnd_num is less 1. Taking into account, that qavg have fixed - point at Wlog, and Plog is related to max_P by - max_P = (qth_max-qth_min)/2^Plog; two lines + point at Wlog, two lines below have the following floating point equivalent: max_P*(qavg - qth_min)/(qth_max-qth_min) < rnd/qcount @@ -315,4 +367,25 @@ static inline int red_action(struct red_parms *p, unsigned long qavg) return RED_DONT_MARK; } +static inline void red_adaptative_algo(struct red_parms *p) +{ + unsigned long qavg; + u32 max_p_delta; + + qavg = p->qavg; + if (red_is_idling(p)) + qavg = red_calc_qavg_from_idle_time(p); + + /* p->qavg is fixed point number with point at Wlog */ + qavg >>= p->Wlog; + + if (qavg > p->target_max && p->max_P <= MAX_P_MAX) + p->max_P += MAX_P_ALPHA(p->max_P); /* maxp = maxp + alpha */ + else if (qavg < p->target_min && p->max_P >= MAX_P_MIN) + p->max_P = (p->max_P/10)*9; /* maxp = maxp * Beta */ + + max_p_delta = DIV_ROUND_CLOSEST(p->max_P, p->qth_delta); + max_p_delta = max(max_p_delta, 1U); + p->max_P_reciprocal = reciprocal_value(max_p_delta); +} #endif diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 6a72a58..d368561 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h @@ -71,7 +71,7 @@ #include <linux/jiffies.h> #include <linux/idr.h> -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) #include <net/ipv6.h> #include <net/ip6_route.h> #endif @@ -383,7 +383,7 @@ static inline void sctp_sysctl_unregister(void) { return; } /* Size of Supported Address Parameter for 'x' address types. */ #define SCTP_SAT_LEN(x) (sizeof(struct sctp_paramhdr) + (x) * sizeof(__u16)) -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) void sctp_v6_pf_init(void); void sctp_v6_pf_exit(void); diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 3382615..88949a9 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -235,12 +235,15 @@ extern struct sctp_globals { /* Flag to indicate whether computing and verifying checksum * is disabled. */ - int checksum_disable; + bool checksum_disable; /* Threshold for rwnd update SACKS. Receive buffer shifted this many * bits is an indicator of when to send and window update SACK. */ int rwnd_update_shift; + + /* Threshold for autoclose timeout, in seconds. */ + unsigned long max_autoclose; } sctp_globals; #define sctp_rto_initial (sctp_globals.rto_initial) @@ -281,6 +284,7 @@ extern struct sctp_globals { #define sctp_auth_enable (sctp_globals.auth_enable) #define sctp_checksum_disable (sctp_globals.checksum_disable) #define sctp_rwnd_upd_shift (sctp_globals.rwnd_update_shift) +#define sctp_max_autoclose (sctp_globals.max_autoclose) /* SCTP Socket type: UDP or TCP style. */ typedef enum { @@ -365,7 +369,7 @@ static inline struct sock *sctp_opt2sk(const struct sctp_sock *sp) return (struct sock *)sp; } -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct sctp6_sock { struct sctp_sock sctp; struct ipv6_pinfo inet6; diff --git a/include/net/sock.h b/include/net/sock.h index 8ac338c..bb972d2 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -53,6 +53,8 @@ #include <linux/security.h> #include <linux/slab.h> #include <linux/uaccess.h> +#include <linux/memcontrol.h> +#include <linux/res_counter.h> #include <linux/filter.h> #include <linux/rculist_nulls.h> @@ -62,6 +64,22 @@ #include <net/dst.h> #include <net/checksum.h> +struct cgroup; +struct cgroup_subsys; +#ifdef CONFIG_NET +int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss); +void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss); +#else +static inline +int mem_cgroup_sockets_init(struct cgroup *cgrp, struct cgroup_subsys *ss) +{ + return 0; +} +static inline +void mem_cgroup_sockets_destroy(struct cgroup *cgrp, struct cgroup_subsys *ss) +{ +} +#endif /* * This structure really needs to be cleaned up. * Most of it is for TCP, and not used by any of @@ -167,6 +185,7 @@ struct sock_common { /* public: */ }; +struct cg_proto; /** * struct sock - network layer representation of sockets * @__sk_common: shared layout with inet_timewait_sock @@ -227,6 +246,7 @@ struct sock_common { * @sk_security: used by security modules * @sk_mark: generic packet mark * @sk_classid: this socket's cgroup classid + * @sk_cgrp: this socket's cgroup-specific proto data * @sk_write_pending: a write to stream socket waits to start * @sk_state_change: callback to indicate change in the state of the sock * @sk_data_ready: callback to indicate there is data to be processed @@ -341,6 +361,7 @@ struct sock { #endif __u32 sk_mark; u32 sk_classid; + struct cg_proto *sk_cgrp; void (*sk_state_change)(struct sock *sk); void (*sk_data_ready)(struct sock *sk, int bytes); void (*sk_write_space)(struct sock *sk); @@ -641,12 +662,14 @@ static inline void __sk_add_backlog(struct sock *sk, struct sk_buff *skb) /* * Take into account size of receive queue and backlog queue + * Do not take into account this skb truesize, + * to allow even a single big packet to come. */ static inline bool sk_rcvqueues_full(const struct sock *sk, const struct sk_buff *skb) { unsigned int qsize = sk->sk_backlog.len + atomic_read(&sk->sk_rmem_alloc); - return qsize + skb->truesize > sk->sk_rcvbuf; + return qsize > sk->sk_rcvbuf; } /* The per-socket spinlock must be held here. */ @@ -837,6 +860,37 @@ struct proto { #ifdef SOCK_REFCNT_DEBUG atomic_t socks; #endif +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM + /* + * cgroup specific init/deinit functions. Called once for all + * protocols that implement it, from cgroups populate function. + * This function has to setup any files the protocol want to + * appear in the kmem cgroup filesystem. + */ + int (*init_cgroup)(struct cgroup *cgrp, + struct cgroup_subsys *ss); + void (*destroy_cgroup)(struct cgroup *cgrp, + struct cgroup_subsys *ss); + struct cg_proto *(*proto_cgroup)(struct mem_cgroup *memcg); +#endif +}; + +struct cg_proto { + void (*enter_memory_pressure)(struct sock *sk); + struct res_counter *memory_allocated; /* Current allocated memory. */ + struct percpu_counter *sockets_allocated; /* Current number of sockets. */ + int *memory_pressure; + long *sysctl_mem; + /* + * memcg field is used to find which memcg we belong directly + * Each memcg struct can hold more than one cg_proto, so container_of + * won't really cut. + * + * The elegant solution would be having an inverse function to + * proto_cgroup in struct proto, but that means polluting the structure + * for everybody, instead of just for memcg users. + */ + struct mem_cgroup *memcg; }; extern int proto_register(struct proto *prot, int alloc_slab); @@ -855,7 +909,7 @@ static inline void sk_refcnt_debug_dec(struct sock *sk) sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks)); } -static inline void sk_refcnt_debug_release(const struct sock *sk) +inline void sk_refcnt_debug_release(const struct sock *sk) { if (atomic_read(&sk->sk_refcnt) != 1) printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n", @@ -867,6 +921,208 @@ static inline void sk_refcnt_debug_release(const struct sock *sk) #define sk_refcnt_debug_release(sk) do { } while (0) #endif /* SOCK_REFCNT_DEBUG */ +#ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM +extern struct jump_label_key memcg_socket_limit_enabled; +static inline struct cg_proto *parent_cg_proto(struct proto *proto, + struct cg_proto *cg_proto) +{ + return proto->proto_cgroup(parent_mem_cgroup(cg_proto->memcg)); +} +#define mem_cgroup_sockets_enabled static_branch(&memcg_socket_limit_enabled) +#else +#define mem_cgroup_sockets_enabled 0 +static inline struct cg_proto *parent_cg_proto(struct proto *proto, + struct cg_proto *cg_proto) +{ + return NULL; +} +#endif + + +static inline bool sk_has_memory_pressure(const struct sock *sk) +{ + return sk->sk_prot->memory_pressure != NULL; +} + +static inline bool sk_under_memory_pressure(const struct sock *sk) +{ + if (!sk->sk_prot->memory_pressure) + return false; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) + return !!*sk->sk_cgrp->memory_pressure; + + return !!*sk->sk_prot->memory_pressure; +} + +static inline void sk_leave_memory_pressure(struct sock *sk) +{ + int *memory_pressure = sk->sk_prot->memory_pressure; + + if (!memory_pressure) + return; + + if (*memory_pressure) + *memory_pressure = 0; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { + struct cg_proto *cg_proto = sk->sk_cgrp; + struct proto *prot = sk->sk_prot; + + for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) + if (*cg_proto->memory_pressure) + *cg_proto->memory_pressure = 0; + } + +} + +static inline void sk_enter_memory_pressure(struct sock *sk) +{ + if (!sk->sk_prot->enter_memory_pressure) + return; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { + struct cg_proto *cg_proto = sk->sk_cgrp; + struct proto *prot = sk->sk_prot; + + for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) + cg_proto->enter_memory_pressure(sk); + } + + sk->sk_prot->enter_memory_pressure(sk); +} + +static inline long sk_prot_mem_limits(const struct sock *sk, int index) +{ + long *prot = sk->sk_prot->sysctl_mem; + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) + prot = sk->sk_cgrp->sysctl_mem; + return prot[index]; +} + +static inline void memcg_memory_allocated_add(struct cg_proto *prot, + unsigned long amt, + int *parent_status) +{ + struct res_counter *fail; + int ret; + + ret = res_counter_charge(prot->memory_allocated, + amt << PAGE_SHIFT, &fail); + + if (ret < 0) + *parent_status = OVER_LIMIT; +} + +static inline void memcg_memory_allocated_sub(struct cg_proto *prot, + unsigned long amt) +{ + res_counter_uncharge(prot->memory_allocated, amt << PAGE_SHIFT); +} + +static inline u64 memcg_memory_allocated_read(struct cg_proto *prot) +{ + u64 ret; + ret = res_counter_read_u64(prot->memory_allocated, RES_USAGE); + return ret >> PAGE_SHIFT; +} + +static inline long +sk_memory_allocated(const struct sock *sk) +{ + struct proto *prot = sk->sk_prot; + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) + return memcg_memory_allocated_read(sk->sk_cgrp); + + return atomic_long_read(prot->memory_allocated); +} + +static inline long +sk_memory_allocated_add(struct sock *sk, int amt, int *parent_status) +{ + struct proto *prot = sk->sk_prot; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { + memcg_memory_allocated_add(sk->sk_cgrp, amt, parent_status); + /* update the root cgroup regardless */ + atomic_long_add_return(amt, prot->memory_allocated); + return memcg_memory_allocated_read(sk->sk_cgrp); + } + + return atomic_long_add_return(amt, prot->memory_allocated); +} + +static inline void +sk_memory_allocated_sub(struct sock *sk, int amt, int parent_status) +{ + struct proto *prot = sk->sk_prot; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp && + parent_status != OVER_LIMIT) /* Otherwise was uncharged already */ + memcg_memory_allocated_sub(sk->sk_cgrp, amt); + + atomic_long_sub(amt, prot->memory_allocated); +} + +static inline void sk_sockets_allocated_dec(struct sock *sk) +{ + struct proto *prot = sk->sk_prot; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { + struct cg_proto *cg_proto = sk->sk_cgrp; + + for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) + percpu_counter_dec(cg_proto->sockets_allocated); + } + + percpu_counter_dec(prot->sockets_allocated); +} + +static inline void sk_sockets_allocated_inc(struct sock *sk) +{ + struct proto *prot = sk->sk_prot; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) { + struct cg_proto *cg_proto = sk->sk_cgrp; + + for (; cg_proto; cg_proto = parent_cg_proto(prot, cg_proto)) + percpu_counter_inc(cg_proto->sockets_allocated); + } + + percpu_counter_inc(prot->sockets_allocated); +} + +static inline int +sk_sockets_allocated_read_positive(struct sock *sk) +{ + struct proto *prot = sk->sk_prot; + + if (mem_cgroup_sockets_enabled && sk->sk_cgrp) + return percpu_counter_sum_positive(sk->sk_cgrp->sockets_allocated); + + return percpu_counter_sum_positive(prot->sockets_allocated); +} + +static inline int +proto_sockets_allocated_sum_positive(struct proto *prot) +{ + return percpu_counter_sum_positive(prot->sockets_allocated); +} + +static inline long +proto_memory_allocated(struct proto *prot) +{ + return atomic_long_read(prot->memory_allocated); +} + +static inline bool +proto_memory_pressure(struct proto *prot) +{ + if (!prot->memory_pressure) + return false; + return !!*prot->memory_pressure; +} + #ifdef CONFIG_PROC_FS /* Called with local bh disabled */ @@ -1674,7 +1930,7 @@ static inline struct page *sk_stream_alloc_page(struct sock *sk) page = alloc_pages(sk->sk_allocation, 0); if (!page) { - sk->sk_prot->enter_memory_pressure(sk); + sk_enter_memory_pressure(sk); sk_stream_moderate_sndbuf(sk); } return page; diff --git a/include/net/tcp.h b/include/net/tcp.h index 87e3c80..0118ea9 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -44,6 +44,7 @@ #include <net/dst.h> #include <linux/seq_file.h> +#include <linux/memcontrol.h> extern struct inet_hashinfo tcp_hashinfo; @@ -229,7 +230,6 @@ extern int sysctl_tcp_fack; extern int sysctl_tcp_reordering; extern int sysctl_tcp_ecn; extern int sysctl_tcp_dsack; -extern long sysctl_tcp_mem[3]; extern int sysctl_tcp_wmem[3]; extern int sysctl_tcp_rmem[3]; extern int sysctl_tcp_app_win; @@ -285,7 +285,7 @@ static inline bool tcp_too_many_orphans(struct sock *sk, int shift) } if (sk->sk_wmem_queued > SOCK_MIN_SNDBUF && - atomic_long_read(&tcp_memory_allocated) > sysctl_tcp_mem[2]) + sk_memory_allocated(sk) > sk_prot_mem_limits(sk, 2)) return true; return false; } @@ -628,7 +628,7 @@ extern u32 __tcp_select_window(struct sock *sk); struct tcp_skb_cb { union { struct inet_skb_parm h4; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct inet6_skb_parm h6; #endif } header; /* For incoming frames */ @@ -773,12 +773,12 @@ static inline int tcp_is_reno(const struct tcp_sock *tp) static inline int tcp_is_fack(const struct tcp_sock *tp) { - return tp->rx_opt.sack_ok & 2; + return tp->rx_opt.sack_ok & TCP_FACK_ENABLED; } static inline void tcp_enable_fack(struct tcp_sock *tp) { - tp->rx_opt.sack_ok |= 2; + tp->rx_opt.sack_ok |= TCP_FACK_ENABLED; } static inline unsigned int tcp_left_out(const struct tcp_sock *tp) @@ -1152,7 +1152,7 @@ struct tcp6_md5sig_key { /* - sock block */ struct tcp_md5sig_info { struct tcp4_md5sig_key *keys4; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct tcp6_md5sig_key *keys6; u32 entries6; u32 alloced6; @@ -1179,7 +1179,7 @@ struct tcp6_pseudohdr { union tcp_md5sum_block { struct tcp4_pseudohdr ip4; -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct tcp6_pseudohdr ip6; #endif }; diff --git a/include/net/tcp_memcontrol.h b/include/net/tcp_memcontrol.h new file mode 100644 index 0000000..3512082 --- /dev/null +++ b/include/net/tcp_memcontrol.h @@ -0,0 +1,19 @@ +#ifndef _TCP_MEMCG_H +#define _TCP_MEMCG_H + +struct tcp_memcontrol { + struct cg_proto cg_proto; + /* per-cgroup tcp memory pressure knobs */ + struct res_counter tcp_memory_allocated; + struct percpu_counter tcp_sockets_allocated; + /* those two are read-mostly, leave them at the end */ + long tcp_prot_mem[3]; + int tcp_memory_pressure; +}; + +struct cg_proto *tcp_proto_cgroup(struct mem_cgroup *memcg); +int tcp_init_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss); +void tcp_destroy_cgroup(struct cgroup *cgrp, struct cgroup_subsys *ss); +unsigned long long tcp_max_memory(const struct mem_cgroup *memcg); +void tcp_prot_mem(struct mem_cgroup *memcg, long val, int idx); +#endif /* _TCP_MEMCG_H */ diff --git a/include/net/udp.h b/include/net/udp.h index f54a515..e39592f 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -41,7 +41,7 @@ struct udp_skb_cb { union { struct inet_skb_parm h4; -#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) struct inet6_skb_parm h6; #endif } header; @@ -194,9 +194,15 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, __be32 daddr, __be16 dport, int dif); +extern struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, + __be32 daddr, __be16 dport, + int dif, struct udp_table *tbl); extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, __be16 dport, int dif); +extern struct sock *__udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, + const struct in6_addr *daddr, __be16 dport, + int dif, struct udp_table *tbl); /* * SNMP statistics for UDP and UDP-Lite @@ -217,7 +223,7 @@ extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *sadd else SNMP_INC_STATS_USER((net)->mib.udp_stats_in6, field); \ } while(0) -#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) +#if IS_ENABLED(CONFIG_IPV6) #define UDPX_INC_STATS_BH(sk, field) \ do { \ if ((sk)->sk_family == AF_INET) \ |