diff options
author | Chris Mason <clm@fb.com> | 2016-05-17 17:43:19 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2016-05-17 17:43:19 -0400 |
commit | c315ef8d9db7f1a0ebd023a395ebdfde1c68057e (patch) | |
tree | 501e1fc558de9e56b78e457aa928fa255e660486 /net | |
parent | a88336d13c66fc171f336c6332fcb67339894e08 (diff) | |
parent | 5f9a8a51d8b95505d8de8b7191ae2ed8c504d4af (diff) |
Merge branch 'for-chris-4.7' of git://git.kernel.org/pub/scm/linux/kernel/git/fdmanana/linux into for-linus-4.7
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'net')
34 files changed, 376 insertions, 238 deletions
diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c index 3315b9a598af..4026f198a734 100644 --- a/net/batman-adv/bat_v.c +++ b/net/batman-adv/bat_v.c | |||
@@ -32,10 +32,21 @@ | |||
32 | 32 | ||
33 | #include "bat_v_elp.h" | 33 | #include "bat_v_elp.h" |
34 | #include "bat_v_ogm.h" | 34 | #include "bat_v_ogm.h" |
35 | #include "hard-interface.h" | ||
35 | #include "hash.h" | 36 | #include "hash.h" |
36 | #include "originator.h" | 37 | #include "originator.h" |
37 | #include "packet.h" | 38 | #include "packet.h" |
38 | 39 | ||
40 | static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface) | ||
41 | { | ||
42 | /* B.A.T.M.A.N. V does not use any queuing mechanism, therefore it can | ||
43 | * set the interface as ACTIVE right away, without any risk of race | ||
44 | * condition | ||
45 | */ | ||
46 | if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED) | ||
47 | hard_iface->if_status = BATADV_IF_ACTIVE; | ||
48 | } | ||
49 | |||
39 | static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface) | 50 | static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface) |
40 | { | 51 | { |
41 | int ret; | 52 | int ret; |
@@ -274,6 +285,7 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1, | |||
274 | 285 | ||
275 | static struct batadv_algo_ops batadv_batman_v __read_mostly = { | 286 | static struct batadv_algo_ops batadv_batman_v __read_mostly = { |
276 | .name = "BATMAN_V", | 287 | .name = "BATMAN_V", |
288 | .bat_iface_activate = batadv_v_iface_activate, | ||
277 | .bat_iface_enable = batadv_v_iface_enable, | 289 | .bat_iface_enable = batadv_v_iface_enable, |
278 | .bat_iface_disable = batadv_v_iface_disable, | 290 | .bat_iface_disable = batadv_v_iface_disable, |
279 | .bat_iface_update_mac = batadv_v_iface_update_mac, | 291 | .bat_iface_update_mac = batadv_v_iface_update_mac, |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index e96d7c745b4a..3e6b2624f980 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -568,6 +568,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, | |||
568 | * be sent to | 568 | * be sent to |
569 | * @bat_priv: the bat priv with all the soft interface information | 569 | * @bat_priv: the bat priv with all the soft interface information |
570 | * @ip_dst: ipv4 to look up in the DHT | 570 | * @ip_dst: ipv4 to look up in the DHT |
571 | * @vid: VLAN identifier | ||
571 | * | 572 | * |
572 | * An originator O is selected if and only if its DHT_ID value is one of three | 573 | * An originator O is selected if and only if its DHT_ID value is one of three |
573 | * closest values (from the LEFT, with wrap around if needed) then the hash | 574 | * closest values (from the LEFT, with wrap around if needed) then the hash |
@@ -576,7 +577,8 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv, | |||
576 | * Return: the candidate array of size BATADV_DAT_CANDIDATE_NUM. | 577 | * Return: the candidate array of size BATADV_DAT_CANDIDATE_NUM. |
577 | */ | 578 | */ |
578 | static struct batadv_dat_candidate * | 579 | static struct batadv_dat_candidate * |
579 | batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | 580 | batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst, |
581 | unsigned short vid) | ||
580 | { | 582 | { |
581 | int select; | 583 | int select; |
582 | batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key; | 584 | batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key; |
@@ -592,7 +594,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | |||
592 | return NULL; | 594 | return NULL; |
593 | 595 | ||
594 | dat.ip = ip_dst; | 596 | dat.ip = ip_dst; |
595 | dat.vid = 0; | 597 | dat.vid = vid; |
596 | ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat, | 598 | ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat, |
597 | BATADV_DAT_ADDR_MAX); | 599 | BATADV_DAT_ADDR_MAX); |
598 | 600 | ||
@@ -612,6 +614,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | |||
612 | * @bat_priv: the bat priv with all the soft interface information | 614 | * @bat_priv: the bat priv with all the soft interface information |
613 | * @skb: payload to send | 615 | * @skb: payload to send |
614 | * @ip: the DHT key | 616 | * @ip: the DHT key |
617 | * @vid: VLAN identifier | ||
615 | * @packet_subtype: unicast4addr packet subtype to use | 618 | * @packet_subtype: unicast4addr packet subtype to use |
616 | * | 619 | * |
617 | * This function copies the skb with pskb_copy() and is sent as unicast packet | 620 | * This function copies the skb with pskb_copy() and is sent as unicast packet |
@@ -622,7 +625,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | |||
622 | */ | 625 | */ |
623 | static bool batadv_dat_send_data(struct batadv_priv *bat_priv, | 626 | static bool batadv_dat_send_data(struct batadv_priv *bat_priv, |
624 | struct sk_buff *skb, __be32 ip, | 627 | struct sk_buff *skb, __be32 ip, |
625 | int packet_subtype) | 628 | unsigned short vid, int packet_subtype) |
626 | { | 629 | { |
627 | int i; | 630 | int i; |
628 | bool ret = false; | 631 | bool ret = false; |
@@ -631,7 +634,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv, | |||
631 | struct sk_buff *tmp_skb; | 634 | struct sk_buff *tmp_skb; |
632 | struct batadv_dat_candidate *cand; | 635 | struct batadv_dat_candidate *cand; |
633 | 636 | ||
634 | cand = batadv_dat_select_candidates(bat_priv, ip); | 637 | cand = batadv_dat_select_candidates(bat_priv, ip, vid); |
635 | if (!cand) | 638 | if (!cand) |
636 | goto out; | 639 | goto out; |
637 | 640 | ||
@@ -1022,7 +1025,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | |||
1022 | ret = true; | 1025 | ret = true; |
1023 | } else { | 1026 | } else { |
1024 | /* Send the request to the DHT */ | 1027 | /* Send the request to the DHT */ |
1025 | ret = batadv_dat_send_data(bat_priv, skb, ip_dst, | 1028 | ret = batadv_dat_send_data(bat_priv, skb, ip_dst, vid, |
1026 | BATADV_P_DAT_DHT_GET); | 1029 | BATADV_P_DAT_DHT_GET); |
1027 | } | 1030 | } |
1028 | out: | 1031 | out: |
@@ -1150,8 +1153,8 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | |||
1150 | /* Send the ARP reply to the candidates for both the IP addresses that | 1153 | /* Send the ARP reply to the candidates for both the IP addresses that |
1151 | * the node obtained from the ARP reply | 1154 | * the node obtained from the ARP reply |
1152 | */ | 1155 | */ |
1153 | batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT); | 1156 | batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT); |
1154 | batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT); | 1157 | batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT); |
1155 | } | 1158 | } |
1156 | 1159 | ||
1157 | /** | 1160 | /** |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b22b2775a0a5..0a7deaf2670a 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -407,6 +407,9 @@ batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface) | |||
407 | 407 | ||
408 | batadv_update_min_mtu(hard_iface->soft_iface); | 408 | batadv_update_min_mtu(hard_iface->soft_iface); |
409 | 409 | ||
410 | if (bat_priv->bat_algo_ops->bat_iface_activate) | ||
411 | bat_priv->bat_algo_ops->bat_iface_activate(hard_iface); | ||
412 | |||
410 | out: | 413 | out: |
411 | if (primary_if) | 414 | if (primary_if) |
412 | batadv_hardif_put(primary_if); | 415 | batadv_hardif_put(primary_if); |
@@ -572,8 +575,7 @@ void batadv_hardif_disable_interface(struct batadv_hard_iface *hard_iface, | |||
572 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 575 | struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
573 | struct batadv_hard_iface *primary_if = NULL; | 576 | struct batadv_hard_iface *primary_if = NULL; |
574 | 577 | ||
575 | if (hard_iface->if_status == BATADV_IF_ACTIVE) | 578 | batadv_hardif_deactivate_interface(hard_iface); |
576 | batadv_hardif_deactivate_interface(hard_iface); | ||
577 | 579 | ||
578 | if (hard_iface->if_status != BATADV_IF_INACTIVE) | 580 | if (hard_iface->if_status != BATADV_IF_INACTIVE) |
579 | goto out; | 581 | goto out; |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index e4cbb0753e37..c355a824713c 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -250,7 +250,6 @@ static void batadv_neigh_node_release(struct kref *ref) | |||
250 | { | 250 | { |
251 | struct hlist_node *node_tmp; | 251 | struct hlist_node *node_tmp; |
252 | struct batadv_neigh_node *neigh_node; | 252 | struct batadv_neigh_node *neigh_node; |
253 | struct batadv_hardif_neigh_node *hardif_neigh; | ||
254 | struct batadv_neigh_ifinfo *neigh_ifinfo; | 253 | struct batadv_neigh_ifinfo *neigh_ifinfo; |
255 | struct batadv_algo_ops *bao; | 254 | struct batadv_algo_ops *bao; |
256 | 255 | ||
@@ -262,13 +261,7 @@ static void batadv_neigh_node_release(struct kref *ref) | |||
262 | batadv_neigh_ifinfo_put(neigh_ifinfo); | 261 | batadv_neigh_ifinfo_put(neigh_ifinfo); |
263 | } | 262 | } |
264 | 263 | ||
265 | hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming, | 264 | batadv_hardif_neigh_put(neigh_node->hardif_neigh); |
266 | neigh_node->addr); | ||
267 | if (hardif_neigh) { | ||
268 | /* batadv_hardif_neigh_get() increases refcount too */ | ||
269 | batadv_hardif_neigh_put(hardif_neigh); | ||
270 | batadv_hardif_neigh_put(hardif_neigh); | ||
271 | } | ||
272 | 265 | ||
273 | if (bao->bat_neigh_free) | 266 | if (bao->bat_neigh_free) |
274 | bao->bat_neigh_free(neigh_node); | 267 | bao->bat_neigh_free(neigh_node); |
@@ -663,6 +656,11 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node, | |||
663 | ether_addr_copy(neigh_node->addr, neigh_addr); | 656 | ether_addr_copy(neigh_node->addr, neigh_addr); |
664 | neigh_node->if_incoming = hard_iface; | 657 | neigh_node->if_incoming = hard_iface; |
665 | neigh_node->orig_node = orig_node; | 658 | neigh_node->orig_node = orig_node; |
659 | neigh_node->last_seen = jiffies; | ||
660 | |||
661 | /* increment unique neighbor refcount */ | ||
662 | kref_get(&hardif_neigh->refcount); | ||
663 | neigh_node->hardif_neigh = hardif_neigh; | ||
666 | 664 | ||
667 | /* extra reference for return */ | 665 | /* extra reference for return */ |
668 | kref_init(&neigh_node->refcount); | 666 | kref_init(&neigh_node->refcount); |
@@ -672,9 +670,6 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node, | |||
672 | hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); | 670 | hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list); |
673 | spin_unlock_bh(&orig_node->neigh_list_lock); | 671 | spin_unlock_bh(&orig_node->neigh_list_lock); |
674 | 672 | ||
675 | /* increment unique neighbor refcount */ | ||
676 | kref_get(&hardif_neigh->refcount); | ||
677 | |||
678 | batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, | 673 | batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv, |
679 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", | 674 | "Creating new neighbor %pM for orig_node %pM on interface %s\n", |
680 | neigh_addr, orig_node->orig, hard_iface->net_dev->name); | 675 | neigh_addr, orig_node->orig, hard_iface->net_dev->name); |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 4dd646a52f1a..b781bf753250 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -105,6 +105,15 @@ static void _batadv_update_route(struct batadv_priv *bat_priv, | |||
105 | neigh_node = NULL; | 105 | neigh_node = NULL; |
106 | 106 | ||
107 | spin_lock_bh(&orig_node->neigh_list_lock); | 107 | spin_lock_bh(&orig_node->neigh_list_lock); |
108 | /* curr_router used earlier may not be the current orig_ifinfo->router | ||
109 | * anymore because it was dereferenced outside of the neigh_list_lock | ||
110 | * protected region. After the new best neighbor has replace the current | ||
111 | * best neighbor the reference counter needs to decrease. Consequently, | ||
112 | * the code needs to ensure the curr_router variable contains a pointer | ||
113 | * to the replaced best neighbor. | ||
114 | */ | ||
115 | curr_router = rcu_dereference_protected(orig_ifinfo->router, true); | ||
116 | |||
108 | rcu_assign_pointer(orig_ifinfo->router, neigh_node); | 117 | rcu_assign_pointer(orig_ifinfo->router, neigh_node); |
109 | spin_unlock_bh(&orig_node->neigh_list_lock); | 118 | spin_unlock_bh(&orig_node->neigh_list_lock); |
110 | batadv_orig_ifinfo_put(orig_ifinfo); | 119 | batadv_orig_ifinfo_put(orig_ifinfo); |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 3ce06e0a91b1..76417850d3fc 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -675,6 +675,9 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, | |||
675 | 675 | ||
676 | if (pending) { | 676 | if (pending) { |
677 | hlist_del(&forw_packet->list); | 677 | hlist_del(&forw_packet->list); |
678 | if (!forw_packet->own) | ||
679 | atomic_inc(&bat_priv->bcast_queue_left); | ||
680 | |||
678 | batadv_forw_packet_free(forw_packet); | 681 | batadv_forw_packet_free(forw_packet); |
679 | } | 682 | } |
680 | } | 683 | } |
@@ -702,6 +705,9 @@ batadv_purge_outstanding_packets(struct batadv_priv *bat_priv, | |||
702 | 705 | ||
703 | if (pending) { | 706 | if (pending) { |
704 | hlist_del(&forw_packet->list); | 707 | hlist_del(&forw_packet->list); |
708 | if (!forw_packet->own) | ||
709 | atomic_inc(&bat_priv->batman_queue_left); | ||
710 | |||
705 | batadv_forw_packet_free(forw_packet); | 711 | batadv_forw_packet_free(forw_packet); |
706 | } | 712 | } |
707 | } | 713 | } |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 0710379491bf..8a136b6a1ff0 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -408,11 +408,17 @@ void batadv_interface_rx(struct net_device *soft_iface, | |||
408 | */ | 408 | */ |
409 | nf_reset(skb); | 409 | nf_reset(skb); |
410 | 410 | ||
411 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) | ||
412 | goto dropped; | ||
413 | |||
411 | vid = batadv_get_vid(skb, 0); | 414 | vid = batadv_get_vid(skb, 0); |
412 | ethhdr = eth_hdr(skb); | 415 | ethhdr = eth_hdr(skb); |
413 | 416 | ||
414 | switch (ntohs(ethhdr->h_proto)) { | 417 | switch (ntohs(ethhdr->h_proto)) { |
415 | case ETH_P_8021Q: | 418 | case ETH_P_8021Q: |
419 | if (!pskb_may_pull(skb, VLAN_ETH_HLEN)) | ||
420 | goto dropped; | ||
421 | |||
416 | vhdr = (struct vlan_ethhdr *)skb->data; | 422 | vhdr = (struct vlan_ethhdr *)skb->data; |
417 | 423 | ||
418 | if (vhdr->h_vlan_encapsulated_proto != ethertype) | 424 | if (vhdr->h_vlan_encapsulated_proto != ethertype) |
@@ -424,8 +430,6 @@ void batadv_interface_rx(struct net_device *soft_iface, | |||
424 | } | 430 | } |
425 | 431 | ||
426 | /* skb->dev & skb->pkt_type are set here */ | 432 | /* skb->dev & skb->pkt_type are set here */ |
427 | if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) | ||
428 | goto dropped; | ||
429 | skb->protocol = eth_type_trans(skb, soft_iface); | 433 | skb->protocol = eth_type_trans(skb, soft_iface); |
430 | 434 | ||
431 | /* should not be necessary anymore as we use skb_pull_rcsum() | 435 | /* should not be necessary anymore as we use skb_pull_rcsum() |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 0b43e86328a5..9b4551a86535 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -215,6 +215,8 @@ static void batadv_tt_local_entry_release(struct kref *ref) | |||
215 | tt_local_entry = container_of(ref, struct batadv_tt_local_entry, | 215 | tt_local_entry = container_of(ref, struct batadv_tt_local_entry, |
216 | common.refcount); | 216 | common.refcount); |
217 | 217 | ||
218 | batadv_softif_vlan_put(tt_local_entry->vlan); | ||
219 | |||
218 | kfree_rcu(tt_local_entry, common.rcu); | 220 | kfree_rcu(tt_local_entry, common.rcu); |
219 | } | 221 | } |
220 | 222 | ||
@@ -673,6 +675,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr, | |||
673 | kref_get(&tt_local->common.refcount); | 675 | kref_get(&tt_local->common.refcount); |
674 | tt_local->last_seen = jiffies; | 676 | tt_local->last_seen = jiffies; |
675 | tt_local->common.added_at = tt_local->last_seen; | 677 | tt_local->common.added_at = tt_local->last_seen; |
678 | tt_local->vlan = vlan; | ||
676 | 679 | ||
677 | /* the batman interface mac and multicast addresses should never be | 680 | /* the batman interface mac and multicast addresses should never be |
678 | * purged | 681 | * purged |
@@ -991,7 +994,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
991 | struct batadv_tt_common_entry *tt_common_entry; | 994 | struct batadv_tt_common_entry *tt_common_entry; |
992 | struct batadv_tt_local_entry *tt_local; | 995 | struct batadv_tt_local_entry *tt_local; |
993 | struct batadv_hard_iface *primary_if; | 996 | struct batadv_hard_iface *primary_if; |
994 | struct batadv_softif_vlan *vlan; | ||
995 | struct hlist_head *head; | 997 | struct hlist_head *head; |
996 | unsigned short vid; | 998 | unsigned short vid; |
997 | u32 i; | 999 | u32 i; |
@@ -1027,14 +1029,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
1027 | last_seen_msecs = last_seen_msecs % 1000; | 1029 | last_seen_msecs = last_seen_msecs % 1000; |
1028 | 1030 | ||
1029 | no_purge = tt_common_entry->flags & np_flag; | 1031 | no_purge = tt_common_entry->flags & np_flag; |
1030 | |||
1031 | vlan = batadv_softif_vlan_get(bat_priv, vid); | ||
1032 | if (!vlan) { | ||
1033 | seq_printf(seq, "Cannot retrieve VLAN %d\n", | ||
1034 | BATADV_PRINT_VID(vid)); | ||
1035 | continue; | ||
1036 | } | ||
1037 | |||
1038 | seq_printf(seq, | 1032 | seq_printf(seq, |
1039 | " * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n", | 1033 | " * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n", |
1040 | tt_common_entry->addr, | 1034 | tt_common_entry->addr, |
@@ -1052,9 +1046,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
1052 | BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'), | 1046 | BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'), |
1053 | no_purge ? 0 : last_seen_secs, | 1047 | no_purge ? 0 : last_seen_secs, |
1054 | no_purge ? 0 : last_seen_msecs, | 1048 | no_purge ? 0 : last_seen_msecs, |
1055 | vlan->tt.crc); | 1049 | tt_local->vlan->tt.crc); |
1056 | |||
1057 | batadv_softif_vlan_put(vlan); | ||
1058 | } | 1050 | } |
1059 | rcu_read_unlock(); | 1051 | rcu_read_unlock(); |
1060 | } | 1052 | } |
@@ -1099,7 +1091,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr, | |||
1099 | { | 1091 | { |
1100 | struct batadv_tt_local_entry *tt_local_entry; | 1092 | struct batadv_tt_local_entry *tt_local_entry; |
1101 | u16 flags, curr_flags = BATADV_NO_FLAGS; | 1093 | u16 flags, curr_flags = BATADV_NO_FLAGS; |
1102 | struct batadv_softif_vlan *vlan; | ||
1103 | void *tt_entry_exists; | 1094 | void *tt_entry_exists; |
1104 | 1095 | ||
1105 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); | 1096 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); |
@@ -1139,14 +1130,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr, | |||
1139 | /* extra call to free the local tt entry */ | 1130 | /* extra call to free the local tt entry */ |
1140 | batadv_tt_local_entry_put(tt_local_entry); | 1131 | batadv_tt_local_entry_put(tt_local_entry); |
1141 | 1132 | ||
1142 | /* decrease the reference held for this vlan */ | ||
1143 | vlan = batadv_softif_vlan_get(bat_priv, vid); | ||
1144 | if (!vlan) | ||
1145 | goto out; | ||
1146 | |||
1147 | batadv_softif_vlan_put(vlan); | ||
1148 | batadv_softif_vlan_put(vlan); | ||
1149 | |||
1150 | out: | 1133 | out: |
1151 | if (tt_local_entry) | 1134 | if (tt_local_entry) |
1152 | batadv_tt_local_entry_put(tt_local_entry); | 1135 | batadv_tt_local_entry_put(tt_local_entry); |
@@ -1219,7 +1202,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
1219 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 1202 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
1220 | struct batadv_tt_common_entry *tt_common_entry; | 1203 | struct batadv_tt_common_entry *tt_common_entry; |
1221 | struct batadv_tt_local_entry *tt_local; | 1204 | struct batadv_tt_local_entry *tt_local; |
1222 | struct batadv_softif_vlan *vlan; | ||
1223 | struct hlist_node *node_tmp; | 1205 | struct hlist_node *node_tmp; |
1224 | struct hlist_head *head; | 1206 | struct hlist_head *head; |
1225 | u32 i; | 1207 | u32 i; |
@@ -1241,14 +1223,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
1241 | struct batadv_tt_local_entry, | 1223 | struct batadv_tt_local_entry, |
1242 | common); | 1224 | common); |
1243 | 1225 | ||
1244 | /* decrease the reference held for this vlan */ | ||
1245 | vlan = batadv_softif_vlan_get(bat_priv, | ||
1246 | tt_common_entry->vid); | ||
1247 | if (vlan) { | ||
1248 | batadv_softif_vlan_put(vlan); | ||
1249 | batadv_softif_vlan_put(vlan); | ||
1250 | } | ||
1251 | |||
1252 | batadv_tt_local_entry_put(tt_local); | 1226 | batadv_tt_local_entry_put(tt_local); |
1253 | } | 1227 | } |
1254 | spin_unlock_bh(list_lock); | 1228 | spin_unlock_bh(list_lock); |
@@ -3309,7 +3283,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | |||
3309 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; | 3283 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
3310 | struct batadv_tt_common_entry *tt_common; | 3284 | struct batadv_tt_common_entry *tt_common; |
3311 | struct batadv_tt_local_entry *tt_local; | 3285 | struct batadv_tt_local_entry *tt_local; |
3312 | struct batadv_softif_vlan *vlan; | ||
3313 | struct hlist_node *node_tmp; | 3286 | struct hlist_node *node_tmp; |
3314 | struct hlist_head *head; | 3287 | struct hlist_head *head; |
3315 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 3288 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
@@ -3339,13 +3312,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | |||
3339 | struct batadv_tt_local_entry, | 3312 | struct batadv_tt_local_entry, |
3340 | common); | 3313 | common); |
3341 | 3314 | ||
3342 | /* decrease the reference held for this vlan */ | ||
3343 | vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid); | ||
3344 | if (vlan) { | ||
3345 | batadv_softif_vlan_put(vlan); | ||
3346 | batadv_softif_vlan_put(vlan); | ||
3347 | } | ||
3348 | |||
3349 | batadv_tt_local_entry_put(tt_local); | 3315 | batadv_tt_local_entry_put(tt_local); |
3350 | } | 3316 | } |
3351 | spin_unlock_bh(list_lock); | 3317 | spin_unlock_bh(list_lock); |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 9abfb3e73c34..1e47fbe8bb7b 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -433,6 +433,7 @@ struct batadv_hardif_neigh_node { | |||
433 | * @ifinfo_lock: lock protecting private ifinfo members and list | 433 | * @ifinfo_lock: lock protecting private ifinfo members and list |
434 | * @if_incoming: pointer to incoming hard-interface | 434 | * @if_incoming: pointer to incoming hard-interface |
435 | * @last_seen: when last packet via this neighbor was received | 435 | * @last_seen: when last packet via this neighbor was received |
436 | * @hardif_neigh: hardif_neigh of this neighbor | ||
436 | * @refcount: number of contexts the object is used | 437 | * @refcount: number of contexts the object is used |
437 | * @rcu: struct used for freeing in an RCU-safe manner | 438 | * @rcu: struct used for freeing in an RCU-safe manner |
438 | */ | 439 | */ |
@@ -444,6 +445,7 @@ struct batadv_neigh_node { | |||
444 | spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */ | 445 | spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */ |
445 | struct batadv_hard_iface *if_incoming; | 446 | struct batadv_hard_iface *if_incoming; |
446 | unsigned long last_seen; | 447 | unsigned long last_seen; |
448 | struct batadv_hardif_neigh_node *hardif_neigh; | ||
447 | struct kref refcount; | 449 | struct kref refcount; |
448 | struct rcu_head rcu; | 450 | struct rcu_head rcu; |
449 | }; | 451 | }; |
@@ -1073,10 +1075,12 @@ struct batadv_tt_common_entry { | |||
1073 | * struct batadv_tt_local_entry - translation table local entry data | 1075 | * struct batadv_tt_local_entry - translation table local entry data |
1074 | * @common: general translation table data | 1076 | * @common: general translation table data |
1075 | * @last_seen: timestamp used for purging stale tt local entries | 1077 | * @last_seen: timestamp used for purging stale tt local entries |
1078 | * @vlan: soft-interface vlan of the entry | ||
1076 | */ | 1079 | */ |
1077 | struct batadv_tt_local_entry { | 1080 | struct batadv_tt_local_entry { |
1078 | struct batadv_tt_common_entry common; | 1081 | struct batadv_tt_common_entry common; |
1079 | unsigned long last_seen; | 1082 | unsigned long last_seen; |
1083 | struct batadv_softif_vlan *vlan; | ||
1080 | }; | 1084 | }; |
1081 | 1085 | ||
1082 | /** | 1086 | /** |
@@ -1250,6 +1254,8 @@ struct batadv_forw_packet { | |||
1250 | * struct batadv_algo_ops - mesh algorithm callbacks | 1254 | * struct batadv_algo_ops - mesh algorithm callbacks |
1251 | * @list: list node for the batadv_algo_list | 1255 | * @list: list node for the batadv_algo_list |
1252 | * @name: name of the algorithm | 1256 | * @name: name of the algorithm |
1257 | * @bat_iface_activate: start routing mechanisms when hard-interface is brought | ||
1258 | * up | ||
1253 | * @bat_iface_enable: init routing info when hard-interface is enabled | 1259 | * @bat_iface_enable: init routing info when hard-interface is enabled |
1254 | * @bat_iface_disable: de-init routing info when hard-interface is disabled | 1260 | * @bat_iface_disable: de-init routing info when hard-interface is disabled |
1255 | * @bat_iface_update_mac: (re-)init mac addresses of the protocol information | 1261 | * @bat_iface_update_mac: (re-)init mac addresses of the protocol information |
@@ -1277,6 +1283,7 @@ struct batadv_forw_packet { | |||
1277 | struct batadv_algo_ops { | 1283 | struct batadv_algo_ops { |
1278 | struct hlist_node list; | 1284 | struct hlist_node list; |
1279 | char *name; | 1285 | char *name; |
1286 | void (*bat_iface_activate)(struct batadv_hard_iface *hard_iface); | ||
1280 | int (*bat_iface_enable)(struct batadv_hard_iface *hard_iface); | 1287 | int (*bat_iface_enable)(struct batadv_hard_iface *hard_iface); |
1281 | void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface); | 1288 | void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface); |
1282 | void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface); | 1289 | void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface); |
diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 253bc77eda3b..7dbc80d01eb0 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c | |||
@@ -61,6 +61,19 @@ static void __mdb_entry_fill_flags(struct br_mdb_entry *e, unsigned char flags) | |||
61 | e->flags |= MDB_FLAGS_OFFLOAD; | 61 | e->flags |= MDB_FLAGS_OFFLOAD; |
62 | } | 62 | } |
63 | 63 | ||
64 | static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip) | ||
65 | { | ||
66 | memset(ip, 0, sizeof(struct br_ip)); | ||
67 | ip->vid = entry->vid; | ||
68 | ip->proto = entry->addr.proto; | ||
69 | if (ip->proto == htons(ETH_P_IP)) | ||
70 | ip->u.ip4 = entry->addr.u.ip4; | ||
71 | #if IS_ENABLED(CONFIG_IPV6) | ||
72 | else | ||
73 | ip->u.ip6 = entry->addr.u.ip6; | ||
74 | #endif | ||
75 | } | ||
76 | |||
64 | static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, | 77 | static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, |
65 | struct net_device *dev) | 78 | struct net_device *dev) |
66 | { | 79 | { |
@@ -243,9 +256,45 @@ static inline size_t rtnl_mdb_nlmsg_size(void) | |||
243 | + nla_total_size(sizeof(struct br_mdb_entry)); | 256 | + nla_total_size(sizeof(struct br_mdb_entry)); |
244 | } | 257 | } |
245 | 258 | ||
246 | static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry, | 259 | struct br_mdb_complete_info { |
247 | int type, struct net_bridge_port_group *pg) | 260 | struct net_bridge_port *port; |
261 | struct br_ip ip; | ||
262 | }; | ||
263 | |||
264 | static void br_mdb_complete(struct net_device *dev, int err, void *priv) | ||
248 | { | 265 | { |
266 | struct br_mdb_complete_info *data = priv; | ||
267 | struct net_bridge_port_group __rcu **pp; | ||
268 | struct net_bridge_port_group *p; | ||
269 | struct net_bridge_mdb_htable *mdb; | ||
270 | struct net_bridge_mdb_entry *mp; | ||
271 | struct net_bridge_port *port = data->port; | ||
272 | struct net_bridge *br = port->br; | ||
273 | |||
274 | if (err) | ||
275 | goto err; | ||
276 | |||
277 | spin_lock_bh(&br->multicast_lock); | ||
278 | mdb = mlock_dereference(br->mdb, br); | ||
279 | mp = br_mdb_ip_get(mdb, &data->ip); | ||
280 | if (!mp) | ||
281 | goto out; | ||
282 | for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; | ||
283 | pp = &p->next) { | ||
284 | if (p->port != port) | ||
285 | continue; | ||
286 | p->flags |= MDB_PG_FLAGS_OFFLOAD; | ||
287 | } | ||
288 | out: | ||
289 | spin_unlock_bh(&br->multicast_lock); | ||
290 | err: | ||
291 | kfree(priv); | ||
292 | } | ||
293 | |||
294 | static void __br_mdb_notify(struct net_device *dev, struct net_bridge_port *p, | ||
295 | struct br_mdb_entry *entry, int type) | ||
296 | { | ||
297 | struct br_mdb_complete_info *complete_info; | ||
249 | struct switchdev_obj_port_mdb mdb = { | 298 | struct switchdev_obj_port_mdb mdb = { |
250 | .obj = { | 299 | .obj = { |
251 | .id = SWITCHDEV_OBJ_ID_PORT_MDB, | 300 | .id = SWITCHDEV_OBJ_ID_PORT_MDB, |
@@ -268,9 +317,14 @@ static void __br_mdb_notify(struct net_device *dev, struct br_mdb_entry *entry, | |||
268 | 317 | ||
269 | mdb.obj.orig_dev = port_dev; | 318 | mdb.obj.orig_dev = port_dev; |
270 | if (port_dev && type == RTM_NEWMDB) { | 319 | if (port_dev && type == RTM_NEWMDB) { |
271 | err = switchdev_port_obj_add(port_dev, &mdb.obj); | 320 | complete_info = kmalloc(sizeof(*complete_info), GFP_ATOMIC); |
272 | if (!err && pg) | 321 | if (complete_info) { |
273 | pg->flags |= MDB_PG_FLAGS_OFFLOAD; | 322 | complete_info->port = p; |
323 | __mdb_entry_to_br_ip(entry, &complete_info->ip); | ||
324 | mdb.obj.complete_priv = complete_info; | ||
325 | mdb.obj.complete = br_mdb_complete; | ||
326 | switchdev_port_obj_add(port_dev, &mdb.obj); | ||
327 | } | ||
274 | } else if (port_dev && type == RTM_DELMDB) { | 328 | } else if (port_dev && type == RTM_DELMDB) { |
275 | switchdev_port_obj_del(port_dev, &mdb.obj); | 329 | switchdev_port_obj_del(port_dev, &mdb.obj); |
276 | } | 330 | } |
@@ -291,21 +345,21 @@ errout: | |||
291 | rtnl_set_sk_err(net, RTNLGRP_MDB, err); | 345 | rtnl_set_sk_err(net, RTNLGRP_MDB, err); |
292 | } | 346 | } |
293 | 347 | ||
294 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port_group *pg, | 348 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, |
295 | int type) | 349 | struct br_ip *group, int type, u8 flags) |
296 | { | 350 | { |
297 | struct br_mdb_entry entry; | 351 | struct br_mdb_entry entry; |
298 | 352 | ||
299 | memset(&entry, 0, sizeof(entry)); | 353 | memset(&entry, 0, sizeof(entry)); |
300 | entry.ifindex = pg->port->dev->ifindex; | 354 | entry.ifindex = port->dev->ifindex; |
301 | entry.addr.proto = pg->addr.proto; | 355 | entry.addr.proto = group->proto; |
302 | entry.addr.u.ip4 = pg->addr.u.ip4; | 356 | entry.addr.u.ip4 = group->u.ip4; |
303 | #if IS_ENABLED(CONFIG_IPV6) | 357 | #if IS_ENABLED(CONFIG_IPV6) |
304 | entry.addr.u.ip6 = pg->addr.u.ip6; | 358 | entry.addr.u.ip6 = group->u.ip6; |
305 | #endif | 359 | #endif |
306 | entry.vid = pg->addr.vid; | 360 | entry.vid = group->vid; |
307 | __mdb_entry_fill_flags(&entry, pg->flags); | 361 | __mdb_entry_fill_flags(&entry, flags); |
308 | __br_mdb_notify(dev, &entry, type, pg); | 362 | __br_mdb_notify(dev, port, &entry, type); |
309 | } | 363 | } |
310 | 364 | ||
311 | static int nlmsg_populate_rtr_fill(struct sk_buff *skb, | 365 | static int nlmsg_populate_rtr_fill(struct sk_buff *skb, |
@@ -450,8 +504,7 @@ static int br_mdb_parse(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
450 | } | 504 | } |
451 | 505 | ||
452 | static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, | 506 | static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, |
453 | struct br_ip *group, unsigned char state, | 507 | struct br_ip *group, unsigned char state) |
454 | struct net_bridge_port_group **pg) | ||
455 | { | 508 | { |
456 | struct net_bridge_mdb_entry *mp; | 509 | struct net_bridge_mdb_entry *mp; |
457 | struct net_bridge_port_group *p; | 510 | struct net_bridge_port_group *p; |
@@ -482,7 +535,6 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, | |||
482 | if (unlikely(!p)) | 535 | if (unlikely(!p)) |
483 | return -ENOMEM; | 536 | return -ENOMEM; |
484 | rcu_assign_pointer(*pp, p); | 537 | rcu_assign_pointer(*pp, p); |
485 | *pg = p; | ||
486 | if (state == MDB_TEMPORARY) | 538 | if (state == MDB_TEMPORARY) |
487 | mod_timer(&p->timer, now + br->multicast_membership_interval); | 539 | mod_timer(&p->timer, now + br->multicast_membership_interval); |
488 | 540 | ||
@@ -490,8 +542,7 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, | |||
490 | } | 542 | } |
491 | 543 | ||
492 | static int __br_mdb_add(struct net *net, struct net_bridge *br, | 544 | static int __br_mdb_add(struct net *net, struct net_bridge *br, |
493 | struct br_mdb_entry *entry, | 545 | struct br_mdb_entry *entry) |
494 | struct net_bridge_port_group **pg) | ||
495 | { | 546 | { |
496 | struct br_ip ip; | 547 | struct br_ip ip; |
497 | struct net_device *dev; | 548 | struct net_device *dev; |
@@ -509,18 +560,10 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, | |||
509 | if (!p || p->br != br || p->state == BR_STATE_DISABLED) | 560 | if (!p || p->br != br || p->state == BR_STATE_DISABLED) |
510 | return -EINVAL; | 561 | return -EINVAL; |
511 | 562 | ||
512 | memset(&ip, 0, sizeof(ip)); | 563 | __mdb_entry_to_br_ip(entry, &ip); |
513 | ip.vid = entry->vid; | ||
514 | ip.proto = entry->addr.proto; | ||
515 | if (ip.proto == htons(ETH_P_IP)) | ||
516 | ip.u.ip4 = entry->addr.u.ip4; | ||
517 | #if IS_ENABLED(CONFIG_IPV6) | ||
518 | else | ||
519 | ip.u.ip6 = entry->addr.u.ip6; | ||
520 | #endif | ||
521 | 564 | ||
522 | spin_lock_bh(&br->multicast_lock); | 565 | spin_lock_bh(&br->multicast_lock); |
523 | ret = br_mdb_add_group(br, p, &ip, entry->state, pg); | 566 | ret = br_mdb_add_group(br, p, &ip, entry->state); |
524 | spin_unlock_bh(&br->multicast_lock); | 567 | spin_unlock_bh(&br->multicast_lock); |
525 | return ret; | 568 | return ret; |
526 | } | 569 | } |
@@ -528,7 +571,6 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, | |||
528 | static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) | 571 | static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) |
529 | { | 572 | { |
530 | struct net *net = sock_net(skb->sk); | 573 | struct net *net = sock_net(skb->sk); |
531 | struct net_bridge_port_group *pg; | ||
532 | struct net_bridge_vlan_group *vg; | 574 | struct net_bridge_vlan_group *vg; |
533 | struct net_device *dev, *pdev; | 575 | struct net_device *dev, *pdev; |
534 | struct br_mdb_entry *entry; | 576 | struct br_mdb_entry *entry; |
@@ -558,15 +600,15 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
558 | if (br_vlan_enabled(br) && vg && entry->vid == 0) { | 600 | if (br_vlan_enabled(br) && vg && entry->vid == 0) { |
559 | list_for_each_entry(v, &vg->vlan_list, vlist) { | 601 | list_for_each_entry(v, &vg->vlan_list, vlist) { |
560 | entry->vid = v->vid; | 602 | entry->vid = v->vid; |
561 | err = __br_mdb_add(net, br, entry, &pg); | 603 | err = __br_mdb_add(net, br, entry); |
562 | if (err) | 604 | if (err) |
563 | break; | 605 | break; |
564 | __br_mdb_notify(dev, entry, RTM_NEWMDB, pg); | 606 | __br_mdb_notify(dev, p, entry, RTM_NEWMDB); |
565 | } | 607 | } |
566 | } else { | 608 | } else { |
567 | err = __br_mdb_add(net, br, entry, &pg); | 609 | err = __br_mdb_add(net, br, entry); |
568 | if (!err) | 610 | if (!err) |
569 | __br_mdb_notify(dev, entry, RTM_NEWMDB, pg); | 611 | __br_mdb_notify(dev, p, entry, RTM_NEWMDB); |
570 | } | 612 | } |
571 | 613 | ||
572 | return err; | 614 | return err; |
@@ -584,15 +626,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) | |||
584 | if (!netif_running(br->dev) || br->multicast_disabled) | 626 | if (!netif_running(br->dev) || br->multicast_disabled) |
585 | return -EINVAL; | 627 | return -EINVAL; |
586 | 628 | ||
587 | memset(&ip, 0, sizeof(ip)); | 629 | __mdb_entry_to_br_ip(entry, &ip); |
588 | ip.vid = entry->vid; | ||
589 | ip.proto = entry->addr.proto; | ||
590 | if (ip.proto == htons(ETH_P_IP)) | ||
591 | ip.u.ip4 = entry->addr.u.ip4; | ||
592 | #if IS_ENABLED(CONFIG_IPV6) | ||
593 | else | ||
594 | ip.u.ip6 = entry->addr.u.ip6; | ||
595 | #endif | ||
596 | 630 | ||
597 | spin_lock_bh(&br->multicast_lock); | 631 | spin_lock_bh(&br->multicast_lock); |
598 | mdb = mlock_dereference(br->mdb, br); | 632 | mdb = mlock_dereference(br->mdb, br); |
@@ -662,12 +696,12 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
662 | entry->vid = v->vid; | 696 | entry->vid = v->vid; |
663 | err = __br_mdb_del(br, entry); | 697 | err = __br_mdb_del(br, entry); |
664 | if (!err) | 698 | if (!err) |
665 | __br_mdb_notify(dev, entry, RTM_DELMDB, NULL); | 699 | __br_mdb_notify(dev, p, entry, RTM_DELMDB); |
666 | } | 700 | } |
667 | } else { | 701 | } else { |
668 | err = __br_mdb_del(br, entry); | 702 | err = __br_mdb_del(br, entry); |
669 | if (!err) | 703 | if (!err) |
670 | __br_mdb_notify(dev, entry, RTM_DELMDB, NULL); | 704 | __br_mdb_notify(dev, p, entry, RTM_DELMDB); |
671 | } | 705 | } |
672 | 706 | ||
673 | return err; | 707 | return err; |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index a4c15df2b792..191ea66e4d92 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -283,7 +283,8 @@ static void br_multicast_del_pg(struct net_bridge *br, | |||
283 | rcu_assign_pointer(*pp, p->next); | 283 | rcu_assign_pointer(*pp, p->next); |
284 | hlist_del_init(&p->mglist); | 284 | hlist_del_init(&p->mglist); |
285 | del_timer(&p->timer); | 285 | del_timer(&p->timer); |
286 | br_mdb_notify(br->dev, p, RTM_DELMDB); | 286 | br_mdb_notify(br->dev, p->port, &pg->addr, RTM_DELMDB, |
287 | p->flags); | ||
287 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 288 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
288 | 289 | ||
289 | if (!mp->ports && !mp->mglist && | 290 | if (!mp->ports && !mp->mglist && |
@@ -705,7 +706,7 @@ static int br_multicast_add_group(struct net_bridge *br, | |||
705 | if (unlikely(!p)) | 706 | if (unlikely(!p)) |
706 | goto err; | 707 | goto err; |
707 | rcu_assign_pointer(*pp, p); | 708 | rcu_assign_pointer(*pp, p); |
708 | br_mdb_notify(br->dev, p, RTM_NEWMDB); | 709 | br_mdb_notify(br->dev, port, group, RTM_NEWMDB, 0); |
709 | 710 | ||
710 | found: | 711 | found: |
711 | mod_timer(&p->timer, now + br->multicast_membership_interval); | 712 | mod_timer(&p->timer, now + br->multicast_membership_interval); |
@@ -1461,7 +1462,8 @@ br_multicast_leave_group(struct net_bridge *br, | |||
1461 | hlist_del_init(&p->mglist); | 1462 | hlist_del_init(&p->mglist); |
1462 | del_timer(&p->timer); | 1463 | del_timer(&p->timer); |
1463 | call_rcu_bh(&p->rcu, br_multicast_free_pg); | 1464 | call_rcu_bh(&p->rcu, br_multicast_free_pg); |
1464 | br_mdb_notify(br->dev, p, RTM_DELMDB); | 1465 | br_mdb_notify(br->dev, port, group, RTM_DELMDB, |
1466 | p->flags); | ||
1465 | 1467 | ||
1466 | if (!mp->ports && !mp->mglist && | 1468 | if (!mp->ports && !mp->mglist && |
1467 | netif_running(br->dev)) | 1469 | netif_running(br->dev)) |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1b5d145dfcbf..d9da857182ef 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -560,8 +560,8 @@ br_multicast_new_port_group(struct net_bridge_port *port, struct br_ip *group, | |||
560 | unsigned char flags); | 560 | unsigned char flags); |
561 | void br_mdb_init(void); | 561 | void br_mdb_init(void); |
562 | void br_mdb_uninit(void); | 562 | void br_mdb_uninit(void); |
563 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port_group *pg, | 563 | void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port, |
564 | int type); | 564 | struct br_ip *group, int type, u8 flags); |
565 | void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, | 565 | void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port, |
566 | int type); | 566 | int type); |
567 | 567 | ||
diff --git a/net/ceph/auth.c b/net/ceph/auth.c index 6b923bcaa2a4..2bc5965fdd1e 100644 --- a/net/ceph/auth.c +++ b/net/ceph/auth.c | |||
@@ -293,13 +293,9 @@ int ceph_auth_create_authorizer(struct ceph_auth_client *ac, | |||
293 | } | 293 | } |
294 | EXPORT_SYMBOL(ceph_auth_create_authorizer); | 294 | EXPORT_SYMBOL(ceph_auth_create_authorizer); |
295 | 295 | ||
296 | void ceph_auth_destroy_authorizer(struct ceph_auth_client *ac, | 296 | void ceph_auth_destroy_authorizer(struct ceph_authorizer *a) |
297 | struct ceph_authorizer *a) | ||
298 | { | 297 | { |
299 | mutex_lock(&ac->mutex); | 298 | a->destroy(a); |
300 | if (ac->ops && ac->ops->destroy_authorizer) | ||
301 | ac->ops->destroy_authorizer(ac, a); | ||
302 | mutex_unlock(&ac->mutex); | ||
303 | } | 299 | } |
304 | EXPORT_SYMBOL(ceph_auth_destroy_authorizer); | 300 | EXPORT_SYMBOL(ceph_auth_destroy_authorizer); |
305 | 301 | ||
diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c index 8c93fa8d81bc..5f836f02ae36 100644 --- a/net/ceph/auth_none.c +++ b/net/ceph/auth_none.c | |||
@@ -16,7 +16,6 @@ static void reset(struct ceph_auth_client *ac) | |||
16 | struct ceph_auth_none_info *xi = ac->private; | 16 | struct ceph_auth_none_info *xi = ac->private; |
17 | 17 | ||
18 | xi->starting = true; | 18 | xi->starting = true; |
19 | xi->built_authorizer = false; | ||
20 | } | 19 | } |
21 | 20 | ||
22 | static void destroy(struct ceph_auth_client *ac) | 21 | static void destroy(struct ceph_auth_client *ac) |
@@ -39,6 +38,27 @@ static int should_authenticate(struct ceph_auth_client *ac) | |||
39 | return xi->starting; | 38 | return xi->starting; |
40 | } | 39 | } |
41 | 40 | ||
41 | static int ceph_auth_none_build_authorizer(struct ceph_auth_client *ac, | ||
42 | struct ceph_none_authorizer *au) | ||
43 | { | ||
44 | void *p = au->buf; | ||
45 | void *const end = p + sizeof(au->buf); | ||
46 | int ret; | ||
47 | |||
48 | ceph_encode_8_safe(&p, end, 1, e_range); | ||
49 | ret = ceph_entity_name_encode(ac->name, &p, end); | ||
50 | if (ret < 0) | ||
51 | return ret; | ||
52 | |||
53 | ceph_encode_64_safe(&p, end, ac->global_id, e_range); | ||
54 | au->buf_len = p - (void *)au->buf; | ||
55 | dout("%s built authorizer len %d\n", __func__, au->buf_len); | ||
56 | return 0; | ||
57 | |||
58 | e_range: | ||
59 | return -ERANGE; | ||
60 | } | ||
61 | |||
42 | static int build_request(struct ceph_auth_client *ac, void *buf, void *end) | 62 | static int build_request(struct ceph_auth_client *ac, void *buf, void *end) |
43 | { | 63 | { |
44 | return 0; | 64 | return 0; |
@@ -57,32 +77,32 @@ static int handle_reply(struct ceph_auth_client *ac, int result, | |||
57 | return result; | 77 | return result; |
58 | } | 78 | } |
59 | 79 | ||
80 | static void ceph_auth_none_destroy_authorizer(struct ceph_authorizer *a) | ||
81 | { | ||
82 | kfree(a); | ||
83 | } | ||
84 | |||
60 | /* | 85 | /* |
61 | * build an 'authorizer' with our entity_name and global_id. we can | 86 | * build an 'authorizer' with our entity_name and global_id. it is |
62 | * reuse a single static copy since it is identical for all services | 87 | * identical for all services we connect to. |
63 | * we connect to. | ||
64 | */ | 88 | */ |
65 | static int ceph_auth_none_create_authorizer( | 89 | static int ceph_auth_none_create_authorizer( |
66 | struct ceph_auth_client *ac, int peer_type, | 90 | struct ceph_auth_client *ac, int peer_type, |
67 | struct ceph_auth_handshake *auth) | 91 | struct ceph_auth_handshake *auth) |
68 | { | 92 | { |
69 | struct ceph_auth_none_info *ai = ac->private; | 93 | struct ceph_none_authorizer *au; |
70 | struct ceph_none_authorizer *au = &ai->au; | ||
71 | void *p, *end; | ||
72 | int ret; | 94 | int ret; |
73 | 95 | ||
74 | if (!ai->built_authorizer) { | 96 | au = kmalloc(sizeof(*au), GFP_NOFS); |
75 | p = au->buf; | 97 | if (!au) |
76 | end = p + sizeof(au->buf); | 98 | return -ENOMEM; |
77 | ceph_encode_8(&p, 1); | 99 | |
78 | ret = ceph_entity_name_encode(ac->name, &p, end - 8); | 100 | au->base.destroy = ceph_auth_none_destroy_authorizer; |
79 | if (ret < 0) | 101 | |
80 | goto bad; | 102 | ret = ceph_auth_none_build_authorizer(ac, au); |
81 | ceph_decode_need(&p, end, sizeof(u64), bad2); | 103 | if (ret) { |
82 | ceph_encode_64(&p, ac->global_id); | 104 | kfree(au); |
83 | au->buf_len = p - (void *)au->buf; | 105 | return ret; |
84 | ai->built_authorizer = true; | ||
85 | dout("built authorizer len %d\n", au->buf_len); | ||
86 | } | 106 | } |
87 | 107 | ||
88 | auth->authorizer = (struct ceph_authorizer *) au; | 108 | auth->authorizer = (struct ceph_authorizer *) au; |
@@ -92,17 +112,6 @@ static int ceph_auth_none_create_authorizer( | |||
92 | auth->authorizer_reply_buf_len = sizeof (au->reply_buf); | 112 | auth->authorizer_reply_buf_len = sizeof (au->reply_buf); |
93 | 113 | ||
94 | return 0; | 114 | return 0; |
95 | |||
96 | bad2: | ||
97 | ret = -ERANGE; | ||
98 | bad: | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static void ceph_auth_none_destroy_authorizer(struct ceph_auth_client *ac, | ||
103 | struct ceph_authorizer *a) | ||
104 | { | ||
105 | /* nothing to do */ | ||
106 | } | 115 | } |
107 | 116 | ||
108 | static const struct ceph_auth_client_ops ceph_auth_none_ops = { | 117 | static const struct ceph_auth_client_ops ceph_auth_none_ops = { |
@@ -114,7 +123,6 @@ static const struct ceph_auth_client_ops ceph_auth_none_ops = { | |||
114 | .build_request = build_request, | 123 | .build_request = build_request, |
115 | .handle_reply = handle_reply, | 124 | .handle_reply = handle_reply, |
116 | .create_authorizer = ceph_auth_none_create_authorizer, | 125 | .create_authorizer = ceph_auth_none_create_authorizer, |
117 | .destroy_authorizer = ceph_auth_none_destroy_authorizer, | ||
118 | }; | 126 | }; |
119 | 127 | ||
120 | int ceph_auth_none_init(struct ceph_auth_client *ac) | 128 | int ceph_auth_none_init(struct ceph_auth_client *ac) |
@@ -127,7 +135,6 @@ int ceph_auth_none_init(struct ceph_auth_client *ac) | |||
127 | return -ENOMEM; | 135 | return -ENOMEM; |
128 | 136 | ||
129 | xi->starting = true; | 137 | xi->starting = true; |
130 | xi->built_authorizer = false; | ||
131 | 138 | ||
132 | ac->protocol = CEPH_AUTH_NONE; | 139 | ac->protocol = CEPH_AUTH_NONE; |
133 | ac->private = xi; | 140 | ac->private = xi; |
diff --git a/net/ceph/auth_none.h b/net/ceph/auth_none.h index 059a3ce4b53f..62021535ae4a 100644 --- a/net/ceph/auth_none.h +++ b/net/ceph/auth_none.h | |||
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | struct ceph_none_authorizer { | 14 | struct ceph_none_authorizer { |
15 | struct ceph_authorizer base; | ||
15 | char buf[128]; | 16 | char buf[128]; |
16 | int buf_len; | 17 | int buf_len; |
17 | char reply_buf[0]; | 18 | char reply_buf[0]; |
@@ -19,8 +20,6 @@ struct ceph_none_authorizer { | |||
19 | 20 | ||
20 | struct ceph_auth_none_info { | 21 | struct ceph_auth_none_info { |
21 | bool starting; | 22 | bool starting; |
22 | bool built_authorizer; | ||
23 | struct ceph_none_authorizer au; /* we only need one; it's static */ | ||
24 | }; | 23 | }; |
25 | 24 | ||
26 | int ceph_auth_none_init(struct ceph_auth_client *ac); | 25 | int ceph_auth_none_init(struct ceph_auth_client *ac); |
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 9e43a315e662..a0905f04bd13 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
@@ -565,6 +565,14 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result, | |||
565 | return -EAGAIN; | 565 | return -EAGAIN; |
566 | } | 566 | } |
567 | 567 | ||
568 | static void ceph_x_destroy_authorizer(struct ceph_authorizer *a) | ||
569 | { | ||
570 | struct ceph_x_authorizer *au = (void *)a; | ||
571 | |||
572 | ceph_x_authorizer_cleanup(au); | ||
573 | kfree(au); | ||
574 | } | ||
575 | |||
568 | static int ceph_x_create_authorizer( | 576 | static int ceph_x_create_authorizer( |
569 | struct ceph_auth_client *ac, int peer_type, | 577 | struct ceph_auth_client *ac, int peer_type, |
570 | struct ceph_auth_handshake *auth) | 578 | struct ceph_auth_handshake *auth) |
@@ -581,6 +589,8 @@ static int ceph_x_create_authorizer( | |||
581 | if (!au) | 589 | if (!au) |
582 | return -ENOMEM; | 590 | return -ENOMEM; |
583 | 591 | ||
592 | au->base.destroy = ceph_x_destroy_authorizer; | ||
593 | |||
584 | ret = ceph_x_build_authorizer(ac, th, au); | 594 | ret = ceph_x_build_authorizer(ac, th, au); |
585 | if (ret) { | 595 | if (ret) { |
586 | kfree(au); | 596 | kfree(au); |
@@ -643,16 +653,6 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, | |||
643 | return ret; | 653 | return ret; |
644 | } | 654 | } |
645 | 655 | ||
646 | static void ceph_x_destroy_authorizer(struct ceph_auth_client *ac, | ||
647 | struct ceph_authorizer *a) | ||
648 | { | ||
649 | struct ceph_x_authorizer *au = (void *)a; | ||
650 | |||
651 | ceph_x_authorizer_cleanup(au); | ||
652 | kfree(au); | ||
653 | } | ||
654 | |||
655 | |||
656 | static void ceph_x_reset(struct ceph_auth_client *ac) | 656 | static void ceph_x_reset(struct ceph_auth_client *ac) |
657 | { | 657 | { |
658 | struct ceph_x_info *xi = ac->private; | 658 | struct ceph_x_info *xi = ac->private; |
@@ -770,7 +770,6 @@ static const struct ceph_auth_client_ops ceph_x_ops = { | |||
770 | .create_authorizer = ceph_x_create_authorizer, | 770 | .create_authorizer = ceph_x_create_authorizer, |
771 | .update_authorizer = ceph_x_update_authorizer, | 771 | .update_authorizer = ceph_x_update_authorizer, |
772 | .verify_authorizer_reply = ceph_x_verify_authorizer_reply, | 772 | .verify_authorizer_reply = ceph_x_verify_authorizer_reply, |
773 | .destroy_authorizer = ceph_x_destroy_authorizer, | ||
774 | .invalidate_authorizer = ceph_x_invalidate_authorizer, | 773 | .invalidate_authorizer = ceph_x_invalidate_authorizer, |
775 | .reset = ceph_x_reset, | 774 | .reset = ceph_x_reset, |
776 | .destroy = ceph_x_destroy, | 775 | .destroy = ceph_x_destroy, |
diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h index 40b1a3cf7397..21a5af904bae 100644 --- a/net/ceph/auth_x.h +++ b/net/ceph/auth_x.h | |||
@@ -26,6 +26,7 @@ struct ceph_x_ticket_handler { | |||
26 | 26 | ||
27 | 27 | ||
28 | struct ceph_x_authorizer { | 28 | struct ceph_x_authorizer { |
29 | struct ceph_authorizer base; | ||
29 | struct ceph_crypto_key session_key; | 30 | struct ceph_crypto_key session_key; |
30 | struct ceph_buffer *buf; | 31 | struct ceph_buffer *buf; |
31 | unsigned int service; | 32 | unsigned int service; |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 32355d9d0103..40a53a70efdf 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -1087,10 +1087,8 @@ static void put_osd(struct ceph_osd *osd) | |||
1087 | dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref), | 1087 | dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref), |
1088 | atomic_read(&osd->o_ref) - 1); | 1088 | atomic_read(&osd->o_ref) - 1); |
1089 | if (atomic_dec_and_test(&osd->o_ref)) { | 1089 | if (atomic_dec_and_test(&osd->o_ref)) { |
1090 | struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth; | ||
1091 | |||
1092 | if (osd->o_auth.authorizer) | 1090 | if (osd->o_auth.authorizer) |
1093 | ceph_auth_destroy_authorizer(ac, osd->o_auth.authorizer); | 1091 | ceph_auth_destroy_authorizer(osd->o_auth.authorizer); |
1094 | kfree(osd); | 1092 | kfree(osd); |
1095 | } | 1093 | } |
1096 | } | 1094 | } |
@@ -2984,7 +2982,7 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, | |||
2984 | struct ceph_auth_handshake *auth = &o->o_auth; | 2982 | struct ceph_auth_handshake *auth = &o->o_auth; |
2985 | 2983 | ||
2986 | if (force_new && auth->authorizer) { | 2984 | if (force_new && auth->authorizer) { |
2987 | ceph_auth_destroy_authorizer(ac, auth->authorizer); | 2985 | ceph_auth_destroy_authorizer(auth->authorizer); |
2988 | auth->authorizer = NULL; | 2986 | auth->authorizer = NULL; |
2989 | } | 2987 | } |
2990 | if (!auth->authorizer) { | 2988 | if (!auth->authorizer) { |
diff --git a/net/core/dev.c b/net/core/dev.c index 77a71cd68535..5c925ac50b95 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2802,7 +2802,7 @@ static netdev_features_t harmonize_features(struct sk_buff *skb, | |||
2802 | 2802 | ||
2803 | if (skb->ip_summed != CHECKSUM_NONE && | 2803 | if (skb->ip_summed != CHECKSUM_NONE && |
2804 | !can_checksum_protocol(features, type)) { | 2804 | !can_checksum_protocol(features, type)) { |
2805 | features &= ~NETIF_F_CSUM_MASK; | 2805 | features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK); |
2806 | } else if (illegal_highdma(skb->dev, skb)) { | 2806 | } else if (illegal_highdma(skb->dev, skb)) { |
2807 | features &= ~NETIF_F_SG; | 2807 | features &= ~NETIF_F_SG; |
2808 | } | 2808 | } |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 8a9246deccfe..63566ec54794 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -904,7 +904,11 @@ void fib_del_ifaddr(struct in_ifaddr *ifa, struct in_ifaddr *iprim) | |||
904 | if (ifa->ifa_flags & IFA_F_SECONDARY) { | 904 | if (ifa->ifa_flags & IFA_F_SECONDARY) { |
905 | prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); | 905 | prim = inet_ifa_byprefix(in_dev, any, ifa->ifa_mask); |
906 | if (!prim) { | 906 | if (!prim) { |
907 | pr_warn("%s: bug: prim == NULL\n", __func__); | 907 | /* if the device has been deleted, we don't perform |
908 | * address promotion | ||
909 | */ | ||
910 | if (!in_dev->dead) | ||
911 | pr_warn("%s: bug: prim == NULL\n", __func__); | ||
908 | return; | 912 | return; |
909 | } | 913 | } |
910 | if (iprim && iprim != prim) { | 914 | if (iprim && iprim != prim) { |
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index bc68eced0105..0d9e9d7bb029 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c | |||
@@ -470,6 +470,7 @@ static int inet_reuseport_add_sock(struct sock *sk, | |||
470 | const struct sock *sk2, | 470 | const struct sock *sk2, |
471 | bool match_wildcard)) | 471 | bool match_wildcard)) |
472 | { | 472 | { |
473 | struct inet_bind_bucket *tb = inet_csk(sk)->icsk_bind_hash; | ||
473 | struct sock *sk2; | 474 | struct sock *sk2; |
474 | struct hlist_nulls_node *node; | 475 | struct hlist_nulls_node *node; |
475 | kuid_t uid = sock_i_uid(sk); | 476 | kuid_t uid = sock_i_uid(sk); |
@@ -479,6 +480,7 @@ static int inet_reuseport_add_sock(struct sock *sk, | |||
479 | sk2->sk_family == sk->sk_family && | 480 | sk2->sk_family == sk->sk_family && |
480 | ipv6_only_sock(sk2) == ipv6_only_sock(sk) && | 481 | ipv6_only_sock(sk2) == ipv6_only_sock(sk) && |
481 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if && | 482 | sk2->sk_bound_dev_if == sk->sk_bound_dev_if && |
483 | inet_csk(sk2)->icsk_bind_hash == tb && | ||
482 | sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) && | 484 | sk2->sk_reuseport && uid_eq(uid, sock_i_uid(sk2)) && |
483 | saddr_same(sk, sk2, false)) | 485 | saddr_same(sk, sk2, false)) |
484 | return reuseport_add_sock(sk, sk2); | 486 | return reuseport_add_sock(sk, sk2); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index af5d1f38217f..205a2b8a5a84 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -179,6 +179,7 @@ static __be16 tnl_flags_to_gre_flags(__be16 tflags) | |||
179 | return flags; | 179 | return flags; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* Fills in tpi and returns header length to be pulled. */ | ||
182 | static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, | 183 | static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, |
183 | bool *csum_err) | 184 | bool *csum_err) |
184 | { | 185 | { |
@@ -238,7 +239,7 @@ static int parse_gre_header(struct sk_buff *skb, struct tnl_ptk_info *tpi, | |||
238 | return -EINVAL; | 239 | return -EINVAL; |
239 | } | 240 | } |
240 | } | 241 | } |
241 | return iptunnel_pull_header(skb, hdr_len, tpi->proto, false); | 242 | return hdr_len; |
242 | } | 243 | } |
243 | 244 | ||
244 | static void ipgre_err(struct sk_buff *skb, u32 info, | 245 | static void ipgre_err(struct sk_buff *skb, u32 info, |
@@ -341,7 +342,7 @@ static void gre_err(struct sk_buff *skb, u32 info) | |||
341 | struct tnl_ptk_info tpi; | 342 | struct tnl_ptk_info tpi; |
342 | bool csum_err = false; | 343 | bool csum_err = false; |
343 | 344 | ||
344 | if (parse_gre_header(skb, &tpi, &csum_err)) { | 345 | if (parse_gre_header(skb, &tpi, &csum_err) < 0) { |
345 | if (!csum_err) /* ignore csum errors. */ | 346 | if (!csum_err) /* ignore csum errors. */ |
346 | return; | 347 | return; |
347 | } | 348 | } |
@@ -419,6 +420,7 @@ static int gre_rcv(struct sk_buff *skb) | |||
419 | { | 420 | { |
420 | struct tnl_ptk_info tpi; | 421 | struct tnl_ptk_info tpi; |
421 | bool csum_err = false; | 422 | bool csum_err = false; |
423 | int hdr_len; | ||
422 | 424 | ||
423 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 425 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
424 | if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { | 426 | if (ipv4_is_multicast(ip_hdr(skb)->daddr)) { |
@@ -428,7 +430,10 @@ static int gre_rcv(struct sk_buff *skb) | |||
428 | } | 430 | } |
429 | #endif | 431 | #endif |
430 | 432 | ||
431 | if (parse_gre_header(skb, &tpi, &csum_err) < 0) | 433 | hdr_len = parse_gre_header(skb, &tpi, &csum_err); |
434 | if (hdr_len < 0) | ||
435 | goto drop; | ||
436 | if (iptunnel_pull_header(skb, hdr_len, tpi.proto, false) < 0) | ||
432 | goto drop; | 437 | goto drop; |
433 | 438 | ||
434 | if (ipgre_rcv(skb, &tpi) == PACKET_RCVD) | 439 | if (ipgre_rcv(skb, &tpi) == PACKET_RCVD) |
@@ -523,7 +528,8 @@ static struct rtable *gre_get_rt(struct sk_buff *skb, | |||
523 | return ip_route_output_key(net, fl); | 528 | return ip_route_output_key(net, fl); |
524 | } | 529 | } |
525 | 530 | ||
526 | static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) | 531 | static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev, |
532 | __be16 proto) | ||
527 | { | 533 | { |
528 | struct ip_tunnel_info *tun_info; | 534 | struct ip_tunnel_info *tun_info; |
529 | const struct ip_tunnel_key *key; | 535 | const struct ip_tunnel_key *key; |
@@ -575,7 +581,7 @@ static void gre_fb_xmit(struct sk_buff *skb, struct net_device *dev) | |||
575 | } | 581 | } |
576 | 582 | ||
577 | flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); | 583 | flags = tun_info->key.tun_flags & (TUNNEL_CSUM | TUNNEL_KEY); |
578 | build_header(skb, tunnel_hlen, flags, htons(ETH_P_TEB), | 584 | build_header(skb, tunnel_hlen, flags, proto, |
579 | tunnel_id_to_key(tun_info->key.tun_id), 0); | 585 | tunnel_id_to_key(tun_info->key.tun_id), 0); |
580 | 586 | ||
581 | df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; | 587 | df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0; |
@@ -616,7 +622,7 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, | |||
616 | const struct iphdr *tnl_params; | 622 | const struct iphdr *tnl_params; |
617 | 623 | ||
618 | if (tunnel->collect_md) { | 624 | if (tunnel->collect_md) { |
619 | gre_fb_xmit(skb, dev); | 625 | gre_fb_xmit(skb, dev, skb->protocol); |
620 | return NETDEV_TX_OK; | 626 | return NETDEV_TX_OK; |
621 | } | 627 | } |
622 | 628 | ||
@@ -660,7 +666,7 @@ static netdev_tx_t gre_tap_xmit(struct sk_buff *skb, | |||
660 | struct ip_tunnel *tunnel = netdev_priv(dev); | 666 | struct ip_tunnel *tunnel = netdev_priv(dev); |
661 | 667 | ||
662 | if (tunnel->collect_md) { | 668 | if (tunnel->collect_md) { |
663 | gre_fb_xmit(skb, dev); | 669 | gre_fb_xmit(skb, dev, htons(ETH_P_TEB)); |
664 | return NETDEV_TX_OK; | 670 | return NETDEV_TX_OK; |
665 | } | 671 | } |
666 | 672 | ||
@@ -893,7 +899,7 @@ static int ipgre_tunnel_init(struct net_device *dev) | |||
893 | netif_keep_dst(dev); | 899 | netif_keep_dst(dev); |
894 | dev->addr_len = 4; | 900 | dev->addr_len = 4; |
895 | 901 | ||
896 | if (iph->daddr) { | 902 | if (iph->daddr && !tunnel->collect_md) { |
897 | #ifdef CONFIG_NET_IPGRE_BROADCAST | 903 | #ifdef CONFIG_NET_IPGRE_BROADCAST |
898 | if (ipv4_is_multicast(iph->daddr)) { | 904 | if (ipv4_is_multicast(iph->daddr)) { |
899 | if (!iph->saddr) | 905 | if (!iph->saddr) |
@@ -902,8 +908,9 @@ static int ipgre_tunnel_init(struct net_device *dev) | |||
902 | dev->header_ops = &ipgre_header_ops; | 908 | dev->header_ops = &ipgre_header_ops; |
903 | } | 909 | } |
904 | #endif | 910 | #endif |
905 | } else | 911 | } else if (!tunnel->collect_md) { |
906 | dev->header_ops = &ipgre_header_ops; | 912 | dev->header_ops = &ipgre_header_ops; |
913 | } | ||
907 | 914 | ||
908 | return ip_tunnel_init(dev); | 915 | return ip_tunnel_init(dev); |
909 | } | 916 | } |
@@ -946,6 +953,11 @@ static int ipgre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
946 | if (flags & (GRE_VERSION|GRE_ROUTING)) | 953 | if (flags & (GRE_VERSION|GRE_ROUTING)) |
947 | return -EINVAL; | 954 | return -EINVAL; |
948 | 955 | ||
956 | if (data[IFLA_GRE_COLLECT_METADATA] && | ||
957 | data[IFLA_GRE_ENCAP_TYPE] && | ||
958 | nla_get_u16(data[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) | ||
959 | return -EINVAL; | ||
960 | |||
949 | return 0; | 961 | return 0; |
950 | } | 962 | } |
951 | 963 | ||
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 6aad0192443d..a69ed94bda1b 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -326,12 +326,12 @@ static int ip_tunnel_bind_dev(struct net_device *dev) | |||
326 | 326 | ||
327 | if (!IS_ERR(rt)) { | 327 | if (!IS_ERR(rt)) { |
328 | tdev = rt->dst.dev; | 328 | tdev = rt->dst.dev; |
329 | dst_cache_set_ip4(&tunnel->dst_cache, &rt->dst, | ||
330 | fl4.saddr); | ||
331 | ip_rt_put(rt); | 329 | ip_rt_put(rt); |
332 | } | 330 | } |
333 | if (dev->type != ARPHRD_ETHER) | 331 | if (dev->type != ARPHRD_ETHER) |
334 | dev->flags |= IFF_POINTOPOINT; | 332 | dev->flags |= IFF_POINTOPOINT; |
333 | |||
334 | dst_cache_reset(&tunnel->dst_cache); | ||
335 | } | 335 | } |
336 | 336 | ||
337 | if (!tdev && tunnel->parms.link) | 337 | if (!tdev && tunnel->parms.link) |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 23cec53b568a..8ec4b3089e20 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3176,35 +3176,9 @@ static void addrconf_gre_config(struct net_device *dev) | |||
3176 | } | 3176 | } |
3177 | #endif | 3177 | #endif |
3178 | 3178 | ||
3179 | #if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV) | ||
3180 | /* If the host route is cached on the addr struct make sure it is associated | ||
3181 | * with the proper table. e.g., enslavement can change and if so the cached | ||
3182 | * host route needs to move to the new table. | ||
3183 | */ | ||
3184 | static void l3mdev_check_host_rt(struct inet6_dev *idev, | ||
3185 | struct inet6_ifaddr *ifp) | ||
3186 | { | ||
3187 | if (ifp->rt) { | ||
3188 | u32 tb_id = l3mdev_fib_table(idev->dev) ? : RT6_TABLE_LOCAL; | ||
3189 | |||
3190 | if (tb_id != ifp->rt->rt6i_table->tb6_id) { | ||
3191 | ip6_del_rt(ifp->rt); | ||
3192 | ifp->rt = NULL; | ||
3193 | } | ||
3194 | } | ||
3195 | } | ||
3196 | #else | ||
3197 | static void l3mdev_check_host_rt(struct inet6_dev *idev, | ||
3198 | struct inet6_ifaddr *ifp) | ||
3199 | { | ||
3200 | } | ||
3201 | #endif | ||
3202 | |||
3203 | static int fixup_permanent_addr(struct inet6_dev *idev, | 3179 | static int fixup_permanent_addr(struct inet6_dev *idev, |
3204 | struct inet6_ifaddr *ifp) | 3180 | struct inet6_ifaddr *ifp) |
3205 | { | 3181 | { |
3206 | l3mdev_check_host_rt(idev, ifp); | ||
3207 | |||
3208 | if (!ifp->rt) { | 3182 | if (!ifp->rt) { |
3209 | struct rt6_info *rt; | 3183 | struct rt6_info *rt; |
3210 | 3184 | ||
@@ -3304,6 +3278,9 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
3304 | break; | 3278 | break; |
3305 | 3279 | ||
3306 | if (event == NETDEV_UP) { | 3280 | if (event == NETDEV_UP) { |
3281 | /* restore routes for permanent addresses */ | ||
3282 | addrconf_permanent_addr(dev); | ||
3283 | |||
3307 | if (!addrconf_qdisc_ok(dev)) { | 3284 | if (!addrconf_qdisc_ok(dev)) { |
3308 | /* device is not ready yet. */ | 3285 | /* device is not ready yet. */ |
3309 | pr_info("ADDRCONF(NETDEV_UP): %s: link is not ready\n", | 3286 | pr_info("ADDRCONF(NETDEV_UP): %s: link is not ready\n", |
@@ -3337,9 +3314,6 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
3337 | run_pending = 1; | 3314 | run_pending = 1; |
3338 | } | 3315 | } |
3339 | 3316 | ||
3340 | /* restore routes for permanent addresses */ | ||
3341 | addrconf_permanent_addr(dev); | ||
3342 | |||
3343 | switch (dev->type) { | 3317 | switch (dev->type) { |
3344 | #if IS_ENABLED(CONFIG_IPV6_SIT) | 3318 | #if IS_ENABLED(CONFIG_IPV6_SIT) |
3345 | case ARPHRD_SIT: | 3319 | case ARPHRD_SIT: |
@@ -3556,6 +3530,8 @@ restart: | |||
3556 | 3530 | ||
3557 | INIT_LIST_HEAD(&del_list); | 3531 | INIT_LIST_HEAD(&del_list); |
3558 | list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) { | 3532 | list_for_each_entry_safe(ifa, tmp, &idev->addr_list, if_list) { |
3533 | struct rt6_info *rt = NULL; | ||
3534 | |||
3559 | addrconf_del_dad_work(ifa); | 3535 | addrconf_del_dad_work(ifa); |
3560 | 3536 | ||
3561 | write_unlock_bh(&idev->lock); | 3537 | write_unlock_bh(&idev->lock); |
@@ -3568,6 +3544,9 @@ restart: | |||
3568 | ifa->state = 0; | 3544 | ifa->state = 0; |
3569 | if (!(ifa->flags & IFA_F_NODAD)) | 3545 | if (!(ifa->flags & IFA_F_NODAD)) |
3570 | ifa->flags |= IFA_F_TENTATIVE; | 3546 | ifa->flags |= IFA_F_TENTATIVE; |
3547 | |||
3548 | rt = ifa->rt; | ||
3549 | ifa->rt = NULL; | ||
3571 | } else { | 3550 | } else { |
3572 | state = ifa->state; | 3551 | state = ifa->state; |
3573 | ifa->state = INET6_IFADDR_STATE_DEAD; | 3552 | ifa->state = INET6_IFADDR_STATE_DEAD; |
@@ -3578,6 +3557,9 @@ restart: | |||
3578 | 3557 | ||
3579 | spin_unlock_bh(&ifa->lock); | 3558 | spin_unlock_bh(&ifa->lock); |
3580 | 3559 | ||
3560 | if (rt) | ||
3561 | ip6_del_rt(rt); | ||
3562 | |||
3581 | if (state != INET6_IFADDR_STATE_DEAD) { | 3563 | if (state != INET6_IFADDR_STATE_DEAD) { |
3582 | __ipv6_ifa_notify(RTM_DELADDR, ifa); | 3564 | __ipv6_ifa_notify(RTM_DELADDR, ifa); |
3583 | inet6addr_notifier_call_chain(NETDEV_DOWN, ifa); | 3565 | inet6addr_notifier_call_chain(NETDEV_DOWN, ifa); |
@@ -5343,10 +5325,10 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
5343 | if (rt) | 5325 | if (rt) |
5344 | ip6_del_rt(rt); | 5326 | ip6_del_rt(rt); |
5345 | } | 5327 | } |
5346 | dst_hold(&ifp->rt->dst); | 5328 | if (ifp->rt) { |
5347 | 5329 | dst_hold(&ifp->rt->dst); | |
5348 | ip6_del_rt(ifp->rt); | 5330 | ip6_del_rt(ifp->rt); |
5349 | 5331 | } | |
5350 | rt_genid_bump_ipv6(net); | 5332 | rt_genid_bump_ipv6(net); |
5351 | break; | 5333 | break; |
5352 | } | 5334 | } |
diff --git a/net/ipv6/ila/ila_lwt.c b/net/ipv6/ila/ila_lwt.c index 2ae3c4fd8aab..41f18de5dcc2 100644 --- a/net/ipv6/ila/ila_lwt.c +++ b/net/ipv6/ila/ila_lwt.c | |||
@@ -120,8 +120,7 @@ nla_put_failure: | |||
120 | 120 | ||
121 | static int ila_encap_nlsize(struct lwtunnel_state *lwtstate) | 121 | static int ila_encap_nlsize(struct lwtunnel_state *lwtstate) |
122 | { | 122 | { |
123 | /* No encapsulation overhead */ | 123 | return nla_total_size(sizeof(u64)); /* ILA_ATTR_LOCATOR */ |
124 | return 0; | ||
125 | } | 124 | } |
126 | 125 | ||
127 | static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b) | 126 | static int ila_encap_cmp(struct lwtunnel_state *a, struct lwtunnel_state *b) |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index afca2eb4dfa7..6edfa9980314 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -1376,9 +1376,9 @@ static int l2tp_tunnel_sock_create(struct net *net, | |||
1376 | memcpy(&udp_conf.peer_ip6, cfg->peer_ip6, | 1376 | memcpy(&udp_conf.peer_ip6, cfg->peer_ip6, |
1377 | sizeof(udp_conf.peer_ip6)); | 1377 | sizeof(udp_conf.peer_ip6)); |
1378 | udp_conf.use_udp6_tx_checksums = | 1378 | udp_conf.use_udp6_tx_checksums = |
1379 | cfg->udp6_zero_tx_checksums; | 1379 | ! cfg->udp6_zero_tx_checksums; |
1380 | udp_conf.use_udp6_rx_checksums = | 1380 | udp_conf.use_udp6_rx_checksums = |
1381 | cfg->udp6_zero_rx_checksums; | 1381 | ! cfg->udp6_zero_rx_checksums; |
1382 | } else | 1382 | } else |
1383 | #endif | 1383 | #endif |
1384 | { | 1384 | { |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 453b4e741780..e1cb22c16530 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1761,7 +1761,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1761 | 1761 | ||
1762 | ret = dev_alloc_name(ndev, ndev->name); | 1762 | ret = dev_alloc_name(ndev, ndev->name); |
1763 | if (ret < 0) { | 1763 | if (ret < 0) { |
1764 | free_netdev(ndev); | 1764 | ieee80211_if_free(ndev); |
1765 | return ret; | 1765 | return ret; |
1766 | } | 1766 | } |
1767 | 1767 | ||
@@ -1847,7 +1847,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1847 | 1847 | ||
1848 | ret = register_netdevice(ndev); | 1848 | ret = register_netdevice(ndev); |
1849 | if (ret) { | 1849 | if (ret) { |
1850 | free_netdev(ndev); | 1850 | ieee80211_if_free(ndev); |
1851 | return ret; | 1851 | return ret; |
1852 | } | 1852 | } |
1853 | } | 1853 | } |
diff --git a/net/rds/tcp.c b/net/rds/tcp.c index 61ed2a8764ba..86187dad1440 100644 --- a/net/rds/tcp.c +++ b/net/rds/tcp.c | |||
@@ -127,7 +127,7 @@ void rds_tcp_restore_callbacks(struct socket *sock, | |||
127 | 127 | ||
128 | /* | 128 | /* |
129 | * This is the only path that sets tc->t_sock. Send and receive trust that | 129 | * This is the only path that sets tc->t_sock. Send and receive trust that |
130 | * it is set. The RDS_CONN_CONNECTED bit protects those paths from being | 130 | * it is set. The RDS_CONN_UP bit protects those paths from being |
131 | * called while it isn't set. | 131 | * called while it isn't set. |
132 | */ | 132 | */ |
133 | void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn) | 133 | void rds_tcp_set_callbacks(struct socket *sock, struct rds_connection *conn) |
@@ -216,6 +216,7 @@ static int rds_tcp_conn_alloc(struct rds_connection *conn, gfp_t gfp) | |||
216 | if (!tc) | 216 | if (!tc) |
217 | return -ENOMEM; | 217 | return -ENOMEM; |
218 | 218 | ||
219 | mutex_init(&tc->t_conn_lock); | ||
219 | tc->t_sock = NULL; | 220 | tc->t_sock = NULL; |
220 | tc->t_tinc = NULL; | 221 | tc->t_tinc = NULL; |
221 | tc->t_tinc_hdr_rem = sizeof(struct rds_header); | 222 | tc->t_tinc_hdr_rem = sizeof(struct rds_header); |
diff --git a/net/rds/tcp.h b/net/rds/tcp.h index 64f873c0c6b6..41c228300525 100644 --- a/net/rds/tcp.h +++ b/net/rds/tcp.h | |||
@@ -12,6 +12,10 @@ struct rds_tcp_connection { | |||
12 | 12 | ||
13 | struct list_head t_tcp_node; | 13 | struct list_head t_tcp_node; |
14 | struct rds_connection *conn; | 14 | struct rds_connection *conn; |
15 | /* t_conn_lock synchronizes the connection establishment between | ||
16 | * rds_tcp_accept_one and rds_tcp_conn_connect | ||
17 | */ | ||
18 | struct mutex t_conn_lock; | ||
15 | struct socket *t_sock; | 19 | struct socket *t_sock; |
16 | void *t_orig_write_space; | 20 | void *t_orig_write_space; |
17 | void *t_orig_data_ready; | 21 | void *t_orig_data_ready; |
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index 5cb16875c460..49a3fcfed360 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c | |||
@@ -78,7 +78,14 @@ int rds_tcp_conn_connect(struct rds_connection *conn) | |||
78 | struct socket *sock = NULL; | 78 | struct socket *sock = NULL; |
79 | struct sockaddr_in src, dest; | 79 | struct sockaddr_in src, dest; |
80 | int ret; | 80 | int ret; |
81 | struct rds_tcp_connection *tc = conn->c_transport_data; | ||
82 | |||
83 | mutex_lock(&tc->t_conn_lock); | ||
81 | 84 | ||
85 | if (rds_conn_up(conn)) { | ||
86 | mutex_unlock(&tc->t_conn_lock); | ||
87 | return 0; | ||
88 | } | ||
82 | ret = sock_create_kern(rds_conn_net(conn), PF_INET, | 89 | ret = sock_create_kern(rds_conn_net(conn), PF_INET, |
83 | SOCK_STREAM, IPPROTO_TCP, &sock); | 90 | SOCK_STREAM, IPPROTO_TCP, &sock); |
84 | if (ret < 0) | 91 | if (ret < 0) |
@@ -120,6 +127,7 @@ int rds_tcp_conn_connect(struct rds_connection *conn) | |||
120 | } | 127 | } |
121 | 128 | ||
122 | out: | 129 | out: |
130 | mutex_unlock(&tc->t_conn_lock); | ||
123 | if (sock) | 131 | if (sock) |
124 | sock_release(sock); | 132 | sock_release(sock); |
125 | return ret; | 133 | return ret; |
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 0936a4a32b47..be263cdf268b 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c | |||
@@ -76,7 +76,9 @@ int rds_tcp_accept_one(struct socket *sock) | |||
76 | struct rds_connection *conn; | 76 | struct rds_connection *conn; |
77 | int ret; | 77 | int ret; |
78 | struct inet_sock *inet; | 78 | struct inet_sock *inet; |
79 | struct rds_tcp_connection *rs_tcp; | 79 | struct rds_tcp_connection *rs_tcp = NULL; |
80 | int conn_state; | ||
81 | struct sock *nsk; | ||
80 | 82 | ||
81 | ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family, | 83 | ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family, |
82 | sock->sk->sk_type, sock->sk->sk_protocol, | 84 | sock->sk->sk_type, sock->sk->sk_protocol, |
@@ -115,28 +117,44 @@ int rds_tcp_accept_one(struct socket *sock) | |||
115 | * rds_tcp_state_change() will do that cleanup | 117 | * rds_tcp_state_change() will do that cleanup |
116 | */ | 118 | */ |
117 | rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data; | 119 | rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data; |
118 | if (rs_tcp->t_sock && | ||
119 | ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) { | ||
120 | struct sock *nsk = new_sock->sk; | ||
121 | |||
122 | nsk->sk_user_data = NULL; | ||
123 | nsk->sk_prot->disconnect(nsk, 0); | ||
124 | tcp_done(nsk); | ||
125 | new_sock = NULL; | ||
126 | ret = 0; | ||
127 | goto out; | ||
128 | } else if (rs_tcp->t_sock) { | ||
129 | rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp); | ||
130 | conn->c_outgoing = 0; | ||
131 | } | ||
132 | |||
133 | rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING); | 120 | rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING); |
121 | mutex_lock(&rs_tcp->t_conn_lock); | ||
122 | conn_state = rds_conn_state(conn); | ||
123 | if (conn_state != RDS_CONN_CONNECTING && conn_state != RDS_CONN_UP) | ||
124 | goto rst_nsk; | ||
125 | if (rs_tcp->t_sock) { | ||
126 | /* Need to resolve a duelling SYN between peers. | ||
127 | * We have an outstanding SYN to this peer, which may | ||
128 | * potentially have transitioned to the RDS_CONN_UP state, | ||
129 | * so we must quiesce any send threads before resetting | ||
130 | * c_transport_data. | ||
131 | */ | ||
132 | wait_event(conn->c_waitq, | ||
133 | !test_bit(RDS_IN_XMIT, &conn->c_flags)); | ||
134 | if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) { | ||
135 | goto rst_nsk; | ||
136 | } else if (rs_tcp->t_sock) { | ||
137 | rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp); | ||
138 | conn->c_outgoing = 0; | ||
139 | } | ||
140 | } | ||
134 | rds_tcp_set_callbacks(new_sock, conn); | 141 | rds_tcp_set_callbacks(new_sock, conn); |
135 | rds_connect_complete(conn); | 142 | rds_connect_complete(conn); /* marks RDS_CONN_UP */ |
143 | new_sock = NULL; | ||
144 | ret = 0; | ||
145 | goto out; | ||
146 | rst_nsk: | ||
147 | /* reset the newly returned accept sock and bail */ | ||
148 | nsk = new_sock->sk; | ||
149 | rds_tcp_stats_inc(s_tcp_listen_closed_stale); | ||
150 | nsk->sk_user_data = NULL; | ||
151 | nsk->sk_prot->disconnect(nsk, 0); | ||
152 | tcp_done(nsk); | ||
136 | new_sock = NULL; | 153 | new_sock = NULL; |
137 | ret = 0; | 154 | ret = 0; |
138 | |||
139 | out: | 155 | out: |
156 | if (rs_tcp) | ||
157 | mutex_unlock(&rs_tcp->t_conn_lock); | ||
140 | if (new_sock) | 158 | if (new_sock) |
141 | sock_release(new_sock); | 159 | sock_release(new_sock); |
142 | return ret; | 160 | return ret; |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 9640bb39a5d2..4befe97a9034 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -395,6 +395,25 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) | |||
395 | sch->q.qlen++; | 395 | sch->q.qlen++; |
396 | } | 396 | } |
397 | 397 | ||
398 | /* netem can't properly corrupt a megapacket (like we get from GSO), so instead | ||
399 | * when we statistically choose to corrupt one, we instead segment it, returning | ||
400 | * the first packet to be corrupted, and re-enqueue the remaining frames | ||
401 | */ | ||
402 | static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch) | ||
403 | { | ||
404 | struct sk_buff *segs; | ||
405 | netdev_features_t features = netif_skb_features(skb); | ||
406 | |||
407 | segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); | ||
408 | |||
409 | if (IS_ERR_OR_NULL(segs)) { | ||
410 | qdisc_reshape_fail(skb, sch); | ||
411 | return NULL; | ||
412 | } | ||
413 | consume_skb(skb); | ||
414 | return segs; | ||
415 | } | ||
416 | |||
398 | /* | 417 | /* |
399 | * Insert one skb into qdisc. | 418 | * Insert one skb into qdisc. |
400 | * Note: parent depends on return value to account for queue length. | 419 | * Note: parent depends on return value to account for queue length. |
@@ -407,7 +426,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
407 | /* We don't fill cb now as skb_unshare() may invalidate it */ | 426 | /* We don't fill cb now as skb_unshare() may invalidate it */ |
408 | struct netem_skb_cb *cb; | 427 | struct netem_skb_cb *cb; |
409 | struct sk_buff *skb2; | 428 | struct sk_buff *skb2; |
429 | struct sk_buff *segs = NULL; | ||
430 | unsigned int len = 0, last_len, prev_len = qdisc_pkt_len(skb); | ||
431 | int nb = 0; | ||
410 | int count = 1; | 432 | int count = 1; |
433 | int rc = NET_XMIT_SUCCESS; | ||
411 | 434 | ||
412 | /* Random duplication */ | 435 | /* Random duplication */ |
413 | if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) | 436 | if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor)) |
@@ -453,10 +476,23 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
453 | * do it now in software before we mangle it. | 476 | * do it now in software before we mangle it. |
454 | */ | 477 | */ |
455 | if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) { | 478 | if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) { |
479 | if (skb_is_gso(skb)) { | ||
480 | segs = netem_segment(skb, sch); | ||
481 | if (!segs) | ||
482 | return NET_XMIT_DROP; | ||
483 | } else { | ||
484 | segs = skb; | ||
485 | } | ||
486 | |||
487 | skb = segs; | ||
488 | segs = segs->next; | ||
489 | |||
456 | if (!(skb = skb_unshare(skb, GFP_ATOMIC)) || | 490 | if (!(skb = skb_unshare(skb, GFP_ATOMIC)) || |
457 | (skb->ip_summed == CHECKSUM_PARTIAL && | 491 | (skb->ip_summed == CHECKSUM_PARTIAL && |
458 | skb_checksum_help(skb))) | 492 | skb_checksum_help(skb))) { |
459 | return qdisc_drop(skb, sch); | 493 | rc = qdisc_drop(skb, sch); |
494 | goto finish_segs; | ||
495 | } | ||
460 | 496 | ||
461 | skb->data[prandom_u32() % skb_headlen(skb)] ^= | 497 | skb->data[prandom_u32() % skb_headlen(skb)] ^= |
462 | 1<<(prandom_u32() % 8); | 498 | 1<<(prandom_u32() % 8); |
@@ -516,6 +552,27 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
516 | sch->qstats.requeues++; | 552 | sch->qstats.requeues++; |
517 | } | 553 | } |
518 | 554 | ||
555 | finish_segs: | ||
556 | if (segs) { | ||
557 | while (segs) { | ||
558 | skb2 = segs->next; | ||
559 | segs->next = NULL; | ||
560 | qdisc_skb_cb(segs)->pkt_len = segs->len; | ||
561 | last_len = segs->len; | ||
562 | rc = qdisc_enqueue(segs, sch); | ||
563 | if (rc != NET_XMIT_SUCCESS) { | ||
564 | if (net_xmit_drop_count(rc)) | ||
565 | qdisc_qstats_drop(sch); | ||
566 | } else { | ||
567 | nb++; | ||
568 | len += last_len; | ||
569 | } | ||
570 | segs = skb2; | ||
571 | } | ||
572 | sch->q.qlen += nb; | ||
573 | if (nb > 1) | ||
574 | qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len); | ||
575 | } | ||
519 | return NET_XMIT_SUCCESS; | 576 | return NET_XMIT_SUCCESS; |
520 | } | 577 | } |
521 | 578 | ||
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 2b9b98f1c2ff..b7e01d88bdc5 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -305,6 +305,8 @@ static void switchdev_port_attr_set_deferred(struct net_device *dev, | |||
305 | if (err && err != -EOPNOTSUPP) | 305 | if (err && err != -EOPNOTSUPP) |
306 | netdev_err(dev, "failed (err=%d) to set attribute (id=%d)\n", | 306 | netdev_err(dev, "failed (err=%d) to set attribute (id=%d)\n", |
307 | err, attr->id); | 307 | err, attr->id); |
308 | if (attr->complete) | ||
309 | attr->complete(dev, err, attr->complete_priv); | ||
308 | } | 310 | } |
309 | 311 | ||
310 | static int switchdev_port_attr_set_defer(struct net_device *dev, | 312 | static int switchdev_port_attr_set_defer(struct net_device *dev, |
@@ -434,6 +436,8 @@ static void switchdev_port_obj_add_deferred(struct net_device *dev, | |||
434 | if (err && err != -EOPNOTSUPP) | 436 | if (err && err != -EOPNOTSUPP) |
435 | netdev_err(dev, "failed (err=%d) to add object (id=%d)\n", | 437 | netdev_err(dev, "failed (err=%d) to add object (id=%d)\n", |
436 | err, obj->id); | 438 | err, obj->id); |
439 | if (obj->complete) | ||
440 | obj->complete(dev, err, obj->complete_priv); | ||
437 | } | 441 | } |
438 | 442 | ||
439 | static int switchdev_port_obj_add_defer(struct net_device *dev, | 443 | static int switchdev_port_obj_add_defer(struct net_device *dev, |
@@ -502,6 +506,8 @@ static void switchdev_port_obj_del_deferred(struct net_device *dev, | |||
502 | if (err && err != -EOPNOTSUPP) | 506 | if (err && err != -EOPNOTSUPP) |
503 | netdev_err(dev, "failed (err=%d) to del object (id=%d)\n", | 507 | netdev_err(dev, "failed (err=%d) to del object (id=%d)\n", |
504 | err, obj->id); | 508 | err, obj->id); |
509 | if (obj->complete) | ||
510 | obj->complete(dev, err, obj->complete_priv); | ||
505 | } | 511 | } |
506 | 512 | ||
507 | static int switchdev_port_obj_del_defer(struct net_device *dev, | 513 | static int switchdev_port_obj_del_defer(struct net_device *dev, |
diff --git a/net/tipc/node.c b/net/tipc/node.c index ace178fd3850..9aaa1bc566ae 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -1444,6 +1444,7 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
1444 | int bearer_id = b->identity; | 1444 | int bearer_id = b->identity; |
1445 | struct tipc_link_entry *le; | 1445 | struct tipc_link_entry *le; |
1446 | u16 bc_ack = msg_bcast_ack(hdr); | 1446 | u16 bc_ack = msg_bcast_ack(hdr); |
1447 | u32 self = tipc_own_addr(net); | ||
1447 | int rc = 0; | 1448 | int rc = 0; |
1448 | 1449 | ||
1449 | __skb_queue_head_init(&xmitq); | 1450 | __skb_queue_head_init(&xmitq); |
@@ -1460,6 +1461,10 @@ void tipc_rcv(struct net *net, struct sk_buff *skb, struct tipc_bearer *b) | |||
1460 | return tipc_node_bc_rcv(net, skb, bearer_id); | 1461 | return tipc_node_bc_rcv(net, skb, bearer_id); |
1461 | } | 1462 | } |
1462 | 1463 | ||
1464 | /* Discard unicast link messages destined for another node */ | ||
1465 | if (unlikely(!msg_short(hdr) && (msg_destnode(hdr) != self))) | ||
1466 | goto discard; | ||
1467 | |||
1463 | /* Locate neighboring node that sent packet */ | 1468 | /* Locate neighboring node that sent packet */ |
1464 | n = tipc_node_find(net, msg_prevnode(hdr)); | 1469 | n = tipc_node_find(net, msg_prevnode(hdr)); |
1465 | if (unlikely(!n)) | 1470 | if (unlikely(!n)) |