Commit e853ae77 authored by Stanislav Fomichev's avatar Stanislav Fomichev Committed by Alexei Starovoitov

selftests/bpf: support BPF_FLOW_DISSECTOR_F_STOP_AT_ENCAP

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: default avatarPetar Penkov <ppenkov@google.com>
Acked-by: default avatarWillem de Bruijn <willemb@google.com>
Acked-by: default avatarSong Liu <songliubraving@fb.com>
Cc: Song Liu <songliubraving@fb.com>
Cc: Willem de Bruijn <willemb@google.com>
Cc: Petar Penkov <ppenkov@google.com>
Signed-off-by: default avatarStanislav Fomichev <sdf@google.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent 71c99e32
...@@ -41,6 +41,13 @@ struct ipv4_pkt { ...@@ -41,6 +41,13 @@ struct ipv4_pkt {
struct tcphdr tcp; struct tcphdr tcp;
} __packed; } __packed;
struct ipip_pkt {
struct ethhdr eth;
struct iphdr iph;
struct iphdr iph_inner;
struct tcphdr tcp;
} __packed;
struct svlan_ipv4_pkt { struct svlan_ipv4_pkt {
struct ethhdr eth; struct ethhdr eth;
__u16 vlan_tci; __u16 vlan_tci;
...@@ -82,6 +89,7 @@ struct test { ...@@ -82,6 +89,7 @@ struct test {
union { union {
struct ipv4_pkt ipv4; struct ipv4_pkt ipv4;
struct svlan_ipv4_pkt svlan_ipv4; struct svlan_ipv4_pkt svlan_ipv4;
struct ipip_pkt ipip;
struct ipv6_pkt ipv6; struct ipv6_pkt ipv6;
struct ipv6_frag_pkt ipv6_frag; struct ipv6_frag_pkt ipv6_frag;
struct dvlan_ipv6_pkt dvlan_ipv6; struct dvlan_ipv6_pkt dvlan_ipv6;
...@@ -303,6 +311,62 @@ struct test tests[] = { ...@@ -303,6 +311,62 @@ struct test tests[] = {
}, },
.flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL, .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,
.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) static int create_tap(const char *ifname)
......
...@@ -167,9 +167,15 @@ static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto) ...@@ -167,9 +167,15 @@ static __always_inline int parse_ip_proto(struct __sk_buff *skb, __u8 proto)
return export_flow_keys(keys, BPF_OK); return export_flow_keys(keys, BPF_OK);
case IPPROTO_IPIP: case IPPROTO_IPIP:
keys->is_encap = true; 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)); return parse_eth_proto(skb, bpf_htons(ETH_P_IP));
case IPPROTO_IPV6: case IPPROTO_IPV6:
keys->is_encap = true; 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)); return parse_eth_proto(skb, bpf_htons(ETH_P_IPV6));
case IPPROTO_GRE: case IPPROTO_GRE:
gre = bpf_flow_dissect_get_header(skb, sizeof(*gre), &_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) ...@@ -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->thoff += 4; /* Step over sequence number */
keys->is_encap = true; 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)) { if (gre->proto == bpf_htons(ETH_P_TEB)) {
eth = bpf_flow_dissect_get_header(skb, sizeof(*eth), eth = bpf_flow_dissect_get_header(skb, sizeof(*eth),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment