selftests/bpf: Fix BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL for empty flow label
authorStanislav Fomichev <sdf@google.com>
Tue, 21 Feb 2023 18:05:18 +0000 (10:05 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 22 Feb 2023 21:13:13 +0000 (13:13 -0800)
Kernel's flow dissector continues to parse the packet when
the (optional) IPv6 flow label is empty even when instructed
to stop (via BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL). Do
the same in our reference BPF reimplementation.

Signed-off-by: Stanislav Fomichev <sdf@google.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Link: https://lore.kernel.org/r/20230221180518.2139026-1-sdf@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
tools/testing/selftests/bpf/prog_tests/flow_dissector.c
tools/testing/selftests/bpf/progs/bpf_flow.c

index 7acca37..c477317 100644 (file)
@@ -346,6 +346,30 @@ struct test tests[] = {
                .retval = BPF_OK,
        },
        {
+               .name = "ipv6-empty-flow-label",
+               .pkt.ipv6 = {
+                       .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
+                       .iph.nexthdr = IPPROTO_TCP,
+                       .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
+                       .iph.flow_lbl = { 0x00, 0x00, 0x00 },
+                       .tcp.doff = 5,
+                       .tcp.source = 80,
+                       .tcp.dest = 8080,
+               },
+               .keys = {
+                       .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL,
+                       .nhoff = ETH_HLEN,
+                       .thoff = ETH_HLEN + sizeof(struct ipv6hdr),
+                       .addr_proto = ETH_P_IPV6,
+                       .ip_proto = IPPROTO_TCP,
+                       .n_proto = __bpf_constant_htons(ETH_P_IPV6),
+                       .sport = 80,
+                       .dport = 8080,
+               },
+               .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL,
+               .retval = BPF_OK,
+       },
+       {
                .name = "ipip-encap",
                .pkt.ipip = {
                        .eth.h_proto = __bpf_constant_htons(ETH_P_IP),
index a20c5ed..b04e092 100644 (file)
@@ -337,7 +337,7 @@ PROG(IPV6)(struct __sk_buff *skb)
        keys->ip_proto = ip6h->nexthdr;
        keys->flow_label = ip6_flowlabel(ip6h);
 
-       if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL)
+       if (keys->flow_label && keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL)
                return export_flow_keys(keys, BPF_OK);
 
        return parse_ipv6_proto(skb, ip6h->nexthdr);