aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin KaFai Lau <martin.lau@kernel.org>2022-11-11 14:00:20 -0800
committerMartin KaFai Lau <martin.lau@kernel.org>2022-11-14 14:51:43 -0800
commitd2d2160958599732349aa30bb163d9d9a78cfe3a (patch)
tree65b9f2ca968d756f5eacbc3ab7bd91ce111f917b
parentde763fbb2c5bfad1ab7c4232e6a804726f0b0744 (diff)
downloadbpf-next-test_veth_perf.tar.gz
bpf: A veth perf testtest_veth_perf
A test that test the veth performance. To avoid the ip routing overhead, bpf_redirect_peer (phy-eth0 => veth) and bpf_redirect_neigh (veth => phy-eth0) is used. In particular, veth backlog queue performance is the interest here. eth0 (phy-nic) < -- > veth0 (host) < -- > veth_eth0 (netns) host: VETH_ETH0_ADDR6="ip6-addr-at-veth_eth0(netns)" VETH0_ADDR="ip6-addr-at-veth0(host)" ./test_progs -v -t veth_perf ... ... Press any key to cleanup: netns: ip netns exec ns_test bash # enter netns ./tcp_rr -6 -P 12345 -Q 64 -R 128 -l 30 -T 36 -U -F 1024 #run test server client: ./tcp_rr -c -H 2803:6080:c124:5ab::3 -P 12345 -Q 64 -R 128 -l 30 -T 36 -U -F 256 Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
-rw-r--r--tools/testing/selftests/bpf/prog_tests/veth_perf.c173
-rw-r--r--tools/testing/selftests/bpf/progs/veth_perf.c74
2 files changed, 247 insertions, 0 deletions
diff --git a/tools/testing/selftests/bpf/prog_tests/veth_perf.c b/tools/testing/selftests/bpf/prog_tests/veth_perf.c
new file mode 100644
index 00000000000000..f5238f5f93a8ef
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/veth_perf.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
+#define _GNU_SOURCE
+#include <sched.h>
+#include <net/if.h>
+#include "test_progs.h"
+#include "network_helpers.h"
+#include "veth_perf.skel.h"
+
+static int eth0_ifindex;
+static int veth0_ifindex;
+static int veth_eth0_ifindex;
+
+static const char *veth_eth0_addr6_str = "2803:6080:c124:5ab::3";
+static const char *veth0_addr6_str = "2803:6080:c124:5ab::2";
+static const char *veth_eth0_mac = "00:22:33:44:55:66";
+static const char *veth0_mac = "00:11:22:33:44:55";
+static __u32 veth_eth0_addr6[4];
+
+#define SYS(fmt, ...) \
+ ({ \
+ char cmd[1024]; \
+ snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
+ if (!ASSERT_OK(system(cmd), cmd)) \
+ goto fail; \
+ })
+
+#define PIN_FNAME(__file) "/sys/fs/bpf/" #__file
+#define PIN(__prog) ({ \
+ int err = bpf_program__pin(skel->progs.__prog, PIN_FNAME(__prog)); \
+ if (!ASSERT_OK(err, "pin " #__prog)) \
+ goto fail; \
+ })
+#define UNPIN(__prog) ({ bpf_program__unpin(skel->progs.__prog, PIN_FNAME(__prog)); })
+
+static int saved_netns = -1;
+
+static int switch_netns(const char *name)
+{
+ char nspath[PATH_MAX];
+ int err, nsfd;
+
+ if (!ASSERT_EQ(saved_netns, -1, "saved_netns"))
+ return -1;
+
+ saved_netns = open("/proc/self/ns/net", O_RDONLY);
+ if (!ASSERT_NEQ(saved_netns, -1, "open /proc/self/ns/net"))
+ return -1;
+
+ snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name);
+ nsfd = open(nspath, O_RDONLY | O_CLOEXEC);
+ if (!ASSERT_GE(nsfd, 0, "open netns fd")) {
+ saved_netns = -1;
+ return -1;
+ }
+
+ err = setns(nsfd, CLONE_NEWNET);
+ if (!ASSERT_OK(err, "setns")) {
+ saved_netns = -1;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int restore_netns(void)
+{
+ int err;
+
+ if (!ASSERT_NEQ(saved_netns, -1, "saved_netns"))
+ return -1;
+
+ err = setns(saved_netns, CLONE_NEWNET);
+ if (!ASSERT_OK(err, "setns_by_fd"))
+ return -1;
+
+ saved_netns = -1;
+ return 0;
+}
+
+static int setup_veth(void)
+{
+ SYS("ip link add veth0 type veth peer name veth_eth0");
+
+ eth0_ifindex = if_nametoindex("eth0");
+ if (!ASSERT_NEQ(eth0_ifindex, 0, "eth0_ifindex"))
+ goto fail;
+
+ veth0_ifindex = if_nametoindex("veth0");
+ if (!ASSERT_NEQ(veth0_ifindex, 0, "veth0_ifindex"))
+ goto fail;
+
+ veth_eth0_ifindex = if_nametoindex("veth_eth0");
+ if (!ASSERT_NEQ(veth_eth0_ifindex, 0, "veth_eth0_ifindex"))
+ goto fail;
+
+ SYS("ip link set veth0 address %s", veth0_mac);
+ SYS("ip -6 addr add %s/64 dev veth0 nodad", veth0_addr6_str);
+ SYS("ip link set dev veth0 up");
+
+ SYS("ip netns add ns_test");
+ SYS("ip link set dev veth_eth0 netns ns_test");
+
+ switch_netns("ns_test");
+ SYS("ip link set veth_eth0 address %s", veth_eth0_mac);
+ SYS("ip -6 addr add %s/64 dev veth_eth0 nodad", veth_eth0_addr6_str);
+ SYS("ip -6 neigh add %s dev veth_eth0 lladdr %s", veth0_addr6_str,
+ veth0_mac);
+ SYS("ip link set dev veth_eth0 up");
+ SYS("ip -6 route add default via %s dev veth_eth0", veth0_addr6_str);
+ restore_netns();
+
+ system("tc qdisc add dev eth0 clsact >& /dev/null");
+ SYS("tc filter add dev eth0 ingress prio 10 bpf da object-pinned "
+ PIN_FNAME(eth0_ingress));
+
+ SYS("tc qdisc add dev veth0 clsact");
+ SYS("tc filter add dev veth0 ingress prio 10 bpf da object-pinned "
+ PIN_FNAME(veth0_ingress));
+
+ return 0;
+fail:
+ system("ip netns del ns_test >& /dev/null");
+ system("ip link del veth0 >& /dev/null");
+ system("tc filter del ingress dev eth0 prio 10 >& /dev/null");
+ return -1;
+}
+
+void test_veth_perf(void)
+{
+ struct veth_perf *skel;
+ const char *addr6_str;
+ int err;
+ char c;
+
+ addr6_str = getenv("VETH_ETH0_ADDR6");
+ if (addr6_str)
+ veth_eth0_addr6_str = addr6_str;
+
+ addr6_str = getenv("VETH0_ADDR6");
+ if (addr6_str)
+ veth0_addr6_str = addr6_str;
+
+ err = inet_pton(AF_INET6, veth_eth0_addr6_str, veth_eth0_addr6);
+ if (!ASSERT_EQ(err, 1, "inet_pton"))
+ return;
+
+ skel = veth_perf__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel"))
+ return;
+ PIN(eth0_ingress);
+ PIN(veth0_ingress);
+
+ if (!ASSERT_OK(setup_veth(), "setup_veth"))
+ goto fail;
+
+ memcpy(skel->bss->veth_eth0_addr6, veth_eth0_addr6,
+ sizeof(veth_eth0_addr6));
+ skel->bss->eth0 = eth0_ifindex;
+ skel->bss->veth0 = veth0_ifindex;
+
+ printf("Press any key to cleanup: ");
+ scanf("%c", &c);
+
+ system("ip netns del ns_test");
+ system("ip link del veth0");
+ system("tc filter del ingress dev eth0 pref 10");
+
+fail:
+ UNPIN(eth0_ingress);
+ UNPIN(veth0_ingress);
+ veth_perf__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/veth_perf.c b/tools/testing/selftests/bpf/progs/veth_perf.c
new file mode 100644
index 00000000000000..4136c6769c76d6
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/veth_perf.c
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 Meta Platforms, Inc. and affiliates. */
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <linux/bpf.h>
+#include <linux/stddef.h>
+#include <linux/pkt_cls.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/ipv6.h>
+
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+#ifndef ctx_ptr
+# define ctx_ptr(field) (void *)(long)(field)
+#endif
+
+__u32 veth_eth0_addr6[4] = {};
+int veth0 = 0;
+int eth0 = 0;
+
+static bool v6_equal(__u32 *a, __u32 *b)
+{
+ return a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3];
+}
+
+SEC("tc")
+int veth0_ingress(struct __sk_buff *skb)
+{
+ void *data_end = ctx_ptr(skb->data_end);
+ void *data = ctx_ptr(skb->data);
+ struct ipv6hdr *ip6h;
+
+ if (skb->protocol != __bpf_constant_htons(ETH_P_IPV6))
+ return TC_ACT_OK;
+
+ if (data + sizeof(struct ethhdr) > data_end)
+ return TC_ACT_SHOT;
+
+ ip6h = (struct ipv6hdr *)(data + sizeof(struct ethhdr));
+ if ((void *)(ip6h + 1) > data_end)
+ return TC_ACT_SHOT;
+
+ return bpf_redirect_neigh(eth0, NULL, 0, 0);
+}
+
+SEC("tc")
+int eth0_ingress(struct __sk_buff *skb)
+{
+ void *data_end = ctx_ptr(skb->data_end);
+ void *data = ctx_ptr(skb->data);
+ struct ipv6hdr *ip6h;
+
+ if (skb->protocol != __bpf_constant_htons(ETH_P_IPV6))
+ return TC_ACT_UNSPEC;
+
+ if (data + sizeof(struct ethhdr) > data_end)
+ return TC_ACT_UNSPEC;
+
+ ip6h = (struct ipv6hdr *)(data + sizeof(struct ethhdr));
+ if ((void *)(ip6h + 1) > data_end)
+ return TC_ACT_UNSPEC;
+
+ if (!v6_equal(ip6h->daddr.s6_addr32, veth_eth0_addr6))
+ return TC_ACT_UNSPEC;
+
+ if (!veth0)
+ return TC_ACT_UNSPEC;
+
+ return bpf_redirect_peer(veth0, 0);
+}