summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislav Fomichev <sdf@google.com>2019-07-25 18:52:30 -0400
committerAlexei Starovoitov <ast@kernel.org>2019-07-25 21:00:41 -0400
commit71c99e32b926159ea628352751f66383d7d04d17 (patch)
tree6a2b488c1d184b9ce514deb7187ab9b0130a270c
parentae173a915785e55574c1fc54edf58b9b87b28c22 (diff)
bpf/flow_dissector: support ipv6 flow_label and BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL
Add support for exporting ipv6 flow label via bpf_flow_keys. Export flow label from bpf_flow.c and also return early when BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL is passed. Acked-by: Petar Penkov <ppenkov@google.com> Acked-by: Willem de Bruijn <willemb@google.com> Acked-by: Song 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: Stanislav Fomichev <sdf@google.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
-rw-r--r--include/uapi/linux/bpf.h1
-rw-r--r--net/core/flow_dissector.c9
-rw-r--r--tools/include/uapi/linux/bpf.h1
-rw-r--r--tools/testing/selftests/bpf/prog_tests/flow_dissector.c46
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_flow.c10
5 files changed, 67 insertions, 0 deletions
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 88b9d743036f..e985f07a98ed 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -3533,6 +3533,7 @@ struct bpf_flow_keys {
3533 }; 3533 };
3534 }; 3534 };
3535 __u32 flags; 3535 __u32 flags;
3536 __be32 flow_label;
3536}; 3537};
3537 3538
3538struct bpf_func_info { 3539struct bpf_func_info {
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 50ed1a688709..9741b593ea53 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -737,6 +737,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
737 struct flow_dissector_key_basic *key_basic; 737 struct flow_dissector_key_basic *key_basic;
738 struct flow_dissector_key_addrs *key_addrs; 738 struct flow_dissector_key_addrs *key_addrs;
739 struct flow_dissector_key_ports *key_ports; 739 struct flow_dissector_key_ports *key_ports;
740 struct flow_dissector_key_tags *key_tags;
740 741
741 key_control = skb_flow_dissector_target(flow_dissector, 742 key_control = skb_flow_dissector_target(flow_dissector,
742 FLOW_DISSECTOR_KEY_CONTROL, 743 FLOW_DISSECTOR_KEY_CONTROL,
@@ -781,6 +782,14 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
781 key_ports->src = flow_keys->sport; 782 key_ports->src = flow_keys->sport;
782 key_ports->dst = flow_keys->dport; 783 key_ports->dst = flow_keys->dport;
783 } 784 }
785
786 if (dissector_uses_key(flow_dissector,
787 FLOW_DISSECTOR_KEY_FLOW_LABEL)) {
788 key_tags = skb_flow_dissector_target(flow_dissector,
789 FLOW_DISSECTOR_KEY_FLOW_LABEL,
790 target_container);
791 key_tags->flow_label = ntohl(flow_keys->flow_label);
792 }
784} 793}
785 794
786bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx, 795bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 2e4b0848d795..3d7fc67ec1b8 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -3530,6 +3530,7 @@ struct bpf_flow_keys {
3530 }; 3530 };
3531 }; 3531 };
3532 __u32 flags; 3532 __u32 flags;
3533 __be32 flow_label;
3533}; 3534};
3534 3535
3535struct bpf_func_info { 3536struct bpf_func_info {
diff --git a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
index 8e8c18aced9b..ef83f145a6f1 100644
--- a/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
+++ b/tools/testing/selftests/bpf/prog_tests/flow_dissector.c
@@ -20,6 +20,7 @@
20 "is_encap=%u/%u " \ 20 "is_encap=%u/%u " \
21 "ip_proto=0x%x/0x%x " \ 21 "ip_proto=0x%x/0x%x " \
22 "n_proto=0x%x/0x%x " \ 22 "n_proto=0x%x/0x%x " \
23 "flow_label=0x%x/0x%x " \
23 "sport=%u/%u " \ 24 "sport=%u/%u " \
24 "dport=%u/%u\n", \ 25 "dport=%u/%u\n", \
25 got.nhoff, expected.nhoff, \ 26 got.nhoff, expected.nhoff, \
@@ -30,6 +31,7 @@
30 got.is_encap, expected.is_encap, \ 31 got.is_encap, expected.is_encap, \
31 got.ip_proto, expected.ip_proto, \ 32 got.ip_proto, expected.ip_proto, \
32 got.n_proto, expected.n_proto, \ 33 got.n_proto, expected.n_proto, \
34 got.flow_label, expected.flow_label, \
33 got.sport, expected.sport, \ 35 got.sport, expected.sport, \
34 got.dport, expected.dport) 36 got.dport, expected.dport)
35 37
@@ -257,6 +259,50 @@ struct test tests[] = {
257 .is_first_frag = true, 259 .is_first_frag = true,
258 }, 260 },
259 }, 261 },
262 {
263 .name = "ipv6-flow-label",
264 .pkt.ipv6 = {
265 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
266 .iph.nexthdr = IPPROTO_TCP,
267 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
268 .iph.flow_lbl = { 0xb, 0xee, 0xef },
269 .tcp.doff = 5,
270 .tcp.source = 80,
271 .tcp.dest = 8080,
272 },
273 .keys = {
274 .nhoff = ETH_HLEN,
275 .thoff = ETH_HLEN + sizeof(struct ipv6hdr),
276 .addr_proto = ETH_P_IPV6,
277 .ip_proto = IPPROTO_TCP,
278 .n_proto = __bpf_constant_htons(ETH_P_IPV6),
279 .sport = 80,
280 .dport = 8080,
281 .flow_label = __bpf_constant_htonl(0xbeeef),
282 },
283 },
284 {
285 .name = "ipv6-no-flow-label",
286 .pkt.ipv6 = {
287 .eth.h_proto = __bpf_constant_htons(ETH_P_IPV6),
288 .iph.nexthdr = IPPROTO_TCP,
289 .iph.payload_len = __bpf_constant_htons(MAGIC_BYTES),
290 .iph.flow_lbl = { 0xb, 0xee, 0xef },
291 .tcp.doff = 5,
292 .tcp.source = 80,
293 .tcp.dest = 8080,
294 },
295 .keys = {
296 .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL,
297 .nhoff = ETH_HLEN,
298 .thoff = ETH_HLEN + sizeof(struct ipv6hdr),
299 .addr_proto = ETH_P_IPV6,
300 .ip_proto = IPPROTO_TCP,
301 .n_proto = __bpf_constant_htons(ETH_P_IPV6),
302 .flow_label = __bpf_constant_htonl(0xbeeef),
303 },
304 .flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL,
305 },
260}; 306};
261 307
262static int create_tap(const char *ifname) 308static 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 f931cd3db9d4..7fbfa22f33df 100644
--- a/tools/testing/selftests/bpf/progs/bpf_flow.c
+++ b/tools/testing/selftests/bpf/progs/bpf_flow.c
@@ -83,6 +83,12 @@ static __always_inline int export_flow_keys(struct bpf_flow_keys *keys,
83 return ret; 83 return ret;
84} 84}
85 85
86#define IPV6_FLOWLABEL_MASK __bpf_constant_htonl(0x000FFFFF)
87static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
88{
89 return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
90}
91
86static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb, 92static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb,
87 __u16 hdr_size, 93 __u16 hdr_size,
88 void *buffer) 94 void *buffer)
@@ -308,6 +314,10 @@ PROG(IPV6)(struct __sk_buff *skb)
308 314
309 keys->thoff += sizeof(struct ipv6hdr); 315 keys->thoff += sizeof(struct ipv6hdr);
310 keys->ip_proto = ip6h->nexthdr; 316 keys->ip_proto = ip6h->nexthdr;
317 keys->flow_label = ip6_flowlabel(ip6h);
318
319 if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL)
320 return export_flow_keys(keys, BPF_OK);
311 321
312 return parse_ipv6_proto(skb, ip6h->nexthdr); 322 return parse_ipv6_proto(skb, ip6h->nexthdr);
313} 323}