diff options
author | John Fastabend <john.r.fastabend@intel.com> | 2011-06-06 08:27:16 +0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-06-07 03:43:43 +0400 |
commit | 8d13e670d3fb83f4668c9e37196c3bbf5b9f094c (patch) | |
tree | c921e3e49d089fe315ff356a354b2f7c6558ecbe /drivers/net/macvlan.c | |
parent | 5d0c90cf4d417ccafcd1af4ec32945c3f80e98e2 (diff) | |
download | linux-8d13e670d3fb83f4668c9e37196c3bbf5b9f094c.tar.xz |
macvlan: add VLAN filters to lowerdev
Stacking VLANs on top of the macvlan device does not
work if the lowerdev device is using vlan filters set
by NETIF_F_HW_VLAN_FILTER. Add ndo ops to pass vlan
calls to lowerdev.
Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/macvlan.c')
-rw-r--r-- | drivers/net/macvlan.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index d6aeaa5f25ea..cc67cbe670cb 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -414,7 +414,8 @@ static struct lock_class_key macvlan_netdev_addr_lock_key; #define MACVLAN_FEATURES \ (NETIF_F_SG | NETIF_F_ALL_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \ NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_GSO_ROBUST | \ - NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM) + NETIF_F_TSO_ECN | NETIF_F_TSO6 | NETIF_F_GRO | NETIF_F_RXCSUM | \ + NETIF_F_HW_VLAN_FILTER) #define MACVLAN_STATE_MASK \ ((1<<__LINK_STATE_NOCARRIER) | (1<<__LINK_STATE_DORMANT)) @@ -509,6 +510,39 @@ static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev, return stats; } +static void macvlan_vlan_rx_register(struct net_device *dev, + struct vlan_group *grp) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; + + if (ops->ndo_vlan_rx_register) + ops->ndo_vlan_rx_register(lowerdev, grp); +} + +static void macvlan_vlan_rx_add_vid(struct net_device *dev, + unsigned short vid) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; + + if (ops->ndo_vlan_rx_add_vid) + ops->ndo_vlan_rx_add_vid(lowerdev, vid); +} + +static void macvlan_vlan_rx_kill_vid(struct net_device *dev, + unsigned short vid) +{ + struct macvlan_dev *vlan = netdev_priv(dev); + struct net_device *lowerdev = vlan->lowerdev; + const struct net_device_ops *ops = lowerdev->netdev_ops; + + if (ops->ndo_vlan_rx_kill_vid) + ops->ndo_vlan_rx_kill_vid(lowerdev, vid); +} + static void macvlan_ethtool_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { @@ -541,6 +575,9 @@ static const struct net_device_ops macvlan_netdev_ops = { .ndo_set_multicast_list = macvlan_set_multicast_list, .ndo_get_stats64 = macvlan_dev_get_stats64, .ndo_validate_addr = eth_validate_addr, + .ndo_vlan_rx_register = macvlan_vlan_rx_register, + .ndo_vlan_rx_add_vid = macvlan_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = macvlan_vlan_rx_kill_vid, }; void macvlan_common_setup(struct net_device *dev) |