[RFCv2 bpf-next 09/12] udp6: Run inet_lookup bpf program on socket lookup
From: Jakub Sitnicki <jakub@cloudflare.com>
Date: 2019-08-28 07:23:21
Also in:
bpf
Subsystem:
networking [general], the rest, user datagram protocol (udp) · Maintainers:
"David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds, Willem de Bruijn
Same as for udp, split the socket lookup into two phases and let the BPF inet_lookup program select the receiving socket. Suggested-by: Marek Majkowski <redacted> Reviewed-by: Lorenz Bauer <redacted> Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com> --- net/ipv6/udp.c | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 16ef2303bd8d..7380cf57e88c 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c@@ -101,7 +101,7 @@ void udp_v6_rehash(struct sock *sk) static int compute_score(struct sock *sk, struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, unsigned short hnum, - int dif, int sdif) + int dif, int sdif, unsigned char state) { int score; struct inet_sock *inet;
@@ -112,6 +112,9 @@ static int compute_score(struct sock *sk, struct net *net, sk->sk_family != PF_INET6) return -1; + if (state && sk->sk_state != state) + return -1; + if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr)) return -1;
@@ -146,7 +149,7 @@ static struct sock *udp6_lib_lookup2(struct net *net, const struct in6_addr *saddr, __be16 sport, const struct in6_addr *daddr, unsigned int hnum, int dif, int sdif, struct udp_hslot *hslot2, - struct sk_buff *skb) + struct sk_buff *skb, unsigned char state) { struct sock *sk, *result; int score, badness;
@@ -156,7 +159,7 @@ static struct sock *udp6_lib_lookup2(struct net *net, badness = -1; udp_portaddr_for_each_entry_rcu(sk, &hslot2->head) { score = compute_score(sk, net, saddr, sport, - daddr, hnum, dif, sdif); + daddr, hnum, dif, sdif, state); if (score > badness) { if (sk->sk_reuseport) { hash = udp6_ehashfn(net, daddr, hnum,
@@ -190,19 +193,34 @@ struct sock *__udp6_lib_lookup(struct net *net, slot2 = hash2 & udptable->mask; hslot2 = &udptable->hash2[slot2]; + /* Lookup connected sockets */ result = udp6_lib_lookup2(net, saddr, sport, daddr, hnum, dif, sdif, - hslot2, skb); - if (!result) { - hash2 = ipv6_portaddr_hash(net, &in6addr_any, hnum); - slot2 = hash2 & udptable->mask; + hslot2, skb, TCP_ESTABLISHED); + if (result) + goto done; - hslot2 = &udptable->hash2[slot2]; + /* Lookup redirect from BPF */ + result = inet6_lookup_run_bpf(net, udptable->protocol, + saddr, sport, daddr, hnum); + if (result) + goto done; - result = udp6_lib_lookup2(net, saddr, sport, - &in6addr_any, hnum, dif, sdif, - hslot2, skb); - } + /* Lookup bound sockets */ + result = udp6_lib_lookup2(net, saddr, sport, + daddr, hnum, dif, sdif, + hslot2, skb, 0); + if (result) + goto done; + + hash2 = ipv6_portaddr_hash(net, &in6addr_any, hnum); + slot2 = hash2 & udptable->mask; + hslot2 = &udptable->hash2[slot2]; + + result = udp6_lib_lookup2(net, saddr, sport, + &in6addr_any, hnum, dif, sdif, + hslot2, skb, 0); +done: if (IS_ERR(result)) return NULL; return result;
--
2.20.1