BPF Archive on lore.kernel.org
 help / color / Atom feed
From: Jakub Sitnicki <jakub@cloudflare.com>
To: bpf@vger.kernel.org, netdev@vger.kernel.org
Cc: kernel-team@cloudflare.com, Lorenz Bauer <lmb@cloudflare.com>,
	Marek Majkowski <marek@cloudflare.com>
Subject: [RFCv2 bpf-next 06/12] inet: Run inet_lookup bpf program on socket lookup
Date: Wed, 28 Aug 2019 09:22:44 +0200
Message-ID: <20190828072250.29828-7-jakub@cloudflare.com> (raw)
In-Reply-To: <20190828072250.29828-1-jakub@cloudflare.com>

Run a BPF program before looking up the listening socket. The program can
redirect the skb to a listening socket of its choice, providing it calls
bpf_redirect_lookup() helper and returns BPF_REDIRECT.

This lets the user-space program mappings between packet 4-tuple and
listening sockets. With the possibility to override the socket lookup from
BPF, applications don't need to bind sockets to every addresses they
receive on, or resort to listening on all addresses with INADDR_ANY.

Also port sharing conflicts become a non-issue. Application can listen on
any free port and still receive traffic destined to its assigned service
port.

Suggested-by: Marek Majkowski <marek@cloudflare.com>
Reviewed-by: Lorenz Bauer <lmb@cloudflare.com>
Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
---
 include/net/inet_hashtables.h | 33 +++++++++++++++++++++++++++++++++
 net/ipv4/inet_hashtables.c    |  5 +++++
 2 files changed, 38 insertions(+)

diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index b2d43ee72dc1..c9c7efb961cb 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -417,4 +417,37 @@ 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);
+
+static inline struct sock *__inet_lookup_run_bpf(const struct net *net,
+						 struct bpf_inet_lookup_kern *ctx)
+{
+	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();
+
+	return ret == BPF_REDIRECT ? ctx->redir_sk : NULL;
+}
+
+static inline struct sock *inet_lookup_run_bpf(const struct net *net, u8 proto,
+					       __be32 saddr, __be16 sport,
+					       __be32 daddr,
+					       unsigned short hnum)
+{
+	struct bpf_inet_lookup_kern ctx = {
+		.family		= AF_INET,
+		.protocol	= proto,
+		.saddr		= saddr,
+		.sport		= sport,
+		.daddr		= daddr,
+		.hnum		= hnum,
+	};
+
+	return __inet_lookup_run_bpf(net, &ctx);
+}
+
 #endif /* _INET_HASHTABLES_H */
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index 97824864e40d..ab6d89c27c94 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -299,6 +299,11 @@ struct sock *__inet_lookup_listener(struct net *net,
 	struct sock *result = NULL;
 	unsigned int hash2;
 
+	result = inet_lookup_run_bpf(net, hashinfo->protocol,
+				     saddr, sport, daddr, hnum);
+	if (result)
+		goto done;
+
 	hash2 = ipv4_portaddr_hash(net, daddr, hnum);
 	ilb2 = inet_lhash2_bucket(hashinfo, hash2);
 
-- 
2.20.1


  parent reply index

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-08-28  7:22 [RFCv2 bpf-next 00/12] Programming socket lookup with BPF Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 01/12] flow_dissector: Extract attach/detach/query helpers Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 02/12] bpf: Introduce inet_lookup program type for redirecting socket lookup Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 03/12] bpf: Add verifier tests for inet_lookup context access Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 04/12] inet: Store layer 4 protocol in inet_hashinfo Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 05/12] udp: Store layer 4 protocol in udp_table Jakub Sitnicki
2019-08-28  7:22 ` Jakub Sitnicki [this message]
2019-08-28  7:22 ` [RFCv2 bpf-next 07/12] inet6: Run inet_lookup bpf program on socket lookup Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 08/12] udp: " Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 09/12] udp6: " Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 10/12] bpf: Sync linux/bpf.h to tools/ Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 11/12] libbpf: Add support for inet_lookup program type Jakub Sitnicki
2019-08-28  7:22 ` [RFCv2 bpf-next 12/12] bpf: Test redirecting listening/receiving socket lookup Jakub Sitnicki

Reply instructions:

You may reply publically 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=20190828072250.29828-7-jakub@cloudflare.com \
    --to=jakub@cloudflare.com \
    --cc=bpf@vger.kernel.org \
    --cc=kernel-team@cloudflare.com \
    --cc=lmb@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

BPF Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/bpf/0 bpf/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 bpf bpf/ https://lore.kernel.org/bpf \
		bpf@vger.kernel.org
	public-inbox-index bpf

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.bpf


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git