xdp: rss hash types representation
authorJesper Dangaard Brouer <brouer@redhat.com>
Wed, 12 Apr 2023 19:48:40 +0000 (21:48 +0200)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 13 Apr 2023 18:15:10 +0000 (11:15 -0700)
The RSS hash type specifies what portion of packet data NIC hardware used
when calculating RSS hash value. The RSS types are focused on Internet
traffic protocols at OSI layers L3 and L4. L2 (e.g. ARP) often get hash
value zero and no RSS type. For L3 focused on IPv4 vs. IPv6, and L4
primarily TCP vs UDP, but some hardware supports SCTP.

Hardware RSS types are differently encoded for each hardware NIC. Most
hardware represent RSS hash type as a number. Determining L3 vs L4 often
requires a mapping table as there often isn't a pattern or sorting
according to ISO layer.

The patch introduce a XDP RSS hash type (enum xdp_rss_hash_type) that
contains both BITs for the L3/L4 types, and combinations to be used by
drivers for their mapping tables. The enum xdp_rss_type_bits get exposed
to BPF via BTF, and it is up to the BPF-programmer to match using these
defines.

This proposal change the kfunc API bpf_xdp_metadata_rx_hash() adding
a pointer value argument for provide the RSS hash type.
Change signature for all xmo_rx_hash calls in drivers to make it compile.

The RSS type implementations for each driver comes as separate patches.

Fixes: 3d76a4d3d4e5 ("bpf: XDP metadata RX kfuncs")
Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
Acked-by: Toke Høiland-Jørgensen <toke@redhat.com>
Acked-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/168132892042.340624.582563003880565460.stgit@firesoul
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
drivers/net/veth.c
include/linux/netdevice.h
include/net/xdp.h
net/core/xdp.c

index 4b5e459b6d49fee01508e0fff1e203ba3d1cee74..73d10aa4c503fdbf26136fb97c7a929cf8a7cfd2 100644 (file)
@@ -681,7 +681,8 @@ int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        return 0;
 }
 
-int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
+int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                       enum xdp_rss_hash_type *rss_type)
 {
        struct mlx4_en_xdp_buff *_ctx = (void *)ctx;
 
index 544e09b97483cb4a09ff8957f12e35001c802d77..4ac4d883047b1c7b12317c62e705382c7e4d2d12 100644 (file)
@@ -798,7 +798,8 @@ int mlx4_en_netdev_event(struct notifier_block *this,
 
 struct xdp_md;
 int mlx4_en_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp);
-int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash);
+int mlx4_en_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                       enum xdp_rss_hash_type *rss_type);
 
 /*
  * Functions for time stamping
index c5dae48b7932f7a6216f55cb3b14faa7d167e1c8..efe609f8e3aac358ee675a64c6f0a8f6bf886696 100644 (file)
@@ -169,7 +169,8 @@ static int mlx5e_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        return 0;
 }
 
-static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
+static int mlx5e_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                            enum xdp_rss_hash_type *rss_type)
 {
        const struct mlx5e_xdp_buff *_ctx = (void *)ctx;
 
index c1178915496d80da7e8c63c91bf395444ce3194f..424e8876a16b604db699c5ac5377bf73d2e8076d 100644 (file)
@@ -1648,7 +1648,8 @@ static int veth_xdp_rx_timestamp(const struct xdp_md *ctx, u64 *timestamp)
        return 0;
 }
 
-static int veth_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash)
+static int veth_xdp_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                           enum xdp_rss_hash_type *rss_type)
 {
        struct veth_xdp_buff *_ctx = (void *)ctx;
 
index 470085b121d3c241e8045416e9d0426eb8a43850..c35f04f636f15a2a034baedd0b60b0857b96f0e0 100644 (file)
@@ -1624,7 +1624,8 @@ struct net_device_ops {
 
 struct xdp_metadata_ops {
        int     (*xmo_rx_timestamp)(const struct xdp_md *ctx, u64 *timestamp);
-       int     (*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash);
+       int     (*xmo_rx_hash)(const struct xdp_md *ctx, u32 *hash,
+                              enum xdp_rss_hash_type *rss_type);
 };
 
 /**
index 41c57b8b167147bb4544a9bdcb92e7a61459fc40..a76c4ea203eaab03d07674d6f8e26d81e0a22546 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/skbuff.h> /* skb_shared_info */
 #include <uapi/linux/netdev.h>
