All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: bpf@vger.kernel.org
Cc: "Kumar Kartikeya Dwivedi" <memxor@gmail.com>,
	"Alexei Starovoitov" <ast@kernel.org>,
	"Daniel Borkmann" <daniel@iogearbox.net>,
	"Andrii Nakryiko" <andrii@kernel.org>,
	"Jesper Dangaard Brouer" <brouer@redhat.com>,
	"Toke Høiland-Jørgensen" <toke@redhat.com>,
	netdev@vger.kernel.org
Subject: [PATCH bpf-next v2 3/8] samples: bpf: Add BPF support for XDP samples helper
Date: Thu, 22 Jul 2021 02:58:28 +0530	[thread overview]
Message-ID: <20210721212833.701342-4-memxor@gmail.com> (raw)
In-Reply-To: <20210721212833.701342-1-memxor@gmail.com>

These eBPF tracepoint programs export data that is consumed by the
helpers added in the previous commit.

Also add support int the Makefile to generate a vmlinux.h header that
would be used by other bpf.c files in later commits.

Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
---
 samples/bpf/Makefile         |  25 ++++
 samples/bpf/xdp_sample.bpf.c | 215 +++++++++++++++++++++++++++++++++++
 samples/bpf/xdp_sample.bpf.h |  57 ++++++++++
 3 files changed, 297 insertions(+)
 create mode 100644 samples/bpf/xdp_sample.bpf.c
 create mode 100644 samples/bpf/xdp_sample.bpf.h

diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index 57ccff5ccac4..52ac1c6b56e2 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -280,6 +280,11 @@ $(LIBBPF): FORCE
 	$(MAKE) -C $(dir $@) RM='rm -rf' EXTRA_CFLAGS="$(TPROGS_CFLAGS)" \
 		LDFLAGS=$(TPROGS_LDFLAGS) srctree=$(BPF_SAMPLES_PATH)/../../ O=
 
