Commit 87002b03baabd2b8f6281ab6411ed88d24958de1

Authored by Jiri Pirko
Committed by David S. Miller
1 parent 8e586137e6

net: introduce vlan_vid_[add/del] and use them instead of direct [add/kill]_vid ndo calls

This patch adds wrapper for ndo_vlan_rx_add_vid/ndo_vlan_rx_kill_vid
functions. Check for NETIF_F_HW_VLAN_FILTER feature is done in this
wrapper.

Signed-off-by: Jiri Pirko <jpirko@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 6 changed files with 87 additions and 59 deletions Side-by-side Diff

drivers/net/bonding/bond_main.c
... ... @@ -431,17 +431,13 @@
431 431 static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
432 432 {
433 433 struct bonding *bond = netdev_priv(bond_dev);
434   - struct slave *slave;
  434 + struct slave *slave, *stop_at;
435 435 int i, res;
436 436  
437 437 bond_for_each_slave(bond, slave, i) {
438   - struct net_device *slave_dev = slave->dev;
439   - const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
440   -
441   - if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
442   - slave_ops->ndo_vlan_rx_add_vid) {
443   - slave_ops->ndo_vlan_rx_add_vid(slave_dev, vid);
444   - }
  438 + res = vlan_vid_add(slave->dev, vid);
  439 + if (res)
  440 + goto unwind;
445 441 }
446 442  
447 443 res = bond_add_vlan(bond, vid);
... ... @@ -452,6 +448,14 @@
452 448 }
453 449  
454 450 return 0;
  451 +
  452 +unwind:
  453 + /* unwind from head to the slave that failed */
  454 + stop_at = slave;
  455 + bond_for_each_slave_from_to(bond, slave, i, bond->first_slave, stop_at)
  456 + vlan_vid_del(slave->dev, vid);
  457 +
  458 + return res;
