mirror of
https://github.com/torvalds/linux.git
synced 2024-11-27 14:41:39 +00:00
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>
This commit is contained in:
parent
ae173a9157
commit
71c99e32b9
@ -3533,6 +3533,7 @@ struct bpf_flow_keys {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
__u32 flags;
|
__u32 flags;
|
||||||
|
__be32 flow_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bpf_func_info {
|
struct bpf_func_info {
|
||||||
|
@ -737,6 +737,7 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
|
|||||||
struct flow_dissector_key_basic *key_basic;
|
struct flow_dissector_key_basic *key_basic;
|
||||||
struct flow_dissector_key_addrs *key_addrs;
|
struct flow_dissector_key_addrs *key_addrs;
|
||||||
struct flow_dissector_key_ports *key_ports;
|
struct flow_dissector_key_ports *key_ports;
|
||||||
|
struct flow_dissector_key_tags *key_tags;
|
||||||
|
|
||||||
key_control = skb_flow_dissector_target(flow_dissector,
|
key_control = skb_flow_dissector_target(flow_dissector,
|
||||||
FLOW_DISSECTOR_KEY_CONTROL,
|
FLOW_DISSECTOR_KEY_CONTROL,
|
||||||
@ -781,6 +782,14 @@ static void __skb_flow_bpf_to_target(const struct bpf_flow_keys *flow_keys,
|
|||||||
key_ports->src = flow_keys->sport;
|
key_ports->src = flow_keys->sport;
|
||||||
key_ports->dst = flow_keys->dport;
|
key_ports->dst = flow_keys->dport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dissector_uses_key(flow_dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_FLOW_LABEL)) {
|
||||||
|
key_tags = skb_flow_dissector_target(flow_dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_FLOW_LABEL,
|
||||||
|
target_container);
|
||||||
|
key_tags->flow_label = ntohl(flow_keys->flow_label);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,
|
bool bpf_flow_dissect(struct bpf_prog *prog, struct bpf_flow_dissector *ctx,
|
||||||
|
@ -3530,6 +3530,7 @@ struct bpf_flow_keys {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
__u32 flags;
|
__u32 flags;
|
||||||
|
__be32 flow_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bpf_func_info {
|
struct bpf_func_info {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"is_encap=%u/%u " \
|
"is_encap=%u/%u " \
|
||||||
"ip_proto=0x%x/0x%x " \
|
"ip_proto=0x%x/0x%x " \
|
||||||
"n_proto=0x%x/0x%x " \
|
"n_proto=0x%x/0x%x " \
|
||||||
|
"flow_label=0x%x/0x%x " \
|
||||||
"sport=%u/%u " \
|
"sport=%u/%u " \
|
||||||
"dport=%u/%u\n", \
|
"dport=%u/%u\n", \
|
||||||
got.nhoff, expected.nhoff, \
|
got.nhoff, expected.nhoff, \
|
||||||
@ -30,6 +31,7 @@
|
|||||||
got.is_encap, expected.is_encap, \
|
got.is_encap, expected.is_encap, \
|
||||||
got.ip_proto, expected.ip_proto, \
|
got.ip_proto, expected.ip_proto, \
|
||||||
got.n_proto, expected.n_proto, \
|
got.n_proto, expected.n_proto, \
|
||||||
|
got.flow_label, expected.flow_label, \
|
||||||
got.sport, expected.sport, \
|
got.sport, expected.sport, \
|
||||||
got.dport, expected.dport)
|
got.dport, expected.dport)
|
||||||
|
|
||||||
@ -257,6 +259,50 @@ struct test tests[] = {
|
|||||||
.is_first_frag = true,
|
.is_first_frag = true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.name = "ipv6-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 = { 0xb, 0xee, 0xef },
|
||||||
|
.tcp.doff = 5,
|
||||||
|
.tcp.source = 80,
|
||||||
|
.tcp.dest = 8080,
|
||||||
|
},
|
||||||
|
.keys = {
|
||||||
|
.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,
|
||||||
|
.flow_label = __bpf_constant_htonl(0xbeeef),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.name = "ipv6-no-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 = { 0xb, 0xee, 0xef },
|
||||||
|
.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),
|
||||||
|
.flow_label = __bpf_constant_htonl(0xbeeef),
|
||||||
|
},
|
||||||
|
.flags = BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static int create_tap(const char *ifname)
|
static int create_tap(const char *ifname)
|
||||||
|
@ -83,6 +83,12 @@ static __always_inline int export_flow_keys(struct bpf_flow_keys *keys,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define IPV6_FLOWLABEL_MASK __bpf_constant_htonl(0x000FFFFF)
|
||||||
|
static inline __be32 ip6_flowlabel(const struct ipv6hdr *hdr)
|
||||||
|
{
|
||||||
|
return *(__be32 *)hdr & IPV6_FLOWLABEL_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb,
|
static __always_inline void *bpf_flow_dissect_get_header(struct __sk_buff *skb,
|
||||||
__u16 hdr_size,
|
__u16 hdr_size,
|
||||||
void *buffer)
|
void *buffer)
|
||||||
@ -308,6 +314,10 @@ PROG(IPV6)(struct __sk_buff *skb)
|
|||||||
|
|
||||||
keys->thoff += sizeof(struct ipv6hdr);
|
keys->thoff += sizeof(struct ipv6hdr);
|
||||||
keys->ip_proto = ip6h->nexthdr;
|
keys->ip_proto = ip6h->nexthdr;
|
||||||
|
keys->flow_label = ip6_flowlabel(ip6h);
|
||||||
|
|
||||||
|
if (keys->flags & BPF_FLOW_DISSECTOR_F_STOP_AT_FLOW_LABEL)
|
||||||
|
return export_flow_keys(keys, BPF_OK);
|
||||||
|
|
||||||
return parse_ipv6_proto(skb, ip6h->nexthdr);
|
return parse_ipv6_proto(skb, ip6h->nexthdr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user