bpf: support flow label for bpf_skb_{set, get}_tunnel_key
This patch extends bpf_tunnel_key with a tunnel_label member, that maps to ip_tunnel_key's label so underlying backends like vxlan and geneve can propagate the label to udp_tunnel6_xmit_skb(), where it's being set in the IPv6 header. It allows for having 20 more bits to encode/decode flow related meta information programmatically. Tested with vxlan and geneve. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8eb3b99554
commit
4018ab1875
@ -375,6 +375,7 @@ struct bpf_tunnel_key {
|
|||||||
};
|
};
|
||||||
__u8 tunnel_tos;
|
__u8 tunnel_tos;
|
||||||
__u8 tunnel_ttl;
|
__u8 tunnel_ttl;
|
||||||
|
__u32 tunnel_label;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _UAPI__LINUX_BPF_H__ */
|
#endif /* _UAPI__LINUX_BPF_H__ */
|
||||||
|
@ -1770,12 +1770,15 @@ static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
|
|||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
if (unlikely(size != sizeof(struct bpf_tunnel_key))) {
|
if (unlikely(size != sizeof(struct bpf_tunnel_key))) {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
case offsetof(struct bpf_tunnel_key, tunnel_label):
|
||||||
|
goto set_compat;
|
||||||
case offsetof(struct bpf_tunnel_key, remote_ipv6[1]):
|
case offsetof(struct bpf_tunnel_key, remote_ipv6[1]):
|
||||||
/* Fixup deprecated structure layouts here, so we have
|
/* Fixup deprecated structure layouts here, so we have
|
||||||
* a common path later on.
|
* a common path later on.
|
||||||
*/
|
*/
|
||||||
if (ip_tunnel_info_af(info) != AF_INET)
|
if (ip_tunnel_info_af(info) != AF_INET)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
set_compat:
|
||||||
to = (struct bpf_tunnel_key *)compat;
|
to = (struct bpf_tunnel_key *)compat;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1787,11 +1790,13 @@ static u64 bpf_skb_get_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
|
|||||||
to->tunnel_tos = info->key.tos;
|
to->tunnel_tos = info->key.tos;
|
||||||
to->tunnel_ttl = info->key.ttl;
|
to->tunnel_ttl = info->key.ttl;
|
||||||
|
|
||||||
if (flags & BPF_F_TUNINFO_IPV6)
|
if (flags & BPF_F_TUNINFO_IPV6) {
|
||||||
memcpy(to->remote_ipv6, &info->key.u.ipv6.src,
|
memcpy(to->remote_ipv6, &info->key.u.ipv6.src,
|
||||||
sizeof(to->remote_ipv6));
|
sizeof(to->remote_ipv6));
|
||||||
else
|
to->tunnel_label = be32_to_cpu(info->key.label);
|
||||||
|
} else {
|
||||||
to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src);
|
to->remote_ipv4 = be32_to_cpu(info->key.u.ipv4.src);
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely(size != sizeof(struct bpf_tunnel_key)))
|
if (unlikely(size != sizeof(struct bpf_tunnel_key)))
|
||||||
memcpy((void *)(long) r2, to, size);
|
memcpy((void *)(long) r2, to, size);
|
||||||
@ -1850,6 +1855,7 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (unlikely(size != sizeof(struct bpf_tunnel_key))) {
|
if (unlikely(size != sizeof(struct bpf_tunnel_key))) {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
|
case offsetof(struct bpf_tunnel_key, tunnel_label):
|
||||||
case offsetof(struct bpf_tunnel_key, remote_ipv6[1]):
|
case offsetof(struct bpf_tunnel_key, remote_ipv6[1]):
|
||||||
/* Fixup deprecated structure layouts here, so we have
|
/* Fixup deprecated structure layouts here, so we have
|
||||||
* a common path later on.
|
* a common path later on.
|
||||||
@ -1862,6 +1868,8 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (unlikely(!(flags & BPF_F_TUNINFO_IPV6) && from->tunnel_label))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
skb_dst_drop(skb);
|
skb_dst_drop(skb);
|
||||||
dst_hold((struct dst_entry *) md);
|
dst_hold((struct dst_entry *) md);
|
||||||
@ -1882,6 +1890,8 @@ static u64 bpf_skb_set_tunnel_key(u64 r1, u64 r2, u64 size, u64 flags, u64 r5)
|
|||||||
info->mode |= IP_TUNNEL_INFO_IPV6;
|
info->mode |= IP_TUNNEL_INFO_IPV6;
|
||||||
memcpy(&info->key.u.ipv6.dst, from->remote_ipv6,
|
memcpy(&info->key.u.ipv6.dst, from->remote_ipv6,
|
||||||
sizeof(from->remote_ipv6));
|
sizeof(from->remote_ipv6));
|
||||||
|
info->key.label = cpu_to_be32(from->tunnel_label) &
|
||||||
|
IPV6_FLOWLABEL_MASK;
|
||||||
} else {
|
} else {
|
||||||
info->key.u.ipv4.dst = cpu_to_be32(from->remote_ipv4);
|
info->key.u.ipv4.dst = cpu_to_be32(from->remote_ipv4);
|
||||||
if (flags & BPF_F_ZERO_CSUM_TX)
|
if (flags & BPF_F_ZERO_CSUM_TX)
|
||||||
|
Loading…
Reference in New Issue
Block a user