@@ -132,6 +132,7 @@ extern int vlan_for_each(struct net_device *dev,
int (*action)(struct net_device *dev, int vid,
void *arg), void *arg);
extern u16 vlan_dev_get_addr_vid(struct net_device *dev, const u8 *addr);
+extern void vlan_dev_ivdf_set(struct net_device *dev, bool enable);
extern struct net_device *vlan_dev_real_dev(const struct net_device *dev);
extern u16 vlan_dev_vlan_id(const struct net_device *dev);
extern __be16 vlan_dev_vlan_proto(const struct net_device *dev);
@@ -39,3 +39,15 @@ config VLAN_8021Q_MVRP
supersedes GVRP and is not backwards-compatible.
If unsure, say N.
+
+config VLAN_8021Q_IVDF
+ bool "IVDF (Individual Virtual Device Filtering) support"
+ depends on VLAN_8021Q
+ help
+ Select this to enable IVDF addressing scheme support. IVDF is used
+ for automatic propagation of registered VLANs addresses to real end
+ devices. If no device supporting IVDF then disable this as it can
+ consume some memory in configuration with complex network device
+ structures to hold vlan addresses.
+
+ If unsure, say N.
@@ -453,6 +453,18 @@ bool vlan_uses_dev(const struct net_device *dev)
}
EXPORT_SYMBOL(vlan_uses_dev);
+void vlan_dev_ivdf_set(struct net_device *dev, bool enable)
+{
+#ifdef CONFIG_VLAN_8021Q_IVDF
+ if (enable) {
+ dev->vid_len = NET_8021Q_VID_TSIZE;
+ return;
+ }
+#endif
+ dev->vid_len = 0;
+}
+EXPORT_SYMBOL(vlan_dev_ivdf_set);
+
u16 vlan_dev_get_addr_vid(struct net_device *dev, const u8 *addr)
{
u16 vid = 0;
@@ -894,5 +894,6 @@ void vlan_setup(struct net_device *dev)
dev->min_mtu = 0;
dev->max_mtu = ETH_MAX_MTU;
+ vlan_dev_ivdf_set(dev, true);
eth_zero_addr(dev->broadcast);
}
@@ -372,6 +372,7 @@ void ether_setup(struct net_device *dev)
dev->flags = IFF_BROADCAST|IFF_MULTICAST;
dev->priv_flags |= IFF_TX_SKB_SHARING;
+ vlan_dev_ivdf_set(dev, false);
eth_broadcast_addr(dev->broadcast);
}
@@ -395,8 +396,15 @@ EXPORT_SYMBOL(ether_setup);
struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs,
unsigned int rxqs)
{
- return alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_UNKNOWN,
- ether_setup, txqs, rxqs);
+ struct net_device *dev;
+
+ dev = alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_UNKNOWN,
+ ether_setup, txqs, rxqs);
+ if (!dev)
+ return NULL;
+
+ vlan_dev_ivdf_set(dev, false);
+ return dev;
}
EXPORT_SYMBOL(alloc_etherdev_mqs);