From: Jakub Sitnicki <jakub@cloudflare.com>
To: Martin KaFai Lau <kafai@fb.com>
Cc: netdev@vger.kernel.org, bpf@vger.kernel.org,
dccp@vger.kernel.org, kernel-team@cloudflare.com,
Alexei Starovoitov <ast@kernel.org>,
"Daniel Borkmann" <daniel@iogearbox.net>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Gerrit Renker <gerrit@erg.abdn.ac.uk>,
Jakub Kicinski <kuba@kernel.org>,
Marek Majkowski <marek@cloudflare.com>,
Lorenz Bauer <lmb@cloudflare.com>
Subject: Re: [PATCH bpf-next 02/17] bpf: Introduce SK_LOOKUP program type with a dedicated attach point
Date: Fri, 08 May 2020 12:45:14 +0200 [thread overview]
Message-ID: <87a72ivh6t.fsf@cloudflare.com> (raw)
In-Reply-To: <20200508070638.pqe73q4v3paxpkq5@kafai-mbp.dhcp.thefacebook.com>
On Fri, May 08, 2020 at 09:06 AM CEST, Martin KaFai Lau wrote:
> On Wed, May 06, 2020 at 02:54:58PM +0200, Jakub Sitnicki wrote:
>> Add a new program type BPF_PROG_TYPE_SK_LOOKUP and a dedicated attach type
>> called BPF_SK_LOOKUP. The new program kind is to be invoked by the
>> transport layer when looking up a socket for a received packet.
>>
>> When called, SK_LOOKUP program can select a socket that will receive the
>> packet. This serves as a mechanism to overcome the limits of what bind()
>> API allows to express. Two use-cases driving this work are:
>>
>> (1) steer packets destined to an IP range, fixed port to a socket
>>
>> 192.0.2.0/24, port 80 -> NGINX socket
>>
>> (2) steer packets destined to an IP address, any port to a socket
>>
>> 198.51.100.1, any port -> L7 proxy socket
>>
>> In its run-time context, program receives information about the packet that
>> triggered the socket lookup. Namely IP version, L4 protocol identifier, and
>> address 4-tuple. Context can be further extended to include ingress
>> interface identifier.
>>
>> To select a socket BPF program fetches it from a map holding socket
>> references, like SOCKMAP or SOCKHASH, and calls bpf_sk_assign(ctx, sk, ...)
>> helper to record the selection. Transport layer then uses the selected
>> socket as a result of socket lookup.
>>
>> This patch only enables the user to attach an SK_LOOKUP program to a
>> network namespace. Subsequent patches hook it up to run on local delivery
>> path in ipv4 and ipv6 stacks.
>>
>> Suggested-by: Marek Majkowski <marek@cloudflare.com>
>> Reviewed-by: Lorenz Bauer <lmb@cloudflare.com>
>> Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
>> ---
[...]
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index bb1ab7da6103..26d643c171fd 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -2729,6 +2729,8 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
>> case BPF_CGROUP_GETSOCKOPT:
>> case BPF_CGROUP_SETSOCKOPT:
>> return BPF_PROG_TYPE_CGROUP_SOCKOPT;
>> + case BPF_SK_LOOKUP:
> It may be a good idea to enforce the "expected_attach_type ==
> BPF_SK_LOOKUP" during prog load time in bpf_prog_load_check_attach().
> The attr->expected_attach_type could be anything right now if I read
> it correctly.
I'll extend bpf_prog_attach_check_attach_type to enforce it for SK_LOOKUP.
>
>> + return BPF_PROG_TYPE_SK_LOOKUP;
>> default:
>> return BPF_PROG_TYPE_UNSPEC;
>> }
>> @@ -2778,6 +2780,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
>> case BPF_PROG_TYPE_FLOW_DISSECTOR:
>> ret = skb_flow_dissector_bpf_prog_attach(attr, prog);
>> break;
>> + case BPF_PROG_TYPE_SK_LOOKUP:
>> + ret = sk_lookup_prog_attach(attr, prog);
>> + break;
>> case BPF_PROG_TYPE_CGROUP_DEVICE:
>> case BPF_PROG_TYPE_CGROUP_SKB:
>> case BPF_PROG_TYPE_CGROUP_SOCK:
>> @@ -2818,6 +2823,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
>> return lirc_prog_detach(attr);
>> case BPF_PROG_TYPE_FLOW_DISSECTOR:
>> return skb_flow_dissector_bpf_prog_detach(attr);
>> + case BPF_PROG_TYPE_SK_LOOKUP:
>> + return sk_lookup_prog_detach(attr);
>> case BPF_PROG_TYPE_CGROUP_DEVICE:
>> case BPF_PROG_TYPE_CGROUP_SKB:
>> case BPF_PROG_TYPE_CGROUP_SOCK:
>> @@ -2867,6 +2874,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
>> return lirc_prog_query(attr, uattr);
>> case BPF_FLOW_DISSECTOR:
>> return skb_flow_dissector_prog_query(attr, uattr);
>> + case BPF_SK_LOOKUP:
>> + return sk_lookup_prog_query(attr, uattr);
> "# CONFIG_NET is not set" needs to be taken care.
Sorry, embarassing mistake. Will add stubs returning -EINVAL like
flow_dissector and cgroup_bpf progs have.
>
>> default:
>> return -EINVAL;
>> }
>> diff --git a/net/core/filter.c b/net/core/filter.c
>> index bc25bb1085b1..a00bdc70041c 100644
>> --- a/net/core/filter.c
>> +++ b/net/core/filter.c
>> @@ -9054,6 +9054,253 @@ const struct bpf_verifier_ops sk_reuseport_verifier_ops = {
>>
>> const struct bpf_prog_ops sk_reuseport_prog_ops = {
>> };
>> +
>> +static DEFINE_MUTEX(sk_lookup_prog_mutex);
>> +
>> +int sk_lookup_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
>> +{
>> + struct net *net = current->nsproxy->net_ns;
>> + int ret;
>> +
>> + if (unlikely(attr->attach_flags))
>> + return -EINVAL;
>> +
>> + mutex_lock(&sk_lookup_prog_mutex);
>> + ret = bpf_prog_attach_one(&net->sk_lookup_prog,
>> + &sk_lookup_prog_mutex, prog,
>> + attr->attach_flags);
>> + mutex_unlock(&sk_lookup_prog_mutex);
>> +
>> + return ret;
>> +}
>> +
>> +int sk_lookup_prog_detach(const union bpf_attr *attr)
>> +{
>> + struct net *net = current->nsproxy->net_ns;
>> + int ret;
>> +
>> + if (unlikely(attr->attach_flags))
>> + return -EINVAL;
>> +
>> + mutex_lock(&sk_lookup_prog_mutex);
>> + ret = bpf_prog_detach_one(&net->sk_lookup_prog,
>> + &sk_lookup_prog_mutex);
>> + mutex_unlock(&sk_lookup_prog_mutex);
>> +
>> + return ret;
>> +}
>> +
>> +int sk_lookup_prog_query(const union bpf_attr *attr,
>> + union bpf_attr __user *uattr)
>> +{
>> + struct net *net;
>> + int ret;
>> +
>> + net = get_net_ns_by_fd(attr->query.target_fd);
>> + if (IS_ERR(net))
>> + return PTR_ERR(net);
>> +
>> + ret = bpf_prog_query_one(&net->sk_lookup_prog, attr, uattr);
>> +
>> + put_net(net);
>> + return ret;
>> +}
>> +
>> +BPF_CALL_3(bpf_sk_lookup_assign, struct bpf_sk_lookup_kern *, ctx,
>> + struct sock *, sk, u64, flags)
>> +{
>> + if (unlikely(flags != 0))
>> + return -EINVAL;
>> + if (unlikely(!sk_fullsock(sk)))
> May be ARG_PTR_TO_SOCKET instead?
I had ARG_PTR_TO_SOCKET initially, then switched to SOCK_COMMON to match
the TC bpf_sk_assign proto. Now that you point it out, it makes more
sense to be more specific in the helper proto.
>
>> + return -ESOCKTNOSUPPORT;
>> +
>> + /* Check if socket is suitable for packet L3/L4 protocol */
>> + if (sk->sk_protocol != ctx->protocol)
>> + return -EPROTOTYPE;
>> + if (sk->sk_family != ctx->family &&
>> + (sk->sk_family == AF_INET || ipv6_only_sock(sk)))
>> + return -EAFNOSUPPORT;
>> +
>> + /* Select socket as lookup result */
>> + ctx->selected_sk = sk;
> Could sk be a TCP_ESTABLISHED sk?
Yes, and what's worse, it could be ref-counted. This is a bug. I should
be rejecting ref counted sockets here.
Callers of __inet_lookup_listener() and inet6_lookup_listener() expect
an RCU-freed socket on return.
For UDP lookup, returning a TCP_ESTABLISHED (connected) socket is okay.
Thank you for valuable comments. Will fix all of the above in v2.
WARNING: multiple messages have this Message-ID (diff)
From: Jakub Sitnicki <jakub@cloudflare.com>
To: dccp@vger.kernel.org
Subject: Re: [PATCH bpf-next 02/17] bpf: Introduce SK_LOOKUP program type with a dedicated attach point
Date: Fri, 08 May 2020 10:45:14 +0000 [thread overview]
Message-ID: <87a72ivh6t.fsf@cloudflare.com> (raw)
In-Reply-To: <20200506125514.1020829-3-jakub@cloudflare.com>
On Fri, May 08, 2020 at 09:06 AM CEST, Martin KaFai Lau wrote:
> On Wed, May 06, 2020 at 02:54:58PM +0200, Jakub Sitnicki wrote:
>> Add a new program type BPF_PROG_TYPE_SK_LOOKUP and a dedicated attach type
>> called BPF_SK_LOOKUP. The new program kind is to be invoked by the
>> transport layer when looking up a socket for a received packet.
>>
>> When called, SK_LOOKUP program can select a socket that will receive the
>> packet. This serves as a mechanism to overcome the limits of what bind()
>> API allows to express. Two use-cases driving this work are:
>>
>> (1) steer packets destined to an IP range, fixed port to a socket
>>
>> 192.0.2.0/24, port 80 -> NGINX socket
>>
>> (2) steer packets destined to an IP address, any port to a socket
>>
>> 198.51.100.1, any port -> L7 proxy socket
>>
>> In its run-time context, program receives information about the packet that
>> triggered the socket lookup. Namely IP version, L4 protocol identifier, and
>> address 4-tuple. Context can be further extended to include ingress
>> interface identifier.
>>
>> To select a socket BPF program fetches it from a map holding socket
>> references, like SOCKMAP or SOCKHASH, and calls bpf_sk_assign(ctx, sk, ...)
>> helper to record the selection. Transport layer then uses the selected
>> socket as a result of socket lookup.
>>
>> This patch only enables the user to attach an SK_LOOKUP program to a
>> network namespace. Subsequent patches hook it up to run on local delivery
>> path in ipv4 and ipv6 stacks.
>>
>> Suggested-by: Marek Majkowski <marek@cloudflare.com>
>> Reviewed-by: Lorenz Bauer <lmb@cloudflare.com>
>> Signed-off-by: Jakub Sitnicki <jakub@cloudflare.com>
>> ---
[...]
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index bb1ab7da6103..26d643c171fd 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -2729,6 +2729,8 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
>> case BPF_CGROUP_GETSOCKOPT:
>> case BPF_CGROUP_SETSOCKOPT:
>> return BPF_PROG_TYPE_CGROUP_SOCKOPT;
>> + case BPF_SK_LOOKUP:
> It may be a good idea to enforce the "expected_attach_type =
> BPF_SK_LOOKUP" during prog load time in bpf_prog_load_check_attach().
> The attr->expected_attach_type could be anything right now if I read
> it correctly.
I'll extend bpf_prog_attach_check_attach_type to enforce it for SK_LOOKUP.
>
>> + return BPF_PROG_TYPE_SK_LOOKUP;
>> default:
>> return BPF_PROG_TYPE_UNSPEC;
>> }
>> @@ -2778,6 +2780,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
>> case BPF_PROG_TYPE_FLOW_DISSECTOR:
>> ret = skb_flow_dissector_bpf_prog_attach(attr, prog);
>> break;
>> + case BPF_PROG_TYPE_SK_LOOKUP:
>> + ret = sk_lookup_prog_attach(attr, prog);
>> + break;
>> case BPF_PROG_TYPE_CGROUP_DEVICE:
>> case BPF_PROG_TYPE_CGROUP_SKB:
>> case BPF_PROG_TYPE_CGROUP_SOCK:
>> @@ -2818,6 +2823,8 @@ static int bpf_prog_detach(const union bpf_attr *attr)
>> return lirc_prog_detach(attr);
>> case BPF_PROG_TYPE_FLOW_DISSECTOR:
>> return skb_flow_dissector_bpf_prog_detach(attr);
>> + case BPF_PROG_TYPE_SK_LOOKUP:
>> + return sk_lookup_prog_detach(attr);
>> case BPF_PROG_TYPE_CGROUP_DEVICE:
>> case BPF_PROG_TYPE_CGROUP_SKB:
>> case BPF_PROG_TYPE_CGROUP_SOCK:
>> @@ -2867,6 +2874,8 @@ static int bpf_prog_query(const union bpf_attr *attr,
>> return lirc_prog_query(attr, uattr);
>> case BPF_FLOW_DISSECTOR:
>> return skb_flow_dissector_prog_query(attr, uattr);
>> + case BPF_SK_LOOKUP:
>> + return sk_lookup_prog_query(attr, uattr);
> "# CONFIG_NET is not set" needs to be taken care.
Sorry, embarassing mistake. Will add stubs returning -EINVAL like
flow_dissector and cgroup_bpf progs have.
>
>> default:
>> return -EINVAL;
>> }
>> diff --git a/net/core/filter.c b/net/core/filter.c
>> index bc25bb1085b1..a00bdc70041c 100644
>> --- a/net/core/filter.c
>> +++ b/net/core/filter.c
>> @@ -9054,6 +9054,253 @@ const struct bpf_verifier_ops sk_reuseport_verifier_ops = {
>>
>> const struct bpf_prog_ops sk_reuseport_prog_ops = {
>> };
>> +
>> +static DEFINE_MUTEX(sk_lookup_prog_mutex);
>> +
>> +int sk_lookup_prog_attach(const union bpf_attr *attr, struct bpf_prog *prog)
>> +{
>> + struct net *net = current->nsproxy->net_ns;
>> + int ret;
>> +
>> + if (unlikely(attr->attach_flags))
>> + return -EINVAL;
>> +
>> + mutex_lock(&sk_lookup_prog_mutex);
>> + ret = bpf_prog_attach_one(&net->sk_lookup_prog,
>> + &sk_lookup_prog_mutex, prog,
>> + attr->attach_flags);
>> + mutex_unlock(&sk_lookup_prog_mutex);
>> +
>> + return ret;
>> +}
>> +
>> +int sk_lookup_prog_detach(const union bpf_attr *attr)
>> +{
>> + struct net *net = current->nsproxy->net_ns;
>> + int ret;
>> +
>> + if (unlikely(attr->attach_flags))
>> + return -EINVAL;
>> +
>> + mutex_lock(&sk_lookup_prog_mutex);
>> + ret = bpf_prog_detach_one(&net->sk_lookup_prog,
>> + &sk_lookup_prog_mutex);
>> + mutex_unlock(&sk_lookup_prog_mutex);
>> +
>> + return ret;
>> +}
>> +
>> +int sk_lookup_prog_query(const union bpf_attr *attr,
>> + union bpf_attr __user *uattr)
>> +{
>> + struct net *net;
>> + int ret;
>> +
>> + net = get_net_ns_by_fd(attr->query.target_fd);
>> + if (IS_ERR(net))
>> + return PTR_ERR(net);
>> +
>> + ret = bpf_prog_query_one(&net->sk_lookup_prog, attr, uattr);
>> +
>> + put_net(net);
>> + return ret;
>> +}
>> +
>> +BPF_CALL_3(bpf_sk_lookup_assign, struct bpf_sk_lookup_kern *, ctx,
>> + struct sock *, sk, u64, flags)
>> +{
>> + if (unlikely(flags != 0))
>> + return -EINVAL;
>> + if (unlikely(!sk_fullsock(sk)))
> May be ARG_PTR_TO_SOCKET instead?
I had ARG_PTR_TO_SOCKET initially, then switched to SOCK_COMMON to match
the TC bpf_sk_assign proto. Now that you point it out, it makes more
sense to be more specific in the helper proto.
>
>> + return -ESOCKTNOSUPPORT;
>> +
>> + /* Check if socket is suitable for packet L3/L4 protocol */
>> + if (sk->sk_protocol != ctx->protocol)
>> + return -EPROTOTYPE;
>> + if (sk->sk_family != ctx->family &&
>> + (sk->sk_family = AF_INET || ipv6_only_sock(sk)))
>> + return -EAFNOSUPPORT;
>> +
>> + /* Select socket as lookup result */
>> + ctx->selected_sk = sk;
> Could sk be a TCP_ESTABLISHED sk?
Yes, and what's worse, it could be ref-counted. This is a bug. I should
be rejecting ref counted sockets here.
Callers of __inet_lookup_listener() and inet6_lookup_listener() expect
an RCU-freed socket on return.
For UDP lookup, returning a TCP_ESTABLISHED (connected) socket is okay.
Thank you for valuable comments. Will fix all of the above in v2.
next prev parent reply other threads:[~2020-05-08 10:45 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-06 12:54 [PATCH bpf-next 00/17] Run a BPF program on socket lookup Jakub Sitnicki
2020-05-06 12:54 ` Jakub Sitnicki
2020-05-06 12:54 ` [PATCH bpf-next 01/17] flow_dissector: Extract attach/detach/query helpers Jakub Sitnicki
2020-05-06 12:54 ` Jakub Sitnicki
2020-05-06 12:54 ` [PATCH bpf-next 02/17] bpf: Introduce SK_LOOKUP program type with a dedicated attach point Jakub Sitnicki
2020-05-06 12:54 ` Jakub Sitnicki
2020-05-06 13:16 ` Lorenz Bauer
2020-05-06 13:16 ` Lorenz Bauer
2020-05-06 13:53 ` Jakub Sitnicki
2020-05-06 13:53 ` Jakub Sitnicki
2020-05-07 20:55 ` Martin KaFai Lau
2020-05-07 20:55 ` Martin KaFai Lau
2020-05-08 8:54 ` Jakub Sitnicki
2020-05-08 8:54 ` Jakub Sitnicki
2020-05-08 7:06 ` Martin KaFai Lau
2020-05-08 7:06 ` Martin KaFai Lau
2020-05-08 10:45 ` Jakub Sitnicki [this message]
2020-05-08 10:45 ` Jakub Sitnicki
2020-05-08 18:39 ` Martin KaFai Lau
2020-05-08 18:39 ` Martin KaFai Lau
2020-05-11 9:08 ` Jakub Sitnicki
2020-05-11 9:08 ` Jakub Sitnicki
2020-05-11 18:59 ` Martin KaFai Lau
2020-05-11 18:59 ` Martin KaFai Lau
2020-05-11 19:26 ` Jakub Sitnicki
2020-05-11 19:26 ` Jakub Sitnicki
2020-05-11 20:54 ` Martin KaFai Lau
2020-05-11 20:54 ` Martin KaFai Lau
2020-05-12 14:16 ` Jakub Sitnicki
2020-05-12 14:16 ` Jakub Sitnicki
2020-05-06 12:54 ` [PATCH bpf-next 03/17] inet: Store layer 4 protocol in inet_hashinfo Jakub Sitnicki
2020-05-06 12:54 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 04/17] inet: Extract helper for selecting socket from reuseport group Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 05/17] inet: Run SK_LOOKUP BPF program on socket lookup Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 06/17] inet6: Extract helper for selecting socket from reuseport group Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 07/17] inet6: Run SK_LOOKUP BPF program on socket lookup Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 08/17] udp: Store layer 4 protocol in udp_table Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 09/17] udp: Extract helper for selecting socket from reuseport group Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 10/17] udp: Run SK_LOOKUP BPF program on socket lookup Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 11/17] udp6: Extract helper for selecting socket from reuseport group Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 12/17] udp6: Run SK_LOOKUP BPF program on socket lookup Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 13/17] bpf: Sync linux/bpf.h to tools/ Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 14/17] libbpf: Add support for SK_LOOKUP program type Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-08 17:41 ` Andrii Nakryiko
2020-05-08 17:41 ` Andrii Nakryiko
2020-05-08 17:52 ` Yonghong Song
2020-05-08 17:52 ` Yonghong Song
2020-05-08 17:59 ` Andrii Nakryiko
2020-05-08 17:59 ` Andrii Nakryiko
2020-05-11 8:12 ` Jakub Sitnicki
2020-05-11 8:12 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 15/17] selftests/bpf: Add verifier tests for bpf_sk_lookup context access Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 16/17] selftests/bpf: Rename test_sk_lookup_kern.c to test_ref_track_kern.c Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
2020-05-06 12:55 ` [PATCH bpf-next 17/17] selftests/bpf: Tests for BPF_SK_LOOKUP attach point Jakub Sitnicki
2020-05-06 12:55 ` Jakub Sitnicki
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=87a72ivh6t.fsf@cloudflare.com \
--to=jakub@cloudflare.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=dccp@vger.kernel.org \
--cc=edumazet@google.com \
--cc=gerrit@erg.abdn.ac.uk \
--cc=kafai@fb.com \
--cc=kernel-team@cloudflare.com \
--cc=kuba@kernel.org \
--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
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.