xsk: add new netlink attribute dedicated for ZC max frags
authorMaciej Fijalkowski <maciej.fijalkowski@intel.com>
Wed, 19 Jul 2023 13:24:07 +0000 (15:24 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 19 Jul 2023 16:56:49 +0000 (09:56 -0700)
Introduce new netlink attribute NETDEV_A_DEV_XDP_ZC_MAX_SEGS that will
carry maximum fragments that underlying ZC driver is able to handle on
TX side. It is going to be included in netlink response only when driver
supports ZC. Any value higher than 1 implies multi-buffer ZC support on
underlying device.

Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
Link: https://lore.kernel.org/r/20230719132421.584801-11-maciej.fijalkowski@intel.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Documentation/netlink/specs/netdev.yaml
include/linux/netdevice.h
include/uapi/linux/netdev.h
net/core/dev.c
net/core/netdev-genl.c
tools/include/uapi/linux/netdev.h
tools/lib/bpf/libbpf.h
tools/lib/bpf/netlink.c

index b99e7ffef7a1578f837e96047ddd0e4967adbed8..e41015310a6e30c19643f7a3df8119a4da6c448a 100644 (file)
@@ -62,6 +62,12 @@ attribute-sets:
         type: u64
         enum: xdp-act
         enum-as-flags: true
+      -
+        name: xdp_zc_max_segs
+        doc: max fragment count supported by ZC driver
+        type: u32
+        checks:
+          min: 1
 
 operations:
   list:
index b828c7a75be20b76c87e8ab7152d4bd55ee83438..b12477ea4032bc50a5f40b8503718b93bcf3c986 100644 (file)
@@ -2250,6 +2250,7 @@ struct net_device {
 #define GRO_MAX_SIZE           (8 * 65535u)
        unsigned int            gro_max_size;
        unsigned int            gro_ipv4_max_size;
+       unsigned int            xdp_zc_max_segs;
        rx_handler_func_t __rcu *rx_handler;
        void __rcu              *rx_handler_data;
 
index 639524b59930bfcabcd0d352048a3fd4aa1da08b..bf71698a1e82aa40e87610aada8a5a45ff11df87 100644 (file)
@@ -41,6 +41,7 @@ enum {
        NETDEV_A_DEV_IFINDEX = 1,
        NETDEV_A_DEV_PAD,
        NETDEV_A_DEV_XDP_FEATURES,
+       NETDEV_A_DEV_XDP_ZC_MAX_SEGS,
 
        __NETDEV_A_DEV_MAX,
        NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
index d6e1b786c5c52686d4ba442ff8a412e34b07c2ef..dd4f114a7cbfe5125229fda7c47e0c3b3e62c380 100644 (file)
@@ -10613,6 +10613,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        dev_net_set(dev, &init_net);
 
        dev->gso_max_size = GSO_LEGACY_MAX_SIZE;
+       dev->xdp_zc_max_segs = 1;
        dev->gso_max_segs = GSO_MAX_SEGS;
        dev->gro_max_size = GRO_LEGACY_MAX_SIZE;
        dev->gso_ipv4_max_size = GSO_LEGACY_MAX_SIZE;
index a4270fafdf11978c7546972470dabb7eda575db4..65ef4867fc495b44b3eec63783a63b4359d1b9a2 100644 (file)
@@ -25,6 +25,14 @@ netdev_nl_dev_fill(struct net_device *netdev, struct sk_buff *rsp,
                return -EINVAL;
        }
 
+       if (netdev->xdp_features & NETDEV_XDP_ACT_XSK_ZEROCOPY) {
+               if (nla_put_u32(rsp, NETDEV_A_DEV_XDP_ZC_MAX_SEGS,
+                               netdev->xdp_zc_max_segs)) {
+                       genlmsg_cancel(rsp, hdr);
+                       return -EINVAL;
+               }
+       }
+
        genlmsg_end(rsp, hdr);
 
        return 0;
index 639524b59930bfcabcd0d352048a3fd4aa1da08b..bf71698a1e82aa40e87610aada8a5a45ff11df87 100644 (file)
@@ -41,6 +41,7 @@ enum {
        NETDEV_A_DEV_IFINDEX = 1,
        NETDEV_A_DEV_PAD,
        NETDEV_A_DEV_XDP_FEATURES,
+       NETDEV_A_DEV_XDP_ZC_MAX_SEGS,
 
        __NETDEV_A_DEV_MAX,
        NETDEV_A_DEV_MAX = (__NETDEV_A_DEV_MAX - 1)
index 10642ad69d763228392f8a8261b93cd6a29c8689..674e5788eb1080912523c3089d1c888fef6a7802 100644 (file)
@@ -1105,9 +1105,10 @@ struct bpf_xdp_query_opts {
        __u32 skb_prog_id;      /* output */
        __u8 attach_mode;       /* output */
        __u64 feature_flags;    /* output */
+       __u32 xdp_zc_max_segs;  /* output */
        size_t :0;
 };
-#define bpf_xdp_query_opts__last_field feature_flags
+#define bpf_xdp_query_opts__last_field xdp_zc_max_segs
 
 LIBBPF_API int bpf_xdp_attach(int ifindex, int prog_fd, __u32 flags,
                              const struct bpf_xdp_attach_opts *opts);
index 84dd5fa149058d21c196fdb6e011f98779961765..090bcf6e3b3d583e07088dba0daea7ef72fa5bd6 100644 (file)
@@ -45,6 +45,7 @@ struct xdp_id_md {
 
 struct xdp_features_md {
        int ifindex;
+       __u32 xdp_zc_max_segs;
        __u64 flags;
 };
 
@@ -421,6 +422,9 @@ static int parse_xdp_features(struct nlmsghdr *nh, libbpf_dump_nlmsg_t fn,
                return NL_CONT;
 
        md->flags = libbpf_nla_getattr_u64(tb[NETDEV_A_DEV_XDP_FEATURES]);
+       if (tb[NETDEV_A_DEV_XDP_ZC_MAX_SEGS])
+               md->xdp_zc_max_segs =
+                       libbpf_nla_getattr_u32(tb[NETDEV_A_DEV_XDP_ZC_MAX_SEGS]);
        return NL_DONE;
 }
 
@@ -493,6 +497,7 @@ int bpf_xdp_query(int ifindex, int xdp_flags, struct bpf_xdp_query_opts *opts)
                return libbpf_err(err);
 
        opts->feature_flags = md.flags;
+       opts->xdp_zc_max_segs = md.xdp_zc_max_segs;
 
 skip_feature_flags:
        return 0;