Skip to content

Commit 87002b0

Browse files
Jiri Pirkodavem330
Jiri Pirko
authored andcommitted
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>
1 parent 8e58613 commit 87002b0

File tree

6 files changed

+87
-59
lines changed

6 files changed

+87
-59
lines changed

drivers/net/bonding/bond_main.c

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -431,17 +431,13 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb,
431431
static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
432432
{
433433
struct bonding *bond = netdev_priv(bond_dev);
434-
struct slave *slave;
434+
struct slave *slave, *stop_at;
435435
int i, res;
436436

437437
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;
445441
}
446442

447443
res = bond_add_vlan(bond, vid);
@@ -452,6 +448,14 @@ static int bond_vlan_rx_add_vid(struct net_device *bond_dev, uint16_t vid)
452448
}
453449

454450
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;
455459
}
456460

457461
/**
@@ -465,15 +469,8 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
465469
struct slave *slave;
466470
int i, res;
467471

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;
471-
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-
}
472+
bond_for_each_slave(bond, slave, i)
473+
vlan_vid_del(slave->dev, vid);
477474

478475
res = bond_del_vlan(bond, vid);
479476
if (res) {
@@ -488,30 +485,26 @@ static int bond_vlan_rx_kill_vid(struct net_device *bond_dev, uint16_t vid)
488485
static void bond_add_vlans_on_slave(struct bonding *bond, struct net_device *slave_dev)
489486
{
490487
struct vlan_entry *vlan;
491-
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
492-
493-
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
494-
!(slave_ops->ndo_vlan_rx_add_vid))
495-
return;
488+
int res;
496489

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+
}
499497
}
500498

501499
static void bond_del_vlans_from_slave(struct bonding *bond,
502500
struct net_device *slave_dev)
503501
{
504-
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
505502
struct vlan_entry *vlan;
506503

507-
if (!(slave_dev->features & NETIF_F_HW_VLAN_FILTER) ||
508-
!(slave_ops->ndo_vlan_rx_kill_vid))
509-
return;
510-
511504
list_for_each_entry(vlan, &bond->vlan_list, vlan_list) {
512505
if (!vlan->vlan_id)
513506
continue;
514-
slave_ops->ndo_vlan_rx_kill_vid(slave_dev, vlan->vlan_id);
507+
vlan_vid_del(slave_dev, vlan->vlan_id);
515508
}
516509
}
517510

drivers/net/macvlan.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <linux/etherdevice.h>
2727
#include <linux/ethtool.h>
2828
#include <linux/if_arp.h>
29+
#include <linux/if_vlan.h>
2930
#include <linux/if_link.h>
3031
#include <linux/if_macvlan.h>
3132
#include <net/rtnetlink.h>
@@ -525,22 +526,17 @@ static int macvlan_vlan_rx_add_vid(struct net_device *dev,
525526
{
526527
struct macvlan_dev *vlan = netdev_priv(dev);
527528
struct net_device *lowerdev = vlan->lowerdev;
528-
const struct net_device_ops *ops = lowerdev->netdev_ops;
529529

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);
533531
}
534532

535533
static int macvlan_vlan_rx_kill_vid(struct net_device *dev,
536534
unsigned short vid)
537535
{
538536
struct macvlan_dev *vlan = netdev_priv(dev);
539537
struct net_device *lowerdev = vlan->lowerdev;
540-
const struct net_device_ops *ops = lowerdev->netdev_ops;
541538

542-
if (ops->ndo_vlan_rx_kill_vid)
543-
return ops->ndo_vlan_rx_kill_vid(lowerdev, vid);
539+
vlan_vid_del(lowerdev, vid);
544540
return 0;
545541
}
546542

drivers/net/team/team.c

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/ctype.h>
1919
#include <linux/notifier.h>
2020
#include <linux/netdevice.h>
21+
#include <linux/if_vlan.h>
2122
#include <linux/if_arp.h>
2223
#include <linux/socket.h>
2324
#include <linux/etherdevice.h>
@@ -906,17 +907,28 @@ static int team_vlan_rx_add_vid(struct net_device *dev, uint16_t vid)
906907
{
907908
struct team *team = netdev_priv(dev);
908909
struct team_port *port;
910+
int err;
909911

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;
916921
}
917-
rcu_read_unlock();
922+
mutex_unlock(&team->lock);
918923

919924
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;
920932
}
921933

922934
static int team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
@@ -925,12 +937,8 @@ static int team_vlan_rx_kill_vid(struct net_device *dev, uint16_t vid)
925937
struct team_port *port;
926938

927939
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);
934942
rcu_read_unlock();
935943

936944
return 0;

include/linux/if_vlan.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ extern u16 vlan_dev_vlan_id(const struct net_device *dev);
109109
extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler);
110110
extern struct sk_buff *vlan_untag(struct sk_buff *skb);
111111

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+
112115
#else
113116
static inline struct net_device *
114117
__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id)
@@ -139,6 +142,15 @@ static inline struct sk_buff *vlan_untag(struct sk_buff *skb)
139142
{
140143
return skb;
141144
}
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+
{
153+
}
142154
#endif
143155

144156
/**

net/8021q/vlan.c

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
101101
{
102102
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
103103
struct net_device *real_dev = vlan->real_dev;
104-
const struct net_device_ops *ops = real_dev->netdev_ops;
105104
struct vlan_group *grp;
106105
u16 vlan_id = vlan->vlan_id;
107106

@@ -114,8 +113,8 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
114113
* HW accelerating devices or SW vlan input packet processing if
115114
* VLAN is not 0 (leave it there for 802.1p).
116115
*/
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);
119118

120119
grp->nr_vlans--;
121120

@@ -169,7 +168,6 @@ int register_vlan_dev(struct net_device *dev)
169168
{
170169
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
171170
struct net_device *real_dev = vlan->real_dev;
172-
const struct net_device_ops *ops = real_dev->netdev_ops;
173171
u16 vlan_id = vlan->vlan_id;
174172
struct vlan_group *grp, *ngrp = NULL;
175173
int err;
@@ -207,8 +205,7 @@ int register_vlan_dev(struct net_device *dev)
207205
if (ngrp) {
208206
rcu_assign_pointer(real_dev->vlgrp, ngrp);
209207
}
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);
212209

213210
return 0;
214211

@@ -369,11 +366,10 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
369366
__vlan_device_event(dev, event);
370367

371368
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)) {
374370
pr_info("adding VLAN 0 to HW filter on device %s\n",
375371
dev->name);
376-
dev->netdev_ops->ndo_vlan_rx_add_vid(dev, 0);
372+
vlan_vid_add(dev, 0);
377373
}
378374

379375
grp = rtnl_dereference(dev->vlgrp);

net/8021q/vlan_core.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,26 @@ struct sk_buff *vlan_untag(struct sk_buff *skb)
146146
kfree_skb(skb);
147147
return NULL;
148148
}
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);

0 commit comments

Comments
 (0)