|
@@ -63,6 +63,27 @@ bool vlan_do_receive(struct sk_buff **skbp)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
+/* Must be invoked with rcu_read_lock or with RTNL. */
|
|
|
+struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
|
|
|
+ u16 vlan_id)
|
|
|
+{
|
|
|
+ struct vlan_group *grp = rcu_dereference_rtnl(real_dev->vlgrp);
|
|
|
+
|
|
|
+ if (grp) {
|
|
|
+ return vlan_group_get_device(grp, vlan_id);
|
|
|
+ } else {
|
|
|
+ /*
|
|
|
+ * Bonding slaves do not have grp assigned to themselves.
|
|
|
+ * Grp is assigned to bonding master instead.
|
|
|
+ */
|
|
|
+ if (netif_is_bond_slave(real_dev))
|
|
|
+ return __vlan_find_dev_deep(real_dev->master, vlan_id);
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(__vlan_find_dev_deep);
|
|
|
+
|
|
|
struct net_device *vlan_dev_real_dev(const struct net_device *dev)
|
|
|
{
|
|
|
return vlan_dev_info(dev)->real_dev;
|