selftests/bpf: Make sure we trigger metadata kfuncs for dst 8080
authorStanislav Fomichev <sdf@google.com>
Mon, 4 Dec 2023 17:44:23 +0000 (09:44 -0800)
committerDaniel Borkmann <daniel@iogearbox.net>
Tue, 5 Dec 2023 14:11:24 +0000 (15:11 +0100)
xdp_metadata test is flaky sometimes:

  verify_xsk_metadata:FAIL:rx_hash_type unexpected rx_hash_type: actual 8 != expected 0

Where 8 means XDP_RSS_TYPE_L4_ANY and is exported from veth driver only when
'skb->l4_hash' condition is met. This makes me think that the program is
triggering again for some other packet.

Let's have a filter, similar to xdp_hw_metadata, where we trigger XDP kfuncs
only for UDP packets destined to port 8080.

Signed-off-by: Stanislav Fomichev <sdf@google.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20231204174423.3460052-1-sdf@google.com
tools/testing/selftests/bpf/progs/xdp_metadata.c

index d151d406a123efc004c1fb09f28844adccade711..5d6c1245c3106ecf91cffb604c60046222eb851d 100644 (file)
@@ -27,11 +27,40 @@ extern int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, __u32 *hash,
 SEC("xdp")
 int rx(struct xdp_md *ctx)
 {
-       void *data, *data_meta;
+       void *data, *data_meta, *data_end;
+       struct ipv6hdr *ip6h = NULL;
+       struct ethhdr *eth = NULL;
+       struct udphdr *udp = NULL;
+       struct iphdr *iph = NULL;
        struct xdp_meta *meta;
        u64 timestamp = -1;
        int ret;
 
+       data = (void *)(long)ctx->data;
+       data_end = (void *)(long)ctx->data_end;
+       eth = data;
+       if (eth + 1 < data_end) {
+               if (eth->h_proto == bpf_htons(ETH_P_IP)) {
+                       iph = (void *)(eth + 1);
+                       if (iph + 1 < data_end && iph->protocol == IPPROTO_UDP)
+                               udp = (void *)(iph + 1);
+               }
+               if (eth->h_proto == bpf_htons(ETH_P_IPV6)) {
+                       ip6h = (void *)(eth + 1);
+                       if (ip6h + 1 < data_end && ip6h->nexthdr == IPPROTO_UDP)
+                               udp = (void *)(ip6h + 1);
+               }
+               if (udp && udp + 1 > data_end)
+                       udp = NULL;
+       }
+
+       if (!udp)
+               return XDP_PASS;
+
+       /* Forwarding UDP:8080 to AF_XDP */
+       if (udp->dest != bpf_htons(8080))
+               return XDP_PASS;
+
        /* Reserve enough for all custom metadata. */
 
        ret = bpf_xdp_adjust_meta(ctx, -(int)sizeof(struct xdp_meta));