Skip to content

Commit 71c99e3

Browse files
fomichevAlexei Starovoitov
authored andcommitted
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 <[email protected]> Acked-by: Willem de Bruijn <[email protected]> Acked-by: Song Liu <[email protected]> Cc: Song Liu <[email protected]> Cc: Willem de Bruijn <[email protected]> Cc: Petar Penkov <[email protected]> Signed-off-by: Stanislav Fomichev <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent ae173a9 commit 71c99e3

File tree

5 files changed

+67
-0
lines changed

5 files changed

+67
-0
lines changed

include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3533,6 +3533,7 @@ struct bpf_flow_keys {
35333533
};
35343534
};
35353535
__u32 flags;
3536+
__be32 flow_label;
35363537
};
35373538

35383539
struct bpf_func_info {

net/core/flow_dissector.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
737737
struct flow_dissector_key_basic *key_basic;
738738
struct flow_dissector_key_addrs *key_addrs;
739739
struct flow_dissector_key_ports *key_ports;
740+
struct flow_dissector_key_tags *key_tags;
740741

741742
key_control = skb_flow_dissector_target(flow_dissector,
742743
FLOW_DISSECTOR_KEY_CONTROL,
@@ -781,6 +782,14 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
781782
key_ports->src = flow_keys->sport;
782783
key_ports->dst = flow_keys->dport;
783784
}
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+
}
784793
}
785794

786795
bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,

tools/include/uapi/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3530,6 +3530,7 @@ struct bpf_flow_keys {
35303530
};
35313531
};
35323532
__u32 flags;
3533+
__be32 flow_label;
35333534
};
35343535

35353536
struct bpf_func_info {

tools/testing/selftests/bpf/prog_tests/flow_dissector.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"is_encap=%u/%u " \
2121
"ip_proto=0x%x/0x%x " \
2222
"n_proto=0x%x/0x%x " \
23+
"flow_label=0x%x/0x%x " \
2324
"sport=%u/%u " \
2425
"dport=%u/%u\n", \
2526
got.nhoff, expected.nhoff, \
@@ -30,6 +31,7 @@
3031
got.is_encap, expected.is_encap, \
3132
got.ip_proto, expected.ip_proto, \
3233
got.n_proto, expected.n_proto, \
34+
got.flow_label, expected.flow_label, \
3335
got.sport, expected.sport, \
3436
got.dport, expected.dport)
3537

@@ -257,6 +259,50 @@ struct test tests[] = {
257259
.is_first_frag = true,
258260
},
259261
},
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+
},
260306
};
261307

262308
static int create_tap(const char *ifname)

tools/testing/selftests/bpf/progs/bpf_flow.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ static __always_inline int export_flow_keys(struct bpf_flow_keys *keys,
8383
return ret;
8484
}
8585

86+
#define IPV6_FLOWLABEL_MASK __bpf_constant_htonl(0x000FFFFF)
87+
static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
88+
{
89+
return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
90+
}
91+
8692
static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb,
8793
__u16 hdr_size,
8894
void *buffer)
@@ -308,6 +314,10 @@ PROG(IPV6)(struct __sk_buff *skb)
308314

309315
keys->thoff += sizeof(struct ipv6hdr);
310316
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);
311321

312322
return parse_ipv6_proto(skb, ip6h->nexthdr);
313323
}

0 commit comments

Comments
 (0)