aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_vlan.h8
-rw-r--r--net/8021q/vlan_core.c21
2 files changed, 29 insertions, 0 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index cfb0cf2230a9..69391cc20f3d 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -120,6 +120,8 @@ static inline int is_vlan_dev(struct net_device *dev)
120 120
121#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) 121#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
122 122
123extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
124 u16 vlan_id);
123extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); 125extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
124extern u16 vlan_dev_vlan_id(const struct net_device *dev); 126extern u16 vlan_dev_vlan_id(const struct net_device *dev);
125 127
@@ -135,6 +137,12 @@ vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp,
135 unsigned int vlan_tci); 137 unsigned int vlan_tci);
136 138
137#else 139#else
140static inline struct net_device *
141__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id)
142{
143 return NULL;
144}
145
138static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) 146static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
139{ 147{
140 BUG(); 148 BUG();
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c
index fcc684678af6..5940366fac48 100644
--- a/net/8021q/vlan_core.c
+++ b/net/8021q/vlan_core.c
@@ -63,6 +63,27 @@ bool vlan_do_receive(struct sk_buff **skbp)
63 return true; 63 return true;
64} 64}
65 65
66/* Must be invoked with rcu_read_lock or with RTNL. */
67struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
68 u16 vlan_id)
69{
70 struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp);
71
72 if (grp) {
73 return vlan_group_get_device(grp, vlan_id);
74 } else {
75 /*
76 * Bonding slaves do not have grp assigned to themselves.
77 * Grp is assigned to bonding master instead.
78 */
79 if (netif_is_bond_slave(real_dev))
80 return __vlan_find_dev_deep(real_dev->master, vlan_id);
81 }
82
83 return NULL;
84}
85EXPORT_SYMBOL(__vlan_find_dev_deep);
86
66struct net_device *vlan_dev_real_dev(const struct net_device *dev) 87struct net_device *vlan_dev_real_dev(const struct net_device *dev)
67{ 88{
68 return vlan_dev_info(dev)->real_dev; 89 return vlan_dev_info(dev)->real_dev;