diff options
author | David S. Miller <davem@davemloft.net> | 2014-05-24 00:32:30 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-05-24 00:32:30 -0400 |
commit | 54e5c4def0614ab540fbdf68e45342a4af141702 (patch) | |
tree | 95a2f61c72336932e83d9e4180cd9739106d624b /net | |
parent | be65de7174123e02477bd488db1a657caf0f9947 (diff) | |
parent | 1ee1ceafb572f1a925809168267a7962a4289de8 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/bonding/bond_alb.c
drivers/net/ethernet/altera/altera_msgdma.c
drivers/net/ethernet/altera/altera_sgdma.c
net/ipv6/xfrm6_output.c
Several cases of overlapping changes.
The xfrm6_output.c has a bug fix which overlaps the renaming
of skb->local_df to skb->ignore_df.
In the Altera TSE driver cases, the register access cleanups
in net-next overlapped with bug fixes done in net.
Similarly a bug fix to send ALB packets in the bonding driver using
the right source address overlaps with cleanups in net-next.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
40 files changed, 420 insertions, 173 deletions
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 175273f38cb1..44ebd5c2cd4a 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -169,6 +169,7 @@ int register_vlan_dev(struct net_device *dev) | |||
169 | if (err < 0) | 169 | if (err < 0) |
170 | goto out_uninit_mvrp; | 170 | goto out_uninit_mvrp; |
171 | 171 | ||
172 | vlan->nest_level = dev_get_nest_level(real_dev, is_vlan_dev) + 1; | ||
172 | err = register_netdevice(dev); | 173 | err = register_netdevice(dev); |
173 | if (err < 0) | 174 | if (err < 0) |
174 | goto out_uninit_mvrp; | 175 | goto out_uninit_mvrp; |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 4181fb71ba77..ad2ac3c00398 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -493,48 +493,10 @@ static void vlan_dev_change_rx_flags(struct net_device *dev, int change) | |||
493 | } | 493 | } |
494 | } | 494 | } |
495 | 495 | ||
496 | static int vlan_calculate_locking_subclass(struct net_device *real_dev) | ||
497 | { | ||
498 | int subclass = 0; | ||
499 | |||
500 | while (is_vlan_dev(real_dev)) { | ||
501 | subclass++; | ||
502 | real_dev = vlan_dev_priv(real_dev)->real_dev; | ||
503 | } | ||
504 | |||
505 | return subclass; | ||
506 | } | ||
507 | |||
508 | static void vlan_dev_mc_sync(struct net_device *to, struct net_device *from) | ||
509 | { | ||
510 | int err = 0, subclass; | ||
511 | |||
512 | subclass = vlan_calculate_locking_subclass(to); | ||
513 | |||
514 | spin_lock_nested(&to->addr_list_lock, subclass); | ||
515 | err = __hw_addr_sync(&to->mc, &from->mc, to->addr_len); | ||
516 | if (!err) | ||
517 | __dev_set_rx_mode(to); | ||
518 | spin_unlock(&to->addr_list_lock); | ||
519 | } | ||
520 | |||
521 | static void vlan_dev_uc_sync(struct net_device *to, struct net_device *from) | ||
522 | { | ||
523 | int err = 0, subclass; | ||
524 | |||
525 | subclass = vlan_calculate_locking_subclass(to); | ||
526 | |||
527 | spin_lock_nested(&to->addr_list_lock, subclass); | ||
528 | err = __hw_addr_sync(&to->uc, &from->uc, to->addr_len); | ||
529 | if (!err) | ||
530 | __dev_set_rx_mode(to); | ||
531 | spin_unlock(&to->addr_list_lock); | ||
532 | } | ||
533 | |||
534 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) | 496 | static void vlan_dev_set_rx_mode(struct net_device *vlan_dev) |
535 | { | 497 | { |
536 | vlan_dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); | 498 | dev_mc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); |
537 | vlan_dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); | 499 | dev_uc_sync(vlan_dev_priv(vlan_dev)->real_dev, vlan_dev); |
538 | } | 500 | } |
539 | 501 | ||
540 | /* | 502 | /* |
@@ -562,6 +524,11 @@ static void vlan_dev_set_lockdep_class(struct net_device *dev, int subclass) | |||
562 | netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass); | 524 | netdev_for_each_tx_queue(dev, vlan_dev_set_lockdep_one, &subclass); |
563 | } | 525 | } |
564 | 526 | ||
527 | static int vlan_dev_get_lock_subclass(struct net_device *dev) | ||
528 | { | ||
529 | return vlan_dev_priv(dev)->nest_level; | ||
530 | } | ||
531 | |||
565 | static const struct header_ops vlan_header_ops = { | 532 | static const struct header_ops vlan_header_ops = { |
566 | .create = vlan_dev_hard_header, | 533 | .create = vlan_dev_hard_header, |
567 | .rebuild = vlan_dev_rebuild_header, | 534 | .rebuild = vlan_dev_rebuild_header, |
@@ -597,7 +564,6 @@ static const struct net_device_ops vlan_netdev_ops; | |||
597 | static int vlan_dev_init(struct net_device *dev) | 564 | static int vlan_dev_init(struct net_device *dev) |
598 | { | 565 | { |
599 | struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; | 566 | struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; |
600 | int subclass = 0; | ||
601 | 567 | ||
602 | netif_carrier_off(dev); | 568 | netif_carrier_off(dev); |
603 | 569 | ||
@@ -646,8 +612,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
646 | 612 | ||
647 | SET_NETDEV_DEVTYPE(dev, &vlan_type); | 613 | SET_NETDEV_DEVTYPE(dev, &vlan_type); |
648 | 614 | ||
649 | subclass = vlan_calculate_locking_subclass(dev); | 615 | vlan_dev_set_lockdep_class(dev, vlan_dev_get_lock_subclass(dev)); |
650 | vlan_dev_set_lockdep_class(dev, subclass); | ||
651 | 616 | ||
652 | vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); | 617 | vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
653 | if (!vlan_dev_priv(dev)->vlan_pcpu_stats) | 618 | if (!vlan_dev_priv(dev)->vlan_pcpu_stats) |
@@ -817,6 +782,7 @@ static const struct net_device_ops vlan_netdev_ops = { | |||
817 | .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, | 782 | .ndo_netpoll_cleanup = vlan_dev_netpoll_cleanup, |
818 | #endif | 783 | #endif |
819 | .ndo_fix_features = vlan_dev_fix_features, | 784 | .ndo_fix_features = vlan_dev_fix_features, |
785 | .ndo_get_lock_subclass = vlan_dev_get_lock_subclass, | ||
820 | }; | 786 | }; |
821 | 787 | ||
822 | void vlan_setup(struct net_device *dev) | 788 | void vlan_setup(struct net_device *dev) |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index b3bd4ec3fd94..f04224c32005 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -1545,6 +1545,8 @@ out_neigh: | |||
1545 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 1545 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
1546 | batadv_orig_node_free_ref(orig_neigh_node); | 1546 | batadv_orig_node_free_ref(orig_neigh_node); |
1547 | out: | 1547 | out: |
1548 | if (router_ifinfo) | ||
1549 | batadv_neigh_ifinfo_free_ref(router_ifinfo); | ||
1548 | if (router) | 1550 | if (router) |
1549 | batadv_neigh_node_free_ref(router); | 1551 | batadv_neigh_node_free_ref(router); |
1550 | if (router_router) | 1552 | if (router_router) |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index 60889df808f3..dcd99b2bea3c 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -941,8 +941,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv, | |||
941 | * additional DAT answer may trigger kernel warnings about | 941 | * additional DAT answer may trigger kernel warnings about |
942 | * a packet coming from the wrong port. | 942 | * a packet coming from the wrong port. |
943 | */ | 943 | */ |
944 | if (batadv_is_my_client(bat_priv, dat_entry->mac_addr, | 944 | if (batadv_is_my_client(bat_priv, dat_entry->mac_addr, vid)) { |
945 | BATADV_NO_FLAGS)) { | ||
946 | ret = true; | 945 | ret = true; |
947 | goto out; | 946 | goto out; |
948 | } | 947 | } |
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index bcc4bea632fa..f14e54a05691 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
@@ -418,12 +418,13 @@ bool batadv_frag_send_packet(struct sk_buff *skb, | |||
418 | struct batadv_neigh_node *neigh_node) | 418 | struct batadv_neigh_node *neigh_node) |
419 | { | 419 | { |
420 | struct batadv_priv *bat_priv; | 420 | struct batadv_priv *bat_priv; |
421 | struct batadv_hard_iface *primary_if; | 421 | struct batadv_hard_iface *primary_if = NULL; |
422 | struct batadv_frag_packet frag_header; | 422 | struct batadv_frag_packet frag_header; |
423 | struct sk_buff *skb_fragment; | 423 | struct sk_buff *skb_fragment; |
424 | unsigned mtu = neigh_node->if_incoming->net_dev->mtu; | 424 | unsigned mtu = neigh_node->if_incoming->net_dev->mtu; |
425 | unsigned header_size = sizeof(frag_header); | 425 | unsigned header_size = sizeof(frag_header); |
426 | unsigned max_fragment_size, max_packet_size; | 426 | unsigned max_fragment_size, max_packet_size; |
427 | bool ret = false; | ||
427 | 428 | ||
428 | /* To avoid merge and refragmentation at next-hops we never send | 429 | /* To avoid merge and refragmentation at next-hops we never send |
429 | * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE | 430 | * fragments larger than BATADV_FRAG_MAX_FRAG_SIZE |
@@ -483,7 +484,11 @@ bool batadv_frag_send_packet(struct sk_buff *skb, | |||
483 | skb->len + ETH_HLEN); | 484 | skb->len + ETH_HLEN); |
484 | batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 485 | batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
485 | 486 | ||
486 | return true; | 487 | ret = true; |
488 | |||
487 | out_err: | 489 | out_err: |
488 | return false; | 490 | if (primary_if) |
491 | batadv_hardif_free_ref(primary_if); | ||
492 | |||
493 | return ret; | ||
489 | } | 494 | } |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index c835e137423b..90cff585b37d 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -42,8 +42,10 @@ | |||
42 | 42 | ||
43 | static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) | 43 | static void batadv_gw_node_free_ref(struct batadv_gw_node *gw_node) |
44 | { | 44 | { |
45 | if (atomic_dec_and_test(&gw_node->refcount)) | 45 | if (atomic_dec_and_test(&gw_node->refcount)) { |
46 | batadv_orig_node_free_ref(gw_node->orig_node); | ||
46 | kfree_rcu(gw_node, rcu); | 47 | kfree_rcu(gw_node, rcu); |
48 | } | ||
47 | } | 49 | } |
48 | 50 | ||
49 | static struct batadv_gw_node * | 51 | static struct batadv_gw_node * |
@@ -406,9 +408,14 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, | |||
406 | if (gateway->bandwidth_down == 0) | 408 | if (gateway->bandwidth_down == 0) |
407 | return; | 409 | return; |
408 | 410 | ||
411 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
412 | return; | ||
413 | |||
409 | gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); | 414 | gw_node = kzalloc(sizeof(*gw_node), GFP_ATOMIC); |
410 | if (!gw_node) | 415 | if (!gw_node) { |
416 | batadv_orig_node_free_ref(orig_node); | ||
411 | return; | 417 | return; |
418 | } | ||
412 | 419 | ||
413 | INIT_HLIST_NODE(&gw_node->list); | 420 | INIT_HLIST_NODE(&gw_node->list); |
414 | gw_node->orig_node = orig_node; | 421 | gw_node->orig_node = orig_node; |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b851cc580853..fbda6b54baff 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -83,7 +83,7 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev) | |||
83 | return true; | 83 | return true; |
84 | 84 | ||
85 | /* no more parents..stop recursion */ | 85 | /* no more parents..stop recursion */ |
86 | if (net_dev->iflink == net_dev->ifindex) | 86 | if (net_dev->iflink == 0 || net_dev->iflink == net_dev->ifindex) |
87 | return false; | 87 | return false; |
88 | 88 | ||
89 | /* recurse over the parent device */ | 89 | /* recurse over the parent device */ |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ffd9dfbd9b0e..6a484514cd3e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -501,12 +501,17 @@ batadv_neigh_node_get(const struct batadv_orig_node *orig_node, | |||
501 | static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) | 501 | static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) |
502 | { | 502 | { |
503 | struct batadv_orig_ifinfo *orig_ifinfo; | 503 | struct batadv_orig_ifinfo *orig_ifinfo; |
504 | struct batadv_neigh_node *router; | ||
504 | 505 | ||
505 | orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu); | 506 | orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu); |
506 | 507 | ||
507 | if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) | 508 | if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) |
508 | batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing); | 509 | batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing); |
509 | 510 | ||
511 | /* this is the last reference to this object */ | ||
512 | router = rcu_dereference_protected(orig_ifinfo->router, true); | ||
513 | if (router) | ||
514 | batadv_neigh_node_free_ref_now(router); | ||
510 | kfree(orig_ifinfo); | 515 | kfree(orig_ifinfo); |
511 | } | 516 | } |
512 | 517 | ||
@@ -702,6 +707,47 @@ free_orig_node: | |||
702 | } | 707 | } |
703 | 708 | ||
704 | /** | 709 | /** |
710 | * batadv_purge_neigh_ifinfo - purge obsolete ifinfo entries from neighbor | ||
711 | * @bat_priv: the bat priv with all the soft interface information | ||
712 | * @neigh: orig node which is to be checked | ||
713 | */ | ||
714 | static void | ||
715 | batadv_purge_neigh_ifinfo(struct batadv_priv *bat_priv, | ||
716 | struct batadv_neigh_node *neigh) | ||
717 | { | ||
718 | struct batadv_neigh_ifinfo *neigh_ifinfo; | ||
719 | struct batadv_hard_iface *if_outgoing; | ||
720 | struct hlist_node *node_tmp; | ||
721 | |||
722 | spin_lock_bh(&neigh->ifinfo_lock); | ||
723 | |||
724 | /* for all ifinfo objects for this neighinator */ | ||
725 | hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, | ||
726 | &neigh->ifinfo_list, list) { | ||
727 | if_outgoing = neigh_ifinfo->if_outgoing; | ||
728 | |||
729 | /* always keep the default interface */ | ||
730 | if (if_outgoing == BATADV_IF_DEFAULT) | ||
731 | continue; | ||
732 | |||
733 | /* don't purge if the interface is not (going) down */ | ||
734 | if ((if_outgoing->if_status != BATADV_IF_INACTIVE) && | ||
735 | (if_outgoing->if_status != BATADV_IF_NOT_IN_USE) && | ||
736 | (if_outgoing->if_status != BATADV_IF_TO_BE_REMOVED)) | ||
737 | continue; | ||
738 | |||
739 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | ||
740 | "neighbor/ifinfo purge: neighbor %pM, iface: %s\n", | ||
741 | neigh->addr, if_outgoing->net_dev->name); | ||
742 | |||
743 | hlist_del_rcu(&neigh_ifinfo->list); | ||
744 | batadv_neigh_ifinfo_free_ref(neigh_ifinfo); | ||
745 | } | ||
746 | |||
747 | spin_unlock_bh(&neigh->ifinfo_lock); | ||
748 | } | ||
749 | |||
750 | /** | ||
705 | * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator | 751 | * batadv_purge_orig_ifinfo - purge obsolete ifinfo entries from originator |
706 | * @bat_priv: the bat priv with all the soft interface information | 752 | * @bat_priv: the bat priv with all the soft interface information |
707 | * @orig_node: orig node which is to be checked | 753 | * @orig_node: orig node which is to be checked |
@@ -800,6 +846,11 @@ batadv_purge_orig_neighbors(struct batadv_priv *bat_priv, | |||
800 | 846 | ||
801 | hlist_del_rcu(&neigh_node->list); | 847 | hlist_del_rcu(&neigh_node->list); |
802 | batadv_neigh_node_free_ref(neigh_node); | 848 | batadv_neigh_node_free_ref(neigh_node); |
849 | } else { | ||
850 | /* only necessary if not the whole neighbor is to be | ||
851 | * deleted, but some interface has been removed. | ||
852 | */ | ||
853 | batadv_purge_neigh_ifinfo(bat_priv, neigh_node); | ||
803 | } | 854 | } |
804 | } | 855 | } |
805 | 856 | ||
@@ -857,7 +908,7 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, | |||
857 | { | 908 | { |
858 | struct batadv_neigh_node *best_neigh_node; | 909 | struct batadv_neigh_node *best_neigh_node; |
859 | struct batadv_hard_iface *hard_iface; | 910 | struct batadv_hard_iface *hard_iface; |
860 | bool changed; | 911 | bool changed_ifinfo, changed_neigh; |
861 | 912 | ||
862 | if (batadv_has_timed_out(orig_node->last_seen, | 913 | if (batadv_has_timed_out(orig_node->last_seen, |
863 | 2 * BATADV_PURGE_TIMEOUT)) { | 914 | 2 * BATADV_PURGE_TIMEOUT)) { |
@@ -867,10 +918,10 @@ static bool batadv_purge_orig_node(struct batadv_priv *bat_priv, | |||
867 | jiffies_to_msecs(orig_node->last_seen)); | 918 | jiffies_to_msecs(orig_node->last_seen)); |
868 | return true; | 919 | return true; |
869 | } | 920 | } |
870 | changed = batadv_purge_orig_ifinfo(bat_priv, orig_node); | 921 | changed_ifinfo = batadv_purge_orig_ifinfo(bat_priv, orig_node); |
871 | changed = changed || batadv_purge_orig_neighbors(bat_priv, orig_node); | 922 | changed_neigh = batadv_purge_orig_neighbors(bat_priv, orig_node); |
872 | 923 | ||
873 | if (!changed) | 924 | if (!changed_ifinfo && !changed_neigh) |
874 | return false; | 925 | return false; |
875 | 926 | ||
876 | /* first for NULL ... */ | 927 | /* first for NULL ... */ |
@@ -1028,7 +1079,8 @@ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset) | |||
1028 | bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface); | 1079 | bat_priv->bat_algo_ops->bat_orig_print(bat_priv, seq, hard_iface); |
1029 | 1080 | ||
1030 | out: | 1081 | out: |
1031 | batadv_hardif_free_ref(hard_iface); | 1082 | if (hard_iface) |
1083 | batadv_hardif_free_ref(hard_iface); | ||
1032 | return 0; | 1084 | return 0; |
1033 | } | 1085 | } |
1034 | 1086 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index dac7f9b98687..1948d592aa54 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -557,7 +557,7 @@ static int ceph_tcp_sendmsg(struct socket *sock, struct kvec *iov, | |||
557 | return r; | 557 | return r; |
558 | } | 558 | } |
559 | 559 | ||
560 | static int ceph_tcp_sendpage(struct socket *sock, struct page *page, | 560 | static int __ceph_tcp_sendpage(struct socket *sock, struct page *page, |
561 | int offset, size_t size, bool more) | 561 | int offset, size_t size, bool more) |
562 | { | 562 | { |
563 | int flags = MSG_DONTWAIT | MSG_NOSIGNAL | (more ? MSG_MORE : MSG_EOR); | 563 | int flags = MSG_DONTWAIT | MSG_NOSIGNAL | (more ? MSG_MORE : MSG_EOR); |
@@ -570,6 +570,24 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, | |||
570 | return ret; | 570 | return ret; |
571 | } | 571 | } |
572 | 572 | ||
573 | static int ceph_tcp_sendpage(struct socket *sock, struct page *page, | ||
574 | int offset, size_t size, bool more) | ||
575 | { | ||
576 | int ret; | ||
577 | struct kvec iov; | ||
578 | |||
579 | /* sendpage cannot properly handle pages with page_count == 0, | ||
580 | * we need to fallback to sendmsg if that's the case */ | ||
581 | if (page_count(page) >= 1) | ||
582 | return __ceph_tcp_sendpage(sock, page, offset, size, more); | ||
583 | |||
584 | iov.iov_base = kmap(page) + offset; | ||
585 | iov.iov_len = size; | ||
586 | ret = ceph_tcp_sendmsg(sock, &iov, 1, size, more); | ||
587 | kunmap(page); | ||
588 | |||
589 | return ret; | ||
590 | } | ||
573 | 591 | ||
574 | /* | 592 | /* |
575 | * Shutdown/close the socket for the given connection. | 593 | * Shutdown/close the socket for the given connection. |
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 8b8a5a24b223..c547e46084d3 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
@@ -329,6 +329,11 @@ static struct crush_map *crush_decode(void *pbyval, void *end) | |||
329 | dout("crush decode tunable chooseleaf_descend_once = %d", | 329 | dout("crush decode tunable chooseleaf_descend_once = %d", |
330 | c->chooseleaf_descend_once); | 330 | c->chooseleaf_descend_once); |
331 | 331 | ||
332 | ceph_decode_need(p, end, sizeof(u8), done); | ||
333 | c->chooseleaf_vary_r = ceph_decode_8(p); | ||
334 | dout("crush decode tunable chooseleaf_vary_r = %d", | ||
335 | c->chooseleaf_vary_r); | ||
336 | |||
332 | done: | 337 | done: |
333 | dout("crush_decode success\n"); | 338 | dout("crush_decode success\n"); |
334 | return c; | 339 | return c; |
diff --git a/net/core/dev.c b/net/core/dev.c index 867adb25b5b8..0355ca5d2924 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -3957,6 +3957,7 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
3957 | } | 3957 | } |
3958 | NAPI_GRO_CB(skb)->count = 1; | 3958 | NAPI_GRO_CB(skb)->count = 1; |
3959 | NAPI_GRO_CB(skb)->age = jiffies; | 3959 | NAPI_GRO_CB(skb)->age = jiffies; |
3960 | NAPI_GRO_CB(skb)->last = skb; | ||
3960 | skb_shinfo(skb)->gso_size = skb_gro_len(skb); | 3961 | skb_shinfo(skb)->gso_size = skb_gro_len(skb); |
3961 | skb->next = napi->gro_list; | 3962 | skb->next = napi->gro_list; |
3962 | napi->gro_list = skb; | 3963 | napi->gro_list = skb; |
@@ -4547,6 +4548,32 @@ void *netdev_adjacent_get_private(struct list_head *adj_list) | |||
4547 | EXPORT_SYMBOL(netdev_adjacent_get_private); | 4548 | EXPORT_SYMBOL(netdev_adjacent_get_private); |
4548 | 4549 | ||
4549 | /** | 4550 | /** |
4551 | * netdev_upper_get_next_dev_rcu - Get the next dev from upper list | ||
4552 | * @dev: device | ||
4553 | * @iter: list_head ** of the current position | ||
4554 | * | ||
4555 | * Gets the next device from the dev's upper list, starting from iter | ||
4556 | * position. The caller must hold RCU read lock. | ||
4557 | */ | ||
4558 | struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev, | ||
4559 | struct list_head **iter) | ||
4560 | { | ||
4561 | struct netdev_adjacent *upper; | ||
4562 | |||
4563 | WARN_ON_ONCE(!rcu_read_lock_held() && !lockdep_rtnl_is_held()); | ||
4564 | |||
4565 | upper = list_entry_rcu((*iter)->next, struct netdev_adjacent, list); | ||
4566 | |||
4567 | if (&upper->list == &dev->adj_list.upper) | ||
4568 | return NULL; | ||
4569 | |||
4570 | *iter = &upper->list; | ||
4571 | |||
4572 | return upper->dev; | ||
4573 | } | ||
4574 | EXPORT_SYMBOL(netdev_upper_get_next_dev_rcu); | ||
4575 | |||
4576 | /** | ||
4550 | * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list | 4577 | * netdev_all_upper_get_next_dev_rcu - Get the next dev from upper list |
4551 | * @dev: device | 4578 | * @dev: device |
4552 | * @iter: list_head ** of the current position | 4579 | * @iter: list_head ** of the current position |
@@ -4628,6 +4655,32 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, | |||
4628 | EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); | 4655 | EXPORT_SYMBOL(netdev_lower_get_next_private_rcu); |
4629 | 4656 | ||
4630 | /** | 4657 | /** |
4658 | * netdev_lower_get_next - Get the next device from the lower neighbour | ||
4659 | * list | ||
4660 | * @dev: device | ||
4661 | * @iter: list_head ** of the current position | ||
4662 | * | ||
4663 | * Gets the next netdev_adjacent from the dev's lower neighbour | ||
4664 | * list, starting from iter position. The caller must hold RTNL lock or | ||
4665 | * its own locking that guarantees that the neighbour lower | ||
4666 | * list will remain unchainged. | ||
4667 | */ | ||
4668 | void *netdev_lower_get_next(struct net_device *dev, struct list_head **iter) | ||
4669 | { | ||
4670 | struct netdev_adjacent *lower; | ||
4671 | |||
4672 | lower = list_entry((*iter)->next, struct netdev_adjacent, list); | ||
4673 | |||
4674 | if (&lower->list == &dev->adj_list.lower) | ||
4675 | return NULL; | ||
4676 | |||
4677 | *iter = &lower->list; | ||
4678 | |||
4679 | return lower->dev; | ||
4680 | } | ||
4681 | EXPORT_SYMBOL(netdev_lower_get_next); | ||
4682 | |||
4683 | /** | ||
4631 | * netdev_lower_get_first_private_rcu - Get the first ->private from the | 4684 | * netdev_lower_get_first_private_rcu - Get the first ->private from the |
4632 | * lower neighbour list, RCU | 4685 | * lower neighbour list, RCU |
4633 | * variant | 4686 | * variant |
@@ -5077,6 +5130,30 @@ void *netdev_lower_dev_get_private(struct net_device *dev, | |||
5077 | } | 5130 | } |
5078 | EXPORT_SYMBOL(netdev_lower_dev_get_private); | 5131 | EXPORT_SYMBOL(netdev_lower_dev_get_private); |
5079 | 5132 | ||
5133 | |||
5134 | int dev_get_nest_level(struct net_device *dev, | ||
5135 | bool (*type_check)(struct net_device *dev)) | ||
5136 | { | ||
5137 | struct net_device *lower = NULL; | ||
5138 | struct list_head *iter; | ||
5139 | int max_nest = -1; | ||
5140 | int nest; | ||
5141 | |||
5142 | ASSERT_RTNL(); | ||
5143 | |||
5144 | netdev_for_each_lower_dev(dev, lower, iter) { | ||
5145 | nest = dev_get_nest_level(lower, type_check); | ||
5146 | if (max_nest < nest) | ||
5147 | max_nest = nest; | ||
5148 | } | ||
5149 | |||
5150 | if (type_check(dev)) | ||
5151 | max_nest++; | ||
5152 | |||
5153 | return max_nest; | ||
5154 | } | ||
5155 | EXPORT_SYMBOL(dev_get_nest_level); | ||
5156 | |||
5080 | static void dev_change_rx_flags(struct net_device *dev, int flags) | 5157 | static void dev_change_rx_flags(struct net_device *dev, int flags) |
5081 | { | 5158 | { |
5082 | const struct net_device_ops *ops = dev->netdev_ops; | 5159 | const struct net_device_ops *ops = dev->netdev_ops; |
@@ -5242,7 +5319,6 @@ void __dev_set_rx_mode(struct net_device *dev) | |||
5242 | if (ops->ndo_set_rx_mode) | 5319 | if (ops->ndo_set_rx_mode) |
5243 | ops->ndo_set_rx_mode(dev); | 5320 | ops->ndo_set_rx_mode(dev); |
5244 | } | 5321 | } |
5245 | EXPORT_SYMBOL(__dev_set_rx_mode); | ||
5246 | 5322 | ||
5247 | void dev_set_rx_mode(struct net_device *dev) | 5323 | void dev_set_rx_mode(struct net_device *dev) |
5248 | { | 5324 | { |
@@ -5547,7 +5623,7 @@ static int dev_new_index(struct net *net) | |||
5547 | 5623 | ||
5548 | /* Delayed registration/unregisteration */ | 5624 | /* Delayed registration/unregisteration */ |
5549 | static LIST_HEAD(net_todo_list); | 5625 | static LIST_HEAD(net_todo_list); |
5550 | static DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq); | 5626 | DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq); |
5551 | 5627 | ||
5552 | static void net_set_todo(struct net_device *dev) | 5628 | static void net_set_todo(struct net_device *dev) |
5553 | { | 5629 | { |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 8f8a96ef9f3f..32d872eec7f5 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
@@ -1248,8 +1248,8 @@ void __neigh_set_probe_once(struct neighbour *neigh) | |||
1248 | neigh->updated = jiffies; | 1248 | neigh->updated = jiffies; |
1249 | if (!(neigh->nud_state & NUD_FAILED)) | 1249 | if (!(neigh->nud_state & NUD_FAILED)) |
1250 | return; | 1250 | return; |
1251 | neigh->nud_state = NUD_PROBE; | 1251 | neigh->nud_state = NUD_INCOMPLETE; |
1252 | atomic_set(&neigh->probes, NEIGH_VAR(neigh->parms, UCAST_PROBES)); | 1252 | atomic_set(&neigh->probes, neigh_max_probes(neigh)); |
1253 | neigh_add_timer(neigh, | 1253 | neigh_add_timer(neigh, |
1254 | jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME)); | 1254 | jiffies + NEIGH_VAR(neigh->parms, RETRANS_TIME)); |
1255 | } | 1255 | } |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 05e949d48204..85b62691f4f2 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | static LIST_HEAD(pernet_list); | 25 | static LIST_HEAD(pernet_list); |
26 | static struct list_head *first_device = &pernet_list; | 26 | static struct list_head *first_device = &pernet_list; |
27 | static DEFINE_MUTEX(net_mutex); | 27 | DEFINE_MUTEX(net_mutex); |
28 | 28 | ||
29 | LIST_HEAD(net_namespace_list); | 29 | LIST_HEAD(net_namespace_list); |
30 | EXPORT_SYMBOL_GPL(net_namespace_list); | 30 | EXPORT_SYMBOL_GPL(net_namespace_list); |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d6417464dc66..f31268dbc0d1 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -353,15 +353,46 @@ void __rtnl_link_unregister(struct rtnl_link_ops *ops) | |||
353 | } | 353 | } |
354 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | 354 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); |
355 | 355 | ||
356 | /* Return with the rtnl_lock held when there are no network | ||
357 | * devices unregistering in any network namespace. | ||
358 | */ | ||
359 | static void rtnl_lock_unregistering_all(void) | ||
360 | { | ||
361 | struct net *net; | ||
362 | bool unregistering; | ||
363 | DEFINE_WAIT(wait); | ||
364 | |||
365 | for (;;) { | ||
366 | prepare_to_wait(&netdev_unregistering_wq, &wait, | ||
367 | TASK_UNINTERRUPTIBLE); | ||
368 | unregistering = false; | ||
369 | rtnl_lock(); | ||
370 | for_each_net(net) { | ||
371 | if (net->dev_unreg_count > 0) { | ||
372 | unregistering = true; | ||
373 | break; | ||
374 | } | ||
375 | } | ||
376 | if (!unregistering) | ||
377 | break; | ||
378 | __rtnl_unlock(); | ||
379 | schedule(); | ||
380 | } | ||
381 | finish_wait(&netdev_unregistering_wq, &wait); | ||
382 | } | ||
383 | |||
356 | /** | 384 | /** |
357 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. | 385 | * rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink. |
358 | * @ops: struct rtnl_link_ops * to unregister | 386 | * @ops: struct rtnl_link_ops * to unregister |
359 | */ | 387 | */ |
360 | void rtnl_link_unregister(struct rtnl_link_ops *ops) | 388 | void rtnl_link_unregister(struct rtnl_link_ops *ops) |
361 | { | 389 | { |
362 | rtnl_lock(); | 390 | /* Close the race with cleanup_net() */ |
391 | mutex_lock(&net_mutex); | ||
392 | rtnl_lock_unregistering_all(); | ||
363 | __rtnl_link_unregister(ops); | 393 | __rtnl_link_unregister(ops); |
364 | rtnl_unlock(); | 394 | rtnl_unlock(); |
395 | mutex_unlock(&net_mutex); | ||
365 | } | 396 | } |
366 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | 397 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); |
367 | 398 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 3d74530ae82b..3f6c7e8be8a4 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -3076,7 +3076,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
3076 | if (unlikely(p->len + len >= 65536)) | 3076 | if (unlikely(p->len + len >= 65536)) |
3077 | return -E2BIG; | 3077 | return -E2BIG; |
3078 | 3078 | ||
3079 | lp = NAPI_GRO_CB(p)->last ?: p; | 3079 | lp = NAPI_GRO_CB(p)->last; |
3080 | pinfo = skb_shinfo(lp); | 3080 | pinfo = skb_shinfo(lp); |
3081 | 3081 | ||
3082 | if (headlen <= offset) { | 3082 | if (headlen <= offset) { |
@@ -3192,7 +3192,7 @@ merge: | |||
3192 | 3192 | ||
3193 | __skb_pull(skb, offset); | 3193 | __skb_pull(skb, offset); |
3194 | 3194 | ||
3195 | if (!NAPI_GRO_CB(p)->last) | 3195 | if (NAPI_GRO_CB(p)->last == p) |
3196 | skb_shinfo(p)->frag_list = skb; | 3196 | skb_shinfo(p)->frag_list = skb; |
3197 | else | 3197 | else |
3198 | NAPI_GRO_CB(p)->last->next = skb; | 3198 | NAPI_GRO_CB(p)->last->next = skb; |
diff --git a/net/core/utils.c b/net/core/utils.c index 2f737bf90b3f..eed34338736c 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -348,8 +348,8 @@ static void __net_random_once_deferred(struct work_struct *w) | |||
348 | { | 348 | { |
349 | struct __net_random_once_work *work = | 349 | struct __net_random_once_work *work = |
350 | container_of(w, struct __net_random_once_work, work); | 350 | container_of(w, struct __net_random_once_work, work); |
351 | if (!static_key_enabled(work->key)) | 351 | BUG_ON(!static_key_enabled(work->key)); |
352 | static_key_slow_inc(work->key); | 352 | static_key_slow_dec(work->key); |
353 | kfree(work); | 353 | kfree(work); |
354 | } | 354 | } |
355 | 355 | ||
@@ -367,7 +367,7 @@ static void __net_random_once_disable_jump(struct static_key *key) | |||
367 | } | 367 | } |
368 | 368 | ||
369 | bool __net_get_random_once(void *buf, int nbytes, bool *done, | 369 | bool __net_get_random_once(void *buf, int nbytes, bool *done, |
370 | struct static_key *done_key) | 370 | struct static_key *once_key) |
371 | { | 371 | { |
372 | static DEFINE_SPINLOCK(lock); | 372 | static DEFINE_SPINLOCK(lock); |
373 | unsigned long flags; | 373 | unsigned long flags; |
@@ -382,7 +382,7 @@ bool __net_get_random_once(void *buf, int nbytes, bool *done, | |||
382 | *done = true; | 382 | *done = true; |
383 | spin_unlock_irqrestore(&lock, flags); | 383 | spin_unlock_irqrestore(&lock, flags); |
384 | 384 | ||
385 | __net_random_once_disable_jump(done_key); | 385 | __net_random_once_disable_jump(once_key); |
386 | 386 | ||
387 | return true; | 387 | return true; |
388 | } | 388 | } |
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 0eb5d5e76dfb..5db37cef50a9 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -406,8 +406,9 @@ static int dsa_of_probe(struct platform_device *pdev) | |||
406 | goto out_free; | 406 | goto out_free; |
407 | } | 407 | } |
408 | 408 | ||
409 | chip_index = 0; | 409 | chip_index = -1; |
410 | for_each_available_child_of_node(np, child) { | 410 | for_each_available_child_of_node(np, child) { |
411 | chip_index++; | ||
411 | cd = &pd->chip[chip_index]; | 412 | cd = &pd->chip[chip_index]; |
412 | 413 | ||
413 | cd->mii_bus = &mdio_bus->dev; | 414 | cd->mii_bus = &mdio_bus->dev; |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 289c6ee388c1..86a00bd6684c 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -539,9 +539,10 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
539 | unsigned int max_headroom; /* The extra header space needed */ | 539 | unsigned int max_headroom; /* The extra header space needed */ |
540 | __be32 dst; | 540 | __be32 dst; |
541 | int err; | 541 | int err; |
542 | bool connected = true; | 542 | bool connected; |
543 | 543 | ||
544 | inner_iph = (const struct iphdr *)skb_inner_network_header(skb); | 544 | inner_iph = (const struct iphdr *)skb_inner_network_header(skb); |
545 | connected = (tunnel->parms.iph.daddr != 0); | ||
545 | 546 | ||
546 | dst = tnl_params->daddr; | 547 | dst = tnl_params->daddr; |
547 | if (dst == 0) { | 548 | if (dst == 0) { |
@@ -879,6 +880,7 @@ int ip_tunnel_init_net(struct net *net, int ip_tnl_net_id, | |||
879 | */ | 880 | */ |
880 | if (!IS_ERR(itn->fb_tunnel_dev)) { | 881 | if (!IS_ERR(itn->fb_tunnel_dev)) { |
881 | itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; | 882 | itn->fb_tunnel_dev->features |= NETIF_F_NETNS_LOCAL; |
883 | itn->fb_tunnel_dev->mtu = ip_tunnel_bind_dev(itn->fb_tunnel_dev); | ||
882 | ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); | 884 | ip_tunnel_add(itn, netdev_priv(itn->fb_tunnel_dev)); |
883 | } | 885 | } |
884 | rtnl_unlock(); | 886 | rtnl_unlock(); |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index afcee51b90ed..13ef00f1e17b 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -239,6 +239,7 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
239 | static int vti4_err(struct sk_buff *skb, u32 info) | 239 | static int vti4_err(struct sk_buff *skb, u32 info) |
240 | { | 240 | { |
241 | __be32 spi; | 241 | __be32 spi; |
242 | __u32 mark; | ||
242 | struct xfrm_state *x; | 243 | struct xfrm_state *x; |
243 | struct ip_tunnel *tunnel; | 244 | struct ip_tunnel *tunnel; |
244 | struct ip_esp_hdr *esph; | 245 | struct ip_esp_hdr *esph; |
@@ -254,6 +255,8 @@ static int vti4_err(struct sk_buff *skb, u32 info) | |||
254 | if (!tunnel) | 255 | if (!tunnel) |
255 | return -1; | 256 | return -1; |
256 | 257 | ||
258 | mark = be32_to_cpu(tunnel->parms.o_key); | ||
259 | |||
257 | switch (protocol) { | 260 | switch (protocol) { |
258 | case IPPROTO_ESP: | 261 | case IPPROTO_ESP: |
259 | esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); | 262 | esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); |
@@ -281,7 +284,7 @@ static int vti4_err(struct sk_buff *skb, u32 info) | |||
281 | return 0; | 284 | return 0; |
282 | } | 285 | } |
283 | 286 | ||
284 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | 287 | x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr, |
285 | spi, protocol, AF_INET); | 288 | spi, protocol, AF_INET); |
286 | if (!x) | 289 | if (!x) |
287 | return 0; | 290 | return 0; |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 50e1e0feddfc..4154eb76b0ad 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1526,7 +1526,7 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1526 | struct in_device *out_dev; | 1526 | struct in_device *out_dev; |
1527 | unsigned int flags = 0; | 1527 | unsigned int flags = 0; |
1528 | bool do_cache; | 1528 | bool do_cache; |
1529 | u32 itag; | 1529 | u32 itag = 0; |
1530 | 1530 | ||
1531 | /* get a working reference to the output device */ | 1531 | /* get a working reference to the output device */ |
1532 | out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res)); | 1532 | out_dev = __in_dev_get_rcu(FIB_RES_DEV(*res)); |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 8e8c018d9d2d..d5f6bd9a210a 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -62,10 +62,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
62 | if (err) | 62 | if (err) |
63 | return err; | 63 | return err; |
64 | 64 | ||
65 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | 65 | IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE; |
66 | IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED; | ||
67 | |||
68 | skb->protocol = htons(ETH_P_IP); | ||
69 | 66 | ||
70 | return x->outer_mode->output2(x, skb); | 67 | return x->outer_mode->output2(x, skb); |
71 | } | 68 | } |
@@ -73,27 +70,34 @@ EXPORT_SYMBOL(xfrm4_prepare_output); | |||
73 | 70 | ||
74 | int xfrm4_output_finish(struct sk_buff *skb) | 71 | int xfrm4_output_finish(struct sk_buff *skb) |
75 | { | 72 | { |
73 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | ||
74 | skb->protocol = htons(ETH_P_IP); | ||
75 | |||
76 | #ifdef CONFIG_NETFILTER | ||
77 | IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; | ||
78 | #endif | ||
79 | |||
80 | return xfrm_output(skb); | ||
81 | } | ||
82 | |||
83 | static int __xfrm4_output(struct sk_buff *skb) | ||
84 | { | ||
85 | struct xfrm_state *x = skb_dst(skb)->xfrm; | ||
86 | |||
76 | #ifdef CONFIG_NETFILTER | 87 | #ifdef CONFIG_NETFILTER |
77 | if (!skb_dst(skb)->xfrm) { | 88 | if (!x) { |
78 | IPCB(skb)->flags |= IPSKB_REROUTED; | 89 | IPCB(skb)->flags |= IPSKB_REROUTED; |
79 | return dst_output(skb); | 90 | return dst_output(skb); |
80 | } | 91 | } |
81 | |||
82 | IPCB(skb)->flags |= IPSKB_XFRM_TRANSFORMED; | ||
83 | #endif | 92 | #endif |
84 | 93 | ||
85 | skb->protocol = htons(ETH_P_IP); | 94 | return x->outer_mode->afinfo->output_finish(skb); |
86 | return xfrm_output(skb); | ||
87 | } | 95 | } |
88 | 96 | ||
89 | int xfrm4_output(struct sock *sk, struct sk_buff *skb) | 97 | int xfrm4_output(struct sock *sk, struct sk_buff *skb) |
90 | { | 98 | { |
91 | struct dst_entry *dst = skb_dst(skb); | ||
92 | struct xfrm_state *x = dst->xfrm; | ||
93 | |||
94 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, | 99 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, |
95 | NULL, dst->dev, | 100 | NULL, skb_dst(skb)->dev, __xfrm4_output, |
96 | x->outer_mode->afinfo->output_finish, | ||
97 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 101 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
98 | } | 102 | } |
99 | 103 | ||
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c index 7f7b243e8139..a2ce0101eaac 100644 --- a/net/ipv4/xfrm4_protocol.c +++ b/net/ipv4/xfrm4_protocol.c | |||
@@ -50,8 +50,12 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err) | |||
50 | { | 50 | { |
51 | int ret; | 51 | int ret; |
52 | struct xfrm4_protocol *handler; | 52 | struct xfrm4_protocol *handler; |
53 | struct xfrm4_protocol __rcu **head = proto_handlers(protocol); | ||
53 | 54 | ||
54 | for_each_protocol_rcu(*proto_handlers(protocol), handler) | 55 | if (!head) |
56 | return 0; | ||
57 | |||
58 | for_each_protocol_rcu(*head, handler) | ||
55 | if ((ret = handler->cb_handler(skb, err)) <= 0) | 59 | if ((ret = handler->cb_handler(skb, err)) <= 0) |
56 | return ret; | 60 | return ret; |
57 | 61 | ||
@@ -64,15 +68,20 @@ int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, | |||
64 | { | 68 | { |
65 | int ret; | 69 | int ret; |
66 | struct xfrm4_protocol *handler; | 70 | struct xfrm4_protocol *handler; |
71 | struct xfrm4_protocol __rcu **head = proto_handlers(nexthdr); | ||
67 | 72 | ||
68 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; | 73 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; |
69 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; | 74 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; |
70 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); | 75 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); |
71 | 76 | ||
72 | for_each_protocol_rcu(*proto_handlers(nexthdr), handler) | 77 | if (!head) |
78 | goto out; | ||
79 | |||
80 | for_each_protocol_rcu(*head, handler) | ||
73 | if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) | 81 | if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) |
74 | return ret; | 82 | return ret; |
75 | 83 | ||
84 | out: | ||
76 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | 85 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
77 | 86 | ||
78 | kfree_skb(skb); | 87 | kfree_skb(skb); |
@@ -208,6 +217,9 @@ int xfrm4_protocol_register(struct xfrm4_protocol *handler, | |||
208 | int ret = -EEXIST; | 217 | int ret = -EEXIST; |
209 | int priority = handler->priority; | 218 | int priority = handler->priority; |
210 | 219 | ||
220 | if (!proto_handlers(protocol) || !netproto(protocol)) | ||
221 | return -EINVAL; | ||
222 | |||
211 | mutex_lock(&xfrm4_protocol_mutex); | 223 | mutex_lock(&xfrm4_protocol_mutex); |
212 | 224 | ||
213 | if (!rcu_dereference_protected(*proto_handlers(protocol), | 225 | if (!rcu_dereference_protected(*proto_handlers(protocol), |
@@ -250,6 +262,9 @@ int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, | |||
250 | struct xfrm4_protocol *t; | 262 | struct xfrm4_protocol *t; |
251 | int ret = -ENOENT; | 263 | int ret = -ENOENT; |
252 | 264 | ||
265 | if (!proto_handlers(protocol) || !netproto(protocol)) | ||
266 | return -EINVAL; | ||
267 | |||
253 | mutex_lock(&xfrm4_protocol_mutex); | 268 | mutex_lock(&xfrm4_protocol_mutex); |
254 | 269 | ||
255 | for (pprev = proto_handlers(protocol); | 270 | for (pprev = proto_handlers(protocol); |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 59f95affceb0..b2f091566f88 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -196,7 +196,6 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
196 | unsigned int off; | 196 | unsigned int off; |
197 | u16 flush = 1; | 197 | u16 flush = 1; |
198 | int proto; | 198 | int proto; |
199 | __wsum csum; | ||
200 | 199 | ||
201 | off = skb_gro_offset(skb); | 200 | off = skb_gro_offset(skb); |
202 | hlen = off + sizeof(*iph); | 201 | hlen = off + sizeof(*iph); |
@@ -264,13 +263,10 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
264 | 263 | ||
265 | NAPI_GRO_CB(skb)->flush |= flush; | 264 | NAPI_GRO_CB(skb)->flush |= flush; |
266 | 265 | ||
267 | csum = skb->csum; | 266 | skb_gro_postpull_rcsum(skb, iph, nlen); |
268 | skb_postpull_rcsum(skb, iph, skb_network_header_len(skb)); | ||
269 | 267 | ||
270 | pp = ops->callbacks.gro_receive(head, skb); | 268 | pp = ops->callbacks.gro_receive(head, skb); |
271 | 269 | ||
272 | skb->csum = csum; | ||
273 | |||
274 | out_unlock: | 270 | out_unlock: |
275 | rcu_read_unlock(); | 271 | rcu_read_unlock(); |
276 | 272 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ab0cc57f779c..85aaeca1f7f3 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1229,7 +1229,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1229 | unsigned int maxnonfragsize, headersize; | 1229 | unsigned int maxnonfragsize, headersize; |
1230 | 1230 | ||
1231 | headersize = sizeof(struct ipv6hdr) + | 1231 | headersize = sizeof(struct ipv6hdr) + |
1232 | (opt ? opt->tot_len : 0) + | 1232 | (opt ? opt->opt_flen + opt->opt_nflen : 0) + |
1233 | (dst_allfrag(&rt->dst) ? | 1233 | (dst_allfrag(&rt->dst) ? |
1234 | sizeof(struct frag_hdr) : 0) + | 1234 | sizeof(struct frag_hdr) : 0) + |
1235 | rt->rt6i_nfheader_len; | 1235 | rt->rt6i_nfheader_len; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index fe61545dde71..afa082458360 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -1558,7 +1558,7 @@ static int ip6_tnl_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
1558 | { | 1558 | { |
1559 | u8 proto; | 1559 | u8 proto; |
1560 | 1560 | ||
1561 | if (!data) | 1561 | if (!data || !data[IFLA_IPTUN_PROTO]) |
1562 | return 0; | 1562 | return 0; |
1563 | 1563 | ||
1564 | proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); | 1564 | proto = nla_get_u8(data[IFLA_IPTUN_PROTO]); |
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 2953c0c26c27..9aaa6bb229e4 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -511,6 +511,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
511 | u8 type, u8 code, int offset, __be32 info) | 511 | u8 type, u8 code, int offset, __be32 info) |
512 | { | 512 | { |
513 | __be32 spi; | 513 | __be32 spi; |
514 | __u32 mark; | ||
514 | struct xfrm_state *x; | 515 | struct xfrm_state *x; |
515 | struct ip6_tnl *t; | 516 | struct ip6_tnl *t; |
516 | struct ip_esp_hdr *esph; | 517 | struct ip_esp_hdr *esph; |
@@ -524,6 +525,8 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
524 | if (!t) | 525 | if (!t) |
525 | return -1; | 526 | return -1; |
526 | 527 | ||
528 | mark = be32_to_cpu(t->parms.o_key); | ||
529 | |||
527 | switch (protocol) { | 530 | switch (protocol) { |
528 | case IPPROTO_ESP: | 531 | case IPPROTO_ESP: |
529 | esph = (struct ip_esp_hdr *)(skb->data + offset); | 532 | esph = (struct ip_esp_hdr *)(skb->data + offset); |
@@ -545,7 +548,7 @@ static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
545 | type != NDISC_REDIRECT) | 548 | type != NDISC_REDIRECT) |
546 | return 0; | 549 | return 0; |
547 | 550 | ||
548 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | 551 | x = xfrm_state_lookup(net, mark, (const xfrm_address_t *)&iph->daddr, |
549 | spi, protocol, AF_INET6); | 552 | spi, protocol, AF_INET6); |
550 | if (!x) | 553 | if (!x) |
551 | return 0; | 554 | return 0; |
@@ -1094,7 +1097,6 @@ static int __init vti6_tunnel_init(void) | |||
1094 | 1097 | ||
1095 | err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); | 1098 | err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); |
1096 | if (err < 0) { | 1099 | if (err < 0) { |
1097 | unregister_pernet_device(&vti6_net_ops); | ||
1098 | pr_err("%s: can't register vti6 protocol\n", __func__); | 1100 | pr_err("%s: can't register vti6 protocol\n", __func__); |
1099 | 1101 | ||
1100 | goto out; | 1102 | goto out; |
@@ -1103,7 +1105,6 @@ static int __init vti6_tunnel_init(void) | |||
1103 | err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); | 1105 | err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); |
1104 | if (err < 0) { | 1106 | if (err < 0) { |
1105 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | 1107 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); |
1106 | unregister_pernet_device(&vti6_net_ops); | ||
1107 | pr_err("%s: can't register vti6 protocol\n", __func__); | 1108 | pr_err("%s: can't register vti6 protocol\n", __func__); |
1108 | 1109 | ||
1109 | goto out; | 1110 | goto out; |
@@ -1113,7 +1114,6 @@ static int __init vti6_tunnel_init(void) | |||
1113 | if (err < 0) { | 1114 | if (err < 0) { |
1114 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); | 1115 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); |
1115 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | 1116 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); |
1116 | unregister_pernet_device(&vti6_net_ops); | ||
1117 | pr_err("%s: can't register vti6 protocol\n", __func__); | 1117 | pr_err("%s: can't register vti6 protocol\n", __func__); |
1118 | 1118 | ||
1119 | goto out; | 1119 | goto out; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 09a22f4f36c9..ca8d4ea48a5d 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -851,7 +851,7 @@ out: | |||
851 | static void ndisc_recv_na(struct sk_buff *skb) | 851 | static void ndisc_recv_na(struct sk_buff *skb) |
852 | { | 852 | { |
853 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); | 853 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); |
854 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; | 854 | struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
855 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; | 855 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; |
856 | u8 *lladdr = NULL; | 856 | u8 *lladdr = NULL; |
857 | u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + | 857 | u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) + |
@@ -944,10 +944,7 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
944 | /* | 944 | /* |
945 | * Change: router to host | 945 | * Change: router to host |
946 | */ | 946 | */ |
947 | struct rt6_info *rt; | 947 | rt6_clean_tohost(dev_net(dev), saddr); |
948 | rt = rt6_get_dflt_router(saddr, dev); | ||
949 | if (rt) | ||
950 | ip6_del_rt(rt); | ||
951 | } | 948 | } |
952 | 949 | ||
953 | out: | 950 | out: |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index aa883afa652d..f23fbd28a501 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2234,6 +2234,27 @@ void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) | |||
2234 | fib6_clean_all(net, fib6_remove_prefsrc, &adni); | 2234 | fib6_clean_all(net, fib6_remove_prefsrc, &adni); |
2235 | } | 2235 | } |
2236 | 2236 | ||
2237 | #define RTF_RA_ROUTER (RTF_ADDRCONF | RTF_DEFAULT | RTF_GATEWAY) | ||
2238 | #define RTF_CACHE_GATEWAY (RTF_GATEWAY | RTF_CACHE) | ||
2239 | |||
2240 | /* Remove routers and update dst entries when gateway turn into host. */ | ||
2241 | static int fib6_clean_tohost(struct rt6_info *rt, void *arg) | ||
2242 | { | ||
2243 | struct in6_addr *gateway = (struct in6_addr *)arg; | ||
2244 | |||
2245 | if ((((rt->rt6i_flags & RTF_RA_ROUTER) == RTF_RA_ROUTER) || | ||
2246 | ((rt->rt6i_flags & RTF_CACHE_GATEWAY) == RTF_CACHE_GATEWAY)) && | ||
2247 | ipv6_addr_equal(gateway, &rt->rt6i_gateway)) { | ||
2248 | return -1; | ||
2249 | } | ||
2250 | return 0; | ||
2251 | } | ||
2252 | |||
2253 | void rt6_clean_tohost(struct net *net, struct in6_addr *gateway) | ||
2254 | { | ||
2255 | fib6_clean_all(net, fib6_clean_tohost, gateway); | ||
2256 | } | ||
2257 | |||
2237 | struct arg_dev_net { | 2258 | struct arg_dev_net { |
2238 | struct net_device *dev; | 2259 | struct net_device *dev; |
2239 | struct net *net; | 2260 | struct net *net; |
@@ -2709,6 +2730,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh) | |||
2709 | if (tb[RTA_OIF]) | 2730 | if (tb[RTA_OIF]) |
2710 | oif = nla_get_u32(tb[RTA_OIF]); | 2731 | oif = nla_get_u32(tb[RTA_OIF]); |
2711 | 2732 | ||
2733 | if (tb[RTA_MARK]) | ||
2734 | fl6.flowi6_mark = nla_get_u32(tb[RTA_MARK]); | ||
2735 | |||
2712 | if (iif) { | 2736 | if (iif) { |
2713 | struct net_device *dev; | 2737 | struct net_device *dev; |
2714 | int flags = 0; | 2738 | int flags = 0; |
diff --git a/net/ipv6/tcpv6_offload.c b/net/ipv6/tcpv6_offload.c index 0d78132ff18a..8517d3cd1aed 100644 --- a/net/ipv6/tcpv6_offload.c +++ b/net/ipv6/tcpv6_offload.c | |||
@@ -42,7 +42,7 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | |||
42 | if (NAPI_GRO_CB(skb)->flush) | 42 | if (NAPI_GRO_CB(skb)->flush) |
43 | goto skip_csum; | 43 | goto skip_csum; |
44 | 44 | ||
45 | wsum = skb->csum; | 45 | wsum = NAPI_GRO_CB(skb)->csum; |
46 | 46 | ||
47 | switch (skb->ip_summed) { | 47 | switch (skb->ip_summed) { |
48 | case CHECKSUM_NONE: | 48 | case CHECKSUM_NONE: |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index f47c8b153dd3..433672d07d0b 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -114,12 +114,6 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
114 | if (err) | 114 | if (err) |
115 | return err; | 115 | return err; |
116 | 116 | ||
117 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); | ||
118 | #ifdef CONFIG_NETFILTER | ||
119 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; | ||
120 | #endif | ||
121 | |||
122 | skb->protocol = htons(ETH_P_IPV6); | ||
123 | skb->ignore_df = 1; | 117 | skb->ignore_df = 1; |
124 | 118 | ||
125 | return x->outer_mode->output2(x, skb); | 119 | return x->outer_mode->output2(x, skb); |
@@ -128,11 +122,13 @@ EXPORT_SYMBOL(xfrm6_prepare_output); | |||
128 | 122 | ||
129 | int xfrm6_output_finish(struct sk_buff *skb) | 123 | int xfrm6_output_finish(struct sk_buff *skb) |
130 | { | 124 | { |
125 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); | ||
126 | skb->protocol = htons(ETH_P_IPV6); | ||
127 | |||
131 | #ifdef CONFIG_NETFILTER | 128 | #ifdef CONFIG_NETFILTER |
132 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; | 129 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; |
133 | #endif | 130 | #endif |
134 | 131 | ||
135 | skb->protocol = htons(ETH_P_IPV6); | ||
136 | return xfrm_output(skb); | 132 | return xfrm_output(skb); |
137 | } | 133 | } |
138 | 134 | ||
@@ -142,6 +138,13 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
142 | struct xfrm_state *x = dst->xfrm; | 138 | struct xfrm_state *x = dst->xfrm; |
143 | int mtu; | 139 | int mtu; |
144 | 140 | ||
141 | #ifdef CONFIG_NETFILTER | ||
142 | if (!x) { | ||
143 | IP6CB(skb)->flags |= IP6SKB_REROUTED; | ||
144 | return dst_output(skb); | ||
145 | } | ||
146 | #endif | ||
147 | |||
145 | if (skb->protocol == htons(ETH_P_IPV6)) | 148 | if (skb->protocol == htons(ETH_P_IPV6)) |
146 | mtu = ip6_skb_dst_mtu(skb); | 149 | mtu = ip6_skb_dst_mtu(skb); |
147 | else | 150 | else |
@@ -165,6 +168,7 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
165 | 168 | ||
166 | int xfrm6_output(struct sock *sk, struct sk_buff *skb) | 169 | int xfrm6_output(struct sock *sk, struct sk_buff *skb) |
167 | { | 170 | { |
168 | return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, | 171 | return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, |
169 | skb_dst(skb)->dev, __xfrm6_output); | 172 | NULL, skb_dst(skb)->dev, __xfrm6_output, |
173 | !(IP6CB(skb)->flags & IP6SKB_REROUTED)); | ||
170 | } | 174 | } |
diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c index 6ab989c486f7..54d13f8dbbae 100644 --- a/net/ipv6/xfrm6_protocol.c +++ b/net/ipv6/xfrm6_protocol.c | |||
@@ -50,6 +50,10 @@ int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err) | |||
50 | { | 50 | { |
51 | int ret; | 51 | int ret; |
52 | struct xfrm6_protocol *handler; | 52 | struct xfrm6_protocol *handler; |
53 | struct xfrm6_protocol __rcu **head = proto_handlers(protocol); | ||
54 | |||
55 | if (!head) | ||
56 | return 0; | ||
53 | 57 | ||
54 | for_each_protocol_rcu(*proto_handlers(protocol), handler) | 58 | for_each_protocol_rcu(*proto_handlers(protocol), handler) |
55 | if ((ret = handler->cb_handler(skb, err)) <= 0) | 59 | if ((ret = handler->cb_handler(skb, err)) <= 0) |
@@ -184,10 +188,12 @@ int xfrm6_protocol_register(struct xfrm6_protocol *handler, | |||
184 | struct xfrm6_protocol __rcu **pprev; | 188 | struct xfrm6_protocol __rcu **pprev; |
185 | struct xfrm6_protocol *t; | 189 | struct xfrm6_protocol *t; |
186 | bool add_netproto = false; | 190 | bool add_netproto = false; |
187 | |||
188 | int ret = -EEXIST; | 191 | int ret = -EEXIST; |
189 | int priority = handler->priority; | 192 | int priority = handler->priority; |
190 | 193 | ||
194 | if (!proto_handlers(protocol) || !netproto(protocol)) | ||
195 | return -EINVAL; | ||
196 | |||
191 | mutex_lock(&xfrm6_protocol_mutex); | 197 | mutex_lock(&xfrm6_protocol_mutex); |
192 | 198 | ||
193 | if (!rcu_dereference_protected(*proto_handlers(protocol), | 199 | if (!rcu_dereference_protected(*proto_handlers(protocol), |
@@ -230,6 +236,9 @@ int xfrm6_protocol_deregister(struct xfrm6_protocol *handler, | |||
230 | struct xfrm6_protocol *t; | 236 | struct xfrm6_protocol *t; |
231 | int ret = -ENOENT; | 237 | int ret = -ENOENT; |
232 | 238 | ||
239 | if (!proto_handlers(protocol) || !netproto(protocol)) | ||
240 | return -EINVAL; | ||
241 | |||
233 | mutex_lock(&xfrm6_protocol_mutex); | 242 | mutex_lock(&xfrm6_protocol_mutex); |
234 | 243 | ||
235 | for (pprev = proto_handlers(protocol); | 244 | for (pprev = proto_handlers(protocol); |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 01e77b0ae075..8c9d7302c846 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -1830,7 +1830,7 @@ static void iucv_callback_txdone(struct iucv_path *path, | |||
1830 | spin_lock_irqsave(&list->lock, flags); | 1830 | spin_lock_irqsave(&list->lock, flags); |
1831 | 1831 | ||
1832 | while (list_skb != (struct sk_buff *)list) { | 1832 | while (list_skb != (struct sk_buff *)list) { |
1833 | if (msg->tag != IUCV_SKB_CB(list_skb)->tag) { | 1833 | if (msg->tag == IUCV_SKB_CB(list_skb)->tag) { |
1834 | this = list_skb; | 1834 | this = list_skb; |
1835 | break; | 1835 | break; |
1836 | } | 1836 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index b455f62d357a..487c2ef0982a 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -317,6 +317,7 @@ struct ieee80211_roc_work { | |||
317 | 317 | ||
318 | bool started, abort, hw_begun, notified; | 318 | bool started, abort, hw_begun, notified; |
319 | bool to_be_freed; | 319 | bool to_be_freed; |
320 | bool on_channel; | ||
320 | 321 | ||
321 | unsigned long hw_start_time; | 322 | unsigned long hw_start_time; |
322 | 323 | ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 488826f188a7..bfb5e20796b6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3598,18 +3598,24 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) | |||
3598 | 3598 | ||
3599 | sdata_lock(sdata); | 3599 | sdata_lock(sdata); |
3600 | 3600 | ||
3601 | if (ifmgd->auth_data) { | 3601 | if (ifmgd->auth_data || ifmgd->assoc_data) { |
3602 | const u8 *bssid = ifmgd->auth_data ? | ||
3603 | ifmgd->auth_data->bss->bssid : | ||
3604 | ifmgd->assoc_data->bss->bssid; | ||
3605 | |||
3602 | /* | 3606 | /* |
3603 | * If we are trying to authenticate while suspending, cfg80211 | 3607 | * If we are trying to authenticate / associate while suspending, |
3604 | * won't know and won't actually abort those attempts, thus we | 3608 | * cfg80211 won't know and won't actually abort those attempts, |
3605 | * need to do that ourselves. | 3609 | * thus we need to do that ourselves. |
3606 | */ | 3610 | */ |
3607 | ieee80211_send_deauth_disassoc(sdata, | 3611 | ieee80211_send_deauth_disassoc(sdata, bssid, |
3608 | ifmgd->auth_data->bss->bssid, | ||
3609 | IEEE80211_STYPE_DEAUTH, | 3612 | IEEE80211_STYPE_DEAUTH, |
3610 | WLAN_REASON_DEAUTH_LEAVING, | 3613 | WLAN_REASON_DEAUTH_LEAVING, |
3611 | false, frame_buf); | 3614 | false, frame_buf); |
3612 | ieee80211_destroy_auth_data(sdata, false); | 3615 | if (ifmgd->assoc_data) |
3616 | ieee80211_destroy_assoc_data(sdata, false); | ||
3617 | if (ifmgd->auth_data) | ||
3618 | ieee80211_destroy_auth_data(sdata, false); | ||
3613 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | 3619 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, |
3614 | IEEE80211_DEAUTH_FRAME_LEN); | 3620 | IEEE80211_DEAUTH_FRAME_LEN); |
3615 | } | 3621 | } |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 6fb38558a5e6..7a17decd27f9 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -333,7 +333,7 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
333 | container_of(work, struct ieee80211_roc_work, work.work); | 333 | container_of(work, struct ieee80211_roc_work, work.work); |
334 | struct ieee80211_sub_if_data *sdata = roc->sdata; | 334 | struct ieee80211_sub_if_data *sdata = roc->sdata; |
335 | struct ieee80211_local *local = sdata->local; | 335 | struct ieee80211_local *local = sdata->local; |
336 | bool started; | 336 | bool started, on_channel; |
337 | 337 | ||
338 | mutex_lock(&local->mtx); | 338 | mutex_lock(&local->mtx); |
339 | 339 | ||
@@ -354,14 +354,26 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
354 | if (!roc->started) { | 354 | if (!roc->started) { |
355 | struct ieee80211_roc_work *dep; | 355 | struct ieee80211_roc_work *dep; |
356 | 356 | ||
357 | /* start this ROC */ | 357 | WARN_ON(local->use_chanctx); |
358 | ieee80211_offchannel_stop_vifs(local); | 358 | |
359 | /* If actually operating on the desired channel (with at least | ||
360 | * 20 MHz channel width) don't stop all the operations but still | ||
361 | * treat it as though the ROC operation started properly, so | ||
362 | * other ROC operations won't interfere with this one. | ||
363 | */ | ||
364 | roc->on_channel = roc->chan == local->_oper_chandef.chan && | ||
365 | local->_oper_chandef.width != NL80211_CHAN_WIDTH_5 && | ||
366 | local->_oper_chandef.width != NL80211_CHAN_WIDTH_10; | ||
359 | 367 | ||
360 | /* switch channel etc */ | 368 | /* start this ROC */ |
361 | ieee80211_recalc_idle(local); | 369 | ieee80211_recalc_idle(local); |
362 | 370 | ||
363 | local->tmp_channel = roc->chan; | 371 | if (!roc->on_channel) { |
364 | ieee80211_hw_config(local, 0); | 372 | ieee80211_offchannel_stop_vifs(local); |
373 | |||
374 | local->tmp_channel = roc->chan; | ||
375 | ieee80211_hw_config(local, 0); | ||
376 | } | ||
365 | 377 | ||
366 | /* tell userspace or send frame */ | 378 | /* tell userspace or send frame */ |
367 | ieee80211_handle_roc_started(roc); | 379 | ieee80211_handle_roc_started(roc); |
@@ -380,9 +392,10 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
380 | finish: | 392 | finish: |
381 | list_del(&roc->list); | 393 | list_del(&roc->list); |
382 | started = roc->started; | 394 | started = roc->started; |
395 | on_channel = roc->on_channel; | ||
383 | ieee80211_roc_notify_destroy(roc, !roc->abort); | 396 | ieee80211_roc_notify_destroy(roc, !roc->abort); |
384 | 397 | ||
385 | if (started) { | 398 | if (started && !on_channel) { |
386 | ieee80211_flush_queues(local, NULL); | 399 | ieee80211_flush_queues(local, NULL); |
387 | 400 | ||
388 | local->tmp_channel = NULL; | 401 | local->tmp_channel = NULL; |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index a0b0aea76525..cec5b60487a4 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -21,10 +21,10 @@ | |||
21 | 21 | ||
22 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ | 22 | #define VIF_ENTRY __field(enum nl80211_iftype, vif_type) __field(void *, sdata) \ |
23 | __field(bool, p2p) \ | 23 | __field(bool, p2p) \ |
24 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 24 | __string(vif_name, sdata->name) |
25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | 25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
26 | __entry->p2p = sdata->vif.p2p; \ | 26 | __entry->p2p = sdata->vif.p2p; \ |
27 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name) | 27 | __assign_str(vif_name, sdata->name) |
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index e9e36a256165..9265adfdabfc 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -129,9 +129,12 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
129 | if (!vht_cap_ie || !sband->vht_cap.vht_supported) | 129 | if (!vht_cap_ie || !sband->vht_cap.vht_supported) |
130 | return; | 130 | return; |
131 | 131 | ||
132 | /* A VHT STA must support 40 MHz */ | 132 | /* |
133 | if (!(sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)) | 133 | * A VHT STA must support 40 MHz, but if we verify that here |
134 | return; | 134 | * then we break a few things - some APs (e.g. Netgear R6300v2 |
135 | * and others based on the BCM4360 chipset) will unset this | ||
136 | * capability bit when operating in 20 MHz. | ||
137 | */ | ||
135 | 138 | ||
136 | vht_cap->vht_supported = true; | 139 | vht_cap->vht_supported = true; |
137 | 140 | ||
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 804105391b9a..345acfb1720b 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
@@ -66,20 +66,6 @@ struct nft_jumpstack { | |||
66 | int rulenum; | 66 | int rulenum; |
67 | }; | 67 | }; |
68 | 68 | ||
69 | static inline void | ||
70 | nft_chain_stats(const struct nft_chain *this, const struct nft_pktinfo *pkt, | ||
71 | struct nft_jumpstack *jumpstack, unsigned int stackptr) | ||
72 | { | ||
73 | struct nft_stats __percpu *stats; | ||
74 | const struct nft_chain *chain = stackptr ? jumpstack[0].chain : this; | ||
75 | |||
76 | rcu_read_lock_bh(); | ||
77 | stats = rcu_dereference(nft_base_chain(chain)->stats); | ||
78 | __this_cpu_inc(stats->pkts); | ||
79 | __this_cpu_add(stats->bytes, pkt->skb->len); | ||
80 | rcu_read_unlock_bh(); | ||
81 | } | ||
82 | |||
83 | enum nft_trace { | 69 | enum nft_trace { |
84 | NFT_TRACE_RULE, | 70 | NFT_TRACE_RULE, |
85 | NFT_TRACE_RETURN, | 71 | NFT_TRACE_RETURN, |
@@ -117,13 +103,14 @@ static void nft_trace_packet(const struct nft_pktinfo *pkt, | |||
117 | unsigned int | 103 | unsigned int |
118 | nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | 104 | nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) |
119 | { | 105 | { |
120 | const struct nft_chain *chain = ops->priv; | 106 | const struct nft_chain *chain = ops->priv, *basechain = chain; |
121 | const struct nft_rule *rule; | 107 | const struct nft_rule *rule; |
122 | const struct nft_expr *expr, *last; | 108 | const struct nft_expr *expr, *last; |
123 | struct nft_data data[NFT_REG_MAX + 1]; | 109 | struct nft_data data[NFT_REG_MAX + 1]; |
124 | unsigned int stackptr = 0; | 110 | unsigned int stackptr = 0; |
125 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; | 111 | struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; |
126 | int rulenum = 0; | 112 | struct nft_stats __percpu *stats; |
113 | int rulenum; | ||
127 | /* | 114 | /* |
128 | * Cache cursor to avoid problems in case that the cursor is updated | 115 | * Cache cursor to avoid problems in case that the cursor is updated |
129 | * while traversing the ruleset. | 116 | * while traversing the ruleset. |
@@ -131,6 +118,7 @@ nft_do_chain(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops) | |||
131 | unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor); | 118 | unsigned int gencursor = ACCESS_ONCE(chain->net->nft.gencursor); |
132 | 119 | ||
133 | do_chain: | 120 | do_chain: |
121 | rulenum = 0; | ||
134 | rule = list_entry(&chain->rules, struct nft_rule, list); | 122 | rule = list_entry(&chain->rules, struct nft_rule, list); |
135 | next_rule: | 123 | next_rule: |
136 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 124 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; |
@@ -156,8 +144,10 @@ next_rule: | |||
156 | switch (data[NFT_REG_VERDICT].verdict) { | 144 | switch (data[NFT_REG_VERDICT].verdict) { |
157 | case NFT_BREAK: | 145 | case NFT_BREAK: |
158 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; | 146 | data[NFT_REG_VERDICT].verdict = NFT_CONTINUE; |
159 | /* fall through */ | 147 | continue; |
160 | case NFT_CONTINUE: | 148 | case NFT_CONTINUE: |
149 | if (unlikely(pkt->skb->nf_trace)) | ||
150 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | ||
161 | continue; | 151 | continue; |
162 | } | 152 | } |
163 | break; | 153 | break; |
@@ -183,37 +173,44 @@ next_rule: | |||
183 | jumpstack[stackptr].rule = rule; | 173 | jumpstack[stackptr].rule = rule; |
184 | jumpstack[stackptr].rulenum = rulenum; | 174 | jumpstack[stackptr].rulenum = rulenum; |
185 | stackptr++; | 175 | stackptr++; |
186 | /* fall through */ | 176 | chain = data[NFT_REG_VERDICT].chain; |
177 | goto do_chain; | ||
187 | case NFT_GOTO: | 178 | case NFT_GOTO: |
179 | if (unlikely(pkt->skb->nf_trace)) | ||
180 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE); | ||
181 | |||
188 | chain = data[NFT_REG_VERDICT].chain; | 182 | chain = data[NFT_REG_VERDICT].chain; |
189 | goto do_chain; | 183 | goto do_chain; |
190 | case NFT_RETURN: | 184 | case NFT_RETURN: |
191 | if (unlikely(pkt->skb->nf_trace)) | 185 | if (unlikely(pkt->skb->nf_trace)) |
192 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); | 186 | nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN); |
193 | 187 | break; | |
194 | /* fall through */ | ||
195 | case NFT_CONTINUE: | 188 | case NFT_CONTINUE: |
189 | if (unlikely(pkt->skb->nf_trace && !(chain->flags & NFT_BASE_CHAIN))) | ||
190 | nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN); | ||
196 | break; | 191 | break; |
197 | default: | 192 | default: |
198 | WARN_ON(1); | 193 | WARN_ON(1); |
199 | } | 194 | } |
200 | 195 | ||
201 | if (stackptr > 0) { | 196 | if (stackptr > 0) { |
202 | if (unlikely(pkt->skb->nf_trace)) | ||
203 | nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN); | ||
204 | |||
205 | stackptr--; | 197 | stackptr--; |
206 | chain = jumpstack[stackptr].chain; | 198 | chain = jumpstack[stackptr].chain; |
207 | rule = jumpstack[stackptr].rule; | 199 | rule = jumpstack[stackptr].rule; |
208 | rulenum = jumpstack[stackptr].rulenum; | 200 | rulenum = jumpstack[stackptr].rulenum; |
209 | goto next_rule; | 201 | goto next_rule; |
210 | } | 202 | } |
211 | nft_chain_stats(chain, pkt, jumpstack, stackptr); | ||
212 | 203 | ||
213 | if (unlikely(pkt->skb->nf_trace)) | 204 | if (unlikely(pkt->skb->nf_trace)) |
214 | nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY); | 205 | nft_trace_packet(pkt, basechain, -1, NFT_TRACE_POLICY); |
206 | |||
207 | rcu_read_lock_bh(); | ||
208 | stats = rcu_dereference(nft_base_chain(basechain)->stats); | ||
209 | __this_cpu_inc(stats->pkts); | ||
210 | __this_cpu_add(stats->bytes, pkt->skb->len); | ||
211 | rcu_read_unlock_bh(); | ||
215 | 212 | ||
216 | return nft_base_chain(chain)->policy; | 213 | return nft_base_chain(basechain)->policy; |
217 | } | 214 | } |
218 | EXPORT_SYMBOL_GPL(nft_do_chain); | 215 | EXPORT_SYMBOL_GPL(nft_do_chain); |
219 | 216 | ||
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 7633a752c65e..0ad080790a32 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -99,7 +99,7 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, | |||
99 | _debug("tktlen: %x", tktlen); | 99 | _debug("tktlen: %x", tktlen); |
100 | if (tktlen > AFSTOKEN_RK_TIX_MAX) | 100 | if (tktlen > AFSTOKEN_RK_TIX_MAX) |
101 | return -EKEYREJECTED; | 101 | return -EKEYREJECTED; |
102 | if (8 * 4 + tktlen != toklen) | 102 | if (toklen < 8 * 4 + tktlen) |
103 | return -EKEYREJECTED; | 103 | return -EKEYREJECTED; |
104 | 104 | ||
105 | plen = sizeof(*token) + sizeof(*token->kad) + tktlen; | 105 | plen = sizeof(*token) + sizeof(*token->kad) + tktlen; |
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index d11d0a4fbe34..c721cd4a469f 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -188,6 +188,12 @@ static const struct nla_policy tcindex_policy[TCA_TCINDEX_MAX + 1] = { | |||
188 | [TCA_TCINDEX_CLASSID] = { .type = NLA_U32 }, | 188 | [TCA_TCINDEX_CLASSID] = { .type = NLA_U32 }, |
189 | }; | 189 | }; |
190 | 190 | ||
191 | static void tcindex_filter_result_init(struct tcindex_filter_result *r) | ||
192 | { | ||
193 | memset(r, 0, sizeof(*r)); | ||
194 | tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); | ||
195 | } | ||
196 | |||
191 | static int | 197 | static int |
192 | tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, | 198 | tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, |
193 | u32 handle, struct tcindex_data *p, | 199 | u32 handle, struct tcindex_data *p, |
@@ -207,15 +213,11 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, | |||
207 | return err; | 213 | return err; |
208 | 214 | ||
209 | memcpy(&cp, p, sizeof(cp)); | 215 | memcpy(&cp, p, sizeof(cp)); |
210 | memset(&new_filter_result, 0, sizeof(new_filter_result)); | 216 | tcindex_filter_result_init(&new_filter_result); |
211 | tcf_exts_init(&new_filter_result.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); | ||
212 | 217 | ||
218 | tcindex_filter_result_init(&cr); | ||
213 | if (old_r) | 219 | if (old_r) |
214 | memcpy(&cr, r, sizeof(cr)); | 220 | cr.res = r->res; |
215 | else { | ||
216 | memset(&cr, 0, sizeof(cr)); | ||
217 | tcf_exts_init(&cr.exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE); | ||
218 | } | ||
219 | 221 | ||
220 | if (tb[TCA_TCINDEX_HASH]) | 222 | if (tb[TCA_TCINDEX_HASH]) |
221 | cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); | 223 | cp.hash = nla_get_u32(tb[TCA_TCINDEX_HASH]); |
@@ -267,9 +269,14 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, | |||
267 | err = -ENOMEM; | 269 | err = -ENOMEM; |
268 | if (!cp.perfect && !cp.h) { | 270 | if (!cp.perfect && !cp.h) { |
269 | if (valid_perfect_hash(&cp)) { | 271 | if (valid_perfect_hash(&cp)) { |
272 | int i; | ||
273 | |||
270 | cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL); | 274 | cp.perfect = kcalloc(cp.hash, sizeof(*r), GFP_KERNEL); |
271 | if (!cp.perfect) | 275 | if (!cp.perfect) |
272 | goto errout; | 276 | goto errout; |
277 | for (i = 0; i < cp.hash; i++) | ||
278 | tcf_exts_init(&cp.perfect[i].exts, TCA_TCINDEX_ACT, | ||
279 | TCA_TCINDEX_POLICE); | ||
273 | balloc = 1; | 280 | balloc = 1; |
274 | } else { | 281 | } else { |
275 | cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL); | 282 | cp.h = kcalloc(cp.hash, sizeof(f), GFP_KERNEL); |
@@ -295,14 +302,17 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, | |||
295 | tcf_bind_filter(tp, &cr.res, base); | 302 | tcf_bind_filter(tp, &cr.res, base); |
296 | } | 303 | } |
297 | 304 | ||
298 | tcf_exts_change(tp, &cr.exts, &e); | 305 | if (old_r) |
306 | tcf_exts_change(tp, &r->exts, &e); | ||
307 | else | ||
308 | tcf_exts_change(tp, &cr.exts, &e); | ||
299 | 309 | ||
300 | tcf_tree_lock(tp); | 310 | tcf_tree_lock(tp); |
301 | if (old_r && old_r != r) | 311 | if (old_r && old_r != r) |
302 | memset(old_r, 0, sizeof(*old_r)); | 312 | tcindex_filter_result_init(old_r); |
303 | 313 | ||
304 | memcpy(p, &cp, sizeof(cp)); | 314 | memcpy(p, &cp, sizeof(cp)); |
305 | memcpy(r, &cr, sizeof(cr)); | 315 | r->res = cr.res; |
306 | 316 | ||
307 | if (r == &new_filter_result) { | 317 | if (r == &new_filter_result) { |
308 | struct tcindex_filter **fp; | 318 | struct tcindex_filter **fp; |