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: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/20260408115240.1636047-3-cratiu@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Cosmin Ratiu
2026-04-08 14:52:38 +03:00
committed by Jakub Kicinski
parent e1ab601bb2
commit c89f194b6b
2 changed files with 71 additions and 2 deletions

View File

@@ -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,