455 459 }
456 460  
457 461 /**
458 462  
... ... @@ -465,16 +469,9 @@
465 469 struct slave *slave;
466 470 int i, res;
467 471  
468   - bond_for_each_slave(bond, slave, i) {
469   - struct net_device *slave_dev = slave->dev;
470   - const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
  472 + bond_for_each_slave(bond, slave, i)
  473 + vlan_vid_del(slave->dev, vid);
471 474  
472   - if ((slave_dev->features & NETIF_F_HW_VLAN_FILTER) &&
473   - slave_ops->ndo_vlan_rx_kill_vid) {
474   - slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vid);
475   - }
476   - }
477   -
478 475 res = bond_del_vlan(bond, vid);
479 476 if (res) {
480 477 pr_err("%s: Error: Failed to remove vlan id %d\n",
481 478  
482 479  
483 480  
484 481  
... ... @@ -488,30 +485,26 @@
488 485 static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
489 486 {
490 487 struct vlan_entry *vlan;
491   - const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
  488 + int res;
492 489  
493   - if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
494   - !(slave_ops->ndo_vlan_rx_add_vid))
495   - return;
496   -
497   - list_for_each_entry(vlan, &bond->vlan_list, vlan_list)
498   - slave_ops->ndo_vlan_rx_add_vid(slave_dev, vlan->vlan_id);
  490 + list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
  491 + res = vlan_vid_add(slave_dev, vlan->vlan_id);
  492 + if (res)
  493 + pr_warning("%s: Failed to add vlan id %d to device %s\n",
  494 + bond->dev->name, vlan->vlan_id,
  495 + slave_dev->name);
  496 + }
499 497 }
500 498  
501 499 static void bond_del_vlans_from_slave(struct bonding *bond,
502 500 struct net_device *slave_dev)
503 501 {
504   - const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
505 502 struct vlan_entry *vlan;
506 503  
507   - if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
508   - !(slave_ops->ndo_vlan_rx_kill_vid))
509   - return;
510   -
511 504 list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
512 505 if (!vlan->vlan_id)
513 506 continue;
514   - slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
  507 + vlan_vid_del(slave_dev, vlan->vlan_id);
515 508 }
516 509 }
517 510  
drivers/net/macvlan.c
... ... @@ -26,6 +26,7 @@
26 26 #include <linux/etherdevice.h>
27 27 #include <linux/ethtool.h>
28 28 #include <linux/if_arp.h>
  29 +#include <linux/if_vlan.h>
29 30 #include <linux/if_link.h>
30 31 #include <linux/if_macvlan.h>
31 32 #include <net/rtnetlink.h>
32 33  
... ... @@ -525,11 +526,8 @@
525 526 {
526 527 struct macvlan_dev *vlan = netdev_priv(dev);
527 528 struct net_device *lowerdev = vlan->lowerdev;
528   - const struct net_device_ops *ops = lowerdev->netdev_ops;
529 529  
530   - if (ops->ndo_vlan_rx_add_vid)
531   - return ops->ndo_vlan_rx_add_vid(lowerdev, vid);
532   - return 0;
  530 + return vlan_vid_add(lowerdev, vid);
533 531 }
534 532  
535 533 static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
536 534  
... ... @@ -537,10 +535,8 @@
537 535 {
538 536 struct macvlan_dev *vlan = netdev_priv(dev);
539 537 struct net_device *lowerdev = vlan->lowerdev;
540   - const struct net_device_ops *ops = lowerdev->netdev_ops;
541 538  
542   - if (ops->ndo_vlan_rx_kill_vid)
543   - return ops->ndo_vlan_rx_kill_vid(lowerdev, vid);
  539 + vlan_vid_del(lowerdev, vid);
544 540 return 0;
545 541 }
546 542  
drivers/net/team/team.c
... ... @@ -18,6 +18,7 @@
18 18 #include <linux/ctype.h>
19 19 #include <linux/notifier.h>
20 20 #include <linux/netdevice.h>
  21 +#include <linux/if_vlan.h>
21 22 #include <linux/if_arp.h>
22 23 #include <linux/socket.h>
23 24 #include <linux/etherdevice.h>
24 25  
25 26  
26 27  
... ... @@ -906,17 +907,28 @@
906 907 {
907 908 struct team *team = netdev_priv(dev);
908 909 struct team_port *port;
  910 + int err;
909 911  
910   - rcu_read_lock();
911   - list_for_each_entry_rcu(port, &team->port_list, list) {
912   - const struct net_device_ops *ops = port->dev->netdev_ops;
913   -
914   - if (ops->ndo_vlan_rx_add_vid)
915   - ops->ndo_vlan_rx_add_vid(port->dev, vid);
  912 + /*
  913 + * Alhough this is reader, it's guarded by team lock. It's not possible
  914 + * to traverse list in reverse under rcu_read_lock
  915 + */
  916 + mutex_lock(&team->lock);
  917 + list_for_each_entry(port, &team->port_list, list) {
  918 + err = vlan_vid_add(port->dev, vid);
  919 + if (err)
  920 + goto unwind;
916 921 }
917   - rcu_read_unlock();
  922 + mutex_unlock(&team->lock);
918 923  
919 924 return 0;
  925 +
  926 +unwind:
  927 + list_for_each_entry_continue_reverse(port, &team->port_list, list)
  928 + vlan_vid_del(port->dev, vid);
  929 + mutex_unlock(&team->lock);
  930 +
  931 + return err;
920 932 }
921 933  
922 934 static int team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
... ... @@ -925,12 +937,8 @@
925 937 struct team_port *port;
926 938  
927 939 rcu_read_lock();
928   - list_for_each_entry_rcu(port, &team->port_list, list) {
929   - const struct net_device_ops *ops = port->dev->netdev_ops;
930   -
931   - if (ops->ndo_vlan_rx_kill_vid)
932   - ops->ndo_vlan_rx_kill_vid(port->dev, vid);
933   - }
  940 + list_for_each_entry_rcu(port, &team->port_list, list)
  941 + vlan_vid_del(port->dev, vid);
934 942 rcu_read_unlock();
935 943  
936 944 return 0;
include/linux/if_vlan.h
... ... @@ -109,6 +109,9 @@
109 109 extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler);
110 110 extern struct sk_buff *vlan_untag(struct sk_buff *skb);
111 111  
  112 +extern int vlan_vid_add(struct net_device *dev, unsigned short vid);
  113 +extern void vlan_vid_del(struct net_device *dev, unsigned short vid);
  114 +
