diff options
author | David S. Miller <davem@davemloft.net> | 2015-04-02 16:16:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-04-02 16:16:53 -0400 |
commit | 9f0d34bc344889c2e6c593bd949d7ab821f0f4a5 (patch) | |
tree | e5bfc776a09315afa4dbcae97ac04f2cca239c96 /drivers/net/ipvlan | |
parent | e4a924f5768c55002c02ceba9b9f86824c35f956 (diff) | |
parent | 0a4812798fae4f6bfcaab51e31b3898ff5ea3108 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts:
drivers/net/usb/asix_common.c
drivers/net/usb/sr9800.c
drivers/net/usb/usbnet.c
include/linux/usb/usbnet.h
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c
The TCP conflicts were overlapping changes. In 'net' we added a
READ_ONCE() to the socket cached RX route read, whilst in 'net-next'
Eric Dumazet touched the surrounding code dealing with how mini
sockets are handled.
With USB, it's a case of the same bug fix first going into net-next
and then I cherry picked it back into net.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipvlan')
-rw-r--r-- | drivers/net/ipvlan/ipvlan.h | 4 | ||||
-rw-r--r-- | drivers/net/ipvlan/ipvlan_core.c | 28 | ||||
-rw-r--r-- | drivers/net/ipvlan/ipvlan_main.c | 30 |
3 files changed, 42 insertions, 20 deletions
diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index 924ea98bd531..54549a6223dd 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h | |||
@@ -114,7 +114,9 @@ unsigned int ipvlan_mac_hash(const unsigned char *addr); | |||
114 | rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb); | 114 | rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb); |
115 | int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev); | 115 | int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev); |
116 | void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr); | 116 | void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr); |
117 | bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6); | 117 | struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, |
118 | const void *iaddr, bool is_v6); | ||
119 | bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6); | ||
118 | struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, | 120 | struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, |
119 | const void *iaddr, bool is_v6); | 121 | const void *iaddr, bool is_v6); |
120 | void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); | 122 | void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); |
diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index 131bde98188d..c30b5c300c05 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c | |||
@@ -81,19 +81,20 @@ void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr) | |||
81 | hash = (addr->atype == IPVL_IPV6) ? | 81 | hash = (addr->atype == IPVL_IPV6) ? |
82 | ipvlan_get_v6_hash(&addr->ip6addr) : | 82 | ipvlan_get_v6_hash(&addr->ip6addr) : |
83 | ipvlan_get_v4_hash(&addr->ip4addr); | 83 | ipvlan_get_v4_hash(&addr->ip4addr); |
84 | hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); | 84 | if (hlist_unhashed(&addr->hlnode)) |
85 | hlist_add_head_rcu(&addr->hlnode, &port->hlhead[hash]); | ||
85 | } | 86 | } |
86 | 87 | ||
87 | void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) | 88 | void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) |
88 | { | 89 | { |
89 | hlist_del_rcu(&addr->hlnode); | 90 | hlist_del_init_rcu(&addr->hlnode); |
90 | if (sync) | 91 | if (sync) |
91 | synchronize_rcu(); | 92 | synchronize_rcu(); |
92 | } | 93 | } |
93 | 94 | ||
94 | bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) | 95 | struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, |
96 | const void *iaddr, bool is_v6) | ||
95 | { | 97 | { |
96 | struct ipvl_port *port = ipvlan->port; | ||
97 | struct ipvl_addr *addr; | 98 | struct ipvl_addr *addr; |
98 | 99 | ||
99 | list_for_each_entry(addr, &ipvlan->addrs, anode) { | 100 | list_for_each_entry(addr, &ipvlan->addrs, anode) { |
@@ -101,12 +102,21 @@ bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) | |||
101 | ipv6_addr_equal(&addr->ip6addr, iaddr)) || | 102 | ipv6_addr_equal(&addr->ip6addr, iaddr)) || |
102 | (!is_v6 && addr->atype == IPVL_IPV4 && | 103 | (!is_v6 && addr->atype == IPVL_IPV4 && |
103 | addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr)) | 104 | addr->ip4addr.s_addr == ((struct in_addr *)iaddr)->s_addr)) |
104 | return true; | 105 | return addr; |
105 | } | 106 | } |
107 | return NULL; | ||
108 | } | ||
109 | |||
110 | bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6) | ||
111 | { | ||
112 | struct ipvl_dev *ipvlan; | ||
106 | 113 | ||
107 | if (ipvlan_ht_addr_lookup(port, iaddr, is_v6)) | 114 | ASSERT_RTNL(); |
108 | return true; | ||
109 | 115 | ||
116 | list_for_each_entry(ipvlan, &port->ipvlans, pnode) { | ||
117 | if (ipvlan_find_addr(ipvlan, iaddr, is_v6)) | ||
118 | return true; | ||
119 | } | ||
110 | return false; | 120 | return false; |
111 | } | 121 | } |
112 | 122 | ||
@@ -192,7 +202,8 @@ static void ipvlan_multicast_frame(struct ipvl_port *port, struct sk_buff *skb, | |||
192 | if (skb->protocol == htons(ETH_P_PAUSE)) | 202 | if (skb->protocol == htons(ETH_P_PAUSE)) |
193 | return; | 203 | return; |
194 | 204 | ||
195 | list_for_each_entry(ipvlan, &port->ipvlans, pnode) { | 205 | rcu_read_lock(); |
206 | list_for_each_entry_rcu(ipvlan, &port->ipvlans, pnode) { | ||
196 | if (local && (ipvlan == in_dev)) | 207 | if (local && (ipvlan == in_dev)) |
197 | continue; | 208 | continue; |
198 | 209 | ||
@@ -219,6 +230,7 @@ static void ipvlan_multicast_frame(struct ipvl_port *port, struct sk_buff *skb, | |||
219 | mcast_acct: | 230 | mcast_acct: |
220 | ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, true); | 231 | ipvlan_count_rx(ipvlan, len, ret == NET_RX_SUCCESS, true); |
221 | } | 232 | } |
233 | rcu_read_unlock(); | ||
222 | 234 | ||
223 | /* Locally generated? ...Forward a copy to the main-device as | 235 | /* Locally generated? ...Forward a copy to the main-device as |
224 | * well. On the RX side we'll ignore it (wont give it to any | 236 | * well. On the RX side we'll ignore it (wont give it to any |
diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 1701ede2df89..77b92a0fe557 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c | |||
@@ -511,7 +511,7 @@ static void ipvlan_link_delete(struct net_device *dev, struct list_head *head) | |||
511 | if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { | 511 | if (ipvlan->ipv6cnt > 0 || ipvlan->ipv4cnt > 0) { |
512 | list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { | 512 | list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { |
513 | ipvlan_ht_addr_del(addr, !dev->dismantle); | 513 | ipvlan_ht_addr_del(addr, !dev->dismantle); |
514 | list_del_rcu(&addr->anode); | 514 | list_del(&addr->anode); |
515 | } | 515 | } |
516 | } | 516 | } |
517 | list_del_rcu(&ipvlan->pnode); | 517 | list_del_rcu(&ipvlan->pnode); |
@@ -613,7 +613,7 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) | |||
613 | { | 613 | { |
614 | struct ipvl_addr *addr; | 614 | struct ipvl_addr *addr; |
615 | 615 | ||
616 | if (ipvlan_addr_busy(ipvlan, ip6_addr, true)) { | 616 | if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) { |
617 | netif_err(ipvlan, ifup, ipvlan->dev, | 617 | netif_err(ipvlan, ifup, ipvlan->dev, |
618 | "Failed to add IPv6=%pI6c addr for %s intf\n", | 618 | "Failed to add IPv6=%pI6c addr for %s intf\n", |
619 | ip6_addr, ipvlan->dev->name); | 619 | ip6_addr, ipvlan->dev->name); |
@@ -626,9 +626,13 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) | |||
626 | addr->master = ipvlan; | 626 | addr->master = ipvlan; |
627 | memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr)); | 627 | memcpy(&addr->ip6addr, ip6_addr, sizeof(struct in6_addr)); |
628 | addr->atype = IPVL_IPV6; | 628 | addr->atype = IPVL_IPV6; |
629 | list_add_tail_rcu(&addr->anode, &ipvlan->addrs); | 629 | list_add_tail(&addr->anode, &ipvlan->addrs); |
630 | ipvlan->ipv6cnt++; | 630 | ipvlan->ipv6cnt++; |
631 | ipvlan_ht_addr_add(ipvlan, addr); | 631 | /* If the interface is not up, the address will be added to the hash |
632 | * list by ipvlan_open. | ||
633 | */ | ||
634 | if (netif_running(ipvlan->dev)) | ||
635 | ipvlan_ht_addr_add(ipvlan, addr); | ||
632 | 636 | ||
633 | return 0; | 637 | return 0; |
634 | } | 638 | } |
@@ -637,12 +641,12 @@ static void ipvlan_del_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) | |||
637 | { | 641 | { |
638 | struct ipvl_addr *addr; | 642 | struct ipvl_addr *addr; |
639 | 643 | ||
640 | addr = ipvlan_ht_addr_lookup(ipvlan->port, ip6_addr, true); | 644 | addr = ipvlan_find_addr(ipvlan, ip6_addr, true); |
641 | if (!addr) | 645 | if (!addr) |
642 | return; | 646 | return; |
643 | 647 | ||
644 | ipvlan_ht_addr_del(addr, true); | 648 | ipvlan_ht_addr_del(addr, true); |
645 | list_del_rcu(&addr->anode); | 649 | list_del(&addr->anode); |
646 | ipvlan->ipv6cnt--; | 650 | ipvlan->ipv6cnt--; |
647 | WARN_ON(ipvlan->ipv6cnt < 0); | 651 | WARN_ON(ipvlan->ipv6cnt < 0); |
648 | kfree_rcu(addr, rcu); | 652 | kfree_rcu(addr, rcu); |
@@ -681,7 +685,7 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) | |||
681 | { | 685 | { |
682 | struct ipvl_addr *addr; | 686 | struct ipvl_addr *addr; |
683 | 687 | ||
684 | if (ipvlan_addr_busy(ipvlan, ip4_addr, false)) { | 688 | if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) { |
685 | netif_err(ipvlan, ifup, ipvlan->dev, | 689 | netif_err(ipvlan, ifup, ipvlan->dev, |
686 | "Failed to add IPv4=%pI4 on %s intf.\n", | 690 | "Failed to add IPv4=%pI4 on %s intf.\n", |
687 | ip4_addr, ipvlan->dev->name); | 691 | ip4_addr, ipvlan->dev->name); |
@@ -694,9 +698,13 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) | |||
694 | addr->master = ipvlan; | 698 | addr->master = ipvlan; |
695 | memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr)); | 699 | memcpy(&addr->ip4addr, ip4_addr, sizeof(struct in_addr)); |
696 | addr->atype = IPVL_IPV4; | 700 | addr->atype = IPVL_IPV4; |
697 | list_add_tail_rcu(&addr->anode, &ipvlan->addrs); | 701 | list_add_tail(&addr->anode, &ipvlan->addrs); |
698 | ipvlan->ipv4cnt++; | 702 | ipvlan->ipv4cnt++; |
699 | ipvlan_ht_addr_add(ipvlan, addr); | 703 | /* If the interface is not up, the address will be added to the hash |
704 | * list by ipvlan_open. | ||
705 | */ | ||
706 | if (netif_running(ipvlan->dev)) | ||
707 | ipvlan_ht_addr_add(ipvlan, addr); | ||
700 | ipvlan_set_broadcast_mac_filter(ipvlan, true); | 708 | ipvlan_set_broadcast_mac_filter(ipvlan, true); |
701 | 709 | ||
702 | return 0; | 710 | return 0; |
@@ -706,12 +714,12 @@ static void ipvlan_del_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) | |||
706 | { | 714 | { |
707 | struct ipvl_addr *addr; | 715 | struct ipvl_addr *addr; |
708 | 716 | ||
709 | addr = ipvlan_ht_addr_lookup(ipvlan->port, ip4_addr, false); | 717 | addr = ipvlan_find_addr(ipvlan, ip4_addr, false); |
710 | if (!addr) | 718 | if (!addr) |
711 | return; | 719 | return; |
712 | 720 | ||
713 | ipvlan_ht_addr_del(addr, true); | 721 | ipvlan_ht_addr_del(addr, true); |
714 | list_del_rcu(&addr->anode); | 722 | list_del(&addr->anode); |
715 | ipvlan->ipv4cnt--; | 723 | ipvlan->ipv4cnt--; |
716 | WARN_ON(ipvlan->ipv4cnt < 0); | 724 | WARN_ON(ipvlan->ipv4cnt < 0); |
717 | if (!ipvlan->ipv4cnt) | 725 | if (!ipvlan->ipv4cnt) |