Commit c89f194b authored by Cosmin Ratiu's avatar Cosmin Ratiu Committed by Jakub Kicinski
Browse files

nsim: Add support for VLAN filters



Add support for storing the list of VLANs in nsim devices, together with
ops for adding/removing them and a debug file to show them.

This will be used in upcoming tests.

Signed-off-by: default avatarCosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/20260408115240.1636047-3-cratiu@nvidia.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent e1ab601b
Loading
Loading
Loading
Loading
+63 −2
Original line number Diff line number Diff line
@@ -605,6 +605,36 @@ static int nsim_stop(struct net_device *dev)
	return 0;
}

static int nsim_vlan_rx_add_vid(struct net_device *dev, __be16 proto, u16 vid)
{
	struct netdevsim *ns = netdev_priv(dev);

	if (vid >= VLAN_N_VID)
		return -EINVAL;

	if (proto == htons(ETH_P_8021Q))
		WARN_ON_ONCE(test_and_set_bit(vid, ns->vlan.ctag));
	else if (proto == htons(ETH_P_8021AD))
		WARN_ON_ONCE(test_and_set_bit(vid, ns->vlan.stag));

	return 0;
}

static int nsim_vlan_rx_kill_vid(struct net_device *dev, __be16 proto, u16 vid)
{
	struct netdevsim *ns = netdev_priv(dev);

	if (vid >= VLAN_N_VID)
		return -EINVAL;

	if (proto == htons(ETH_P_8021Q))
		WARN_ON_ONCE(!test_and_clear_bit(vid, ns->vlan.ctag));
	else if (proto == htons(ETH_P_8021AD))
		WARN_ON_ONCE(!test_and_clear_bit(vid, ns->vlan.stag));

	return 0;
}

static int nsim_shaper_set(struct net_shaper_binding *binding,
			   const struct net_shaper *shaper,
			   struct netlink_ext_ack *extack)
@@ -662,6 +692,8 @@ static const struct net_device_ops nsim_netdev_ops = {
	.ndo_bpf		= nsim_bpf,
	.ndo_open		= nsim_open,
	.ndo_stop		= nsim_stop,
	.ndo_vlan_rx_add_vid	= nsim_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= nsim_vlan_rx_kill_vid,
	.net_shaper_ops		= &nsim_shaper_ops,
};

@@ -673,6 +705,8 @@ static const struct net_device_ops nsim_vf_netdev_ops = {
	.ndo_change_mtu		= nsim_change_mtu,
	.ndo_setup_tc		= nsim_setup_tc,
	.ndo_set_features	= nsim_set_features,
	.ndo_vlan_rx_add_vid	= nsim_vlan_rx_add_vid,
	.ndo_vlan_rx_kill_vid	= nsim_vlan_rx_kill_vid,
};

/* We don't have true per-queue stats, yet, so do some random fakery here.
@@ -970,6 +1004,20 @@ static const struct file_operations nsim_pp_hold_fops = {
	.owner = THIS_MODULE,
};

static int nsim_vlan_show(struct seq_file *s, void *data)
{
	struct netdevsim *ns = s->private;
	int vid;

	for_each_set_bit(vid, ns->vlan.ctag, VLAN_N_VID)
		seq_printf(s, "ctag %d\n", vid);
	for_each_set_bit(vid, ns->vlan.stag, VLAN_N_VID)
		seq_printf(s, "stag %d\n", vid);

	return 0;
}
DEFINE_SHOW_ATTRIBUTE(nsim_vlan);

static void nsim_setup(struct net_device *dev)
{
	ether_setup(dev);
@@ -982,14 +1030,18 @@ static void nsim_setup(struct net_device *dev)
			 NETIF_F_FRAGLIST |
			 NETIF_F_HW_CSUM |
			 NETIF_F_LRO |
			 NETIF_F_TSO;
			 NETIF_F_TSO |
			 NETIF_F_HW_VLAN_CTAG_FILTER |
			 NETIF_F_HW_VLAN_STAG_FILTER;
	dev->hw_features |= NETIF_F_HW_TC |
			    NETIF_F_SG |
			    NETIF_F_FRAGLIST |
			    NETIF_F_HW_CSUM |
			    NETIF_F_LRO |
			    NETIF_F_TSO |
			    NETIF_F_LOOPBACK;
			    NETIF_F_LOOPBACK |
			    NETIF_F_HW_VLAN_CTAG_FILTER |
			    NETIF_F_HW_VLAN_STAG_FILTER;
	dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
	dev->max_mtu = ETH_MAX_MTU;
	dev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_HW_OFFLOAD;
@@ -1156,6 +1208,8 @@ struct netdevsim *nsim_create(struct nsim_dev *nsim_dev,
	ns->qr_dfs = debugfs_create_file("queue_reset", 0200,
					 nsim_dev_port->ddir, ns,
					 &nsim_qreset_fops);
	ns->vlan_dfs = debugfs_create_file("vlan", 0400, nsim_dev_port->ddir,
					   ns, &nsim_vlan_fops);
	return ns;

err_free_netdev:
@@ -1167,7 +1221,9 @@ void nsim_destroy(struct netdevsim *ns)
{
	struct net_device *dev = ns->netdev;
	struct netdevsim *peer;
	u16 vid;

	debugfs_remove(ns->vlan_dfs);
	debugfs_remove(ns->qr_dfs);
	debugfs_remove(ns->pp_dfs);

@@ -1193,6 +1249,11 @@ void nsim_destroy(struct netdevsim *ns)
	if (nsim_dev_port_is_pf(ns->nsim_dev_port))
		nsim_exit_netdevsim(ns);

	for_each_set_bit(vid, ns->vlan.ctag, VLAN_N_VID)
		WARN_ON_ONCE(1);
	for_each_set_bit(vid, ns->vlan.stag, VLAN_N_VID)
		WARN_ON_ONCE(1);

	/* Put this intentionally late to exercise the orphaning path */
	if (ns->page) {
		page_pool_put_full_page(pp_page_to_nmdesc(ns->page)->pp,
+8 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/ethtool.h>
#include <linux/ethtool_netlink.h>
#include <linux/kernel.h>
#include <linux/if_vlan.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/ptp_mock.h>
@@ -75,6 +76,11 @@ struct nsim_macsec {
	u8 nsim_secy_count;
};

struct nsim_vlan {
	DECLARE_BITMAP(ctag, VLAN_N_VID);
	DECLARE_BITMAP(stag, VLAN_N_VID);
};

struct nsim_ethtool_pauseparam {
	bool rx;
	bool tx;
@@ -135,6 +141,7 @@ struct netdevsim {
	bool bpf_map_accept;
	struct nsim_ipsec ipsec;
	struct nsim_macsec macsec;
	struct nsim_vlan vlan;
	struct {
		u32 inject_error;
		u32 __ports[2][NSIM_UDP_TUNNEL_N_PORTS];
@@ -146,6 +153,7 @@ struct netdevsim {
	struct page *page;
	struct dentry *pp_dfs;
	struct dentry *qr_dfs;
	struct dentry *vlan_dfs;

	struct nsim_ethtool ethtool;
	struct netdevsim __rcu *peer;