From: Farid Zakaria <farid.m.zakaria@gmail.com>
To: ast@kernel.org, daniel@iogearbox.net, netdev@vger.kernel.org,
bpf@vger.kernel.org
Cc: Farid Zakaria <farid.m.zakaria@gmail.com>
Subject: [PATCH 1/1] bpf: introduce new helper udp_flow_src_port
Date: Fri, 2 Aug 2019 21:43:20 -0700 [thread overview]
Message-ID: <20190803044320.5530-2-farid.m.zakaria@gmail.com> (raw)
In-Reply-To: <20190803044320.5530-1-farid.m.zakaria@gmail.com>
Foo over UDP uses UDP encapsulation to add additional entropy
into the packets so that they get beter distribution across EMCP
routes.
Expose udp_flow_src_port as a bpf helper so that tunnel filters
can benefit from the helper.
Signed-off-by: Farid Zakaria <farid.m.zakaria@gmail.com>
---
include/uapi/linux/bpf.h | 21 +++++++--
net/core/filter.c | 20 ++++++++
tools/include/uapi/linux/bpf.h | 21 +++++++--
tools/testing/selftests/bpf/bpf_helpers.h | 2 +
.../bpf/prog_tests/udp_flow_src_port.c | 28 +++++++++++
.../bpf/progs/test_udp_flow_src_port_kern.c | 47 +++++++++++++++++++
6 files changed, 131 insertions(+), 8 deletions(-)
create mode 100644 tools/testing/selftests/bpf/prog_tests/udp_flow_src_port.c
create mode 100644 tools/testing/selftests/bpf/progs/test_udp_flow_src_port_kern.c
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 4393bd4b2419..90e814153dec 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -2545,9 +2545,21 @@ union bpf_attr {
* *th* points to the start of the TCP header, while *th_len*
* contains **sizeof**\ (**struct tcphdr**).
*
- * Return
- * 0 if *iph* and *th* are a valid SYN cookie ACK, or a negative
- * error otherwise.
+ * Return
+ * 0 if *iph* and *th* are a valid SYN cookie ACK, or a negative
+ * error otherwise.
+ *
+ * int bpf_udp_flow_src_port(struct sk_buff *skb, int min, int max, int use_eth)
+ * Description
+ * It's common to implement tunnelling inside a UDP protocol to provide
+ * additional randomness to the packet. The destination port of the UDP
+ * header indicates the inner packet type whereas the source port is used
+ * for additional entropy.
+ *
+ * Return
+ * An obfuscated hash of the packet that falls within the
+ * min & max port range.
+ * If min >= max, the default port range is used
*
* int bpf_sysctl_get_name(struct bpf_sysctl *ctx, char *buf, size_t buf_len, u64 flags)
* Description
@@ -2853,7 +2865,8 @@ union bpf_attr {
FN(sk_storage_get), \
FN(sk_storage_delete), \
FN(send_signal), \
- FN(tcp_gen_syncookie),
+ FN(tcp_gen_syncookie), \
+ FN(udp_flow_src_port),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
diff --git a/net/core/filter.c b/net/core/filter.c
index 5a2707918629..fdf0ebb8c2c8 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -2341,6 +2341,24 @@ static const struct bpf_func_proto bpf_msg_pull_data_proto = {
.arg4_type = ARG_ANYTHING,
};
+BPF_CALL_4(bpf_udp_flow_src_port, struct sk_buff *, skb, int, min,
+ int, max, int, use_eth)
+{
+ struct net *net = dev_net(skb->dev);
+
+ return udp_flow_src_port(net, skb, min, max, use_eth);
+}
+
+static const struct bpf_func_proto bpf_udp_flow_src_port_proto = {
+ .func = bpf_udp_flow_src_port,
+ .gpl_only = false,
+ .ret_type = RET_INTEGER,
+ .arg1_type = ARG_PTR_TO_CTX,
+ .arg2_type = ARG_ANYTHING,
+ .arg3_type = ARG_ANYTHING,
+ .arg4_type = ARG_ANYTHING,
+};
+
BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
u32, len, u64, flags)
{
@@ -6186,6 +6204,8 @@ tc_cls_act_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
return &bpf_sk_storage_get_proto;
case BPF_FUNC_sk_storage_delete:
return &bpf_sk_storage_delete_proto;
+ case BPF_FUNC_udp_flow_src_port:
+ return &bpf_udp_flow_src_port_proto;
#ifdef CONFIG_XFRM
case BPF_FUNC_skb_get_xfrm_state:
return &bpf_skb_get_xfrm_state_proto;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 4393bd4b2419..90e814153dec 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -2545,9 +2545,21 @@ union bpf_attr {
* *th* points to the start of the TCP header, while *th_len*
* contains **sizeof**\ (**struct tcphdr**).
*
- * Return
- * 0 if *iph* and *th* are a valid SYN cookie ACK, or a negative
- * error otherwise.
+ * Return
+ * 0 if *iph* and *th* are a valid SYN cookie ACK, or a negative
+ * error otherwise.
+ *
+ * int bpf_udp_flow_src_port(struct sk_buff *skb, int min, int max, int use_eth)
+ * Description
+ * It's common to implement tunnelling inside a UDP protocol to provide
+ * additional randomness to the packet. The destination port of the UDP
+ * header indicates the inner packet type whereas the source port is used
+ * for additional entropy.
+ *
+ * Return
+ * An obfuscated hash of the packet that falls within the
+ * min & max port range.
+ * If min >= max, the default port range is used
*
* int bpf_sysctl_get_name(struct bpf_sysctl *ctx, char *buf, size_t buf_len, u64 flags)
* Description
@@ -2853,7 +2865,8 @@ union bpf_attr {
FN(sk_storage_get), \
FN(sk_storage_delete), \
FN(send_signal), \
- FN(tcp_gen_syncookie),
+ FN(tcp_gen_syncookie), \
+ FN(udp_flow_src_port),
/* integer value in 'imm' field of BPF_CALL instruction selects which helper
* function eBPF program intends to call
diff --git a/tools/testing/selftests/bpf/bpf_helpers.h b/tools/testing/selftests/bpf/bpf_helpers.h
index 120aa86c58d3..385bfd8b7436 100644
--- a/tools/testing/selftests/bpf/bpf_helpers.h
+++ b/tools/testing/selftests/bpf/bpf_helpers.h
@@ -313,6 +313,8 @@ static unsigned int (*bpf_set_hash)(void *ctx, __u32 hash) =
static int (*bpf_skb_adjust_room)(void *ctx, __s32 len_diff, __u32 mode,
unsigned long long flags) =
(void *) BPF_FUNC_skb_adjust_room;
+static int (*bpf_udp_flow_src_port)(void *ctx, int min, int max, int use_eth) =
+ (void *) BPF_FUNC_udp_flow_src_port;
/* Scan the ARCH passed in from ARCH env variable (see Makefile) */
#if defined(__TARGET_ARCH_x86)
diff --git a/tools/testing/selftests/bpf/prog_tests/udp_flow_src_port.c b/tools/testing/selftests/bpf/prog_tests/udp_flow_src_port.c
new file mode 100644
index 000000000000..0f7303b51d1d
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/udp_flow_src_port.c
@@ -0,0 +1,28 @@
+#include <test_progs.h>
+#include <linux/pkt_cls.h>
+
+void test_udp_flow_src_port(void)
+{
+ const char *file = "./test_udp_flow_src_port_kern.o";
+ struct bpf_object *obj;
+ __u32 duration, retval, size;
+ int err, prog_fd;
+ char buf[128];
+ struct tcphdr *tcph = (void *)buf + sizeof(struct ethhdr) + sizeof(struct iphdr);
+
+ err = bpf_prog_load(file, BPF_PROG_TYPE_SCHED_CLS, &obj, &prog_fd);
+ if (err) {
+ error_cnt++;
+ return;
+ }
+
+ short original = tcph->source;
+
+ err = bpf_prog_test_run(prog_fd, 1, &pkt_v4, sizeof(pkt_v4),
+ buf, &size, &retval, &duration);
+ CHECK(err || retval != TC_ACT_OK || tcph->source == original, "ipv4",
+ "err %d errno %d retval %d sport %d duration %d\n",
+ err, errno, retval, tcph->source, duration);
+
+ bpf_object__close(obj);
+}
diff --git a/tools/testing/selftests/bpf/progs/test_udp_flow_src_port_kern.c b/tools/testing/selftests/bpf/progs/test_udp_flow_src_port_kern.c
new file mode 100644
index 000000000000..6238bd5fa856
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_udp_flow_src_port_kern.c
@@ -0,0 +1,47 @@
+#include <stddef.h>
+#include <stdbool.h>
+#include <string.h>
+#include <linux/bpf.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+#include <linux/pkt_cls.h>
+#include <linux/tcp.h>
+#include "bpf_helpers.h"
+#include "bpf_endian.h"
+
+int _version SEC("version") = 1;
+char _license[] SEC("license") = "GPL";
+
+SEC("skb_udp_flow")
+int process(struct __sk_buff *skb)
+{
+ void *data = (void *)(size_t)skb->data;
+ void *data_end = (void *)(size_t)skb->data_end;
+ /* Is it an Ethernet frame? */
+ struct ethhdr *ethernet_header = (struct ethhdr *)data;
+ data += sizeof(*ethernet_header);
+ if (data > data_end) {
+ return TC_ACT_SHOT;
+ }
+
+ struct iphdr *ip_header = (struct iphdr *)data;
+ data += sizeof(*ip_header);
+ if (data > data_end) {
+ return TC_ACT_SHOT;
+ }
+
+ struct tcphdr *tcp_header = (struct tcphdr*)data;
+ data += sizeof(*tcp_header);
+ if (data > data_end) {
+ return TC_ACT_SHOT;
+ }
+
+ //lets assign the calculated source port in the
+ // tcp packet and verify it in the test
+ int sport = bpf_udp_flow_src_port(skb, 0, 0, 0);
+ tcp_header->source = sport;
+
+ return TC_ACT_OK;
+}
--
2.21.0
next prev parent reply other threads:[~2019-08-03 4:44 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-03 4:43 [PATCH 0/1] bpf: introduce new helper udp_flow_src_port Farid Zakaria
2019-08-03 4:43 ` Farid Zakaria [this message]
2019-08-04 6:52 ` [PATCH 1/1] " Y Song
[not found] ` <CACCo2jmcYAfY8zHJiT7NCb-Ct7Wguk9XHRc8QmZa7V3eJy0WTg@mail.gmail.com>
2019-08-04 20:43 ` Farid Zakaria
2019-08-04 23:04 ` Y Song
2019-08-06 0:10 ` Jakub Kicinski
2019-08-08 18:48 ` Andrii Nakryiko
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=20190803044320.5530-2-farid.m.zakaria@gmail.com \
--to=farid.m.zakaria@gmail.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--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).