+#include <linux/bitfield.h>
 
 /**
  * DOC: XDP RX-queue information
@@ -425,6 +426,50 @@ XDP_METADATA_KFUNC_xxx
 MAX_XDP_METADATA_KFUNC,
 };
 
+enum xdp_rss_hash_type {
+       /* First part: Individual bits for L3/L4 types */
+       XDP_RSS_L3_IPV4         = BIT(0),
+       XDP_RSS_L3_IPV6         = BIT(1),
+
+       /* The fixed (L3) IPv4 and IPv6 headers can both be followed by
+        * variable/dynamic headers, IPv4 called Options and IPv6 called
+        * Extension Headers. HW RSS type can contain this info.
+        */
+       XDP_RSS_L3_DYNHDR       = BIT(2),
+
+       /* When RSS hash covers L4 then drivers MUST set XDP_RSS_L4 bit in
+        * addition to the protocol specific bit.  This ease interaction with
+        * SKBs and avoids reserving a fixed mask for future L4 protocol bits.
+        */
+       XDP_RSS_L4              = BIT(3), /* L4 based hash, proto can be unknown */
+       XDP_RSS_L4_TCP          = BIT(4),
+       XDP_RSS_L4_UDP          = BIT(5),
+       XDP_RSS_L4_SCTP         = BIT(6),
+       XDP_RSS_L4_IPSEC        = BIT(7), /* L4 based hash include IPSEC SPI */
+
+       /* Second part: RSS hash type combinations used for driver HW mapping */
+       XDP_RSS_TYPE_NONE            = 0,
+       XDP_RSS_TYPE_L2              = XDP_RSS_TYPE_NONE,
+
+       XDP_RSS_TYPE_L3_IPV4         = XDP_RSS_L3_IPV4,
+       XDP_RSS_TYPE_L3_IPV6         = XDP_RSS_L3_IPV6,
+       XDP_RSS_TYPE_L3_IPV4_OPT     = XDP_RSS_L3_IPV4 | XDP_RSS_L3_DYNHDR,
+       XDP_RSS_TYPE_L3_IPV6_EX      = XDP_RSS_L3_IPV6 | XDP_RSS_L3_DYNHDR,
+
+       XDP_RSS_TYPE_L4_ANY          = XDP_RSS_L4,
+       XDP_RSS_TYPE_L4_IPV4_TCP     = XDP_RSS_L3_IPV4 | XDP_RSS_L4 | XDP_RSS_L4_TCP,
+       XDP_RSS_TYPE_L4_IPV4_UDP     = XDP_RSS_L3_IPV4 | XDP_RSS_L4 | XDP_RSS_L4_UDP,
+       XDP_RSS_TYPE_L4_IPV4_SCTP    = XDP_RSS_L3_IPV4 | XDP_RSS_L4 | XDP_RSS_L4_SCTP,
+
+       XDP_RSS_TYPE_L4_IPV6_TCP     = XDP_RSS_L3_IPV6 | XDP_RSS_L4 | XDP_RSS_L4_TCP,
+       XDP_RSS_TYPE_L4_IPV6_UDP     = XDP_RSS_L3_IPV6 | XDP_RSS_L4 | XDP_RSS_L4_UDP,
+       XDP_RSS_TYPE_L4_IPV6_SCTP    = XDP_RSS_L3_IPV6 | XDP_RSS_L4 | XDP_RSS_L4_SCTP,
+
+       XDP_RSS_TYPE_L4_IPV6_TCP_EX  = XDP_RSS_TYPE_L4_IPV6_TCP  | XDP_RSS_L3_DYNHDR,
+       XDP_RSS_TYPE_L4_IPV6_UDP_EX  = XDP_RSS_TYPE_L4_IPV6_UDP  | XDP_RSS_L3_DYNHDR,
+       XDP_RSS_TYPE_L4_IPV6_SCTP_EX = XDP_RSS_TYPE_L4_IPV6_SCTP | XDP_RSS_L3_DYNHDR,
+};
+
 #ifdef CONFIG_NET
 u32 bpf_xdp_metadata_kfunc_id(int id);
 bool bpf_dev_bound_kfunc_id(u32 btf_id);
index 528d4b37983df8c61bd3f6f50b9f4ccbe8cc7132..fb85aca819619b344bdbb74f72e1e0a0d4c3e5b2 100644 (file)
@@ -734,13 +734,21 @@ __bpf_kfunc int bpf_xdp_metadata_rx_timestamp(const struct xdp_md *ctx, u64 *tim
  * bpf_xdp_metadata_rx_hash - Read XDP frame RX hash.
  * @ctx: XDP context pointer.
  * @hash: Return value pointer.
+ * @rss_type: Return value pointer for RSS type.
+ *
+ * The RSS hash type (@rss_type) specifies what portion of packet headers NIC
+ * hardware used when calculating RSS hash value.  The RSS type can be decoded
+ * via &enum xdp_rss_hash_type either matching on individual L3/L4 bits
+ * ``XDP_RSS_L*`` or by combined traditional *RSS Hashing Types*
+ * ``XDP_RSS_TYPE_L*``.
  *
  * Return:
  * * Returns 0 on success or ``-errno`` on error.
  * * ``-EOPNOTSUPP`` : means device driver doesn't implement kfunc
  * * ``-ENODATA``    : means no RX-hash available for this frame
  */
-__bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash)
+__bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash,
+                                        enum xdp_rss_hash_type *rss_type)
 {
        return -EOPNOTSUPP;
 }