From: Shmulik Ladkani <shmulik@metanetworks.com>
To: bpf@vger.kernel.org, Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
John Fastabend <john.fastabend@gmail.com>
Cc: Andrii Nakryiko <andrii@kernel.org>,
Paul Chaignon <paul@isovalent.com>,
Shmulik Ladkani <shmulik.ladkani@gmail.com>
Subject: [PATCH v4 bpf-next 2/4] bpf: Support setting variable-length tunnel options
Date: Tue, 23 Aug 2022 16:30:18 +0300 [thread overview]
Message-ID: <20220823133020.73872-3-shmulik.ladkani@gmail.com> (raw)
In-Reply-To: <20220823133020.73872-1-shmulik.ladkani@gmail.com>
Existing 'bpf_skb_set_tunnel_opt' allows setting tunnel options given
an option buffer (ARG_PTR_TO_MEM) and the compile-time fixed buffer
size (ARG_CONST_SIZE).
However, in certain cases we wish to set tunnel options of dynamic
length.
For example, we have an ebpf program that gets geneve options on
incoming packets, stores them into a map (using a key representing
the incoming flow), and later needs to assign *same* options to
reply packets (belonging to same flow).
This is currently imposssible without knowing sender's exact geneve
options length, which unfortunately is dymamic.
Introduce 'bpf_skb_set_tunnel_opt_dynptr'.
This is a variant of 'bpf_skb_set_tunnel_opt' which gets a bpf dynamic
pointer (ARG_PTR_TO_DYNPTR) parameter 'ptr' whose data points to the
options buffer, and 'len', the byte length of options data caller wishes
to copy into ip_tunnnel_info.
'len' must never exceed the dynptr's internal size, o/w EINVAL is
returned.
Signed-off-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
---
v3: Avoid 'inline' for the __bpf_skb_set_tunopt helper function
v4: change API to be based on bpf_dynptr, suggested by John Fastabend <john.fastabend@gmail.com>
---
include/uapi/linux/bpf.h | 12 ++++++++++++
net/core/filter.c | 36 ++++++++++++++++++++++++++++++++--
tools/include/uapi/linux/bpf.h | 12 ++++++++++++
3 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 934a2a8beb87..6d7eedf3644e 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -5355,6 +5355,17 @@ union bpf_attr {
* Return
* Current *ktime*.
*
+ * long bpf_skb_set_tunnel_opt_dynptr(struct sk_buff *skb, struct bpf_dynptr *opt, u32 len)
+ * Description
+ * Set tunnel options metadata for the packet associated to *skb*
+ * to the variable length *len* bytes of option data pointed to
+ * by the *opts* dynptr.
+ *
+ * See also the description of the **bpf_skb_get_tunnel_opt**\ ()
+ * helper for additional information.
+ * Return
+ * 0 on success, or a negative error in case of failure.
+ *
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -5566,6 +5577,7 @@ union bpf_attr {
FN(tcp_raw_check_syncookie_ipv4), \
FN(tcp_raw_check_syncookie_ipv6), \
FN(ktime_get_tai_ns), \
+ FN(skb_set_tunnel_opt_dynptr), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
diff --git a/net/core/filter.c b/net/core/filter.c
index 1acfaffeaf32..406ed0c50149 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -4669,8 +4669,7 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_key_proto = {
.arg4_type = ARG_ANYTHING,
};
-BPF_CALL_3(bpf_skb_set_tunnel_opt, struct sk_buff *, skb,
- const u8 *, from, u32, size)
+static u64 __bpf_skb_set_tunopt(struct sk_buff *skb, const u8 *from, u32 size)
{
struct ip_tunnel_info *info = skb_tunnel_info(skb);
const struct metadata_dst *md = this_cpu_ptr(md_dst);
@@ -4685,6 +4684,26 @@ BPF_CALL_3(bpf_skb_set_tunnel_opt, struct sk_buff *, skb,
return 0;
}
+BPF_CALL_3(bpf_skb_set_tunnel_opt, struct sk_buff *, skb,
+ const u8 *, from, u32, size)
+{
+ return __bpf_skb_set_tunopt(skb, from, size);
+}
+
+BPF_CALL_3(bpf_skb_set_tunnel_opt_dynptr, struct sk_buff *, skb,
+ struct bpf_dynptr_kern *, ptr, u32, len)
+{
+ const u8 *from;
+ u32 avail;
+
+ from = bpf_dynptr_get_data(ptr, &avail);
+ if (unlikely(!from))
+ return -EFAULT;
+ if (unlikely(len > avail))
+ return -EINVAL;
+ return __bpf_skb_set_tunopt(skb, from, len);
+}
+
static const struct bpf_func_proto bpf_skb_set_tunnel_opt_proto = {
.func = bpf_skb_set_tunnel_opt,
.gpl_only = false,
@@ -4694,6 +4713,15 @@ static const struct bpf_func_proto bpf_skb_set_tunnel_opt_proto = {
.arg3_type = ARG_CONST_SIZE,
};
+static const struct bpf_func_proto bpf_skb_set_tunnel_opt_dynptr_proto = {
+ .func = bpf_skb_set_tunnel_opt_dynptr,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL,
+ .arg3_type = ARG_ANYTHING,
+};
+
static const struct bpf_func_proto *
bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
{
@@ -4714,6 +4742,8 @@ bpf_get_skb_set_tunnel_proto(enum bpf_func_id which)
return &bpf_skb_set_tunnel_key_proto;
case BPF_FUNC_skb_set_tunnel_opt:
return &bpf_skb_set_tunnel_opt_proto;
+ case BPF_FUNC_skb_set_tunnel_opt_dynptr:
+ return &bpf_skb_set_tunnel_opt_dynptr_proto;
default:
return NULL;
}
@@ -7826,6 +7856,7 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
case BPF_FUNC_skb_get_tunnel_opt:
return &bpf_skb_get_tunnel_opt_proto;
case BPF_FUNC_skb_set_tunnel_opt:
+ case BPF_FUNC_skb_set_tunnel_opt_dynptr:
return bpf_get_skb_set_tunnel_proto(func_id);
case BPF_FUNC_redirect:
return &bpf_redirect_proto;
@@ -8169,6 +8200,7 @@ lwt_xmit_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
case BPF_FUNC_skb_get_tunnel_opt:
return &bpf_skb_get_tunnel_opt_proto;
case BPF_FUNC_skb_set_tunnel_opt:
+ case BPF_FUNC_skb_set_tunnel_opt_dynptr:
return bpf_get_skb_set_tunnel_proto(func_id);
case BPF_FUNC_redirect:
return &bpf_redirect_proto;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 1d6085e15fc8..b9bbccd1e5fa 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -5355,6 +5355,17 @@ union bpf_attr {
* Return
* Current *ktime*.
*
+ * long bpf_skb_set_tunnel_opt_dynptr(struct sk_buff *skb, struct bpf_dynptr *opt, u32 len)
+ * Description
+ * Set tunnel options metadata for the packet associated to *skb*
+ * to the variable length *len* bytes of option data pointed to
+ * by the *opts* dynptr.
+ *
+ * See also the description of the **bpf_skb_get_tunnel_opt**\ ()
+ * helper for additional information.
+ * Return
+ * 0 on success, or a negative error in case of failure.
+ *
*/
#define __BPF_FUNC_MAPPER(FN) \
FN(unspec), \
@@ -5566,6 +5577,7 @@ union bpf_attr {
FN(tcp_raw_check_syncookie_ipv4), \
FN(tcp_raw_check_syncookie_ipv6), \
FN(ktime_get_tai_ns), \
+ FN(skb_set_tunnel_opt_dynptr), \
/* */
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
--
2.37.2
next prev parent reply other threads:[~2022-08-23 16:59 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-23 13:30 [PATCH v4 bpf-next 0/4] bpf: Support setting variable-length tunnel options Shmulik Ladkani
2022-08-23 13:30 ` [PATCH v4 bpf-next 1/4] bpf: Add 'bpf_dynptr_get_data' helper Shmulik Ladkani
2022-08-23 19:11 ` Joanne Koong
2022-08-24 4:07 ` Shmulik Ladkani
2022-08-23 13:30 ` Shmulik Ladkani [this message]
2022-08-23 13:30 ` [PATCH v4 bpf-next 3/4] selftests/bpf: Simplify test_tunnel setup for allowing non-local tunnel traffic Shmulik Ladkani
2022-08-23 13:30 ` [PATCH v4 bpf-next 4/4] selftests/bpf: Add geneve with bpf_skb_set_tunnel_opt_dynptr test-case to test_progs Shmulik Ladkani
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=20220823133020.73872-3-shmulik.ladkani@gmail.com \
--to=shmulik@metanetworks.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=john.fastabend@gmail.com \
--cc=paul@isovalent.com \
--cc=shmulik.ladkani@gmail.com \
/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.