aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ipvlan
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-04-02 16:16:53 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-02 16:16:53 -0400
commit9f0d34bc344889c2e6c593bd949d7ab821f0f4a5 (patch)
treee5bfc776a09315afa4dbcae97ac04f2cca239c96 /drivers/net/ipvlan
parente4a924f5768c55002c02ceba9b9f86824c35f956 (diff)
parent0a4812798fae4f6bfcaab51e31b3898ff5ea3108 (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.h4
-rw-r--r--drivers/net/ipvlan/ipvlan_core.c28
-rw-r--r--drivers/net/ipvlan/ipvlan_main.c30
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);
114rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb); 114rx_handler_result_t ipvlan_handle_frame(struct sk_buff **pskb);
115int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev); 115int ipvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev);
116void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr); 116void ipvlan_ht_addr_add(struct ipvl_dev *ipvlan, struct ipvl_addr *addr);
117bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6); 117struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan,
118 const void *iaddr, bool is_v6);
119bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6);
118struct ipvl_addr *ipvlan_ht_addr_lookup(const struct ipvl_port *port, 120struct 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);
120void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync); 122void 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
87void ipvlan_ht_addr_del(struct ipvl_addr *addr, bool sync) 88void 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
94bool ipvlan_addr_busy(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) 95struct 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
110bool 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,
219mcast_acct: 230mcast_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)