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 <[email protected]>
---
 drivers/net/netdevsim/netdev.c    | 65 ++++++++++++++++++++++++++++++-
 drivers/net/netdevsim/netdevsim.h |  8 ++++
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 3645ebde049a..19b0ff183c45 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -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,
diff --git a/drivers/net/netdevsim/netdevsim.h 
b/drivers/net/netdevsim/netdevsim.h
index f767fc8a7505..f844c27ca78b 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -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;
-- 
2.53.0


Reply via email to