diff options
-rw-r--r-- | include/linux/if_vlan.h | 8 | ||||
-rw-r--r-- | net/8021q/vlan_core.c | 21 |
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 | ||
123 | extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, | ||
124 | u16 vlan_id); | ||
123 | extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); | 125 | extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); |
124 | extern u16 vlan_dev_vlan_id(const struct net_device *dev); | 126 | extern 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 |
140 | static inline struct net_device * | ||
141 | __vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id) | ||
142 | { | ||
143 | return NULL; | ||
144 | } | ||
145 | |||
138 | static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev) | 146 | static 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. */ | ||
67 | struct 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 | } | ||
85 | EXPORT_SYMBOL(__vlan_find_dev_deep); | ||
86 | |||
66 | struct net_device *vlan_dev_real_dev(const struct net_device *dev) | 87 | struct 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; |