#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 
+extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev,
+                                              u16 vlan_id);
 extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
 extern u16 vlan_dev_vlan_id(const struct net_device *dev);
 
               unsigned int vlan_tci);
 
 #else
+static inline struct net_device *
+__vlan_find_dev_deep(struct net_device *real_dev, u16 vlan_id)
+{
+       return NULL;
+}
+
 static inline struct net_device *vlan_dev_real_dev(const struct net_device *dev)
 {
        BUG();
 
        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;