Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8d13e670 authored by John Fastabend's avatar John Fastabend Committed by David S. Miller
Browse files

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: default avatarJohn Fastabend <john.r.fastabend@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5d0c90cf
Loading
Loading
Loading
Loading
+38 −1
Original line number Diff line number Diff line
@@ -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)