+BPFTOOLDIR := $(TOOLS_PATH)/bpf/bpftool
+BPFTOOL := $(BPFTOOLDIR)/bpftool
+$(BPFTOOL): $(wildcard $(BPFTOOLDIR)/*.[ch] $(BPFTOOLDIR)/Makefile)
+	    $(MAKE) -C $(BPFTOOLDIR) srctree=$(BPF_SAMPLES_PATH)/../../
+
 $(obj)/syscall_nrs.h:	$(obj)/syscall_nrs.s FORCE
 	$(call filechk,offsets,__SYSCALL_NRS_H__)
 
@@ -317,6 +322,26 @@ $(obj)/hbm_edt_kern.o: $(src)/hbm.h $(src)/hbm_kern.h
 
 -include $(BPF_SAMPLES_PATH)/Makefile.target
 
+VMLINUX_BTF_PATHS ?= $(if $(O),$(O)/vmlinux)				\
+		     $(if $(KBUILD_OUTPUT),$(KBUILD_OUTPUT)/vmlinux)	\
+		     ../../../../vmlinux				\
+		     /sys/kernel/btf/vmlinux				\
+		     /boot/vmlinux-$(shell uname -r)
+VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
+
+ifeq ($(VMLINUX_BTF),)
+$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)")
+endif
+
+$(obj)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL)
+ifeq ($(VMLINUX_H),)
+	$(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@
+else
+	$(Q)cp "$(VMLINUX_H)" $@
+endif
+
+clean-files += vmlinux.h
+
 # asm/sysreg.h - inline assembly used by it is incompatible with llvm.
 # But, there is no easy way to fix it, so just exclude it since it is
 # useless for BPF samples.
diff --git a/samples/bpf/xdp_sample.bpf.c b/samples/bpf/xdp_sample.bpf.c
new file mode 100644
index 000000000000..3359b4791ca4
--- /dev/null
+++ b/samples/bpf/xdp_sample.bpf.c
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: GPL-2.0
+/*  GPLv2, Copyright(c) 2017 Jesper Dangaard Brouer, Red Hat, Inc. */
+#include "xdp_sample.bpf.h"
+
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <bpf/bpf_helpers.h>
+
+struct sample_data sample_data;
+devmap_xmit_cnt_multi_t devmap_xmit_cnt_multi SEC(".maps");
+
+static __always_inline
+__u32 xdp_get_err_key(int err)
+{
+	switch (err) {
+	case 0:
+		return 0;
+	case -EINVAL:
+		return 2;
+	case -ENETDOWN:
+		return 3;
+	case -EMSGSIZE:
+		return 4;
+	case -EOPNOTSUPP:
+		return 5;
+	case -ENOSPC:
+		return 6;
+	default:
+		return 1;
+	}
+}
+
+static __always_inline
+int xdp_redirect_collect_stat(int err)
+{
+	u32 cpu = bpf_get_smp_processor_id();
+	u32 key = XDP_REDIRECT_ERROR;
+	struct datarec *rec;
+	u32 idx;
+
+	key = xdp_get_err_key(err);
+	idx = key * MAX_CPUS + cpu;
+
+	if (idx < 7 * MAX_CPUS) {
+		rec = &sample_data.redirect_err_cnt[idx];
+		if (key)
+			ATOMIC_INC_NORMW(rec->dropped);
+		else
+			ATOMIC_INC_NORMW(rec->processed);
+	}
+	return 0; /* Indicate event was filtered (no further processing)*/
+	/*
+	 * Returning 1 here would allow e.g. a perf-record tracepoint
+	 * to see and record these events, but it doesn't work well
+	 * in-practice as stopping perf-record also unload this
+	 * bpf_prog.  Plus, there is additional overhead of doing so.
+	 */
+}
+
+SEC("tp_btf/xdp_redirect_err")
+int BPF_PROG(tp_xdp_redirect_err, const struct net_device *dev,
+		 const struct bpf_prog *xdp,
+		 const void *tgt, int err,
+		 const struct bpf_map *map, u32 index)
+{
+	return xdp_redirect_collect_stat(err);
+}
+
+SEC("tp_btf/xdp_redirect_map_err")
+int BPF_PROG(tp_xdp_redirect_map_err, const struct net_device *dev,
+		 const struct bpf_prog *xdp,
+		 const void *tgt, int err,
+		 const struct bpf_map *map, u32 index)
+{
+	return xdp_redirect_collect_stat(err);
+}
+
+SEC("tp_btf/xdp_redirect")
+int BPF_PROG(tp_xdp_redirect, const struct net_device *dev,
+		 const struct bpf_prog *xdp,
+		 const void *tgt, int err,
+		 const struct bpf_map *map, u32 index)
+{
+	return xdp_redirect_collect_stat(err);
+}
+
+SEC("tp_btf/xdp_redirect_map")
+int BPF_PROG(tp_xdp_redirect_map, const struct net_device *dev,
+		 const struct bpf_prog *xdp,
+		 const void *tgt, int err,
+		 const struct bpf_map *map, u32 index)
+{
+	return xdp_redirect_collect_stat(err);
+}
+
+SEC("tp_btf/xdp_exception")
+int BPF_PROG(tp_xdp_exception, const struct net_device *dev,
+	     const struct bpf_prog *xdp, u32 act)
+{
+	u32 cpu = bpf_get_smp_processor_id();
+	struct datarec *rec;
+	u32 key = act, idx;
+
+	if (key > XDP_REDIRECT)
+		key = XDP_REDIRECT + 1;
+	idx = key * MAX_CPUS + cpu;
+
+	if (idx < 6 * MAX_CPUS) {
+		rec = &sample_data.exception_cnt[idx];
+		ATOMIC_INC_NORMW(rec->dropped);
+	}
+
+	return 0;
+}
+
+SEC("tp_btf/xdp_cpumap_enqueue")
+int BPF_PROG(tp_xdp_cpumap_enqueue, int map_id, unsigned int processed,
+	     unsigned int drops, int to_cpu)
+{
+	u32 cpu = bpf_get_smp_processor_id();
+	struct datarec *rec;
+	u32 idx;
+
+	idx = to_cpu * MAX_CPUS + cpu;
+
+	if (idx < MAX_CPUS * MAX_CPUS) {
+		rec = &sample_data.cpumap_enqueue_cnt[idx];
+
+		ATOMIC_ADD_NORMW(rec->processed, processed);
+		ATOMIC_ADD_NORMW(rec->dropped, drops);
+		/* Record bulk events, then userspace can calc average bulk size */
+		if (processed > 0)
+			ATOMIC_INC_NORMW(rec->issue);
+	}
+	/* Inception: It's possible to detect overload situations, via
+	 * this tracepoint.  This can be used for creating a feedback
+	 * loop to XDP, which can take appropriate actions to mitigate
+	 * this overload situation.
+	 */
+	return 0;
+}
+
+SEC("tp_btf/xdp_cpumap_kthread")
+int BPF_PROG(tp_xdp_cpumap_kthread, int map_id, unsigned int processed,
+	     unsigned int drops, int sched, struct xdp_cpumap_stats *xdp_stats)
+{
+	// Using xdp_stats directly fails verification
+	u32 cpu = bpf_get_smp_processor_id();
+	struct datarec *rec;
+
+	if (cpu < MAX_CPUS) {
+		rec = &sample_data.cpumap_kthread_cnt[cpu];
+
+		ATOMIC_ADD_NORMW(rec->processed, processed);
+		ATOMIC_ADD_NORMW(rec->dropped, drops);
+		ATOMIC_ADD_NORMW(rec->xdp_pass, xdp_stats->pass);
+		ATOMIC_ADD_NORMW(rec->xdp_drop, xdp_stats->drop);
+		ATOMIC_ADD_NORMW(rec->xdp_redirect, xdp_stats->redirect);
+		/* Count times kthread yielded CPU via schedule call */
+		if (sched)
+			ATOMIC_INC_NORMW(rec->issue);
+	}
+	return 0;
+}
+
+SEC("tp_btf/xdp_devmap_xmit")
+int BPF_PROG(tp_xdp_devmap_xmit, const struct net_device *from_dev,
+	     const struct net_device *to_dev, int sent, int drops, int err)
+{
+	u32 cpu = bpf_get_smp_processor_id();
+	struct datarec *rec;
+
+	if (cpu < MAX_CPUS) {
+		rec = &sample_data.devmap_xmit_cnt[cpu];
+
+		ATOMIC_ADD_NORMW(rec->processed, sent);
+		ATOMIC_ADD_NORMW(rec->dropped, drops);
+		/* Record bulk events, then userspace can calc average bulk size */
+		ATOMIC_INC_NORMW(rec->info);
+		/* Record error cases, where no frame were sent */
+		/* Catch API error of drv ndo_xdp_xmit sent more than count */
+		if (err || drops < 0)
+			ATOMIC_INC_NORMW(rec->issue);
+	}
+	return 0;
+}
+
+SEC("tp_btf/xdp_devmap_xmit")
+int BPF_PROG(tp_xdp_devmap_xmit_multi, const struct net_device *from_dev,
+	     const struct net_device *to_dev, int sent, int drops, int err)
+{
+	struct datarec empty = {};
+	struct datarec *rec;
+	int idx_in, idx_out;
+	u64 idx;
+
+	idx_in = from_dev->ifindex;
+	idx_out = to_dev->ifindex;
+	idx = idx_in;
+	idx = idx << 32 | idx_out;
+
+	bpf_map_update_elem(&devmap_xmit_cnt_multi, &idx, &empty, BPF_NOEXIST);
+	rec = bpf_map_lookup_elem(&devmap_xmit_cnt_multi, &idx);
+	if (!rec)
+		return 0;
+
+	ATOMIC_ADD_NORMW(rec->processed, sent);
+	ATOMIC_ADD_NORMW(rec->dropped, drops);
+	ATOMIC_INC_NORMW(rec->info);
+
+	if (err || drops < 0)
+		ATOMIC_INC_NORMW(rec->issue);
+
+	return 0;
+}
diff --git a/samples/bpf/xdp_sample.bpf.h b/samples/bpf/xdp_sample.bpf.h
new file mode 100644
index 000000000000..20fbafe28be5
--- /dev/null
+++ b/samples/bpf/xdp_sample.bpf.h
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+#ifndef _XDP_SAMPLE_BPF_H
+#define _XDP_SAMPLE_BPF_H
+
+#include "vmlinux.h"
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include <bpf/bpf_helpers.h>
+
+#include "xdp_sample_shared.h"
+
+#define ETH_ALEN 6
+#define ETH_P_802_3_MIN 0x0600
+#define ETH_P_8021Q 0x8100
+#define ETH_P_8021AD 0x88A8
+#define ETH_P_IP 0x0800
+#define ETH_P_IPV6 0x86DD
+#define ETH_P_ARP 0x0806
+#define IPPROTO_ICMPV6 58
+
+#define EINVAL 22
+#define ENETDOWN 100
+#define EMSGSIZE 90
+#define EOPNOTSUPP 95
+#define ENOSPC 28
+
+extern struct sample_data sample_data;
+
+typedef struct {
+	__uint(type, BPF_MAP_TYPE_PERCPU_HASH);
+	__uint(max_entries, 32);
+	__type(key, u64);
+	__type(value, struct datarec);
+} devmap_xmit_cnt_multi_t;
+
+enum {
+	XDP_REDIRECT_SUCCESS = 0,
+	XDP_REDIRECT_ERROR = 1
+};
+
+static __always_inline void swap_src_dst_mac(void *data)
+{
+	unsigned short *p = data;
+	unsigned short dst[3];
+
+	dst[0] = p[0];
+	dst[1] = p[1];
+	dst[2] = p[2];
+	p[0] = p[3];
+	p[1] = p[4];
+	p[2] = p[5];
+	p[3] = dst[0];
+	p[4] = dst[1];
+	p[5] = dst[2];
+}
+
+#endif
-- 
2.32.0


  parent reply	other threads:[~2021-07-21 21:28 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-21 21:28 [PATCH bpf-next v2 0/8] Improve XDP samples usability and output Kumar Kartikeya Dwivedi
2021-07-21 21:28 ` [PATCH bpf-next v2 1/8] samples: bpf: fix a couple of warnings Kumar Kartikeya Dwivedi
2021-07-21 21:28 ` [PATCH bpf-next v2 2/8] samples: bpf: Add common infrastructure for XDP samples Kumar Kartikeya Dwivedi
2021-07-23  3:34   ` Andrii Nakryiko
2021-07-21 21:28 ` Kumar Kartikeya Dwivedi [this message]
2021-07-23  3:42   ` [PATCH bpf-next v2 3/8] samples: bpf: Add BPF support for XDP samples helper Andrii Nakryiko
2021-07-21 21:28 ` [PATCH bpf-next v2 4/8] samples: bpf: Convert xdp_monitor to use " Kumar Kartikeya Dwivedi
2021-07-21 21:28 ` [PATCH bpf-next v2 5/8] samples: bpf: Convert xdp_redirect " Kumar Kartikeya Dwivedi
2021-07-23  3:49   ` Andrii Nakryiko
2021-07-21 21:28 ` [PATCH bpf-next v2 6/8] samples: bpf: Convert xdp_redirect_map to use XDP samples helpers Kumar Kartikeya Dwivedi
2021-07-21 21:28 ` [PATCH bpf-next v2 7/8] samples: bpf: Convert xdp_redirect_map_multi " Kumar Kartikeya Dwivedi
2021-07-21 21:28 ` [PATCH bpf-next v2 8/8] samples: bpf: Convert xdp_redirect_cpu " Kumar Kartikeya Dwivedi
2021-07-23 21:32 ` [PATCH bpf-next v2 0/8] Improve XDP samples usability and output Toke Høiland-Jørgensen

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=20210721212833.701342-4-memxor@gmail.com \
    --to=memxor@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=brouer@redhat.com \
    --cc=daniel@iogearbox.net \
    --cc=netdev@vger.kernel.org \
    --cc=toke@redhat.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.