diff options
Diffstat (limited to 'net')
148 files changed, 1730 insertions, 1006 deletions
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 240ed70912d6..d78938e3e008 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
| @@ -277,17 +277,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv) | |||
| 277 | * batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached | 277 | * batadv_iv_ogm_aggr_packet() - checks if there is another OGM attached |
| 278 | * @buff_pos: current position in the skb | 278 | * @buff_pos: current position in the skb |
| 279 | * @packet_len: total length of the skb | 279 | * @packet_len: total length of the skb |
| 280 | * @tvlv_len: tvlv length of the previously considered OGM | 280 | * @ogm_packet: potential OGM in buffer |
| 281 | * | 281 | * |
| 282 | * Return: true if there is enough space for another OGM, false otherwise. | 282 | * Return: true if there is enough space for another OGM, false otherwise. |
| 283 | */ | 283 | */ |
| 284 | static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, | 284 | static bool |
| 285 | __be16 tvlv_len) | 285 | batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len, |
| 286 | const struct batadv_ogm_packet *ogm_packet) | ||
| 286 | { | 287 | { |
| 287 | int next_buff_pos = 0; | 288 | int next_buff_pos = 0; |
| 288 | 289 | ||
| 289 | next_buff_pos += buff_pos + BATADV_OGM_HLEN; | 290 | /* check if there is enough space for the header */ |
| 290 | next_buff_pos += ntohs(tvlv_len); | 291 | next_buff_pos += buff_pos + sizeof(*ogm_packet); |
| 292 | if (next_buff_pos > packet_len) | ||
| 293 | return false; | ||
| 294 | |||
| 295 | /* check if there is enough space for the optional TVLV */ | ||
| 296 | next_buff_pos += ntohs(ogm_packet->tvlv_len); | ||
| 291 | 297 | ||
| 292 | return (next_buff_pos <= packet_len) && | 298 | return (next_buff_pos <= packet_len) && |
| 293 | (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); | 299 | (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); |
| @@ -315,7 +321,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, | |||
| 315 | 321 | ||
| 316 | /* adjust all flags and log packets */ | 322 | /* adjust all flags and log packets */ |
| 317 | while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, | 323 | while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, |
| 318 | batadv_ogm_packet->tvlv_len)) { | 324 | batadv_ogm_packet)) { |
| 319 | /* we might have aggregated direct link packets with an | 325 | /* we might have aggregated direct link packets with an |
| 320 | * ordinary base packet | 326 | * ordinary base packet |
| 321 | */ | 327 | */ |
| @@ -1704,7 +1710,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
| 1704 | 1710 | ||
| 1705 | /* unpack the aggregated packets and process them one by one */ | 1711 | /* unpack the aggregated packets and process them one by one */ |
| 1706 | while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb), | 1712 | while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb), |
| 1707 | ogm_packet->tvlv_len)) { | 1713 | ogm_packet)) { |
| 1708 | batadv_iv_ogm_process(skb, ogm_offset, if_incoming); | 1714 | batadv_iv_ogm_process(skb, ogm_offset, if_incoming); |
| 1709 | 1715 | ||
| 1710 | ogm_offset += BATADV_OGM_HLEN; | 1716 | ogm_offset += BATADV_OGM_HLEN; |
diff --git a/net/batman-adv/bat_v_ogm.c b/net/batman-adv/bat_v_ogm.c index fad95ef64e01..bc06e3cdfa84 100644 --- a/net/batman-adv/bat_v_ogm.c +++ b/net/batman-adv/bat_v_ogm.c | |||
| @@ -631,17 +631,23 @@ batadv_v_ogm_process_per_outif(struct batadv_priv *bat_priv, | |||
| 631 | * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated | 631 | * batadv_v_ogm_aggr_packet() - checks if there is another OGM aggregated |
| 632 | * @buff_pos: current position in the skb | 632 | * @buff_pos: current position in the skb |
| 633 | * @packet_len: total length of the skb | 633 | * @packet_len: total length of the skb |
| 634 | * @tvlv_len: tvlv length of the previously considered OGM | 634 | * @ogm2_packet: potential OGM2 in buffer |
| 635 | * | 635 | * |
| 636 | * Return: true if there is enough space for another OGM, false otherwise. | 636 | * Return: true if there is enough space for another OGM, false otherwise. |
| 637 | */ | 637 | */ |
| 638 | static bool batadv_v_ogm_aggr_packet(int buff_pos, int packet_len, | 638 | static bool |
| 639 | __be16 tvlv_len) | 639 | batadv_v_ogm_aggr_packet(int buff_pos, int packet_len, |
| 640 | const struct batadv_ogm2_packet *ogm2_packet) | ||
| 640 | { | 641 | { |
| 641 | int next_buff_pos = 0; | 642 | int next_buff_pos = 0; |
| 642 | 643 | ||
| 643 | next_buff_pos += buff_pos + BATADV_OGM2_HLEN; | 644 | /* check if there is enough space for the header */ |
| 644 | next_buff_pos += ntohs(tvlv_len); | 645 | next_buff_pos += buff_pos + sizeof(*ogm2_packet); |
| 646 | if (next_buff_pos > packet_len) | ||
| 647 | return false; | ||
| 648 | |||
| 649 | /* check if there is enough space for the optional TVLV */ | ||
| 650 | next_buff_pos += ntohs(ogm2_packet->tvlv_len); | ||
| 645 | 651 | ||
| 646 | return (next_buff_pos <= packet_len) && | 652 | return (next_buff_pos <= packet_len) && |
| 647 | (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); | 653 | (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES); |
| @@ -818,7 +824,7 @@ int batadv_v_ogm_packet_recv(struct sk_buff *skb, | |||
| 818 | ogm_packet = (struct batadv_ogm2_packet *)skb->data; | 824 | ogm_packet = (struct batadv_ogm2_packet *)skb->data; |
| 819 | 825 | ||
| 820 | while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb), | 826 | while (batadv_v_ogm_aggr_packet(ogm_offset, skb_headlen(skb), |
| 821 | ogm_packet->tvlv_len)) { | 827 | ogm_packet)) { |
| 822 | batadv_v_ogm_process(skb, ogm_offset, if_incoming); | 828 | batadv_v_ogm_process(skb, ogm_offset, if_incoming); |
| 823 | 829 | ||
| 824 | ogm_offset += BATADV_OGM2_HLEN; | 830 | ogm_offset += BATADV_OGM2_HLEN; |
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 67d7f83009ae..1d5bdf3a4b65 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c | |||
| @@ -2303,7 +2303,7 @@ __batadv_mcast_flags_dump(struct sk_buff *msg, u32 portid, | |||
| 2303 | 2303 | ||
| 2304 | while (bucket_tmp < hash->size) { | 2304 | while (bucket_tmp < hash->size) { |
| 2305 | if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash, | 2305 | if (batadv_mcast_flags_dump_bucket(msg, portid, cb, hash, |
| 2306 | *bucket, &idx_tmp)) | 2306 | bucket_tmp, &idx_tmp)) |
| 2307 | break; | 2307 | break; |
| 2308 | 2308 | ||
| 2309 | bucket_tmp++; | 2309 | bucket_tmp++; |
| @@ -2420,8 +2420,10 @@ void batadv_mcast_purge_orig(struct batadv_orig_node *orig) | |||
| 2420 | batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); | 2420 | batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); |
| 2421 | batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS); | 2421 | batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS); |
| 2422 | batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS); | 2422 | batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS); |
| 2423 | batadv_mcast_want_rtr4_update(bat_priv, orig, BATADV_NO_FLAGS); | 2423 | batadv_mcast_want_rtr4_update(bat_priv, orig, |
| 2424 | batadv_mcast_want_rtr6_update(bat_priv, orig, BATADV_NO_FLAGS); | 2424 | BATADV_MCAST_WANT_NO_RTR4); |
| 2425 | batadv_mcast_want_rtr6_update(bat_priv, orig, | ||
| 2426 | BATADV_MCAST_WANT_NO_RTR6); | ||
| 2425 | 2427 | ||
| 2426 | spin_unlock_bh(&orig->mcast_handler_lock); | 2428 | spin_unlock_bh(&orig->mcast_handler_lock); |
| 2427 | } | 2429 | } |
diff --git a/net/batman-adv/netlink.c b/net/batman-adv/netlink.c index 6f08fd122a8d..7e052d6f759b 100644 --- a/net/batman-adv/netlink.c +++ b/net/batman-adv/netlink.c | |||
| @@ -164,7 +164,7 @@ batadv_netlink_get_ifindex(const struct nlmsghdr *nlh, int attrtype) | |||
| 164 | { | 164 | { |
| 165 | struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype); | 165 | struct nlattr *attr = nlmsg_find_attr(nlh, GENL_HDRLEN, attrtype); |
| 166 | 166 | ||
| 167 | return attr ? nla_get_u32(attr) : 0; | 167 | return (attr && nla_len(attr) == sizeof(u32)) ? nla_get_u32(attr) : 0; |
| 168 | } | 168 | } |
| 169 | 169 | ||
| 170 | /** | 170 | /** |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b9585e7d9d2e..04bc79359a17 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -3202,6 +3202,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
| 3202 | hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE; | 3202 | hdev->conn_info_min_age = DEFAULT_CONN_INFO_MIN_AGE; |
| 3203 | hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE; | 3203 | hdev->conn_info_max_age = DEFAULT_CONN_INFO_MAX_AGE; |
| 3204 | hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT; | 3204 | hdev->auth_payload_timeout = DEFAULT_AUTH_PAYLOAD_TIMEOUT; |
| 3205 | hdev->min_enc_key_size = HCI_MIN_ENC_KEY_SIZE; | ||
| 3205 | 3206 | ||
| 3206 | mutex_init(&hdev->lock); | 3207 | mutex_init(&hdev->lock); |
| 3207 | mutex_init(&hdev->req_lock); | 3208 | mutex_init(&hdev->req_lock); |
diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index bb67f4a5479a..402e2cc54044 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c | |||
| @@ -433,6 +433,35 @@ static int auto_accept_delay_set(void *data, u64 val) | |||
| 433 | return 0; | 433 | return 0; |
| 434 | } | 434 | } |
| 435 | 435 | ||
| 436 | static int min_encrypt_key_size_set(void *data, u64 val) | ||
| 437 | { | ||
| 438 | struct hci_dev *hdev = data; | ||
| 439 | |||
| 440 | if (val < 1 || val > 16) | ||
| 441 | return -EINVAL; | ||
| 442 | |||
| 443 | hci_dev_lock(hdev); | ||
| 444 | hdev->min_enc_key_size = val; | ||
| 445 | hci_dev_unlock(hdev); | ||
| 446 | |||
| 447 | return 0; | ||
| 448 | } | ||
| 449 | |||
| 450 | static int min_encrypt_key_size_get(void *data, u64 *val) | ||
| 451 | { | ||
| 452 | struct hci_dev *hdev = data; | ||
| 453 | |||
| 454 | hci_dev_lock(hdev); | ||
| 455 | *val = hdev->min_enc_key_size; | ||
| 456 | hci_dev_unlock(hdev); | ||
| 457 | |||
| 458 | return 0; | ||
| 459 | } | ||
| 460 | |||
| 461 | DEFINE_SIMPLE_ATTRIBUTE(min_encrypt_key_size_fops, | ||
| 462 | min_encrypt_key_size_get, | ||
| 463 | min_encrypt_key_size_set, "%llu\n"); | ||
| 464 | |||
| 436 | static int auto_accept_delay_get(void *data, u64 *val) | 465 | static int auto_accept_delay_get(void *data, u64 *val) |
| 437 | { | 466 | { |
| 438 | struct hci_dev *hdev = data; | 467 | struct hci_dev *hdev = data; |
| @@ -545,6 +574,8 @@ void hci_debugfs_create_bredr(struct hci_dev *hdev) | |||
| 545 | if (lmp_ssp_capable(hdev)) { | 574 | if (lmp_ssp_capable(hdev)) { |
| 546 | debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs, | 575 | debugfs_create_file("ssp_debug_mode", 0444, hdev->debugfs, |
| 547 | hdev, &ssp_debug_mode_fops); | 576 | hdev, &ssp_debug_mode_fops); |
| 577 | debugfs_create_file("min_encrypt_key_size", 0644, hdev->debugfs, | ||
| 578 | hdev, &min_encrypt_key_size_fops); | ||
| 548 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, | 579 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, |
| 549 | hdev, &auto_accept_delay_fops); | 580 | hdev, &auto_accept_delay_fops); |
| 550 | } | 581 | } |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 5abd423b55fa..8d889969ae7e 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
| @@ -101,6 +101,7 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock, | |||
| 101 | { | 101 | { |
| 102 | struct sk_buff *skb; | 102 | struct sk_buff *skb; |
| 103 | struct sock *sk = sock->sk; | 103 | struct sock *sk = sock->sk; |
| 104 | int ret; | ||
| 104 | 105 | ||
| 105 | BT_DBG("session %p data %p size %d", session, data, size); | 106 | BT_DBG("session %p data %p size %d", session, data, size); |
| 106 | 107 | ||
| @@ -114,13 +115,17 @@ static int hidp_send_message(struct hidp_session *session, struct socket *sock, | |||
| 114 | } | 115 | } |
| 115 | 116 | ||
| 116 | skb_put_u8(skb, hdr); | 117 | skb_put_u8(skb, hdr); |
| 117 | if (data && size > 0) | 118 | if (data && size > 0) { |
| 118 | skb_put_data(skb, data, size); | 119 | skb_put_data(skb, data, size); |
| 120 | ret = size; | ||
| 121 | } else { | ||
| 122 | ret = 0; | ||
| 123 | } | ||
| 119 | 124 | ||
| 120 | skb_queue_tail(transmit, skb); | 125 | skb_queue_tail(transmit, skb); |
| 121 | wake_up_interruptible(sk_sleep(sk)); | 126 | wake_up_interruptible(sk_sleep(sk)); |
| 122 | 127 | ||
| 123 | return 0; | 128 | return ret; |
| 124 | } | 129 | } |
| 125 | 130 | ||
| 126 | static int hidp_send_ctrl_message(struct hidp_session *session, | 131 | static int hidp_send_ctrl_message(struct hidp_session *session, |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cc506fe99b4d..dfc1edb168b7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
| @@ -1361,7 +1361,7 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon) | |||
| 1361 | * actually encrypted before enforcing a key size. | 1361 | * actually encrypted before enforcing a key size. |
| 1362 | */ | 1362 | */ |
| 1363 | return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || | 1363 | return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || |
| 1364 | hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE); | 1364 | hcon->enc_key_size >= hcon->hdev->min_enc_key_size); |
| 1365 | } | 1365 | } |
| 1366 | 1366 | ||
| 1367 | static void l2cap_do_start(struct l2cap_chan *chan) | 1367 | static void l2cap_do_start(struct l2cap_chan *chan) |
diff --git a/net/bridge/br.c b/net/bridge/br.c index d164f63a4345..8a8f9e5f264f 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
| @@ -37,12 +37,15 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
| 37 | int err; | 37 | int err; |
| 38 | 38 | ||
| 39 | if (dev->priv_flags & IFF_EBRIDGE) { | 39 | if (dev->priv_flags & IFF_EBRIDGE) { |
| 40 | err = br_vlan_bridge_event(dev, event, ptr); | ||
| 41 | if (err) | ||
| 42 | return notifier_from_errno(err); | ||
| 43 | |||
| 40 | if (event == NETDEV_REGISTER) { | 44 | if (event == NETDEV_REGISTER) { |
| 41 | /* register of bridge completed, add sysfs entries */ | 45 | /* register of bridge completed, add sysfs entries */ |
| 42 | br_sysfs_addbr(dev); | 46 | br_sysfs_addbr(dev); |
| 43 | return NOTIFY_DONE; | 47 | return NOTIFY_DONE; |
| 44 | } | 48 | } |
| 45 | br_vlan_bridge_event(dev, event, ptr); | ||
| 46 | } | 49 | } |
| 47 | 50 | ||
| 48 | /* not a port of a bridge */ | 51 | /* not a port of a bridge */ |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 3d8deac2353d..f8cac3702712 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -1388,6 +1388,9 @@ br_multicast_leave_group(struct net_bridge *br, | |||
| 1388 | if (!br_port_group_equal(p, port, src)) | 1388 | if (!br_port_group_equal(p, port, src)) |
| 1389 | continue; | 1389 | continue; |
| 1390 | 1390 | ||
| 1391 | if (p->flags & MDB_PG_FLAGS_PERMANENT) | ||
| 1392 | break; | ||
| 1393 | |||
| 1391 | rcu_assign_pointer(*pp, p->next); | 1394 | rcu_assign_pointer(*pp, p->next); |
| 1392 | hlist_del_init(&p->mglist); | 1395 | hlist_del_init(&p->mglist); |
| 1393 | del_timer(&p->timer); | 1396 | del_timer(&p->timer); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e8cf03b43b7d..646504db0220 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -894,8 +894,8 @@ int nbp_get_num_vlan_infos(struct net_bridge_port *p, u32 filter_mask); | |||
| 894 | void br_vlan_get_stats(const struct net_bridge_vlan *v, | 894 | void br_vlan_get_stats(const struct net_bridge_vlan *v, |
| 895 | struct br_vlan_stats *stats); | 895 | struct br_vlan_stats *stats); |
| 896 | void br_vlan_port_event(struct net_bridge_port *p, unsigned long event); | 896 | void br_vlan_port_event(struct net_bridge_port *p, unsigned long event); |
| 897 | void br_vlan_bridge_event(struct net_device *dev, unsigned long event, | 897 | int br_vlan_bridge_event(struct net_device *dev, unsigned long event, |
| 898 | void *ptr); | 898 | void *ptr); |
| 899 | 899 | ||
| 900 | static inline struct net_bridge_vlan_group *br_vlan_group( | 900 | static inline struct net_bridge_vlan_group *br_vlan_group( |
| 901 | const struct net_bridge *br) | 901 | const struct net_bridge *br) |
| @@ -1085,9 +1085,10 @@ static inline void br_vlan_port_event(struct net_bridge_port *p, | |||
| 1085 | { | 1085 | { |
| 1086 | } | 1086 | } |
| 1087 | 1087 | ||
| 1088 | static inline void br_vlan_bridge_event(struct net_device *dev, | 1088 | static inline int br_vlan_bridge_event(struct net_device *dev, |
| 1089 | unsigned long event, void *ptr) | 1089 | unsigned long event, void *ptr) |
| 1090 | { | 1090 | { |
| 1091 | return 0; | ||
| 1091 | } | 1092 | } |
| 1092 | #endif | 1093 | #endif |
| 1093 | 1094 | ||
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 021cc9f66804..f5b2aeebbfe9 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
| @@ -1053,7 +1053,6 @@ int br_vlan_init(struct net_bridge *br) | |||
| 1053 | { | 1053 | { |
| 1054 | struct net_bridge_vlan_group *vg; | 1054 | struct net_bridge_vlan_group *vg; |
| 1055 | int ret = -ENOMEM; | 1055 | int ret = -ENOMEM; |
| 1056 | bool changed; | ||
| 1057 | 1056 | ||
| 1058 | vg = kzalloc(sizeof(*vg), GFP_KERNEL); | 1057 | vg = kzalloc(sizeof(*vg), GFP_KERNEL); |
| 1059 | if (!vg) | 1058 | if (!vg) |
| @@ -1068,17 +1067,10 @@ int br_vlan_init(struct net_bridge *br) | |||
| 1068 | br->vlan_proto = htons(ETH_P_8021Q); | 1067 | br->vlan_proto = htons(ETH_P_8021Q); |
| 1069 | br->default_pvid = 1; | 1068 | br->default_pvid = 1; |
| 1070 | rcu_assign_pointer(br->vlgrp, vg); | 1069 | rcu_assign_pointer(br->vlgrp, vg); |
| 1071 | ret = br_vlan_add(br, 1, | ||
| 1072 | BRIDGE_VLAN_INFO_PVID | BRIDGE_VLAN_INFO_UNTAGGED | | ||
| 1073 | BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL); | ||
| 1074 | if (ret) | ||
| 1075 | goto err_vlan_add; | ||
| 1076 | 1070 | ||
| 1077 | out: | 1071 | out: |
| 1078 | return ret; | 1072 | return ret; |
| 1079 | 1073 | ||
| 1080 | err_vlan_add: | ||
| 1081 | vlan_tunnel_deinit(vg); | ||
| 1082 | err_tunnel_init: | 1074 | err_tunnel_init: |
| 1083 | rhashtable_destroy(&vg->vlan_hash); | 1075 | rhashtable_destroy(&vg->vlan_hash); |
| 1084 | err_rhtbl: | 1076 | err_rhtbl: |
| @@ -1464,13 +1456,23 @@ static void nbp_vlan_set_vlan_dev_state(struct net_bridge_port *p, u16 vid) | |||
| 1464 | } | 1456 | } |
| 1465 | 1457 | ||
| 1466 | /* Must be protected by RTNL. */ | 1458 | /* Must be protected by RTNL. */ |
| 1467 | void br_vlan_bridge_event(struct net_device *dev, unsigned long event, | 1459 | int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr) |
| 1468 | void *ptr) | ||
| 1469 | { | 1460 | { |
| 1470 | struct netdev_notifier_changeupper_info *info; | 1461 | struct netdev_notifier_changeupper_info *info; |
| 1471 | struct net_bridge *br; | 1462 | struct net_bridge *br = netdev_priv(dev); |
| 1463 | bool changed; | ||
| 1464 | int ret = 0; | ||
| 1472 | 1465 | ||
| 1473 | switch (event) { | 1466 | switch (event) { |
| 1467 | case NETDEV_REGISTER: | ||
| 1468 | ret = br_vlan_add(br, br->default_pvid, | ||
| 1469 | BRIDGE_VLAN_INFO_PVID | | ||
| 1470 | BRIDGE_VLAN_INFO_UNTAGGED | | ||
| 1471 | BRIDGE_VLAN_INFO_BRENTRY, &changed, NULL); | ||
| 1472 | break; | ||
| 1473 | case NETDEV_UNREGISTER: | ||
| 1474 | br_vlan_delete(br, br->default_pvid); | ||
| 1475 | break; | ||
| 1474 | case NETDEV_CHANGEUPPER: | 1476 | case NETDEV_CHANGEUPPER: |
| 1475 | info = ptr; | 1477 | info = ptr; |
| 1476 | br_vlan_upper_change(dev, info->upper_dev, info->linking); | 1478 | br_vlan_upper_change(dev, info->upper_dev, info->linking); |
| @@ -1478,12 +1480,13 @@ void br_vlan_bridge_event(struct net_device *dev, unsigned long event, | |||
| 1478 | 1480 | ||
| 1479 | case NETDEV_CHANGE: | 1481 | case NETDEV_CHANGE: |
| 1480 | case NETDEV_UP: | 1482 | case NETDEV_UP: |
| 1481 | br = netdev_priv(dev); | ||
| 1482 | if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING)) | 1483 | if (!br_opt_get(br, BROPT_VLAN_BRIDGE_BINDING)) |
| 1483 | return; | 1484 | break; |
| 1484 | br_vlan_link_state_change(dev, br); | 1485 | br_vlan_link_state_change(dev, br); |
| 1485 | break; | 1486 | break; |
| 1486 | } | 1487 | } |
| 1488 | |||
| 1489 | return ret; | ||
| 1487 | } | 1490 | } |
| 1488 | 1491 | ||
| 1489 | /* Must be protected by RTNL. */ | 1492 | /* Must be protected by RTNL. */ |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 963dfdc14827..4096d8a74a2b 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -221,7 +221,7 @@ unsigned int ebt_do_table(struct sk_buff *skb, | |||
| 221 | return NF_DROP; | 221 | return NF_DROP; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | ADD_COUNTER(*(counter_base + i), 1, skb->len); | 224 | ADD_COUNTER(*(counter_base + i), skb->len, 1); |
| 225 | 225 | ||
| 226 | /* these should only watch: not modify, nor tell us | 226 | /* these should only watch: not modify, nor tell us |
| 227 | * what to do with the packet | 227 | * what to do with the packet |
| @@ -959,8 +959,8 @@ static void get_counters(const struct ebt_counter *oldcounters, | |||
| 959 | continue; | 959 | continue; |
| 960 | counter_base = COUNTER_BASE(oldcounters, nentries, cpu); | 960 | counter_base = COUNTER_BASE(oldcounters, nentries, cpu); |
| 961 | for (i = 0; i < nentries; i++) | 961 | for (i = 0; i < nentries; i++) |
| 962 | ADD_COUNTER(counters[i], counter_base[i].pcnt, | 962 | ADD_COUNTER(counters[i], counter_base[i].bcnt, |
| 963 | counter_base[i].bcnt); | 963 | counter_base[i].pcnt); |
| 964 | } | 964 | } |
| 965 | } | 965 | } |
| 966 | 966 | ||
| @@ -1280,7 +1280,7 @@ static int do_update_counters(struct net *net, const char *name, | |||
| 1280 | 1280 | ||
| 1281 | /* we add to the counters of the first cpu */ | 1281 | /* we add to the counters of the first cpu */ |
| 1282 | for (i = 0; i < num_counters; i++) | 1282 | for (i = 0; i < num_counters; i++) |
| 1283 | ADD_COUNTER(t->private->counters[i], tmp[i].pcnt, tmp[i].bcnt); | 1283 | ADD_COUNTER(t->private->counters[i], tmp[i].bcnt, tmp[i].pcnt); |
| 1284 | 1284 | ||
| 1285 | write_unlock_bh(&t->lock); | 1285 | write_unlock_bh(&t->lock); |
| 1286 | ret = 0; | 1286 | ret = 0; |
| @@ -1770,20 +1770,28 @@ static int compat_calc_entry(const struct ebt_entry *e, | |||
| 1770 | return 0; | 1770 | return 0; |
| 1771 | } | 1771 | } |
| 1772 | 1772 | ||
| 1773 | static int ebt_compat_init_offsets(unsigned int number) | ||
| 1774 | { | ||
| 1775 | if (number > INT_MAX) | ||
| 1776 | return -EINVAL; | ||
| 1777 | |||
| 1778 | /* also count the base chain policies */ | ||
| 1779 | number += NF_BR_NUMHOOKS; | ||
| 1780 | |||
| 1781 | return xt_compat_init_offsets(NFPROTO_BRIDGE, number); | ||
| 1782 | } | ||
| 1773 | 1783 | ||
| 1774 | static int compat_table_info(const struct ebt_table_info *info, | 1784 | static int compat_table_info(const struct ebt_table_info *info, |
| 1775 | struct compat_ebt_replace *newinfo) | 1785 | struct compat_ebt_replace *newinfo) |
| 1776 | { | 1786 | { |
| 1777 | unsigned int size = info->entries_size; | 1787 | unsigned int size = info->entries_size; |
| 1778 | const void *entries = info->entries; | 1788 | const void *entries = info->entries; |
| 1789 | int ret; | ||
| 1779 | 1790 | ||
| 1780 | newinfo->entries_size = size; | 1791 | newinfo->entries_size = size; |
| 1781 | if (info->nentries) { | 1792 | ret = ebt_compat_init_offsets(info->nentries); |
| 1782 | int ret = xt_compat_init_offsets(NFPROTO_BRIDGE, | 1793 | if (ret) |
| 1783 | info->nentries); | 1794 | return ret; |
| 1784 | if (ret) | ||
| 1785 | return ret; | ||
| 1786 | } | ||
| 1787 | 1795 | ||
| 1788 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, | 1796 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, |
| 1789 | entries, newinfo); | 1797 | entries, newinfo); |
| @@ -2234,11 +2242,9 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
| 2234 | 2242 | ||
| 2235 | xt_compat_lock(NFPROTO_BRIDGE); | 2243 | xt_compat_lock(NFPROTO_BRIDGE); |
| 2236 | 2244 | ||
| 2237 | if (tmp.nentries) { | 2245 | ret = ebt_compat_init_offsets(tmp.nentries); |
| 2238 | ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); | 2246 | if (ret < 0) |
| 2239 | if (ret < 0) | 2247 | goto out_unlock; |
| 2240 | goto out_unlock; | ||
| 2241 | } | ||
| 2242 | 2248 | ||
| 2243 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); | 2249 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
| 2244 | if (ret < 0) | 2250 | if (ret < 0) |
| @@ -2261,8 +2267,10 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
| 2261 | state.buf_kern_len = size64; | 2267 | state.buf_kern_len = size64; |
| 2262 | 2268 | ||
| 2263 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); | 2269 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
| 2264 | if (WARN_ON(ret < 0)) | 2270 | if (WARN_ON(ret < 0)) { |
| 2271 | vfree(entries_tmp); | ||
| 2265 | goto out_unlock; | 2272 | goto out_unlock; |
| 2273 | } | ||
| 2266 | 2274 | ||
| 2267 | vfree(entries_tmp); | 2275 | vfree(entries_tmp); |
| 2268 | tmp.entries_size = size64; | 2276 | tmp.entries_size = size64; |
diff --git a/net/bridge/netfilter/nft_meta_bridge.c b/net/bridge/netfilter/nft_meta_bridge.c index bed66f536b34..7c9e92b2f806 100644 --- a/net/bridge/netfilter/nft_meta_bridge.c +++ b/net/bridge/netfilter/nft_meta_bridge.c | |||
| @@ -30,13 +30,9 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr, | |||
| 30 | switch (priv->key) { | 30 | switch (priv->key) { |
| 31 | case NFT_META_BRI_IIFNAME: | 31 | case NFT_META_BRI_IIFNAME: |
| 32 | br_dev = nft_meta_get_bridge(in); | 32 | br_dev = nft_meta_get_bridge(in); |
| 33 | if (!br_dev) | ||
| 34 | goto err; | ||
| 35 | break; | 33 | break; |
| 36 | case NFT_META_BRI_OIFNAME: | 34 | case NFT_META_BRI_OIFNAME: |
| 37 | br_dev = nft_meta_get_bridge(out); | 35 | br_dev = nft_meta_get_bridge(out); |
| 38 | if (!br_dev) | ||
| 39 | goto err; | ||
| 40 | break; | 36 | break; |
| 41 | case NFT_META_BRI_IIFPVID: { | 37 | case NFT_META_BRI_IIFPVID: { |
| 42 | u16 p_pvid; | 38 | u16 p_pvid; |
| @@ -57,17 +53,15 @@ static void nft_meta_bridge_get_eval(const struct nft_expr *expr, | |||
| 57 | goto err; | 53 | goto err; |
| 58 | 54 | ||
| 59 | br_vlan_get_proto(br_dev, &p_proto); | 55 | br_vlan_get_proto(br_dev, &p_proto); |
| 60 | nft_reg_store16(dest, p_proto); | 56 | nft_reg_store16(dest, htons(p_proto)); |
| 61 | return; | 57 | return; |
| 62 | } | 58 | } |
| 63 | default: | 59 | default: |
| 64 | goto out; | 60 | return nft_meta_get_eval(expr, regs, pkt); |
| 65 | } | 61 | } |
| 66 | 62 | ||
| 67 | strncpy((char *)dest, br_dev->name, IFNAMSIZ); | 63 | strncpy((char *)dest, br_dev ? br_dev->name : "", IFNAMSIZ); |
| 68 | return; | 64 | return; |
| 69 | out: | ||
| 70 | return nft_meta_get_eval(expr, regs, pkt); | ||
| 71 | err: | 65 | err: |
| 72 | regs->verdict.code = NFT_BREAK; | 66 | regs->verdict.code = NFT_BREAK; |
| 73 | } | 67 | } |
diff --git a/net/can/gw.c b/net/can/gw.c index 5275ddf580bc..72711053ebe6 100644 --- a/net/can/gw.c +++ b/net/can/gw.c | |||
| @@ -1046,32 +1046,50 @@ static __init int cgw_module_init(void) | |||
| 1046 | pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n", | 1046 | pr_info("can: netlink gateway (rev " CAN_GW_VERSION ") max_hops=%d\n", |
| 1047 | max_hops); | 1047 | max_hops); |
| 1048 | 1048 | ||
| 1049 | register_pernet_subsys(&cangw_pernet_ops); | 1049 | ret = register_pernet_subsys(&cangw_pernet_ops); |
| 1050 | if (ret) | ||
| 1051 | return ret; | ||
| 1052 | |||
| 1053 | ret = -ENOMEM; | ||
| 1050 | cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job), | 1054 | cgw_cache = kmem_cache_create("can_gw", sizeof(struct cgw_job), |
| 1051 | 0, 0, NULL); | 1055 | 0, 0, NULL); |
| 1052 | |||
| 1053 | if (!cgw_cache) | 1056 | if (!cgw_cache) |
| 1054 | return -ENOMEM; | 1057 | goto out_cache_create; |
| 1055 | 1058 | ||
| 1056 | /* set notifier */ | 1059 | /* set notifier */ |
| 1057 | notifier.notifier_call = cgw_notifier; | 1060 | notifier.notifier_call = cgw_notifier; |
| 1058 | register_netdevice_notifier(¬ifier); | 1061 | ret = register_netdevice_notifier(¬ifier); |
| 1062 | if (ret) | ||
| 1063 | goto out_register_notifier; | ||
| 1059 | 1064 | ||
| 1060 | ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_GETROUTE, | 1065 | ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_GETROUTE, |
| 1061 | NULL, cgw_dump_jobs, 0); | 1066 | NULL, cgw_dump_jobs, 0); |
| 1062 | if (ret) { | 1067 | if (ret) |
| 1063 | unregister_netdevice_notifier(¬ifier); | 1068 | goto out_rtnl_register1; |
| 1064 | kmem_cache_destroy(cgw_cache); | 1069 | |
| 1065 | return -ENOBUFS; | 1070 | ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE, |
| 1066 | } | 1071 | cgw_create_job, NULL, 0); |
| 1067 | 1072 | if (ret) | |
| 1068 | /* Only the first call to rtnl_register_module can fail */ | 1073 | goto out_rtnl_register2; |
| 1069 | rtnl_register_module(THIS_MODULE, PF_CAN, RTM_NEWROUTE, | 1074 | ret = rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE, |
| 1070 | cgw_create_job, NULL, 0); | 1075 | cgw_remove_job, NULL, 0); |
| 1071 | rtnl_register_module(THIS_MODULE, PF_CAN, RTM_DELROUTE, | 1076 | if (ret) |
| 1072 | cgw_remove_job, NULL, 0); | 1077 | goto out_rtnl_register3; |
| 1073 | 1078 | ||
| 1074 | return 0; | 1079 | return 0; |
| 1080 | |||
| 1081 | out_rtnl_register3: | ||
| 1082 | rtnl_unregister(PF_CAN, RTM_NEWROUTE); | ||
| 1083 | out_rtnl_register2: | ||
| 1084 | rtnl_unregister(PF_CAN, RTM_GETROUTE); | ||
| 1085 | out_rtnl_register1: | ||
| 1086 | unregister_netdevice_notifier(¬ifier); | ||
| 1087 | out_register_notifier: | ||
| 1088 | kmem_cache_destroy(cgw_cache); | ||
| 1089 | out_cache_create: | ||
| 1090 | unregister_pernet_subsys(&cangw_pernet_ops); | ||
| 1091 | |||
| 1092 | return ret; | ||
| 1075 | } | 1093 | } |
| 1076 | 1094 | ||
| 1077 | static __exit void cgw_module_exit(void) | 1095 | static __exit void cgw_module_exit(void) |
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 5d6724cee38f..4f75df40fb12 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
| @@ -136,8 +136,10 @@ void ceph_crypto_key_destroy(struct ceph_crypto_key *key) | |||
| 136 | if (key) { | 136 | if (key) { |
| 137 | kfree(key->key); | 137 | kfree(key->key); |
| 138 | key->key = NULL; | 138 | key->key = NULL; |
| 139 | crypto_free_sync_skcipher(key->tfm); | 139 | if (key->tfm) { |
| 140 | key->tfm = NULL; | 140 | crypto_free_sync_skcipher(key->tfm); |
| 141 | key->tfm = NULL; | ||
| 142 | } | ||
| 141 | } | 143 | } |
| 142 | } | 144 | } |
| 143 | 145 | ||
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 0b2df09b2554..78ae6e8c953d 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
| @@ -1496,7 +1496,7 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc, | |||
| 1496 | struct ceph_osds up, acting; | 1496 | struct ceph_osds up, acting; |
| 1497 | bool force_resend = false; | 1497 | bool force_resend = false; |
| 1498 | bool unpaused = false; | 1498 | bool unpaused = false; |
| 1499 | bool legacy_change; | 1499 | bool legacy_change = false; |
| 1500 | bool split = false; | 1500 | bool split = false; |
| 1501 | bool sort_bitwise = ceph_osdmap_flag(osdc, CEPH_OSDMAP_SORTBITWISE); | 1501 | bool sort_bitwise = ceph_osdmap_flag(osdc, CEPH_OSDMAP_SORTBITWISE); |
| 1502 | bool recovery_deletes = ceph_osdmap_flag(osdc, | 1502 | bool recovery_deletes = ceph_osdmap_flag(osdc, |
| @@ -1584,15 +1584,14 @@ static enum calc_target_result calc_target(struct ceph_osd_client *osdc, | |||
| 1584 | t->osd = acting.primary; | 1584 | t->osd = acting.primary; |
| 1585 | } | 1585 | } |
| 1586 | 1586 | ||
| 1587 | if (unpaused || legacy_change || force_resend || | 1587 | if (unpaused || legacy_change || force_resend || split) |
| 1588 | (split && con && CEPH_HAVE_FEATURE(con->peer_features, | ||
| 1589 | RESEND_ON_SPLIT))) | ||
| 1590 | ct_res = CALC_TARGET_NEED_RESEND; | 1588 | ct_res = CALC_TARGET_NEED_RESEND; |
| 1591 | else | 1589 | else |
| 1592 | ct_res = CALC_TARGET_NO_ACTION; | 1590 | ct_res = CALC_TARGET_NO_ACTION; |
| 1593 | 1591 | ||
| 1594 | out: | 1592 | out: |
| 1595 | dout("%s t %p -> ct_res %d osd %d\n", __func__, t, ct_res, t->osd); | 1593 | dout("%s t %p -> %d%d%d%d ct_res %d osd%d\n", __func__, t, unpaused, |
| 1594 | legacy_change, force_resend, split, ct_res, t->osd); | ||
| 1596 | return ct_res; | 1595 | return ct_res; |
| 1597 | } | 1596 | } |
| 1598 | 1597 | ||
diff --git a/net/core/dev.c b/net/core/dev.c index fc676b2610e3..0891f499c1bb 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -4374,12 +4374,17 @@ static u32 netif_receive_generic_xdp(struct sk_buff *skb, | |||
| 4374 | 4374 | ||
| 4375 | act = bpf_prog_run_xdp(xdp_prog, xdp); | 4375 | act = bpf_prog_run_xdp(xdp_prog, xdp); |
| 4376 | 4376 | ||
| 4377 | /* check if bpf_xdp_adjust_head was used */ | ||
| 4377 | off = xdp->data - orig_data; | 4378 | off = xdp->data - orig_data; |
| 4378 | if (off > 0) | 4379 | if (off) { |
| 4379 | __skb_pull(skb, off); | 4380 | if (off > 0) |
| 4380 | else if (off < 0) | 4381 | __skb_pull(skb, off); |
| 4381 | __skb_push(skb, -off); | 4382 | else if (off < 0) |
| 4382 | skb->mac_header += off; | 4383 | __skb_push(skb, -off); |
| 4384 | |||
| 4385 | skb->mac_header += off; | ||
| 4386 | skb_reset_network_header(skb); | ||
| 4387 | } | ||
| 4383 | 4388 | ||
| 4384 | /* check if bpf_xdp_adjust_tail was used. it can only "shrink" | 4389 | /* check if bpf_xdp_adjust_tail was used. it can only "shrink" |
| 4385 | * pckt. | 4390 | * pckt. |
| @@ -9701,6 +9706,8 @@ static void __net_exit default_device_exit(struct net *net) | |||
| 9701 | 9706 | ||
| 9702 | /* Push remaining network devices to init_net */ | 9707 | /* Push remaining network devices to init_net */ |
| 9703 | snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); | 9708 | snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); |
| 9709 | if (__dev_get_by_name(&init_net, fb_name)) | ||
| 9710 | snprintf(fb_name, IFNAMSIZ, "dev%%d"); | ||
| 9704 | err = dev_change_net_namespace(dev, &init_net, fb_name); | 9711 | err = dev_change_net_namespace(dev, &init_net, fb_name); |
| 9705 | if (err) { | 9712 | if (err) { |
| 9706 | pr_emerg("%s: failed to move %s to init_net: %d\n", | 9713 | pr_emerg("%s: failed to move %s to init_net: %d\n", |
diff --git a/net/core/filter.c b/net/core/filter.c index 4e2a79b2fd77..4c6a252d4212 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -7455,12 +7455,12 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type, | |||
| 7455 | case offsetof(struct __sk_buff, gso_segs): | 7455 | case offsetof(struct __sk_buff, gso_segs): |
| 7456 | /* si->dst_reg = skb_shinfo(SKB); */ | 7456 | /* si->dst_reg = skb_shinfo(SKB); */ |
| 7457 | #ifdef NET_SKBUFF_DATA_USES_OFFSET | 7457 | #ifdef NET_SKBUFF_DATA_USES_OFFSET |
| 7458 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head), | ||
| 7459 | si->dst_reg, si->src_reg, | ||
| 7460 | offsetof(struct sk_buff, head)); | ||
| 7461 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end), | 7458 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end), |
| 7462 | BPF_REG_AX, si->src_reg, | 7459 | BPF_REG_AX, si->src_reg, |
| 7463 | offsetof(struct sk_buff, end)); | 7460 | offsetof(struct sk_buff, end)); |
| 7461 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, head), | ||
| 7462 | si->dst_reg, si->src_reg, | ||
| 7463 | offsetof(struct sk_buff, head)); | ||
| 7464 | *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX); | 7464 | *insn++ = BPF_ALU64_REG(BPF_ADD, si->dst_reg, BPF_REG_AX); |
| 7465 | #else | 7465 | #else |
| 7466 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end), | 7466 | *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, end), |
| @@ -8757,13 +8757,13 @@ sk_reuseport_is_valid_access(int off, int size, | |||
| 8757 | return size == size_default; | 8757 | return size == size_default; |
| 8758 | 8758 | ||
| 8759 | /* Fields that allow narrowing */ | 8759 | /* Fields that allow narrowing */ |
| 8760 | case offsetof(struct sk_reuseport_md, eth_protocol): | 8760 | case bpf_ctx_range(struct sk_reuseport_md, eth_protocol): |
| 8761 | if (size < FIELD_SIZEOF(struct sk_buff, protocol)) | 8761 | if (size < FIELD_SIZEOF(struct sk_buff, protocol)) |
| 8762 | return false; | 8762 | return false; |
| 8763 | /* fall through */ | 8763 | /* fall through */ |
| 8764 | case offsetof(struct sk_reuseport_md, ip_protocol): | 8764 | case bpf_ctx_range(struct sk_reuseport_md, ip_protocol): |
| 8765 | case offsetof(struct sk_reuseport_md, bind_inany): | 8765 | case bpf_ctx_range(struct sk_reuseport_md, bind_inany): |
| 8766 | case offsetof(struct sk_reuseport_md, len): | 8766 | case bpf_ctx_range(struct sk_reuseport_md, len): |
| 8767 | bpf_ctx_record_field_size(info, size_default); | 8767 | bpf_ctx_record_field_size(info, size_default); |
| 8768 | return bpf_ctx_narrow_access_ok(off, size, size_default); | 8768 | return bpf_ctx_narrow_access_ok(off, size, size_default); |
| 8769 | 8769 | ||
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 3e6fedb57bc1..2470b4b404e6 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
| @@ -142,8 +142,8 @@ int skb_flow_dissector_bpf_prog_detach(const union bpf_attr *attr) | |||
| 142 | mutex_unlock(&flow_dissector_mutex); | 142 | mutex_unlock(&flow_dissector_mutex); |
| 143 | return -ENOENT; | 143 | return -ENOENT; |
| 144 | } | 144 | } |
| 145 | bpf_prog_put(attached); | ||
| 146 | RCU_INIT_POINTER(net->flow_dissector_prog, NULL); | 145 | RCU_INIT_POINTER(net->flow_dissector_prog, NULL); |
| 146 | bpf_prog_put(attached); | ||
| 147 | mutex_unlock(&flow_dissector_mutex); | 147 | mutex_unlock(&flow_dissector_mutex); |
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 2cf27da1baeb..849380a622ef 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -122,7 +122,7 @@ static void queue_process(struct work_struct *work) | |||
| 122 | txq = netdev_get_tx_queue(dev, q_index); | 122 | txq = netdev_get_tx_queue(dev, q_index); |
| 123 | HARD_TX_LOCK(dev, txq, smp_processor_id()); | 123 | HARD_TX_LOCK(dev, txq, smp_processor_id()); |
| 124 | if (netif_xmit_frozen_or_stopped(txq) || | 124 | if (netif_xmit_frozen_or_stopped(txq) || |
| 125 | netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) { | 125 | !dev_xmit_complete(netpoll_start_xmit(skb, dev, txq))) { |
| 126 | skb_queue_head(&npinfo->txq, skb); | 126 | skb_queue_head(&npinfo->txq, skb); |
| 127 | HARD_TX_UNLOCK(dev, txq); | 127 | HARD_TX_UNLOCK(dev, txq); |
| 128 | local_irq_restore(flags); | 128 | local_irq_restore(flags); |
| @@ -335,7 +335,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 335 | 335 | ||
| 336 | HARD_TX_UNLOCK(dev, txq); | 336 | HARD_TX_UNLOCK(dev, txq); |
| 337 | 337 | ||
| 338 | if (status == NETDEV_TX_OK) | 338 | if (dev_xmit_complete(status)) |
| 339 | break; | 339 | break; |
| 340 | 340 | ||
| 341 | } | 341 | } |
| @@ -352,7 +352,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 352 | 352 | ||
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | if (status != NETDEV_TX_OK) { | 355 | if (!dev_xmit_complete(status)) { |
| 356 | skb_queue_tail(&npinfo->txq, skb); | 356 | skb_queue_tail(&npinfo->txq, skb); |
| 357 | schedule_delayed_work(&npinfo->tx_work,0); | 357 | schedule_delayed_work(&npinfo->tx_work,0); |
| 358 | } | 358 | } |
diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 93bffaad2135..6832eeb4b785 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c | |||
| @@ -585,12 +585,12 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy); | |||
| 585 | 585 | ||
| 586 | void sk_psock_drop(struct sock *sk, struct sk_psock *psock) | 586 | void sk_psock_drop(struct sock *sk, struct sk_psock *psock) |
| 587 | { | 587 | { |
| 588 | rcu_assign_sk_user_data(sk, NULL); | ||
| 589 | sk_psock_cork_free(psock); | 588 | sk_psock_cork_free(psock); |
| 590 | sk_psock_zap_ingress(psock); | 589 | sk_psock_zap_ingress(psock); |
| 591 | sk_psock_restore_proto(sk, psock); | ||
| 592 | 590 | ||
| 593 | write_lock_bh(&sk->sk_callback_lock); | 591 | write_lock_bh(&sk->sk_callback_lock); |
| 592 | sk_psock_restore_proto(sk, psock); | ||
| 593 | rcu_assign_sk_user_data(sk, NULL); | ||
| 594 | if (psock->progs.skb_parser) | 594 | if (psock->progs.skb_parser) |
| 595 | sk_psock_stop_strp(sk, psock); | 595 | sk_psock_stop_strp(sk, psock); |
| 596 | write_unlock_bh(&sk->sk_callback_lock); | 596 | write_unlock_bh(&sk->sk_callback_lock); |
diff --git a/net/core/sock.c b/net/core/sock.c index d57b0cc995a0..545fac19a711 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -1992,6 +1992,19 @@ void skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | |||
| 1992 | } | 1992 | } |
| 1993 | EXPORT_SYMBOL(skb_set_owner_w); | 1993 | EXPORT_SYMBOL(skb_set_owner_w); |
| 1994 | 1994 | ||
| 1995 | static bool can_skb_orphan_partial(const struct sk_buff *skb) | ||
| 1996 | { | ||
| 1997 | #ifdef CONFIG_TLS_DEVICE | ||
| 1998 | /* Drivers depend on in-order delivery for crypto offload, | ||
| 1999 | * partial orphan breaks out-of-order-OK logic. | ||
| 2000 | */ | ||
| 2001 | if (skb->decrypted) | ||
| 2002 | return false; | ||
| 2003 | #endif | ||
| 2004 | return (skb->destructor == sock_wfree || | ||
| 2005 | (IS_ENABLED(CONFIG_INET) && skb->destructor == tcp_wfree)); | ||
| 2006 | } | ||
| 2007 | |||
| 1995 | /* This helper is used by netem, as it can hold packets in its | 2008 | /* This helper is used by netem, as it can hold packets in its |
| 1996 | * delay queue. We want to allow the owner socket to send more | 2009 | * delay queue. We want to allow the owner socket to send more |
| 1997 | * packets, as if they were already TX completed by a typical driver. | 2010 | * packets, as if they were already TX completed by a typical driver. |
| @@ -2003,11 +2016,7 @@ void skb_orphan_partial(struct sk_buff *skb) | |||
| 2003 | if (skb_is_tcp_pure_ack(skb)) | 2016 | if (skb_is_tcp_pure_ack(skb)) |
| 2004 | return; | 2017 | return; |
| 2005 | 2018 | ||
| 2006 | if (skb->destructor == sock_wfree | 2019 | if (can_skb_orphan_partial(skb)) { |
| 2007 | #ifdef CONFIG_INET | ||
| 2008 | || skb->destructor == tcp_wfree | ||
| 2009 | #endif | ||
| 2010 | ) { | ||
| 2011 | struct sock *sk = skb->sk; | 2020 | struct sock *sk = skb->sk; |
| 2012 | 2021 | ||
| 2013 | if (refcount_inc_not_zero(&sk->sk_refcnt)) { | 2022 | if (refcount_inc_not_zero(&sk->sk_refcnt)) { |
| @@ -3278,16 +3287,17 @@ static __init int net_inuse_init(void) | |||
| 3278 | 3287 | ||
| 3279 | core_initcall(net_inuse_init); | 3288 | core_initcall(net_inuse_init); |
| 3280 | 3289 | ||
| 3281 | static void assign_proto_idx(struct proto *prot) | 3290 | static int assign_proto_idx(struct proto *prot) |
| 3282 | { | 3291 | { |
| 3283 | prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR); | 3292 | prot->inuse_idx = find_first_zero_bit(proto_inuse_idx, PROTO_INUSE_NR); |
| 3284 | 3293 | ||
| 3285 | if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) { | 3294 | if (unlikely(prot->inuse_idx == PROTO_INUSE_NR - 1)) { |
| 3286 | pr_err("PROTO_INUSE_NR exhausted\n"); | 3295 | pr_err("PROTO_INUSE_NR exhausted\n"); |
| 3287 | return; | 3296 | return -ENOSPC; |
| 3288 | } | 3297 | } |
| 3289 | 3298 | ||
| 3290 | set_bit(prot->inuse_idx, proto_inuse_idx); | 3299 | set_bit(prot->inuse_idx, proto_inuse_idx); |
| 3300 | return 0; | ||
| 3291 | } | 3301 | } |
| 3292 | 3302 | ||
| 3293 | static void release_proto_idx(struct proto *prot) | 3303 | static void release_proto_idx(struct proto *prot) |
| @@ -3296,8 +3306,9 @@ static void release_proto_idx(struct proto *prot) | |||
| 3296 | clear_bit(prot->inuse_idx, proto_inuse_idx); | 3306 | clear_bit(prot->inuse_idx, proto_inuse_idx); |
| 3297 | } | 3307 | } |
| 3298 | #else | 3308 | #else |
| 3299 | static inline void assign_proto_idx(struct proto *prot) | 3309 | static inline int assign_proto_idx(struct proto *prot) |
| 3300 | { | 3310 | { |
| 3311 | return 0; | ||
| 3301 | } | 3312 | } |
| 3302 | 3313 | ||
| 3303 | static inline void release_proto_idx(struct proto *prot) | 3314 | static inline void release_proto_idx(struct proto *prot) |
| @@ -3346,6 +3357,8 @@ static int req_prot_init(const struct proto *prot) | |||
| 3346 | 3357 | ||
| 3347 | int proto_register(struct proto *prot, int alloc_slab) | 3358 | int proto_register(struct proto *prot, int alloc_slab) |
| 3348 | { | 3359 | { |
| 3360 | int ret = -ENOBUFS; | ||
| 3361 | |||
| 3349 | if (alloc_slab) { | 3362 | if (alloc_slab) { |
| 3350 | prot->slab = kmem_cache_create_usercopy(prot->name, | 3363 | prot->slab = kmem_cache_create_usercopy(prot->name, |
| 3351 | prot->obj_size, 0, | 3364 | prot->obj_size, 0, |
| @@ -3382,20 +3395,27 @@ int proto_register(struct proto *prot, int alloc_slab) | |||
| 3382 | } | 3395 | } |
| 3383 | 3396 | ||
| 3384 | mutex_lock(&proto_list_mutex); | 3397 | mutex_lock(&proto_list_mutex); |
| 3398 | ret = assign_proto_idx(prot); | ||
| 3399 | if (ret) { | ||
| 3400 | mutex_unlock(&proto_list_mutex); | ||
| 3401 | goto out_free_timewait_sock_slab_name; | ||
| 3402 | } | ||
| 3385 | list_add(&prot->node, &proto_list); | 3403 | list_add(&prot->node, &proto_list); |
| 3386 | assign_proto_idx(prot); | ||
| 3387 | mutex_unlock(&proto_list_mutex); | 3404 | mutex_unlock(&proto_list_mutex); |
| 3388 | return 0; | 3405 | return ret; |
| 3389 | 3406 | ||
| 3390 | out_free_timewait_sock_slab_name: | 3407 | out_free_timewait_sock_slab_name: |
| 3391 | kfree(prot->twsk_prot->twsk_slab_name); | 3408 | if (alloc_slab && prot->twsk_prot) |
| 3409 | kfree(prot->twsk_prot->twsk_slab_name); | ||
| 3392 | out_free_request_sock_slab: | 3410 | out_free_request_sock_slab: |
| 3393 | req_prot_cleanup(prot->rsk_prot); | 3411 | if (alloc_slab) { |
| 3412 | req_prot_cleanup(prot->rsk_prot); | ||
| 3394 | 3413 | ||
| 3395 | kmem_cache_destroy(prot->slab); | 3414 | kmem_cache_destroy(prot->slab); |
| 3396 | prot->slab = NULL; | 3415 | prot->slab = NULL; |
| 3416 | } | ||
| 3397 | out: | 3417 | out: |
| 3398 | return -ENOBUFS; | 3418 | return ret; |
| 3399 | } | 3419 | } |
| 3400 | EXPORT_SYMBOL(proto_register); | 3420 | EXPORT_SYMBOL(proto_register); |
| 3401 | 3421 | ||
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 3312a5849a97..c13ffbd33d8d 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c | |||
| @@ -19,6 +19,7 @@ static const struct sock_diag_handler *sock_diag_handlers[AF_MAX]; | |||
| 19 | static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); | 19 | static int (*inet_rcv_compat)(struct sk_buff *skb, struct nlmsghdr *nlh); |
| 20 | static DEFINE_MUTEX(sock_diag_table_mutex); | 20 | static DEFINE_MUTEX(sock_diag_table_mutex); |
| 21 | static struct workqueue_struct *broadcast_wq; | 21 | static struct workqueue_struct *broadcast_wq; |
| 22 | static atomic64_t cookie_gen; | ||
| 22 | 23 | ||
| 23 | u64 sock_gen_cookie(struct sock *sk) | 24 | u64 sock_gen_cookie(struct sock *sk) |
| 24 | { | 25 | { |
| @@ -27,7 +28,7 @@ u64 sock_gen_cookie(struct sock *sk) | |||
| 27 | 28 | ||
| 28 | if (res) | 29 | if (res) |
| 29 | return res; | 30 | return res; |
| 30 | res = atomic64_inc_return(&sock_net(sk)->cookie_gen); | 31 | res = atomic64_inc_return(&cookie_gen); |
| 31 | atomic64_cmpxchg(&sk->sk_cookie, 0, res); | 32 | atomic64_cmpxchg(&sk->sk_cookie, 0, res); |
| 32 | } | 33 | } |
| 33 | } | 34 | } |
diff --git a/net/core/sock_map.c b/net/core/sock_map.c index 52d4faeee18b..1330a7442e5b 100644 --- a/net/core/sock_map.c +++ b/net/core/sock_map.c | |||
| @@ -247,6 +247,8 @@ static void sock_map_free(struct bpf_map *map) | |||
| 247 | raw_spin_unlock_bh(&stab->lock); | 247 | raw_spin_unlock_bh(&stab->lock); |
| 248 | rcu_read_unlock(); | 248 | rcu_read_unlock(); |
| 249 | 249 | ||
| 250 | synchronize_rcu(); | ||
| 251 | |||
| 250 | bpf_map_area_free(stab->sks); | 252 | bpf_map_area_free(stab->sks); |
| 251 | kfree(stab); | 253 | kfree(stab); |
| 252 | } | 254 | } |
| @@ -276,16 +278,20 @@ static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test, | |||
| 276 | struct sock **psk) | 278 | struct sock **psk) |
| 277 | { | 279 | { |
| 278 | struct sock *sk; | 280 | struct sock *sk; |
| 281 | int err = 0; | ||
| 279 | 282 | ||
| 280 | raw_spin_lock_bh(&stab->lock); | 283 | raw_spin_lock_bh(&stab->lock); |
| 281 | sk = *psk; | 284 | sk = *psk; |
| 282 | if (!sk_test || sk_test == sk) | 285 | if (!sk_test || sk_test == sk) |
| 283 | *psk = NULL; | 286 | sk = xchg(psk, NULL); |
| 287 | |||
| 288 | if (likely(sk)) | ||
| 289 | sock_map_unref(sk, psk); | ||
| 290 | else | ||
| 291 | err = -EINVAL; | ||
| 292 | |||
| 284 | raw_spin_unlock_bh(&stab->lock); | 293 | raw_spin_unlock_bh(&stab->lock); |
| 285 | if (unlikely(!sk)) | 294 | return err; |
| 286 | return -EINVAL; | ||
| 287 | sock_map_unref(sk, psk); | ||
| 288 | return 0; | ||
| 289 | } | 295 | } |
| 290 | 296 | ||
| 291 | static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk, | 297 | static void sock_map_delete_from_link(struct bpf_map *map, struct sock *sk, |
| @@ -328,6 +334,7 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx, | |||
| 328 | struct sock *sk, u64 flags) | 334 | struct sock *sk, u64 flags) |
| 329 | { | 335 | { |
| 330 | struct bpf_stab *stab = container_of(map, struct bpf_stab, map); | 336 | struct bpf_stab *stab = container_of(map, struct bpf_stab, map); |
| 337 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
| 331 | struct sk_psock_link *link; | 338 | struct sk_psock_link *link; |
| 332 | struct sk_psock *psock; | 339 | struct sk_psock *psock; |
| 333 | struct sock *osk; | 340 | struct sock *osk; |
| @@ -338,6 +345,8 @@ static int sock_map_update_common(struct bpf_map *map, u32 idx, | |||
| 338 | return -EINVAL; | 345 | return -EINVAL; |
| 339 | if (unlikely(idx >= map->max_entries)) | 346 | if (unlikely(idx >= map->max_entries)) |
| 340 | return -E2BIG; | 347 | return -E2BIG; |
| 348 | if (unlikely(icsk->icsk_ulp_data)) | ||
| 349 | return -EINVAL; | ||
| 341 | 350 | ||
| 342 | link = sk_psock_init_link(); | 351 | link = sk_psock_init_link(); |
| 343 | if (!link) | 352 | if (!link) |
diff --git a/net/core/stream.c b/net/core/stream.c index e94bb02a5629..4f1d4aa5fb38 100644 --- a/net/core/stream.c +++ b/net/core/stream.c | |||
| @@ -120,7 +120,6 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
| 120 | int err = 0; | 120 | int err = 0; |
| 121 | long vm_wait = 0; | 121 | long vm_wait = 0; |
| 122 | long current_timeo = *timeo_p; | 122 | long current_timeo = *timeo_p; |
| 123 | bool noblock = (*timeo_p ? false : true); | ||
| 124 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | 123 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| 125 | 124 | ||
| 126 | if (sk_stream_memory_free(sk)) | 125 | if (sk_stream_memory_free(sk)) |
| @@ -133,11 +132,8 @@ int sk_stream_wait_memory(struct sock *sk, long *timeo_p) | |||
| 133 | 132 | ||
| 134 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) | 133 | if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) |
| 135 | goto do_error; | 134 | goto do_error; |
| 136 | if (!*timeo_p) { | 135 | if (!*timeo_p) |
| 137 | if (noblock) | 136 | goto do_eagain; |
| 138 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
| 139 | goto do_nonblock; | ||
| 140 | } | ||
| 141 | if (signal_pending(current)) | 137 | if (signal_pending(current)) |
| 142 | goto do_interrupted; | 138 | goto do_interrupted; |
| 143 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); | 139 | sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
| @@ -169,7 +165,13 @@ out: | |||
| 169 | do_error: | 165 | do_error: |
| 170 | err = -EPIPE; | 166 | err = -EPIPE; |
| 171 | goto out; | 167 | goto out; |
| 172 | do_nonblock: | 168 | do_eagain: |
| 169 | /* Make sure that whenever EAGAIN is returned, EPOLLOUT event can | ||
| 170 | * be generated later. | ||
| 171 | * When TCP receives ACK packets that make room, tcp_check_space() | ||
| 172 | * only calls tcp_new_space() if SOCK_NOSPACE is set. | ||
| 173 | */ | ||
| 174 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | ||
| 173 | err = -EAGAIN; | 175 | err = -EAGAIN; |
| 174 | goto out; | 176 | goto out; |
| 175 | do_interrupted: | 177 | do_interrupted: |
diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 4ec5b7f85d51..09d9286b27cc 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c | |||
| @@ -153,6 +153,9 @@ static void dsa_switch_mdb_add_bitmap(struct dsa_switch *ds, | |||
| 153 | { | 153 | { |
| 154 | int port; | 154 | int port; |
| 155 | 155 | ||
| 156 | if (!ds->ops->port_mdb_add) | ||
| 157 | return; | ||
| 158 | |||
| 156 | for_each_set_bit(port, bitmap, ds->num_ports) | 159 | for_each_set_bit(port, bitmap, ds->num_ports) |
| 157 | ds->ops->port_mdb_add(ds, port, mdb); | 160 | ds->ops->port_mdb_add(ds, port, mdb); |
| 158 | } | 161 | } |
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c index 6ebbd799c4eb..67a1bc635a7b 100644 --- a/net/dsa/tag_8021q.c +++ b/net/dsa/tag_8021q.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | * | 28 | * |
| 29 | * RSV - VID[9]: | 29 | * RSV - VID[9]: |
| 30 | * To be used for further expansion of SWITCH_ID or for other purposes. | 30 | * To be used for further expansion of SWITCH_ID or for other purposes. |
| 31 | * Must be transmitted as zero and ignored on receive. | ||
| 31 | * | 32 | * |
| 32 | * SWITCH_ID - VID[8:6]: | 33 | * SWITCH_ID - VID[8:6]: |
| 33 | * Index of switch within DSA tree. Must be between 0 and | 34 | * Index of switch within DSA tree. Must be between 0 and |
| @@ -35,6 +36,7 @@ | |||
| 35 | * | 36 | * |
| 36 | * RSV - VID[5:4]: | 37 | * RSV - VID[5:4]: |
| 37 | * To be used for further expansion of PORT or for other purposes. | 38 | * To be used for further expansion of PORT or for other purposes. |
| 39 | * Must be transmitted as zero and ignored on receive. | ||
| 38 | * | 40 | * |
| 39 | * PORT - VID[3:0]: | 41 | * PORT - VID[3:0]: |
| 40 | * Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1. | 42 | * Index of switch port. Must be between 0 and DSA_MAX_PORTS - 1. |
diff --git a/net/dsa/tag_sja1105.c b/net/dsa/tag_sja1105.c index 26363d72d25b..47ee88163a9d 100644 --- a/net/dsa/tag_sja1105.c +++ b/net/dsa/tag_sja1105.c | |||
| @@ -165,6 +165,7 @@ static struct sk_buff | |||
| 165 | "Expected meta frame, is %12llx " | 165 | "Expected meta frame, is %12llx " |
| 166 | "in the DSA master multicast filter?\n", | 166 | "in the DSA master multicast filter?\n", |
| 167 | SJA1105_META_DMAC); | 167 | SJA1105_META_DMAC); |
| 168 | kfree_skb(sp->data->stampable_skb); | ||
| 168 | } | 169 | } |
| 169 | 170 | ||
| 170 | /* Hold a reference to avoid dsa_switch_rcv | 171 | /* Hold a reference to avoid dsa_switch_rcv |
| @@ -211,17 +212,8 @@ static struct sk_buff | |||
| 211 | * for further processing up the network stack. | 212 | * for further processing up the network stack. |
| 212 | */ | 213 | */ |
| 213 | kfree_skb(skb); | 214 | kfree_skb(skb); |
| 214 | 215 | skb = stampable_skb; | |
| 215 | skb = skb_copy(stampable_skb, GFP_ATOMIC); | ||
| 216 | if (!skb) { | ||
| 217 | dev_err_ratelimited(dp->ds->dev, | ||
| 218 | "Failed to copy stampable skb\n"); | ||
| 219 | spin_unlock(&sp->data->meta_lock); | ||
| 220 | return NULL; | ||
| 221 | } | ||
| 222 | sja1105_transfer_meta(skb, meta); | 216 | sja1105_transfer_meta(skb, meta); |
| 223 | /* The cached copy will be freed now */ | ||
| 224 | skb_unref(stampable_skb); | ||
| 225 | 217 | ||
| 226 | spin_unlock(&sp->data->meta_lock); | 218 | spin_unlock(&sp->data->meta_lock); |
| 227 | } | 219 | } |
diff --git a/net/ieee802154/6lowpan/reassembly.c b/net/ieee802154/6lowpan/reassembly.c index e4aba5d485be..bbe9b3b2d395 100644 --- a/net/ieee802154/6lowpan/reassembly.c +++ b/net/ieee802154/6lowpan/reassembly.c | |||
| @@ -170,7 +170,7 @@ static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *skb, | |||
| 170 | reasm_data = inet_frag_reasm_prepare(&fq->q, skb, prev_tail); | 170 | reasm_data = inet_frag_reasm_prepare(&fq->q, skb, prev_tail); |
| 171 | if (!reasm_data) | 171 | if (!reasm_data) |
| 172 | goto out_oom; | 172 | goto out_oom; |
| 173 | inet_frag_reasm_finish(&fq->q, skb, reasm_data); | 173 | inet_frag_reasm_finish(&fq->q, skb, reasm_data, false); |
| 174 | 174 | ||
| 175 | skb->dev = ldev; | 175 | skb->dev = ldev; |
| 176 | skb->tstamp = fq->q.stamp; | 176 | skb->tstamp = fq->q.stamp; |
diff --git a/net/ieee802154/socket.c b/net/ieee802154/socket.c index dacbd58e1799..badc5cfe4dc6 100644 --- a/net/ieee802154/socket.c +++ b/net/ieee802154/socket.c | |||
| @@ -1092,7 +1092,7 @@ static struct packet_type ieee802154_packet_type = { | |||
| 1092 | 1092 | ||
| 1093 | static int __init af_ieee802154_init(void) | 1093 | static int __init af_ieee802154_init(void) |
| 1094 | { | 1094 | { |
| 1095 | int rc = -EINVAL; | 1095 | int rc; |
| 1096 | 1096 | ||
| 1097 | rc = proto_register(&ieee802154_raw_prot, 1); | 1097 | rc = proto_register(&ieee802154_raw_prot, 1); |
| 1098 | if (rc) | 1098 | if (rc) |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 2b2b3d291ab0..1ab2fb6bb37d 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -2145,7 +2145,7 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb, | |||
| 2145 | 2145 | ||
| 2146 | if (filter->dump_exceptions) { | 2146 | if (filter->dump_exceptions) { |
| 2147 | err = fib_dump_info_fnhe(skb, cb, tb->tb_id, fi, | 2147 | err = fib_dump_info_fnhe(skb, cb, tb->tb_id, fi, |
| 2148 | &i_fa, s_fa); | 2148 | &i_fa, s_fa, flags); |
| 2149 | if (err < 0) | 2149 | if (err < 0) |
| 2150 | goto stop; | 2150 | goto stop; |
| 2151 | } | 2151 | } |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 1510e951f451..4298aae74e0e 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
| @@ -582,7 +582,13 @@ void __icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info, | |||
| 582 | 582 | ||
| 583 | if (!rt) | 583 | if (!rt) |
| 584 | goto out; | 584 | goto out; |
| 585 | net = dev_net(rt->dst.dev); | 585 | |
| 586 | if (rt->dst.dev) | ||
| 587 | net = dev_net(rt->dst.dev); | ||
| 588 | else if (skb_in->dev) | ||
| 589 | net = dev_net(skb_in->dev); | ||
| 590 | else | ||
| 591 | goto out; | ||
| 586 | 592 | ||
| 587 | /* | 593 | /* |
| 588 | * Find the original header. It is expected to be valid, of course. | 594 | * Find the original header. It is expected to be valid, of course. |
| @@ -902,7 +908,7 @@ static bool icmp_redirect(struct sk_buff *skb) | |||
| 902 | return false; | 908 | return false; |
| 903 | } | 909 | } |
| 904 | 910 | ||
| 905 | icmp_socket_deliver(skb, icmp_hdr(skb)->un.gateway); | 911 | icmp_socket_deliver(skb, ntohl(icmp_hdr(skb)->un.gateway)); |
| 906 | return true; | 912 | return true; |
| 907 | } | 913 | } |
| 908 | 914 | ||
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 180f6896b98b..480d0b22db1a 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
| @@ -1475,7 +1475,7 @@ EXPORT_SYMBOL(__ip_mc_inc_group); | |||
| 1475 | 1475 | ||
| 1476 | void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) | 1476 | void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) |
| 1477 | { | 1477 | { |
| 1478 | __ip_mc_inc_group(in_dev, addr, MCAST_EXCLUDE); | 1478 | __ip_mc_inc_group(in_dev, addr, GFP_KERNEL); |
| 1479 | } | 1479 | } |
| 1480 | EXPORT_SYMBOL(ip_mc_inc_group); | 1480 | EXPORT_SYMBOL(ip_mc_inc_group); |
| 1481 | 1481 | ||
| @@ -2197,7 +2197,7 @@ static int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr, | |||
| 2197 | iml->sflist = NULL; | 2197 | iml->sflist = NULL; |
| 2198 | iml->sfmode = mode; | 2198 | iml->sfmode = mode; |
| 2199 | rcu_assign_pointer(inet->mc_list, iml); | 2199 | rcu_assign_pointer(inet->mc_list, iml); |
| 2200 | __ip_mc_inc_group(in_dev, addr, mode); | 2200 | ____ip_mc_inc_group(in_dev, addr, mode, GFP_KERNEL); |
| 2201 | err = 0; | 2201 | err = 0; |
| 2202 | done: | 2202 | done: |
| 2203 | return err; | 2203 | return err; |
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index d666756be5f1..10d31733297d 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
| @@ -331,7 +331,7 @@ struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key) | |||
| 331 | prev = rhashtable_lookup(&fqdir->rhashtable, key, fqdir->f->rhash_params); | 331 | prev = rhashtable_lookup(&fqdir->rhashtable, key, fqdir->f->rhash_params); |
| 332 | if (!prev) | 332 | if (!prev) |
| 333 | fq = inet_frag_create(fqdir, key, &prev); | 333 | fq = inet_frag_create(fqdir, key, &prev); |
| 334 | if (prev && !IS_ERR(prev)) { | 334 | if (!IS_ERR_OR_NULL(prev)) { |
| 335 | fq = prev; | 335 | fq = prev; |
| 336 | if (!refcount_inc_not_zero(&fq->refcnt)) | 336 | if (!refcount_inc_not_zero(&fq->refcnt)) |
| 337 | fq = NULL; | 337 | fq = NULL; |
| @@ -475,11 +475,12 @@ void *inet_frag_reasm_prepare(struct inet_frag_queue *q, struct sk_buff *skb, | |||
| 475 | EXPORT_SYMBOL(inet_frag_reasm_prepare); | 475 | EXPORT_SYMBOL(inet_frag_reasm_prepare); |
| 476 | 476 | ||
| 477 | void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head, | 477 | void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head, |
| 478 | void *reasm_data) | 478 | void *reasm_data, bool try_coalesce) |
| 479 | { | 479 | { |
| 480 | struct sk_buff **nextp = (struct sk_buff **)reasm_data; | 480 | struct sk_buff **nextp = (struct sk_buff **)reasm_data; |
| 481 | struct rb_node *rbn; | 481 | struct rb_node *rbn; |
| 482 | struct sk_buff *fp; | 482 | struct sk_buff *fp; |
| 483 | int sum_truesize; | ||
| 483 | 484 | ||
| 484 | skb_push(head, head->data - skb_network_header(head)); | 485 | skb_push(head, head->data - skb_network_header(head)); |
| 485 | 486 | ||
| @@ -487,25 +488,41 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head, | |||
| 487 | fp = FRAG_CB(head)->next_frag; | 488 | fp = FRAG_CB(head)->next_frag; |
| 488 | rbn = rb_next(&head->rbnode); | 489 | rbn = rb_next(&head->rbnode); |
| 489 | rb_erase(&head->rbnode, &q->rb_fragments); | 490 | rb_erase(&head->rbnode, &q->rb_fragments); |
| 491 | |||
| 492 | sum_truesize = head->truesize; | ||
| 490 | while (rbn || fp) { | 493 | while (rbn || fp) { |
| 491 | /* fp points to the next sk_buff in the current run; | 494 | /* fp points to the next sk_buff in the current run; |
| 492 | * rbn points to the next run. | 495 | * rbn points to the next run. |
| 493 | */ | 496 | */ |
| 494 | /* Go through the current run. */ | 497 | /* Go through the current run. */ |
| 495 | while (fp) { | 498 | while (fp) { |
| 496 | *nextp = fp; | 499 | struct sk_buff *next_frag = FRAG_CB(fp)->next_frag; |
| 497 | nextp = &fp->next; | 500 | bool stolen; |
| 498 | fp->prev = NULL; | 501 | int delta; |
| 499 | memset(&fp->rbnode, 0, sizeof(fp->rbnode)); | 502 | |
| 500 | fp->sk = NULL; | 503 | sum_truesize += fp->truesize; |
| 501 | head->data_len += fp->len; | ||
| 502 | head->len += fp->len; | ||
| 503 | if (head->ip_summed != fp->ip_summed) | 504 | if (head->ip_summed != fp->ip_summed) |
| 504 | head->ip_summed = CHECKSUM_NONE; | 505 | head->ip_summed = CHECKSUM_NONE; |
| 505 | else if (head->ip_summed == CHECKSUM_COMPLETE) | 506 | else if (head->ip_summed == CHECKSUM_COMPLETE) |
| 506 | head->csum = csum_add(head->csum, fp->csum); | 507 | head->csum = csum_add(head->csum, fp->csum); |
| 507 | head->truesize += fp->truesize; | 508 | |
| 508 | fp = FRAG_CB(fp)->next_frag; | 509 | if (try_coalesce && skb_try_coalesce(head, fp, &stolen, |
| 510 | &delta)) { | ||
| 511 | kfree_skb_partial(fp, stolen); | ||
| 512 | } else { | ||
| 513 | fp->prev = NULL; | ||
| 514 | memset(&fp->rbnode, 0, sizeof(fp->rbnode)); | ||
| 515 | fp->sk = NULL; | ||
| 516 | |||
| 517 | head->data_len += fp->len; | ||
| 518 | head->len += fp->len; | ||
| 519 | head->truesize += fp->truesize; | ||
| 520 | |||
| 521 | *nextp = fp; | ||
| 522 | nextp = &fp->next; | ||
| 523 | } | ||
| 524 | |||
| 525 | fp = next_frag; | ||
| 509 | } | 526 | } |
| 510 | /* Move to the next run. */ | 527 | /* Move to the next run. */ |
| 511 | if (rbn) { | 528 | if (rbn) { |
| @@ -516,7 +533,7 @@ void inet_frag_reasm_finish(struct inet_frag_queue *q, struct sk_buff *head, | |||
| 516 | rbn = rbnext; | 533 | rbn = rbnext; |
| 517 | } | 534 | } |
| 518 | } | 535 | } |
| 519 | sub_frag_mem_limit(q->fqdir, head->truesize); | 536 | sub_frag_mem_limit(q->fqdir, sum_truesize); |
| 520 | 537 | ||
| 521 | *nextp = NULL; | 538 | *nextp = NULL; |
| 522 | skb_mark_not_on_list(head); | 539 | skb_mark_not_on_list(head); |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 4385eb9e781f..cfeb8890f94e 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
| @@ -393,6 +393,11 @@ err: | |||
| 393 | return err; | 393 | return err; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | static bool ip_frag_coalesce_ok(const struct ipq *qp) | ||
| 397 | { | ||
| 398 | return qp->q.key.v4.user == IP_DEFRAG_LOCAL_DELIVER; | ||
| 399 | } | ||
| 400 | |||
| 396 | /* Build a new IP datagram from all its fragments. */ | 401 | /* Build a new IP datagram from all its fragments. */ |
| 397 | static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb, | 402 | static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb, |
| 398 | struct sk_buff *prev_tail, struct net_device *dev) | 403 | struct sk_buff *prev_tail, struct net_device *dev) |
| @@ -421,7 +426,8 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb, | |||
| 421 | if (len > 65535) | 426 | if (len > 65535) |
| 422 | goto out_oversize; | 427 | goto out_oversize; |
| 423 | 428 | ||
| 424 | inet_frag_reasm_finish(&qp->q, skb, reasm_data); | 429 | inet_frag_reasm_finish(&qp->q, skb, reasm_data, |
| 430 | ip_frag_coalesce_ok(qp)); | ||
| 425 | 431 | ||
| 426 | skb->dev = dev; | 432 | skb->dev = dev; |
| 427 | IPCB(skb)->frag_max_size = max(qp->max_df_size, qp->q.max_size); | 433 | IPCB(skb)->frag_max_size = max(qp->max_df_size, qp->q.max_size); |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 43adfc1641ba..2f01cf6fa0de 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
| @@ -275,6 +275,9 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, | |||
| 275 | const struct iphdr *tiph = &tunnel->parms.iph; | 275 | const struct iphdr *tiph = &tunnel->parms.iph; |
| 276 | u8 ipproto; | 276 | u8 ipproto; |
| 277 | 277 | ||
| 278 | if (!pskb_inet_may_pull(skb)) | ||
| 279 | goto tx_error; | ||
| 280 | |||
| 278 | switch (skb->protocol) { | 281 | switch (skb->protocol) { |
| 279 | case htons(ETH_P_IP): | 282 | case htons(ETH_P_IP): |
| 280 | ipproto = IPPROTO_IPIP; | 283 | ipproto = IPPROTO_IPIP; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 517300d587a7..b6a6f18c3dd1 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -2728,7 +2728,8 @@ EXPORT_SYMBOL_GPL(ip_route_output_flow); | |||
| 2728 | /* called with rcu_read_lock held */ | 2728 | /* called with rcu_read_lock held */ |
| 2729 | static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | 2729 | static int rt_fill_info(struct net *net, __be32 dst, __be32 src, |
| 2730 | struct rtable *rt, u32 table_id, struct flowi4 *fl4, | 2730 | struct rtable *rt, u32 table_id, struct flowi4 *fl4, |
| 2731 | struct sk_buff *skb, u32 portid, u32 seq) | 2731 | struct sk_buff *skb, u32 portid, u32 seq, |
| 2732 | unsigned int flags) | ||
| 2732 | { | 2733 | { |
| 2733 | struct rtmsg *r; | 2734 | struct rtmsg *r; |
| 2734 | struct nlmsghdr *nlh; | 2735 | struct nlmsghdr *nlh; |
| @@ -2736,7 +2737,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | |||
| 2736 | u32 error; | 2737 | u32 error; |
| 2737 | u32 metrics[RTAX_MAX]; | 2738 | u32 metrics[RTAX_MAX]; |
| 2738 | 2739 | ||
| 2739 | nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*r), 0); | 2740 | nlh = nlmsg_put(skb, portid, seq, RTM_NEWROUTE, sizeof(*r), flags); |
| 2740 | if (!nlh) | 2741 | if (!nlh) |
| 2741 | return -EMSGSIZE; | 2742 | return -EMSGSIZE; |
| 2742 | 2743 | ||
| @@ -2860,7 +2861,7 @@ nla_put_failure: | |||
| 2860 | static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb, | 2861 | static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb, |
| 2861 | struct netlink_callback *cb, u32 table_id, | 2862 | struct netlink_callback *cb, u32 table_id, |
| 2862 | struct fnhe_hash_bucket *bucket, int genid, | 2863 | struct fnhe_hash_bucket *bucket, int genid, |
| 2863 | int *fa_index, int fa_start) | 2864 | int *fa_index, int fa_start, unsigned int flags) |
| 2864 | { | 2865 | { |
| 2865 | int i; | 2866 | int i; |
| 2866 | 2867 | ||
| @@ -2891,7 +2892,7 @@ static int fnhe_dump_bucket(struct net *net, struct sk_buff *skb, | |||
| 2891 | err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt, | 2892 | err = rt_fill_info(net, fnhe->fnhe_daddr, 0, rt, |
| 2892 | table_id, NULL, skb, | 2893 | table_id, NULL, skb, |
| 2893 | NETLINK_CB(cb->skb).portid, | 2894 | NETLINK_CB(cb->skb).portid, |
| 2894 | cb->nlh->nlmsg_seq); | 2895 | cb->nlh->nlmsg_seq, flags); |
| 2895 | if (err) | 2896 | if (err) |
| 2896 | return err; | 2897 | return err; |
| 2897 | next: | 2898 | next: |
| @@ -2904,7 +2905,7 @@ next: | |||
| 2904 | 2905 | ||
| 2905 | int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb, | 2906 | int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb, |
| 2906 | u32 table_id, struct fib_info *fi, | 2907 | u32 table_id, struct fib_info *fi, |
| 2907 | int *fa_index, int fa_start) | 2908 | int *fa_index, int fa_start, unsigned int flags) |
| 2908 | { | 2909 | { |
| 2909 | struct net *net = sock_net(cb->skb->sk); | 2910 | struct net *net = sock_net(cb->skb->sk); |
| 2910 | int nhsel, genid = fnhe_genid(net); | 2911 | int nhsel, genid = fnhe_genid(net); |
| @@ -2922,7 +2923,8 @@ int fib_dump_info_fnhe(struct sk_buff *skb, struct netlink_callback *cb, | |||
| 2922 | err = 0; | 2923 | err = 0; |
| 2923 | if (bucket) | 2924 | if (bucket) |
| 2924 | err = fnhe_dump_bucket(net, skb, cb, table_id, bucket, | 2925 | err = fnhe_dump_bucket(net, skb, cb, table_id, bucket, |
| 2925 | genid, fa_index, fa_start); | 2926 | genid, fa_index, fa_start, |
| 2927 | flags); | ||
| 2926 | rcu_read_unlock(); | 2928 | rcu_read_unlock(); |
| 2927 | if (err) | 2929 | if (err) |
| 2928 | return err; | 2930 | return err; |
| @@ -3183,7 +3185,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, | |||
| 3183 | fl4.flowi4_tos, res.fi, 0); | 3185 | fl4.flowi4_tos, res.fi, 0); |
| 3184 | } else { | 3186 | } else { |
| 3185 | err = rt_fill_info(net, dst, src, rt, table_id, &fl4, skb, | 3187 | err = rt_fill_info(net, dst, src, rt, table_id, &fl4, skb, |
| 3186 | NETLINK_CB(in_skb).portid, nlh->nlmsg_seq); | 3188 | NETLINK_CB(in_skb).portid, |
| 3189 | nlh->nlmsg_seq, 0); | ||
| 3187 | } | 3190 | } |
| 3188 | if (err < 0) | 3191 | if (err < 0) |
| 3189 | goto errout_rcu; | 3192 | goto errout_rcu; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 776905899ac0..61082065b26a 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -935,6 +935,22 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags) | |||
| 935 | return mss_now; | 935 | return mss_now; |
| 936 | } | 936 | } |
| 937 | 937 | ||
| 938 | /* In some cases, both sendpage() and sendmsg() could have added | ||
| 939 | * an skb to the write queue, but failed adding payload on it. | ||
| 940 | * We need to remove it to consume less memory, but more | ||
| 941 | * importantly be able to generate EPOLLOUT for Edge Trigger epoll() | ||
| 942 | * users. | ||
| 943 | */ | ||
| 944 | static void tcp_remove_empty_skb(struct sock *sk, struct sk_buff *skb) | ||
| 945 | { | ||
| 946 | if (skb && !skb->len) { | ||
| 947 | tcp_unlink_write_queue(skb, sk); | ||
| 948 | if (tcp_write_queue_empty(sk)) | ||
| 949 | tcp_chrono_stop(sk, TCP_CHRONO_BUSY); | ||
| 950 | sk_wmem_free_skb(sk, skb); | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 938 | ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, | 954 | ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset, |
| 939 | size_t size, int flags) | 955 | size_t size, int flags) |
| 940 | { | 956 | { |
| @@ -984,6 +1000,9 @@ new_segment: | |||
| 984 | if (!skb) | 1000 | if (!skb) |
| 985 | goto wait_for_memory; | 1001 | goto wait_for_memory; |
| 986 | 1002 | ||
| 1003 | #ifdef CONFIG_TLS_DEVICE | ||
| 1004 | skb->decrypted = !!(flags & MSG_SENDPAGE_DECRYPTED); | ||
| 1005 | #endif | ||
| 987 | skb_entail(sk, skb); | 1006 | skb_entail(sk, skb); |
| 988 | copy = size_goal; | 1007 | copy = size_goal; |
| 989 | } | 1008 | } |
| @@ -1061,6 +1080,7 @@ out: | |||
| 1061 | return copied; | 1080 | return copied; |
| 1062 | 1081 | ||
| 1063 | do_error: | 1082 | do_error: |
| 1083 | tcp_remove_empty_skb(sk, tcp_write_queue_tail(sk)); | ||
| 1064 | if (copied) | 1084 | if (copied) |
| 1065 | goto out; | 1085 | goto out; |
| 1066 | out_err: | 1086 | out_err: |
| @@ -1385,18 +1405,11 @@ out_nopush: | |||
| 1385 | sock_zerocopy_put(uarg); | 1405 | sock_zerocopy_put(uarg); |
| 1386 | return copied + copied_syn; | 1406 | return copied + copied_syn; |
| 1387 | 1407 | ||
| 1408 | do_error: | ||
| 1409 | skb = tcp_write_queue_tail(sk); | ||
| 1388 | do_fault: | 1410 | do_fault: |
| 1389 | if (!skb->len) { | 1411 | tcp_remove_empty_skb(sk, skb); |
| 1390 | tcp_unlink_write_queue(skb, sk); | ||
| 1391 | /* It is the one place in all of TCP, except connection | ||
| 1392 | * reset, where we can be unlinking the send_head. | ||
| 1393 | */ | ||
| 1394 | if (tcp_write_queue_empty(sk)) | ||
| 1395 | tcp_chrono_stop(sk, TCP_CHRONO_BUSY); | ||
| 1396 | sk_wmem_free_skb(sk, skb); | ||
| 1397 | } | ||
| 1398 | 1412 | ||
| 1399 | do_error: | ||
| 1400 | if (copied + copied_syn) | 1413 | if (copied + copied_syn) |
| 1401 | goto out; | 1414 | goto out; |
| 1402 | out_err: | 1415 | out_err: |
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c index 3d1e15401384..8a56e09cfb0e 100644 --- a/net/ipv4/tcp_bpf.c +++ b/net/ipv4/tcp_bpf.c | |||
| @@ -398,10 +398,14 @@ more_data: | |||
| 398 | static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) | 398 | static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) |
| 399 | { | 399 | { |
| 400 | struct sk_msg tmp, *msg_tx = NULL; | 400 | struct sk_msg tmp, *msg_tx = NULL; |
| 401 | int flags = msg->msg_flags | MSG_NO_SHARED_FRAGS; | ||
| 402 | int copied = 0, err = 0; | 401 | int copied = 0, err = 0; |
| 403 | struct sk_psock *psock; | 402 | struct sk_psock *psock; |
| 404 | long timeo; | 403 | long timeo; |
| 404 | int flags; | ||
| 405 | |||
| 406 | /* Don't let internal do_tcp_sendpages() flags through */ | ||
| 407 | flags = (msg->msg_flags & ~MSG_SENDPAGE_DECRYPTED); | ||
| 408 | flags |= MSG_NO_SHARED_FRAGS; | ||
| 405 | 409 | ||
| 406 | psock = sk_psock_get(sk); | 410 | psock = sk_psock_get(sk); |
| 407 | if (unlikely(!psock)) | 411 | if (unlikely(!psock)) |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6e4afc48d7bb..8a645f304e6c 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -1320,6 +1320,7 @@ int tcp_fragment(struct sock *sk, enum tcp_queue tcp_queue, | |||
| 1320 | buff = sk_stream_alloc_skb(sk, nsize, gfp, true); | 1320 | buff = sk_stream_alloc_skb(sk, nsize, gfp, true); |
| 1321 | if (!buff) | 1321 | if (!buff) |
| 1322 | return -ENOMEM; /* We'll just try again later. */ | 1322 | return -ENOMEM; /* We'll just try again later. */ |
| 1323 | skb_copy_decrypted(buff, skb); | ||
| 1323 | 1324 | ||
| 1324 | sk->sk_wmem_queued += buff->truesize; | 1325 | sk->sk_wmem_queued += buff->truesize; |
| 1325 | sk_mem_charge(sk, buff->truesize); | 1326 | sk_mem_charge(sk, buff->truesize); |
| @@ -1874,6 +1875,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, | |||
| 1874 | buff = sk_stream_alloc_skb(sk, 0, gfp, true); | 1875 | buff = sk_stream_alloc_skb(sk, 0, gfp, true); |
| 1875 | if (unlikely(!buff)) | 1876 | if (unlikely(!buff)) |
| 1876 | return -ENOMEM; | 1877 | return -ENOMEM; |
| 1878 | skb_copy_decrypted(buff, skb); | ||
| 1877 | 1879 | ||
| 1878 | sk->sk_wmem_queued += buff->truesize; | 1880 | sk->sk_wmem_queued += buff->truesize; |
| 1879 | sk_mem_charge(sk, buff->truesize); | 1881 | sk_mem_charge(sk, buff->truesize); |
| @@ -2051,7 +2053,7 @@ static bool tcp_can_coalesce_send_queue_head(struct sock *sk, int len) | |||
| 2051 | if (len <= skb->len) | 2053 | if (len <= skb->len) |
| 2052 | break; | 2054 | break; |
| 2053 | 2055 | ||
| 2054 | if (unlikely(TCP_SKB_CB(skb)->eor)) | 2056 | if (unlikely(TCP_SKB_CB(skb)->eor) || tcp_has_tx_tstamp(skb)) |
| 2055 | return false; | 2057 | return false; |
| 2056 | 2058 | ||
| 2057 | len -= skb->len; | 2059 | len -= skb->len; |
| @@ -2143,6 +2145,7 @@ static int tcp_mtu_probe(struct sock *sk) | |||
| 2143 | sk_mem_charge(sk, nskb->truesize); | 2145 | sk_mem_charge(sk, nskb->truesize); |
| 2144 | 2146 | ||
| 2145 | skb = tcp_send_head(sk); | 2147 | skb = tcp_send_head(sk); |
| 2148 | skb_copy_decrypted(nskb, skb); | ||
| 2146 | 2149 | ||
| 2147 | TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq; | 2150 | TCP_SKB_CB(nskb)->seq = TCP_SKB_CB(skb)->seq; |
| 2148 | TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size; | 2151 | TCP_SKB_CB(nskb)->end_seq = TCP_SKB_CB(skb)->seq + probe_size; |
| @@ -2167,6 +2170,7 @@ static int tcp_mtu_probe(struct sock *sk) | |||
| 2167 | * we need to propagate it to the new skb. | 2170 | * we need to propagate it to the new skb. |
| 2168 | */ | 2171 | */ |
| 2169 | TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor; | 2172 | TCP_SKB_CB(nskb)->eor = TCP_SKB_CB(skb)->eor; |
| 2173 | tcp_skb_collapse_tstamp(nskb, skb); | ||
| 2170 | tcp_unlink_write_queue(skb, sk); | 2174 | tcp_unlink_write_queue(skb, sk); |
| 2171 | sk_wmem_free_skb(sk, skb); | 2175 | sk_wmem_free_skb(sk, skb); |
| 2172 | } else { | 2176 | } else { |
diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c index 3d8a1d835471..4849edb62d52 100644 --- a/net/ipv4/tcp_ulp.c +++ b/net/ipv4/tcp_ulp.c | |||
| @@ -96,6 +96,19 @@ void tcp_get_available_ulp(char *buf, size_t maxlen) | |||
| 96 | rcu_read_unlock(); | 96 | rcu_read_unlock(); |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | void tcp_update_ulp(struct sock *sk, struct proto *proto) | ||
| 100 | { | ||
| 101 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
| 102 | |||
| 103 | if (!icsk->icsk_ulp_ops) { | ||
| 104 | sk->sk_prot = proto; | ||
| 105 | return; | ||
| 106 | } | ||
| 107 | |||
| 108 | if (icsk->icsk_ulp_ops->update) | ||
| 109 | icsk->icsk_ulp_ops->update(sk, proto); | ||
| 110 | } | ||
| 111 | |||
| 99 | void tcp_cleanup_ulp(struct sock *sk) | 112 | void tcp_cleanup_ulp(struct sock *sk) |
| 100 | { | 113 | { |
| 101 | struct inet_connection_sock *icsk = inet_csk(sk); | 114 | struct inet_connection_sock *icsk = inet_csk(sk); |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index dc73888c7859..6a576ff92c39 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -478,7 +478,7 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev) | |||
| 478 | if (!idev) { | 478 | if (!idev) { |
| 479 | idev = ipv6_add_dev(dev); | 479 | idev = ipv6_add_dev(dev); |
| 480 | if (IS_ERR(idev)) | 480 | if (IS_ERR(idev)) |
| 481 | return NULL; | 481 | return idev; |
| 482 | } | 482 | } |
| 483 | 483 | ||
| 484 | if (dev->flags&IFF_UP) | 484 | if (dev->flags&IFF_UP) |
| @@ -1045,7 +1045,8 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg, | |||
| 1045 | int err = 0; | 1045 | int err = 0; |
| 1046 | 1046 | ||
| 1047 | if (addr_type == IPV6_ADDR_ANY || | 1047 | if (addr_type == IPV6_ADDR_ANY || |
| 1048 | addr_type & IPV6_ADDR_MULTICAST || | 1048 | (addr_type & IPV6_ADDR_MULTICAST && |
| 1049 | !(cfg->ifa_flags & IFA_F_MCAUTOJOIN)) || | ||
| 1049 | (!(idev->dev->flags & IFF_LOOPBACK) && | 1050 | (!(idev->dev->flags & IFF_LOOPBACK) && |
| 1050 | !netif_is_l3_master(idev->dev) && | 1051 | !netif_is_l3_master(idev->dev) && |
| 1051 | addr_type & IPV6_ADDR_LOOPBACK)) | 1052 | addr_type & IPV6_ADDR_LOOPBACK)) |
| @@ -2465,8 +2466,8 @@ static struct inet6_dev *addrconf_add_dev(struct net_device *dev) | |||
| 2465 | ASSERT_RTNL(); | 2466 | ASSERT_RTNL(); |
| 2466 | 2467 | ||
| 2467 | idev = ipv6_find_idev(dev); | 2468 | idev = ipv6_find_idev(dev); |
| 2468 | if (!idev) | 2469 | if (IS_ERR(idev)) |
| 2469 | return ERR_PTR(-ENOBUFS); | 2470 | return idev; |
| 2470 | 2471 | ||
| 2471 | if (idev->cnf.disable_ipv6) | 2472 | if (idev->cnf.disable_ipv6) |
| 2472 | return ERR_PTR(-EACCES); | 2473 | return ERR_PTR(-EACCES); |
| @@ -3158,7 +3159,7 @@ static void init_loopback(struct net_device *dev) | |||
| 3158 | ASSERT_RTNL(); | 3159 | ASSERT_RTNL(); |
| 3159 | 3160 | ||
| 3160 | idev = ipv6_find_idev(dev); | 3161 | idev = ipv6_find_idev(dev); |
| 3161 | if (!idev) { | 3162 | if (IS_ERR(idev)) { |
| 3162 | pr_debug("%s: add_dev failed\n", __func__); | 3163 | pr_debug("%s: add_dev failed\n", __func__); |
| 3163 | return; | 3164 | return; |
| 3164 | } | 3165 | } |
| @@ -3373,7 +3374,7 @@ static void addrconf_sit_config(struct net_device *dev) | |||
| 3373 | */ | 3374 | */ |
| 3374 | 3375 | ||
| 3375 | idev = ipv6_find_idev(dev); | 3376 | idev = ipv6_find_idev(dev); |
| 3376 | if (!idev) { | 3377 | if (IS_ERR(idev)) { |
| 3377 | pr_debug("%s: add_dev failed\n", __func__); | 3378 | pr_debug("%s: add_dev failed\n", __func__); |
| 3378 | return; | 3379 | return; |
| 3379 | } | 3380 | } |
| @@ -3398,7 +3399,7 @@ static void addrconf_gre_config(struct net_device *dev) | |||
| 3398 | ASSERT_RTNL(); | 3399 | ASSERT_RTNL(); |
| 3399 | 3400 | ||
| 3400 | idev = ipv6_find_idev(dev); | 3401 | idev = ipv6_find_idev(dev); |
| 3401 | if (!idev) { | 3402 | if (IS_ERR(idev)) { |
| 3402 | pr_debug("%s: add_dev failed\n", __func__); | 3403 | pr_debug("%s: add_dev failed\n", __func__); |
| 3403 | return; | 3404 | return; |
| 3404 | } | 3405 | } |
| @@ -4772,8 +4773,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 4772 | IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC; | 4773 | IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC; |
| 4773 | 4774 | ||
| 4774 | idev = ipv6_find_idev(dev); | 4775 | idev = ipv6_find_idev(dev); |
| 4775 | if (!idev) | 4776 | if (IS_ERR(idev)) |
| 4776 | return -ENOBUFS; | 4777 | return PTR_ERR(idev); |
| 4777 | 4778 | ||
| 4778 | if (!ipv6_allow_optimistic_dad(net, idev)) | 4779 | if (!ipv6_allow_optimistic_dad(net, idev)) |
| 4779 | cfg.ifa_flags &= ~IFA_F_OPTIMISTIC; | 4780 | cfg.ifa_flags &= ~IFA_F_OPTIMISTIC; |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index c2049c72f3e5..dd2d0b963260 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -660,12 +660,13 @@ static int prepare_ip6gre_xmit_ipv6(struct sk_buff *skb, | |||
| 660 | struct flowi6 *fl6, __u8 *dsfield, | 660 | struct flowi6 *fl6, __u8 *dsfield, |
| 661 | int *encap_limit) | 661 | int *encap_limit) |
| 662 | { | 662 | { |
| 663 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 663 | struct ipv6hdr *ipv6h; |
| 664 | struct ip6_tnl *t = netdev_priv(dev); | 664 | struct ip6_tnl *t = netdev_priv(dev); |
| 665 | __u16 offset; | 665 | __u16 offset; |
| 666 | 666 | ||
| 667 | offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); | 667 | offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); |
| 668 | /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */ | 668 | /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */ |
| 669 | ipv6h = ipv6_hdr(skb); | ||
| 669 | 670 | ||
| 670 | if (offset > 0) { | 671 | if (offset > 0) { |
| 671 | struct ipv6_tlv_tnl_enc_lim *tel; | 672 | struct ipv6_tlv_tnl_enc_lim *tel; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 3134fbb65d7f..754a484d35df 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -1278,12 +1278,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1278 | } | 1278 | } |
| 1279 | 1279 | ||
| 1280 | fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); | 1280 | fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); |
| 1281 | dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph)); | ||
| 1281 | 1282 | ||
| 1282 | if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) | 1283 | if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) |
| 1283 | return -1; | 1284 | return -1; |
| 1284 | 1285 | ||
| 1285 | dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph)); | ||
| 1286 | |||
| 1287 | skb_set_inner_ipproto(skb, IPPROTO_IPIP); | 1286 | skb_set_inner_ipproto(skb, IPPROTO_IPIP); |
| 1288 | 1287 | ||
| 1289 | err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, | 1288 | err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, |
| @@ -1367,12 +1366,11 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1367 | } | 1366 | } |
| 1368 | 1367 | ||
| 1369 | fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); | 1368 | fl6.flowi6_uid = sock_net_uid(dev_net(dev), NULL); |
| 1369 | dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h)); | ||
| 1370 | 1370 | ||
| 1371 | if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) | 1371 | if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) |
| 1372 | return -1; | 1372 | return -1; |
| 1373 | 1373 | ||
| 1374 | dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h)); | ||
| 1375 | |||
| 1376 | skb_set_inner_ipproto(skb, IPPROTO_IPV6); | 1374 | skb_set_inner_ipproto(skb, IPPROTO_IPV6); |
| 1377 | 1375 | ||
| 1378 | err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, | 1376 | err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 7f3f13c37916..eaa4c2cc2fbb 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -787,14 +787,15 @@ static void mld_del_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) | |||
| 787 | if (pmc) { | 787 | if (pmc) { |
| 788 | im->idev = pmc->idev; | 788 | im->idev = pmc->idev; |
| 789 | if (im->mca_sfmode == MCAST_INCLUDE) { | 789 | if (im->mca_sfmode == MCAST_INCLUDE) { |
| 790 | im->mca_tomb = pmc->mca_tomb; | 790 | swap(im->mca_tomb, pmc->mca_tomb); |
| 791 | im->mca_sources = pmc->mca_sources; | 791 | swap(im->mca_sources, pmc->mca_sources); |
| 792 | for (psf = im->mca_sources; psf; psf = psf->sf_next) | 792 | for (psf = im->mca_sources; psf; psf = psf->sf_next) |
| 793 | psf->sf_crcount = idev->mc_qrv; | 793 | psf->sf_crcount = idev->mc_qrv; |
| 794 | } else { | 794 | } else { |
| 795 | im->mca_crcount = idev->mc_qrv; | 795 | im->mca_crcount = idev->mc_qrv; |
| 796 | } | 796 | } |
| 797 | in6_dev_put(pmc->idev); | 797 | in6_dev_put(pmc->idev); |
| 798 | ip6_mc_clear_src(pmc); | ||
| 798 | kfree(pmc); | 799 | kfree(pmc); |
| 799 | } | 800 | } |
| 800 | spin_unlock_bh(&im->mca_lock); | 801 | spin_unlock_bh(&im->mca_lock); |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 0f82c150543b..fed9666a2f7d 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -348,7 +348,7 @@ static int nf_ct_frag6_reasm(struct frag_queue *fq, struct sk_buff *skb, | |||
| 348 | 348 | ||
| 349 | skb_reset_transport_header(skb); | 349 | skb_reset_transport_header(skb); |
| 350 | 350 | ||
| 351 | inet_frag_reasm_finish(&fq->q, skb, reasm_data); | 351 | inet_frag_reasm_finish(&fq->q, skb, reasm_data, false); |
| 352 | 352 | ||
| 353 | skb->ignore_df = 1; | 353 | skb->ignore_df = 1; |
| 354 | skb->dev = dev; | 354 | skb->dev = dev; |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index ca05b16f1bb9..1f5d4d196dcc 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -282,7 +282,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *skb, | |||
| 282 | 282 | ||
| 283 | skb_reset_transport_header(skb); | 283 | skb_reset_transport_header(skb); |
| 284 | 284 | ||
| 285 | inet_frag_reasm_finish(&fq->q, skb, reasm_data); | 285 | inet_frag_reasm_finish(&fq->q, skb, reasm_data, true); |
| 286 | 286 | ||
| 287 | skb->dev = dev; | 287 | skb->dev = dev; |
| 288 | ipv6_hdr(skb)->payload_len = htons(payload_len); | 288 | ipv6_hdr(skb)->payload_len = htons(payload_len); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index e49fec767a10..fd059e08785a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -1951,7 +1951,7 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt) | |||
| 1951 | nexthop_for_each_fib6_nh(from->nh, fib6_nh_find_match, &arg); | 1951 | nexthop_for_each_fib6_nh(from->nh, fib6_nh_find_match, &arg); |
| 1952 | 1952 | ||
| 1953 | if (!arg.match) | 1953 | if (!arg.match) |
| 1954 | return; | 1954 | goto unlock; |
| 1955 | fib6_nh = arg.match; | 1955 | fib6_nh = arg.match; |
| 1956 | } else { | 1956 | } else { |
| 1957 | fib6_nh = from->fib6_nh; | 1957 | fib6_nh = from->fib6_nh; |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 09e1694b6d34..ebb62a4ebe30 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
| @@ -512,7 +512,9 @@ static void iucv_sock_close(struct sock *sk) | |||
| 512 | sk->sk_state = IUCV_DISCONN; | 512 | sk->sk_state = IUCV_DISCONN; |
| 513 | sk->sk_state_change(sk); | 513 | sk->sk_state_change(sk); |
| 514 | } | 514 | } |
| 515 | case IUCV_DISCONN: /* fall through */ | 515 | /* fall through */ |
| 516 | |||
| 517 | case IUCV_DISCONN: | ||
| 516 | sk->sk_state = IUCV_CLOSING; | 518 | sk->sk_state = IUCV_CLOSING; |
| 517 | sk->sk_state_change(sk); | 519 | sk->sk_state_change(sk); |
| 518 | 520 | ||
| @@ -525,8 +527,9 @@ static void iucv_sock_close(struct sock *sk) | |||
| 525 | iucv_sock_in_state(sk, IUCV_CLOSED, 0), | 527 | iucv_sock_in_state(sk, IUCV_CLOSED, 0), |
| 526 | timeo); | 528 | timeo); |
| 527 | } | 529 | } |
| 530 | /* fall through */ | ||
| 528 | 531 | ||
| 529 | case IUCV_CLOSING: /* fall through */ | 532 | case IUCV_CLOSING: |
| 530 | sk->sk_state = IUCV_CLOSED; | 533 | sk->sk_state = IUCV_CLOSED; |
| 531 | sk->sk_state_change(sk); | 534 | sk->sk_state_change(sk); |
| 532 | 535 | ||
| @@ -535,8 +538,9 @@ static void iucv_sock_close(struct sock *sk) | |||
| 535 | 538 | ||
| 536 | skb_queue_purge(&iucv->send_skb_q); | 539 | skb_queue_purge(&iucv->send_skb_q); |
| 537 | skb_queue_purge(&iucv->backlog_skb_q); | 540 | skb_queue_purge(&iucv->backlog_skb_q); |
| 541 | /* fall through */ | ||
| 538 | 542 | ||
| 539 | default: /* fall through */ | 543 | default: |
| 540 | iucv_sever_path(sk, 1); | 544 | iucv_sever_path(sk, 1); |
| 541 | } | 545 | } |
| 542 | 546 | ||
| @@ -2247,10 +2251,10 @@ static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 2247 | kfree_skb(skb); | 2251 | kfree_skb(skb); |
| 2248 | break; | 2252 | break; |
| 2249 | } | 2253 | } |
| 2250 | /* fall through and receive non-zero length data */ | 2254 | /* fall through - and receive non-zero length data */ |
| 2251 | case (AF_IUCV_FLAG_SHT): | 2255 | case (AF_IUCV_FLAG_SHT): |
| 2252 | /* shutdown request */ | 2256 | /* shutdown request */ |
| 2253 | /* fall through and receive zero length data */ | 2257 | /* fall through - and receive zero length data */ |
| 2254 | case 0: | 2258 | case 0: |
| 2255 | /* plain data frame */ | 2259 | /* plain data frame */ |
| 2256 | IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class; | 2260 | IUCV_SKB_CB(skb)->class = trans_hdr->iucv_hdr.class; |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 1d0e5904dedf..c54cb59593ef 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
| @@ -1681,6 +1681,9 @@ static const struct proto_ops pppol2tp_ops = { | |||
| 1681 | .recvmsg = pppol2tp_recvmsg, | 1681 | .recvmsg = pppol2tp_recvmsg, |
| 1682 | .mmap = sock_no_mmap, | 1682 | .mmap = sock_no_mmap, |
| 1683 | .ioctl = pppox_ioctl, | 1683 | .ioctl = pppox_ioctl, |
| 1684 | #ifdef CONFIG_COMPAT | ||
| 1685 | .compat_ioctl = pppox_compat_ioctl, | ||
| 1686 | #endif | ||
| 1684 | }; | 1687 | }; |
| 1685 | 1688 | ||
| 1686 | static const struct pppox_proto pppol2tp_proto = { | 1689 | static const struct pppox_proto pppol2tp_proto = { |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 4d458067d80d..111c400199ec 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -1546,6 +1546,11 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1546 | if (is_multicast_ether_addr(mac)) | 1546 | if (is_multicast_ether_addr(mac)) |
| 1547 | return -EINVAL; | 1547 | return -EINVAL; |
| 1548 | 1548 | ||
| 1549 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER) && | ||
| 1550 | sdata->vif.type == NL80211_IFTYPE_STATION && | ||
| 1551 | !sdata->u.mgd.associated) | ||
| 1552 | return -EINVAL; | ||
| 1553 | |||
| 1549 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); | 1554 | sta = sta_info_alloc(sdata, mac, GFP_KERNEL); |
| 1550 | if (!sta) | 1555 | if (!sta) |
| 1551 | return -ENOMEM; | 1556 | return -ENOMEM; |
| @@ -1553,10 +1558,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
| 1553 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) | 1558 | if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) |
| 1554 | sta->sta.tdls = true; | 1559 | sta->sta.tdls = true; |
| 1555 | 1560 | ||
| 1556 | if (sta->sta.tdls && sdata->vif.type == NL80211_IFTYPE_STATION && | ||
| 1557 | !sdata->u.mgd.associated) | ||
| 1558 | return -EINVAL; | ||
| 1559 | |||
| 1560 | err = sta_apply_parameters(local, sta, params); | 1561 | err = sta_apply_parameters(local, sta, params); |
| 1561 | if (err) { | 1562 | if (err) { |
| 1562 | sta_info_free(local, sta); | 1563 | sta_info_free(local, sta); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 06aac0aaae64..8dc6580e1787 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -1222,7 +1222,6 @@ static void ieee80211_if_setup(struct net_device *dev) | |||
| 1222 | static void ieee80211_if_setup_no_queue(struct net_device *dev) | 1222 | static void ieee80211_if_setup_no_queue(struct net_device *dev) |
| 1223 | { | 1223 | { |
| 1224 | ieee80211_if_setup(dev); | 1224 | ieee80211_if_setup(dev); |
| 1225 | dev->features |= NETIF_F_LLTX; | ||
| 1226 | dev->priv_flags |= IFF_NO_QUEUE; | 1225 | dev->priv_flags |= IFF_NO_QUEUE; |
| 1227 | } | 1226 | } |
| 1228 | 1227 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a99ad0325309..4c888dc9bd81 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -2042,6 +2042,16 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
| 2042 | ieee80211_regulatory_limit_wmm_params(sdata, ¶ms[ac], ac); | 2042 | ieee80211_regulatory_limit_wmm_params(sdata, ¶ms[ac], ac); |
| 2043 | } | 2043 | } |
| 2044 | 2044 | ||
| 2045 | /* WMM specification requires all 4 ACIs. */ | ||
| 2046 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
| 2047 | if (params[ac].cw_min == 0) { | ||
| 2048 | sdata_info(sdata, | ||
| 2049 | "AP has invalid WMM params (missing AC %d), using defaults\n", | ||
| 2050 | ac); | ||
| 2051 | return false; | ||
| 2052 | } | ||
| 2053 | } | ||
| 2054 | |||
| 2045 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | 2055 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { |
| 2046 | mlme_dbg(sdata, | 2056 | mlme_dbg(sdata, |
| 2047 | "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n", | 2057 | "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n", |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3c1ab870fefe..768d14c9a716 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -2447,11 +2447,13 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb, | |||
| 2447 | skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) && | 2447 | skb->protocol == cpu_to_be16(ETH_P_PREAUTH)) && |
| 2448 | sdata->control_port_over_nl80211)) { | 2448 | sdata->control_port_over_nl80211)) { |
| 2449 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 2449 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
| 2450 | bool noencrypt = status->flag & RX_FLAG_DECRYPTED; | 2450 | bool noencrypt = !(status->flag & RX_FLAG_DECRYPTED); |
| 2451 | 2451 | ||
| 2452 | cfg80211_rx_control_port(dev, skb, noencrypt); | 2452 | cfg80211_rx_control_port(dev, skb, noencrypt); |
| 2453 | dev_kfree_skb(skb); | 2453 | dev_kfree_skb(skb); |
| 2454 | } else { | 2454 | } else { |
| 2455 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
| 2456 | |||
| 2455 | /* deliver to local stack */ | 2457 | /* deliver to local stack */ |
| 2456 | if (rx->napi) | 2458 | if (rx->napi) |
| 2457 | napi_gro_receive(rx->napi, skb); | 2459 | napi_gro_receive(rx->napi, skb); |
| @@ -2546,8 +2548,6 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
| 2546 | 2548 | ||
| 2547 | if (skb) { | 2549 | if (skb) { |
| 2548 | skb->protocol = eth_type_trans(skb, dev); | 2550 | skb->protocol = eth_type_trans(skb, dev); |
| 2549 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
| 2550 | |||
| 2551 | ieee80211_deliver_skb_to_local_stack(skb, rx); | 2551 | ieee80211_deliver_skb_to_local_stack(skb, rx); |
| 2552 | } | 2552 | } |
| 2553 | 2553 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1b224fa27367..ad1e58184c4e 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -3796,9 +3796,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, | |||
| 3796 | } | 3796 | } |
| 3797 | 3797 | ||
| 3798 | /* Always allow software iftypes */ | 3798 | /* Always allow software iftypes */ |
| 3799 | if (local->hw.wiphy->software_iftypes & BIT(iftype) || | 3799 | if (cfg80211_iftype_allowed(local->hw.wiphy, iftype, 0, 1)) { |
| 3800 | (iftype == NL80211_IFTYPE_AP_VLAN && | ||
| 3801 | local->hw.wiphy->flags & WIPHY_FLAG_4ADDR_AP)) { | ||
| 3802 | if (radar_detect) | 3800 | if (radar_detect) |
| 3803 | return -EINVAL; | 3801 | return -EINVAL; |
| 3804 | return 0; | 3802 | return 0; |
| @@ -3833,7 +3831,8 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, | |||
| 3833 | 3831 | ||
| 3834 | if (sdata_iter == sdata || | 3832 | if (sdata_iter == sdata || |
| 3835 | !ieee80211_sdata_running(sdata_iter) || | 3833 | !ieee80211_sdata_running(sdata_iter) || |
| 3836 | local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype)) | 3834 | cfg80211_iftype_allowed(local->hw.wiphy, |
| 3835 | wdev_iter->iftype, 0, 1)) | ||
| 3837 | continue; | 3836 | continue; |
| 3838 | 3837 | ||
| 3839 | params.iftype_num[wdev_iter->iftype]++; | 3838 | params.iftype_num[wdev_iter->iftype]++; |
diff --git a/net/mpls/mpls_iptunnel.c b/net/mpls/mpls_iptunnel.c index d25e91d7bdc1..44b675016393 100644 --- a/net/mpls/mpls_iptunnel.c +++ b/net/mpls/mpls_iptunnel.c | |||
| @@ -133,12 +133,12 @@ static int mpls_xmit(struct sk_buff *skb) | |||
| 133 | mpls_stats_inc_outucastpkts(out_dev, skb); | 133 | mpls_stats_inc_outucastpkts(out_dev, skb); |
| 134 | 134 | ||
| 135 | if (rt) { | 135 | if (rt) { |
| 136 | if (rt->rt_gw_family == AF_INET) | 136 | if (rt->rt_gw_family == AF_INET6) |
| 137 | err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4, | ||
| 138 | skb); | ||
| 139 | else if (rt->rt_gw_family == AF_INET6) | ||
| 140 | err = neigh_xmit(NEIGH_ND_TABLE, out_dev, &rt->rt_gw6, | 137 | err = neigh_xmit(NEIGH_ND_TABLE, out_dev, &rt->rt_gw6, |
| 141 | skb); | 138 | skb); |
| 139 | else | ||
| 140 | err = neigh_xmit(NEIGH_ARP_TABLE, out_dev, &rt->rt_gw4, | ||
| 141 | skb); | ||
| 142 | } else if (rt6) { | 142 | } else if (rt6) { |
| 143 | if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) { | 143 | if (ipv6_addr_v4mapped(&rt6->rt6i_gateway)) { |
| 144 | /* 6PE (RFC 4798) */ | 144 | /* 6PE (RFC 4798) */ |
diff --git a/net/ncsi/ncsi-cmd.c b/net/ncsi/ncsi-cmd.c index 5c3fad8cba57..0187e65176c0 100644 --- a/net/ncsi/ncsi-cmd.c +++ b/net/ncsi/ncsi-cmd.c | |||
| @@ -54,7 +54,7 @@ static void ncsi_cmd_build_header(struct ncsi_pkt_hdr *h, | |||
| 54 | checksum = ncsi_calculate_checksum((unsigned char *)h, | 54 | checksum = ncsi_calculate_checksum((unsigned char *)h, |
| 55 | sizeof(*h) + nca->payload); | 55 | sizeof(*h) + nca->payload); |
| 56 | pchecksum = (__be32 *)((void *)h + sizeof(struct ncsi_pkt_hdr) + | 56 | pchecksum = (__be32 *)((void *)h + sizeof(struct ncsi_pkt_hdr) + |
| 57 | nca->payload); | 57 | ALIGN(nca->payload, 4)); |
| 58 | *pchecksum = htonl(checksum); | 58 | *pchecksum = htonl(checksum); |
| 59 | } | 59 | } |
| 60 | 60 | ||
| @@ -309,14 +309,21 @@ static struct ncsi_request *ncsi_alloc_command(struct ncsi_cmd_arg *nca) | |||
| 309 | 309 | ||
| 310 | int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca) | 310 | int ncsi_xmit_cmd(struct ncsi_cmd_arg *nca) |
| 311 | { | 311 | { |
| 312 | struct ncsi_cmd_handler *nch = NULL; | ||
| 312 | struct ncsi_request *nr; | 313 | struct ncsi_request *nr; |
| 314 | unsigned char type; | ||
| 313 | struct ethhdr *eh; | 315 | struct ethhdr *eh; |
| 314 | struct ncsi_cmd_handler *nch = NULL; | ||
| 315 | int i, ret; | 316 | int i, ret; |
| 316 | 317 | ||
| 318 | /* Use OEM generic handler for Netlink request */ | ||
| 319 | if (nca->req_flags == NCSI_REQ_FLAG_NETLINK_DRIVEN) | ||
| 320 | type = NCSI_PKT_CMD_OEM; | ||
| 321 | else | ||
| 322 | type = nca->type; | ||
| 323 | |||
| 317 | /* Search for the handler */ | 324 | /* Search for the handler */ |
| 318 | for (i = 0; i < ARRAY_SIZE(ncsi_cmd_handlers); i++) { | 325 | for (i = 0; i < ARRAY_SIZE(ncsi_cmd_handlers); i++) { |
| 319 | if (ncsi_cmd_handlers[i].type == nca->type) { | 326 | if (ncsi_cmd_handlers[i].type == type) { |
| 320 | if (ncsi_cmd_handlers[i].handler) | 327 | if (ncsi_cmd_handlers[i].handler) |
| 321 | nch = &ncsi_cmd_handlers[i]; | 328 | nch = &ncsi_cmd_handlers[i]; |
| 322 | else | 329 | else |
diff --git a/net/ncsi/ncsi-rsp.c b/net/ncsi/ncsi-rsp.c index 7581bf919885..d876bd55f356 100644 --- a/net/ncsi/ncsi-rsp.c +++ b/net/ncsi/ncsi-rsp.c | |||
| @@ -47,7 +47,8 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr, | |||
| 47 | if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED || | 47 | if (ntohs(h->code) != NCSI_PKT_RSP_C_COMPLETED || |
| 48 | ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR) { | 48 | ntohs(h->reason) != NCSI_PKT_RSP_R_NO_ERROR) { |
| 49 | netdev_dbg(nr->ndp->ndev.dev, | 49 | netdev_dbg(nr->ndp->ndev.dev, |
| 50 | "NCSI: non zero response/reason code\n"); | 50 | "NCSI: non zero response/reason code %04xh, %04xh\n", |
| 51 | ntohs(h->code), ntohs(h->reason)); | ||
| 51 | return -EPERM; | 52 | return -EPERM; |
| 52 | } | 53 | } |
| 53 | 54 | ||
| @@ -55,7 +56,7 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr, | |||
| 55 | * sender doesn't support checksum according to NCSI | 56 | * sender doesn't support checksum according to NCSI |
| 56 | * specification. | 57 | * specification. |
| 57 | */ | 58 | */ |
| 58 | pchecksum = (__be32 *)((void *)(h + 1) + payload - 4); | 59 | pchecksum = (__be32 *)((void *)(h + 1) + ALIGN(payload, 4) - 4); |
| 59 | if (ntohl(*pchecksum) == 0) | 60 | if (ntohl(*pchecksum) == 0) |
| 60 | return 0; | 61 | return 0; |
| 61 | 62 | ||
| @@ -63,7 +64,9 @@ static int ncsi_validate_rsp_pkt(struct ncsi_request *nr, | |||
| 63 | sizeof(*h) + payload - 4); | 64 | sizeof(*h) + payload - 4); |
| 64 | 65 | ||
| 65 | if (*pchecksum != htonl(checksum)) { | 66 | if (*pchecksum != htonl(checksum)) { |
| 66 | netdev_dbg(nr->ndp->ndev.dev, "NCSI: checksum mismatched\n"); | 67 | netdev_dbg(nr->ndp->ndev.dev, |
| 68 | "NCSI: checksum mismatched; recd: %08x calc: %08x\n", | ||
| 69 | *pchecksum, htonl(checksum)); | ||
| 67 | return -EINVAL; | 70 | return -EINVAL; |
| 68 | } | 71 | } |
| 69 | 72 | ||
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index ca7ac4a25ada..1d4e63326e68 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c | |||
| @@ -226,7 +226,7 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
| 226 | 226 | ||
| 227 | e.id = ip_to_id(map, ip); | 227 | e.id = ip_to_id(map, ip); |
| 228 | 228 | ||
| 229 | if (opt->flags & IPSET_DIM_ONE_SRC) | 229 | if (opt->flags & IPSET_DIM_TWO_SRC) |
| 230 | ether_addr_copy(e.ether, eth_hdr(skb)->h_source); | 230 | ether_addr_copy(e.ether, eth_hdr(skb)->h_source); |
| 231 | else | 231 | else |
| 232 | ether_addr_copy(e.ether, eth_hdr(skb)->h_dest); | 232 | ether_addr_copy(e.ether, eth_hdr(skb)->h_dest); |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 2e151856ad99..e64d5f9a89dd 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
| @@ -1161,7 +1161,7 @@ static int ip_set_rename(struct net *net, struct sock *ctnl, | |||
| 1161 | return -ENOENT; | 1161 | return -ENOENT; |
| 1162 | 1162 | ||
| 1163 | write_lock_bh(&ip_set_ref_lock); | 1163 | write_lock_bh(&ip_set_ref_lock); |
| 1164 | if (set->ref != 0) { | 1164 | if (set->ref != 0 || set->ref_netlink != 0) { |
| 1165 | ret = -IPSET_ERR_REFERENCED; | 1165 | ret = -IPSET_ERR_REFERENCED; |
| 1166 | goto out; | 1166 | goto out; |
| 1167 | } | 1167 | } |
diff --git a/net/netfilter/ipset/ip_set_hash_ipmac.c b/net/netfilter/ipset/ip_set_hash_ipmac.c index faf59b6a998f..24d8f4df4230 100644 --- a/net/netfilter/ipset/ip_set_hash_ipmac.c +++ b/net/netfilter/ipset/ip_set_hash_ipmac.c | |||
| @@ -89,15 +89,11 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
| 89 | struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } }; | 89 | struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } }; |
| 90 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); | 90 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); |
| 91 | 91 | ||
| 92 | /* MAC can be src only */ | ||
| 93 | if (!(opt->flags & IPSET_DIM_TWO_SRC)) | ||
| 94 | return 0; | ||
| 95 | |||
| 96 | if (skb_mac_header(skb) < skb->head || | 92 | if (skb_mac_header(skb) < skb->head || |
| 97 | (skb_mac_header(skb) + ETH_HLEN) > skb->data) | 93 | (skb_mac_header(skb) + ETH_HLEN) > skb->data) |
| 98 | return -EINVAL; | 94 | return -EINVAL; |
| 99 | 95 | ||
| 100 | if (opt->flags & IPSET_DIM_ONE_SRC) | 96 | if (opt->flags & IPSET_DIM_TWO_SRC) |
| 101 | ether_addr_copy(e.ether, eth_hdr(skb)->h_source); | 97 | ether_addr_copy(e.ether, eth_hdr(skb)->h_source); |
| 102 | else | 98 | else |
| 103 | ether_addr_copy(e.ether, eth_hdr(skb)->h_dest); | 99 | ether_addr_copy(e.ether, eth_hdr(skb)->h_dest); |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index a542761e90d1..81a8ef42b88d 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -453,13 +453,12 @@ EXPORT_SYMBOL_GPL(nf_ct_invert_tuple); | |||
| 453 | * table location, we assume id gets exposed to userspace. | 453 | * table location, we assume id gets exposed to userspace. |
| 454 | * | 454 | * |
| 455 | * Following nf_conn items do not change throughout lifetime | 455 | * Following nf_conn items do not change throughout lifetime |
| 456 | * of the nf_conn after it has been committed to main hash table: | 456 | * of the nf_conn: |
| 457 | * | 457 | * |
| 458 | * 1. nf_conn address | 458 | * 1. nf_conn address |
| 459 | * 2. nf_conn->ext address | 459 | * 2. nf_conn->master address (normally NULL) |
| 460 | * 3. nf_conn->master address (normally NULL) | 460 | * 3. the associated net namespace |
| 461 | * 4. tuple | 461 | * 4. the original direction tuple |
| 462 | * 5. the associated net namespace | ||
| 463 | */ | 462 | */ |
| 464 | u32 nf_ct_get_id(const struct nf_conn *ct) | 463 | u32 nf_ct_get_id(const struct nf_conn *ct) |
| 465 | { | 464 | { |
| @@ -469,9 +468,10 @@ u32 nf_ct_get_id(const struct nf_conn *ct) | |||
| 469 | net_get_random_once(&ct_id_seed, sizeof(ct_id_seed)); | 468 | net_get_random_once(&ct_id_seed, sizeof(ct_id_seed)); |
| 470 | 469 | ||
| 471 | a = (unsigned long)ct; | 470 | a = (unsigned long)ct; |
| 472 | b = (unsigned long)ct->master ^ net_hash_mix(nf_ct_net(ct)); | 471 | b = (unsigned long)ct->master; |
| 473 | c = (unsigned long)ct->ext; | 472 | c = (unsigned long)nf_ct_net(ct); |
| 474 | d = (unsigned long)siphash(&ct->tuplehash, sizeof(ct->tuplehash), | 473 | d = (unsigned long)siphash(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
| 474 | sizeof(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple), | ||
| 475 | &ct_id_seed); | 475 | &ct_id_seed); |
| 476 | #ifdef CONFIG_64BIT | 476 | #ifdef CONFIG_64BIT |
| 477 | return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed); | 477 | return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed); |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 0ecb3e289ef2..8d96738b7dfd 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
| @@ -322,7 +322,7 @@ static int find_pattern(const char *data, size_t dlen, | |||
| 322 | i++; | 322 | i++; |
| 323 | } | 323 | } |
| 324 | 324 | ||
| 325 | pr_debug("Skipped up to `%c'!\n", skip); | 325 | pr_debug("Skipped up to 0x%hhx delimiter!\n", skip); |
| 326 | 326 | ||
| 327 | *numoff = i; | 327 | *numoff = i; |
| 328 | *numlen = getnum(data + i, dlen - i, cmd, term, numoff); | 328 | *numlen = getnum(data + i, dlen - i, cmd, term, numoff); |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index e0d392cb3075..0006503d2da9 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
| @@ -1037,9 +1037,14 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net) | |||
| 1037 | table[NF_SYSCTL_CT_COUNT].data = &net->ct.count; | 1037 | table[NF_SYSCTL_CT_COUNT].data = &net->ct.count; |
| 1038 | table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum; | 1038 | table[NF_SYSCTL_CT_CHECKSUM].data = &net->ct.sysctl_checksum; |
| 1039 | table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid; | 1039 | table[NF_SYSCTL_CT_LOG_INVALID].data = &net->ct.sysctl_log_invalid; |
| 1040 | table[NF_SYSCTL_CT_ACCT].data = &net->ct.sysctl_acct; | ||
| 1041 | table[NF_SYSCTL_CT_HELPER].data = &net->ct.sysctl_auto_assign_helper; | ||
| 1040 | #ifdef CONFIG_NF_CONNTRACK_EVENTS | 1042 | #ifdef CONFIG_NF_CONNTRACK_EVENTS |
| 1041 | table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events; | 1043 | table[NF_SYSCTL_CT_EVENTS].data = &net->ct.sysctl_events; |
| 1042 | #endif | 1044 | #endif |
| 1045 | #ifdef CONFIG_NF_CONNTRACK_TIMESTAMP | ||
| 1046 | table[NF_SYSCTL_CT_TIMESTAMP].data = &net->ct.sysctl_tstamp; | ||
| 1047 | #endif | ||
| 1043 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout; | 1048 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_GENERIC].data = &nf_generic_pernet(net)->timeout; |
| 1044 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout; | 1049 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP].data = &nf_icmp_pernet(net)->timeout; |
| 1045 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout; | 1050 | table[NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6].data = &nf_icmpv6_pernet(net)->timeout; |
diff --git a/net/netfilter/nf_flow_table_core.c b/net/netfilter/nf_flow_table_core.c index e3d797252a98..80a8f9ae4c93 100644 --- a/net/netfilter/nf_flow_table_core.c +++ b/net/netfilter/nf_flow_table_core.c | |||
| @@ -111,15 +111,16 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp) | |||
| 111 | #define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ) | 111 | #define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT (120 * HZ) |
| 112 | #define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ) | 112 | #define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT (30 * HZ) |
| 113 | 113 | ||
| 114 | static void flow_offload_fixup_ct_state(struct nf_conn *ct) | 114 | static inline __s32 nf_flow_timeout_delta(unsigned int timeout) |
| 115 | { | ||
| 116 | return (__s32)(timeout - (u32)jiffies); | ||
| 117 | } | ||
| 118 | |||
| 119 | static void flow_offload_fixup_ct_timeout(struct nf_conn *ct) | ||
| 115 | { | 120 | { |
| 116 | const struct nf_conntrack_l4proto *l4proto; | 121 | const struct nf_conntrack_l4proto *l4proto; |
| 122 | int l4num = nf_ct_protonum(ct); | ||
| 117 | unsigned int timeout; | 123 | unsigned int timeout; |
| 118 | int l4num; | ||
| 119 | |||
| 120 | l4num = nf_ct_protonum(ct); | ||
| 121 | if (l4num == IPPROTO_TCP) | ||
| 122 | flow_offload_fixup_tcp(&ct->proto.tcp); | ||
| 123 | 124 | ||
| 124 | l4proto = nf_ct_l4proto_find(l4num); | 125 | l4proto = nf_ct_l4proto_find(l4num); |
| 125 | if (!l4proto) | 126 | if (!l4proto) |
| @@ -132,7 +133,20 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct) | |||
| 132 | else | 133 | else |
| 133 | return; | 134 | return; |
| 134 | 135 | ||
| 135 | ct->timeout = nfct_time_stamp + timeout; | 136 | if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout) |
| 137 | ct->timeout = nfct_time_stamp + timeout; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void flow_offload_fixup_ct_state(struct nf_conn *ct) | ||
| 141 | { | ||
| 142 | if (nf_ct_protonum(ct) == IPPROTO_TCP) | ||
| 143 | flow_offload_fixup_tcp(&ct->proto.tcp); | ||
| 144 | } | ||
| 145 | |||
| 146 | static void flow_offload_fixup_ct(struct nf_conn *ct) | ||
| 147 | { | ||
| 148 | flow_offload_fixup_ct_state(ct); | ||
| 149 | flow_offload_fixup_ct_timeout(ct); | ||
| 136 | } | 150 | } |
| 137 | 151 | ||
| 138 | void flow_offload_free(struct flow_offload *flow) | 152 | void flow_offload_free(struct flow_offload *flow) |
| @@ -208,6 +222,11 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow) | |||
| 208 | } | 222 | } |
| 209 | EXPORT_SYMBOL_GPL(flow_offload_add); | 223 | EXPORT_SYMBOL_GPL(flow_offload_add); |
| 210 | 224 | ||
| 225 | static inline bool nf_flow_has_expired(const struct flow_offload *flow) | ||
| 226 | { | ||
| 227 | return nf_flow_timeout_delta(flow->timeout) <= 0; | ||
| 228 | } | ||
| 229 | |||
| 211 | static void flow_offload_del(struct nf_flowtable *flow_table, | 230 | static void flow_offload_del(struct nf_flowtable *flow_table, |
| 212 | struct flow_offload *flow) | 231 | struct flow_offload *flow) |
| 213 | { | 232 | { |
| @@ -223,6 +242,11 @@ static void flow_offload_del(struct nf_flowtable *flow_table, | |||
| 223 | e = container_of(flow, struct flow_offload_entry, flow); | 242 | e = container_of(flow, struct flow_offload_entry, flow); |
| 224 | clear_bit(IPS_OFFLOAD_BIT, &e->ct->status); | 243 | clear_bit(IPS_OFFLOAD_BIT, &e->ct->status); |
| 225 | 244 | ||
| 245 | if (nf_flow_has_expired(flow)) | ||
| 246 | flow_offload_fixup_ct(e->ct); | ||
| 247 | else if (flow->flags & FLOW_OFFLOAD_TEARDOWN) | ||
| 248 | flow_offload_fixup_ct_timeout(e->ct); | ||
| 249 | |||
| 226 | flow_offload_free(flow); | 250 | flow_offload_free(flow); |
| 227 | } | 251 | } |
| 228 | 252 | ||
| @@ -298,11 +322,6 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table, | |||
| 298 | return err; | 322 | return err; |
| 299 | } | 323 | } |
| 300 | 324 | ||
| 301 | static inline bool nf_flow_has_expired(const struct flow_offload *flow) | ||
| 302 | { | ||
| 303 | return (__s32)(flow->timeout - (u32)jiffies) <= 0; | ||
| 304 | } | ||
| 305 | |||
| 306 | static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data) | 325 | static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data) |
| 307 | { | 326 | { |
| 308 | struct nf_flowtable *flow_table = data; | 327 | struct nf_flowtable *flow_table = data; |
diff --git a/net/netfilter/nf_flow_table_ip.c b/net/netfilter/nf_flow_table_ip.c index cdfc33517e85..b9e7dd6e60ce 100644 --- a/net/netfilter/nf_flow_table_ip.c +++ b/net/netfilter/nf_flow_table_ip.c | |||
| @@ -214,6 +214,24 @@ static bool nf_flow_exceeds_mtu(const struct sk_buff *skb, unsigned int mtu) | |||
| 214 | return true; | 214 | return true; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| 217 | static int nf_flow_offload_dst_check(struct dst_entry *dst) | ||
| 218 | { | ||
| 219 | if (unlikely(dst_xfrm(dst))) | ||
| 220 | return dst_check(dst, 0) ? 0 : -1; | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static unsigned int nf_flow_xmit_xfrm(struct sk_buff *skb, | ||
| 226 | const struct nf_hook_state *state, | ||
| 227 | struct dst_entry *dst) | ||
| 228 | { | ||
| 229 | skb_orphan(skb); | ||
| 230 | skb_dst_set_noref(skb, dst); | ||
| 231 | dst_output(state->net, state->sk, skb); | ||
| 232 | return NF_STOLEN; | ||
| 233 | } | ||
| 234 | |||
| 217 | unsigned int | 235 | unsigned int |
| 218 | nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, | 236 | nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, |
| 219 | const struct nf_hook_state *state) | 237 | const struct nf_hook_state *state) |
| @@ -254,12 +272,25 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb, | |||
| 254 | if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff)) | 272 | if (nf_flow_state_check(flow, ip_hdr(skb)->protocol, skb, thoff)) |
| 255 | return NF_ACCEPT; | 273 | return NF_ACCEPT; |
| 256 | 274 | ||
| 275 | if (nf_flow_offload_dst_check(&rt->dst)) { | ||
| 276 | flow_offload_teardown(flow); | ||
| 277 | return NF_ACCEPT; | ||
| 278 | } | ||
| 279 | |||
| 257 | if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0) | 280 | if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0) |
| 258 | return NF_DROP; | 281 | return NF_DROP; |
| 259 | 282 | ||
| 260 | flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; | 283 | flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; |
| 261 | iph = ip_hdr(skb); | 284 | iph = ip_hdr(skb); |
| 262 | ip_decrease_ttl(iph); | 285 | ip_decrease_ttl(iph); |
| 286 | skb->tstamp = 0; | ||
| 287 | |||
| 288 | if (unlikely(dst_xfrm(&rt->dst))) { | ||
| 289 | memset(skb->cb, 0, sizeof(struct inet_skb_parm)); | ||
| 290 | IPCB(skb)->iif = skb->dev->ifindex; | ||
| 291 | IPCB(skb)->flags = IPSKB_FORWARDED; | ||
| 292 | return nf_flow_xmit_xfrm(skb, state, &rt->dst); | ||
| 293 | } | ||
| 263 | 294 | ||
| 264 | skb->dev = outdev; | 295 | skb->dev = outdev; |
| 265 | nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); | 296 | nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr); |
| @@ -467,6 +498,11 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, | |||
| 467 | sizeof(*ip6h))) | 498 | sizeof(*ip6h))) |
| 468 | return NF_ACCEPT; | 499 | return NF_ACCEPT; |
| 469 | 500 | ||
| 501 | if (nf_flow_offload_dst_check(&rt->dst)) { | ||
| 502 | flow_offload_teardown(flow); | ||
| 503 | return NF_ACCEPT; | ||
| 504 | } | ||
| 505 | |||
| 470 | if (skb_try_make_writable(skb, sizeof(*ip6h))) | 506 | if (skb_try_make_writable(skb, sizeof(*ip6h))) |
| 471 | return NF_DROP; | 507 | return NF_DROP; |
| 472 | 508 | ||
| @@ -476,6 +512,14 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb, | |||
| 476 | flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; | 512 | flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT; |
| 477 | ip6h = ipv6_hdr(skb); | 513 | ip6h = ipv6_hdr(skb); |
| 478 | ip6h->hop_limit--; | 514 | ip6h->hop_limit--; |
| 515 | skb->tstamp = 0; | ||
| 516 | |||
| 517 | if (unlikely(dst_xfrm(&rt->dst))) { | ||
| 518 | memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); | ||
| 519 | IP6CB(skb)->iif = skb->dev->ifindex; | ||
| 520 | IP6CB(skb)->flags = IP6SKB_FORWARDED; | ||
| 521 | return nf_flow_xmit_xfrm(skb, state, &rt->dst); | ||
| 522 | } | ||
| 479 | 523 | ||
| 480 | skb->dev = outdev; | 524 | skb->dev = outdev; |
| 481 | nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); | 525 | nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6); |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 605a7cfe7ca7..d47469f824a1 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -138,9 +138,14 @@ static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set) | |||
| 138 | return; | 138 | return; |
| 139 | 139 | ||
| 140 | list_for_each_entry_reverse(trans, &net->nft.commit_list, list) { | 140 | list_for_each_entry_reverse(trans, &net->nft.commit_list, list) { |
| 141 | if (trans->msg_type == NFT_MSG_NEWSET && | 141 | switch (trans->msg_type) { |
| 142 | nft_trans_set(trans) == set) { | 142 | case NFT_MSG_NEWSET: |
| 143 | set->bound = true; | 143 | if (nft_trans_set(trans) == set) |
| 144 | nft_trans_set_bound(trans) = true; | ||
| 145 | break; | ||
| 146 | case NFT_MSG_NEWSETELEM: | ||
| 147 | if (nft_trans_elem_set(trans) == set) | ||
| 148 | nft_trans_elem_set_bound(trans) = true; | ||
| 144 | break; | 149 | break; |
| 145 | } | 150 | } |
| 146 | } | 151 | } |
| @@ -1662,6 +1667,10 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask, | |||
| 1662 | 1667 | ||
| 1663 | chain->flags |= NFT_BASE_CHAIN | flags; | 1668 | chain->flags |= NFT_BASE_CHAIN | flags; |
| 1664 | basechain->policy = NF_ACCEPT; | 1669 | basechain->policy = NF_ACCEPT; |
| 1670 | if (chain->flags & NFT_CHAIN_HW_OFFLOAD && | ||
| 1671 | nft_chain_offload_priority(basechain) < 0) | ||
| 1672 | return -EOPNOTSUPP; | ||
| 1673 | |||
| 1665 | flow_block_init(&basechain->flow_block); | 1674 | flow_block_init(&basechain->flow_block); |
| 1666 | } else { | 1675 | } else { |
| 1667 | chain = kzalloc(sizeof(*chain), GFP_KERNEL); | 1676 | chain = kzalloc(sizeof(*chain), GFP_KERNEL); |
| @@ -6906,7 +6915,7 @@ static int __nf_tables_abort(struct net *net) | |||
| 6906 | break; | 6915 | break; |
| 6907 | case NFT_MSG_NEWSET: | 6916 | case NFT_MSG_NEWSET: |
| 6908 | trans->ctx.table->use--; | 6917 | trans->ctx.table->use--; |
| 6909 | if (nft_trans_set(trans)->bound) { | 6918 | if (nft_trans_set_bound(trans)) { |
| 6910 | nft_trans_destroy(trans); | 6919 | nft_trans_destroy(trans); |
| 6911 | break; | 6920 | break; |
| 6912 | } | 6921 | } |
| @@ -6918,7 +6927,7 @@ static int __nf_tables_abort(struct net *net) | |||
| 6918 | nft_trans_destroy(trans); | 6927 | nft_trans_destroy(trans); |
| 6919 | break; | 6928 | break; |
| 6920 | case NFT_MSG_NEWSETELEM: | 6929 | case NFT_MSG_NEWSETELEM: |
| 6921 | if (nft_trans_elem_set(trans)->bound) { | 6930 | if (nft_trans_elem_set_bound(trans)) { |
| 6922 | nft_trans_destroy(trans); | 6931 | nft_trans_destroy(trans); |
| 6923 | break; | 6932 | break; |
| 6924 | } | 6933 | } |
diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index 64f5fd5f240e..c0d18c1d77ac 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c | |||
| @@ -103,10 +103,11 @@ void nft_offload_update_dependency(struct nft_offload_ctx *ctx, | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static void nft_flow_offload_common_init(struct flow_cls_common_offload *common, | 105 | static void nft_flow_offload_common_init(struct flow_cls_common_offload *common, |
| 106 | __be16 proto, | 106 | __be16 proto, int priority, |
| 107 | struct netlink_ext_ack *extack) | 107 | struct netlink_ext_ack *extack) |
| 108 | { | 108 | { |
| 109 | common->protocol = proto; | 109 | common->protocol = proto; |
| 110 | common->prio = priority; | ||
| 110 | common->extack = extack; | 111 | common->extack = extack; |
| 111 | } | 112 | } |
| 112 | 113 | ||
| @@ -124,6 +125,15 @@ static int nft_setup_cb_call(struct nft_base_chain *basechain, | |||
| 124 | return 0; | 125 | return 0; |
| 125 | } | 126 | } |
| 126 | 127 | ||
| 128 | int nft_chain_offload_priority(struct nft_base_chain *basechain) | ||
| 129 | { | ||
| 130 | if (basechain->ops.priority <= 0 || | ||
| 131 | basechain->ops.priority > USHRT_MAX) | ||
| 132 | return -1; | ||
| 133 | |||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 127 | static int nft_flow_offload_rule(struct nft_trans *trans, | 137 | static int nft_flow_offload_rule(struct nft_trans *trans, |
| 128 | enum flow_cls_command command) | 138 | enum flow_cls_command command) |
| 129 | { | 139 | { |
| @@ -142,7 +152,8 @@ static int nft_flow_offload_rule(struct nft_trans *trans, | |||
| 142 | if (flow) | 152 | if (flow) |
| 143 | proto = flow->proto; | 153 | proto = flow->proto; |
| 144 | 154 | ||
| 145 | nft_flow_offload_common_init(&cls_flow.common, proto, &extack); | 155 | nft_flow_offload_common_init(&cls_flow.common, proto, |
| 156 | basechain->ops.priority, &extack); | ||
| 146 | cls_flow.command = command; | 157 | cls_flow.command = command; |
| 147 | cls_flow.cookie = (unsigned long) rule; | 158 | cls_flow.cookie = (unsigned long) rule; |
| 148 | if (flow) | 159 | if (flow) |
diff --git a/net/netfilter/nft_flow_offload.c b/net/netfilter/nft_flow_offload.c index aa5f571d4361..01705ad74a9a 100644 --- a/net/netfilter/nft_flow_offload.c +++ b/net/netfilter/nft_flow_offload.c | |||
| @@ -72,11 +72,11 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, | |||
| 72 | { | 72 | { |
| 73 | struct nft_flow_offload *priv = nft_expr_priv(expr); | 73 | struct nft_flow_offload *priv = nft_expr_priv(expr); |
| 74 | struct nf_flowtable *flowtable = &priv->flowtable->data; | 74 | struct nf_flowtable *flowtable = &priv->flowtable->data; |
| 75 | struct tcphdr _tcph, *tcph = NULL; | ||
| 75 | enum ip_conntrack_info ctinfo; | 76 | enum ip_conntrack_info ctinfo; |
| 76 | struct nf_flow_route route; | 77 | struct nf_flow_route route; |
| 77 | struct flow_offload *flow; | 78 | struct flow_offload *flow; |
| 78 | enum ip_conntrack_dir dir; | 79 | enum ip_conntrack_dir dir; |
| 79 | bool is_tcp = false; | ||
| 80 | struct nf_conn *ct; | 80 | struct nf_conn *ct; |
| 81 | int ret; | 81 | int ret; |
| 82 | 82 | ||
| @@ -89,7 +89,10 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, | |||
| 89 | 89 | ||
| 90 | switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { | 90 | switch (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum) { |
| 91 | case IPPROTO_TCP: | 91 | case IPPROTO_TCP: |
| 92 | is_tcp = true; | 92 | tcph = skb_header_pointer(pkt->skb, pkt->xt.thoff, |
| 93 | sizeof(_tcph), &_tcph); | ||
| 94 | if (unlikely(!tcph || tcph->fin || tcph->rst)) | ||
| 95 | goto out; | ||
| 93 | break; | 96 | break; |
| 94 | case IPPROTO_UDP: | 97 | case IPPROTO_UDP: |
| 95 | break; | 98 | break; |
| @@ -115,7 +118,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr, | |||
| 115 | if (!flow) | 118 | if (!flow) |
| 116 | goto err_flow_alloc; | 119 | goto err_flow_alloc; |
| 117 | 120 | ||
| 118 | if (is_tcp) { | 121 | if (tcph) { |
| 119 | ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; | 122 | ct->proto.tcp.seen[0].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; |
| 120 | ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; | 123 | ct->proto.tcp.seen[1].flags |= IP_CT_TCP_FLAG_BE_LIBERAL; |
| 121 | } | 124 | } |
| @@ -146,6 +149,11 @@ static int nft_flow_offload_validate(const struct nft_ctx *ctx, | |||
| 146 | return nft_chain_validate_hooks(ctx->chain, hook_mask); | 149 | return nft_chain_validate_hooks(ctx->chain, hook_mask); |
| 147 | } | 150 | } |
| 148 | 151 | ||
| 152 | static const struct nla_policy nft_flow_offload_policy[NFTA_FLOW_MAX + 1] = { | ||
| 153 | [NFTA_FLOW_TABLE_NAME] = { .type = NLA_STRING, | ||
| 154 | .len = NFT_NAME_MAXLEN - 1 }, | ||
| 155 | }; | ||
| 156 | |||
| 149 | static int nft_flow_offload_init(const struct nft_ctx *ctx, | 157 | static int nft_flow_offload_init(const struct nft_ctx *ctx, |
| 150 | const struct nft_expr *expr, | 158 | const struct nft_expr *expr, |
| 151 | const struct nlattr * const tb[]) | 159 | const struct nlattr * const tb[]) |
| @@ -204,6 +212,7 @@ static const struct nft_expr_ops nft_flow_offload_ops = { | |||
| 204 | static struct nft_expr_type nft_flow_offload_type __read_mostly = { | 212 | static struct nft_expr_type nft_flow_offload_type __read_mostly = { |
| 205 | .name = "flow_offload", | 213 | .name = "flow_offload", |
| 206 | .ops = &nft_flow_offload_ops, | 214 | .ops = &nft_flow_offload_ops, |
| 215 | .policy = nft_flow_offload_policy, | ||
| 207 | .maxattr = NFTA_FLOW_MAX, | 216 | .maxattr = NFTA_FLOW_MAX, |
| 208 | .owner = THIS_MODULE, | 217 | .owner = THIS_MODULE, |
| 209 | }; | 218 | }; |
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index f1b1d948c07b..f69afb9ff3cb 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c | |||
| @@ -60,24 +60,16 @@ void nft_meta_get_eval(const struct nft_expr *expr, | |||
| 60 | *dest = skb->mark; | 60 | *dest = skb->mark; |
| 61 | break; | 61 | break; |
| 62 | case NFT_META_IIF: | 62 | case NFT_META_IIF: |
| 63 | if (in == NULL) | 63 | *dest = in ? in->ifindex : 0; |
| 64 | goto err; | ||
| 65 | *dest = in->ifindex; | ||
| 66 | break; | 64 | break; |
| 67 | case NFT_META_OIF: | 65 | case NFT_META_OIF: |
| 68 | if (out == NULL) | 66 | *dest = out ? out->ifindex : 0; |
| 69 | goto err; | ||
| 70 | *dest = out->ifindex; | ||
| 71 | break; | 67 | break; |
| 72 | case NFT_META_IIFNAME: | 68 | case NFT_META_IIFNAME: |
| 73 | if (in == NULL) | 69 | strncpy((char *)dest, in ? in->name : "", IFNAMSIZ); |
| 74 | goto err; | ||
| 75 | strncpy((char *)dest, in->name, IFNAMSIZ); | ||
| 76 | break; | 70 | break; |
| 77 | case NFT_META_OIFNAME: | 71 | case NFT_META_OIFNAME: |
| 78 | if (out == NULL) | 72 | strncpy((char *)dest, out ? out->name : "", IFNAMSIZ); |
| 79 | goto err; | ||
| 80 | strncpy((char *)dest, out->name, IFNAMSIZ); | ||
| 81 | break; | 73 | break; |
| 82 | case NFT_META_IIFTYPE: | 74 | case NFT_META_IIFTYPE: |
| 83 | if (in == NULL) | 75 | if (in == NULL) |
diff --git a/net/netfilter/xt_nfacct.c b/net/netfilter/xt_nfacct.c index d0ab1adf5bff..5aab6df74e0f 100644 --- a/net/netfilter/xt_nfacct.c +++ b/net/netfilter/xt_nfacct.c | |||
| @@ -54,25 +54,39 @@ nfacct_mt_destroy(const struct xt_mtdtor_param *par) | |||
| 54 | nfnl_acct_put(info->nfacct); | 54 | nfnl_acct_put(info->nfacct); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static struct xt_match nfacct_mt_reg __read_mostly = { | 57 | static struct xt_match nfacct_mt_reg[] __read_mostly = { |
| 58 | .name = "nfacct", | 58 | { |
| 59 | .family = NFPROTO_UNSPEC, | 59 | .name = "nfacct", |
| 60 | .checkentry = nfacct_mt_checkentry, | 60 | .revision = 0, |
| 61 | .match = nfacct_mt, | 61 | .family = NFPROTO_UNSPEC, |
| 62 | .destroy = nfacct_mt_destroy, | 62 | .checkentry = nfacct_mt_checkentry, |
| 63 | .matchsize = sizeof(struct xt_nfacct_match_info), | 63 | .match = nfacct_mt, |
| 64 | .usersize = offsetof(struct xt_nfacct_match_info, nfacct), | 64 | .destroy = nfacct_mt_destroy, |
| 65 | .me = THIS_MODULE, | 65 | .matchsize = sizeof(struct xt_nfacct_match_info), |
| 66 | .usersize = offsetof(struct xt_nfacct_match_info, nfacct), | ||
| 67 | .me = THIS_MODULE, | ||
| 68 | }, | ||
| 69 | { | ||
| 70 | .name = "nfacct", | ||
| 71 | .revision = 1, | ||
| 72 | .family = NFPROTO_UNSPEC, | ||
| 73 | .checkentry = nfacct_mt_checkentry, | ||
| 74 | .match = nfacct_mt, | ||
| 75 | .destroy = nfacct_mt_destroy, | ||
| 76 | .matchsize = sizeof(struct xt_nfacct_match_info_v1), | ||
| 77 | .usersize = offsetof(struct xt_nfacct_match_info_v1, nfacct), | ||
| 78 | .me = THIS_MODULE, | ||
| 79 | }, | ||
| 66 | }; | 80 | }; |
| 67 | 81 | ||
| 68 | static int __init nfacct_mt_init(void) | 82 | static int __init nfacct_mt_init(void) |
| 69 | { | 83 | { |
| 70 | return xt_register_match(&nfacct_mt_reg); | 84 | return xt_register_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg)); |
| 71 | } | 85 | } |
| 72 | 86 | ||
| 73 | static void __exit nfacct_mt_exit(void) | 87 | static void __exit nfacct_mt_exit(void) |
| 74 | { | 88 | { |
| 75 | xt_unregister_match(&nfacct_mt_reg); | 89 | xt_unregister_matches(nfacct_mt_reg, ARRAY_SIZE(nfacct_mt_reg)); |
| 76 | } | 90 | } |
| 77 | 91 | ||
| 78 | module_init(nfacct_mt_init); | 92 | module_init(nfacct_mt_init); |
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c index ead7c6022208..b92b22ce8abd 100644 --- a/net/netfilter/xt_physdev.c +++ b/net/netfilter/xt_physdev.c | |||
| @@ -101,11 +101,9 @@ static int physdev_mt_check(const struct xt_mtchk_param *par) | |||
| 101 | if (info->bitmask & (XT_PHYSDEV_OP_OUT | XT_PHYSDEV_OP_ISOUT) && | 101 | if (info->bitmask & (XT_PHYSDEV_OP_OUT | XT_PHYSDEV_OP_ISOUT) && |
| 102 | (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || | 102 | (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) || |
| 103 | info->invert & XT_PHYSDEV_OP_BRIDGED) && | 103 | info->invert & XT_PHYSDEV_OP_BRIDGED) && |
| 104 | par->hook_mask & ((1 << NF_INET_LOCAL_OUT) | | 104 | par->hook_mask & (1 << NF_INET_LOCAL_OUT)) { |
| 105 | (1 << NF_INET_FORWARD) | (1 << NF_INET_POST_ROUTING))) { | ||
| 106 | pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n"); | 105 | pr_info_ratelimited("--physdev-out and --physdev-is-out only supported in the FORWARD and POSTROUTING chains with bridged traffic\n"); |
| 107 | if (par->hook_mask & (1 << NF_INET_LOCAL_OUT)) | 106 | return -EINVAL; |
| 108 | return -EINVAL; | ||
| 109 | } | 107 | } |
| 110 | 108 | ||
| 111 | if (!brnf_probed) { | 109 | if (!brnf_probed) { |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 96740d389377..c4f54ad2b98a 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
| @@ -967,6 +967,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 967 | 967 | ||
| 968 | window = skb->data[20]; | 968 | window = skb->data[20]; |
| 969 | 969 | ||
| 970 | sock_hold(make); | ||
| 970 | skb->sk = make; | 971 | skb->sk = make; |
| 971 | skb->destructor = sock_efree; | 972 | skb->destructor = sock_efree; |
| 972 | make->sk_state = TCP_ESTABLISHED; | 973 | make->sk_state = TCP_ESTABLISHED; |
diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 848c6eb55064..05249eb45082 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c | |||
| @@ -67,6 +67,7 @@ struct ovs_conntrack_info { | |||
| 67 | struct md_mark mark; | 67 | struct md_mark mark; |
| 68 | struct md_labels labels; | 68 | struct md_labels labels; |
| 69 | char timeout[CTNL_TIMEOUT_NAME_MAX]; | 69 | char timeout[CTNL_TIMEOUT_NAME_MAX]; |
| 70 | struct nf_ct_timeout *nf_ct_timeout; | ||
| 70 | #if IS_ENABLED(CONFIG_NF_NAT) | 71 | #if IS_ENABLED(CONFIG_NF_NAT) |
| 71 | struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */ | 72 | struct nf_nat_range2 range; /* Only present for SRC NAT and DST NAT. */ |
| 72 | #endif | 73 | #endif |
| @@ -524,6 +525,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key, | |||
| 524 | return -EPFNOSUPPORT; | 525 | return -EPFNOSUPPORT; |
| 525 | } | 526 | } |
| 526 | 527 | ||
| 528 | /* The key extracted from the fragment that completed this datagram | ||
| 529 | * likely didn't have an L4 header, so regenerate it. | ||
| 530 | */ | ||
| 531 | ovs_flow_key_update_l3l4(skb, key); | ||
| 532 | |||
| 527 | key->ip.frag = OVS_FRAG_TYPE_NONE; | 533 | key->ip.frag = OVS_FRAG_TYPE_NONE; |
| 528 | skb_clear_hash(skb); | 534 | skb_clear_hash(skb); |
| 529 | skb->ignore_df = 1; | 535 | skb->ignore_df = 1; |
| @@ -697,6 +703,14 @@ static bool skb_nfct_cached(struct net *net, | |||
| 697 | if (help && rcu_access_pointer(help->helper) != info->helper) | 703 | if (help && rcu_access_pointer(help->helper) != info->helper) |
| 698 | return false; | 704 | return false; |
| 699 | } | 705 | } |
| 706 | if (info->nf_ct_timeout) { | ||
| 707 | struct nf_conn_timeout *timeout_ext; | ||
| 708 | |||
| 709 | timeout_ext = nf_ct_timeout_find(ct); | ||
| 710 | if (!timeout_ext || info->nf_ct_timeout != | ||
| 711 | rcu_dereference(timeout_ext->timeout)) | ||
| 712 | return false; | ||
| 713 | } | ||
| 700 | /* Force conntrack entry direction to the current packet? */ | 714 | /* Force conntrack entry direction to the current packet? */ |
| 701 | if (info->force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) { | 715 | if (info->force && CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) { |
| 702 | /* Delete the conntrack entry if confirmed, else just release | 716 | /* Delete the conntrack entry if confirmed, else just release |
| @@ -1565,7 +1579,7 @@ static int parse_ct(const struct nlattr *attr, struct ovs_conntrack_info *info, | |||
| 1565 | case OVS_CT_ATTR_TIMEOUT: | 1579 | case OVS_CT_ATTR_TIMEOUT: |
| 1566 | memcpy(info->timeout, nla_data(a), nla_len(a)); | 1580 | memcpy(info->timeout, nla_data(a), nla_len(a)); |
| 1567 | if (!memchr(info->timeout, '\0', nla_len(a))) { | 1581 | if (!memchr(info->timeout, '\0', nla_len(a))) { |
| 1568 | OVS_NLERR(log, "Invalid conntrack helper"); | 1582 | OVS_NLERR(log, "Invalid conntrack timeout"); |
| 1569 | return -EINVAL; | 1583 | return -EINVAL; |
| 1570 | } | 1584 | } |
| 1571 | break; | 1585 | break; |
| @@ -1657,6 +1671,10 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr, | |||
| 1657 | ct_info.timeout)) | 1671 | ct_info.timeout)) |
| 1658 | pr_info_ratelimited("Failed to associated timeout " | 1672 | pr_info_ratelimited("Failed to associated timeout " |
| 1659 | "policy `%s'\n", ct_info.timeout); | 1673 | "policy `%s'\n", ct_info.timeout); |
| 1674 | else | ||
| 1675 | ct_info.nf_ct_timeout = rcu_dereference( | ||
| 1676 | nf_ct_timeout_find(ct_info.ct)->timeout); | ||
| 1677 | |||
| 1660 | } | 1678 | } |
| 1661 | 1679 | ||
| 1662 | if (helper) { | 1680 | if (helper) { |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 892287d06c17..d01410e52097 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -1047,7 +1047,7 @@ error: | |||
| 1047 | } | 1047 | } |
| 1048 | 1048 | ||
| 1049 | /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */ | 1049 | /* Factor out action copy to avoid "Wframe-larger-than=1024" warning. */ |
| 1050 | static struct sw_flow_actions *get_flow_actions(struct net *net, | 1050 | static noinline_for_stack struct sw_flow_actions *get_flow_actions(struct net *net, |
| 1051 | const struct nlattr *a, | 1051 | const struct nlattr *a, |
| 1052 | const struct sw_flow_key *key, | 1052 | const struct sw_flow_key *key, |
| 1053 | const struct sw_flow_mask *mask, | 1053 | const struct sw_flow_mask *mask, |
| @@ -1081,12 +1081,13 @@ static struct sw_flow_actions *get_flow_actions(struct net *net, | |||
| 1081 | * we should not to return match object with dangling reference | 1081 | * we should not to return match object with dangling reference |
| 1082 | * to mask. | 1082 | * to mask. |
| 1083 | * */ | 1083 | * */ |
| 1084 | static int ovs_nla_init_match_and_action(struct net *net, | 1084 | static noinline_for_stack int |
| 1085 | struct sw_flow_match *match, | 1085 | ovs_nla_init_match_and_action(struct net *net, |
| 1086 | struct sw_flow_key *key, | 1086 | struct sw_flow_match *match, |
| 1087 | struct nlattr **a, | 1087 | struct sw_flow_key *key, |
| 1088 | struct sw_flow_actions **acts, | 1088 | struct nlattr **a, |
| 1089 | bool log) | 1089 | struct sw_flow_actions **acts, |
| 1090 | bool log) | ||
| 1090 | { | 1091 | { |
| 1091 | struct sw_flow_mask mask; | 1092 | struct sw_flow_mask mask; |
| 1092 | int error = 0; | 1093 | int error = 0; |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index bc89e16e0505..9d81d2c7bf82 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
| @@ -523,78 +523,15 @@ static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 523 | } | 523 | } |
| 524 | 524 | ||
| 525 | /** | 525 | /** |
| 526 | * key_extract - extracts a flow key from an Ethernet frame. | 526 | * key_extract_l3l4 - extracts L3/L4 header information. |
| 527 | * @skb: sk_buff that contains the frame, with skb->data pointing to the | 527 | * @skb: sk_buff that contains the frame, with skb->data pointing to the |
| 528 | * Ethernet header | 528 | * L3 header |
| 529 | * @key: output flow key | 529 | * @key: output flow key |
| 530 | * | 530 | * |
| 531 | * The caller must ensure that skb->len >= ETH_HLEN. | ||
| 532 | * | ||
| 533 | * Returns 0 if successful, otherwise a negative errno value. | ||
| 534 | * | ||
| 535 | * Initializes @skb header fields as follows: | ||
| 536 | * | ||
| 537 | * - skb->mac_header: the L2 header. | ||
| 538 | * | ||
| 539 | * - skb->network_header: just past the L2 header, or just past the | ||
| 540 | * VLAN header, to the first byte of the L2 payload. | ||
| 541 | * | ||
| 542 | * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 | ||
| 543 | * on output, then just past the IP header, if one is present and | ||
| 544 | * of a correct length, otherwise the same as skb->network_header. | ||
| 545 | * For other key->eth.type values it is left untouched. | ||
| 546 | * | ||
| 547 | * - skb->protocol: the type of the data starting at skb->network_header. | ||
| 548 | * Equals to key->eth.type. | ||
| 549 | */ | 531 | */ |
| 550 | static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | 532 | static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key) |
| 551 | { | 533 | { |
| 552 | int error; | 534 | int error; |
| 553 | struct ethhdr *eth; | ||
| 554 | |||
| 555 | /* Flags are always used as part of stats */ | ||
| 556 | key->tp.flags = 0; | ||
| 557 | |||
| 558 | skb_reset_mac_header(skb); | ||
| 559 | |||
| 560 | /* Link layer. */ | ||
| 561 | clear_vlan(key); | ||
| 562 | if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { | ||
| 563 | if (unlikely(eth_type_vlan(skb->protocol))) | ||
| 564 | return -EINVAL; | ||
| 565 | |||
| 566 | skb_reset_network_header(skb); | ||
| 567 | key->eth.type = skb->protocol; | ||
| 568 | } else { | ||
| 569 | eth = eth_hdr(skb); | ||
| 570 | ether_addr_copy(key->eth.src, eth->h_source); | ||
| 571 | ether_addr_copy(key->eth.dst, eth->h_dest); | ||
| 572 | |||
| 573 | __skb_pull(skb, 2 * ETH_ALEN); | ||
| 574 | /* We are going to push all headers that we pull, so no need to | ||
| 575 | * update skb->csum here. | ||
| 576 | */ | ||
| 577 | |||
| 578 | if (unlikely(parse_vlan(skb, key))) | ||
| 579 | return -ENOMEM; | ||
| 580 | |||
| 581 | key->eth.type = parse_ethertype(skb); | ||
| 582 | if (unlikely(key->eth.type == htons(0))) | ||
| 583 | return -ENOMEM; | ||
| 584 | |||
| 585 | /* Multiple tagged packets need to retain TPID to satisfy | ||
| 586 | * skb_vlan_pop(), which will later shift the ethertype into | ||
| 587 | * skb->protocol. | ||
| 588 | */ | ||
| 589 | if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK)) | ||
| 590 | skb->protocol = key->eth.cvlan.tpid; | ||
| 591 | else | ||
| 592 | skb->protocol = key->eth.type; | ||
| 593 | |||
| 594 | skb_reset_network_header(skb); | ||
| 595 | __skb_push(skb, skb->data - skb_mac_header(skb)); | ||
| 596 | } | ||
| 597 | skb_reset_mac_len(skb); | ||
| 598 | 535 | ||
| 599 | /* Network layer. */ | 536 | /* Network layer. */ |
| 600 | if (key->eth.type == htons(ETH_P_IP)) { | 537 | if (key->eth.type == htons(ETH_P_IP)) { |
| @@ -623,6 +560,7 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 623 | offset = nh->frag_off & htons(IP_OFFSET); | 560 | offset = nh->frag_off & htons(IP_OFFSET); |
| 624 | if (offset) { | 561 | if (offset) { |
| 625 | key->ip.frag = OVS_FRAG_TYPE_LATER; | 562 | key->ip.frag = OVS_FRAG_TYPE_LATER; |
| 563 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 626 | return 0; | 564 | return 0; |
| 627 | } | 565 | } |
| 628 | if (nh->frag_off & htons(IP_MF) || | 566 | if (nh->frag_off & htons(IP_MF) || |
| @@ -740,8 +678,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 740 | return error; | 678 | return error; |
| 741 | } | 679 | } |
| 742 | 680 | ||
| 743 | if (key->ip.frag == OVS_FRAG_TYPE_LATER) | 681 | if (key->ip.frag == OVS_FRAG_TYPE_LATER) { |
| 682 | memset(&key->tp, 0, sizeof(key->tp)); | ||
| 744 | return 0; | 683 | return 0; |
| 684 | } | ||
| 745 | if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) | 685 | if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) |
| 746 | key->ip.frag = OVS_FRAG_TYPE_FIRST; | 686 | key->ip.frag = OVS_FRAG_TYPE_FIRST; |
| 747 | 687 | ||
| @@ -788,6 +728,92 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | |||
| 788 | return 0; | 728 | return 0; |
| 789 | } | 729 | } |
| 790 | 730 | ||
| 731 | /** | ||
| 732 | * key_extract - extracts a flow key from an Ethernet frame. | ||
| 733 | * @skb: sk_buff that contains the frame, with skb->data pointing to the | ||
| 734 | * Ethernet header | ||
| 735 | * @key: output flow key | ||
| 736 | * | ||
| 737 | * The caller must ensure that skb->len >= ETH_HLEN. | ||
| 738 | * | ||
| 739 | * Returns 0 if successful, otherwise a negative errno value. | ||
| 740 | * | ||
| 741 | * Initializes @skb header fields as follows: | ||
| 742 | * | ||
| 743 | * - skb->mac_header: the L2 header. | ||
| 744 | * | ||
| 745 | * - skb->network_header: just past the L2 header, or just past the | ||
| 746 | * VLAN header, to the first byte of the L2 payload. | ||
| 747 | * | ||
| 748 | * - skb->transport_header: If key->eth.type is ETH_P_IP or ETH_P_IPV6 | ||
| 749 | * on output, then just past the IP header, if one is present and | ||
| 750 | * of a correct length, otherwise the same as skb->network_header. | ||
| 751 | * For other key->eth.type values it is left untouched. | ||
| 752 | * | ||
| 753 | * - skb->protocol: the type of the data starting at skb->network_header. | ||
| 754 | * Equals to key->eth.type. | ||
| 755 | */ | ||
| 756 | static int key_extract(struct sk_buff *skb, struct sw_flow_key *key) | ||
| 757 | { | ||
| 758 | struct ethhdr *eth; | ||
| 759 | |||
| 760 | /* Flags are always used as part of stats */ | ||
| 761 | key->tp.flags = 0; | ||
| 762 | |||
| 763 | skb_reset_mac_header(skb); | ||
| 764 | |||
| 765 | /* Link layer. */ | ||
| 766 | clear_vlan(key); | ||
| 767 | if (ovs_key_mac_proto(key) == MAC_PROTO_NONE) { | ||
| 768 | if (unlikely(eth_type_vlan(skb->protocol))) | ||
| 769 | return -EINVAL; | ||
| 770 | |||
| 771 | skb_reset_network_header(skb); | ||
| 772 | key->eth.type = skb->protocol; | ||
| 773 | } else { | ||
| 774 | eth = eth_hdr(skb); | ||
| 775 | ether_addr_copy(key->eth.src, eth->h_source); | ||
| 776 | ether_addr_copy(key->eth.dst, eth->h_dest); | ||
| 777 | |||
| 778 | __skb_pull(skb, 2 * ETH_ALEN); | ||
| 779 | /* We are going to push all headers that we pull, so no need to | ||
| 780 | * update skb->csum here. | ||
| 781 | */ | ||
| 782 | |||
| 783 | if (unlikely(parse_vlan(skb, key))) | ||
| 784 | return -ENOMEM; | ||
| 785 | |||
| 786 | key->eth.type = parse_ethertype(skb); | ||
| 787 | if (unlikely(key->eth.type == htons(0))) | ||
| 788 | return -ENOMEM; | ||
| 789 | |||
| 790 | /* Multiple tagged packets need to retain TPID to satisfy | ||
| 791 | * skb_vlan_pop(), which will later shift the ethertype into | ||
| 792 | * skb->protocol. | ||
| 793 | */ | ||
| 794 | if (key->eth.cvlan.tci & htons(VLAN_CFI_MASK)) | ||
| 795 | skb->protocol = key->eth.cvlan.tpid; | ||
| 796 | else | ||
| 797 | skb->protocol = key->eth.type; | ||
| 798 | |||
| 799 | skb_reset_network_header(skb); | ||
| 800 | __skb_push(skb, skb->data - skb_mac_header(skb)); | ||
| 801 | } | ||
| 802 | |||
| 803 | skb_reset_mac_len(skb); | ||
| 804 | |||
| 805 | /* Fill out L3/L4 key info, if any */ | ||
| 806 | return key_extract_l3l4(skb, key); | ||
| 807 | } | ||
| 808 | |||
| 809 | /* In the case of conntrack fragment handling it expects L3 headers, | ||
| 810 | * add a helper. | ||
| 811 | */ | ||
| 812 | int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key) | ||
| 813 | { | ||
| 814 | return key_extract_l3l4(skb, key); | ||
| 815 | } | ||
| 816 | |||
| 791 | int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key) | 817 | int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key) |
| 792 | { | 818 | { |
| 793 | int res; | 819 | int res; |
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h index a5506e2d4b7a..b830d5ff7af4 100644 --- a/net/openvswitch/flow.h +++ b/net/openvswitch/flow.h | |||
| @@ -270,6 +270,7 @@ void ovs_flow_stats_clear(struct sw_flow *); | |||
| 270 | u64 ovs_flow_used_time(unsigned long flow_jiffies); | 270 | u64 ovs_flow_used_time(unsigned long flow_jiffies); |
| 271 | 271 | ||
| 272 | int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key); | 272 | int ovs_flow_key_update(struct sk_buff *skb, struct sw_flow_key *key); |
| 273 | int ovs_flow_key_update_l3l4(struct sk_buff *skb, struct sw_flow_key *key); | ||
| 273 | int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, | 274 | int ovs_flow_key_extract(const struct ip_tunnel_info *tun_info, |
| 274 | struct sk_buff *skb, | 275 | struct sk_buff *skb, |
| 275 | struct sw_flow_key *key); | 276 | struct sw_flow_key *key); |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8d54f3047768..e2742b006d25 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -2618,6 +2618,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2618 | 2618 | ||
| 2619 | mutex_lock(&po->pg_vec_lock); | 2619 | mutex_lock(&po->pg_vec_lock); |
| 2620 | 2620 | ||
| 2621 | /* packet_sendmsg() check on tx_ring.pg_vec was lockless, | ||
| 2622 | * we need to confirm it under protection of pg_vec_lock. | ||
| 2623 | */ | ||
| 2624 | if (unlikely(!po->tx_ring.pg_vec)) { | ||
| 2625 | err = -EBUSY; | ||
| 2626 | goto out; | ||
| 2627 | } | ||
| 2621 | if (likely(saddr == NULL)) { | 2628 | if (likely(saddr == NULL)) { |
| 2622 | dev = packet_cached_dev_get(po); | 2629 | dev = packet_cached_dev_get(po); |
| 2623 | proto = po->num; | 2630 | proto = po->num; |
diff --git a/net/psample/psample.c b/net/psample/psample.c index 841f198ea1a8..66e4b61a350d 100644 --- a/net/psample/psample.c +++ b/net/psample/psample.c | |||
| @@ -154,7 +154,7 @@ static void psample_group_destroy(struct psample_group *group) | |||
| 154 | { | 154 | { |
| 155 | psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP); | 155 | psample_group_notify(group, PSAMPLE_CMD_DEL_GROUP); |
| 156 | list_del(&group->list); | 156 | list_del(&group->list); |
| 157 | kfree(group); | 157 | kfree_rcu(group, rcu); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | static struct psample_group * | 160 | static struct psample_group * |
diff --git a/net/rds/ib.c b/net/rds/ib.c index ec05d91aa9a2..45acab2de0cf 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c | |||
| @@ -291,7 +291,7 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn, | |||
| 291 | void *buffer) | 291 | void *buffer) |
| 292 | { | 292 | { |
| 293 | struct rds_info_rdma_connection *iinfo = buffer; | 293 | struct rds_info_rdma_connection *iinfo = buffer; |
| 294 | struct rds_ib_connection *ic; | 294 | struct rds_ib_connection *ic = conn->c_transport_data; |
| 295 | 295 | ||
| 296 | /* We will only ever look at IB transports */ | 296 | /* We will only ever look at IB transports */ |
| 297 | if (conn->c_trans != &rds_ib_transport) | 297 | if (conn->c_trans != &rds_ib_transport) |
| @@ -301,15 +301,16 @@ static int rds_ib_conn_info_visitor(struct rds_connection *conn, | |||
| 301 | 301 | ||
| 302 | iinfo->src_addr = conn->c_laddr.s6_addr32[3]; | 302 | iinfo->src_addr = conn->c_laddr.s6_addr32[3]; |
| 303 | iinfo->dst_addr = conn->c_faddr.s6_addr32[3]; | 303 | iinfo->dst_addr = conn->c_faddr.s6_addr32[3]; |
| 304 | iinfo->tos = conn->c_tos; | 304 | if (ic) { |
| 305 | iinfo->tos = conn->c_tos; | ||
| 306 | iinfo->sl = ic->i_sl; | ||
| 307 | } | ||
| 305 | 308 | ||
| 306 | memset(&iinfo->src_gid, 0, sizeof(iinfo->src_gid)); | 309 | memset(&iinfo->src_gid, 0, sizeof(iinfo->src_gid)); |
| 307 | memset(&iinfo->dst_gid, 0, sizeof(iinfo->dst_gid)); | 310 | memset(&iinfo->dst_gid, 0, sizeof(iinfo->dst_gid)); |
| 308 | if (rds_conn_state(conn) == RDS_CONN_UP) { | 311 | if (rds_conn_state(conn) == RDS_CONN_UP) { |
| 309 | struct rds_ib_device *rds_ibdev; | 312 | struct rds_ib_device *rds_ibdev; |
| 310 | 313 | ||
| 311 | ic = conn->c_transport_data; | ||
| 312 | |||
| 313 | rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo->src_gid, | 314 | rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo->src_gid, |
| 314 | (union ib_gid *)&iinfo->dst_gid); | 315 | (union ib_gid *)&iinfo->dst_gid); |
| 315 | 316 | ||
| @@ -329,7 +330,7 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn, | |||
| 329 | void *buffer) | 330 | void *buffer) |
| 330 | { | 331 | { |
| 331 | struct rds6_info_rdma_connection *iinfo6 = buffer; | 332 | struct rds6_info_rdma_connection *iinfo6 = buffer; |
| 332 | struct rds_ib_connection *ic; | 333 | struct rds_ib_connection *ic = conn->c_transport_data; |
| 333 | 334 | ||
| 334 | /* We will only ever look at IB transports */ | 335 | /* We will only ever look at IB transports */ |
| 335 | if (conn->c_trans != &rds_ib_transport) | 336 | if (conn->c_trans != &rds_ib_transport) |
| @@ -337,6 +338,10 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn, | |||
| 337 | 338 | ||
| 338 | iinfo6->src_addr = conn->c_laddr; | 339 | iinfo6->src_addr = conn->c_laddr; |
| 339 | iinfo6->dst_addr = conn->c_faddr; | 340 | iinfo6->dst_addr = conn->c_faddr; |
| 341 | if (ic) { | ||
| 342 | iinfo6->tos = conn->c_tos; | ||
| 343 | iinfo6->sl = ic->i_sl; | ||
| 344 | } | ||
| 340 | 345 | ||
| 341 | memset(&iinfo6->src_gid, 0, sizeof(iinfo6->src_gid)); | 346 | memset(&iinfo6->src_gid, 0, sizeof(iinfo6->src_gid)); |
| 342 | memset(&iinfo6->dst_gid, 0, sizeof(iinfo6->dst_gid)); | 347 | memset(&iinfo6->dst_gid, 0, sizeof(iinfo6->dst_gid)); |
| @@ -344,7 +349,6 @@ static int rds6_ib_conn_info_visitor(struct rds_connection *conn, | |||
| 344 | if (rds_conn_state(conn) == RDS_CONN_UP) { | 349 | if (rds_conn_state(conn) == RDS_CONN_UP) { |
| 345 | struct rds_ib_device *rds_ibdev; | 350 | struct rds_ib_device *rds_ibdev; |
| 346 | 351 | ||
| 347 | ic = conn->c_transport_data; | ||
| 348 | rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo6->src_gid, | 352 | rdma_read_gids(ic->i_cm_id, (union ib_gid *)&iinfo6->src_gid, |
| 349 | (union ib_gid *)&iinfo6->dst_gid); | 353 | (union ib_gid *)&iinfo6->dst_gid); |
| 350 | rds_ibdev = ic->rds_ibdev; | 354 | rds_ibdev = ic->rds_ibdev; |
diff --git a/net/rds/ib.h b/net/rds/ib.h index 303c6ee8bdb7..f2b558e8b5ea 100644 --- a/net/rds/ib.h +++ b/net/rds/ib.h | |||
| @@ -220,6 +220,7 @@ struct rds_ib_connection { | |||
| 220 | /* Send/Recv vectors */ | 220 | /* Send/Recv vectors */ |
| 221 | int i_scq_vector; | 221 | int i_scq_vector; |
| 222 | int i_rcq_vector; | 222 | int i_rcq_vector; |
| 223 | u8 i_sl; | ||
| 223 | }; | 224 | }; |
| 224 | 225 | ||
| 225 | /* This assumes that atomic_t is at least 32 bits */ | 226 | /* This assumes that atomic_t is at least 32 bits */ |
diff --git a/net/rds/ib_cm.c b/net/rds/ib_cm.c index fddaa09f7b0d..233f1368162b 100644 --- a/net/rds/ib_cm.c +++ b/net/rds/ib_cm.c | |||
| @@ -152,6 +152,9 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even | |||
| 152 | RDS_PROTOCOL_MINOR(conn->c_version), | 152 | RDS_PROTOCOL_MINOR(conn->c_version), |
| 153 | ic->i_flowctl ? ", flow control" : ""); | 153 | ic->i_flowctl ? ", flow control" : ""); |
| 154 | 154 | ||
| 155 | /* receive sl from the peer */ | ||
| 156 | ic->i_sl = ic->i_cm_id->route.path_rec->sl; | ||
| 157 | |||
| 155 | atomic_set(&ic->i_cq_quiesce, 0); | 158 | atomic_set(&ic->i_cq_quiesce, 0); |
| 156 | 159 | ||
| 157 | /* Init rings and fill recv. this needs to wait until protocol | 160 | /* Init rings and fill recv. this needs to wait until protocol |
diff --git a/net/rds/rdma_transport.c b/net/rds/rdma_transport.c index ff74c4bbb9fc..5f741e51b4ba 100644 --- a/net/rds/rdma_transport.c +++ b/net/rds/rdma_transport.c | |||
| @@ -43,6 +43,9 @@ static struct rdma_cm_id *rds_rdma_listen_id; | |||
| 43 | static struct rdma_cm_id *rds6_rdma_listen_id; | 43 | static struct rdma_cm_id *rds6_rdma_listen_id; |
| 44 | #endif | 44 | #endif |
| 45 | 45 | ||
| 46 | /* Per IB specification 7.7.3, service level is a 4-bit field. */ | ||
| 47 | #define TOS_TO_SL(tos) ((tos) & 0xF) | ||
| 48 | |||
| 46 | static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, | 49 | static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, |
| 47 | struct rdma_cm_event *event, | 50 | struct rdma_cm_event *event, |
| 48 | bool isv6) | 51 | bool isv6) |
| @@ -97,15 +100,19 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, | |||
| 97 | struct rds_ib_connection *ibic; | 100 | struct rds_ib_connection *ibic; |
| 98 | 101 | ||
| 99 | ibic = conn->c_transport_data; | 102 | ibic = conn->c_transport_data; |
| 100 | if (ibic && ibic->i_cm_id == cm_id) | 103 | if (ibic && ibic->i_cm_id == cm_id) { |
| 104 | cm_id->route.path_rec[0].sl = | ||
| 105 | TOS_TO_SL(conn->c_tos); | ||
| 101 | ret = trans->cm_initiate_connect(cm_id, isv6); | 106 | ret = trans->cm_initiate_connect(cm_id, isv6); |
| 102 | else | 107 | } else { |
| 103 | rds_conn_drop(conn); | 108 | rds_conn_drop(conn); |
| 109 | } | ||
| 104 | } | 110 | } |
| 105 | break; | 111 | break; |
| 106 | 112 | ||
| 107 | case RDMA_CM_EVENT_ESTABLISHED: | 113 | case RDMA_CM_EVENT_ESTABLISHED: |
| 108 | trans->cm_connect_complete(conn, event); | 114 | if (conn) |
| 115 | trans->cm_connect_complete(conn, event); | ||
| 109 | break; | 116 | break; |
| 110 | 117 | ||
| 111 | case RDMA_CM_EVENT_REJECTED: | 118 | case RDMA_CM_EVENT_REJECTED: |
| @@ -137,6 +144,8 @@ static int rds_rdma_cm_event_handler_cmn(struct rdma_cm_id *cm_id, | |||
| 137 | break; | 144 | break; |
| 138 | 145 | ||
| 139 | case RDMA_CM_EVENT_DISCONNECTED: | 146 | case RDMA_CM_EVENT_DISCONNECTED: |
| 147 | if (!conn) | ||
| 148 | break; | ||
| 140 | rdsdebug("DISCONNECT event - dropping connection " | 149 | rdsdebug("DISCONNECT event - dropping connection " |
| 141 | "%pI6c->%pI6c\n", &conn->c_laddr, | 150 | "%pI6c->%pI6c\n", &conn->c_laddr, |
| 142 | &conn->c_faddr); | 151 | &conn->c_faddr); |
diff --git a/net/rds/recv.c b/net/rds/recv.c index 853de4876088..a42ba7fa06d5 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2006, 2018 Oracle and/or its affiliates. All rights reserved. | 2 | * Copyright (c) 2006, 2019 Oracle and/or its affiliates. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This software is available to you under a choice of one of two | 4 | * This software is available to you under a choice of one of two |
| 5 | * licenses. You may choose to be licensed under the terms of the GNU | 5 | * licenses. You may choose to be licensed under the terms of the GNU |
| @@ -811,6 +811,7 @@ void rds6_inc_info_copy(struct rds_incoming *inc, | |||
| 811 | 811 | ||
| 812 | minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence); | 812 | minfo6.seq = be64_to_cpu(inc->i_hdr.h_sequence); |
| 813 | minfo6.len = be32_to_cpu(inc->i_hdr.h_len); | 813 | minfo6.len = be32_to_cpu(inc->i_hdr.h_len); |
| 814 | minfo6.tos = inc->i_conn->c_tos; | ||
| 814 | 815 | ||
| 815 | if (flip) { | 816 | if (flip) { |
| 816 | minfo6.laddr = *daddr; | 817 | minfo6.laddr = *daddr; |
| @@ -824,6 +825,8 @@ void rds6_inc_info_copy(struct rds_incoming *inc, | |||
| 824 | minfo6.fport = inc->i_hdr.h_dport; | 825 | minfo6.fport = inc->i_hdr.h_dport; |
| 825 | } | 826 | } |
| 826 | 827 | ||
| 828 | minfo6.flags = 0; | ||
| 829 | |||
| 827 | rds_info_copy(iter, &minfo6, sizeof(minfo6)); | 830 | rds_info_copy(iter, &minfo6, sizeof(minfo6)); |
| 828 | } | 831 | } |
| 829 | #endif | 832 | #endif |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index d09eaf153544..d72ddb67bb74 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
| @@ -193,7 +193,7 @@ static int rxrpc_bind(struct socket *sock, struct sockaddr *saddr, int len) | |||
| 193 | 193 | ||
| 194 | service_in_use: | 194 | service_in_use: |
| 195 | write_unlock(&local->services_lock); | 195 | write_unlock(&local->services_lock); |
| 196 | rxrpc_put_local(local); | 196 | rxrpc_unuse_local(local); |
| 197 | ret = -EADDRINUSE; | 197 | ret = -EADDRINUSE; |
| 198 | error_unlock: | 198 | error_unlock: |
| 199 | release_sock(&rx->sk); | 199 | release_sock(&rx->sk); |
| @@ -402,7 +402,7 @@ EXPORT_SYMBOL(rxrpc_kernel_check_life); | |||
| 402 | */ | 402 | */ |
| 403 | void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call) | 403 | void rxrpc_kernel_probe_life(struct socket *sock, struct rxrpc_call *call) |
| 404 | { | 404 | { |
| 405 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false, | 405 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, |
| 406 | rxrpc_propose_ack_ping_for_check_life); | 406 | rxrpc_propose_ack_ping_for_check_life); |
| 407 | rxrpc_send_ack_packet(call, true, NULL); | 407 | rxrpc_send_ack_packet(call, true, NULL); |
| 408 | } | 408 | } |
| @@ -862,7 +862,6 @@ static void rxrpc_sock_destructor(struct sock *sk) | |||
| 862 | static int rxrpc_release_sock(struct sock *sk) | 862 | static int rxrpc_release_sock(struct sock *sk) |
| 863 | { | 863 | { |
| 864 | struct rxrpc_sock *rx = rxrpc_sk(sk); | 864 | struct rxrpc_sock *rx = rxrpc_sk(sk); |
| 865 | struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk)); | ||
| 866 | 865 | ||
| 867 | _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt)); | 866 | _enter("%p{%d,%d}", sk, sk->sk_state, refcount_read(&sk->sk_refcnt)); |
| 868 | 867 | ||
| @@ -898,10 +897,8 @@ static int rxrpc_release_sock(struct sock *sk) | |||
| 898 | rxrpc_release_calls_on_socket(rx); | 897 | rxrpc_release_calls_on_socket(rx); |
| 899 | flush_workqueue(rxrpc_workqueue); | 898 | flush_workqueue(rxrpc_workqueue); |
| 900 | rxrpc_purge_queue(&sk->sk_receive_queue); | 899 | rxrpc_purge_queue(&sk->sk_receive_queue); |
| 901 | rxrpc_queue_work(&rxnet->service_conn_reaper); | ||
| 902 | rxrpc_queue_work(&rxnet->client_conn_reaper); | ||
| 903 | 900 | ||
| 904 | rxrpc_put_local(rx->local); | 901 | rxrpc_unuse_local(rx->local); |
| 905 | rx->local = NULL; | 902 | rx->local = NULL; |
| 906 | key_put(rx->key); | 903 | key_put(rx->key); |
| 907 | rx->key = NULL; | 904 | rx->key = NULL; |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 80335b4ee4fd..8051dfdcf26d 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
| @@ -185,11 +185,17 @@ struct rxrpc_host_header { | |||
| 185 | * - max 48 bytes (struct sk_buff::cb) | 185 | * - max 48 bytes (struct sk_buff::cb) |
| 186 | */ | 186 | */ |
| 187 | struct rxrpc_skb_priv { | 187 | struct rxrpc_skb_priv { |
| 188 | union { | 188 | atomic_t nr_ring_pins; /* Number of rxtx ring pins */ |
| 189 | u8 nr_jumbo; /* Number of jumbo subpackets */ | 189 | u8 nr_subpackets; /* Number of subpackets */ |
| 190 | }; | 190 | u8 rx_flags; /* Received packet flags */ |
| 191 | #define RXRPC_SKB_INCL_LAST 0x01 /* - Includes last packet */ | ||
| 192 | #define RXRPC_SKB_TX_BUFFER 0x02 /* - Is transmit buffer */ | ||
| 191 | union { | 193 | union { |
| 192 | int remain; /* amount of space remaining for next write */ | 194 | int remain; /* amount of space remaining for next write */ |
| 195 | |||
| 196 | /* List of requested ACKs on subpackets */ | ||
| 197 | unsigned long rx_req_ack[(RXRPC_MAX_NR_JUMBO + BITS_PER_LONG - 1) / | ||
| 198 | BITS_PER_LONG]; | ||
| 193 | }; | 199 | }; |
| 194 | 200 | ||
| 195 | struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */ | 201 | struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */ |
| @@ -254,7 +260,8 @@ struct rxrpc_security { | |||
| 254 | */ | 260 | */ |
| 255 | struct rxrpc_local { | 261 | struct rxrpc_local { |
| 256 | struct rcu_head rcu; | 262 | struct rcu_head rcu; |
| 257 | atomic_t usage; | 263 | atomic_t active_users; /* Number of users of the local endpoint */ |
| 264 | atomic_t usage; /* Number of references to the structure */ | ||
| 258 | struct rxrpc_net *rxnet; /* The network ns in which this resides */ | 265 | struct rxrpc_net *rxnet; /* The network ns in which this resides */ |
| 259 | struct list_head link; | 266 | struct list_head link; |
| 260 | struct socket *socket; /* my UDP socket */ | 267 | struct socket *socket; /* my UDP socket */ |
| @@ -612,8 +619,7 @@ struct rxrpc_call { | |||
| 612 | #define RXRPC_TX_ANNO_LAST 0x04 | 619 | #define RXRPC_TX_ANNO_LAST 0x04 |
| 613 | #define RXRPC_TX_ANNO_RESENT 0x08 | 620 | #define RXRPC_TX_ANNO_RESENT 0x08 |
| 614 | 621 | ||
| 615 | #define RXRPC_RX_ANNO_JUMBO 0x3f /* Jumbo subpacket number + 1 if not zero */ | 622 | #define RXRPC_RX_ANNO_SUBPACKET 0x3f /* Subpacket number in jumbogram */ |
| 616 | #define RXRPC_RX_ANNO_JLAST 0x40 /* Set if last element of a jumbo packet */ | ||
| 617 | #define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */ | 623 | #define RXRPC_RX_ANNO_VERIFIED 0x80 /* Set if verified and decrypted */ |
| 618 | rxrpc_seq_t tx_hard_ack; /* Dead slot in buffer; the first transmitted but | 624 | rxrpc_seq_t tx_hard_ack; /* Dead slot in buffer; the first transmitted but |
| 619 | * not hard-ACK'd packet follows this. | 625 | * not hard-ACK'd packet follows this. |
| @@ -649,7 +655,6 @@ struct rxrpc_call { | |||
| 649 | 655 | ||
| 650 | /* receive-phase ACK management */ | 656 | /* receive-phase ACK management */ |
| 651 | u8 ackr_reason; /* reason to ACK */ | 657 | u8 ackr_reason; /* reason to ACK */ |
| 652 | u16 ackr_skew; /* skew on packet being ACK'd */ | ||
| 653 | rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */ | 658 | rxrpc_serial_t ackr_serial; /* serial of packet being ACK'd */ |
| 654 | rxrpc_serial_t ackr_first_seq; /* first sequence number received */ | 659 | rxrpc_serial_t ackr_first_seq; /* first sequence number received */ |
| 655 | rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */ | 660 | rxrpc_seq_t ackr_prev_seq; /* previous sequence number received */ |
| @@ -743,7 +748,7 @@ int rxrpc_reject_call(struct rxrpc_sock *); | |||
| 743 | /* | 748 | /* |
| 744 | * call_event.c | 749 | * call_event.c |
| 745 | */ | 750 | */ |
| 746 | void rxrpc_propose_ACK(struct rxrpc_call *, u8, u16, u32, bool, bool, | 751 | void rxrpc_propose_ACK(struct rxrpc_call *, u8, u32, bool, bool, |
| 747 | enum rxrpc_propose_ack_trace); | 752 | enum rxrpc_propose_ack_trace); |
| 748 | void rxrpc_process_call(struct work_struct *); | 753 | void rxrpc_process_call(struct work_struct *); |
| 749 | 754 | ||
| @@ -905,6 +910,7 @@ void rxrpc_disconnect_client_call(struct rxrpc_call *); | |||
| 905 | void rxrpc_put_client_conn(struct rxrpc_connection *); | 910 | void rxrpc_put_client_conn(struct rxrpc_connection *); |
| 906 | void rxrpc_discard_expired_client_conns(struct work_struct *); | 911 | void rxrpc_discard_expired_client_conns(struct work_struct *); |
| 907 | void rxrpc_destroy_all_client_connections(struct rxrpc_net *); | 912 | void rxrpc_destroy_all_client_connections(struct rxrpc_net *); |
| 913 | void rxrpc_clean_up_local_conns(struct rxrpc_local *); | ||
| 908 | 914 | ||
| 909 | /* | 915 | /* |
| 910 | * conn_event.c | 916 | * conn_event.c |
| @@ -1002,6 +1008,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *, const struct sockaddr_rxrpc | |||
| 1002 | struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *); | 1008 | struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *); |
| 1003 | struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *); | 1009 | struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *); |
| 1004 | void rxrpc_put_local(struct rxrpc_local *); | 1010 | void rxrpc_put_local(struct rxrpc_local *); |
| 1011 | struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *); | ||
| 1012 | void rxrpc_unuse_local(struct rxrpc_local *); | ||
| 1005 | void rxrpc_queue_local(struct rxrpc_local *); | 1013 | void rxrpc_queue_local(struct rxrpc_local *); |
| 1006 | void rxrpc_destroy_all_locals(struct rxrpc_net *); | 1014 | void rxrpc_destroy_all_locals(struct rxrpc_net *); |
| 1007 | 1015 | ||
| @@ -1061,6 +1069,7 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *); | |||
| 1061 | struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *); | 1069 | struct rxrpc_peer *rxrpc_get_peer(struct rxrpc_peer *); |
| 1062 | struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *); | 1070 | struct rxrpc_peer *rxrpc_get_peer_maybe(struct rxrpc_peer *); |
| 1063 | void rxrpc_put_peer(struct rxrpc_peer *); | 1071 | void rxrpc_put_peer(struct rxrpc_peer *); |
| 1072 | void rxrpc_put_peer_locked(struct rxrpc_peer *); | ||
| 1064 | 1073 | ||
| 1065 | /* | 1074 | /* |
| 1066 | * proc.c | 1075 | * proc.c |
| @@ -1102,6 +1111,7 @@ void rxrpc_kernel_data_consumed(struct rxrpc_call *, struct sk_buff *); | |||
| 1102 | void rxrpc_packet_destructor(struct sk_buff *); | 1111 | void rxrpc_packet_destructor(struct sk_buff *); |
| 1103 | void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace); | 1112 | void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace); |
| 1104 | void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace); | 1113 | void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace); |
| 1114 | void rxrpc_eaten_skb(struct sk_buff *, enum rxrpc_skb_trace); | ||
| 1105 | void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace); | 1115 | void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace); |
| 1106 | void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace); | 1116 | void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace); |
| 1107 | void rxrpc_purge_queue(struct sk_buff_head *); | 1117 | void rxrpc_purge_queue(struct sk_buff_head *); |
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c index bc2adeb3acb9..cedbbb3a7c2e 100644 --- a/net/rxrpc/call_event.c +++ b/net/rxrpc/call_event.c | |||
| @@ -43,8 +43,7 @@ static void rxrpc_propose_ping(struct rxrpc_call *call, | |||
| 43 | * propose an ACK be sent | 43 | * propose an ACK be sent |
| 44 | */ | 44 | */ |
| 45 | static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, | 45 | static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
| 46 | u16 skew, u32 serial, bool immediate, | 46 | u32 serial, bool immediate, bool background, |
| 47 | bool background, | ||
| 48 | enum rxrpc_propose_ack_trace why) | 47 | enum rxrpc_propose_ack_trace why) |
| 49 | { | 48 | { |
| 50 | enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use; | 49 | enum rxrpc_propose_ack_outcome outcome = rxrpc_propose_ack_use; |
| @@ -69,14 +68,12 @@ static void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, | |||
| 69 | if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) { | 68 | if (RXRPC_ACK_UPDATEABLE & (1 << ack_reason)) { |
| 70 | outcome = rxrpc_propose_ack_update; | 69 | outcome = rxrpc_propose_ack_update; |
| 71 | call->ackr_serial = serial; | 70 | call->ackr_serial = serial; |
| 72 | call->ackr_skew = skew; | ||
| 73 | } | 71 | } |
| 74 | if (!immediate) | 72 | if (!immediate) |
| 75 | goto trace; | 73 | goto trace; |
| 76 | } else if (prior > rxrpc_ack_priority[call->ackr_reason]) { | 74 | } else if (prior > rxrpc_ack_priority[call->ackr_reason]) { |
| 77 | call->ackr_reason = ack_reason; | 75 | call->ackr_reason = ack_reason; |
| 78 | call->ackr_serial = serial; | 76 | call->ackr_serial = serial; |
| 79 | call->ackr_skew = skew; | ||
| 80 | } else { | 77 | } else { |
| 81 | outcome = rxrpc_propose_ack_subsume; | 78 | outcome = rxrpc_propose_ack_subsume; |
| 82 | } | 79 | } |
| @@ -137,11 +134,11 @@ trace: | |||
| 137 | * propose an ACK be sent, locking the call structure | 134 | * propose an ACK be sent, locking the call structure |
| 138 | */ | 135 | */ |
| 139 | void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, | 136 | void rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, |
| 140 | u16 skew, u32 serial, bool immediate, bool background, | 137 | u32 serial, bool immediate, bool background, |
| 141 | enum rxrpc_propose_ack_trace why) | 138 | enum rxrpc_propose_ack_trace why) |
| 142 | { | 139 | { |
| 143 | spin_lock_bh(&call->lock); | 140 | spin_lock_bh(&call->lock); |
| 144 | __rxrpc_propose_ACK(call, ack_reason, skew, serial, | 141 | __rxrpc_propose_ACK(call, ack_reason, serial, |
| 145 | immediate, background, why); | 142 | immediate, background, why); |
| 146 | spin_unlock_bh(&call->lock); | 143 | spin_unlock_bh(&call->lock); |
| 147 | } | 144 | } |
| @@ -202,7 +199,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) | |||
| 202 | continue; | 199 | continue; |
| 203 | 200 | ||
| 204 | skb = call->rxtx_buffer[ix]; | 201 | skb = call->rxtx_buffer[ix]; |
| 205 | rxrpc_see_skb(skb, rxrpc_skb_tx_seen); | 202 | rxrpc_see_skb(skb, rxrpc_skb_seen); |
| 206 | 203 | ||
| 207 | if (anno_type == RXRPC_TX_ANNO_UNACK) { | 204 | if (anno_type == RXRPC_TX_ANNO_UNACK) { |
| 208 | if (ktime_after(skb->tstamp, max_age)) { | 205 | if (ktime_after(skb->tstamp, max_age)) { |
| @@ -239,7 +236,7 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) | |||
| 239 | ack_ts = ktime_sub(now, call->acks_latest_ts); | 236 | ack_ts = ktime_sub(now, call->acks_latest_ts); |
| 240 | if (ktime_to_ns(ack_ts) < call->peer->rtt) | 237 | if (ktime_to_ns(ack_ts) < call->peer->rtt) |
| 241 | goto out; | 238 | goto out; |
| 242 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false, | 239 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, |
| 243 | rxrpc_propose_ack_ping_for_lost_ack); | 240 | rxrpc_propose_ack_ping_for_lost_ack); |
| 244 | rxrpc_send_ack_packet(call, true, NULL); | 241 | rxrpc_send_ack_packet(call, true, NULL); |
| 245 | goto out; | 242 | goto out; |
| @@ -258,18 +255,18 @@ static void rxrpc_resend(struct rxrpc_call *call, unsigned long now_j) | |||
| 258 | continue; | 255 | continue; |
| 259 | 256 | ||
| 260 | skb = call->rxtx_buffer[ix]; | 257 | skb = call->rxtx_buffer[ix]; |
| 261 | rxrpc_get_skb(skb, rxrpc_skb_tx_got); | 258 | rxrpc_get_skb(skb, rxrpc_skb_got); |
| 262 | spin_unlock_bh(&call->lock); | 259 | spin_unlock_bh(&call->lock); |
| 263 | 260 | ||
| 264 | if (rxrpc_send_data_packet(call, skb, true) < 0) { | 261 | if (rxrpc_send_data_packet(call, skb, true) < 0) { |
| 265 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 262 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 266 | return; | 263 | return; |
| 267 | } | 264 | } |
| 268 | 265 | ||
| 269 | if (rxrpc_is_client_call(call)) | 266 | if (rxrpc_is_client_call(call)) |
| 270 | rxrpc_expose_client_call(call); | 267 | rxrpc_expose_client_call(call); |
| 271 | 268 | ||
| 272 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 269 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 273 | spin_lock_bh(&call->lock); | 270 | spin_lock_bh(&call->lock); |
| 274 | 271 | ||
| 275 | /* We need to clear the retransmit state, but there are two | 272 | /* We need to clear the retransmit state, but there are two |
| @@ -372,7 +369,7 @@ recheck_state: | |||
| 372 | if (time_after_eq(now, t)) { | 369 | if (time_after_eq(now, t)) { |
| 373 | trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now); | 370 | trace_rxrpc_timer(call, rxrpc_timer_exp_keepalive, now); |
| 374 | cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET); | 371 | cmpxchg(&call->keepalive_at, t, now + MAX_JIFFY_OFFSET); |
| 375 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, true, | 372 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, true, |
| 376 | rxrpc_propose_ack_ping_for_keepalive); | 373 | rxrpc_propose_ack_ping_for_keepalive); |
| 377 | set_bit(RXRPC_CALL_EV_PING, &call->events); | 374 | set_bit(RXRPC_CALL_EV_PING, &call->events); |
| 378 | } | 375 | } |
| @@ -407,7 +404,7 @@ recheck_state: | |||
| 407 | send_ack = NULL; | 404 | send_ack = NULL; |
| 408 | if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) { | 405 | if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events)) { |
| 409 | call->acks_lost_top = call->tx_top; | 406 | call->acks_lost_top = call->tx_top; |
| 410 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, 0, true, false, | 407 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, 0, true, false, |
| 411 | rxrpc_propose_ack_ping_for_lost_ack); | 408 | rxrpc_propose_ack_ping_for_lost_ack); |
| 412 | send_ack = &call->acks_lost_ping; | 409 | send_ack = &call->acks_lost_ping; |
| 413 | } | 410 | } |
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 217b12be9e08..014548c259ce 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c | |||
| @@ -422,6 +422,19 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace op) | |||
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | /* | 424 | /* |
| 425 | * Clean up the RxTx skb ring. | ||
| 426 | */ | ||
| 427 | static void rxrpc_cleanup_ring(struct rxrpc_call *call) | ||
| 428 | { | ||
| 429 | int i; | ||
| 430 | |||
| 431 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { | ||
| 432 | rxrpc_free_skb(call->rxtx_buffer[i], rxrpc_skb_cleaned); | ||
| 433 | call->rxtx_buffer[i] = NULL; | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | /* | ||
| 425 | * Detach a call from its owning socket. | 438 | * Detach a call from its owning socket. |
| 426 | */ | 439 | */ |
| 427 | void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) | 440 | void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) |
| @@ -429,7 +442,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) | |||
| 429 | const void *here = __builtin_return_address(0); | 442 | const void *here = __builtin_return_address(0); |
| 430 | struct rxrpc_connection *conn = call->conn; | 443 | struct rxrpc_connection *conn = call->conn; |
| 431 | bool put = false; | 444 | bool put = false; |
| 432 | int i; | ||
| 433 | 445 | ||
| 434 | _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); | 446 | _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage)); |
| 435 | 447 | ||
| @@ -479,13 +491,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call) | |||
| 479 | if (conn) | 491 | if (conn) |
| 480 | rxrpc_disconnect_call(call); | 492 | rxrpc_disconnect_call(call); |
| 481 | 493 | ||
| 482 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) { | 494 | rxrpc_cleanup_ring(call); |
| 483 | rxrpc_free_skb(call->rxtx_buffer[i], | ||
| 484 | (call->tx_phase ? rxrpc_skb_tx_cleaned : | ||
| 485 | rxrpc_skb_rx_cleaned)); | ||
| 486 | call->rxtx_buffer[i] = NULL; | ||
| 487 | } | ||
| 488 | |||
| 489 | _leave(""); | 495 | _leave(""); |
| 490 | } | 496 | } |
| 491 | 497 | ||
| @@ -568,8 +574,6 @@ static void rxrpc_rcu_destroy_call(struct rcu_head *rcu) | |||
| 568 | */ | 574 | */ |
| 569 | void rxrpc_cleanup_call(struct rxrpc_call *call) | 575 | void rxrpc_cleanup_call(struct rxrpc_call *call) |
| 570 | { | 576 | { |
| 571 | int i; | ||
| 572 | |||
| 573 | _net("DESTROY CALL %d", call->debug_id); | 577 | _net("DESTROY CALL %d", call->debug_id); |
| 574 | 578 | ||
| 575 | memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); | 579 | memset(&call->sock_node, 0xcd, sizeof(call->sock_node)); |
| @@ -580,13 +584,8 @@ void rxrpc_cleanup_call(struct rxrpc_call *call) | |||
| 580 | ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); | 584 | ASSERT(test_bit(RXRPC_CALL_RELEASED, &call->flags)); |
| 581 | ASSERTCMP(call->conn, ==, NULL); | 585 | ASSERTCMP(call->conn, ==, NULL); |
| 582 | 586 | ||
| 583 | /* Clean up the Rx/Tx buffer */ | 587 | rxrpc_cleanup_ring(call); |
| 584 | for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) | 588 | rxrpc_free_skb(call->tx_pending, rxrpc_skb_cleaned); |
| 585 | rxrpc_free_skb(call->rxtx_buffer[i], | ||
| 586 | (call->tx_phase ? rxrpc_skb_tx_cleaned : | ||
| 587 | rxrpc_skb_rx_cleaned)); | ||
| 588 | |||
| 589 | rxrpc_free_skb(call->tx_pending, rxrpc_skb_tx_cleaned); | ||
| 590 | 589 | ||
| 591 | call_rcu(&call->rcu, rxrpc_rcu_destroy_call); | 590 | call_rcu(&call->rcu, rxrpc_rcu_destroy_call); |
| 592 | } | 591 | } |
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c index aea82f909c60..3f1da1b49f69 100644 --- a/net/rxrpc/conn_client.c +++ b/net/rxrpc/conn_client.c | |||
| @@ -1162,3 +1162,47 @@ void rxrpc_destroy_all_client_connections(struct rxrpc_net *rxnet) | |||
| 1162 | 1162 | ||
| 1163 | _leave(""); | 1163 | _leave(""); |
| 1164 | } | 1164 | } |
| 1165 | |||
| 1166 | /* | ||
| 1167 | * Clean up the client connections on a local endpoint. | ||
| 1168 | */ | ||
| 1169 | void rxrpc_clean_up_local_conns(struct rxrpc_local *local) | ||
| 1170 | { | ||
| 1171 | struct rxrpc_connection *conn, *tmp; | ||
| 1172 | struct rxrpc_net *rxnet = local->rxnet; | ||
| 1173 | unsigned int nr_active; | ||
| 1174 | LIST_HEAD(graveyard); | ||
| 1175 | |||
| 1176 | _enter(""); | ||
| 1177 | |||
| 1178 | spin_lock(&rxnet->client_conn_cache_lock); | ||
| 1179 | nr_active = rxnet->nr_active_client_conns; | ||
| 1180 | |||
| 1181 | list_for_each_entry_safe(conn, tmp, &rxnet->idle_client_conns, | ||
| 1182 | cache_link) { | ||
| 1183 | if (conn->params.local == local) { | ||
| 1184 | ASSERTCMP(conn->cache_state, ==, RXRPC_CONN_CLIENT_IDLE); | ||
| 1185 | |||
| 1186 | trace_rxrpc_client(conn, -1, rxrpc_client_discard); | ||
| 1187 | if (!test_and_clear_bit(RXRPC_CONN_EXPOSED, &conn->flags)) | ||
| 1188 | BUG(); | ||
| 1189 | conn->cache_state = RXRPC_CONN_CLIENT_INACTIVE; | ||
| 1190 | list_move(&conn->cache_link, &graveyard); | ||
| 1191 | nr_active--; | ||
| 1192 | } | ||
| 1193 | } | ||
| 1194 | |||
| 1195 | rxnet->nr_active_client_conns = nr_active; | ||
| 1196 | spin_unlock(&rxnet->client_conn_cache_lock); | ||
| 1197 | ASSERTCMP(nr_active, >=, 0); | ||
| 1198 | |||
| 1199 | while (!list_empty(&graveyard)) { | ||
| 1200 | conn = list_entry(graveyard.next, | ||
| 1201 | struct rxrpc_connection, cache_link); | ||
| 1202 | list_del_init(&conn->cache_link); | ||
| 1203 | |||
| 1204 | rxrpc_put_connection(conn); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | _leave(" [culled]"); | ||
| 1208 | } | ||
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c index df6624c140be..a1ceef4f5cd0 100644 --- a/net/rxrpc/conn_event.c +++ b/net/rxrpc/conn_event.c | |||
| @@ -472,7 +472,7 @@ void rxrpc_process_connection(struct work_struct *work) | |||
| 472 | /* go through the conn-level event packets, releasing the ref on this | 472 | /* go through the conn-level event packets, releasing the ref on this |
| 473 | * connection that each one has when we've finished with it */ | 473 | * connection that each one has when we've finished with it */ |
| 474 | while ((skb = skb_dequeue(&conn->rx_queue))) { | 474 | while ((skb = skb_dequeue(&conn->rx_queue))) { |
| 475 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); | 475 | rxrpc_see_skb(skb, rxrpc_skb_seen); |
| 476 | ret = rxrpc_process_event(conn, skb, &abort_code); | 476 | ret = rxrpc_process_event(conn, skb, &abort_code); |
| 477 | switch (ret) { | 477 | switch (ret) { |
| 478 | case -EPROTO: | 478 | case -EPROTO: |
| @@ -484,7 +484,7 @@ void rxrpc_process_connection(struct work_struct *work) | |||
| 484 | goto requeue_and_leave; | 484 | goto requeue_and_leave; |
| 485 | case -ECONNABORTED: | 485 | case -ECONNABORTED: |
| 486 | default: | 486 | default: |
| 487 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 487 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 488 | break; | 488 | break; |
| 489 | } | 489 | } |
| 490 | } | 490 | } |
| @@ -501,6 +501,6 @@ requeue_and_leave: | |||
| 501 | protocol_error: | 501 | protocol_error: |
| 502 | if (rxrpc_abort_connection(conn, ret, abort_code) < 0) | 502 | if (rxrpc_abort_connection(conn, ret, abort_code) < 0) |
| 503 | goto requeue_and_leave; | 503 | goto requeue_and_leave; |
| 504 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 504 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 505 | goto out; | 505 | goto out; |
| 506 | } | 506 | } |
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index 434ef392212b..ed05b6922132 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c | |||
| @@ -398,7 +398,7 @@ void rxrpc_service_connection_reaper(struct work_struct *work) | |||
| 398 | if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) | 398 | if (conn->state == RXRPC_CONN_SERVICE_PREALLOC) |
| 399 | continue; | 399 | continue; |
| 400 | 400 | ||
| 401 | if (rxnet->live) { | 401 | if (rxnet->live && !conn->params.local->dead) { |
| 402 | idle_timestamp = READ_ONCE(conn->idle_timestamp); | 402 | idle_timestamp = READ_ONCE(conn->idle_timestamp); |
| 403 | expire_at = idle_timestamp + rxrpc_connection_expiry * HZ; | 403 | expire_at = idle_timestamp + rxrpc_connection_expiry * HZ; |
| 404 | if (conn->params.local->service_closed) | 404 | if (conn->params.local->service_closed) |
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c index 5bd6f1546e5c..d122c53c8697 100644 --- a/net/rxrpc/input.c +++ b/net/rxrpc/input.c | |||
| @@ -196,15 +196,14 @@ send_extra_data: | |||
| 196 | * Ping the other end to fill our RTT cache and to retrieve the rwind | 196 | * Ping the other end to fill our RTT cache and to retrieve the rwind |
| 197 | * and MTU parameters. | 197 | * and MTU parameters. |
| 198 | */ | 198 | */ |
| 199 | static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb, | 199 | static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb) |
| 200 | int skew) | ||
| 201 | { | 200 | { |
| 202 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 201 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 203 | ktime_t now = skb->tstamp; | 202 | ktime_t now = skb->tstamp; |
| 204 | 203 | ||
| 205 | if (call->peer->rtt_usage < 3 || | 204 | if (call->peer->rtt_usage < 3 || |
| 206 | ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now)) | 205 | ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now)) |
| 207 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial, | 206 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial, |
| 208 | true, true, | 207 | true, true, |
| 209 | rxrpc_propose_ack_ping_for_params); | 208 | rxrpc_propose_ack_ping_for_params); |
| 210 | } | 209 | } |
| @@ -234,7 +233,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to, | |||
| 234 | ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK; | 233 | ix = call->tx_hard_ack & RXRPC_RXTX_BUFF_MASK; |
| 235 | skb = call->rxtx_buffer[ix]; | 234 | skb = call->rxtx_buffer[ix]; |
| 236 | annotation = call->rxtx_annotations[ix]; | 235 | annotation = call->rxtx_annotations[ix]; |
| 237 | rxrpc_see_skb(skb, rxrpc_skb_tx_rotated); | 236 | rxrpc_see_skb(skb, rxrpc_skb_rotated); |
| 238 | call->rxtx_buffer[ix] = NULL; | 237 | call->rxtx_buffer[ix] = NULL; |
| 239 | call->rxtx_annotations[ix] = 0; | 238 | call->rxtx_annotations[ix] = 0; |
| 240 | skb->next = list; | 239 | skb->next = list; |
| @@ -259,7 +258,7 @@ static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to, | |||
| 259 | skb = list; | 258 | skb = list; |
| 260 | list = skb->next; | 259 | list = skb->next; |
| 261 | skb_mark_not_on_list(skb); | 260 | skb_mark_not_on_list(skb); |
| 262 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 261 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 263 | } | 262 | } |
| 264 | 263 | ||
| 265 | return rot_last; | 264 | return rot_last; |
| @@ -348,7 +347,7 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call) | |||
| 348 | } | 347 | } |
| 349 | 348 | ||
| 350 | /* | 349 | /* |
| 351 | * Scan a jumbo packet to validate its structure and to work out how many | 350 | * Scan a data packet to validate its structure and to work out how many |
| 352 | * subpackets it contains. | 351 | * subpackets it contains. |
| 353 | * | 352 | * |
| 354 | * A jumbo packet is a collection of consecutive packets glued together with | 353 | * A jumbo packet is a collection of consecutive packets glued together with |
| @@ -359,16 +358,21 @@ static bool rxrpc_receiving_reply(struct rxrpc_call *call) | |||
| 359 | * the last are RXRPC_JUMBO_DATALEN in size. The last subpacket may be of any | 358 | * the last are RXRPC_JUMBO_DATALEN in size. The last subpacket may be of any |
| 360 | * size. | 359 | * size. |
| 361 | */ | 360 | */ |
| 362 | static bool rxrpc_validate_jumbo(struct sk_buff *skb) | 361 | static bool rxrpc_validate_data(struct sk_buff *skb) |
| 363 | { | 362 | { |
| 364 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 363 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 365 | unsigned int offset = sizeof(struct rxrpc_wire_header); | 364 | unsigned int offset = sizeof(struct rxrpc_wire_header); |
| 366 | unsigned int len = skb->len; | 365 | unsigned int len = skb->len; |
| 367 | int nr_jumbo = 1; | ||
| 368 | u8 flags = sp->hdr.flags; | 366 | u8 flags = sp->hdr.flags; |
| 369 | 367 | ||
| 370 | do { | 368 | for (;;) { |
| 371 | nr_jumbo++; | 369 | if (flags & RXRPC_REQUEST_ACK) |
| 370 | __set_bit(sp->nr_subpackets, sp->rx_req_ack); | ||
| 371 | sp->nr_subpackets++; | ||
| 372 | |||
| 373 | if (!(flags & RXRPC_JUMBO_PACKET)) | ||
| 374 | break; | ||
| 375 | |||
| 372 | if (len - offset < RXRPC_JUMBO_SUBPKTLEN) | 376 | if (len - offset < RXRPC_JUMBO_SUBPKTLEN) |
| 373 | goto protocol_error; | 377 | goto protocol_error; |
| 374 | if (flags & RXRPC_LAST_PACKET) | 378 | if (flags & RXRPC_LAST_PACKET) |
| @@ -377,9 +381,10 @@ static bool rxrpc_validate_jumbo(struct sk_buff *skb) | |||
| 377 | if (skb_copy_bits(skb, offset, &flags, 1) < 0) | 381 | if (skb_copy_bits(skb, offset, &flags, 1) < 0) |
| 378 | goto protocol_error; | 382 | goto protocol_error; |
| 379 | offset += sizeof(struct rxrpc_jumbo_header); | 383 | offset += sizeof(struct rxrpc_jumbo_header); |
| 380 | } while (flags & RXRPC_JUMBO_PACKET); | 384 | } |
| 381 | 385 | ||
| 382 | sp->nr_jumbo = nr_jumbo; | 386 | if (flags & RXRPC_LAST_PACKET) |
| 387 | sp->rx_flags |= RXRPC_SKB_INCL_LAST; | ||
| 383 | return true; | 388 | return true; |
| 384 | 389 | ||
| 385 | protocol_error: | 390 | protocol_error: |
| @@ -400,10 +405,10 @@ protocol_error: | |||
| 400 | * (that information is encoded in the ACK packet). | 405 | * (that information is encoded in the ACK packet). |
| 401 | */ | 406 | */ |
| 402 | static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq, | 407 | static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq, |
| 403 | u8 annotation, bool *_jumbo_bad) | 408 | bool is_jumbo, bool *_jumbo_bad) |
| 404 | { | 409 | { |
| 405 | /* Discard normal packets that are duplicates. */ | 410 | /* Discard normal packets that are duplicates. */ |
| 406 | if (annotation == 0) | 411 | if (is_jumbo) |
| 407 | return; | 412 | return; |
| 408 | 413 | ||
| 409 | /* Skip jumbo subpackets that are duplicates. When we've had three or | 414 | /* Skip jumbo subpackets that are duplicates. When we've had three or |
| @@ -417,30 +422,30 @@ static void rxrpc_input_dup_data(struct rxrpc_call *call, rxrpc_seq_t seq, | |||
| 417 | } | 422 | } |
| 418 | 423 | ||
| 419 | /* | 424 | /* |
| 420 | * Process a DATA packet, adding the packet to the Rx ring. | 425 | * Process a DATA packet, adding the packet to the Rx ring. The caller's |
| 426 | * packet ref must be passed on or discarded. | ||
| 421 | */ | 427 | */ |
| 422 | static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb, | 428 | static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb) |
| 423 | u16 skew) | ||
| 424 | { | 429 | { |
| 425 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 430 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 426 | enum rxrpc_call_state state; | 431 | enum rxrpc_call_state state; |
| 427 | unsigned int offset = sizeof(struct rxrpc_wire_header); | 432 | unsigned int j; |
| 428 | unsigned int ix; | ||
| 429 | rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0; | 433 | rxrpc_serial_t serial = sp->hdr.serial, ack_serial = 0; |
| 430 | rxrpc_seq_t seq = sp->hdr.seq, hard_ack; | 434 | rxrpc_seq_t seq0 = sp->hdr.seq, hard_ack; |
| 431 | bool immediate_ack = false, jumbo_bad = false, queued; | 435 | bool immediate_ack = false, jumbo_bad = false; |
| 432 | u16 len; | 436 | u8 ack = 0; |
| 433 | u8 ack = 0, flags, annotation = 0; | ||
| 434 | 437 | ||
| 435 | _enter("{%u,%u},{%u,%u}", | 438 | _enter("{%u,%u},{%u,%u}", |
| 436 | call->rx_hard_ack, call->rx_top, skb->len, seq); | 439 | call->rx_hard_ack, call->rx_top, skb->len, seq0); |
| 437 | 440 | ||
| 438 | _proto("Rx DATA %%%u { #%u f=%02x }", | 441 | _proto("Rx DATA %%%u { #%u f=%02x n=%u }", |
| 439 | sp->hdr.serial, seq, sp->hdr.flags); | 442 | sp->hdr.serial, seq0, sp->hdr.flags, sp->nr_subpackets); |
| 440 | 443 | ||
| 441 | state = READ_ONCE(call->state); | 444 | state = READ_ONCE(call->state); |
| 442 | if (state >= RXRPC_CALL_COMPLETE) | 445 | if (state >= RXRPC_CALL_COMPLETE) { |
| 446 | rxrpc_free_skb(skb, rxrpc_skb_freed); | ||
| 443 | return; | 447 | return; |
| 448 | } | ||
| 444 | 449 | ||
| 445 | if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) { | 450 | if (call->state == RXRPC_CALL_SERVER_RECV_REQUEST) { |
| 446 | unsigned long timo = READ_ONCE(call->next_req_timo); | 451 | unsigned long timo = READ_ONCE(call->next_req_timo); |
| @@ -465,156 +470,157 @@ static void rxrpc_input_data(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 465 | !rxrpc_receiving_reply(call)) | 470 | !rxrpc_receiving_reply(call)) |
| 466 | goto unlock; | 471 | goto unlock; |
| 467 | 472 | ||
| 468 | call->ackr_prev_seq = seq; | 473 | call->ackr_prev_seq = seq0; |
| 469 | |||
| 470 | hard_ack = READ_ONCE(call->rx_hard_ack); | 474 | hard_ack = READ_ONCE(call->rx_hard_ack); |
| 471 | if (after(seq, hard_ack + call->rx_winsize)) { | ||
| 472 | ack = RXRPC_ACK_EXCEEDS_WINDOW; | ||
| 473 | ack_serial = serial; | ||
| 474 | goto ack; | ||
| 475 | } | ||
| 476 | 475 | ||
| 477 | flags = sp->hdr.flags; | 476 | if (sp->nr_subpackets > 1) { |
| 478 | if (flags & RXRPC_JUMBO_PACKET) { | ||
| 479 | if (call->nr_jumbo_bad > 3) { | 477 | if (call->nr_jumbo_bad > 3) { |
| 480 | ack = RXRPC_ACK_NOSPACE; | 478 | ack = RXRPC_ACK_NOSPACE; |
| 481 | ack_serial = serial; | 479 | ack_serial = serial; |
| 482 | goto ack; | 480 | goto ack; |
| 483 | } | 481 | } |
| 484 | annotation = 1; | ||
| 485 | } | 482 | } |
| 486 | 483 | ||
| 487 | next_subpacket: | 484 | for (j = 0; j < sp->nr_subpackets; j++) { |
| 488 | queued = false; | 485 | rxrpc_serial_t serial = sp->hdr.serial + j; |
| 489 | ix = seq & RXRPC_RXTX_BUFF_MASK; | 486 | rxrpc_seq_t seq = seq0 + j; |
| 490 | len = skb->len; | 487 | unsigned int ix = seq & RXRPC_RXTX_BUFF_MASK; |
| 491 | if (flags & RXRPC_JUMBO_PACKET) | 488 | bool terminal = (j == sp->nr_subpackets - 1); |
| 492 | len = RXRPC_JUMBO_DATALEN; | 489 | bool last = terminal && (sp->rx_flags & RXRPC_SKB_INCL_LAST); |
| 493 | 490 | u8 flags, annotation = j; | |
| 494 | if (flags & RXRPC_LAST_PACKET) { | 491 | |
| 495 | if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) && | 492 | _proto("Rx DATA+%u %%%u { #%x t=%u l=%u }", |
| 496 | seq != call->rx_top) { | 493 | j, serial, seq, terminal, last); |
| 497 | rxrpc_proto_abort("LSN", call, seq); | 494 | |
| 498 | goto unlock; | 495 | if (last) { |
| 499 | } | 496 | if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) && |
| 500 | } else { | 497 | seq != call->rx_top) { |
| 501 | if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) && | 498 | rxrpc_proto_abort("LSN", call, seq); |
| 502 | after_eq(seq, call->rx_top)) { | 499 | goto unlock; |
| 503 | rxrpc_proto_abort("LSA", call, seq); | 500 | } |
| 504 | goto unlock; | 501 | } else { |
| 502 | if (test_bit(RXRPC_CALL_RX_LAST, &call->flags) && | ||
| 503 | after_eq(seq, call->rx_top)) { | ||
| 504 | rxrpc_proto_abort("LSA", call, seq); | ||
| 505 | goto unlock; | ||
| 506 | } | ||
| 505 | } | 507 | } |
| 506 | } | ||
| 507 | |||
| 508 | trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation); | ||
| 509 | if (before_eq(seq, hard_ack)) { | ||
| 510 | ack = RXRPC_ACK_DUPLICATE; | ||
| 511 | ack_serial = serial; | ||
| 512 | goto skip; | ||
| 513 | } | ||
| 514 | 508 | ||
| 515 | if (flags & RXRPC_REQUEST_ACK && !ack) { | 509 | flags = 0; |
| 516 | ack = RXRPC_ACK_REQUESTED; | 510 | if (last) |
| 517 | ack_serial = serial; | 511 | flags |= RXRPC_LAST_PACKET; |
| 518 | } | 512 | if (!terminal) |
| 513 | flags |= RXRPC_JUMBO_PACKET; | ||
| 514 | if (test_bit(j, sp->rx_req_ack)) | ||
| 515 | flags |= RXRPC_REQUEST_ACK; | ||
| 516 | trace_rxrpc_rx_data(call->debug_id, seq, serial, flags, annotation); | ||
| 519 | 517 | ||
| 520 | if (call->rxtx_buffer[ix]) { | 518 | if (before_eq(seq, hard_ack)) { |
| 521 | rxrpc_input_dup_data(call, seq, annotation, &jumbo_bad); | ||
| 522 | if (ack != RXRPC_ACK_DUPLICATE) { | ||
| 523 | ack = RXRPC_ACK_DUPLICATE; | 519 | ack = RXRPC_ACK_DUPLICATE; |
| 524 | ack_serial = serial; | 520 | ack_serial = serial; |
| 521 | continue; | ||
| 525 | } | 522 | } |
| 526 | immediate_ack = true; | ||
| 527 | goto skip; | ||
| 528 | } | ||
| 529 | |||
| 530 | /* Queue the packet. We use a couple of memory barriers here as need | ||
| 531 | * to make sure that rx_top is perceived to be set after the buffer | ||
| 532 | * pointer and that the buffer pointer is set after the annotation and | ||
| 533 | * the skb data. | ||
| 534 | * | ||
| 535 | * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window() | ||
| 536 | * and also rxrpc_fill_out_ack(). | ||
| 537 | */ | ||
| 538 | rxrpc_get_skb(skb, rxrpc_skb_rx_got); | ||
| 539 | call->rxtx_annotations[ix] = annotation; | ||
| 540 | smp_wmb(); | ||
| 541 | call->rxtx_buffer[ix] = skb; | ||
| 542 | if (after(seq, call->rx_top)) { | ||
| 543 | smp_store_release(&call->rx_top, seq); | ||
| 544 | } else if (before(seq, call->rx_top)) { | ||
| 545 | /* Send an immediate ACK if we fill in a hole */ | ||
| 546 | if (!ack) { | ||
| 547 | ack = RXRPC_ACK_DELAY; | ||
| 548 | ack_serial = serial; | ||
| 549 | } | ||
| 550 | immediate_ack = true; | ||
| 551 | } | ||
| 552 | if (flags & RXRPC_LAST_PACKET) { | ||
| 553 | set_bit(RXRPC_CALL_RX_LAST, &call->flags); | ||
| 554 | trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq); | ||
| 555 | } else { | ||
| 556 | trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq); | ||
| 557 | } | ||
| 558 | queued = true; | ||
| 559 | 523 | ||
| 560 | if (after_eq(seq, call->rx_expect_next)) { | 524 | if (call->rxtx_buffer[ix]) { |
| 561 | if (after(seq, call->rx_expect_next)) { | 525 | rxrpc_input_dup_data(call, seq, sp->nr_subpackets > 1, |
| 562 | _net("OOS %u > %u", seq, call->rx_expect_next); | 526 | &jumbo_bad); |
| 563 | ack = RXRPC_ACK_OUT_OF_SEQUENCE; | 527 | if (ack != RXRPC_ACK_DUPLICATE) { |
| 564 | ack_serial = serial; | 528 | ack = RXRPC_ACK_DUPLICATE; |
| 529 | ack_serial = serial; | ||
| 530 | } | ||
| 531 | immediate_ack = true; | ||
| 532 | continue; | ||
| 565 | } | 533 | } |
| 566 | call->rx_expect_next = seq + 1; | ||
| 567 | } | ||
| 568 | 534 | ||
| 569 | skip: | ||
| 570 | offset += len; | ||
| 571 | if (flags & RXRPC_JUMBO_PACKET) { | ||
| 572 | if (skb_copy_bits(skb, offset, &flags, 1) < 0) { | ||
| 573 | rxrpc_proto_abort("XJF", call, seq); | ||
| 574 | goto unlock; | ||
| 575 | } | ||
| 576 | offset += sizeof(struct rxrpc_jumbo_header); | ||
| 577 | seq++; | ||
| 578 | serial++; | ||
| 579 | annotation++; | ||
| 580 | if (flags & RXRPC_JUMBO_PACKET) | ||
| 581 | annotation |= RXRPC_RX_ANNO_JLAST; | ||
| 582 | if (after(seq, hard_ack + call->rx_winsize)) { | 535 | if (after(seq, hard_ack + call->rx_winsize)) { |
| 583 | ack = RXRPC_ACK_EXCEEDS_WINDOW; | 536 | ack = RXRPC_ACK_EXCEEDS_WINDOW; |
| 584 | ack_serial = serial; | 537 | ack_serial = serial; |
| 585 | if (!jumbo_bad) { | 538 | if (flags & RXRPC_JUMBO_PACKET) { |
| 586 | call->nr_jumbo_bad++; | 539 | if (!jumbo_bad) { |
| 587 | jumbo_bad = true; | 540 | call->nr_jumbo_bad++; |
| 541 | jumbo_bad = true; | ||
| 542 | } | ||
| 588 | } | 543 | } |
| 544 | |||
| 589 | goto ack; | 545 | goto ack; |
| 590 | } | 546 | } |
| 591 | 547 | ||
| 592 | _proto("Rx DATA Jumbo %%%u", serial); | 548 | if (flags & RXRPC_REQUEST_ACK && !ack) { |
| 593 | goto next_subpacket; | 549 | ack = RXRPC_ACK_REQUESTED; |
| 594 | } | 550 | ack_serial = serial; |
| 551 | } | ||
| 552 | |||
| 553 | /* Queue the packet. We use a couple of memory barriers here as need | ||
| 554 | * to make sure that rx_top is perceived to be set after the buffer | ||
| 555 | * pointer and that the buffer pointer is set after the annotation and | ||
| 556 | * the skb data. | ||
| 557 | * | ||
| 558 | * Barriers against rxrpc_recvmsg_data() and rxrpc_rotate_rx_window() | ||
| 559 | * and also rxrpc_fill_out_ack(). | ||
| 560 | */ | ||
| 561 | if (!terminal) | ||
| 562 | rxrpc_get_skb(skb, rxrpc_skb_got); | ||
| 563 | call->rxtx_annotations[ix] = annotation; | ||
| 564 | smp_wmb(); | ||
| 565 | call->rxtx_buffer[ix] = skb; | ||
| 566 | if (after(seq, call->rx_top)) { | ||
| 567 | smp_store_release(&call->rx_top, seq); | ||
| 568 | } else if (before(seq, call->rx_top)) { | ||
| 569 | /* Send an immediate ACK if we fill in a hole */ | ||
| 570 | if (!ack) { | ||
| 571 | ack = RXRPC_ACK_DELAY; | ||
| 572 | ack_serial = serial; | ||
| 573 | } | ||
| 574 | immediate_ack = true; | ||
| 575 | } | ||
| 595 | 576 | ||
| 596 | if (queued && flags & RXRPC_LAST_PACKET && !ack) { | 577 | if (terminal) { |
| 597 | ack = RXRPC_ACK_DELAY; | 578 | /* From this point on, we're not allowed to touch the |
| 598 | ack_serial = serial; | 579 | * packet any longer as its ref now belongs to the Rx |
| 580 | * ring. | ||
| 581 | */ | ||
| 582 | skb = NULL; | ||
| 583 | } | ||
| 584 | |||
| 585 | if (last) { | ||
| 586 | set_bit(RXRPC_CALL_RX_LAST, &call->flags); | ||
| 587 | if (!ack) { | ||
| 588 | ack = RXRPC_ACK_DELAY; | ||
| 589 | ack_serial = serial; | ||
| 590 | } | ||
| 591 | trace_rxrpc_receive(call, rxrpc_receive_queue_last, serial, seq); | ||
| 592 | } else { | ||
| 593 | trace_rxrpc_receive(call, rxrpc_receive_queue, serial, seq); | ||
| 594 | } | ||
| 595 | |||
| 596 | if (after_eq(seq, call->rx_expect_next)) { | ||
| 597 | if (after(seq, call->rx_expect_next)) { | ||
| 598 | _net("OOS %u > %u", seq, call->rx_expect_next); | ||
| 599 | ack = RXRPC_ACK_OUT_OF_SEQUENCE; | ||
| 600 | ack_serial = serial; | ||
| 601 | } | ||
| 602 | call->rx_expect_next = seq + 1; | ||
| 603 | } | ||
| 599 | } | 604 | } |
| 600 | 605 | ||
| 601 | ack: | 606 | ack: |
| 602 | if (ack) | 607 | if (ack) |
| 603 | rxrpc_propose_ACK(call, ack, skew, ack_serial, | 608 | rxrpc_propose_ACK(call, ack, ack_serial, |
| 604 | immediate_ack, true, | 609 | immediate_ack, true, |
| 605 | rxrpc_propose_ack_input_data); | 610 | rxrpc_propose_ack_input_data); |
| 606 | else | 611 | else |
| 607 | rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, skew, serial, | 612 | rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, |
| 608 | false, true, | 613 | false, true, |
| 609 | rxrpc_propose_ack_input_data); | 614 | rxrpc_propose_ack_input_data); |
| 610 | 615 | ||
| 611 | if (sp->hdr.seq == READ_ONCE(call->rx_hard_ack) + 1) { | 616 | if (seq0 == READ_ONCE(call->rx_hard_ack) + 1) { |
| 612 | trace_rxrpc_notify_socket(call->debug_id, serial); | 617 | trace_rxrpc_notify_socket(call->debug_id, serial); |
| 613 | rxrpc_notify_socket(call); | 618 | rxrpc_notify_socket(call); |
| 614 | } | 619 | } |
| 615 | 620 | ||
| 616 | unlock: | 621 | unlock: |
| 617 | spin_unlock(&call->input_lock); | 622 | spin_unlock(&call->input_lock); |
| 623 | rxrpc_free_skb(skb, rxrpc_skb_freed); | ||
| 618 | _leave(" [queued]"); | 624 | _leave(" [queued]"); |
| 619 | } | 625 | } |
| 620 | 626 | ||
| @@ -822,8 +828,7 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call, u8 *acks, | |||
| 822 | * soft-ACK means that the packet may be discarded and retransmission | 828 | * soft-ACK means that the packet may be discarded and retransmission |
| 823 | * requested. A phase is complete when all packets are hard-ACK'd. | 829 | * requested. A phase is complete when all packets are hard-ACK'd. |
| 824 | */ | 830 | */ |
| 825 | static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb, | 831 | static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb) |
| 826 | u16 skew) | ||
| 827 | { | 832 | { |
| 828 | struct rxrpc_ack_summary summary = { 0 }; | 833 | struct rxrpc_ack_summary summary = { 0 }; |
| 829 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 834 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| @@ -867,11 +872,11 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 867 | if (buf.ack.reason == RXRPC_ACK_PING) { | 872 | if (buf.ack.reason == RXRPC_ACK_PING) { |
| 868 | _proto("Rx ACK %%%u PING Request", sp->hdr.serial); | 873 | _proto("Rx ACK %%%u PING Request", sp->hdr.serial); |
| 869 | rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE, | 874 | rxrpc_propose_ACK(call, RXRPC_ACK_PING_RESPONSE, |
| 870 | skew, sp->hdr.serial, true, true, | 875 | sp->hdr.serial, true, true, |
| 871 | rxrpc_propose_ack_respond_to_ping); | 876 | rxrpc_propose_ack_respond_to_ping); |
| 872 | } else if (sp->hdr.flags & RXRPC_REQUEST_ACK) { | 877 | } else if (sp->hdr.flags & RXRPC_REQUEST_ACK) { |
| 873 | rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED, | 878 | rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED, |
| 874 | skew, sp->hdr.serial, true, true, | 879 | sp->hdr.serial, true, true, |
| 875 | rxrpc_propose_ack_respond_to_ack); | 880 | rxrpc_propose_ack_respond_to_ack); |
| 876 | } | 881 | } |
| 877 | 882 | ||
| @@ -948,7 +953,7 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 948 | RXRPC_TX_ANNO_LAST && | 953 | RXRPC_TX_ANNO_LAST && |
| 949 | summary.nr_acks == call->tx_top - hard_ack && | 954 | summary.nr_acks == call->tx_top - hard_ack && |
| 950 | rxrpc_is_client_call(call)) | 955 | rxrpc_is_client_call(call)) |
| 951 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, skew, sp->hdr.serial, | 956 | rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial, |
| 952 | false, true, | 957 | false, true, |
| 953 | rxrpc_propose_ack_ping_for_lost_reply); | 958 | rxrpc_propose_ack_ping_for_lost_reply); |
| 954 | 959 | ||
| @@ -1004,7 +1009,7 @@ static void rxrpc_input_abort(struct rxrpc_call *call, struct sk_buff *skb) | |||
| 1004 | * Process an incoming call packet. | 1009 | * Process an incoming call packet. |
| 1005 | */ | 1010 | */ |
| 1006 | static void rxrpc_input_call_packet(struct rxrpc_call *call, | 1011 | static void rxrpc_input_call_packet(struct rxrpc_call *call, |
| 1007 | struct sk_buff *skb, u16 skew) | 1012 | struct sk_buff *skb) |
| 1008 | { | 1013 | { |
| 1009 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 1014 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 1010 | unsigned long timo; | 1015 | unsigned long timo; |
| @@ -1023,11 +1028,11 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call, | |||
| 1023 | 1028 | ||
| 1024 | switch (sp->hdr.type) { | 1029 | switch (sp->hdr.type) { |
| 1025 | case RXRPC_PACKET_TYPE_DATA: | 1030 | case RXRPC_PACKET_TYPE_DATA: |
| 1026 | rxrpc_input_data(call, skb, skew); | 1031 | rxrpc_input_data(call, skb); |
| 1027 | break; | 1032 | goto no_free; |
| 1028 | 1033 | ||
| 1029 | case RXRPC_PACKET_TYPE_ACK: | 1034 | case RXRPC_PACKET_TYPE_ACK: |
| 1030 | rxrpc_input_ack(call, skb, skew); | 1035 | rxrpc_input_ack(call, skb); |
| 1031 | break; | 1036 | break; |
| 1032 | 1037 | ||
| 1033 | case RXRPC_PACKET_TYPE_BUSY: | 1038 | case RXRPC_PACKET_TYPE_BUSY: |
| @@ -1051,6 +1056,8 @@ static void rxrpc_input_call_packet(struct rxrpc_call *call, | |||
| 1051 | break; | 1056 | break; |
| 1052 | } | 1057 | } |
| 1053 | 1058 | ||
| 1059 | rxrpc_free_skb(skb, rxrpc_skb_freed); | ||
| 1060 | no_free: | ||
| 1054 | _leave(""); | 1061 | _leave(""); |
| 1055 | } | 1062 | } |
| 1056 | 1063 | ||
| @@ -1108,8 +1115,12 @@ static void rxrpc_post_packet_to_local(struct rxrpc_local *local, | |||
| 1108 | { | 1115 | { |
| 1109 | _enter("%p,%p", local, skb); | 1116 | _enter("%p,%p", local, skb); |
| 1110 | 1117 | ||
| 1111 | skb_queue_tail(&local->event_queue, skb); | 1118 | if (rxrpc_get_local_maybe(local)) { |
| 1112 | rxrpc_queue_local(local); | 1119 | skb_queue_tail(&local->event_queue, skb); |
| 1120 | rxrpc_queue_local(local); | ||
| 1121 | } else { | ||
| 1122 | rxrpc_free_skb(skb, rxrpc_skb_freed); | ||
| 1123 | } | ||
| 1113 | } | 1124 | } |
| 1114 | 1125 | ||
| 1115 | /* | 1126 | /* |
| @@ -1119,8 +1130,12 @@ static void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb) | |||
| 1119 | { | 1130 | { |
| 1120 | CHECK_SLAB_OKAY(&local->usage); | 1131 | CHECK_SLAB_OKAY(&local->usage); |
| 1121 | 1132 | ||
| 1122 | skb_queue_tail(&local->reject_queue, skb); | 1133 | if (rxrpc_get_local_maybe(local)) { |
| 1123 | rxrpc_queue_local(local); | 1134 | skb_queue_tail(&local->reject_queue, skb); |
| 1135 | rxrpc_queue_local(local); | ||
| 1136 | } else { | ||
| 1137 | rxrpc_free_skb(skb, rxrpc_skb_freed); | ||
| 1138 | } | ||
| 1124 | } | 1139 | } |
| 1125 | 1140 | ||
| 1126 | /* | 1141 | /* |
| @@ -1173,7 +1188,6 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) | |||
| 1173 | struct rxrpc_peer *peer = NULL; | 1188 | struct rxrpc_peer *peer = NULL; |
| 1174 | struct rxrpc_sock *rx = NULL; | 1189 | struct rxrpc_sock *rx = NULL; |
| 1175 | unsigned int channel; | 1190 | unsigned int channel; |
| 1176 | int skew = 0; | ||
| 1177 | 1191 | ||
| 1178 | _enter("%p", udp_sk); | 1192 | _enter("%p", udp_sk); |
| 1179 | 1193 | ||
| @@ -1184,7 +1198,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) | |||
| 1184 | if (skb->tstamp == 0) | 1198 | if (skb->tstamp == 0) |
| 1185 | skb->tstamp = ktime_get_real(); | 1199 | skb->tstamp = ktime_get_real(); |
| 1186 | 1200 | ||
| 1187 | rxrpc_new_skb(skb, rxrpc_skb_rx_received); | 1201 | rxrpc_new_skb(skb, rxrpc_skb_received); |
| 1188 | 1202 | ||
| 1189 | skb_pull(skb, sizeof(struct udphdr)); | 1203 | skb_pull(skb, sizeof(struct udphdr)); |
| 1190 | 1204 | ||
| @@ -1201,7 +1215,7 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) | |||
| 1201 | static int lose; | 1215 | static int lose; |
| 1202 | if ((lose++ & 7) == 7) { | 1216 | if ((lose++ & 7) == 7) { |
| 1203 | trace_rxrpc_rx_lose(sp); | 1217 | trace_rxrpc_rx_lose(sp); |
| 1204 | rxrpc_free_skb(skb, rxrpc_skb_rx_lost); | 1218 | rxrpc_free_skb(skb, rxrpc_skb_lost); |
| 1205 | return 0; | 1219 | return 0; |
| 1206 | } | 1220 | } |
| 1207 | } | 1221 | } |
| @@ -1233,9 +1247,26 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) | |||
| 1233 | if (sp->hdr.callNumber == 0 || | 1247 | if (sp->hdr.callNumber == 0 || |
| 1234 | sp->hdr.seq == 0) | 1248 | sp->hdr.seq == 0) |
| 1235 | goto bad_message; | 1249 | goto bad_message; |
| 1236 | if (sp->hdr.flags & RXRPC_JUMBO_PACKET && | 1250 | if (!rxrpc_validate_data(skb)) |
| 1237 | !rxrpc_validate_jumbo(skb)) | ||
| 1238 | goto bad_message; | 1251 | goto bad_message; |
| 1252 | |||
| 1253 | /* Unshare the packet so that it can be modified for in-place | ||
| 1254 | * decryption. | ||
| 1255 | */ | ||
| 1256 | if (sp->hdr.securityIndex != 0) { | ||
| 1257 | struct sk_buff *nskb = skb_unshare(skb, GFP_ATOMIC); | ||
| 1258 | if (!nskb) { | ||
| 1259 | rxrpc_eaten_skb(skb, rxrpc_skb_unshared_nomem); | ||
| 1260 | goto out; | ||
| 1261 | } | ||
| 1262 | |||
| 1263 | if (nskb != skb) { | ||
| 1264 | rxrpc_eaten_skb(skb, rxrpc_skb_received); | ||
| 1265 | rxrpc_new_skb(skb, rxrpc_skb_unshared); | ||
| 1266 | skb = nskb; | ||
| 1267 | sp = rxrpc_skb(skb); | ||
| 1268 | } | ||
| 1269 | } | ||
| 1239 | break; | 1270 | break; |
| 1240 | 1271 | ||
| 1241 | case RXRPC_PACKET_TYPE_CHALLENGE: | 1272 | case RXRPC_PACKET_TYPE_CHALLENGE: |
| @@ -1301,15 +1332,8 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) | |||
| 1301 | goto out; | 1332 | goto out; |
| 1302 | } | 1333 | } |
| 1303 | 1334 | ||
| 1304 | /* Note the serial number skew here */ | 1335 | if ((int)sp->hdr.serial - (int)conn->hi_serial > 0) |
| 1305 | skew = (int)sp->hdr.serial - (int)conn->hi_serial; | 1336 | conn->hi_serial = sp->hdr.serial; |
| 1306 | if (skew >= 0) { | ||
| 1307 | if (skew > 0) | ||
| 1308 | conn->hi_serial = sp->hdr.serial; | ||
| 1309 | } else { | ||
| 1310 | skew = -skew; | ||
| 1311 | skew = min(skew, 65535); | ||
| 1312 | } | ||
| 1313 | 1337 | ||
| 1314 | /* Call-bound packets are routed by connection channel. */ | 1338 | /* Call-bound packets are routed by connection channel. */ |
| 1315 | channel = sp->hdr.cid & RXRPC_CHANNELMASK; | 1339 | channel = sp->hdr.cid & RXRPC_CHANNELMASK; |
| @@ -1372,15 +1396,18 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb) | |||
| 1372 | call = rxrpc_new_incoming_call(local, rx, skb); | 1396 | call = rxrpc_new_incoming_call(local, rx, skb); |
| 1373 | if (!call) | 1397 | if (!call) |
| 1374 | goto reject_packet; | 1398 | goto reject_packet; |
| 1375 | rxrpc_send_ping(call, skb, skew); | 1399 | rxrpc_send_ping(call, skb); |
| 1376 | mutex_unlock(&call->user_mutex); | 1400 | mutex_unlock(&call->user_mutex); |
| 1377 | } | 1401 | } |
| 1378 | 1402 | ||
| 1379 | rxrpc_input_call_packet(call, skb, skew); | 1403 | /* Process a call packet; this either discards or passes on the ref |
| 1380 | goto discard; | 1404 | * elsewhere. |
| 1405 | */ | ||
| 1406 | rxrpc_input_call_packet(call, skb); | ||
| 1407 | goto out; | ||
| 1381 | 1408 | ||
| 1382 | discard: | 1409 | discard: |
| 1383 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 1410 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 1384 | out: | 1411 | out: |
| 1385 | trace_rxrpc_rx_done(0, 0); | 1412 | trace_rxrpc_rx_done(0, 0); |
| 1386 | return 0; | 1413 | return 0; |
diff --git a/net/rxrpc/local_event.c b/net/rxrpc/local_event.c index e93a78f7c05e..3ce6d628cd75 100644 --- a/net/rxrpc/local_event.c +++ b/net/rxrpc/local_event.c | |||
| @@ -90,7 +90,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local) | |||
| 90 | if (skb) { | 90 | if (skb) { |
| 91 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 91 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 92 | 92 | ||
| 93 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); | 93 | rxrpc_see_skb(skb, rxrpc_skb_seen); |
| 94 | _debug("{%d},{%u}", local->debug_id, sp->hdr.type); | 94 | _debug("{%d},{%u}", local->debug_id, sp->hdr.type); |
| 95 | 95 | ||
| 96 | switch (sp->hdr.type) { | 96 | switch (sp->hdr.type) { |
| @@ -108,7 +108,7 @@ void rxrpc_process_local_events(struct rxrpc_local *local) | |||
| 108 | break; | 108 | break; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 111 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | _leave(""); | 114 | _leave(""); |
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c index b1c71bad510b..36587260cabd 100644 --- a/net/rxrpc/local_object.c +++ b/net/rxrpc/local_object.c | |||
| @@ -79,6 +79,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet, | |||
| 79 | local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL); | 79 | local = kzalloc(sizeof(struct rxrpc_local), GFP_KERNEL); |
| 80 | if (local) { | 80 | if (local) { |
| 81 | atomic_set(&local->usage, 1); | 81 | atomic_set(&local->usage, 1); |
| 82 | atomic_set(&local->active_users, 1); | ||
| 82 | local->rxnet = rxnet; | 83 | local->rxnet = rxnet; |
| 83 | INIT_LIST_HEAD(&local->link); | 84 | INIT_LIST_HEAD(&local->link); |
| 84 | INIT_WORK(&local->processor, rxrpc_local_processor); | 85 | INIT_WORK(&local->processor, rxrpc_local_processor); |
| @@ -92,7 +93,7 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet, | |||
| 92 | local->debug_id = atomic_inc_return(&rxrpc_debug_id); | 93 | local->debug_id = atomic_inc_return(&rxrpc_debug_id); |
| 93 | memcpy(&local->srx, srx, sizeof(*srx)); | 94 | memcpy(&local->srx, srx, sizeof(*srx)); |
| 94 | local->srx.srx_service = 0; | 95 | local->srx.srx_service = 0; |
| 95 | trace_rxrpc_local(local, rxrpc_local_new, 1, NULL); | 96 | trace_rxrpc_local(local->debug_id, rxrpc_local_new, 1, NULL); |
| 96 | } | 97 | } |
| 97 | 98 | ||
| 98 | _leave(" = %p", local); | 99 | _leave(" = %p", local); |
| @@ -266,11 +267,8 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, | |||
| 266 | * bind the transport socket may still fail if we're attempting | 267 | * bind the transport socket may still fail if we're attempting |
| 267 | * to use a local address that the dying object is still using. | 268 | * to use a local address that the dying object is still using. |
| 268 | */ | 269 | */ |
| 269 | if (!rxrpc_get_local_maybe(local)) { | 270 | if (!rxrpc_use_local(local)) |
| 270 | cursor = cursor->next; | ||
| 271 | list_del_init(&local->link); | ||
| 272 | break; | 271 | break; |
| 273 | } | ||
| 274 | 272 | ||
| 275 | age = "old"; | 273 | age = "old"; |
| 276 | goto found; | 274 | goto found; |
| @@ -284,7 +282,10 @@ struct rxrpc_local *rxrpc_lookup_local(struct net *net, | |||
| 284 | if (ret < 0) | 282 | if (ret < 0) |
| 285 | goto sock_error; | 283 | goto sock_error; |
| 286 | 284 | ||
| 287 | list_add_tail(&local->link, cursor); | 285 | if (cursor != &rxnet->local_endpoints) |
| 286 | list_replace_init(cursor, &local->link); | ||
| 287 | else | ||
| 288 | list_add_tail(&local->link, cursor); | ||
| 288 | age = "new"; | 289 | age = "new"; |
| 289 | 290 | ||
| 290 | found: | 291 | found: |
| @@ -320,7 +321,7 @@ struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local) | |||
| 320 | int n; | 321 | int n; |
| 321 | 322 | ||
| 322 | n = atomic_inc_return(&local->usage); | 323 | n = atomic_inc_return(&local->usage); |
| 323 | trace_rxrpc_local(local, rxrpc_local_got, n, here); | 324 | trace_rxrpc_local(local->debug_id, rxrpc_local_got, n, here); |
| 324 | return local; | 325 | return local; |
| 325 | } | 326 | } |
| 326 | 327 | ||
| @@ -334,7 +335,8 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local) | |||
| 334 | if (local) { | 335 | if (local) { |
| 335 | int n = atomic_fetch_add_unless(&local->usage, 1, 0); | 336 | int n = atomic_fetch_add_unless(&local->usage, 1, 0); |
| 336 | if (n > 0) | 337 | if (n > 0) |
| 337 | trace_rxrpc_local(local, rxrpc_local_got, n + 1, here); | 338 | trace_rxrpc_local(local->debug_id, rxrpc_local_got, |
| 339 | n + 1, here); | ||
| 338 | else | 340 | else |
| 339 | local = NULL; | 341 | local = NULL; |
| 340 | } | 342 | } |
| @@ -342,24 +344,18 @@ struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local) | |||
| 342 | } | 344 | } |
| 343 | 345 | ||
| 344 | /* | 346 | /* |
| 345 | * Queue a local endpoint. | 347 | * Queue a local endpoint and pass the caller's reference to the work item. |
| 346 | */ | 348 | */ |
| 347 | void rxrpc_queue_local(struct rxrpc_local *local) | 349 | void rxrpc_queue_local(struct rxrpc_local *local) |
| 348 | { | 350 | { |
| 349 | const void *here = __builtin_return_address(0); | 351 | const void *here = __builtin_return_address(0); |
| 352 | unsigned int debug_id = local->debug_id; | ||
| 353 | int n = atomic_read(&local->usage); | ||
| 350 | 354 | ||
| 351 | if (rxrpc_queue_work(&local->processor)) | 355 | if (rxrpc_queue_work(&local->processor)) |
| 352 | trace_rxrpc_local(local, rxrpc_local_queued, | 356 | trace_rxrpc_local(debug_id, rxrpc_local_queued, n, here); |
| 353 | atomic_read(&local->usage), here); | 357 | else |
| 354 | } | 358 | rxrpc_put_local(local); |
| 355 | |||
| 356 | /* | ||
| 357 | * A local endpoint reached its end of life. | ||
| 358 | */ | ||
| 359 | static void __rxrpc_put_local(struct rxrpc_local *local) | ||
| 360 | { | ||
| 361 | _enter("%d", local->debug_id); | ||
| 362 | rxrpc_queue_work(&local->processor); | ||
| 363 | } | 359 | } |
| 364 | 360 | ||
| 365 | /* | 361 | /* |
| @@ -372,10 +368,47 @@ void rxrpc_put_local(struct rxrpc_local *local) | |||
| 372 | 368 | ||
| 373 | if (local) { | 369 | if (local) { |
| 374 | n = atomic_dec_return(&local->usage); | 370 | n = atomic_dec_return(&local->usage); |
| 375 | trace_rxrpc_local(local, rxrpc_local_put, n, here); | 371 | trace_rxrpc_local(local->debug_id, rxrpc_local_put, n, here); |
| 376 | 372 | ||
| 377 | if (n == 0) | 373 | if (n == 0) |
| 378 | __rxrpc_put_local(local); | 374 | call_rcu(&local->rcu, rxrpc_local_rcu); |
| 375 | } | ||
| 376 | } | ||
| 377 | |||
| 378 | /* | ||
| 379 | * Start using a local endpoint. | ||
| 380 | */ | ||
| 381 | struct rxrpc_local *rxrpc_use_local(struct rxrpc_local *local) | ||
| 382 | { | ||
| 383 | unsigned int au; | ||
| 384 | |||
| 385 | local = rxrpc_get_local_maybe(local); | ||
| 386 | if (!local) | ||
| 387 | return NULL; | ||
| 388 | |||
| 389 | au = atomic_fetch_add_unless(&local->active_users, 1, 0); | ||
| 390 | if (au == 0) { | ||
| 391 | rxrpc_put_local(local); | ||
| 392 | return NULL; | ||
| 393 | } | ||
| 394 | |||
| 395 | return local; | ||
| 396 | } | ||
| 397 | |||
| 398 | /* | ||
| 399 | * Cease using a local endpoint. Once the number of active users reaches 0, we | ||
| 400 | * start the closure of the transport in the work processor. | ||
| 401 | */ | ||
| 402 | void rxrpc_unuse_local(struct rxrpc_local *local) | ||
| 403 | { | ||
| 404 | unsigned int au; | ||
| 405 | |||
| 406 | if (local) { | ||
| 407 | au = atomic_dec_return(&local->active_users); | ||
| 408 | if (au == 0) | ||
| 409 | rxrpc_queue_local(local); | ||
| 410 | else | ||
| 411 | rxrpc_put_local(local); | ||
| 379 | } | 412 | } |
| 380 | } | 413 | } |
| 381 | 414 | ||
| @@ -393,21 +426,14 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local) | |||
| 393 | 426 | ||
| 394 | _enter("%d", local->debug_id); | 427 | _enter("%d", local->debug_id); |
| 395 | 428 | ||
| 396 | /* We can get a race between an incoming call packet queueing the | ||
| 397 | * processor again and the work processor starting the destruction | ||
| 398 | * process which will shut down the UDP socket. | ||
| 399 | */ | ||
| 400 | if (local->dead) { | ||
| 401 | _leave(" [already dead]"); | ||
| 402 | return; | ||
| 403 | } | ||
| 404 | local->dead = true; | 429 | local->dead = true; |
| 405 | 430 | ||
| 406 | mutex_lock(&rxnet->local_mutex); | 431 | mutex_lock(&rxnet->local_mutex); |
| 407 | list_del_init(&local->link); | 432 | list_del_init(&local->link); |
| 408 | mutex_unlock(&rxnet->local_mutex); | 433 | mutex_unlock(&rxnet->local_mutex); |
| 409 | 434 | ||
| 410 | ASSERT(RB_EMPTY_ROOT(&local->client_conns)); | 435 | rxrpc_clean_up_local_conns(local); |
| 436 | rxrpc_service_connection_reaper(&rxnet->service_conn_reaper); | ||
| 411 | ASSERT(!local->service); | 437 | ASSERT(!local->service); |
| 412 | 438 | ||
| 413 | if (socket) { | 439 | if (socket) { |
| @@ -422,13 +448,11 @@ static void rxrpc_local_destroyer(struct rxrpc_local *local) | |||
| 422 | */ | 448 | */ |
| 423 | rxrpc_purge_queue(&local->reject_queue); | 449 | rxrpc_purge_queue(&local->reject_queue); |
| 424 | rxrpc_purge_queue(&local->event_queue); | 450 | rxrpc_purge_queue(&local->event_queue); |
| 425 | |||
| 426 | _debug("rcu local %d", local->debug_id); | ||
| 427 | call_rcu(&local->rcu, rxrpc_local_rcu); | ||
| 428 | } | 451 | } |
| 429 | 452 | ||
| 430 | /* | 453 | /* |
| 431 | * Process events on an endpoint | 454 | * Process events on an endpoint. The work item carries a ref which |
| 455 | * we must release. | ||
| 432 | */ | 456 | */ |
| 433 | static void rxrpc_local_processor(struct work_struct *work) | 457 | static void rxrpc_local_processor(struct work_struct *work) |
| 434 | { | 458 | { |
| @@ -436,13 +460,15 @@ static void rxrpc_local_processor(struct work_struct *work) | |||
| 436 | container_of(work, struct rxrpc_local, processor); | 460 | container_of(work, struct rxrpc_local, processor); |
| 437 | bool again; | 461 | bool again; |
| 438 | 462 | ||
| 439 | trace_rxrpc_local(local, rxrpc_local_processing, | 463 | trace_rxrpc_local(local->debug_id, rxrpc_local_processing, |
| 440 | atomic_read(&local->usage), NULL); | 464 | atomic_read(&local->usage), NULL); |
| 441 | 465 | ||
| 442 | do { | 466 | do { |
| 443 | again = false; | 467 | again = false; |
| 444 | if (atomic_read(&local->usage) == 0) | 468 | if (atomic_read(&local->active_users) == 0) { |
| 445 | return rxrpc_local_destroyer(local); | 469 | rxrpc_local_destroyer(local); |
| 470 | break; | ||
| 471 | } | ||
| 446 | 472 | ||
| 447 | if (!skb_queue_empty(&local->reject_queue)) { | 473 | if (!skb_queue_empty(&local->reject_queue)) { |
| 448 | rxrpc_reject_packets(local); | 474 | rxrpc_reject_packets(local); |
| @@ -454,6 +480,8 @@ static void rxrpc_local_processor(struct work_struct *work) | |||
| 454 | again = true; | 480 | again = true; |
| 455 | } | 481 | } |
| 456 | } while (again); | 482 | } while (again); |
| 483 | |||
| 484 | rxrpc_put_local(local); | ||
| 457 | } | 485 | } |
| 458 | 486 | ||
| 459 | /* | 487 | /* |
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c index 948e3fe249ec..935bb60fff56 100644 --- a/net/rxrpc/output.c +++ b/net/rxrpc/output.c | |||
| @@ -87,7 +87,7 @@ static size_t rxrpc_fill_out_ack(struct rxrpc_connection *conn, | |||
| 87 | *_top = top; | 87 | *_top = top; |
| 88 | 88 | ||
| 89 | pkt->ack.bufferSpace = htons(8); | 89 | pkt->ack.bufferSpace = htons(8); |
| 90 | pkt->ack.maxSkew = htons(call->ackr_skew); | 90 | pkt->ack.maxSkew = htons(0); |
| 91 | pkt->ack.firstPacket = htonl(hard_ack + 1); | 91 | pkt->ack.firstPacket = htonl(hard_ack + 1); |
| 92 | pkt->ack.previousPacket = htonl(call->ackr_prev_seq); | 92 | pkt->ack.previousPacket = htonl(call->ackr_prev_seq); |
| 93 | pkt->ack.serial = htonl(serial); | 93 | pkt->ack.serial = htonl(serial); |
| @@ -228,7 +228,6 @@ int rxrpc_send_ack_packet(struct rxrpc_call *call, bool ping, | |||
| 228 | if (ping) | 228 | if (ping) |
| 229 | clear_bit(RXRPC_CALL_PINGING, &call->flags); | 229 | clear_bit(RXRPC_CALL_PINGING, &call->flags); |
| 230 | rxrpc_propose_ACK(call, pkt->ack.reason, | 230 | rxrpc_propose_ACK(call, pkt->ack.reason, |
| 231 | ntohs(pkt->ack.maxSkew), | ||
| 232 | ntohl(pkt->ack.serial), | 231 | ntohl(pkt->ack.serial), |
| 233 | false, true, | 232 | false, true, |
| 234 | rxrpc_propose_ack_retry_tx); | 233 | rxrpc_propose_ack_retry_tx); |
| @@ -566,7 +565,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local) | |||
| 566 | memset(&whdr, 0, sizeof(whdr)); | 565 | memset(&whdr, 0, sizeof(whdr)); |
| 567 | 566 | ||
| 568 | while ((skb = skb_dequeue(&local->reject_queue))) { | 567 | while ((skb = skb_dequeue(&local->reject_queue))) { |
| 569 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); | 568 | rxrpc_see_skb(skb, rxrpc_skb_seen); |
| 570 | sp = rxrpc_skb(skb); | 569 | sp = rxrpc_skb(skb); |
| 571 | 570 | ||
| 572 | switch (skb->mark) { | 571 | switch (skb->mark) { |
| @@ -582,7 +581,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local) | |||
| 582 | ioc = 2; | 581 | ioc = 2; |
| 583 | break; | 582 | break; |
| 584 | default: | 583 | default: |
| 585 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 584 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 586 | continue; | 585 | continue; |
| 587 | } | 586 | } |
| 588 | 587 | ||
| @@ -607,7 +606,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local) | |||
| 607 | rxrpc_tx_point_reject); | 606 | rxrpc_tx_point_reject); |
| 608 | } | 607 | } |
| 609 | 608 | ||
| 610 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 609 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 611 | } | 610 | } |
| 612 | 611 | ||
| 613 | _leave(""); | 612 | _leave(""); |
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c index 9f2f45c09e58..c97ebdc043e4 100644 --- a/net/rxrpc/peer_event.c +++ b/net/rxrpc/peer_event.c | |||
| @@ -163,11 +163,11 @@ void rxrpc_error_report(struct sock *sk) | |||
| 163 | _leave("UDP socket errqueue empty"); | 163 | _leave("UDP socket errqueue empty"); |
| 164 | return; | 164 | return; |
| 165 | } | 165 | } |
| 166 | rxrpc_new_skb(skb, rxrpc_skb_rx_received); | 166 | rxrpc_new_skb(skb, rxrpc_skb_received); |
| 167 | serr = SKB_EXT_ERR(skb); | 167 | serr = SKB_EXT_ERR(skb); |
| 168 | if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) { | 168 | if (!skb->len && serr->ee.ee_origin == SO_EE_ORIGIN_TIMESTAMPING) { |
| 169 | _leave("UDP empty message"); | 169 | _leave("UDP empty message"); |
| 170 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 170 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 171 | return; | 171 | return; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| @@ -177,7 +177,7 @@ void rxrpc_error_report(struct sock *sk) | |||
| 177 | peer = NULL; | 177 | peer = NULL; |
| 178 | if (!peer) { | 178 | if (!peer) { |
| 179 | rcu_read_unlock(); | 179 | rcu_read_unlock(); |
| 180 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 180 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 181 | _leave(" [no peer]"); | 181 | _leave(" [no peer]"); |
| 182 | return; | 182 | return; |
| 183 | } | 183 | } |
| @@ -189,7 +189,7 @@ void rxrpc_error_report(struct sock *sk) | |||
| 189 | serr->ee.ee_code == ICMP_FRAG_NEEDED)) { | 189 | serr->ee.ee_code == ICMP_FRAG_NEEDED)) { |
| 190 | rxrpc_adjust_mtu(peer, serr); | 190 | rxrpc_adjust_mtu(peer, serr); |
| 191 | rcu_read_unlock(); | 191 | rcu_read_unlock(); |
| 192 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 192 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 193 | rxrpc_put_peer(peer); | 193 | rxrpc_put_peer(peer); |
| 194 | _leave(" [MTU update]"); | 194 | _leave(" [MTU update]"); |
| 195 | return; | 195 | return; |
| @@ -197,7 +197,7 @@ void rxrpc_error_report(struct sock *sk) | |||
| 197 | 197 | ||
| 198 | rxrpc_store_error(peer, serr); | 198 | rxrpc_store_error(peer, serr); |
| 199 | rcu_read_unlock(); | 199 | rcu_read_unlock(); |
| 200 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 200 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 201 | rxrpc_put_peer(peer); | 201 | rxrpc_put_peer(peer); |
| 202 | 202 | ||
| 203 | _leave(""); | 203 | _leave(""); |
| @@ -378,7 +378,7 @@ static void rxrpc_peer_keepalive_dispatch(struct rxrpc_net *rxnet, | |||
| 378 | spin_lock_bh(&rxnet->peer_hash_lock); | 378 | spin_lock_bh(&rxnet->peer_hash_lock); |
| 379 | list_add_tail(&peer->keepalive_link, | 379 | list_add_tail(&peer->keepalive_link, |
| 380 | &rxnet->peer_keepalive[slot & mask]); | 380 | &rxnet->peer_keepalive[slot & mask]); |
| 381 | rxrpc_put_peer(peer); | 381 | rxrpc_put_peer_locked(peer); |
| 382 | } | 382 | } |
| 383 | 383 | ||
| 384 | spin_unlock_bh(&rxnet->peer_hash_lock); | 384 | spin_unlock_bh(&rxnet->peer_hash_lock); |
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c index 9d3ce81cf8ae..9c3ac96f71cb 100644 --- a/net/rxrpc/peer_object.c +++ b/net/rxrpc/peer_object.c | |||
| @@ -437,6 +437,24 @@ void rxrpc_put_peer(struct rxrpc_peer *peer) | |||
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | /* | 439 | /* |
| 440 | * Drop a ref on a peer record where the caller already holds the | ||
| 441 | * peer_hash_lock. | ||
| 442 | */ | ||
| 443 | void rxrpc_put_peer_locked(struct rxrpc_peer *peer) | ||
| 444 | { | ||
| 445 | const void *here = __builtin_return_address(0); | ||
| 446 | int n; | ||
| 447 | |||
| 448 | n = atomic_dec_return(&peer->usage); | ||
| 449 | trace_rxrpc_peer(peer, rxrpc_peer_put, n, here); | ||
| 450 | if (n == 0) { | ||
| 451 | hash_del_rcu(&peer->hash_link); | ||
| 452 | list_del_init(&peer->keepalive_link); | ||
| 453 | kfree_rcu(peer, rcu); | ||
| 454 | } | ||
| 455 | } | ||
| 456 | |||
| 457 | /* | ||
| 440 | * Make sure all peer records have been discarded. | 458 | * Make sure all peer records have been discarded. |
| 441 | */ | 459 | */ |
| 442 | void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet) | 460 | void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet) |
diff --git a/net/rxrpc/protocol.h b/net/rxrpc/protocol.h index 99ce322d7caa..49bb972539aa 100644 --- a/net/rxrpc/protocol.h +++ b/net/rxrpc/protocol.h | |||
| @@ -89,6 +89,15 @@ struct rxrpc_jumbo_header { | |||
| 89 | #define RXRPC_JUMBO_DATALEN 1412 /* non-terminal jumbo packet data length */ | 89 | #define RXRPC_JUMBO_DATALEN 1412 /* non-terminal jumbo packet data length */ |
| 90 | #define RXRPC_JUMBO_SUBPKTLEN (RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header)) | 90 | #define RXRPC_JUMBO_SUBPKTLEN (RXRPC_JUMBO_DATALEN + sizeof(struct rxrpc_jumbo_header)) |
| 91 | 91 | ||
| 92 | /* | ||
| 93 | * The maximum number of subpackets that can possibly fit in a UDP packet is: | ||
| 94 | * | ||
| 95 | * ((max_IP - IP_hdr - UDP_hdr) / RXRPC_JUMBO_SUBPKTLEN) + 1 | ||
| 96 | * = ((65535 - 28 - 28) / 1416) + 1 | ||
| 97 | * = 46 non-terminal packets and 1 terminal packet. | ||
| 98 | */ | ||
| 99 | #define RXRPC_MAX_NR_JUMBO 47 | ||
| 100 | |||
| 92 | /*****************************************************************************/ | 101 | /*****************************************************************************/ |
| 93 | /* | 102 | /* |
| 94 | * on-the-wire Rx ACK packet data payload | 103 | * on-the-wire Rx ACK packet data payload |
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index 5abf46cf9e6c..3b0becb12041 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c | |||
| @@ -141,7 +141,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial) | |||
| 141 | ASSERTCMP(call->rx_hard_ack, ==, call->rx_top); | 141 | ASSERTCMP(call->rx_hard_ack, ==, call->rx_top); |
| 142 | 142 | ||
| 143 | if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) { | 143 | if (call->state == RXRPC_CALL_CLIENT_RECV_REPLY) { |
| 144 | rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, 0, serial, false, true, | 144 | rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, serial, false, true, |
| 145 | rxrpc_propose_ack_terminal_ack); | 145 | rxrpc_propose_ack_terminal_ack); |
| 146 | //rxrpc_send_ack_packet(call, false, NULL); | 146 | //rxrpc_send_ack_packet(call, false, NULL); |
| 147 | } | 147 | } |
| @@ -159,7 +159,7 @@ static void rxrpc_end_rx_phase(struct rxrpc_call *call, rxrpc_serial_t serial) | |||
| 159 | call->state = RXRPC_CALL_SERVER_ACK_REQUEST; | 159 | call->state = RXRPC_CALL_SERVER_ACK_REQUEST; |
| 160 | call->expect_req_by = jiffies + MAX_JIFFY_OFFSET; | 160 | call->expect_req_by = jiffies + MAX_JIFFY_OFFSET; |
| 161 | write_unlock_bh(&call->state_lock); | 161 | write_unlock_bh(&call->state_lock); |
| 162 | rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial, false, true, | 162 | rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, false, true, |
| 163 | rxrpc_propose_ack_processing_op); | 163 | rxrpc_propose_ack_processing_op); |
| 164 | break; | 164 | break; |
| 165 | default: | 165 | default: |
| @@ -177,7 +177,8 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call) | |||
| 177 | struct sk_buff *skb; | 177 | struct sk_buff *skb; |
| 178 | rxrpc_serial_t serial; | 178 | rxrpc_serial_t serial; |
| 179 | rxrpc_seq_t hard_ack, top; | 179 | rxrpc_seq_t hard_ack, top; |
| 180 | u8 flags; | 180 | bool last = false; |
| 181 | u8 subpacket; | ||
| 181 | int ix; | 182 | int ix; |
| 182 | 183 | ||
| 183 | _enter("%d", call->debug_id); | 184 | _enter("%d", call->debug_id); |
| @@ -189,30 +190,32 @@ static void rxrpc_rotate_rx_window(struct rxrpc_call *call) | |||
| 189 | hard_ack++; | 190 | hard_ack++; |
| 190 | ix = hard_ack & RXRPC_RXTX_BUFF_MASK; | 191 | ix = hard_ack & RXRPC_RXTX_BUFF_MASK; |
| 191 | skb = call->rxtx_buffer[ix]; | 192 | skb = call->rxtx_buffer[ix]; |
| 192 | rxrpc_see_skb(skb, rxrpc_skb_rx_rotated); | 193 | rxrpc_see_skb(skb, rxrpc_skb_rotated); |
| 193 | sp = rxrpc_skb(skb); | 194 | sp = rxrpc_skb(skb); |
| 194 | flags = sp->hdr.flags; | 195 | |
| 195 | serial = sp->hdr.serial; | 196 | subpacket = call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET; |
| 196 | if (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) | 197 | serial = sp->hdr.serial + subpacket; |
| 197 | serial += (call->rxtx_annotations[ix] & RXRPC_RX_ANNO_JUMBO) - 1; | 198 | |
| 199 | if (subpacket == sp->nr_subpackets - 1 && | ||
| 200 | sp->rx_flags & RXRPC_SKB_INCL_LAST) | ||
| 201 | last = true; | ||
| 198 | 202 | ||
| 199 | call->rxtx_buffer[ix] = NULL; | 203 | call->rxtx_buffer[ix] = NULL; |
| 200 | call->rxtx_annotations[ix] = 0; | 204 | call->rxtx_annotations[ix] = 0; |
| 201 | /* Barrier against rxrpc_input_data(). */ | 205 | /* Barrier against rxrpc_input_data(). */ |
| 202 | smp_store_release(&call->rx_hard_ack, hard_ack); | 206 | smp_store_release(&call->rx_hard_ack, hard_ack); |
| 203 | 207 | ||
| 204 | rxrpc_free_skb(skb, rxrpc_skb_rx_freed); | 208 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 205 | 209 | ||
| 206 | _debug("%u,%u,%02x", hard_ack, top, flags); | ||
| 207 | trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack); | 210 | trace_rxrpc_receive(call, rxrpc_receive_rotate, serial, hard_ack); |
| 208 | if (flags & RXRPC_LAST_PACKET) { | 211 | if (last) { |
| 209 | rxrpc_end_rx_phase(call, serial); | 212 | rxrpc_end_rx_phase(call, serial); |
| 210 | } else { | 213 | } else { |
| 211 | /* Check to see if there's an ACK that needs sending. */ | 214 | /* Check to see if there's an ACK that needs sending. */ |
| 212 | if (after_eq(hard_ack, call->ackr_consumed + 2) || | 215 | if (after_eq(hard_ack, call->ackr_consumed + 2) || |
| 213 | after_eq(top, call->ackr_seen + 2) || | 216 | after_eq(top, call->ackr_seen + 2) || |
| 214 | (hard_ack == top && after(hard_ack, call->ackr_consumed))) | 217 | (hard_ack == top && after(hard_ack, call->ackr_consumed))) |
| 215 | rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, 0, serial, | 218 | rxrpc_propose_ACK(call, RXRPC_ACK_DELAY, serial, |
| 216 | true, true, | 219 | true, true, |
| 217 | rxrpc_propose_ack_rotate_rx); | 220 | rxrpc_propose_ack_rotate_rx); |
| 218 | if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY) | 221 | if (call->ackr_reason && call->ackr_reason != RXRPC_ACK_DELAY) |
| @@ -233,18 +236,19 @@ static int rxrpc_verify_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 233 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | 236 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); |
| 234 | rxrpc_seq_t seq = sp->hdr.seq; | 237 | rxrpc_seq_t seq = sp->hdr.seq; |
| 235 | u16 cksum = sp->hdr.cksum; | 238 | u16 cksum = sp->hdr.cksum; |
| 239 | u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET; | ||
| 236 | 240 | ||
| 237 | _enter(""); | 241 | _enter(""); |
| 238 | 242 | ||
| 239 | /* For all but the head jumbo subpacket, the security checksum is in a | 243 | /* For all but the head jumbo subpacket, the security checksum is in a |
| 240 | * jumbo header immediately prior to the data. | 244 | * jumbo header immediately prior to the data. |
| 241 | */ | 245 | */ |
| 242 | if ((annotation & RXRPC_RX_ANNO_JUMBO) > 1) { | 246 | if (subpacket > 0) { |
| 243 | __be16 tmp; | 247 | __be16 tmp; |
| 244 | if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0) | 248 | if (skb_copy_bits(skb, offset - 2, &tmp, 2) < 0) |
| 245 | BUG(); | 249 | BUG(); |
| 246 | cksum = ntohs(tmp); | 250 | cksum = ntohs(tmp); |
| 247 | seq += (annotation & RXRPC_RX_ANNO_JUMBO) - 1; | 251 | seq += subpacket; |
| 248 | } | 252 | } |
| 249 | 253 | ||
| 250 | return call->conn->security->verify_packet(call, skb, offset, len, | 254 | return call->conn->security->verify_packet(call, skb, offset, len, |
| @@ -265,19 +269,18 @@ static int rxrpc_locate_data(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 265 | u8 *_annotation, | 269 | u8 *_annotation, |
| 266 | unsigned int *_offset, unsigned int *_len) | 270 | unsigned int *_offset, unsigned int *_len) |
| 267 | { | 271 | { |
| 272 | struct rxrpc_skb_priv *sp = rxrpc_skb(skb); | ||
| 268 | unsigned int offset = sizeof(struct rxrpc_wire_header); | 273 | unsigned int offset = sizeof(struct rxrpc_wire_header); |
| 269 | unsigned int len; | 274 | unsigned int len; |
| 270 | int ret; | 275 | int ret; |
| 271 | u8 annotation = *_annotation; | 276 | u8 annotation = *_annotation; |
| 277 | u8 subpacket = annotation & RXRPC_RX_ANNO_SUBPACKET; | ||
| 272 | 278 | ||
| 273 | /* Locate the subpacket */ | 279 | /* Locate the subpacket */ |
| 280 | offset += subpacket * RXRPC_JUMBO_SUBPKTLEN; | ||
| 274 | len = skb->len - offset; | 281 | len = skb->len - offset; |
| 275 | if ((annotation & RXRPC_RX_ANNO_JUMBO) > 0) { | 282 | if (subpacket < sp->nr_subpackets - 1) |
| 276 | offset += (((annotation & RXRPC_RX_ANNO_JUMBO) - 1) * | 283 | len = RXRPC_JUMBO_DATALEN; |
| 277 | RXRPC_JUMBO_SUBPKTLEN); | ||
| 278 | len = (annotation & RXRPC_RX_ANNO_JLAST) ? | ||
| 279 | skb->len - offset : RXRPC_JUMBO_SUBPKTLEN; | ||
| 280 | } | ||
| 281 | 284 | ||
| 282 | if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) { | 285 | if (!(annotation & RXRPC_RX_ANNO_VERIFIED)) { |
| 283 | ret = rxrpc_verify_packet(call, skb, annotation, offset, len); | 286 | ret = rxrpc_verify_packet(call, skb, annotation, offset, len); |
| @@ -303,6 +306,7 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, | |||
| 303 | { | 306 | { |
| 304 | struct rxrpc_skb_priv *sp; | 307 | struct rxrpc_skb_priv *sp; |
| 305 | struct sk_buff *skb; | 308 | struct sk_buff *skb; |
| 309 | rxrpc_serial_t serial; | ||
| 306 | rxrpc_seq_t hard_ack, top, seq; | 310 | rxrpc_seq_t hard_ack, top, seq; |
| 307 | size_t remain; | 311 | size_t remain; |
| 308 | bool last; | 312 | bool last; |
| @@ -336,12 +340,15 @@ static int rxrpc_recvmsg_data(struct socket *sock, struct rxrpc_call *call, | |||
| 336 | break; | 340 | break; |
| 337 | } | 341 | } |
| 338 | smp_rmb(); | 342 | smp_rmb(); |
| 339 | rxrpc_see_skb(skb, rxrpc_skb_rx_seen); | 343 | rxrpc_see_skb(skb, rxrpc_skb_seen); |
| 340 | sp = rxrpc_skb(skb); | 344 | sp = rxrpc_skb(skb); |
| 341 | 345 | ||
| 342 | if (!(flags & MSG_PEEK)) | 346 | if (!(flags & MSG_PEEK)) { |
| 347 | serial = sp->hdr.serial; | ||
| 348 | serial += call->rxtx_annotations[ix] & RXRPC_RX_ANNO_SUBPACKET; | ||
| 343 | trace_rxrpc_receive(call, rxrpc_receive_front, | 349 | trace_rxrpc_receive(call, rxrpc_receive_front, |
| 344 | sp->hdr.serial, seq); | 350 | serial, seq); |
| 351 | } | ||
| 345 | 352 | ||
| 346 | if (msg) | 353 | if (msg) |
| 347 | sock_recv_timestamp(msg, sock->sk, skb); | 354 | sock_recv_timestamp(msg, sock->sk, skb); |
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c index ae8cd8926456..c60c520fde7c 100644 --- a/net/rxrpc/rxkad.c +++ b/net/rxrpc/rxkad.c | |||
| @@ -187,10 +187,8 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, | |||
| 187 | struct rxrpc_skb_priv *sp; | 187 | struct rxrpc_skb_priv *sp; |
| 188 | struct rxrpc_crypt iv; | 188 | struct rxrpc_crypt iv; |
| 189 | struct scatterlist sg[16]; | 189 | struct scatterlist sg[16]; |
| 190 | struct sk_buff *trailer; | ||
| 191 | unsigned int len; | 190 | unsigned int len; |
| 192 | u16 check; | 191 | u16 check; |
| 193 | int nsg; | ||
| 194 | int err; | 192 | int err; |
| 195 | 193 | ||
| 196 | sp = rxrpc_skb(skb); | 194 | sp = rxrpc_skb(skb); |
| @@ -214,15 +212,14 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call, | |||
| 214 | crypto_skcipher_encrypt(req); | 212 | crypto_skcipher_encrypt(req); |
| 215 | 213 | ||
| 216 | /* we want to encrypt the skbuff in-place */ | 214 | /* we want to encrypt the skbuff in-place */ |
| 217 | nsg = skb_cow_data(skb, 0, &trailer); | 215 | err = -EMSGSIZE; |
| 218 | err = -ENOMEM; | 216 | if (skb_shinfo(skb)->nr_frags > 16) |
| 219 | if (nsg < 0 || nsg > 16) | ||
| 220 | goto out; | 217 | goto out; |
| 221 | 218 | ||
| 222 | len = data_size + call->conn->size_align - 1; | 219 | len = data_size + call->conn->size_align - 1; |
| 223 | len &= ~(call->conn->size_align - 1); | 220 | len &= ~(call->conn->size_align - 1); |
| 224 | 221 | ||
| 225 | sg_init_table(sg, nsg); | 222 | sg_init_table(sg, ARRAY_SIZE(sg)); |
| 226 | err = skb_to_sgvec(skb, sg, 0, len); | 223 | err = skb_to_sgvec(skb, sg, 0, len); |
| 227 | if (unlikely(err < 0)) | 224 | if (unlikely(err < 0)) |
| 228 | goto out; | 225 | goto out; |
| @@ -319,11 +316,10 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 319 | struct rxkad_level1_hdr sechdr; | 316 | struct rxkad_level1_hdr sechdr; |
| 320 | struct rxrpc_crypt iv; | 317 | struct rxrpc_crypt iv; |
| 321 | struct scatterlist sg[16]; | 318 | struct scatterlist sg[16]; |
| 322 | struct sk_buff *trailer; | ||
| 323 | bool aborted; | 319 | bool aborted; |
| 324 | u32 data_size, buf; | 320 | u32 data_size, buf; |
| 325 | u16 check; | 321 | u16 check; |
| 326 | int nsg, ret; | 322 | int ret; |
| 327 | 323 | ||
| 328 | _enter(""); | 324 | _enter(""); |
| 329 | 325 | ||
| @@ -336,11 +332,7 @@ static int rxkad_verify_packet_1(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 336 | /* Decrypt the skbuff in-place. TODO: We really want to decrypt | 332 | /* Decrypt the skbuff in-place. TODO: We really want to decrypt |
| 337 | * directly into the target buffer. | 333 | * directly into the target buffer. |
| 338 | */ | 334 | */ |
| 339 | nsg = skb_cow_data(skb, 0, &trailer); | 335 | sg_init_table(sg, ARRAY_SIZE(sg)); |
| 340 | if (nsg < 0 || nsg > 16) | ||
| 341 | goto nomem; | ||
| 342 | |||
| 343 | sg_init_table(sg, nsg); | ||
| 344 | ret = skb_to_sgvec(skb, sg, offset, 8); | 336 | ret = skb_to_sgvec(skb, sg, offset, 8); |
| 345 | if (unlikely(ret < 0)) | 337 | if (unlikely(ret < 0)) |
| 346 | return ret; | 338 | return ret; |
| @@ -388,10 +380,6 @@ protocol_error: | |||
| 388 | if (aborted) | 380 | if (aborted) |
| 389 | rxrpc_send_abort_packet(call); | 381 | rxrpc_send_abort_packet(call); |
| 390 | return -EPROTO; | 382 | return -EPROTO; |
| 391 | |||
| 392 | nomem: | ||
| 393 | _leave(" = -ENOMEM"); | ||
| 394 | return -ENOMEM; | ||
| 395 | } | 383 | } |
| 396 | 384 | ||
| 397 | /* | 385 | /* |
| @@ -406,7 +394,6 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 406 | struct rxkad_level2_hdr sechdr; | 394 | struct rxkad_level2_hdr sechdr; |
| 407 | struct rxrpc_crypt iv; | 395 | struct rxrpc_crypt iv; |
| 408 | struct scatterlist _sg[4], *sg; | 396 | struct scatterlist _sg[4], *sg; |
| 409 | struct sk_buff *trailer; | ||
| 410 | bool aborted; | 397 | bool aborted; |
| 411 | u32 data_size, buf; | 398 | u32 data_size, buf; |
| 412 | u16 check; | 399 | u16 check; |
| @@ -423,12 +410,11 @@ static int rxkad_verify_packet_2(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 423 | /* Decrypt the skbuff in-place. TODO: We really want to decrypt | 410 | /* Decrypt the skbuff in-place. TODO: We really want to decrypt |
| 424 | * directly into the target buffer. | 411 | * directly into the target buffer. |
| 425 | */ | 412 | */ |
| 426 | nsg = skb_cow_data(skb, 0, &trailer); | ||
| 427 | if (nsg < 0) | ||
| 428 | goto nomem; | ||
| 429 | |||
| 430 | sg = _sg; | 413 | sg = _sg; |
| 431 | if (unlikely(nsg > 4)) { | 414 | nsg = skb_shinfo(skb)->nr_frags; |
| 415 | if (nsg <= 4) { | ||
| 416 | nsg = 4; | ||
| 417 | } else { | ||
| 432 | sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO); | 418 | sg = kmalloc_array(nsg, sizeof(*sg), GFP_NOIO); |
| 433 | if (!sg) | 419 | if (!sg) |
| 434 | goto nomem; | 420 | goto nomem; |
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 5d3f33ce6d41..6a1547b270fe 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c | |||
| @@ -176,7 +176,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, | |||
| 176 | skb->tstamp = ktime_get_real(); | 176 | skb->tstamp = ktime_get_real(); |
| 177 | 177 | ||
| 178 | ix = seq & RXRPC_RXTX_BUFF_MASK; | 178 | ix = seq & RXRPC_RXTX_BUFF_MASK; |
| 179 | rxrpc_get_skb(skb, rxrpc_skb_tx_got); | 179 | rxrpc_get_skb(skb, rxrpc_skb_got); |
| 180 | call->rxtx_annotations[ix] = annotation; | 180 | call->rxtx_annotations[ix] = annotation; |
| 181 | smp_wmb(); | 181 | smp_wmb(); |
| 182 | call->rxtx_buffer[ix] = skb; | 182 | call->rxtx_buffer[ix] = skb; |
| @@ -226,6 +226,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, | |||
| 226 | rxrpc_set_call_completion(call, | 226 | rxrpc_set_call_completion(call, |
| 227 | RXRPC_CALL_LOCAL_ERROR, | 227 | RXRPC_CALL_LOCAL_ERROR, |
| 228 | 0, ret); | 228 | 0, ret); |
| 229 | rxrpc_notify_socket(call); | ||
| 229 | goto out; | 230 | goto out; |
| 230 | } | 231 | } |
| 231 | _debug("need instant resend %d", ret); | 232 | _debug("need instant resend %d", ret); |
| @@ -247,7 +248,7 @@ static int rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call, | |||
| 247 | } | 248 | } |
| 248 | 249 | ||
| 249 | out: | 250 | out: |
| 250 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 251 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 251 | _leave(" = %d", ret); | 252 | _leave(" = %d", ret); |
| 252 | return ret; | 253 | return ret; |
| 253 | } | 254 | } |
| @@ -288,7 +289,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 288 | 289 | ||
| 289 | skb = call->tx_pending; | 290 | skb = call->tx_pending; |
| 290 | call->tx_pending = NULL; | 291 | call->tx_pending = NULL; |
| 291 | rxrpc_see_skb(skb, rxrpc_skb_tx_seen); | 292 | rxrpc_see_skb(skb, rxrpc_skb_seen); |
| 292 | 293 | ||
| 293 | copied = 0; | 294 | copied = 0; |
| 294 | do { | 295 | do { |
| @@ -335,7 +336,9 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 335 | if (!skb) | 336 | if (!skb) |
| 336 | goto maybe_error; | 337 | goto maybe_error; |
| 337 | 338 | ||
| 338 | rxrpc_new_skb(skb, rxrpc_skb_tx_new); | 339 | sp = rxrpc_skb(skb); |
| 340 | sp->rx_flags |= RXRPC_SKB_TX_BUFFER; | ||
| 341 | rxrpc_new_skb(skb, rxrpc_skb_new); | ||
| 339 | 342 | ||
| 340 | _debug("ALLOC SEND %p", skb); | 343 | _debug("ALLOC SEND %p", skb); |
| 341 | 344 | ||
| @@ -345,7 +348,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, | |||
| 345 | skb_reserve(skb, call->conn->security_size); | 348 | skb_reserve(skb, call->conn->security_size); |
| 346 | skb->len += call->conn->security_size; | 349 | skb->len += call->conn->security_size; |
| 347 | 350 | ||
| 348 | sp = rxrpc_skb(skb); | ||
| 349 | sp->remain = chunk; | 351 | sp->remain = chunk; |
| 350 | if (sp->remain > skb_tailroom(skb)) | 352 | if (sp->remain > skb_tailroom(skb)) |
| 351 | sp->remain = skb_tailroom(skb); | 353 | sp->remain = skb_tailroom(skb); |
| @@ -438,7 +440,7 @@ out: | |||
| 438 | return ret; | 440 | return ret; |
| 439 | 441 | ||
| 440 | call_terminated: | 442 | call_terminated: |
| 441 | rxrpc_free_skb(skb, rxrpc_skb_tx_freed); | 443 | rxrpc_free_skb(skb, rxrpc_skb_freed); |
| 442 | _leave(" = %d", call->error); | 444 | _leave(" = %d", call->error); |
| 443 | return call->error; | 445 | return call->error; |
| 444 | 446 | ||
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c index 9ad5045b7c2f..0348d2bf6f7d 100644 --- a/net/rxrpc/skbuff.c +++ b/net/rxrpc/skbuff.c | |||
| @@ -14,7 +14,8 @@ | |||
| 14 | #include <net/af_rxrpc.h> | 14 | #include <net/af_rxrpc.h> |
| 15 | #include "ar-internal.h" | 15 | #include "ar-internal.h" |
| 16 | 16 | ||
| 17 | #define select_skb_count(op) (op >= rxrpc_skb_tx_cleaned ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs) | 17 | #define is_tx_skb(skb) (rxrpc_skb(skb)->rx_flags & RXRPC_SKB_TX_BUFFER) |
| 18 | #define select_skb_count(skb) (is_tx_skb(skb) ? &rxrpc_n_tx_skbs : &rxrpc_n_rx_skbs) | ||
| 18 | 19 | ||
| 19 | /* | 20 | /* |
| 20 | * Note the allocation or reception of a socket buffer. | 21 | * Note the allocation or reception of a socket buffer. |
| @@ -22,8 +23,9 @@ | |||
| 22 | void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | 23 | void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) |
| 23 | { | 24 | { |
| 24 | const void *here = __builtin_return_address(0); | 25 | const void *here = __builtin_return_address(0); |
| 25 | int n = atomic_inc_return(select_skb_count(op)); | 26 | int n = atomic_inc_return(select_skb_count(skb)); |
| 26 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here); | 27 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, |
| 28 | rxrpc_skb(skb)->rx_flags, here); | ||
| 27 | } | 29 | } |
| 28 | 30 | ||
| 29 | /* | 31 | /* |
| @@ -33,8 +35,9 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | |||
| 33 | { | 35 | { |
| 34 | const void *here = __builtin_return_address(0); | 36 | const void *here = __builtin_return_address(0); |
| 35 | if (skb) { | 37 | if (skb) { |
| 36 | int n = atomic_read(select_skb_count(op)); | 38 | int n = atomic_read(select_skb_count(skb)); |
| 37 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here); | 39 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, |
| 40 | rxrpc_skb(skb)->rx_flags, here); | ||
| 38 | } | 41 | } |
| 39 | } | 42 | } |
| 40 | 43 | ||
| @@ -44,12 +47,23 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | |||
| 44 | void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | 47 | void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) |
| 45 | { | 48 | { |
| 46 | const void *here = __builtin_return_address(0); | 49 | const void *here = __builtin_return_address(0); |
| 47 | int n = atomic_inc_return(select_skb_count(op)); | 50 | int n = atomic_inc_return(select_skb_count(skb)); |
| 48 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here); | 51 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, |
| 52 | rxrpc_skb(skb)->rx_flags, here); | ||
| 49 | skb_get(skb); | 53 | skb_get(skb); |
| 50 | } | 54 | } |
| 51 | 55 | ||
| 52 | /* | 56 | /* |
| 57 | * Note the dropping of a ref on a socket buffer by the core. | ||
| 58 | */ | ||
| 59 | void rxrpc_eaten_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | ||
| 60 | { | ||
| 61 | const void *here = __builtin_return_address(0); | ||
| 62 | int n = atomic_inc_return(&rxrpc_n_rx_skbs); | ||
| 63 | trace_rxrpc_skb(skb, op, 0, n, 0, here); | ||
| 64 | } | ||
| 65 | |||
| 66 | /* | ||
| 53 | * Note the destruction of a socket buffer. | 67 | * Note the destruction of a socket buffer. |
| 54 | */ | 68 | */ |
| 55 | void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | 69 | void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) |
| @@ -58,8 +72,9 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op) | |||
| 58 | if (skb) { | 72 | if (skb) { |
| 59 | int n; | 73 | int n; |
| 60 | CHECK_SLAB_OKAY(&skb->users); | 74 | CHECK_SLAB_OKAY(&skb->users); |
| 61 | n = atomic_dec_return(select_skb_count(op)); | 75 | n = atomic_dec_return(select_skb_count(skb)); |
| 62 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here); | 76 | trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, |
| 77 | rxrpc_skb(skb)->rx_flags, here); | ||
| 63 | kfree_skb(skb); | 78 | kfree_skb(skb); |
| 64 | } | 79 | } |
| 65 | } | 80 | } |
| @@ -72,9 +87,10 @@ void rxrpc_purge_queue(struct sk_buff_head *list) | |||
| 72 | const void *here = __builtin_return_address(0); | 87 | const void *here = __builtin_return_address(0); |
| 73 | struct sk_buff *skb; | 88 | struct sk_buff *skb; |
| 74 | while ((skb = skb_dequeue((list))) != NULL) { | 89 | while ((skb = skb_dequeue((list))) != NULL) { |
| 75 | int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged)); | 90 | int n = atomic_dec_return(select_skb_count(skb)); |
| 76 | trace_rxrpc_skb(skb, rxrpc_skb_rx_purged, | 91 | trace_rxrpc_skb(skb, rxrpc_skb_purged, |
| 77 | refcount_read(&skb->users), n, here); | 92 | refcount_read(&skb->users), n, |
| 93 | rxrpc_skb(skb)->rx_flags, here); | ||
| 78 | kfree_skb(skb); | 94 | kfree_skb(skb); |
| 79 | } | 95 | } |
| 80 | } | 96 | } |
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c index 8126b26f125e..04b7bd4ec751 100644 --- a/net/sched/act_bpf.c +++ b/net/sched/act_bpf.c | |||
| @@ -285,6 +285,7 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 285 | struct tcf_bpf *prog; | 285 | struct tcf_bpf *prog; |
| 286 | bool is_bpf, is_ebpf; | 286 | bool is_bpf, is_ebpf; |
| 287 | int ret, res = 0; | 287 | int ret, res = 0; |
| 288 | u32 index; | ||
| 288 | 289 | ||
| 289 | if (!nla) | 290 | if (!nla) |
| 290 | return -EINVAL; | 291 | return -EINVAL; |
| @@ -298,13 +299,13 @@ static int tcf_bpf_init(struct net *net, struct nlattr *nla, | |||
| 298 | return -EINVAL; | 299 | return -EINVAL; |
| 299 | 300 | ||
| 300 | parm = nla_data(tb[TCA_ACT_BPF_PARMS]); | 301 | parm = nla_data(tb[TCA_ACT_BPF_PARMS]); |
| 301 | 302 | index = parm->index; | |
| 302 | ret = tcf_idr_check_alloc(tn, &parm->index, act, bind); | 303 | ret = tcf_idr_check_alloc(tn, &index, act, bind); |
| 303 | if (!ret) { | 304 | if (!ret) { |
| 304 | ret = tcf_idr_create(tn, parm->index, est, act, | 305 | ret = tcf_idr_create(tn, index, est, act, |
| 305 | &act_bpf_ops, bind, true); | 306 | &act_bpf_ops, bind, true); |
| 306 | if (ret < 0) { | 307 | if (ret < 0) { |
| 307 | tcf_idr_cleanup(tn, parm->index); | 308 | tcf_idr_cleanup(tn, index); |
| 308 | return ret; | 309 | return ret; |
| 309 | } | 310 | } |
| 310 | 311 | ||
| @@ -421,7 +422,7 @@ static __net_init int bpf_init_net(struct net *net) | |||
| 421 | { | 422 | { |
| 422 | struct tc_action_net *tn = net_generic(net, bpf_net_id); | 423 | struct tc_action_net *tn = net_generic(net, bpf_net_id); |
| 423 | 424 | ||
| 424 | return tc_action_net_init(tn, &act_bpf_ops); | 425 | return tc_action_net_init(net, tn, &act_bpf_ops); |
| 425 | } | 426 | } |
| 426 | 427 | ||
| 427 | static void __net_exit bpf_exit_net(struct list_head *net_list) | 428 | static void __net_exit bpf_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c index ce36b0f7e1dc..2b43cacf82af 100644 --- a/net/sched/act_connmark.c +++ b/net/sched/act_connmark.c | |||
| @@ -103,6 +103,7 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, | |||
| 103 | struct tcf_connmark_info *ci; | 103 | struct tcf_connmark_info *ci; |
| 104 | struct tc_connmark *parm; | 104 | struct tc_connmark *parm; |
| 105 | int ret = 0, err; | 105 | int ret = 0, err; |
| 106 | u32 index; | ||
| 106 | 107 | ||
| 107 | if (!nla) | 108 | if (!nla) |
| 108 | return -EINVAL; | 109 | return -EINVAL; |
| @@ -116,13 +117,13 @@ static int tcf_connmark_init(struct net *net, struct nlattr *nla, | |||
| 116 | return -EINVAL; | 117 | return -EINVAL; |
| 117 | 118 | ||
| 118 | parm = nla_data(tb[TCA_CONNMARK_PARMS]); | 119 | parm = nla_data(tb[TCA_CONNMARK_PARMS]); |
| 119 | 120 | index = parm->index; | |
| 120 | ret = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 121 | ret = tcf_idr_check_alloc(tn, &index, a, bind); |
| 121 | if (!ret) { | 122 | if (!ret) { |
| 122 | ret = tcf_idr_create(tn, parm->index, est, a, | 123 | ret = tcf_idr_create(tn, index, est, a, |
| 123 | &act_connmark_ops, bind, false); | 124 | &act_connmark_ops, bind, false); |
| 124 | if (ret) { | 125 | if (ret) { |
| 125 | tcf_idr_cleanup(tn, parm->index); | 126 | tcf_idr_cleanup(tn, index); |
| 126 | return ret; | 127 | return ret; |
| 127 | } | 128 | } |
| 128 | 129 | ||
| @@ -230,7 +231,7 @@ static __net_init int connmark_init_net(struct net *net) | |||
| 230 | { | 231 | { |
| 231 | struct tc_action_net *tn = net_generic(net, connmark_net_id); | 232 | struct tc_action_net *tn = net_generic(net, connmark_net_id); |
| 232 | 233 | ||
| 233 | return tc_action_net_init(tn, &act_connmark_ops); | 234 | return tc_action_net_init(net, tn, &act_connmark_ops); |
| 234 | } | 235 | } |
| 235 | 236 | ||
| 236 | static void __net_exit connmark_exit_net(struct list_head *net_list) | 237 | static void __net_exit connmark_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index 621fb22ce2a9..d3cfad88dc3a 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c | |||
| @@ -52,6 +52,7 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, | |||
| 52 | struct tc_csum *parm; | 52 | struct tc_csum *parm; |
| 53 | struct tcf_csum *p; | 53 | struct tcf_csum *p; |
| 54 | int ret = 0, err; | 54 | int ret = 0, err; |
| 55 | u32 index; | ||
| 55 | 56 | ||
| 56 | if (nla == NULL) | 57 | if (nla == NULL) |
| 57 | return -EINVAL; | 58 | return -EINVAL; |
| @@ -64,13 +65,13 @@ static int tcf_csum_init(struct net *net, struct nlattr *nla, | |||
| 64 | if (tb[TCA_CSUM_PARMS] == NULL) | 65 | if (tb[TCA_CSUM_PARMS] == NULL) |
| 65 | return -EINVAL; | 66 | return -EINVAL; |
| 66 | parm = nla_data(tb[TCA_CSUM_PARMS]); | 67 | parm = nla_data(tb[TCA_CSUM_PARMS]); |
| 67 | 68 | index = parm->index; | |
| 68 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 69 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 69 | if (!err) { | 70 | if (!err) { |
| 70 | ret = tcf_idr_create(tn, parm->index, est, a, | 71 | ret = tcf_idr_create(tn, index, est, a, |
| 71 | &act_csum_ops, bind, true); | 72 | &act_csum_ops, bind, true); |
| 72 | if (ret) { | 73 | if (ret) { |
| 73 | tcf_idr_cleanup(tn, parm->index); | 74 | tcf_idr_cleanup(tn, index); |
| 74 | return ret; | 75 | return ret; |
| 75 | } | 76 | } |
| 76 | ret = ACT_P_CREATED; | 77 | ret = ACT_P_CREATED; |
| @@ -713,7 +714,7 @@ static __net_init int csum_init_net(struct net *net) | |||
| 713 | { | 714 | { |
| 714 | struct tc_action_net *tn = net_generic(net, csum_net_id); | 715 | struct tc_action_net *tn = net_generic(net, csum_net_id); |
| 715 | 716 | ||
| 716 | return tc_action_net_init(tn, &act_csum_ops); | 717 | return tc_action_net_init(net, tn, &act_csum_ops); |
| 717 | } | 718 | } |
| 718 | 719 | ||
| 719 | static void __net_exit csum_exit_net(struct list_head *net_list) | 720 | static void __net_exit csum_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c index b501ce0cf116..cdd6f3818097 100644 --- a/net/sched/act_ct.c +++ b/net/sched/act_ct.c | |||
| @@ -666,6 +666,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, | |||
| 666 | struct tc_ct *parm; | 666 | struct tc_ct *parm; |
| 667 | struct tcf_ct *c; | 667 | struct tcf_ct *c; |
| 668 | int err, res = 0; | 668 | int err, res = 0; |
| 669 | u32 index; | ||
| 669 | 670 | ||
| 670 | if (!nla) { | 671 | if (!nla) { |
| 671 | NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed"); | 672 | NL_SET_ERR_MSG_MOD(extack, "Ct requires attributes to be passed"); |
| @@ -681,16 +682,16 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla, | |||
| 681 | return -EINVAL; | 682 | return -EINVAL; |
| 682 | } | 683 | } |
| 683 | parm = nla_data(tb[TCA_CT_PARMS]); | 684 | parm = nla_data(tb[TCA_CT_PARMS]); |
| 684 | 685 | index = parm->index; | |
| 685 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 686 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 686 | if (err < 0) | 687 | if (err < 0) |
| 687 | return err; | 688 | return err; |
| 688 | 689 | ||
| 689 | if (!err) { | 690 | if (!err) { |
| 690 | err = tcf_idr_create(tn, parm->index, est, a, | 691 | err = tcf_idr_create(tn, index, est, a, |
| 691 | &act_ct_ops, bind, true); | 692 | &act_ct_ops, bind, true); |
| 692 | if (err) { | 693 | if (err) { |
| 693 | tcf_idr_cleanup(tn, parm->index); | 694 | tcf_idr_cleanup(tn, index); |
| 694 | return err; | 695 | return err; |
| 695 | } | 696 | } |
| 696 | res = ACT_P_CREATED; | 697 | res = ACT_P_CREATED; |
| @@ -938,7 +939,7 @@ static __net_init int ct_init_net(struct net *net) | |||
| 938 | tn->labels = true; | 939 | tn->labels = true; |
| 939 | } | 940 | } |
| 940 | 941 | ||
| 941 | return tc_action_net_init(&tn->tn, &act_ct_ops); | 942 | return tc_action_net_init(net, &tn->tn, &act_ct_ops); |
| 942 | } | 943 | } |
| 943 | 944 | ||
| 944 | static void __net_exit ct_exit_net(struct list_head *net_list) | 945 | static void __net_exit ct_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_ctinfo.c b/net/sched/act_ctinfo.c index 10eb2bb99861..0dbcfd1dca7b 100644 --- a/net/sched/act_ctinfo.c +++ b/net/sched/act_ctinfo.c | |||
| @@ -157,10 +157,10 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, | |||
| 157 | struct netlink_ext_ack *extack) | 157 | struct netlink_ext_ack *extack) |
| 158 | { | 158 | { |
| 159 | struct tc_action_net *tn = net_generic(net, ctinfo_net_id); | 159 | struct tc_action_net *tn = net_generic(net, ctinfo_net_id); |
| 160 | u32 dscpmask = 0, dscpstatemask, index; | ||
| 160 | struct nlattr *tb[TCA_CTINFO_MAX + 1]; | 161 | struct nlattr *tb[TCA_CTINFO_MAX + 1]; |
| 161 | struct tcf_ctinfo_params *cp_new; | 162 | struct tcf_ctinfo_params *cp_new; |
| 162 | struct tcf_chain *goto_ch = NULL; | 163 | struct tcf_chain *goto_ch = NULL; |
| 163 | u32 dscpmask = 0, dscpstatemask; | ||
| 164 | struct tc_ctinfo *actparm; | 164 | struct tc_ctinfo *actparm; |
| 165 | struct tcf_ctinfo *ci; | 165 | struct tcf_ctinfo *ci; |
| 166 | u8 dscpmaskshift; | 166 | u8 dscpmaskshift; |
| @@ -206,12 +206,13 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, | |||
| 206 | } | 206 | } |
| 207 | 207 | ||
| 208 | /* done the validation:now to the actual action allocation */ | 208 | /* done the validation:now to the actual action allocation */ |
| 209 | err = tcf_idr_check_alloc(tn, &actparm->index, a, bind); | 209 | index = actparm->index; |
| 210 | err = tcf_idr_check_alloc(tn, &index, a, bind); | ||
| 210 | if (!err) { | 211 | if (!err) { |
| 211 | ret = tcf_idr_create(tn, actparm->index, est, a, | 212 | ret = tcf_idr_create(tn, index, est, a, |
| 212 | &act_ctinfo_ops, bind, false); | 213 | &act_ctinfo_ops, bind, false); |
| 213 | if (ret) { | 214 | if (ret) { |
| 214 | tcf_idr_cleanup(tn, actparm->index); | 215 | tcf_idr_cleanup(tn, index); |
| 215 | return ret; | 216 | return ret; |
| 216 | } | 217 | } |
| 217 | ret = ACT_P_CREATED; | 218 | ret = ACT_P_CREATED; |
| @@ -375,7 +376,7 @@ static __net_init int ctinfo_init_net(struct net *net) | |||
| 375 | { | 376 | { |
| 376 | struct tc_action_net *tn = net_generic(net, ctinfo_net_id); | 377 | struct tc_action_net *tn = net_generic(net, ctinfo_net_id); |
| 377 | 378 | ||
| 378 | return tc_action_net_init(tn, &act_ctinfo_ops); | 379 | return tc_action_net_init(net, tn, &act_ctinfo_ops); |
| 379 | } | 380 | } |
| 380 | 381 | ||
| 381 | static void __net_exit ctinfo_exit_net(struct list_head *net_list) | 382 | static void __net_exit ctinfo_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index b2380c5284e6..324f1d1f6d47 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
| @@ -61,6 +61,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 61 | struct tc_gact *parm; | 61 | struct tc_gact *parm; |
| 62 | struct tcf_gact *gact; | 62 | struct tcf_gact *gact; |
| 63 | int ret = 0; | 63 | int ret = 0; |
| 64 | u32 index; | ||
| 64 | int err; | 65 | int err; |
| 65 | #ifdef CONFIG_GACT_PROB | 66 | #ifdef CONFIG_GACT_PROB |
| 66 | struct tc_gact_p *p_parm = NULL; | 67 | struct tc_gact_p *p_parm = NULL; |
| @@ -77,6 +78,7 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 77 | if (tb[TCA_GACT_PARMS] == NULL) | 78 | if (tb[TCA_GACT_PARMS] == NULL) |
| 78 | return -EINVAL; | 79 | return -EINVAL; |
| 79 | parm = nla_data(tb[TCA_GACT_PARMS]); | 80 | parm = nla_data(tb[TCA_GACT_PARMS]); |
| 81 | index = parm->index; | ||
| 80 | 82 | ||
| 81 | #ifndef CONFIG_GACT_PROB | 83 | #ifndef CONFIG_GACT_PROB |
| 82 | if (tb[TCA_GACT_PROB] != NULL) | 84 | if (tb[TCA_GACT_PROB] != NULL) |
| @@ -94,12 +96,12 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 94 | } | 96 | } |
| 95 | #endif | 97 | #endif |
| 96 | 98 | ||
| 97 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 99 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 98 | if (!err) { | 100 | if (!err) { |
| 99 | ret = tcf_idr_create(tn, parm->index, est, a, | 101 | ret = tcf_idr_create(tn, index, est, a, |
| 100 | &act_gact_ops, bind, true); | 102 | &act_gact_ops, bind, true); |
| 101 | if (ret) { | 103 | if (ret) { |
| 102 | tcf_idr_cleanup(tn, parm->index); | 104 | tcf_idr_cleanup(tn, index); |
| 103 | return ret; | 105 | return ret; |
| 104 | } | 106 | } |
| 105 | ret = ACT_P_CREATED; | 107 | ret = ACT_P_CREATED; |
| @@ -276,7 +278,7 @@ static __net_init int gact_init_net(struct net *net) | |||
| 276 | { | 278 | { |
| 277 | struct tc_action_net *tn = net_generic(net, gact_net_id); | 279 | struct tc_action_net *tn = net_generic(net, gact_net_id); |
| 278 | 280 | ||
| 279 | return tc_action_net_init(tn, &act_gact_ops); | 281 | return tc_action_net_init(net, tn, &act_gact_ops); |
| 280 | } | 282 | } |
| 281 | 283 | ||
| 282 | static void __net_exit gact_exit_net(struct list_head *net_list) | 284 | static void __net_exit gact_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c index 41d5398dd2f2..3a31e241c647 100644 --- a/net/sched/act_ife.c +++ b/net/sched/act_ife.c | |||
| @@ -479,8 +479,14 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, | |||
| 479 | u8 *saddr = NULL; | 479 | u8 *saddr = NULL; |
| 480 | bool exists = false; | 480 | bool exists = false; |
| 481 | int ret = 0; | 481 | int ret = 0; |
| 482 | u32 index; | ||
| 482 | int err; | 483 | int err; |
| 483 | 484 | ||
| 485 | if (!nla) { | ||
| 486 | NL_SET_ERR_MSG_MOD(extack, "IFE requires attributes to be passed"); | ||
| 487 | return -EINVAL; | ||
| 488 | } | ||
| 489 | |||
| 484 | err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy, | 490 | err = nla_parse_nested_deprecated(tb, TCA_IFE_MAX, nla, ife_policy, |
| 485 | NULL); | 491 | NULL); |
| 486 | if (err < 0) | 492 | if (err < 0) |
| @@ -502,7 +508,8 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, | |||
| 502 | if (!p) | 508 | if (!p) |
| 503 | return -ENOMEM; | 509 | return -ENOMEM; |
| 504 | 510 | ||
| 505 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 511 | index = parm->index; |
| 512 | err = tcf_idr_check_alloc(tn, &index, a, bind); | ||
| 506 | if (err < 0) { | 513 | if (err < 0) { |
| 507 | kfree(p); | 514 | kfree(p); |
| 508 | return err; | 515 | return err; |
| @@ -514,10 +521,10 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla, | |||
| 514 | } | 521 | } |
| 515 | 522 | ||
| 516 | if (!exists) { | 523 | if (!exists) { |
| 517 | ret = tcf_idr_create(tn, parm->index, est, a, &act_ife_ops, | 524 | ret = tcf_idr_create(tn, index, est, a, &act_ife_ops, |
| 518 | bind, true); | 525 | bind, true); |
| 519 | if (ret) { | 526 | if (ret) { |
| 520 | tcf_idr_cleanup(tn, parm->index); | 527 | tcf_idr_cleanup(tn, index); |
| 521 | kfree(p); | 528 | kfree(p); |
| 522 | return ret; | 529 | return ret; |
| 523 | } | 530 | } |
| @@ -883,7 +890,7 @@ static __net_init int ife_init_net(struct net *net) | |||
| 883 | { | 890 | { |
| 884 | struct tc_action_net *tn = net_generic(net, ife_net_id); | 891 | struct tc_action_net *tn = net_generic(net, ife_net_id); |
| 885 | 892 | ||
| 886 | return tc_action_net_init(tn, &act_ife_ops); | 893 | return tc_action_net_init(net, tn, &act_ife_ops); |
| 887 | } | 894 | } |
| 888 | 895 | ||
| 889 | static void __net_exit ife_exit_net(struct list_head *net_list) | 896 | static void __net_exit ife_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index ce2c30a591d2..214a03d405cf 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
| @@ -61,12 +61,13 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t, | |||
| 61 | return 0; | 61 | return 0; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | static void ipt_destroy_target(struct xt_entry_target *t) | 64 | static void ipt_destroy_target(struct xt_entry_target *t, struct net *net) |
| 65 | { | 65 | { |
| 66 | struct xt_tgdtor_param par = { | 66 | struct xt_tgdtor_param par = { |
| 67 | .target = t->u.kernel.target, | 67 | .target = t->u.kernel.target, |
| 68 | .targinfo = t->data, | 68 | .targinfo = t->data, |
| 69 | .family = NFPROTO_IPV4, | 69 | .family = NFPROTO_IPV4, |
| 70 | .net = net, | ||
| 70 | }; | 71 | }; |
| 71 | if (par.target->destroy != NULL) | 72 | if (par.target->destroy != NULL) |
| 72 | par.target->destroy(&par); | 73 | par.target->destroy(&par); |
| @@ -78,7 +79,7 @@ static void tcf_ipt_release(struct tc_action *a) | |||
| 78 | struct tcf_ipt *ipt = to_ipt(a); | 79 | struct tcf_ipt *ipt = to_ipt(a); |
| 79 | 80 | ||
| 80 | if (ipt->tcfi_t) { | 81 | if (ipt->tcfi_t) { |
| 81 | ipt_destroy_target(ipt->tcfi_t); | 82 | ipt_destroy_target(ipt->tcfi_t, a->idrinfo->net); |
| 82 | kfree(ipt->tcfi_t); | 83 | kfree(ipt->tcfi_t); |
| 83 | } | 84 | } |
| 84 | kfree(ipt->tcfi_tname); | 85 | kfree(ipt->tcfi_tname); |
| @@ -180,7 +181,7 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla, | |||
| 180 | 181 | ||
| 181 | spin_lock_bh(&ipt->tcf_lock); | 182 | spin_lock_bh(&ipt->tcf_lock); |
| 182 | if (ret != ACT_P_CREATED) { | 183 | if (ret != ACT_P_CREATED) { |
| 183 | ipt_destroy_target(ipt->tcfi_t); | 184 | ipt_destroy_target(ipt->tcfi_t, net); |
| 184 | kfree(ipt->tcfi_tname); | 185 | kfree(ipt->tcfi_tname); |
| 185 | kfree(ipt->tcfi_t); | 186 | kfree(ipt->tcfi_t); |
| 186 | } | 187 | } |
| @@ -350,7 +351,7 @@ static __net_init int ipt_init_net(struct net *net) | |||
| 350 | { | 351 | { |
| 351 | struct tc_action_net *tn = net_generic(net, ipt_net_id); | 352 | struct tc_action_net *tn = net_generic(net, ipt_net_id); |
| 352 | 353 | ||
| 353 | return tc_action_net_init(tn, &act_ipt_ops); | 354 | return tc_action_net_init(net, tn, &act_ipt_ops); |
| 354 | } | 355 | } |
| 355 | 356 | ||
| 356 | static void __net_exit ipt_exit_net(struct list_head *net_list) | 357 | static void __net_exit ipt_exit_net(struct list_head *net_list) |
| @@ -399,7 +400,7 @@ static __net_init int xt_init_net(struct net *net) | |||
| 399 | { | 400 | { |
| 400 | struct tc_action_net *tn = net_generic(net, xt_net_id); | 401 | struct tc_action_net *tn = net_generic(net, xt_net_id); |
| 401 | 402 | ||
| 402 | return tc_action_net_init(tn, &act_xt_ops); | 403 | return tc_action_net_init(net, tn, &act_xt_ops); |
| 403 | } | 404 | } |
| 404 | 405 | ||
| 405 | static void __net_exit xt_exit_net(struct list_head *net_list) | 406 | static void __net_exit xt_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 055faa298c8e..9d1bf508075a 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
| @@ -104,6 +104,7 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 104 | struct net_device *dev; | 104 | struct net_device *dev; |
| 105 | bool exists = false; | 105 | bool exists = false; |
| 106 | int ret, err; | 106 | int ret, err; |
| 107 | u32 index; | ||
| 107 | 108 | ||
| 108 | if (!nla) { | 109 | if (!nla) { |
| 109 | NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed"); | 110 | NL_SET_ERR_MSG_MOD(extack, "Mirred requires attributes to be passed"); |
| @@ -118,8 +119,8 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 118 | return -EINVAL; | 119 | return -EINVAL; |
| 119 | } | 120 | } |
| 120 | parm = nla_data(tb[TCA_MIRRED_PARMS]); | 121 | parm = nla_data(tb[TCA_MIRRED_PARMS]); |
| 121 | 122 | index = parm->index; | |
| 122 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 123 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 123 | if (err < 0) | 124 | if (err < 0) |
| 124 | return err; | 125 | return err; |
| 125 | exists = err; | 126 | exists = err; |
| @@ -136,21 +137,21 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 136 | if (exists) | 137 | if (exists) |
| 137 | tcf_idr_release(*a, bind); | 138 | tcf_idr_release(*a, bind); |
| 138 | else | 139 | else |
| 139 | tcf_idr_cleanup(tn, parm->index); | 140 | tcf_idr_cleanup(tn, index); |
| 140 | NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option"); | 141 | NL_SET_ERR_MSG_MOD(extack, "Unknown mirred option"); |
| 141 | return -EINVAL; | 142 | return -EINVAL; |
| 142 | } | 143 | } |
| 143 | 144 | ||
| 144 | if (!exists) { | 145 | if (!exists) { |
| 145 | if (!parm->ifindex) { | 146 | if (!parm->ifindex) { |
| 146 | tcf_idr_cleanup(tn, parm->index); | 147 | tcf_idr_cleanup(tn, index); |
| 147 | NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist"); | 148 | NL_SET_ERR_MSG_MOD(extack, "Specified device does not exist"); |
| 148 | return -EINVAL; | 149 | return -EINVAL; |
| 149 | } | 150 | } |
| 150 | ret = tcf_idr_create(tn, parm->index, est, a, | 151 | ret = tcf_idr_create(tn, index, est, a, |
| 151 | &act_mirred_ops, bind, true); | 152 | &act_mirred_ops, bind, true); |
| 152 | if (ret) { | 153 | if (ret) { |
| 153 | tcf_idr_cleanup(tn, parm->index); | 154 | tcf_idr_cleanup(tn, index); |
| 154 | return ret; | 155 | return ret; |
| 155 | } | 156 | } |
| 156 | ret = ACT_P_CREATED; | 157 | ret = ACT_P_CREATED; |
| @@ -452,7 +453,7 @@ static __net_init int mirred_init_net(struct net *net) | |||
| 452 | { | 453 | { |
| 453 | struct tc_action_net *tn = net_generic(net, mirred_net_id); | 454 | struct tc_action_net *tn = net_generic(net, mirred_net_id); |
| 454 | 455 | ||
| 455 | return tc_action_net_init(tn, &act_mirred_ops); | 456 | return tc_action_net_init(net, tn, &act_mirred_ops); |
| 456 | } | 457 | } |
| 457 | 458 | ||
| 458 | static void __net_exit mirred_exit_net(struct list_head *net_list) | 459 | static void __net_exit mirred_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c index ca2597ce4ac9..e168df0e008a 100644 --- a/net/sched/act_mpls.c +++ b/net/sched/act_mpls.c | |||
| @@ -138,6 +138,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, | |||
| 138 | struct tcf_mpls *m; | 138 | struct tcf_mpls *m; |
| 139 | int ret = 0, err; | 139 | int ret = 0, err; |
| 140 | u8 mpls_ttl = 0; | 140 | u8 mpls_ttl = 0; |
| 141 | u32 index; | ||
| 141 | 142 | ||
| 142 | if (!nla) { | 143 | if (!nla) { |
| 143 | NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes"); | 144 | NL_SET_ERR_MSG_MOD(extack, "Missing netlink attributes"); |
| @@ -153,6 +154,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, | |||
| 153 | return -EINVAL; | 154 | return -EINVAL; |
| 154 | } | 155 | } |
| 155 | parm = nla_data(tb[TCA_MPLS_PARMS]); | 156 | parm = nla_data(tb[TCA_MPLS_PARMS]); |
| 157 | index = parm->index; | ||
| 156 | 158 | ||
| 157 | /* Verify parameters against action type. */ | 159 | /* Verify parameters against action type. */ |
| 158 | switch (parm->m_action) { | 160 | switch (parm->m_action) { |
| @@ -209,7 +211,7 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, | |||
| 209 | return -EINVAL; | 211 | return -EINVAL; |
| 210 | } | 212 | } |
| 211 | 213 | ||
| 212 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 214 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 213 | if (err < 0) | 215 | if (err < 0) |
| 214 | return err; | 216 | return err; |
| 215 | exists = err; | 217 | exists = err; |
| @@ -217,10 +219,10 @@ static int tcf_mpls_init(struct net *net, struct nlattr *nla, | |||
| 217 | return 0; | 219 | return 0; |
| 218 | 220 | ||
| 219 | if (!exists) { | 221 | if (!exists) { |
| 220 | ret = tcf_idr_create(tn, parm->index, est, a, | 222 | ret = tcf_idr_create(tn, index, est, a, |
| 221 | &act_mpls_ops, bind, true); | 223 | &act_mpls_ops, bind, true); |
| 222 | if (ret) { | 224 | if (ret) { |
| 223 | tcf_idr_cleanup(tn, parm->index); | 225 | tcf_idr_cleanup(tn, index); |
| 224 | return ret; | 226 | return ret; |
| 225 | } | 227 | } |
| 226 | 228 | ||
| @@ -373,7 +375,7 @@ static __net_init int mpls_init_net(struct net *net) | |||
| 373 | { | 375 | { |
| 374 | struct tc_action_net *tn = net_generic(net, mpls_net_id); | 376 | struct tc_action_net *tn = net_generic(net, mpls_net_id); |
| 375 | 377 | ||
| 376 | return tc_action_net_init(tn, &act_mpls_ops); | 378 | return tc_action_net_init(net, tn, &act_mpls_ops); |
| 377 | } | 379 | } |
| 378 | 380 | ||
| 379 | static void __net_exit mpls_exit_net(struct list_head *net_list) | 381 | static void __net_exit mpls_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 45923ebb7a4f..ea4c5359e7df 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c | |||
| @@ -44,6 +44,7 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 44 | struct tc_nat *parm; | 44 | struct tc_nat *parm; |
| 45 | int ret = 0, err; | 45 | int ret = 0, err; |
| 46 | struct tcf_nat *p; | 46 | struct tcf_nat *p; |
| 47 | u32 index; | ||
| 47 | 48 | ||
| 48 | if (nla == NULL) | 49 | if (nla == NULL) |
| 49 | return -EINVAL; | 50 | return -EINVAL; |
| @@ -56,13 +57,13 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 56 | if (tb[TCA_NAT_PARMS] == NULL) | 57 | if (tb[TCA_NAT_PARMS] == NULL) |
| 57 | return -EINVAL; | 58 | return -EINVAL; |
| 58 | parm = nla_data(tb[TCA_NAT_PARMS]); | 59 | parm = nla_data(tb[TCA_NAT_PARMS]); |
| 59 | 60 | index = parm->index; | |
| 60 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 61 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 61 | if (!err) { | 62 | if (!err) { |
| 62 | ret = tcf_idr_create(tn, parm->index, est, a, | 63 | ret = tcf_idr_create(tn, index, est, a, |
| 63 | &act_nat_ops, bind, false); | 64 | &act_nat_ops, bind, false); |
| 64 | if (ret) { | 65 | if (ret) { |
| 65 | tcf_idr_cleanup(tn, parm->index); | 66 | tcf_idr_cleanup(tn, index); |
| 66 | return ret; | 67 | return ret; |
| 67 | } | 68 | } |
| 68 | ret = ACT_P_CREATED; | 69 | ret = ACT_P_CREATED; |
| @@ -326,7 +327,7 @@ static __net_init int nat_init_net(struct net *net) | |||
| 326 | { | 327 | { |
| 327 | struct tc_action_net *tn = net_generic(net, nat_net_id); | 328 | struct tc_action_net *tn = net_generic(net, nat_net_id); |
| 328 | 329 | ||
| 329 | return tc_action_net_init(tn, &act_nat_ops); | 330 | return tc_action_net_init(net, tn, &act_nat_ops); |
| 330 | } | 331 | } |
| 331 | 332 | ||
| 332 | static void __net_exit nat_exit_net(struct list_head *net_list) | 333 | static void __net_exit nat_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 45e9d6bfddb3..cdfaa79382a2 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
| @@ -149,6 +149,7 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 149 | struct tcf_pedit *p; | 149 | struct tcf_pedit *p; |
| 150 | int ret = 0, err; | 150 | int ret = 0, err; |
| 151 | int ksize; | 151 | int ksize; |
| 152 | u32 index; | ||
| 152 | 153 | ||
| 153 | if (!nla) { | 154 | if (!nla) { |
| 154 | NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed"); | 155 | NL_SET_ERR_MSG_MOD(extack, "Pedit requires attributes to be passed"); |
| @@ -179,18 +180,19 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 179 | if (IS_ERR(keys_ex)) | 180 | if (IS_ERR(keys_ex)) |
| 180 | return PTR_ERR(keys_ex); | 181 | return PTR_ERR(keys_ex); |
| 181 | 182 | ||
| 182 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 183 | index = parm->index; |
| 184 | err = tcf_idr_check_alloc(tn, &index, a, bind); | ||
| 183 | if (!err) { | 185 | if (!err) { |
| 184 | if (!parm->nkeys) { | 186 | if (!parm->nkeys) { |
| 185 | tcf_idr_cleanup(tn, parm->index); | 187 | tcf_idr_cleanup(tn, index); |
| 186 | NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed"); | 188 | NL_SET_ERR_MSG_MOD(extack, "Pedit requires keys to be passed"); |
| 187 | ret = -EINVAL; | 189 | ret = -EINVAL; |
| 188 | goto out_free; | 190 | goto out_free; |
| 189 | } | 191 | } |
| 190 | ret = tcf_idr_create(tn, parm->index, est, a, | 192 | ret = tcf_idr_create(tn, index, est, a, |
| 191 | &act_pedit_ops, bind, false); | 193 | &act_pedit_ops, bind, false); |
| 192 | if (ret) { | 194 | if (ret) { |
| 193 | tcf_idr_cleanup(tn, parm->index); | 195 | tcf_idr_cleanup(tn, index); |
| 194 | goto out_free; | 196 | goto out_free; |
| 195 | } | 197 | } |
| 196 | ret = ACT_P_CREATED; | 198 | ret = ACT_P_CREATED; |
| @@ -496,7 +498,7 @@ static __net_init int pedit_init_net(struct net *net) | |||
| 496 | { | 498 | { |
| 497 | struct tc_action_net *tn = net_generic(net, pedit_net_id); | 499 | struct tc_action_net *tn = net_generic(net, pedit_net_id); |
| 498 | 500 | ||
| 499 | return tc_action_net_init(tn, &act_pedit_ops); | 501 | return tc_action_net_init(net, tn, &act_pedit_ops); |
| 500 | } | 502 | } |
| 501 | 503 | ||
| 502 | static void __net_exit pedit_exit_net(struct list_head *net_list) | 504 | static void __net_exit pedit_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index a065f62fa79c..6315e0f8d26e 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
| @@ -57,6 +57,7 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, | |||
| 57 | struct tc_action_net *tn = net_generic(net, police_net_id); | 57 | struct tc_action_net *tn = net_generic(net, police_net_id); |
| 58 | struct tcf_police_params *new; | 58 | struct tcf_police_params *new; |
| 59 | bool exists = false; | 59 | bool exists = false; |
| 60 | u32 index; | ||
| 60 | 61 | ||
| 61 | if (nla == NULL) | 62 | if (nla == NULL) |
| 62 | return -EINVAL; | 63 | return -EINVAL; |
| @@ -73,7 +74,8 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, | |||
| 73 | return -EINVAL; | 74 | return -EINVAL; |
| 74 | 75 | ||
| 75 | parm = nla_data(tb[TCA_POLICE_TBF]); | 76 | parm = nla_data(tb[TCA_POLICE_TBF]); |
| 76 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 77 | index = parm->index; |
| 78 | err = tcf_idr_check_alloc(tn, &index, a, bind); | ||
| 77 | if (err < 0) | 79 | if (err < 0) |
| 78 | return err; | 80 | return err; |
| 79 | exists = err; | 81 | exists = err; |
| @@ -81,10 +83,10 @@ static int tcf_police_init(struct net *net, struct nlattr *nla, | |||
| 81 | return 0; | 83 | return 0; |
| 82 | 84 | ||
| 83 | if (!exists) { | 85 | if (!exists) { |
| 84 | ret = tcf_idr_create(tn, parm->index, NULL, a, | 86 | ret = tcf_idr_create(tn, index, NULL, a, |
| 85 | &act_police_ops, bind, true); | 87 | &act_police_ops, bind, true); |
| 86 | if (ret) { | 88 | if (ret) { |
| 87 | tcf_idr_cleanup(tn, parm->index); | 89 | tcf_idr_cleanup(tn, index); |
| 88 | return ret; | 90 | return ret; |
| 89 | } | 91 | } |
| 90 | ret = ACT_P_CREATED; | 92 | ret = ACT_P_CREATED; |
| @@ -369,7 +371,7 @@ static __net_init int police_init_net(struct net *net) | |||
| 369 | { | 371 | { |
| 370 | struct tc_action_net *tn = net_generic(net, police_net_id); | 372 | struct tc_action_net *tn = net_generic(net, police_net_id); |
| 371 | 373 | ||
| 372 | return tc_action_net_init(tn, &act_police_ops); | 374 | return tc_action_net_init(net, tn, &act_police_ops); |
| 373 | } | 375 | } |
| 374 | 376 | ||
| 375 | static void __net_exit police_exit_net(struct list_head *net_list) | 377 | static void __net_exit police_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c index 274d7a0c0e25..10229124a992 100644 --- a/net/sched/act_sample.c +++ b/net/sched/act_sample.c | |||
| @@ -41,8 +41,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 41 | struct tc_action_net *tn = net_generic(net, sample_net_id); | 41 | struct tc_action_net *tn = net_generic(net, sample_net_id); |
| 42 | struct nlattr *tb[TCA_SAMPLE_MAX + 1]; | 42 | struct nlattr *tb[TCA_SAMPLE_MAX + 1]; |
| 43 | struct psample_group *psample_group; | 43 | struct psample_group *psample_group; |
| 44 | u32 psample_group_num, rate, index; | ||
| 44 | struct tcf_chain *goto_ch = NULL; | 45 | struct tcf_chain *goto_ch = NULL; |
| 45 | u32 psample_group_num, rate; | ||
| 46 | struct tc_sample *parm; | 46 | struct tc_sample *parm; |
| 47 | struct tcf_sample *s; | 47 | struct tcf_sample *s; |
| 48 | bool exists = false; | 48 | bool exists = false; |
| @@ -59,8 +59,8 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 59 | return -EINVAL; | 59 | return -EINVAL; |
| 60 | 60 | ||
| 61 | parm = nla_data(tb[TCA_SAMPLE_PARMS]); | 61 | parm = nla_data(tb[TCA_SAMPLE_PARMS]); |
| 62 | 62 | index = parm->index; | |
| 63 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 63 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 64 | if (err < 0) | 64 | if (err < 0) |
| 65 | return err; | 65 | return err; |
| 66 | exists = err; | 66 | exists = err; |
| @@ -68,10 +68,10 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 68 | return 0; | 68 | return 0; |
| 69 | 69 | ||
| 70 | if (!exists) { | 70 | if (!exists) { |
| 71 | ret = tcf_idr_create(tn, parm->index, est, a, | 71 | ret = tcf_idr_create(tn, index, est, a, |
| 72 | &act_sample_ops, bind, true); | 72 | &act_sample_ops, bind, true); |
| 73 | if (ret) { | 73 | if (ret) { |
| 74 | tcf_idr_cleanup(tn, parm->index); | 74 | tcf_idr_cleanup(tn, index); |
| 75 | return ret; | 75 | return ret; |
| 76 | } | 76 | } |
| 77 | ret = ACT_P_CREATED; | 77 | ret = ACT_P_CREATED; |
| @@ -102,13 +102,17 @@ static int tcf_sample_init(struct net *net, struct nlattr *nla, | |||
| 102 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); | 102 | goto_ch = tcf_action_set_ctrlact(*a, parm->action, goto_ch); |
| 103 | s->rate = rate; | 103 | s->rate = rate; |
| 104 | s->psample_group_num = psample_group_num; | 104 | s->psample_group_num = psample_group_num; |
| 105 | RCU_INIT_POINTER(s->psample_group, psample_group); | 105 | rcu_swap_protected(s->psample_group, psample_group, |
| 106 | lockdep_is_held(&s->tcf_lock)); | ||
| 106 | 107 | ||
| 107 | if (tb[TCA_SAMPLE_TRUNC_SIZE]) { | 108 | if (tb[TCA_SAMPLE_TRUNC_SIZE]) { |
| 108 | s->truncate = true; | 109 | s->truncate = true; |
| 109 | s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]); | 110 | s->trunc_size = nla_get_u32(tb[TCA_SAMPLE_TRUNC_SIZE]); |
| 110 | } | 111 | } |
| 111 | spin_unlock_bh(&s->tcf_lock); | 112 | spin_unlock_bh(&s->tcf_lock); |
| 113 | |||
| 114 | if (psample_group) | ||
| 115 | psample_group_put(psample_group); | ||
| 112 | if (goto_ch) | 116 | if (goto_ch) |
| 113 | tcf_chain_put_by_act(goto_ch); | 117 | tcf_chain_put_by_act(goto_ch); |
| 114 | 118 | ||
| @@ -265,7 +269,7 @@ static __net_init int sample_init_net(struct net *net) | |||
| 265 | { | 269 | { |
| 266 | struct tc_action_net *tn = net_generic(net, sample_net_id); | 270 | struct tc_action_net *tn = net_generic(net, sample_net_id); |
| 267 | 271 | ||
| 268 | return tc_action_net_init(tn, &act_sample_ops); | 272 | return tc_action_net_init(net, tn, &act_sample_ops); |
| 269 | } | 273 | } |
| 270 | 274 | ||
| 271 | static void __net_exit sample_exit_net(struct list_head *net_list) | 275 | static void __net_exit sample_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index f28ddbabff76..6120e56117ca 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
| @@ -95,6 +95,7 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 95 | struct tcf_defact *d; | 95 | struct tcf_defact *d; |
| 96 | bool exists = false; | 96 | bool exists = false; |
| 97 | int ret = 0, err; | 97 | int ret = 0, err; |
| 98 | u32 index; | ||
| 98 | 99 | ||
| 99 | if (nla == NULL) | 100 | if (nla == NULL) |
| 100 | return -EINVAL; | 101 | return -EINVAL; |
| @@ -108,7 +109,8 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 108 | return -EINVAL; | 109 | return -EINVAL; |
| 109 | 110 | ||
| 110 | parm = nla_data(tb[TCA_DEF_PARMS]); | 111 | parm = nla_data(tb[TCA_DEF_PARMS]); |
| 111 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 112 | index = parm->index; |
| 113 | err = tcf_idr_check_alloc(tn, &index, a, bind); | ||
| 112 | if (err < 0) | 114 | if (err < 0) |
| 113 | return err; | 115 | return err; |
| 114 | exists = err; | 116 | exists = err; |
| @@ -119,15 +121,15 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 119 | if (exists) | 121 | if (exists) |
| 120 | tcf_idr_release(*a, bind); | 122 | tcf_idr_release(*a, bind); |
| 121 | else | 123 | else |
| 122 | tcf_idr_cleanup(tn, parm->index); | 124 | tcf_idr_cleanup(tn, index); |
| 123 | return -EINVAL; | 125 | return -EINVAL; |
| 124 | } | 126 | } |
| 125 | 127 | ||
| 126 | if (!exists) { | 128 | if (!exists) { |
| 127 | ret = tcf_idr_create(tn, parm->index, est, a, | 129 | ret = tcf_idr_create(tn, index, est, a, |
| 128 | &act_simp_ops, bind, false); | 130 | &act_simp_ops, bind, false); |
| 129 | if (ret) { | 131 | if (ret) { |
| 130 | tcf_idr_cleanup(tn, parm->index); | 132 | tcf_idr_cleanup(tn, index); |
| 131 | return ret; | 133 | return ret; |
| 132 | } | 134 | } |
| 133 | 135 | ||
| @@ -230,7 +232,7 @@ static __net_init int simp_init_net(struct net *net) | |||
| 230 | { | 232 | { |
| 231 | struct tc_action_net *tn = net_generic(net, simp_net_id); | 233 | struct tc_action_net *tn = net_generic(net, simp_net_id); |
| 232 | 234 | ||
| 233 | return tc_action_net_init(tn, &act_simp_ops); | 235 | return tc_action_net_init(net, tn, &act_simp_ops); |
| 234 | } | 236 | } |
| 235 | 237 | ||
| 236 | static void __net_exit simp_exit_net(struct list_head *net_list) | 238 | static void __net_exit simp_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 215a06705cef..6a8d3337c577 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c | |||
| @@ -99,6 +99,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 99 | u16 *queue_mapping = NULL, *ptype = NULL; | 99 | u16 *queue_mapping = NULL, *ptype = NULL; |
| 100 | bool exists = false; | 100 | bool exists = false; |
| 101 | int ret = 0, err; | 101 | int ret = 0, err; |
| 102 | u32 index; | ||
| 102 | 103 | ||
| 103 | if (nla == NULL) | 104 | if (nla == NULL) |
| 104 | return -EINVAL; | 105 | return -EINVAL; |
| @@ -146,8 +147,8 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 146 | } | 147 | } |
| 147 | 148 | ||
| 148 | parm = nla_data(tb[TCA_SKBEDIT_PARMS]); | 149 | parm = nla_data(tb[TCA_SKBEDIT_PARMS]); |
| 149 | 150 | index = parm->index; | |
| 150 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 151 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 151 | if (err < 0) | 152 | if (err < 0) |
| 152 | return err; | 153 | return err; |
| 153 | exists = err; | 154 | exists = err; |
| @@ -158,15 +159,15 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 158 | if (exists) | 159 | if (exists) |
| 159 | tcf_idr_release(*a, bind); | 160 | tcf_idr_release(*a, bind); |
| 160 | else | 161 | else |
| 161 | tcf_idr_cleanup(tn, parm->index); | 162 | tcf_idr_cleanup(tn, index); |
| 162 | return -EINVAL; | 163 | return -EINVAL; |
| 163 | } | 164 | } |
| 164 | 165 | ||
| 165 | if (!exists) { | 166 | if (!exists) { |
| 166 | ret = tcf_idr_create(tn, parm->index, est, a, | 167 | ret = tcf_idr_create(tn, index, est, a, |
| 167 | &act_skbedit_ops, bind, true); | 168 | &act_skbedit_ops, bind, true); |
| 168 | if (ret) { | 169 | if (ret) { |
| 169 | tcf_idr_cleanup(tn, parm->index); | 170 | tcf_idr_cleanup(tn, index); |
| 170 | return ret; | 171 | return ret; |
| 171 | } | 172 | } |
| 172 | 173 | ||
| @@ -306,6 +307,17 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index) | |||
| 306 | return tcf_idr_search(tn, a, index); | 307 | return tcf_idr_search(tn, a, index); |
| 307 | } | 308 | } |
| 308 | 309 | ||
| 310 | static size_t tcf_skbedit_get_fill_size(const struct tc_action *act) | ||
| 311 | { | ||
| 312 | return nla_total_size(sizeof(struct tc_skbedit)) | ||
| 313 | + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_PRIORITY */ | ||
| 314 | + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_QUEUE_MAPPING */ | ||
| 315 | + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MARK */ | ||
| 316 | + nla_total_size(sizeof(u16)) /* TCA_SKBEDIT_PTYPE */ | ||
| 317 | + nla_total_size(sizeof(u32)) /* TCA_SKBEDIT_MASK */ | ||
| 318 | + nla_total_size_64bit(sizeof(u64)); /* TCA_SKBEDIT_FLAGS */ | ||
| 319 | } | ||
| 320 | |||
| 309 | static struct tc_action_ops act_skbedit_ops = { | 321 | static struct tc_action_ops act_skbedit_ops = { |
| 310 | .kind = "skbedit", | 322 | .kind = "skbedit", |
| 311 | .id = TCA_ID_SKBEDIT, | 323 | .id = TCA_ID_SKBEDIT, |
| @@ -315,6 +327,7 @@ static struct tc_action_ops act_skbedit_ops = { | |||
| 315 | .init = tcf_skbedit_init, | 327 | .init = tcf_skbedit_init, |
| 316 | .cleanup = tcf_skbedit_cleanup, | 328 | .cleanup = tcf_skbedit_cleanup, |
| 317 | .walk = tcf_skbedit_walker, | 329 | .walk = tcf_skbedit_walker, |
| 330 | .get_fill_size = tcf_skbedit_get_fill_size, | ||
| 318 | .lookup = tcf_skbedit_search, | 331 | .lookup = tcf_skbedit_search, |
| 319 | .size = sizeof(struct tcf_skbedit), | 332 | .size = sizeof(struct tcf_skbedit), |
| 320 | }; | 333 | }; |
| @@ -323,7 +336,7 @@ static __net_init int skbedit_init_net(struct net *net) | |||
| 323 | { | 336 | { |
| 324 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); | 337 | struct tc_action_net *tn = net_generic(net, skbedit_net_id); |
| 325 | 338 | ||
| 326 | return tc_action_net_init(tn, &act_skbedit_ops); | 339 | return tc_action_net_init(net, tn, &act_skbedit_ops); |
| 327 | } | 340 | } |
| 328 | 341 | ||
| 329 | static void __net_exit skbedit_exit_net(struct list_head *net_list) | 342 | static void __net_exit skbedit_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c index 4f07706eff07..888437f97ba6 100644 --- a/net/sched/act_skbmod.c +++ b/net/sched/act_skbmod.c | |||
| @@ -87,12 +87,12 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 87 | struct tcf_skbmod_params *p, *p_old; | 87 | struct tcf_skbmod_params *p, *p_old; |
| 88 | struct tcf_chain *goto_ch = NULL; | 88 | struct tcf_chain *goto_ch = NULL; |
| 89 | struct tc_skbmod *parm; | 89 | struct tc_skbmod *parm; |
| 90 | u32 lflags = 0, index; | ||
| 90 | struct tcf_skbmod *d; | 91 | struct tcf_skbmod *d; |
| 91 | bool exists = false; | 92 | bool exists = false; |
| 92 | u8 *daddr = NULL; | 93 | u8 *daddr = NULL; |
| 93 | u8 *saddr = NULL; | 94 | u8 *saddr = NULL; |
| 94 | u16 eth_type = 0; | 95 | u16 eth_type = 0; |
| 95 | u32 lflags = 0; | ||
| 96 | int ret = 0, err; | 96 | int ret = 0, err; |
| 97 | 97 | ||
| 98 | if (!nla) | 98 | if (!nla) |
| @@ -122,10 +122,11 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | parm = nla_data(tb[TCA_SKBMOD_PARMS]); | 124 | parm = nla_data(tb[TCA_SKBMOD_PARMS]); |
| 125 | index = parm->index; | ||
| 125 | if (parm->flags & SKBMOD_F_SWAPMAC) | 126 | if (parm->flags & SKBMOD_F_SWAPMAC) |
| 126 | lflags = SKBMOD_F_SWAPMAC; | 127 | lflags = SKBMOD_F_SWAPMAC; |
| 127 | 128 | ||
| 128 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 129 | err = tcf_idr_check_alloc(tn, &index, a, bind); |
| 129 | if (err < 0) | 130 | if (err < 0) |
| 130 | return err; | 131 | return err; |
| 131 | exists = err; | 132 | exists = err; |
| @@ -136,15 +137,15 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, | |||
| 136 | if (exists) | 137 | if (exists) |
| 137 | tcf_idr_release(*a, bind); | 138 | tcf_idr_release(*a, bind); |
| 138 | else | 139 | else |
| 139 | tcf_idr_cleanup(tn, parm->index); | 140 | tcf_idr_cleanup(tn, index); |
| 140 | return -EINVAL; | 141 | return -EINVAL; |
| 141 | } | 142 | } |
| 142 | 143 | ||
| 143 | if (!exists) { | 144 | if (!exists) { |
| 144 | ret = tcf_idr_create(tn, parm->index, est, a, | 145 | ret = tcf_idr_create(tn, index, est, a, |
| 145 | &act_skbmod_ops, bind, true); | 146 | &act_skbmod_ops, bind, true); |
| 146 | if (ret) { | 147 | if (ret) { |
| 147 | tcf_idr_cleanup(tn, parm->index); | 148 | tcf_idr_cleanup(tn, index); |
| 148 | return ret; | 149 | return ret; |
| 149 | } | 150 | } |
| 150 | 151 | ||
| @@ -286,7 +287,7 @@ static __net_init int skbmod_init_net(struct net *net) | |||
| 286 | { | 287 | { |
| 287 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); | 288 | struct tc_action_net *tn = net_generic(net, skbmod_net_id); |
| 288 | 289 | ||
| 289 | return tc_action_net_init(tn, &act_skbmod_ops); | 290 | return tc_action_net_init(net, tn, &act_skbmod_ops); |
| 290 | } | 291 | } |
| 291 | 292 | ||
| 292 | static void __net_exit skbmod_exit_net(struct list_head *net_list) | 293 | static void __net_exit skbmod_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c index 10dffda1d5cc..2f83a79f76aa 100644 --- a/net/sched/act_tunnel_key.c +++ b/net/sched/act_tunnel_key.c | |||
| @@ -225,6 +225,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, | |||
| 225 | __be16 flags = 0; | 225 | __be16 flags = 0; |
| 226 | u8 tos, ttl; | 226 | u8 tos, ttl; |
| 227 | int ret = 0; | 227 | int ret = 0; |
| 228 | u32 index; | ||
| 228 | int err; | 229 | int err; |
| 229 | 230 | ||
| 230 | if (!nla) { | 231 | if (!nla) { |
| @@ -245,7 +246,8 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, | |||
| 245 | } | 246 | } |
| 246 | 247 | ||
| 247 | parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]); | 248 | parm = nla_data(tb[TCA_TUNNEL_KEY_PARMS]); |
| 248 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 249 | index = parm->index; |
| 250 | err = tcf_idr_check_alloc(tn, &index, a, bind); | ||
| 249 | if (err < 0) | 251 | if (err < 0) |
| 250 | return err; | 252 | return err; |
| 251 | exists = err; | 253 | exists = err; |
| @@ -345,7 +347,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, | |||
| 345 | } | 347 | } |
| 346 | 348 | ||
| 347 | if (!exists) { | 349 | if (!exists) { |
| 348 | ret = tcf_idr_create(tn, parm->index, est, a, | 350 | ret = tcf_idr_create(tn, index, est, a, |
| 349 | &act_tunnel_key_ops, bind, true); | 351 | &act_tunnel_key_ops, bind, true); |
| 350 | if (ret) { | 352 | if (ret) { |
| 351 | NL_SET_ERR_MSG(extack, "Cannot create TC IDR"); | 353 | NL_SET_ERR_MSG(extack, "Cannot create TC IDR"); |
| @@ -403,7 +405,7 @@ err_out: | |||
| 403 | if (exists) | 405 | if (exists) |
| 404 | tcf_idr_release(*a, bind); | 406 | tcf_idr_release(*a, bind); |
| 405 | else | 407 | else |
| 406 | tcf_idr_cleanup(tn, parm->index); | 408 | tcf_idr_cleanup(tn, index); |
| 407 | return ret; | 409 | return ret; |
| 408 | } | 410 | } |
| 409 | 411 | ||
| @@ -598,7 +600,7 @@ static __net_init int tunnel_key_init_net(struct net *net) | |||
| 598 | { | 600 | { |
| 599 | struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); | 601 | struct tc_action_net *tn = net_generic(net, tunnel_key_net_id); |
| 600 | 602 | ||
| 601 | return tc_action_net_init(tn, &act_tunnel_key_ops); | 603 | return tc_action_net_init(net, tn, &act_tunnel_key_ops); |
| 602 | } | 604 | } |
| 603 | 605 | ||
| 604 | static void __net_exit tunnel_key_exit_net(struct list_head *net_list) | 606 | static void __net_exit tunnel_key_exit_net(struct list_head *net_list) |
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index 9269d350fb8a..287a30bf8930 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c | |||
| @@ -116,6 +116,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 116 | u8 push_prio = 0; | 116 | u8 push_prio = 0; |
| 117 | bool exists = false; | 117 | bool exists = false; |
| 118 | int ret = 0, err; | 118 | int ret = 0, err; |
| 119 | u32 index; | ||
| 119 | 120 | ||
| 120 | if (!nla) | 121 | if (!nla) |
| 121 | return -EINVAL; | 122 | return -EINVAL; |
| @@ -128,7 +129,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 128 | if (!tb[TCA_VLAN_PARMS]) | 129 | if (!tb[TCA_VLAN_PARMS]) |
| 129 | return -EINVAL; | 130 | return -EINVAL; |
| 130 | parm = nla_data(tb[TCA_VLAN_PARMS]); | 131 | parm = nla_data(tb[TCA_VLAN_PARMS]); |
| 131 | err = tcf_idr_check_alloc(tn, &parm->index, a, bind); | 132 | index = parm->index; |
| 133 | err = tcf_idr_check_alloc(tn, &index, a, bind); | ||
| 132 | if (err < 0) | 134 | if (err < 0) |
| 133 | return err; | 135 | return err; |
| 134 | exists = err; | 136 | exists = err; |
| @@ -144,7 +146,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 144 | if (exists) | 146 | if (exists) |
| 145 | tcf_idr_release(*a, bind); | 147 | tcf_idr_release(*a, bind); |
| 146 | else | 148 | else |
| 147 | tcf_idr_cleanup(tn, parm->index); | 149 | tcf_idr_cleanup(tn, index); |
| 148 | return -EINVAL; | 150 | return -EINVAL; |
| 149 | } | 151 | } |
| 150 | push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); | 152 | push_vid = nla_get_u16(tb[TCA_VLAN_PUSH_VLAN_ID]); |
| @@ -152,7 +154,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 152 | if (exists) | 154 | if (exists) |
| 153 | tcf_idr_release(*a, bind); | 155 | tcf_idr_release(*a, bind); |
| 154 | else | 156 | else |
| 155 | tcf_idr_cleanup(tn, parm->index); | 157 | tcf_idr_cleanup(tn, index); |
| 156 | return -ERANGE; | 158 | return -ERANGE; |
| 157 | } | 159 | } |
| 158 | 160 | ||
| @@ -166,7 +168,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 166 | if (exists) | 168 | if (exists) |
| 167 | tcf_idr_release(*a, bind); | 169 | tcf_idr_release(*a, bind); |
| 168 | else | 170 | else |
| 169 | tcf_idr_cleanup(tn, parm->index); | 171 | tcf_idr_cleanup(tn, index); |
| 170 | return -EPROTONOSUPPORT; | 172 | return -EPROTONOSUPPORT; |
| 171 | } | 173 | } |
| 172 | } else { | 174 | } else { |
| @@ -180,16 +182,16 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, | |||
| 180 | if (exists) | 182 | if (exists) |
| 181 | tcf_idr_release(*a, bind); | 183 | tcf_idr_release(*a, bind); |
| 182 | else | 184 | else |
| 183 | tcf_idr_cleanup(tn, parm->index); | 185 | tcf_idr_cleanup(tn, index); |
| 184 | return -EINVAL; | 186 | return -EINVAL; |
| 185 | } | 187 | } |
| 186 | action = parm->v_action; | 188 | action = parm->v_action; |
| 187 | 189 | ||
| 188 | if (!exists) { | 190 | if (!exists) { |
| 189 | ret = tcf_idr_create(tn, parm->index, est, a, | 191 | ret = tcf_idr_create(tn, index, est, a, |
| 190 | &act_vlan_ops, bind, true); | 192 | &act_vlan_ops, bind, true); |
| 191 | if (ret) { | 193 | if (ret) { |
| 192 | tcf_idr_cleanup(tn, parm->index); | 194 | tcf_idr_cleanup(tn, index); |
| 193 | return ret; | 195 | return ret; |
| 194 | } | 196 | } |
| 195 | 197 | ||
| @@ -306,6 +308,14 @@ static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index) | |||
| 306 | return tcf_idr_search(tn, a, index); | 308 | return tcf_idr_search(tn, a, index); |
| 307 | } | 309 | } |
| 308 | 310 | ||
| 311 | static size_t tcf_vlan_get_fill_size(const struct tc_action *act) | ||
| 312 | { | ||
| 313 | return nla_total_size(sizeof(struct tc_vlan)) | ||
| 314 | + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_ID */ | ||
| 315 | + nla_total_size(sizeof(u16)) /* TCA_VLAN_PUSH_VLAN_PROTOCOL */ | ||
| 316 | + nla_total_size(sizeof(u8)); /* TCA_VLAN_PUSH_VLAN_PRIORITY */ | ||
| 317 | } | ||
| 318 | |||
| 309 | static struct tc_action_ops act_vlan_ops = { | 319 | static struct tc_action_ops act_vlan_ops = { |
| 310 | .kind = "vlan", | 320 | .kind = "vlan", |
| 311 | .id = TCA_ID_VLAN, | 321 | .id = TCA_ID_VLAN, |
| @@ -315,6 +325,7 @@ static struct tc_action_ops act_vlan_ops = { | |||
| 315 | .init = tcf_vlan_init, | 325 | .init = tcf_vlan_init, |
| 316 | .cleanup = tcf_vlan_cleanup, | 326 | .cleanup = tcf_vlan_cleanup, |
| 317 | .walk = tcf_vlan_walker, | 327 | .walk = tcf_vlan_walker, |
| 328 | .get_fill_size = tcf_vlan_get_fill_size, | ||
| 318 | .lookup = tcf_vlan_search, | 329 | .lookup = tcf_vlan_search, |
| 319 | .size = sizeof(struct tcf_vlan), | 330 | .size = sizeof(struct tcf_vlan), |
| 320 | }; | 331 | }; |
| @@ -323,7 +334,7 @@ static __net_init int vlan_init_net(struct net *net) | |||
| 323 | { | 334 | { |
| 324 | struct tc_action_net *tn = net_generic(net, vlan_net_id); | 335 | struct tc_action_net *tn = net_generic(net, vlan_net_id); |
| 325 | 336 | ||
| 326 | return tc_action_net_init(tn, &act_vlan_ops); | 337 | return tc_action_net_init(net, tn, &act_vlan_ops); |
| 327 | } | 338 | } |
| 328 | 339 | ||
| 329 | static void __net_exit vlan_exit_net(struct list_head *net_list) | 340 | static void __net_exit vlan_exit_net(struct list_head *net_list) |
diff --git a/net/sched/sch_cbs.c b/net/sched/sch_cbs.c index 732e109c3055..810645b5c086 100644 --- a/net/sched/sch_cbs.c +++ b/net/sched/sch_cbs.c | |||
| @@ -181,11 +181,6 @@ static struct sk_buff *cbs_dequeue_soft(struct Qdisc *sch) | |||
| 181 | s64 credits; | 181 | s64 credits; |
| 182 | int len; | 182 | int len; |
| 183 | 183 | ||
| 184 | if (atomic64_read(&q->port_rate) == -1) { | ||
| 185 | WARN_ONCE(1, "cbs: dequeue() called with unknown port rate."); | ||
| 186 | return NULL; | ||
| 187 | } | ||
| 188 | |||
| 189 | if (q->credits < 0) { | 184 | if (q->credits < 0) { |
| 190 | credits = timediff_to_credits(now - q->last, q->idleslope); | 185 | credits = timediff_to_credits(now - q->last, q->idleslope); |
| 191 | 186 | ||
| @@ -303,11 +298,19 @@ static int cbs_enable_offload(struct net_device *dev, struct cbs_sched_data *q, | |||
| 303 | static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q) | 298 | static void cbs_set_port_rate(struct net_device *dev, struct cbs_sched_data *q) |
| 304 | { | 299 | { |
| 305 | struct ethtool_link_ksettings ecmd; | 300 | struct ethtool_link_ksettings ecmd; |
| 301 | int speed = SPEED_10; | ||
| 306 | int port_rate = -1; | 302 | int port_rate = -1; |
| 303 | int err; | ||
| 304 | |||
| 305 | err = __ethtool_get_link_ksettings(dev, &ecmd); | ||
| 306 | if (err < 0) | ||
| 307 | goto skip; | ||
| 308 | |||
| 309 | if (ecmd.base.speed != SPEED_UNKNOWN) | ||
| 310 | speed = ecmd.base.speed; | ||
| 307 | 311 | ||
| 308 | if (!__ethtool_get_link_ksettings(dev, &ecmd) && | 312 | skip: |
| 309 | ecmd.base.speed != SPEED_UNKNOWN) | 313 | port_rate = speed * 1000 * BYTES_PER_KBIT; |
| 310 | port_rate = ecmd.base.speed * 1000 * BYTES_PER_KBIT; | ||
| 311 | 314 | ||
| 312 | atomic64_set(&q->port_rate, port_rate); | 315 | atomic64_set(&q->port_rate, port_rate); |
| 313 | netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n", | 316 | netdev_dbg(dev, "cbs: set %s's port_rate to: %lld, linkspeed: %d\n", |
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c index 25ef172c23df..30169b3adbbb 100644 --- a/net/sched/sch_codel.c +++ b/net/sched/sch_codel.c | |||
| @@ -71,10 +71,10 @@ static struct sk_buff *dequeue_func(struct codel_vars *vars, void *ctx) | |||
| 71 | struct Qdisc *sch = ctx; | 71 | struct Qdisc *sch = ctx; |
| 72 | struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); | 72 | struct sk_buff *skb = __qdisc_dequeue_head(&sch->q); |
| 73 | 73 | ||
| 74 | if (skb) | 74 | if (skb) { |
| 75 | sch->qstats.backlog -= qdisc_pkt_len(skb); | 75 | sch->qstats.backlog -= qdisc_pkt_len(skb); |
| 76 | 76 | prefetch(&skb->end); /* we'll need skb_shinfo() */ | |
| 77 | prefetch(&skb->end); /* we'll need skb_shinfo() */ | 77 | } |
| 78 | return skb; | 78 | return skb; |
| 79 | } | 79 | } |
| 80 | 80 | ||
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 11c03cf4aa74..137db1cbde85 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
| @@ -624,8 +624,12 @@ static int pfifo_fast_enqueue(struct sk_buff *skb, struct Qdisc *qdisc, | |||
| 624 | 624 | ||
| 625 | err = skb_array_produce(q, skb); | 625 | err = skb_array_produce(q, skb); |
| 626 | 626 | ||
| 627 | if (unlikely(err)) | 627 | if (unlikely(err)) { |
| 628 | return qdisc_drop_cpu(skb, qdisc, to_free); | 628 | if (qdisc_is_percpu_stats(qdisc)) |
| 629 | return qdisc_drop_cpu(skb, qdisc, to_free); | ||
| 630 | else | ||
| 631 | return qdisc_drop(skb, qdisc, to_free); | ||
| 632 | } | ||
| 629 | 633 | ||
| 630 | qdisc_update_stats_at_enqueue(qdisc, pkt_len); | 634 | qdisc_update_stats_at_enqueue(qdisc, pkt_len); |
| 631 | return NET_XMIT_SUCCESS; | 635 | return NET_XMIT_SUCCESS; |
| @@ -688,11 +692,14 @@ static void pfifo_fast_reset(struct Qdisc *qdisc) | |||
| 688 | kfree_skb(skb); | 692 | kfree_skb(skb); |
| 689 | } | 693 | } |
| 690 | 694 | ||
| 691 | for_each_possible_cpu(i) { | 695 | if (qdisc_is_percpu_stats(qdisc)) { |
| 692 | struct gnet_stats_queue *q = per_cpu_ptr(qdisc->cpu_qstats, i); | 696 | for_each_possible_cpu(i) { |
| 697 | struct gnet_stats_queue *q; | ||
| 693 | 698 | ||
| 694 | q->backlog = 0; | 699 | q = per_cpu_ptr(qdisc->cpu_qstats, i); |
| 695 | q->qlen = 0; | 700 | q->backlog = 0; |
| 701 | q->qlen = 0; | ||
| 702 | } | ||
| 696 | } | 703 | } |
| 697 | } | 704 | } |
| 698 | 705 | ||
diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c index c39db507ba3f..8d8bc2ec5cd6 100644 --- a/net/sched/sch_taprio.c +++ b/net/sched/sch_taprio.c | |||
| @@ -477,11 +477,6 @@ static struct sk_buff *taprio_dequeue(struct Qdisc *sch) | |||
| 477 | u32 gate_mask; | 477 | u32 gate_mask; |
| 478 | int i; | 478 | int i; |
| 479 | 479 | ||
| 480 | if (atomic64_read(&q->picos_per_byte) == -1) { | ||
| 481 | WARN_ONCE(1, "taprio: dequeue() called with unknown picos per byte."); | ||
| 482 | return NULL; | ||
| 483 | } | ||
| 484 | |||
| 485 | rcu_read_lock(); | 480 | rcu_read_lock(); |
| 486 | entry = rcu_dereference(q->current_entry); | 481 | entry = rcu_dereference(q->current_entry); |
| 487 | /* if there's no entry, it means that the schedule didn't | 482 | /* if there's no entry, it means that the schedule didn't |
| @@ -958,12 +953,20 @@ static void taprio_set_picos_per_byte(struct net_device *dev, | |||
| 958 | struct taprio_sched *q) | 953 | struct taprio_sched *q) |
| 959 | { | 954 | { |
| 960 | struct ethtool_link_ksettings ecmd; | 955 | struct ethtool_link_ksettings ecmd; |
| 961 | int picos_per_byte = -1; | 956 | int speed = SPEED_10; |
| 957 | int picos_per_byte; | ||
| 958 | int err; | ||
| 962 | 959 | ||
| 963 | if (!__ethtool_get_link_ksettings(dev, &ecmd) && | 960 | err = __ethtool_get_link_ksettings(dev, &ecmd); |
| 964 | ecmd.base.speed != SPEED_UNKNOWN) | 961 | if (err < 0) |
| 965 | picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8, | 962 | goto skip; |
| 966 | ecmd.base.speed * 1000 * 1000); | 963 | |
| 964 | if (ecmd.base.speed != SPEED_UNKNOWN) | ||
| 965 | speed = ecmd.base.speed; | ||
| 966 | |||
| 967 | skip: | ||
| 968 | picos_per_byte = div64_s64(NSEC_PER_SEC * 1000LL * 8, | ||
| 969 | speed * 1000 * 1000); | ||
| 967 | 970 | ||
| 968 | atomic64_set(&q->picos_per_byte, picos_per_byte); | 971 | atomic64_set(&q->picos_per_byte, picos_per_byte); |
| 969 | netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n", | 972 | netdev_dbg(dev, "taprio: set %s's picos_per_byte to: %lld, linkspeed: %d\n", |
| @@ -1195,7 +1198,8 @@ unlock: | |||
| 1195 | spin_unlock_bh(qdisc_lock(sch)); | 1198 | spin_unlock_bh(qdisc_lock(sch)); |
| 1196 | 1199 | ||
| 1197 | free_sched: | 1200 | free_sched: |
| 1198 | kfree(new_admin); | 1201 | if (new_admin) |
| 1202 | call_rcu(&new_admin->rcu, taprio_free_sched_cb); | ||
| 1199 | 1203 | ||
| 1200 | return err; | 1204 | return err; |
| 1201 | } | 1205 | } |
| @@ -1248,6 +1252,10 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt, | |||
| 1248 | */ | 1252 | */ |
| 1249 | q->clockid = -1; | 1253 | q->clockid = -1; |
| 1250 | 1254 | ||
| 1255 | spin_lock(&taprio_list_lock); | ||
| 1256 | list_add(&q->taprio_list, &taprio_list); | ||
| 1257 | spin_unlock(&taprio_list_lock); | ||
| 1258 | |||
| 1251 | if (sch->parent != TC_H_ROOT) | 1259 | if (sch->parent != TC_H_ROOT) |
| 1252 | return -EOPNOTSUPP; | 1260 | return -EOPNOTSUPP; |
| 1253 | 1261 | ||
| @@ -1265,10 +1273,6 @@ static int taprio_init(struct Qdisc *sch, struct nlattr *opt, | |||
| 1265 | if (!opt) | 1273 | if (!opt) |
| 1266 | return -EINVAL; | 1274 | return -EINVAL; |
| 1267 | 1275 | ||
| 1268 | spin_lock(&taprio_list_lock); | ||
| 1269 | list_add(&q->taprio_list, &taprio_list); | ||
| 1270 | spin_unlock(&taprio_list_lock); | ||
| 1271 | |||
| 1272 | for (i = 0; i < dev->num_tx_queues; i++) { | 1276 | for (i = 0; i < dev->num_tx_queues; i++) { |
| 1273 | struct netdev_queue *dev_queue; | 1277 | struct netdev_queue *dev_queue; |
| 1274 | struct Qdisc *qdisc; | 1278 | struct Qdisc *qdisc; |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index a554d6d15d1b..1cf5bb5b73c4 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
| @@ -546,7 +546,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_cmd_seq *commands, | |||
| 546 | */ | 546 | */ |
| 547 | if (net->sctp.pf_enable && | 547 | if (net->sctp.pf_enable && |
| 548 | (transport->state == SCTP_ACTIVE) && | 548 | (transport->state == SCTP_ACTIVE) && |
| 549 | (asoc->pf_retrans < transport->pathmaxrxt) && | 549 | (transport->error_count < transport->pathmaxrxt) && |
| 550 | (transport->error_count > asoc->pf_retrans)) { | 550 | (transport->error_count > asoc->pf_retrans)) { |
| 551 | 551 | ||
| 552 | sctp_assoc_control_transport(asoc, transport, | 552 | sctp_assoc_control_transport(asoc, transport, |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index aa80cda36581..9d1f83b10c0a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -985,7 +985,7 @@ static int sctp_setsockopt_bindx(struct sock *sk, | |||
| 985 | return -EINVAL; | 985 | return -EINVAL; |
| 986 | 986 | ||
| 987 | kaddrs = memdup_user(addrs, addrs_size); | 987 | kaddrs = memdup_user(addrs, addrs_size); |
| 988 | if (unlikely(IS_ERR(kaddrs))) | 988 | if (IS_ERR(kaddrs)) |
| 989 | return PTR_ERR(kaddrs); | 989 | return PTR_ERR(kaddrs); |
| 990 | 990 | ||
| 991 | /* Walk through the addrs buffer and count the number of addresses. */ | 991 | /* Walk through the addrs buffer and count the number of addresses. */ |
| @@ -1315,7 +1315,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk, | |||
| 1315 | return -EINVAL; | 1315 | return -EINVAL; |
| 1316 | 1316 | ||
| 1317 | kaddrs = memdup_user(addrs, addrs_size); | 1317 | kaddrs = memdup_user(addrs, addrs_size); |
| 1318 | if (unlikely(IS_ERR(kaddrs))) | 1318 | if (IS_ERR(kaddrs)) |
| 1319 | return PTR_ERR(kaddrs); | 1319 | return PTR_ERR(kaddrs); |
| 1320 | 1320 | ||
| 1321 | /* Allow security module to validate connectx addresses. */ | 1321 | /* Allow security module to validate connectx addresses. */ |
diff --git a/net/sctp/stream.c b/net/sctp/stream.c index 25946604af85..e83cdaa2ab76 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c | |||
| @@ -316,6 +316,7 @@ int sctp_send_reset_streams(struct sctp_association *asoc, | |||
| 316 | nstr_list[i] = htons(str_list[i]); | 316 | nstr_list[i] = htons(str_list[i]); |
| 317 | 317 | ||
| 318 | if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) { | 318 | if (out && !sctp_stream_outq_is_empty(stream, str_nums, nstr_list)) { |
| 319 | kfree(nstr_list); | ||
| 319 | retval = -EAGAIN; | 320 | retval = -EAGAIN; |
| 320 | goto out; | 321 | goto out; |
| 321 | } | 322 | } |
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 302e355f2ebc..5b932583e407 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c | |||
| @@ -263,7 +263,7 @@ static int smc_bind(struct socket *sock, struct sockaddr *uaddr, | |||
| 263 | 263 | ||
| 264 | /* Check if socket is already active */ | 264 | /* Check if socket is already active */ |
| 265 | rc = -EINVAL; | 265 | rc = -EINVAL; |
| 266 | if (sk->sk_state != SMC_INIT) | 266 | if (sk->sk_state != SMC_INIT || smc->connect_nonblock) |
| 267 | goto out_rel; | 267 | goto out_rel; |
| 268 | 268 | ||
| 269 | smc->clcsock->sk->sk_reuse = sk->sk_reuse; | 269 | smc->clcsock->sk->sk_reuse = sk->sk_reuse; |
| @@ -1390,7 +1390,8 @@ static int smc_listen(struct socket *sock, int backlog) | |||
| 1390 | lock_sock(sk); | 1390 | lock_sock(sk); |
| 1391 | 1391 | ||
| 1392 | rc = -EINVAL; | 1392 | rc = -EINVAL; |
| 1393 | if ((sk->sk_state != SMC_INIT) && (sk->sk_state != SMC_LISTEN)) | 1393 | if ((sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) || |
| 1394 | smc->connect_nonblock) | ||
| 1394 | goto out; | 1395 | goto out; |
| 1395 | 1396 | ||
| 1396 | rc = 0; | 1397 | rc = 0; |
| @@ -1518,7 +1519,7 @@ static int smc_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) | |||
| 1518 | goto out; | 1519 | goto out; |
| 1519 | 1520 | ||
| 1520 | if (msg->msg_flags & MSG_FASTOPEN) { | 1521 | if (msg->msg_flags & MSG_FASTOPEN) { |
| 1521 | if (sk->sk_state == SMC_INIT) { | 1522 | if (sk->sk_state == SMC_INIT && !smc->connect_nonblock) { |
| 1522 | smc_switch_to_fallback(smc); | 1523 | smc_switch_to_fallback(smc); |
| 1523 | smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP; | 1524 | smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP; |
| 1524 | } else { | 1525 | } else { |
| @@ -1732,14 +1733,18 @@ static int smc_setsockopt(struct socket *sock, int level, int optname, | |||
| 1732 | } | 1733 | } |
| 1733 | break; | 1734 | break; |
| 1734 | case TCP_NODELAY: | 1735 | case TCP_NODELAY: |
| 1735 | if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) { | 1736 | if (sk->sk_state != SMC_INIT && |
| 1737 | sk->sk_state != SMC_LISTEN && | ||
| 1738 | sk->sk_state != SMC_CLOSED) { | ||
| 1736 | if (val && !smc->use_fallback) | 1739 | if (val && !smc->use_fallback) |
| 1737 | mod_delayed_work(system_wq, &smc->conn.tx_work, | 1740 | mod_delayed_work(system_wq, &smc->conn.tx_work, |
| 1738 | 0); | 1741 | 0); |
| 1739 | } | 1742 | } |
| 1740 | break; | 1743 | break; |
| 1741 | case TCP_CORK: | 1744 | case TCP_CORK: |
| 1742 | if (sk->sk_state != SMC_INIT && sk->sk_state != SMC_LISTEN) { | 1745 | if (sk->sk_state != SMC_INIT && |
| 1746 | sk->sk_state != SMC_LISTEN && | ||
| 1747 | sk->sk_state != SMC_CLOSED) { | ||
| 1743 | if (!val && !smc->use_fallback) | 1748 | if (!val && !smc->use_fallback) |
| 1744 | mod_delayed_work(system_wq, &smc->conn.tx_work, | 1749 | mod_delayed_work(system_wq, &smc->conn.tx_work, |
| 1745 | 0); | 1750 | 0); |
diff --git a/net/smc/smc_tx.c b/net/smc/smc_tx.c index f0de323d15d6..6c8f09c1ce51 100644 --- a/net/smc/smc_tx.c +++ b/net/smc/smc_tx.c | |||
| @@ -76,13 +76,11 @@ static int smc_tx_wait(struct smc_sock *smc, int flags) | |||
| 76 | DEFINE_WAIT_FUNC(wait, woken_wake_function); | 76 | DEFINE_WAIT_FUNC(wait, woken_wake_function); |
| 77 | struct smc_connection *conn = &smc->conn; | 77 | struct smc_connection *conn = &smc->conn; |
| 78 | struct sock *sk = &smc->sk; | 78 | struct sock *sk = &smc->sk; |
| 79 | bool noblock; | ||
| 80 | long timeo; | 79 | long timeo; |
| 81 | int rc = 0; | 80 | int rc = 0; |
| 82 | 81 | ||
| 83 | /* similar to sk_stream_wait_memory */ | 82 | /* similar to sk_stream_wait_memory */ |
| 84 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | 83 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); |
| 85 | noblock = timeo ? false : true; | ||
| 86 | add_wait_queue(sk_sleep(sk), &wait); | 84 | add_wait_queue(sk_sleep(sk), &wait); |
| 87 | while (1) { | 85 | while (1) { |
| 88 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); | 86 | sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk); |
| @@ -97,8 +95,8 @@ static int smc_tx_wait(struct smc_sock *smc, int flags) | |||
| 97 | break; | 95 | break; |
| 98 | } | 96 | } |
| 99 | if (!timeo) { | 97 | if (!timeo) { |
| 100 | if (noblock) | 98 | /* ensure EPOLLOUT is subsequently generated */ |
| 101 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); | 99 | set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); |
| 102 | rc = -EAGAIN; | 100 | rc = -EAGAIN; |
| 103 | break; | 101 | break; |
| 104 | } | 102 | } |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d8679b6027e9..a07b516e503a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -1970,6 +1970,7 @@ call_bind(struct rpc_task *task) | |||
| 1970 | static void | 1970 | static void |
| 1971 | call_bind_status(struct rpc_task *task) | 1971 | call_bind_status(struct rpc_task *task) |
| 1972 | { | 1972 | { |
| 1973 | struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt; | ||
| 1973 | int status = -EIO; | 1974 | int status = -EIO; |
| 1974 | 1975 | ||
| 1975 | if (rpc_task_transmitted(task)) { | 1976 | if (rpc_task_transmitted(task)) { |
| @@ -1977,14 +1978,15 @@ call_bind_status(struct rpc_task *task) | |||
| 1977 | return; | 1978 | return; |
| 1978 | } | 1979 | } |
| 1979 | 1980 | ||
| 1980 | if (task->tk_status >= 0) { | 1981 | dprint_status(task); |
| 1981 | dprint_status(task); | 1982 | trace_rpc_bind_status(task); |
| 1983 | if (task->tk_status >= 0) | ||
| 1984 | goto out_next; | ||
| 1985 | if (xprt_bound(xprt)) { | ||
| 1982 | task->tk_status = 0; | 1986 | task->tk_status = 0; |
| 1983 | task->tk_action = call_connect; | 1987 | goto out_next; |
| 1984 | return; | ||
| 1985 | } | 1988 | } |
| 1986 | 1989 | ||
| 1987 | trace_rpc_bind_status(task); | ||
| 1988 | switch (task->tk_status) { | 1990 | switch (task->tk_status) { |
| 1989 | case -ENOMEM: | 1991 | case -ENOMEM: |
| 1990 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); | 1992 | dprintk("RPC: %5u rpcbind out of memory\n", task->tk_pid); |
| @@ -2003,6 +2005,9 @@ call_bind_status(struct rpc_task *task) | |||
| 2003 | task->tk_rebind_retry--; | 2005 | task->tk_rebind_retry--; |
| 2004 | rpc_delay(task, 3*HZ); | 2006 | rpc_delay(task, 3*HZ); |
| 2005 | goto retry_timeout; | 2007 | goto retry_timeout; |
| 2008 | case -ENOBUFS: | ||
| 2009 | rpc_delay(task, HZ >> 2); | ||
| 2010 | goto retry_timeout; | ||
| 2006 | case -EAGAIN: | 2011 | case -EAGAIN: |
| 2007 | goto retry_timeout; | 2012 | goto retry_timeout; |
| 2008 | case -ETIMEDOUT: | 2013 | case -ETIMEDOUT: |
| @@ -2026,7 +2031,6 @@ call_bind_status(struct rpc_task *task) | |||
| 2026 | case -ENETDOWN: | 2031 | case -ENETDOWN: |
| 2027 | case -EHOSTUNREACH: | 2032 | case -EHOSTUNREACH: |
| 2028 | case -ENETUNREACH: | 2033 | case -ENETUNREACH: |
| 2029 | case -ENOBUFS: | ||
| 2030 | case -EPIPE: | 2034 | case -EPIPE: |
| 2031 | dprintk("RPC: %5u remote rpcbind unreachable: %d\n", | 2035 | dprintk("RPC: %5u remote rpcbind unreachable: %d\n", |
| 2032 | task->tk_pid, task->tk_status); | 2036 | task->tk_pid, task->tk_status); |
| @@ -2043,7 +2047,9 @@ call_bind_status(struct rpc_task *task) | |||
| 2043 | 2047 | ||
| 2044 | rpc_call_rpcerror(task, status); | 2048 | rpc_call_rpcerror(task, status); |
| 2045 | return; | 2049 | return; |
| 2046 | 2050 | out_next: | |
| 2051 | task->tk_action = call_connect; | ||
| 2052 | return; | ||
| 2047 | retry_timeout: | 2053 | retry_timeout: |
| 2048 | task->tk_status = 0; | 2054 | task->tk_status = 0; |
| 2049 | task->tk_action = call_bind; | 2055 | task->tk_action = call_bind; |
| @@ -2090,6 +2096,7 @@ call_connect(struct rpc_task *task) | |||
| 2090 | static void | 2096 | static void |
| 2091 | call_connect_status(struct rpc_task *task) | 2097 | call_connect_status(struct rpc_task *task) |
| 2092 | { | 2098 | { |
| 2099 | struct rpc_xprt *xprt = task->tk_rqstp->rq_xprt; | ||
| 2093 | struct rpc_clnt *clnt = task->tk_client; | 2100 | struct rpc_clnt *clnt = task->tk_client; |
| 2094 | int status = task->tk_status; | 2101 | int status = task->tk_status; |
| 2095 | 2102 | ||
| @@ -2099,8 +2106,17 @@ call_connect_status(struct rpc_task *task) | |||
| 2099 | } | 2106 | } |
| 2100 | 2107 | ||
| 2101 | dprint_status(task); | 2108 | dprint_status(task); |
| 2102 | |||
| 2103 | trace_rpc_connect_status(task); | 2109 | trace_rpc_connect_status(task); |
| 2110 | |||
| 2111 | if (task->tk_status == 0) { | ||
| 2112 | clnt->cl_stats->netreconn++; | ||
| 2113 | goto out_next; | ||
| 2114 | } | ||
| 2115 | if (xprt_connected(xprt)) { | ||
| 2116 | task->tk_status = 0; | ||
| 2117 | goto out_next; | ||
| 2118 | } | ||
| 2119 | |||
| 2104 | task->tk_status = 0; | 2120 | task->tk_status = 0; |
| 2105 | switch (status) { | 2121 | switch (status) { |
| 2106 | case -ECONNREFUSED: | 2122 | case -ECONNREFUSED: |
| @@ -2117,8 +2133,6 @@ call_connect_status(struct rpc_task *task) | |||
| 2117 | case -ENETDOWN: | 2133 | case -ENETDOWN: |
| 2118 | case -ENETUNREACH: | 2134 | case -ENETUNREACH: |
| 2119 | case -EHOSTUNREACH: | 2135 | case -EHOSTUNREACH: |
| 2120 | case -EADDRINUSE: | ||
| 2121 | case -ENOBUFS: | ||
| 2122 | case -EPIPE: | 2136 | case -EPIPE: |
| 2123 | xprt_conditional_disconnect(task->tk_rqstp->rq_xprt, | 2137 | xprt_conditional_disconnect(task->tk_rqstp->rq_xprt, |
| 2124 | task->tk_rqstp->rq_connect_cookie); | 2138 | task->tk_rqstp->rq_connect_cookie); |
| @@ -2127,17 +2141,20 @@ call_connect_status(struct rpc_task *task) | |||
| 2127 | /* retry with existing socket, after a delay */ | 2141 | /* retry with existing socket, after a delay */ |
| 2128 | rpc_delay(task, 3*HZ); | 2142 | rpc_delay(task, 3*HZ); |
| 2129 | /* fall through */ | 2143 | /* fall through */ |
| 2144 | case -EADDRINUSE: | ||
| 2130 | case -ENOTCONN: | 2145 | case -ENOTCONN: |
| 2131 | case -EAGAIN: | 2146 | case -EAGAIN: |
| 2132 | case -ETIMEDOUT: | 2147 | case -ETIMEDOUT: |
| 2133 | goto out_retry; | 2148 | goto out_retry; |
| 2134 | case 0: | 2149 | case -ENOBUFS: |
| 2135 | clnt->cl_stats->netreconn++; | 2150 | rpc_delay(task, HZ >> 2); |
| 2136 | task->tk_action = call_transmit; | 2151 | goto out_retry; |
| 2137 | return; | ||
| 2138 | } | 2152 | } |
| 2139 | rpc_call_rpcerror(task, status); | 2153 | rpc_call_rpcerror(task, status); |
| 2140 | return; | 2154 | return; |
| 2155 | out_next: | ||
| 2156 | task->tk_action = call_transmit; | ||
| 2157 | return; | ||
| 2141 | out_retry: | 2158 | out_retry: |
| 2142 | /* Check for timeouts before looping back to call_bind */ | 2159 | /* Check for timeouts before looping back to call_bind */ |
| 2143 | task->tk_action = call_bind; | 2160 | task->tk_action = call_bind; |
| @@ -2365,7 +2382,7 @@ call_status(struct rpc_task *task) | |||
| 2365 | case -ECONNABORTED: | 2382 | case -ECONNABORTED: |
| 2366 | case -ENOTCONN: | 2383 | case -ENOTCONN: |
| 2367 | rpc_force_rebind(clnt); | 2384 | rpc_force_rebind(clnt); |
| 2368 | /* fall through */ | 2385 | break; |
| 2369 | case -EADDRINUSE: | 2386 | case -EADDRINUSE: |
| 2370 | rpc_delay(task, 3*HZ); | 2387 | rpc_delay(task, 3*HZ); |
| 2371 | /* fall through */ | 2388 | /* fall through */ |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 783748dc5e6f..2e71f5455c6c 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -1408,13 +1408,6 @@ xprt_request_transmit(struct rpc_rqst *req, struct rpc_task *snd_task) | |||
| 1408 | status = -EBADMSG; | 1408 | status = -EBADMSG; |
| 1409 | goto out_dequeue; | 1409 | goto out_dequeue; |
| 1410 | } | 1410 | } |
| 1411 | if (task->tk_ops->rpc_call_prepare_transmit) { | ||
| 1412 | task->tk_ops->rpc_call_prepare_transmit(task, | ||
| 1413 | task->tk_calldata); | ||
| 1414 | status = task->tk_status; | ||
| 1415 | if (status < 0) | ||
| 1416 | goto out_dequeue; | ||
| 1417 | } | ||
| 1418 | if (RPC_SIGNALLED(task)) { | 1411 | if (RPC_SIGNALLED(task)) { |
| 1419 | status = -ERESTARTSYS; | 1412 | status = -ERESTARTSYS; |
| 1420 | goto out_dequeue; | 1413 | goto out_dequeue; |
diff --git a/net/tipc/addr.c b/net/tipc/addr.c index b88d48d00913..0f1eaed1bd1b 100644 --- a/net/tipc/addr.c +++ b/net/tipc/addr.c | |||
| @@ -75,6 +75,7 @@ void tipc_set_node_addr(struct net *net, u32 addr) | |||
| 75 | tipc_set_node_id(net, node_id); | 75 | tipc_set_node_id(net, node_id); |
| 76 | } | 76 | } |
| 77 | tn->trial_addr = addr; | 77 | tn->trial_addr = addr; |
| 78 | tn->addr_trial_end = jiffies; | ||
| 78 | pr_info("32-bit node address hash set to %x\n", addr); | 79 | pr_info("32-bit node address hash set to %x\n", addr); |
| 79 | } | 80 | } |
| 80 | 81 | ||
diff --git a/net/tipc/link.c b/net/tipc/link.c index 66d3a07bc571..c2c5c53cad22 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -106,8 +106,6 @@ struct tipc_stats { | |||
| 106 | * @transmitq: queue for sent, non-acked messages | 106 | * @transmitq: queue for sent, non-acked messages |
| 107 | * @backlogq: queue for messages waiting to be sent | 107 | * @backlogq: queue for messages waiting to be sent |
| 108 | * @snt_nxt: next sequence number to use for outbound messages | 108 | * @snt_nxt: next sequence number to use for outbound messages |
| 109 | * @prev_from: sequence number of most previous retransmission request | ||
| 110 | * @stale_limit: time when repeated identical retransmits must force link reset | ||
| 111 | * @ackers: # of peers that needs to ack each packet before it can be released | 109 | * @ackers: # of peers that needs to ack each packet before it can be released |
| 112 | * @acked: # last packet acked by a certain peer. Used for broadcast. | 110 | * @acked: # last packet acked by a certain peer. Used for broadcast. |
| 113 | * @rcv_nxt: next sequence number to expect for inbound messages | 111 | * @rcv_nxt: next sequence number to expect for inbound messages |
| @@ -164,9 +162,7 @@ struct tipc_link { | |||
| 164 | u16 limit; | 162 | u16 limit; |
| 165 | } backlog[5]; | 163 | } backlog[5]; |
| 166 | u16 snd_nxt; | 164 | u16 snd_nxt; |
| 167 | u16 prev_from; | ||
| 168 | u16 window; | 165 | u16 window; |
| 169 | unsigned long stale_limit; | ||
| 170 | 166 | ||
| 171 | /* Reception */ | 167 | /* Reception */ |
| 172 | u16 rcv_nxt; | 168 | u16 rcv_nxt; |
| @@ -1044,47 +1040,53 @@ static void tipc_link_advance_backlog(struct tipc_link *l, | |||
| 1044 | * link_retransmit_failure() - Detect repeated retransmit failures | 1040 | * link_retransmit_failure() - Detect repeated retransmit failures |
| 1045 | * @l: tipc link sender | 1041 | * @l: tipc link sender |
| 1046 | * @r: tipc link receiver (= l in case of unicast) | 1042 | * @r: tipc link receiver (= l in case of unicast) |
| 1047 | * @from: seqno of the 1st packet in retransmit request | ||
| 1048 | * @rc: returned code | 1043 | * @rc: returned code |
| 1049 | * | 1044 | * |
| 1050 | * Return: true if the repeated retransmit failures happens, otherwise | 1045 | * Return: true if the repeated retransmit failures happens, otherwise |
| 1051 | * false | 1046 | * false |
| 1052 | */ | 1047 | */ |
| 1053 | static bool link_retransmit_failure(struct tipc_link *l, struct tipc_link *r, | 1048 | static bool link_retransmit_failure(struct tipc_link *l, struct tipc_link *r, |
| 1054 | u16 from, int *rc) | 1049 | int *rc) |
| 1055 | { | 1050 | { |
| 1056 | struct sk_buff *skb = skb_peek(&l->transmq); | 1051 | struct sk_buff *skb = skb_peek(&l->transmq); |
| 1057 | struct tipc_msg *hdr; | 1052 | struct tipc_msg *hdr; |
| 1058 | 1053 | ||
| 1059 | if (!skb) | 1054 | if (!skb) |
| 1060 | return false; | 1055 | return false; |
| 1061 | hdr = buf_msg(skb); | ||
| 1062 | 1056 | ||
| 1063 | /* Detect repeated retransmit failures on same packet */ | 1057 | if (!TIPC_SKB_CB(skb)->retr_cnt) |
| 1064 | if (r->prev_from != from) { | 1058 | return false; |
| 1065 | r->prev_from = from; | ||
| 1066 | r->stale_limit = jiffies + msecs_to_jiffies(r->tolerance); | ||
| 1067 | } else if (time_after(jiffies, r->stale_limit)) { | ||
| 1068 | pr_warn("Retransmission failure on link <%s>\n", l->name); | ||
| 1069 | link_print(l, "State of link "); | ||
| 1070 | pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n", | ||
| 1071 | msg_user(hdr), msg_type(hdr), msg_size(hdr), | ||
| 1072 | msg_errcode(hdr)); | ||
| 1073 | pr_info("sqno %u, prev: %x, src: %x\n", | ||
| 1074 | msg_seqno(hdr), msg_prevnode(hdr), msg_orignode(hdr)); | ||
| 1075 | |||
| 1076 | trace_tipc_list_dump(&l->transmq, true, "retrans failure!"); | ||
| 1077 | trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!"); | ||
| 1078 | trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!"); | ||
| 1079 | 1059 | ||
| 1080 | if (link_is_bc_sndlink(l)) | 1060 | if (!time_after(jiffies, TIPC_SKB_CB(skb)->retr_stamp + |
| 1081 | *rc = TIPC_LINK_DOWN_EVT; | 1061 | msecs_to_jiffies(r->tolerance))) |
| 1062 | return false; | ||
| 1063 | |||
| 1064 | hdr = buf_msg(skb); | ||
| 1065 | if (link_is_bc_sndlink(l) && !less(r->acked, msg_seqno(hdr))) | ||
| 1066 | return false; | ||
| 1082 | 1067 | ||
| 1068 | pr_warn("Retransmission failure on link <%s>\n", l->name); | ||
| 1069 | link_print(l, "State of link "); | ||
| 1070 | pr_info("Failed msg: usr %u, typ %u, len %u, err %u\n", | ||
| 1071 | msg_user(hdr), msg_type(hdr), msg_size(hdr), msg_errcode(hdr)); | ||
| 1072 | pr_info("sqno %u, prev: %x, dest: %x\n", | ||
| 1073 | msg_seqno(hdr), msg_prevnode(hdr), msg_destnode(hdr)); | ||
| 1074 | pr_info("retr_stamp %d, retr_cnt %d\n", | ||
| 1075 | jiffies_to_msecs(TIPC_SKB_CB(skb)->retr_stamp), | ||
| 1076 | TIPC_SKB_CB(skb)->retr_cnt); | ||
| 1077 | |||
| 1078 | trace_tipc_list_dump(&l->transmq, true, "retrans failure!"); | ||
| 1079 | trace_tipc_link_dump(l, TIPC_DUMP_NONE, "retrans failure!"); | ||
| 1080 | trace_tipc_link_dump(r, TIPC_DUMP_NONE, "retrans failure!"); | ||
| 1081 | |||
| 1082 | if (link_is_bc_sndlink(l)) { | ||
| 1083 | r->state = LINK_RESET; | ||
| 1084 | *rc = TIPC_LINK_DOWN_EVT; | ||
| 1085 | } else { | ||
| 1083 | *rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); | 1086 | *rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT); |
| 1084 | return true; | ||
| 1085 | } | 1087 | } |
| 1086 | 1088 | ||
| 1087 | return false; | 1089 | return true; |
| 1088 | } | 1090 | } |
| 1089 | 1091 | ||
| 1090 | /* tipc_link_bc_retrans() - retransmit zero or more packets | 1092 | /* tipc_link_bc_retrans() - retransmit zero or more packets |
| @@ -1110,7 +1112,7 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r, | |||
| 1110 | 1112 | ||
| 1111 | trace_tipc_link_retrans(r, from, to, &l->transmq); | 1113 | trace_tipc_link_retrans(r, from, to, &l->transmq); |
| 1112 | 1114 | ||
| 1113 | if (link_retransmit_failure(l, r, from, &rc)) | 1115 | if (link_retransmit_failure(l, r, &rc)) |
| 1114 | return rc; | 1116 | return rc; |
| 1115 | 1117 | ||
| 1116 | skb_queue_walk(&l->transmq, skb) { | 1118 | skb_queue_walk(&l->transmq, skb) { |
| @@ -1119,11 +1121,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r, | |||
| 1119 | continue; | 1121 | continue; |
| 1120 | if (more(msg_seqno(hdr), to)) | 1122 | if (more(msg_seqno(hdr), to)) |
| 1121 | break; | 1123 | break; |
| 1122 | if (link_is_bc_sndlink(l)) { | 1124 | |
| 1123 | if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr)) | 1125 | if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr)) |
| 1124 | continue; | 1126 | continue; |
| 1125 | TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM; | 1127 | TIPC_SKB_CB(skb)->nxt_retr = TIPC_BC_RETR_LIM; |
| 1126 | } | ||
| 1127 | _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC); | 1128 | _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, GFP_ATOMIC); |
| 1128 | if (!_skb) | 1129 | if (!_skb) |
| 1129 | return 0; | 1130 | return 0; |
| @@ -1133,6 +1134,10 @@ static int tipc_link_bc_retrans(struct tipc_link *l, struct tipc_link *r, | |||
| 1133 | _skb->priority = TC_PRIO_CONTROL; | 1134 | _skb->priority = TC_PRIO_CONTROL; |
| 1134 | __skb_queue_tail(xmitq, _skb); | 1135 | __skb_queue_tail(xmitq, _skb); |
| 1135 | l->stats.retransmitted++; | 1136 | l->stats.retransmitted++; |
| 1137 | |||
| 1138 | /* Increase actual retrans counter & mark first time */ | ||
| 1139 | if (!TIPC_SKB_CB(skb)->retr_cnt++) | ||
| 1140 | TIPC_SKB_CB(skb)->retr_stamp = jiffies; | ||
| 1136 | } | 1141 | } |
| 1137 | return 0; | 1142 | return 0; |
| 1138 | } | 1143 | } |
| @@ -1357,12 +1362,10 @@ static int tipc_link_advance_transmq(struct tipc_link *l, u16 acked, u16 gap, | |||
| 1357 | struct tipc_msg *hdr; | 1362 | struct tipc_msg *hdr; |
| 1358 | u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1; | 1363 | u16 bc_ack = l->bc_rcvlink->rcv_nxt - 1; |
| 1359 | u16 ack = l->rcv_nxt - 1; | 1364 | u16 ack = l->rcv_nxt - 1; |
| 1365 | bool passed = false; | ||
| 1360 | u16 seqno, n = 0; | 1366 | u16 seqno, n = 0; |
| 1361 | int rc = 0; | 1367 | int rc = 0; |
| 1362 | 1368 | ||
| 1363 | if (gap && link_retransmit_failure(l, l, acked + 1, &rc)) | ||
| 1364 | return rc; | ||
| 1365 | |||
| 1366 | skb_queue_walk_safe(&l->transmq, skb, tmp) { | 1369 | skb_queue_walk_safe(&l->transmq, skb, tmp) { |
| 1367 | seqno = buf_seqno(skb); | 1370 | seqno = buf_seqno(skb); |
| 1368 | 1371 | ||
| @@ -1372,12 +1375,17 @@ next_gap_ack: | |||
| 1372 | __skb_unlink(skb, &l->transmq); | 1375 | __skb_unlink(skb, &l->transmq); |
| 1373 | kfree_skb(skb); | 1376 | kfree_skb(skb); |
| 1374 | } else if (less_eq(seqno, acked + gap)) { | 1377 | } else if (less_eq(seqno, acked + gap)) { |
| 1375 | /* retransmit skb */ | 1378 | /* First, check if repeated retrans failures occurs? */ |
| 1379 | if (!passed && link_retransmit_failure(l, l, &rc)) | ||
| 1380 | return rc; | ||
| 1381 | passed = true; | ||
| 1382 | |||
| 1383 | /* retransmit skb if unrestricted*/ | ||
| 1376 | if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr)) | 1384 | if (time_before(jiffies, TIPC_SKB_CB(skb)->nxt_retr)) |
| 1377 | continue; | 1385 | continue; |
| 1378 | TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME; | 1386 | TIPC_SKB_CB(skb)->nxt_retr = TIPC_UC_RETR_TIME; |
| 1379 | 1387 | _skb = __pskb_copy(skb, LL_MAX_HEADER + MIN_H_SIZE, | |
| 1380 | _skb = __pskb_copy(skb, MIN_H_SIZE, GFP_ATOMIC); | 1388 | GFP_ATOMIC); |
| 1381 | if (!_skb) | 1389 | if (!_skb) |
| 1382 | continue; | 1390 | continue; |
| 1383 | hdr = buf_msg(_skb); | 1391 | hdr = buf_msg(_skb); |
| @@ -1386,6 +1394,10 @@ next_gap_ack: | |||
| 1386 | _skb->priority = TC_PRIO_CONTROL; | 1394 | _skb->priority = TC_PRIO_CONTROL; |
| 1387 | __skb_queue_tail(xmitq, _skb); | 1395 | __skb_queue_tail(xmitq, _skb); |
| 1388 | l->stats.retransmitted++; | 1396 | l->stats.retransmitted++; |
| 1397 | |||
| 1398 | /* Increase actual retrans counter & mark first time */ | ||
| 1399 | if (!TIPC_SKB_CB(skb)->retr_cnt++) | ||
| 1400 | TIPC_SKB_CB(skb)->retr_stamp = jiffies; | ||
| 1389 | } else { | 1401 | } else { |
| 1390 | /* retry with Gap ACK blocks if any */ | 1402 | /* retry with Gap ACK blocks if any */ |
| 1391 | if (!ga || n >= ga->gack_cnt) | 1403 | if (!ga || n >= ga->gack_cnt) |
| @@ -2577,7 +2589,7 @@ int tipc_link_dump(struct tipc_link *l, u16 dqueues, char *buf) | |||
| 2577 | i += scnprintf(buf + i, sz - i, " %x", l->peer_caps); | 2589 | i += scnprintf(buf + i, sz - i, " %x", l->peer_caps); |
| 2578 | i += scnprintf(buf + i, sz - i, " %u", l->silent_intv_cnt); | 2590 | i += scnprintf(buf + i, sz - i, " %u", l->silent_intv_cnt); |
| 2579 | i += scnprintf(buf + i, sz - i, " %u", l->rst_cnt); | 2591 | i += scnprintf(buf + i, sz - i, " %u", l->rst_cnt); |
| 2580 | i += scnprintf(buf + i, sz - i, " %u", l->prev_from); | 2592 | i += scnprintf(buf + i, sz - i, " %u", 0); |
| 2581 | i += scnprintf(buf + i, sz - i, " %u", 0); | 2593 | i += scnprintf(buf + i, sz - i, " %u", 0); |
| 2582 | i += scnprintf(buf + i, sz - i, " %u", l->acked); | 2594 | i += scnprintf(buf + i, sz - i, " %u", l->acked); |
| 2583 | 2595 | ||
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index da509f0eb9ca..d7ebc9e955f6 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
| @@ -102,13 +102,15 @@ struct plist; | |||
| 102 | #define TIPC_MEDIA_INFO_OFFSET 5 | 102 | #define TIPC_MEDIA_INFO_OFFSET 5 |
| 103 | 103 | ||
| 104 | struct tipc_skb_cb { | 104 | struct tipc_skb_cb { |
| 105 | u32 bytes_read; | ||
| 106 | u32 orig_member; | ||
| 107 | struct sk_buff *tail; | 105 | struct sk_buff *tail; |
| 108 | unsigned long nxt_retr; | 106 | unsigned long nxt_retr; |
| 109 | bool validated; | 107 | unsigned long retr_stamp; |
| 108 | u32 bytes_read; | ||
| 109 | u32 orig_member; | ||
| 110 | u16 chain_imp; | 110 | u16 chain_imp; |
| 111 | u16 ackers; | 111 | u16 ackers; |
| 112 | u16 retr_cnt; | ||
| 113 | bool validated; | ||
| 112 | }; | 114 | }; |
| 113 | 115 | ||
| 114 | #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) | 116 | #define TIPC_SKB_CB(__skb) ((struct tipc_skb_cb *)&((__skb)->cb[0])) |
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index d86030ef1232..e135d4e11231 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c | |||
| @@ -55,6 +55,7 @@ struct tipc_nl_compat_msg { | |||
| 55 | int rep_type; | 55 | int rep_type; |
| 56 | int rep_size; | 56 | int rep_size; |
| 57 | int req_type; | 57 | int req_type; |
| 58 | int req_size; | ||
| 58 | struct net *net; | 59 | struct net *net; |
| 59 | struct sk_buff *rep; | 60 | struct sk_buff *rep; |
| 60 | struct tlv_desc *req; | 61 | struct tlv_desc *req; |
| @@ -257,7 +258,8 @@ static int tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd, | |||
| 257 | int err; | 258 | int err; |
| 258 | struct sk_buff *arg; | 259 | struct sk_buff *arg; |
| 259 | 260 | ||
| 260 | if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type)) | 261 | if (msg->req_type && (!msg->req_size || |
| 262 | !TLV_CHECK_TYPE(msg->req, msg->req_type))) | ||
| 261 | return -EINVAL; | 263 | return -EINVAL; |
| 262 | 264 | ||
| 263 | msg->rep = tipc_tlv_alloc(msg->rep_size); | 265 | msg->rep = tipc_tlv_alloc(msg->rep_size); |
| @@ -354,7 +356,8 @@ static int tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd, | |||
| 354 | { | 356 | { |
| 355 | int err; | 357 | int err; |
| 356 | 358 | ||
| 357 | if (msg->req_type && !TLV_CHECK_TYPE(msg->req, msg->req_type)) | 359 | if (msg->req_type && (!msg->req_size || |
| 360 | !TLV_CHECK_TYPE(msg->req, msg->req_type))) | ||
| 358 | return -EINVAL; | 361 | return -EINVAL; |
| 359 | 362 | ||
| 360 | err = __tipc_nl_compat_doit(cmd, msg); | 363 | err = __tipc_nl_compat_doit(cmd, msg); |
| @@ -1278,8 +1281,8 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info) | |||
| 1278 | goto send; | 1281 | goto send; |
| 1279 | } | 1282 | } |
| 1280 | 1283 | ||
| 1281 | len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN); | 1284 | msg.req_size = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN); |
| 1282 | if (!len || !TLV_OK(msg.req, len)) { | 1285 | if (msg.req_size && !TLV_OK(msg.req, msg.req_size)) { |
| 1283 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); | 1286 | msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED); |
| 1284 | err = -EOPNOTSUPP; | 1287 | err = -EOPNOTSUPP; |
| 1285 | goto send; | 1288 | goto send; |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index dd8537f988c4..83ae41d7e554 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -485,9 +485,8 @@ static int tipc_sk_create(struct net *net, struct socket *sock, | |||
| 485 | tsk_set_unreturnable(tsk, true); | 485 | tsk_set_unreturnable(tsk, true); |
| 486 | if (sock->type == SOCK_DGRAM) | 486 | if (sock->type == SOCK_DGRAM) |
| 487 | tsk_set_unreliable(tsk, true); | 487 | tsk_set_unreliable(tsk, true); |
| 488 | __skb_queue_head_init(&tsk->mc_method.deferredq); | ||
| 489 | } | 488 | } |
| 490 | 489 | __skb_queue_head_init(&tsk->mc_method.deferredq); | |
| 491 | trace_tipc_sk_create(sk, NULL, TIPC_DUMP_NONE, " "); | 490 | trace_tipc_sk_create(sk, NULL, TIPC_DUMP_NONE, " "); |
| 492 | return 0; | 491 | return 0; |
| 493 | } | 492 | } |
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c index 7c0b2b778703..43922d86e510 100644 --- a/net/tls/tls_device.c +++ b/net/tls/tls_device.c | |||
| @@ -373,9 +373,9 @@ static int tls_push_data(struct sock *sk, | |||
| 373 | struct tls_context *tls_ctx = tls_get_ctx(sk); | 373 | struct tls_context *tls_ctx = tls_get_ctx(sk); |
| 374 | struct tls_prot_info *prot = &tls_ctx->prot_info; | 374 | struct tls_prot_info *prot = &tls_ctx->prot_info; |
| 375 | struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx); | 375 | struct tls_offload_context_tx *ctx = tls_offload_ctx_tx(tls_ctx); |
| 376 | int tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST; | ||
| 377 | int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE); | 376 | int more = flags & (MSG_SENDPAGE_NOTLAST | MSG_MORE); |
| 378 | struct tls_record_info *record = ctx->open_record; | 377 | struct tls_record_info *record = ctx->open_record; |
| 378 | int tls_push_record_flags; | ||
| 379 | struct page_frag *pfrag; | 379 | struct page_frag *pfrag; |
| 380 | size_t orig_size = size; | 380 | size_t orig_size = size; |
| 381 | u32 max_open_record_len; | 381 | u32 max_open_record_len; |
| @@ -390,6 +390,9 @@ static int tls_push_data(struct sock *sk, | |||
| 390 | if (sk->sk_err) | 390 | if (sk->sk_err) |
| 391 | return -sk->sk_err; | 391 | return -sk->sk_err; |
| 392 | 392 | ||
| 393 | flags |= MSG_SENDPAGE_DECRYPTED; | ||
| 394 | tls_push_record_flags = flags | MSG_SENDPAGE_NOTLAST; | ||
| 395 | |||
| 393 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | 396 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); |
| 394 | if (tls_is_partially_sent_record(tls_ctx)) { | 397 | if (tls_is_partially_sent_record(tls_ctx)) { |
| 395 | rc = tls_push_partial_record(sk, tls_ctx, flags); | 398 | rc = tls_push_partial_record(sk, tls_ctx, flags); |
| @@ -576,7 +579,9 @@ void tls_device_write_space(struct sock *sk, struct tls_context *ctx) | |||
| 576 | gfp_t sk_allocation = sk->sk_allocation; | 579 | gfp_t sk_allocation = sk->sk_allocation; |
| 577 | 580 | ||
| 578 | sk->sk_allocation = GFP_ATOMIC; | 581 | sk->sk_allocation = GFP_ATOMIC; |
| 579 | tls_push_partial_record(sk, ctx, MSG_DONTWAIT | MSG_NOSIGNAL); | 582 | tls_push_partial_record(sk, ctx, |
| 583 | MSG_DONTWAIT | MSG_NOSIGNAL | | ||
| 584 | MSG_SENDPAGE_DECRYPTED); | ||
| 580 | sk->sk_allocation = sk_allocation; | 585 | sk->sk_allocation = sk_allocation; |
| 581 | } | 586 | } |
| 582 | } | 587 | } |
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c index 4674e57e66b0..43252a801c3f 100644 --- a/net/tls/tls_main.c +++ b/net/tls/tls_main.c | |||
| @@ -261,24 +261,9 @@ void tls_ctx_free(struct tls_context *ctx) | |||
| 261 | kfree(ctx); | 261 | kfree(ctx); |
| 262 | } | 262 | } |
| 263 | 263 | ||
| 264 | static void tls_sk_proto_close(struct sock *sk, long timeout) | 264 | static void tls_sk_proto_cleanup(struct sock *sk, |
| 265 | struct tls_context *ctx, long timeo) | ||
| 265 | { | 266 | { |
| 266 | struct tls_context *ctx = tls_get_ctx(sk); | ||
| 267 | long timeo = sock_sndtimeo(sk, 0); | ||
| 268 | void (*sk_proto_close)(struct sock *sk, long timeout); | ||
| 269 | bool free_ctx = false; | ||
| 270 | |||
| 271 | lock_sock(sk); | ||
| 272 | sk_proto_close = ctx->sk_proto_close; | ||
| 273 | |||
| 274 | if (ctx->tx_conf == TLS_HW_RECORD && ctx->rx_conf == TLS_HW_RECORD) | ||
| 275 | goto skip_tx_cleanup; | ||
| 276 | |||
| 277 | if (ctx->tx_conf == TLS_BASE && ctx->rx_conf == TLS_BASE) { | ||
| 278 | free_ctx = true; | ||
| 279 | goto skip_tx_cleanup; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (unlikely(sk->sk_write_pending) && | 267 | if (unlikely(sk->sk_write_pending) && |
| 283 | !wait_on_pending_writer(sk, &timeo)) | 268 | !wait_on_pending_writer(sk, &timeo)) |
| 284 | tls_handle_open_record(sk, 0); | 269 | tls_handle_open_record(sk, 0); |
| @@ -287,7 +272,7 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) | |||
| 287 | if (ctx->tx_conf == TLS_SW) { | 272 | if (ctx->tx_conf == TLS_SW) { |
| 288 | kfree(ctx->tx.rec_seq); | 273 | kfree(ctx->tx.rec_seq); |
| 289 | kfree(ctx->tx.iv); | 274 | kfree(ctx->tx.iv); |
| 290 | tls_sw_free_resources_tx(sk); | 275 | tls_sw_release_resources_tx(sk); |
| 291 | #ifdef CONFIG_TLS_DEVICE | 276 | #ifdef CONFIG_TLS_DEVICE |
| 292 | } else if (ctx->tx_conf == TLS_HW) { | 277 | } else if (ctx->tx_conf == TLS_HW) { |
| 293 | tls_device_free_resources_tx(sk); | 278 | tls_device_free_resources_tx(sk); |
| @@ -295,26 +280,46 @@ static void tls_sk_proto_close(struct sock *sk, long timeout) | |||
| 295 | } | 280 | } |
| 296 | 281 | ||
| 297 | if (ctx->rx_conf == TLS_SW) | 282 | if (ctx->rx_conf == TLS_SW) |
| 298 | tls_sw_free_resources_rx(sk); | 283 | tls_sw_release_resources_rx(sk); |
| 299 | 284 | ||
| 300 | #ifdef CONFIG_TLS_DEVICE | 285 | #ifdef CONFIG_TLS_DEVICE |
| 301 | if (ctx->rx_conf == TLS_HW) | 286 | if (ctx->rx_conf == TLS_HW) |
| 302 | tls_device_offload_cleanup_rx(sk); | 287 | tls_device_offload_cleanup_rx(sk); |
| 303 | |||
| 304 | if (ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW) { | ||
| 305 | #else | ||
| 306 | { | ||
| 307 | #endif | 288 | #endif |
| 308 | tls_ctx_free(ctx); | 289 | } |
| 309 | ctx = NULL; | ||
| 310 | } | ||
| 311 | 290 | ||
| 312 | skip_tx_cleanup: | 291 | static void tls_sk_proto_close(struct sock *sk, long timeout) |
| 292 | { | ||
| 293 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
| 294 | struct tls_context *ctx = tls_get_ctx(sk); | ||
| 295 | long timeo = sock_sndtimeo(sk, 0); | ||
| 296 | bool free_ctx; | ||
| 297 | |||
| 298 | if (ctx->tx_conf == TLS_SW) | ||
| 299 | tls_sw_cancel_work_tx(ctx); | ||
| 300 | |||
| 301 | lock_sock(sk); | ||
| 302 | free_ctx = ctx->tx_conf != TLS_HW && ctx->rx_conf != TLS_HW; | ||
| 303 | |||
| 304 | if (ctx->tx_conf != TLS_BASE || ctx->rx_conf != TLS_BASE) | ||
| 305 | tls_sk_proto_cleanup(sk, ctx, timeo); | ||
| 306 | |||
| 307 | write_lock_bh(&sk->sk_callback_lock); | ||
| 308 | if (free_ctx) | ||
| 309 | icsk->icsk_ulp_data = NULL; | ||
| 310 | sk->sk_prot = ctx->sk_proto; | ||
| 311 | if (sk->sk_write_space == tls_write_space) | ||
| 312 | sk->sk_write_space = ctx->sk_write_space; | ||
| 313 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 313 | release_sock(sk); | 314 | release_sock(sk); |
| 314 | sk_proto_close(sk, timeout); | 315 | if (ctx->tx_conf == TLS_SW) |
| 315 | /* free ctx for TLS_HW_RECORD, used by tcp_set_state | 316 | tls_sw_free_ctx_tx(ctx); |
| 316 | * for sk->sk_prot->unhash [tls_hw_unhash] | 317 | if (ctx->rx_conf == TLS_SW || ctx->rx_conf == TLS_HW) |
| 317 | */ | 318 | tls_sw_strparser_done(ctx); |
| 319 | if (ctx->rx_conf == TLS_SW) | ||
| 320 | tls_sw_free_ctx_rx(ctx); | ||
| 321 | ctx->sk_proto_close(sk, timeout); | ||
| 322 | |||
| 318 | if (free_ctx) | 323 | if (free_ctx) |
| 319 | tls_ctx_free(ctx); | 324 | tls_ctx_free(ctx); |
| 320 | } | 325 | } |
| @@ -526,6 +531,8 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||
| 526 | { | 531 | { |
| 527 | #endif | 532 | #endif |
| 528 | rc = tls_set_sw_offload(sk, ctx, 1); | 533 | rc = tls_set_sw_offload(sk, ctx, 1); |
| 534 | if (rc) | ||
| 535 | goto err_crypto_info; | ||
| 529 | conf = TLS_SW; | 536 | conf = TLS_SW; |
| 530 | } | 537 | } |
| 531 | } else { | 538 | } else { |
| @@ -537,13 +544,13 @@ static int do_tls_setsockopt_conf(struct sock *sk, char __user *optval, | |||
| 537 | { | 544 | { |
| 538 | #endif | 545 | #endif |
| 539 | rc = tls_set_sw_offload(sk, ctx, 0); | 546 | rc = tls_set_sw_offload(sk, ctx, 0); |
| 547 | if (rc) | ||
| 548 | goto err_crypto_info; | ||
| 540 | conf = TLS_SW; | 549 | conf = TLS_SW; |
| 541 | } | 550 | } |
| 551 | tls_sw_strparser_arm(sk, ctx); | ||
| 542 | } | 552 | } |
| 543 | 553 | ||
| 544 | if (rc) | ||
| 545 | goto err_crypto_info; | ||
| 546 | |||
| 547 | if (tx) | 554 | if (tx) |
| 548 | ctx->tx_conf = conf; | 555 | ctx->tx_conf = conf; |
| 549 | else | 556 | else |
| @@ -607,6 +614,7 @@ static struct tls_context *create_ctx(struct sock *sk) | |||
| 607 | ctx->setsockopt = sk->sk_prot->setsockopt; | 614 | ctx->setsockopt = sk->sk_prot->setsockopt; |
| 608 | ctx->getsockopt = sk->sk_prot->getsockopt; | 615 | ctx->getsockopt = sk->sk_prot->getsockopt; |
| 609 | ctx->sk_proto_close = sk->sk_prot->close; | 616 | ctx->sk_proto_close = sk->sk_prot->close; |
| 617 | ctx->unhash = sk->sk_prot->unhash; | ||
| 610 | return ctx; | 618 | return ctx; |
| 611 | } | 619 | } |
| 612 | 620 | ||
| @@ -764,7 +772,6 @@ static void build_protos(struct proto prot[TLS_NUM_CONFIG][TLS_NUM_CONFIG], | |||
| 764 | prot[TLS_HW_RECORD][TLS_HW_RECORD] = *base; | 772 | prot[TLS_HW_RECORD][TLS_HW_RECORD] = *base; |
| 765 | prot[TLS_HW_RECORD][TLS_HW_RECORD].hash = tls_hw_hash; | 773 | prot[TLS_HW_RECORD][TLS_HW_RECORD].hash = tls_hw_hash; |
| 766 | prot[TLS_HW_RECORD][TLS_HW_RECORD].unhash = tls_hw_unhash; | 774 | prot[TLS_HW_RECORD][TLS_HW_RECORD].unhash = tls_hw_unhash; |
| 767 | prot[TLS_HW_RECORD][TLS_HW_RECORD].close = tls_sk_proto_close; | ||
| 768 | } | 775 | } |
| 769 | 776 | ||
| 770 | static int tls_init(struct sock *sk) | 777 | static int tls_init(struct sock *sk) |
| @@ -773,7 +780,7 @@ static int tls_init(struct sock *sk) | |||
| 773 | int rc = 0; | 780 | int rc = 0; |
| 774 | 781 | ||
| 775 | if (tls_hw_prot(sk)) | 782 | if (tls_hw_prot(sk)) |
| 776 | goto out; | 783 | return 0; |
| 777 | 784 | ||
| 778 | /* The TLS ulp is currently supported only for TCP sockets | 785 | /* The TLS ulp is currently supported only for TCP sockets |
| 779 | * in ESTABLISHED state. | 786 | * in ESTABLISHED state. |
| @@ -784,21 +791,38 @@ static int tls_init(struct sock *sk) | |||
| 784 | if (sk->sk_state != TCP_ESTABLISHED) | 791 | if (sk->sk_state != TCP_ESTABLISHED) |
| 785 | return -ENOTSUPP; | 792 | return -ENOTSUPP; |
| 786 | 793 | ||
| 794 | tls_build_proto(sk); | ||
| 795 | |||
| 787 | /* allocate tls context */ | 796 | /* allocate tls context */ |
| 797 | write_lock_bh(&sk->sk_callback_lock); | ||
| 788 | ctx = create_ctx(sk); | 798 | ctx = create_ctx(sk); |
| 789 | if (!ctx) { | 799 | if (!ctx) { |
| 790 | rc = -ENOMEM; | 800 | rc = -ENOMEM; |
| 791 | goto out; | 801 | goto out; |
| 792 | } | 802 | } |
| 793 | 803 | ||
| 794 | tls_build_proto(sk); | ||
| 795 | ctx->tx_conf = TLS_BASE; | 804 | ctx->tx_conf = TLS_BASE; |
| 796 | ctx->rx_conf = TLS_BASE; | 805 | ctx->rx_conf = TLS_BASE; |
| 806 | ctx->sk_proto = sk->sk_prot; | ||
| 797 | update_sk_prot(sk, ctx); | 807 | update_sk_prot(sk, ctx); |
| 798 | out: | 808 | out: |
| 809 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 799 | return rc; | 810 | return rc; |
| 800 | } | 811 | } |
| 801 | 812 | ||
| 813 | static void tls_update(struct sock *sk, struct proto *p) | ||
| 814 | { | ||
| 815 | struct tls_context *ctx; | ||
| 816 | |||
| 817 | ctx = tls_get_ctx(sk); | ||
| 818 | if (likely(ctx)) { | ||
| 819 | ctx->sk_proto_close = p->close; | ||
| 820 | ctx->sk_proto = p; | ||
| 821 | } else { | ||
| 822 | sk->sk_prot = p; | ||
| 823 | } | ||
| 824 | } | ||
| 825 | |||
| 802 | void tls_register_device(struct tls_device *device) | 826 | void tls_register_device(struct tls_device *device) |
| 803 | { | 827 | { |
| 804 | spin_lock_bh(&device_spinlock); | 828 | spin_lock_bh(&device_spinlock); |
| @@ -819,6 +843,7 @@ static struct tcp_ulp_ops tcp_tls_ulp_ops __read_mostly = { | |||
| 819 | .name = "tls", | 843 | .name = "tls", |
| 820 | .owner = THIS_MODULE, | 844 | .owner = THIS_MODULE, |
| 821 | .init = tls_init, | 845 | .init = tls_init, |
| 846 | .update = tls_update, | ||
| 822 | }; | 847 | }; |
| 823 | 848 | ||
| 824 | static int __init tls_register(void) | 849 | static int __init tls_register(void) |
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 53b4ad94e74a..91d21b048a9b 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c | |||
| @@ -2054,7 +2054,16 @@ static void tls_data_ready(struct sock *sk) | |||
| 2054 | } | 2054 | } |
| 2055 | } | 2055 | } |
| 2056 | 2056 | ||
| 2057 | void tls_sw_free_resources_tx(struct sock *sk) | 2057 | void tls_sw_cancel_work_tx(struct tls_context *tls_ctx) |
| 2058 | { | ||
| 2059 | struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); | ||
| 2060 | |||
| 2061 | set_bit(BIT_TX_CLOSING, &ctx->tx_bitmask); | ||
| 2062 | set_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask); | ||
| 2063 | cancel_delayed_work_sync(&ctx->tx_work.work); | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | void tls_sw_release_resources_tx(struct sock *sk) | ||
| 2058 | { | 2067 | { |
| 2059 | struct tls_context *tls_ctx = tls_get_ctx(sk); | 2068 | struct tls_context *tls_ctx = tls_get_ctx(sk); |
| 2060 | struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); | 2069 | struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); |
| @@ -2065,11 +2074,6 @@ void tls_sw_free_resources_tx(struct sock *sk) | |||
| 2065 | if (atomic_read(&ctx->encrypt_pending)) | 2074 | if (atomic_read(&ctx->encrypt_pending)) |
| 2066 | crypto_wait_req(-EINPROGRESS, &ctx->async_wait); | 2075 | crypto_wait_req(-EINPROGRESS, &ctx->async_wait); |
| 2067 | 2076 | ||
| 2068 | release_sock(sk); | ||
| 2069 | cancel_delayed_work_sync(&ctx->tx_work.work); | ||
| 2070 | lock_sock(sk); | ||
| 2071 | |||
| 2072 | /* Tx whatever records we can transmit and abandon the rest */ | ||
| 2073 | tls_tx_records(sk, -1); | 2077 | tls_tx_records(sk, -1); |
| 2074 | 2078 | ||
| 2075 | /* Free up un-sent records in tx_list. First, free | 2079 | /* Free up un-sent records in tx_list. First, free |
| @@ -2092,6 +2096,11 @@ void tls_sw_free_resources_tx(struct sock *sk) | |||
| 2092 | 2096 | ||
| 2093 | crypto_free_aead(ctx->aead_send); | 2097 | crypto_free_aead(ctx->aead_send); |
| 2094 | tls_free_open_rec(sk); | 2098 | tls_free_open_rec(sk); |
| 2099 | } | ||
| 2100 | |||
| 2101 | void tls_sw_free_ctx_tx(struct tls_context *tls_ctx) | ||
| 2102 | { | ||
| 2103 | struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); | ||
| 2095 | 2104 | ||
| 2096 | kfree(ctx); | 2105 | kfree(ctx); |
| 2097 | } | 2106 | } |
| @@ -2110,25 +2119,40 @@ void tls_sw_release_resources_rx(struct sock *sk) | |||
| 2110 | skb_queue_purge(&ctx->rx_list); | 2119 | skb_queue_purge(&ctx->rx_list); |
| 2111 | crypto_free_aead(ctx->aead_recv); | 2120 | crypto_free_aead(ctx->aead_recv); |
| 2112 | strp_stop(&ctx->strp); | 2121 | strp_stop(&ctx->strp); |
| 2113 | write_lock_bh(&sk->sk_callback_lock); | 2122 | /* If tls_sw_strparser_arm() was not called (cleanup paths) |
| 2114 | sk->sk_data_ready = ctx->saved_data_ready; | 2123 | * we still want to strp_stop(), but sk->sk_data_ready was |
| 2115 | write_unlock_bh(&sk->sk_callback_lock); | 2124 | * never swapped. |
| 2116 | release_sock(sk); | 2125 | */ |
| 2117 | strp_done(&ctx->strp); | 2126 | if (ctx->saved_data_ready) { |
| 2118 | lock_sock(sk); | 2127 | write_lock_bh(&sk->sk_callback_lock); |
| 2128 | sk->sk_data_ready = ctx->saved_data_ready; | ||
| 2129 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 2130 | } | ||
| 2119 | } | 2131 | } |
| 2120 | } | 2132 | } |
| 2121 | 2133 | ||
| 2122 | void tls_sw_free_resources_rx(struct sock *sk) | 2134 | void tls_sw_strparser_done(struct tls_context *tls_ctx) |
| 2123 | { | 2135 | { |
| 2124 | struct tls_context *tls_ctx = tls_get_ctx(sk); | ||
| 2125 | struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); | 2136 | struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); |
| 2126 | 2137 | ||
| 2127 | tls_sw_release_resources_rx(sk); | 2138 | strp_done(&ctx->strp); |
| 2139 | } | ||
| 2140 | |||
| 2141 | void tls_sw_free_ctx_rx(struct tls_context *tls_ctx) | ||
| 2142 | { | ||
| 2143 | struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx); | ||
| 2128 | 2144 | ||
| 2129 | kfree(ctx); | 2145 | kfree(ctx); |
| 2130 | } | 2146 | } |
| 2131 | 2147 | ||
| 2148 | void tls_sw_free_resources_rx(struct sock *sk) | ||
| 2149 | { | ||
| 2150 | struct tls_context *tls_ctx = tls_get_ctx(sk); | ||
| 2151 | |||
| 2152 | tls_sw_release_resources_rx(sk); | ||
| 2153 | tls_sw_free_ctx_rx(tls_ctx); | ||
| 2154 | } | ||
| 2155 | |||
| 2132 | /* The work handler to transmitt the encrypted records in tx_list */ | 2156 | /* The work handler to transmitt the encrypted records in tx_list */ |
| 2133 | static void tx_work_handler(struct work_struct *work) | 2157 | static void tx_work_handler(struct work_struct *work) |
| 2134 | { | 2158 | { |
| @@ -2137,11 +2161,17 @@ static void tx_work_handler(struct work_struct *work) | |||
| 2137 | struct tx_work, work); | 2161 | struct tx_work, work); |
| 2138 | struct sock *sk = tx_work->sk; | 2162 | struct sock *sk = tx_work->sk; |
| 2139 | struct tls_context *tls_ctx = tls_get_ctx(sk); | 2163 | struct tls_context *tls_ctx = tls_get_ctx(sk); |
| 2140 | struct tls_sw_context_tx *ctx = tls_sw_ctx_tx(tls_ctx); | 2164 | struct tls_sw_context_tx *ctx; |
| 2141 | 2165 | ||
| 2142 | if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) | 2166 | if (unlikely(!tls_ctx)) |
| 2143 | return; | 2167 | return; |
| 2144 | 2168 | ||
| 2169 | ctx = tls_sw_ctx_tx(tls_ctx); | ||
| 2170 | if (test_bit(BIT_TX_CLOSING, &ctx->tx_bitmask)) | ||
| 2171 | return; | ||
| 2172 | |||
| 2173 | if (!test_and_clear_bit(BIT_TX_SCHEDULED, &ctx->tx_bitmask)) | ||
| 2174 | return; | ||
| 2145 | lock_sock(sk); | 2175 | lock_sock(sk); |
| 2146 | tls_tx_records(sk, -1); | 2176 | tls_tx_records(sk, -1); |
| 2147 | release_sock(sk); | 2177 | release_sock(sk); |
| @@ -2160,6 +2190,18 @@ void tls_sw_write_space(struct sock *sk, struct tls_context *ctx) | |||
| 2160 | } | 2190 | } |
| 2161 | } | 2191 | } |
| 2162 | 2192 | ||
| 2193 | void tls_sw_strparser_arm(struct sock *sk, struct tls_context *tls_ctx) | ||
| 2194 | { | ||
| 2195 | struct tls_sw_context_rx *rx_ctx = tls_sw_ctx_rx(tls_ctx); | ||
| 2196 | |||
| 2197 | write_lock_bh(&sk->sk_callback_lock); | ||
| 2198 | rx_ctx->saved_data_ready = sk->sk_data_ready; | ||
| 2199 | sk->sk_data_ready = tls_data_ready; | ||
| 2200 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 2201 | |||
| 2202 | strp_check_rcv(&rx_ctx->strp); | ||
| 2203 | } | ||
| 2204 | |||
| 2163 | int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) | 2205 | int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) |
| 2164 | { | 2206 | { |
| 2165 | struct tls_context *tls_ctx = tls_get_ctx(sk); | 2207 | struct tls_context *tls_ctx = tls_get_ctx(sk); |
| @@ -2357,13 +2399,6 @@ int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx, int tx) | |||
| 2357 | cb.parse_msg = tls_read_size; | 2399 | cb.parse_msg = tls_read_size; |
| 2358 | 2400 | ||
| 2359 | strp_init(&sw_ctx_rx->strp, sk, &cb); | 2401 | strp_init(&sw_ctx_rx->strp, sk, &cb); |
| 2360 | |||
| 2361 | write_lock_bh(&sk->sk_callback_lock); | ||
| 2362 | sw_ctx_rx->saved_data_ready = sk->sk_data_ready; | ||
| 2363 | sk->sk_data_ready = tls_data_ready; | ||
| 2364 | write_unlock_bh(&sk->sk_callback_lock); | ||
| 2365 | |||
| 2366 | strp_check_rcv(&sw_ctx_rx->strp); | ||
| 2367 | } | 2402 | } |
| 2368 | 2403 | ||
| 2369 | goto out; | 2404 | goto out; |
diff --git a/net/vmw_vsock/hyperv_transport.c b/net/vmw_vsock/hyperv_transport.c index f2084e3f7aa4..9d864ebeb7b3 100644 --- a/net/vmw_vsock/hyperv_transport.c +++ b/net/vmw_vsock/hyperv_transport.c | |||
| @@ -312,6 +312,11 @@ static void hvs_close_connection(struct vmbus_channel *chan) | |||
| 312 | lock_sock(sk); | 312 | lock_sock(sk); |
| 313 | hvs_do_close_lock_held(vsock_sk(sk), true); | 313 | hvs_do_close_lock_held(vsock_sk(sk), true); |
| 314 | release_sock(sk); | 314 | release_sock(sk); |
| 315 | |||
| 316 | /* Release the refcnt for the channel that's opened in | ||
| 317 | * hvs_open_connection(). | ||
| 318 | */ | ||
| 319 | sock_put(sk); | ||
| 315 | } | 320 | } |
| 316 | 321 | ||
| 317 | static void hvs_open_connection(struct vmbus_channel *chan) | 322 | static void hvs_open_connection(struct vmbus_channel *chan) |
| @@ -407,6 +412,9 @@ static void hvs_open_connection(struct vmbus_channel *chan) | |||
| 407 | } | 412 | } |
| 408 | 413 | ||
| 409 | set_per_channel_state(chan, conn_from_host ? new : sk); | 414 | set_per_channel_state(chan, conn_from_host ? new : sk); |
| 415 | |||
| 416 | /* This reference will be dropped by hvs_close_connection(). */ | ||
| 417 | sock_hold(conn_from_host ? new : sk); | ||
| 410 | vmbus_set_chn_rescind_callback(chan, hvs_close_connection); | 418 | vmbus_set_chn_rescind_callback(chan, hvs_close_connection); |
| 411 | 419 | ||
| 412 | /* Set the pending send size to max packet size to always get | 420 | /* Set the pending send size to max packet size to always get |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 45d9afcff6d5..32b3c719fdfc 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -1410,10 +1410,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
| 1410 | } | 1410 | } |
| 1411 | break; | 1411 | break; |
| 1412 | case NETDEV_PRE_UP: | 1412 | case NETDEV_PRE_UP: |
| 1413 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)) && | 1413 | if (!cfg80211_iftype_allowed(wdev->wiphy, wdev->iftype, |
| 1414 | !(wdev->iftype == NL80211_IFTYPE_AP_VLAN && | 1414 | wdev->use_4addr, 0)) |
| 1415 | rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP && | ||
| 1416 | wdev->use_4addr)) | ||
| 1417 | return notifier_from_errno(-EOPNOTSUPP); | 1415 | return notifier_from_errno(-EOPNOTSUPP); |
| 1418 | 1416 | ||
| 1419 | if (rfkill_blocked(rdev->rfkill)) | 1417 | if (rfkill_blocked(rdev->rfkill)) |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index fc83dd179c1a..fd05ae1437a9 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -3484,9 +3484,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
| 3484 | return err; | 3484 | return err; |
| 3485 | } | 3485 | } |
| 3486 | 3486 | ||
| 3487 | if (!(rdev->wiphy.interface_modes & (1 << type)) && | 3487 | if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0)) |
| 3488 | !(type == NL80211_IFTYPE_AP_VLAN && params.use_4addr && | ||
| 3489 | rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)) | ||
| 3490 | return -EOPNOTSUPP; | 3488 | return -EOPNOTSUPP; |
| 3491 | 3489 | ||
| 3492 | err = nl80211_parse_mon_options(rdev, type, info, ¶ms); | 3490 | err = nl80211_parse_mon_options(rdev, type, info, ¶ms); |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 4831ad745f91..327479ce69f5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -2788,7 +2788,7 @@ static void reg_process_pending_hints(void) | |||
| 2788 | 2788 | ||
| 2789 | /* When last_request->processed becomes true this will be rescheduled */ | 2789 | /* When last_request->processed becomes true this will be rescheduled */ |
| 2790 | if (lr && !lr->processed) { | 2790 | if (lr && !lr->processed) { |
| 2791 | reg_process_hint(lr); | 2791 | pr_debug("Pending regulatory request, waiting for it to be processed...\n"); |
| 2792 | return; | 2792 | return; |
| 2793 | } | 2793 | } |
| 2794 | 2794 | ||
diff --git a/net/wireless/util.c b/net/wireless/util.c index 1c39d6a2e850..e74837824cea 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
| @@ -233,25 +233,30 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | |||
| 233 | 233 | ||
| 234 | switch (params->cipher) { | 234 | switch (params->cipher) { |
| 235 | case WLAN_CIPHER_SUITE_TKIP: | 235 | case WLAN_CIPHER_SUITE_TKIP: |
| 236 | /* Extended Key ID can only be used with CCMP/GCMP ciphers */ | ||
| 237 | if ((pairwise && key_idx) || | ||
| 238 | params->mode != NL80211_KEY_RX_TX) | ||
| 239 | return -EINVAL; | ||
| 240 | break; | ||
| 236 | case WLAN_CIPHER_SUITE_CCMP: | 241 | case WLAN_CIPHER_SUITE_CCMP: |
| 237 | case WLAN_CIPHER_SUITE_CCMP_256: | 242 | case WLAN_CIPHER_SUITE_CCMP_256: |
| 238 | case WLAN_CIPHER_SUITE_GCMP: | 243 | case WLAN_CIPHER_SUITE_GCMP: |
| 239 | case WLAN_CIPHER_SUITE_GCMP_256: | 244 | case WLAN_CIPHER_SUITE_GCMP_256: |
| 240 | /* IEEE802.11-2016 allows only 0 and - when using Extended Key | 245 | /* IEEE802.11-2016 allows only 0 and - when supporting |
| 241 | * ID - 1 as index for pairwise keys. | 246 | * Extended Key ID - 1 as index for pairwise keys. |
| 242 | * @NL80211_KEY_NO_TX is only allowed for pairwise keys when | 247 | * @NL80211_KEY_NO_TX is only allowed for pairwise keys when |
| 243 | * the driver supports Extended Key ID. | 248 | * the driver supports Extended Key ID. |
| 244 | * @NL80211_KEY_SET_TX can't be set when installing and | 249 | * @NL80211_KEY_SET_TX can't be set when installing and |
| 245 | * validating a key. | 250 | * validating a key. |
| 246 | */ | 251 | */ |
| 247 | if (params->mode == NL80211_KEY_NO_TX) { | 252 | if ((params->mode == NL80211_KEY_NO_TX && !pairwise) || |
| 248 | if (!wiphy_ext_feature_isset(&rdev->wiphy, | 253 | params->mode == NL80211_KEY_SET_TX) |
| 249 | NL80211_EXT_FEATURE_EXT_KEY_ID)) | 254 | return -EINVAL; |
| 250 | return -EINVAL; | 255 | if (wiphy_ext_feature_isset(&rdev->wiphy, |
| 251 | else if (!pairwise || key_idx < 0 || key_idx > 1) | 256 | NL80211_EXT_FEATURE_EXT_KEY_ID)) { |
| 257 | if (pairwise && (key_idx < 0 || key_idx > 1)) | ||
| 252 | return -EINVAL; | 258 | return -EINVAL; |
| 253 | } else if ((pairwise && key_idx) || | 259 | } else if (pairwise && key_idx) { |
| 254 | params->mode == NL80211_KEY_SET_TX) { | ||
| 255 | return -EINVAL; | 260 | return -EINVAL; |
| 256 | } | 261 | } |
| 257 | break; | 262 | break; |
| @@ -1697,7 +1702,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, | |||
| 1697 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { | 1702 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { |
| 1698 | num_interfaces += params->iftype_num[iftype]; | 1703 | num_interfaces += params->iftype_num[iftype]; |
| 1699 | if (params->iftype_num[iftype] > 0 && | 1704 | if (params->iftype_num[iftype] > 0 && |
| 1700 | !(wiphy->software_iftypes & BIT(iftype))) | 1705 | !cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) |
| 1701 | used_iftypes |= BIT(iftype); | 1706 | used_iftypes |= BIT(iftype); |
| 1702 | } | 1707 | } |
| 1703 | 1708 | ||
| @@ -1719,7 +1724,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy, | |||
| 1719 | return -ENOMEM; | 1724 | return -ENOMEM; |
| 1720 | 1725 | ||
| 1721 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { | 1726 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { |
| 1722 | if (wiphy->software_iftypes & BIT(iftype)) | 1727 | if (cfg80211_iftype_allowed(wiphy, iftype, 0, 1)) |
| 1723 | continue; | 1728 | continue; |
| 1724 | for (j = 0; j < c->n_limits; j++) { | 1729 | for (j = 0; j < c->n_limits; j++) { |
| 1725 | all_iftypes |= limits[j].types; | 1730 | all_iftypes |= limits[j].types; |
| @@ -2072,3 +2077,26 @@ int ieee80211_get_vht_max_nss(struct ieee80211_vht_cap *cap, | |||
| 2072 | return max_vht_nss; | 2077 | return max_vht_nss; |
| 2073 | } | 2078 | } |
| 2074 | EXPORT_SYMBOL(ieee80211_get_vht_max_nss); | 2079 | EXPORT_SYMBOL(ieee80211_get_vht_max_nss); |
| 2080 | |||
| 2081 | bool cfg80211_iftype_allowed(struct wiphy *wiphy, enum nl80211_iftype iftype, | ||
| 2082 | bool is_4addr, u8 check_swif) | ||
| 2083 | |||
| 2084 | { | ||
| 2085 | bool is_vlan = iftype == NL80211_IFTYPE_AP_VLAN; | ||
| 2086 | |||
| 2087 | switch (check_swif) { | ||
| 2088 | case 0: | ||
| 2089 | if (is_vlan && is_4addr) | ||
| 2090 | return wiphy->flags & WIPHY_FLAG_4ADDR_AP; | ||
| 2091 | return wiphy->interface_modes & BIT(iftype); | ||
| 2092 | case 1: | ||
| 2093 | if (!(wiphy->software_iftypes & BIT(iftype)) && is_vlan) | ||
| 2094 | return wiphy->flags & WIPHY_FLAG_4ADDR_AP; | ||
| 2095 | return wiphy->software_iftypes & BIT(iftype); | ||
| 2096 | default: | ||
| 2097 | break; | ||
| 2098 | } | ||
| 2099 | |||
| 2100 | return false; | ||
| 2101 | } | ||
| 2102 | EXPORT_SYMBOL(cfg80211_iftype_allowed); | ||
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c index 83de74ca729a..688aac7a6943 100644 --- a/net/xdp/xdp_umem.c +++ b/net/xdp/xdp_umem.c | |||
| @@ -365,7 +365,7 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) | |||
| 365 | umem->pages = kcalloc(umem->npgs, sizeof(*umem->pages), GFP_KERNEL); | 365 | umem->pages = kcalloc(umem->npgs, sizeof(*umem->pages), GFP_KERNEL); |
| 366 | if (!umem->pages) { | 366 | if (!umem->pages) { |
| 367 | err = -ENOMEM; | 367 | err = -ENOMEM; |
| 368 | goto out_account; | 368 | goto out_pin; |
| 369 | } | 369 | } |
| 370 | 370 | ||
| 371 | for (i = 0; i < umem->npgs; i++) | 371 | for (i = 0; i < umem->npgs; i++) |
| @@ -373,6 +373,8 @@ static int xdp_umem_reg(struct xdp_umem *umem, struct xdp_umem_reg *mr) | |||
| 373 | 373 | ||
| 374 | return 0; | 374 | return 0; |
| 375 | 375 | ||
| 376 | out_pin: | ||
| 377 | xdp_umem_unpin_pages(umem); | ||
| 376 | out_account: | 378 | out_account: |
| 377 | xdp_umem_unaccount_pages(umem); | 379 | xdp_umem_unaccount_pages(umem); |
| 378 | return err; | 380 | return err; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 8ca637a72697..ec94f5795ea4 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -3269,7 +3269,7 @@ decode_session4(struct sk_buff *skb, struct flowi *fl, bool reverse) | |||
| 3269 | struct flowi4 *fl4 = &fl->u.ip4; | 3269 | struct flowi4 *fl4 = &fl->u.ip4; |
| 3270 | int oif = 0; | 3270 | int oif = 0; |
| 3271 | 3271 | ||
| 3272 | if (skb_dst(skb)) | 3272 | if (skb_dst(skb) && skb_dst(skb)->dev) |
| 3273 | oif = skb_dst(skb)->dev->ifindex; | 3273 | oif = skb_dst(skb)->dev->ifindex; |
| 3274 | 3274 | ||
| 3275 | memset(fl4, 0, sizeof(struct flowi4)); | 3275 | memset(fl4, 0, sizeof(struct flowi4)); |
| @@ -3387,7 +3387,7 @@ decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse) | |||
| 3387 | 3387 | ||
| 3388 | nexthdr = nh[nhoff]; | 3388 | nexthdr = nh[nhoff]; |
| 3389 | 3389 | ||
| 3390 | if (skb_dst(skb)) | 3390 | if (skb_dst(skb) && skb_dst(skb)->dev) |
| 3391 | oif = skb_dst(skb)->dev->ifindex; | 3391 | oif = skb_dst(skb)->dev->ifindex; |
| 3392 | 3392 | ||
| 3393 | memset(fl6, 0, sizeof(struct flowi6)); | 3393 | memset(fl6, 0, sizeof(struct flowi6)); |
