History

bpf, net: Support SO_REUSEPORT sockets with bpf_sk_assign

Currently the bpf_sk_assign helper in tc BPF context refuses SO_REUSEPORT sockets. This means we can't use the helper to steer traffic to Envoy, which configures SO_REUSEPORT on its sockets. In turn, we're blocked from removing TPROXY from our setup. The reason that bpf_sk_assign refuses such sockets is that the bpf_sk_lookup helpers don't execute SK_REUSEPORT programs. Instead, one of the reuseport sockets is selected by hash. This could cause dispatch to the "wrong" socket: sk = bpf_sk_lookup_tcp(...) // select SO_REUSEPORT by hash bpf_sk_assign(skb, sk) // SK_REUSEPORT wasn't executed Fixing this isn't as simple as invoking SK_REUSEPORT from the lookup helpers unfortunately. In the tc context, L2 headers are at the start of the skb, while SK_REUSEPORT expects L3 headers instead. Instead, we execute the SK_REUSEPORT program when the assigned socket is pulled out of the skb, further up the stack. This creates some trickiness with regards to refcounting as bpf_sk_assign will put both refcounted and RCU freed sockets in skb->sk. reuseport sockets are RCU freed. We can infer that the sk_assigned socket is RCU freed if the reuseport lookup succeeds, but convincing yourself of this fact isn't straight forward. Therefore we defensively check refcounting on the sk_assign sock even though it's probably not required in practice.

Lorenz Bauer committed 3 years ago

Commit 9c02bec1 parent 6c886db8 files · +115 −21Browse files

Showing the changes to tools/include/uapi/linux (1 of 8 files). Show all

Unified · Split

tools/include/uapi/linux/bpf.h+0−3
@@ -4198,9 +4198,6 @@ union bpf_attr { · 4197 unmodified lines
41984198 * **-EOPNOTSUPP** if the operation is not supported, for example
41994199 * a call from outside of TC ingress.
42004200 *
4201− * **-ESOCKTNOSUPPORT** if the socket type is not supported
4202− * (reuseport).
4203− *
42044201 * long bpf_sk_assign(struct bpf_sk_lookup *ctx, struct bpf_sock *sk, u64 flags)
42054202 * Description
42064203 * Helper is overloaded depending on BPF program type. This