112 115 #else
113 116 static inline struct net_device *
114 117 __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id)
... ... @@ -138,6 +141,15 @@
138 141 static inline struct sk_buff *vlan_untag(struct sk_buff *skb)
139 142 {
140 143 return skb;
  144 +}
  145 +
  146 +static inline int vlan_vid_add(struct net_device *dev, unsigned short vid)
  147 +{
  148 + return 0;
  149 +}
  150 +
  151 +static inline void vlan_vid_del(struct net_device *dev, unsigned short vid)
  152 +{
141 153 }
142 154 #endif
143 155  
... ... @@ -101,7 +101,6 @@
101 101 {
102 102 struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
103 103 struct net_device *real_dev = vlan->real_dev;
104   - const struct net_device_ops *ops = real_dev->netdev_ops;
105 104 struct vlan_group *grp;
106 105 u16 vlan_id = vlan->vlan_id;
107 106  
... ... @@ -114,8 +113,8 @@
114 113 * HW accelerating devices or SW vlan input packet processing if
115 114 * VLAN is not 0 (leave it there for 802.1p).
116 115 */
117   - if (vlan_id && (real_dev->features & NETIF_F_HW_VLAN_FILTER))
118   - ops->ndo_vlan_rx_kill_vid(real_dev, vlan_id);
  116 + if (vlan_id)
  117 + vlan_vid_del(real_dev, vlan_id);
119 118  
120 119 grp->nr_vlans--;
121 120  
... ... @@ -169,7 +168,6 @@
169 168 {
170 169 struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
171 170 struct net_device *real_dev = vlan->real_dev;
172   - const struct net_device_ops *ops = real_dev->netdev_ops;
173 171 u16 vlan_id = vlan->vlan_id;
174 172 struct vlan_group *grp, *ngrp = NULL;
175 173 int err;
... ... @@ -207,8 +205,7 @@
207 205 if (ngrp) {
208 206 rcu_assign_pointer(real_dev->vlgrp, ngrp);
209 207 }
210   - if (real_dev->features & NETIF_F_HW_VLAN_FILTER)
211   - ops->ndo_vlan_rx_add_vid(real_dev, vlan_id);
  208 + vlan_vid_add(real_dev, vlan_id);
212 209  
213 210 return 0;
214 211  
215 212  
... ... @@ -369,11 +366,10 @@
369 366 __vlan_device_event(dev, event);
370 367  
371 368 if ((event == NETDEV_UP) &&
372   - (dev->features & NETIF_F_HW_VLAN_FILTER) &&
373   - dev->netdev_ops->ndo_vlan_rx_add_vid) {
  369 + (dev->features & NETIF_F_HW_VLAN_FILTER)) {
374 370 pr_info("adding VLAN 0 to HW filter on device %s\n",
375 371 dev->name);
376   - dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
  372 + vlan_vid_add(dev, 0);
377 373 }
378 374  
379 375 grp = rtnl_dereference(dev->vlgrp);
net/8021q/vlan_core.c
... ... @@ -146,4 +146,27 @@
146 146 kfree_skb(skb);
147 147 return NULL;
148 148 }
  149 +
  150 +int vlan_vid_add(struct net_device *dev, unsigned short vid)
  151 +{
  152 + const struct net_device_ops *ops = dev->netdev_ops;
  153 +
  154 + if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
  155 + ops->ndo_vlan_rx_add_vid) {
  156 + return ops->ndo_vlan_rx_add_vid(dev, vid);
  157 + }
  158 + return 0;
  159 +}
  160 +EXPORT_SYMBOL(vlan_vid_add);
  161 +
  162 +void vlan_vid_del(struct net_device *dev, unsigned short vid)
  163 +{
  164 + const struct net_device_ops *ops = dev->netdev_ops;
  165 +
  166 + if ((dev->features & NETIF_F_HW_VLAN_FILTER) &&
  167 + ops->ndo_vlan_rx_kill_vid) {
  168 + ops->ndo_vlan_rx_kill_vid(dev, vid);
  169 + }
  170 +}
  171 +EXPORT_SYMBOL(vlan_vid_del);