Yeah, I've sent the fix upstream yesterday, will backport. Feel free to ignore the following patches: https://screenshot.googleplex.com/DOQKAzGDksV They are all blocked on this nhoff defined twice :-( I'll backport them On Tue, Aug 27, 2019 at 11:04 AM Eric Dumazet <eric.dumazet@xxxxxxxxx> wrote: > > > > On 7/26/19 12:52 AM, Stanislav Fomichev wrote: > > Exit as soon as we found that packet is encapped when > > BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP is passed. > > Add appropriate selftest cases. > > > > v2: > > * Subtract sizeof(struct iphdr) from .iph_inner.tot_len (Willem de Bruijn) > > > > Acked-by: Petar Penkov <ppenkov@xxxxxxxxxx> > > Acked-by: Willem de Bruijn <willemb@xxxxxxxxxx> > > Acked-by: Song Liu <songliubraving@xxxxxx> > > Cc: Song Liu <songliubraving@xxxxxx> > > Cc: Willem de Bruijn <willemb@xxxxxxxxxx> > > Cc: Petar Penkov <ppenkov@xxxxxxxxxx> > > Signed-off-by: Stanislav Fomichev <sdf@xxxxxxxxxx> > > --- > > .../selftests/bpf/prog_tests/flow_dissector.c | 64 +++++++++++++++++++ > > tools/testing/selftests/bpf/progs/bpf_flow.c | 8 +++ > > 2 files changed, 72 insertions(+) > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c > > index ef83f145a6f1..700d73d2f22a 100644 > > --- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c > > +++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c > > @@ -41,6 +41,13 @@ struct ipv4_pkt { > > struct tcphdr tcp; > > } __packed; > > > > +struct ipip_pkt { > > + struct ethhdr eth; > > + struct iphdr iph; > > + struct iphdr iph_inner; > > + struct tcphdr tcp; > > +} __packed; > > + > > struct svlan_ipv4_pkt { > > struct ethhdr eth; > > __u16 vlan_tci; > > @@ -82,6 +89,7 @@ struct test { > > union { > > struct ipv4_pkt ipv4; > > struct svlan_ipv4_pkt svlan_ipv4; > > + struct ipip_pkt ipip; > > struct ipv6_pkt ipv6; > > struct ipv6_frag_pkt ipv6_frag; > > struct dvlan_ipv6_pkt dvlan_ipv6; > > @@ -303,6 +311,62 @@ struct test tests[] = { > > }, > > .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL, > > }, > > + { > > + .name = "ipip-encap", > > + .pkt.ipip = { > > + .eth.h_proto = __bpf_constant_htons(ETH_P_IP), > > + .iph.ihl = 5, > > + .iph.protocol = IPPROTO_IPIP, > > + .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), > > + .iph_inner.ihl = 5, > > + .iph_inner.protocol = IPPROTO_TCP, > > + .iph_inner.tot_len = > > + __bpf_constant_htons(MAGIC_BYTES) - > > + sizeof(struct iphdr), > > + .tcp.doff = 5, > > + .tcp.source = 80, > > + .tcp.dest = 8080, > > + }, > > + .keys = { > > + .nhoff = 0, > > + .nhoff = ETH_HLEN, > > clang emits a warning because nhoff is defined twice. > > > + .thoff = ETH_HLEN + sizeof(struct iphdr) + > > + sizeof(struct iphdr), > > + .addr_proto = ETH_P_IP, > > + .ip_proto = IPPROTO_TCP, > > + .n_proto = __bpf_constant_htons(ETH_P_IP), > > + .is_encap = true, > > + .sport = 80, > > + .dport = 8080, > > + }, > > + }, > > + { > > + .name = "ipip-no-encap", > > + .pkt.ipip = { > > + .eth.h_proto = __bpf_constant_htons(ETH_P_IP), > > + .iph.ihl = 5, > > + .iph.protocol = IPPROTO_IPIP, > > + .iph.tot_len = __bpf_constant_htons(MAGIC_BYTES), > > + .iph_inner.ihl = 5, > > + .iph_inner.protocol = IPPROTO_TCP, > > + .iph_inner.tot_len = > > + __bpf_constant_htons(MAGIC_BYTES) - > > + sizeof(struct iphdr), > > + .tcp.doff = 5, > > + .tcp.source = 80, > > + .tcp.dest = 8080, > > + }, > > + .keys = { > > + .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP, > > + .nhoff = ETH_HLEN, > > + .thoff = ETH_HLEN + sizeof(struct iphdr), > > + .addr_proto = ETH_P_IP, > > + .ip_proto = IPPROTO_IPIP, > > + .n_proto = __bpf_constant_htons(ETH_P_IP), > > + .is_encap = true, > > + }, > > + .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP, > > + }, > > }; > > > > static int create_tap(const char *ifname) > > diff --git a/tools/testing/selftests/bpf/progs/bpf_flow.c b/tools/testing/selftests/bpf/progs/bpf_flow.c > > index 7fbfa22f33df..08bd8b9d58d0 100644 > > --- a/tools/testing/selftests/bpf/progs/bpf_flow.c > > +++ b/tools/testing/selftests/bpf/progs/bpf_flow.c > > @@ -167,9 +167,15 @@ static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto) > > return export_flow_keys(keys, BPF_OK); > > case IPPROTO_IPIP: > > keys->is_encap = true; > > + if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP) > > + return export_flow_keys(keys, BPF_OK); > > + > > return parse_eth_proto(skb, bpf_htons(ETH_P_IP)); > > case IPPROTO_IPV6: > > keys->is_encap = true; > > + if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP) > > + return export_flow_keys(keys, BPF_OK); > > + > > return parse_eth_proto(skb, bpf_htons(ETH_P_IPV6)); > > case IPPROTO_GRE: > > gre = bpf_flow_dissect_get_header(skb, sizeof(*gre), &_gre); > > @@ -189,6 +195,8 @@ static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto) > > keys->thoff += 4; /* Step over sequence number */ > > > > keys->is_encap = true; > > + if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP) > > + return export_flow_keys(keys, BPF_OK); > > > > if (gre->proto == bpf_htons(ETH_P_TEB)) { > > eth = bpf_flow_dissect_get_header(skb, sizeof(*eth), > >