bpf.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jakub Sitnicki <jakub@cloudflare.com>
To: netdev@vger.kernel.org, bpf@vger.kernel.org
Cc: kernel-team@cloudflare.com, Marek Majkowski <marek@cloudflare.com>
Subject: [RFC bpf-next 2/7] ipv4: Run inet_lookup bpf program on socket lookup
Date: Tue, 18 Jun 2019 15:00:45 +0200	[thread overview]
Message-ID: <20190618130050.8344-3-jakub@cloudflare.com> (raw)
In-Reply-To: <20190618130050.8344-1-jakub@cloudflare.com>

Run a BPF program before looking up the listening socket, or in case of udp
before looking up any socket, connected or not. The program is allowed to
change the destination address & port we use as keys for the lookup,
providing its return code is BPF_REDIRECT.

This allows us to redirect traffic destined to a set of addresses and ports
without bindings sockets to all the addresses and ports we want to receive
on.

Suggested-by: Marek Majkowski <marek@cloudflare.com>
Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
---
 include/net/inet_hashtables.h | 39 +++++++++++++++++++++++++++++++++++
 net/ipv4/inet_hashtables.c    | 11 ++++++----
 net/ipv4/udp.c                |  1 +
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index babb14136705..7d8b58b2ded0 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -418,4 +418,43 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
 
 int inet_hash_connect(struct inet_timewait_death_row *death_row,
 		      struct sock *sk);
+
+#ifdef CONFIG_BPF_SYSCALL
+static inline void inet_lookup_run_bpf(struct net *net,
+				       const __be32 saddr,
+				       const __be16 sport,
+				       __be32 *daddr,
+				       unsigned short *hnum)
+{
+	struct bpf_inet_lookup_kern ctx = {
+		.family	= AF_INET,
+		.saddr	= saddr,
+		.sport	= sport,
+		.daddr	= *daddr,
+		.hnum	= *hnum,
+	};
+	struct bpf_prog *prog;
+	int ret = BPF_OK;
+
+	rcu_read_lock();
+	prog = rcu_dereference(net->inet_lookup_prog);
+	if (prog)
+		ret = BPF_PROG_RUN(prog, &ctx);
+	rcu_read_unlock();
+
+	if (ret == BPF_REDIRECT) {
+		*daddr = ctx.daddr;
+		*hnum = ctx.hnum;
+	}
+}
+#else
+static inline void inet_lookup_run_bpf(struct sk_buff *skb,
+				       const __be32 saddr,
+				       const __be16 sport,
+				       __be32 *daddr,
+				       unsigned short *hnum)
+{
+}
+#endif	/* CONFIG_BPF_SYSCALL */
+
 #endif /* _INET_HASHTABLES_H */
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 942265d65eb3..ae3f1da1b4f6 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -300,24 +300,27 @@ struct sock *__inet_lookup_listener(struct net *net,
 				    const int dif, const int sdif)
 {
 	struct inet_listen_hashbucket *ilb2;
+	unsigned short hnum2 = hnum;
 	struct sock *result = NULL;
+	__be32 daddr2 = daddr;
 	unsigned int hash2;
 
-	hash2 = ipv4_portaddr_hash(net, daddr, hnum);
+	inet_lookup_run_bpf(net, saddr, sport, &daddr2, &hnum2);
+	hash2 = ipv4_portaddr_hash(net, daddr2, hnum2);
 	ilb2 = inet_lhash2_bucket(hashinfo, hash2);
 
 	result = inet_lhash2_lookup(net, ilb2, skb, doff,
-				    saddr, sport, daddr, hnum,
+				    saddr, sport, daddr2, hnum2,
 				    dif, sdif);
 	if (result)
 		goto done;
 
 	/* Lookup lhash2 with INADDR_ANY */
-	hash2 = ipv4_portaddr_hash(net, htonl(INADDR_ANY), hnum);
+	hash2 = ipv4_portaddr_hash(net, htonl(INADDR_ANY), hnum2);
 	ilb2 = inet_lhash2_bucket(hashinfo, hash2);
 
 	result = inet_lhash2_lookup(net, ilb2, skb, doff,
-				    saddr, sport, htonl(INADDR_ANY), hnum,
+				    saddr, sport, htonl(INADDR_ANY), hnum2,
 				    dif, sdif);
 done:
 	if (unlikely(IS_ERR(result)))
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 8fb250ed53d4..c4f4c94525ec 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -467,6 +467,7 @@ struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
 	struct udp_hslot *hslot2;
 	bool exact_dif = udp_lib_exact_dif_match(net, skb);
 
+	inet_lookup_run_bpf(net, saddr, sport, &daddr, &hnum);
 	hash2 = ipv4_portaddr_hash(net, daddr, hnum);
 	slot2 = hash2 & udptable->mask;
 	hslot2 = &udptable->hash2[slot2];
-- 
2.20.1


  parent reply	other threads:[~2019-06-18 13:00 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-18 13:00 [RFC bpf-next 0/7] Programming socket lookup with BPF Jakub Sitnicki
2019-06-18 13:00 ` [RFC bpf-next 1/7] bpf: Introduce inet_lookup program type Jakub Sitnicki
2019-06-18 13:00 ` Jakub Sitnicki [this message]
2019-06-18 13:00 ` [RFC bpf-next 3/7] ipv6: Run inet_lookup bpf program on socket lookup Jakub Sitnicki
2019-06-18 13:00 ` [RFC bpf-next 4/7] bpf: Sync linux/bpf.h to tools/ Jakub Sitnicki
2019-06-18 13:00 ` [RFC bpf-next 5/7] libbpf: Add support for inet_lookup program type Jakub Sitnicki
2019-06-18 13:00 ` [RFC bpf-next 6/7] bpf: Test destination address remapping with inet_lookup Jakub Sitnicki
2019-06-18 13:00 ` [RFC bpf-next 7/7] bpf: Add verifier tests for inet_lookup context access Jakub Sitnicki
2019-06-18 13:52 ` [RFC bpf-next 0/7] Programming socket lookup with BPF Florian Westphal
2019-06-19  9:13   ` Jakub Sitnicki
2019-06-20 11:56     ` Florian Westphal
2019-06-20 22:20     ` Joe Stringer
     [not found]       ` <CAGn+7TUmgsA8oKw-mM6S5iR4rmNt6sWxjUgw8=qSCHb=m0ROyg@mail.gmail.com>
2019-06-21 16:50         ` Joe Stringer
2019-06-25  8:11           ` Jakub Sitnicki
2019-06-25  7:28       ` Jakub Sitnicki
2019-06-21 12:51     ` Florian Westphal
2019-06-21 14:33       ` Eric Dumazet
2019-06-21 16:41         ` Florian Westphal
2019-06-21 16:54           ` Paolo Abeni

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20190618130050.8344-3-jakub@cloudflare.com \
    --to=jakub@cloudflare.com \
    --cc=bpf@vger.kernel.org \
    --cc=kernel-team@cloudflare.com \
    --cc=marek@cloudflare.com \
    --cc=netdev@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).