mirror of
https://github.com/eunomia-bpf/bpf-developer-tutorial.git
synced 2026-02-03 02:04:30 +08:00
update 43 for xdp test
This commit is contained in:
@@ -393,7 +393,7 @@ Assuming you have a user-space application or a tool to load and attach the eBPF
|
||||
**Sample Output:**
|
||||
|
||||
```bash
|
||||
# sudo ./load_kfunc
|
||||
# sudo ./kfunc
|
||||
BPF program loaded and attached successfully. Press Ctrl-C to exit.
|
||||
```
|
||||
|
||||
|
||||
@@ -393,7 +393,7 @@ int handle_kprobe(struct pt_regs *ctx)
|
||||
**示例输出:**
|
||||
|
||||
```bash
|
||||
# sudo ./load_kfunc
|
||||
# sudo ./kfunc
|
||||
BPF 程序已加载并成功附加。按 Ctrl-C 退出。
|
||||
```
|
||||
|
||||
|
||||
3
src/46-xdp-test/.gitignore
vendored
Normal file
3
src/46-xdp-test/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/.output
|
||||
/bootstrap
|
||||
xdp-pktgen
|
||||
141
src/46-xdp-test/Makefile
Normal file
141
src/46-xdp-test/Makefile
Normal file
@@ -0,0 +1,141 @@
|
||||
# SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
OUTPUT := .output
|
||||
CLANG ?= clang
|
||||
LIBBPF_SRC := $(abspath ../third_party/libbpf/src)
|
||||
BPFTOOL_SRC := $(abspath ../third_party/bpftool/src)
|
||||
LIBBPF_OBJ := $(abspath $(OUTPUT)/libbpf.a)
|
||||
BPFTOOL_OUTPUT ?= $(abspath $(OUTPUT)/bpftool)
|
||||
BPFTOOL ?= $(BPFTOOL_OUTPUT)/bootstrap/bpftool
|
||||
LIBBLAZESYM_SRC := $(abspath ../third_party/blazesym/)
|
||||
LIBBLAZESYM_OBJ := $(abspath $(OUTPUT)/libblazesym.a)
|
||||
LIBBLAZESYM_HEADER := $(abspath $(OUTPUT)/blazesym.h)
|
||||
ARCH ?= $(shell uname -m | sed 's/x86_64/x86/' \
|
||||
| sed 's/arm.*/arm/' \
|
||||
| sed 's/aarch64/arm64/' \
|
||||
| sed 's/ppc64le/powerpc/' \
|
||||
| sed 's/mips.*/mips/' \
|
||||
| sed 's/riscv64/riscv/' \
|
||||
| sed 's/loongarch64/loongarch/')
|
||||
VMLINUX := ../third_party/vmlinux/$(ARCH)/vmlinux.h
|
||||
# Use our own libbpf API headers and Linux UAPI headers distributed with
|
||||
# libbpf to avoid dependency on system-wide headers, which could be missing or
|
||||
# outdated
|
||||
INCLUDES := -I$(OUTPUT) -I../third_party/libbpf/include/uapi -I$(dir $(VMLINUX))
|
||||
CFLAGS := -g -Wall
|
||||
ALL_LDFLAGS := $(LDFLAGS) $(EXTRA_LDFLAGS)
|
||||
|
||||
APPS = xdp-pktgen # minimal minimal_legacy uprobe kprobe fentry usdt sockfilter tc ksyscall
|
||||
|
||||
CARGO ?= $(shell which cargo)
|
||||
ifeq ($(strip $(CARGO)),)
|
||||
BZS_APPS :=
|
||||
else
|
||||
BZS_APPS := # profile
|
||||
APPS += $(BZS_APPS)
|
||||
# Required by libblazesym
|
||||
ALL_LDFLAGS += -lrt -ldl -lpthread -lm
|
||||
endif
|
||||
|
||||
# Get Clang's default includes on this system. We'll explicitly add these dirs
|
||||
# to the includes list when compiling with `-target bpf` because otherwise some
|
||||
# architecture-specific dirs will be "missing" on some architectures/distros -
|
||||
# headers such as asm/types.h, asm/byteorder.h, asm/socket.h, asm/sockios.h,
|
||||
# sys/cdefs.h etc. might be missing.
|
||||
#
|
||||
# Use '-idirafter': Don't interfere with include mechanics except where the
|
||||
# build would have failed anyways.
|
||||
CLANG_BPF_SYS_INCLUDES ?= $(shell $(CLANG) -v -E - </dev/null 2>&1 \
|
||||
| sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }')
|
||||
|
||||
ifeq ($(V),1)
|
||||
Q =
|
||||
msg =
|
||||
else
|
||||
Q = @
|
||||
msg = @printf ' %-8s %s%s\n' \
|
||||
"$(1)" \
|
||||
"$(patsubst $(abspath $(OUTPUT))/%,%,$(2))" \
|
||||
"$(if $(3), $(3))";
|
||||
MAKEFLAGS += --no-print-directory
|
||||
endif
|
||||
|
||||
define allow-override
|
||||
$(if $(or $(findstring environment,$(origin $(1))),\
|
||||
$(findstring command line,$(origin $(1)))),,\
|
||||
$(eval $(1) = $(2)))
|
||||
endef
|
||||
|
||||
$(call allow-override,CC,$(CROSS_COMPILE)cc)
|
||||
$(call allow-override,LD,$(CROSS_COMPILE)ld)
|
||||
|
||||
.PHONY: all
|
||||
all: $(APPS)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(call msg,CLEAN)
|
||||
$(Q)rm -rf $(OUTPUT) $(APPS)
|
||||
|
||||
$(OUTPUT) $(OUTPUT)/libbpf $(BPFTOOL_OUTPUT):
|
||||
$(call msg,MKDIR,$@)
|
||||
$(Q)mkdir -p $@
|
||||
|
||||
# Build libbpf
|
||||
$(LIBBPF_OBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUTPUT)/libbpf
|
||||
$(call msg,LIB,$@)
|
||||
$(Q)$(MAKE) -C $(LIBBPF_SRC) BUILD_STATIC_ONLY=1 \
|
||||
OBJDIR=$(dir $@)/libbpf DESTDIR=$(dir $@) \
|
||||
INCLUDEDIR= LIBDIR= UAPIDIR= \
|
||||
install
|
||||
|
||||
# Build bpftool
|
||||
$(BPFTOOL): | $(BPFTOOL_OUTPUT)
|
||||
$(call msg,BPFTOOL,$@)
|
||||
$(Q)$(MAKE) ARCH= CROSS_COMPILE= OUTPUT=$(BPFTOOL_OUTPUT)/ -C $(BPFTOOL_SRC) bootstrap
|
||||
|
||||
|
||||
$(LIBBLAZESYM_SRC)/target/release/libblazesym.a::
|
||||
$(Q)cd $(LIBBLAZESYM_SRC) && $(CARGO) build --features=cheader,dont-generate-test-files --release
|
||||
|
||||
$(LIBBLAZESYM_OBJ): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT)
|
||||
$(call msg,LIB, $@)
|
||||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/libblazesym.a $@
|
||||
|
||||
$(LIBBLAZESYM_HEADER): $(LIBBLAZESYM_SRC)/target/release/libblazesym.a | $(OUTPUT)
|
||||
$(call msg,LIB,$@)
|
||||
$(Q)cp $(LIBBLAZESYM_SRC)/target/release/blazesym.h $@
|
||||
|
||||
# Build BPF code
|
||||
$(OUTPUT)/%.bpf.o: %.bpf.c $(LIBBPF_OBJ) $(wildcard %.h) $(VMLINUX) | $(OUTPUT) $(BPFTOOL)
|
||||
$(call msg,BPF,$@)
|
||||
$(Q)$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \
|
||||
$(INCLUDES) $(CLANG_BPF_SYS_INCLUDES) \
|
||||
-c $(filter %.c,$^) -o $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
|
||||
$(Q)$(BPFTOOL) gen object $@ $(patsubst %.bpf.o,%.tmp.bpf.o,$@)
|
||||
|
||||
# Generate BPF skeletons
|
||||
$(OUTPUT)/%.skel.h: $(OUTPUT)/%.bpf.o | $(OUTPUT) $(BPFTOOL)
|
||||
$(call msg,GEN-SKEL,$@)
|
||||
$(Q)$(BPFTOOL) gen skeleton $< > $@
|
||||
|
||||
# Build user-space code
|
||||
$(patsubst %,$(OUTPUT)/%.o,$(APPS)): %.o: %.skel.h
|
||||
|
||||
$(OUTPUT)/%.o: %.c $(wildcard %.h) | $(OUTPUT)
|
||||
$(call msg,CC,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@
|
||||
|
||||
$(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_HEADER)
|
||||
|
||||
$(BZS_APPS): $(LIBBLAZESYM_OBJ)
|
||||
|
||||
# Build application binary
|
||||
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT)
|
||||
$(call msg,BINARY,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@
|
||||
|
||||
# delete failed targets
|
||||
.DELETE_ON_ERROR:
|
||||
|
||||
# keep intermediate (.skel.h, .bpf.o, etc) targets
|
||||
.SECONDARY:
|
||||
44
src/46-xdp-test/README.md
Normal file
44
src/46-xdp-test/README.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# xdp-pktgen: xdp based packet generator
|
||||
|
||||
This is a simple xdp based packet generator.
|
||||
|
||||
## **How to use**
|
||||
|
||||
clone the repo, you can update the git submodule with following commands:
|
||||
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### **3. Install dependencies**
|
||||
|
||||
For dependencies, it varies from distribution to distribution. You can refer to shell.nix and dockerfile for installation.
|
||||
|
||||
On Ubuntu, you may run `make install` or
|
||||
|
||||
```sh
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
libelf1 libelf-dev zlib1g-dev \
|
||||
make clang llvm
|
||||
```
|
||||
|
||||
to install dependencies.
|
||||
|
||||
### **4. Build the project**
|
||||
|
||||
To build the project, run the following command:
|
||||
|
||||
```sh
|
||||
make build
|
||||
```
|
||||
|
||||
This will compile your code and create the necessary binaries. You can you the `Github Code space` or `Github Action` to build the project as well.
|
||||
|
||||
### ***Run the Project***
|
||||
|
||||
You can run the binary with:
|
||||
|
||||
```console
|
||||
sudo ./xdp-pktgen
|
||||
```
|
||||
|
||||
44
src/46-xdp-test/README.zh.md
Normal file
44
src/46-xdp-test/README.zh.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# xdp-pktgen: xdp based packet generator
|
||||
|
||||
This is a simple xdp based packet generator.
|
||||
|
||||
## **How to use**
|
||||
|
||||
clone the repo, you can update the git submodule with following commands:
|
||||
|
||||
```sh
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
### **3. Install dependencies**
|
||||
|
||||
For dependencies, it varies from distribution to distribution. You can refer to shell.nix and dockerfile for installation.
|
||||
|
||||
On Ubuntu, you may run `make install` or
|
||||
|
||||
```sh
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
libelf1 libelf-dev zlib1g-dev \
|
||||
make clang llvm
|
||||
```
|
||||
|
||||
to install dependencies.
|
||||
|
||||
### **4. Build the project**
|
||||
|
||||
To build the project, run the following command:
|
||||
|
||||
```sh
|
||||
make build
|
||||
```
|
||||
|
||||
This will compile your code and create the necessary binaries. You can you the `Github Code space` or `Github Action` to build the project as well.
|
||||
|
||||
### ***Run the Project***
|
||||
|
||||
You can run the binary with:
|
||||
|
||||
```console
|
||||
sudo ./xdp-pktgen
|
||||
```
|
||||
|
||||
114
src/46-xdp-test/test_udp_pkt.h
Normal file
114
src/46-xdp-test/test_udp_pkt.h
Normal file
@@ -0,0 +1,114 @@
|
||||
#ifndef TEST_UDP_PKT_H
|
||||
#define TEST_UDP_PKT_H
|
||||
|
||||
#include <net/if.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/in.h>
|
||||
#include <linux/udp.h>
|
||||
#include <arpa/inet.h> // For inet_addr()
|
||||
#include <string.h> // For memcpy, memset
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <linux/netdev.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define PORT 9876
|
||||
#define SERVER_IP "127.0.0.1"
|
||||
|
||||
// Define packet structures first
|
||||
struct test_udp_packet {
|
||||
struct ethhdr eth;
|
||||
struct ipv6hdr iph;
|
||||
struct udphdr udp;
|
||||
__u8 payload[64 - sizeof(struct udphdr) - sizeof(struct ethhdr) - sizeof(struct ipv6hdr)];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct test_udp_packet_v4 {
|
||||
struct ethhdr eth;
|
||||
struct iphdr iph;
|
||||
struct udphdr udp;
|
||||
uint8_t payload[64 - sizeof(struct udphdr) - sizeof(struct ethhdr) - sizeof(struct iphdr)];
|
||||
} __attribute__((packed));
|
||||
|
||||
// Helper function declarations
|
||||
static uint16_t ip_checksum(void *vdata, size_t length);
|
||||
static __be16 __calc_udp_cksum(const struct test_udp_packet *pkt);
|
||||
|
||||
// Helper function implementations
|
||||
static uint16_t ip_checksum(void *vdata, size_t length) {
|
||||
char *data = vdata;
|
||||
uint64_t acc = 0xffff;
|
||||
|
||||
for (size_t i = 0; i + 1 < length; i += 2) {
|
||||
uint16_t word;
|
||||
memcpy(&word, data + i, 2);
|
||||
acc += ntohs(word);
|
||||
if (acc > 0xffff) {
|
||||
acc -= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
if (length & 1) {
|
||||
uint16_t word = 0;
|
||||
memcpy(&word, data + length - 1, 1);
|
||||
acc += ntohs(word);
|
||||
if (acc > 0xffff) {
|
||||
acc -= 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
return htons(~acc);
|
||||
}
|
||||
|
||||
static __be16 __calc_udp_cksum(const struct test_udp_packet *pkt) {
|
||||
__u32 chksum = pkt->iph.nexthdr + bpf_ntohs(pkt->iph.payload_len);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
chksum += bpf_ntohs(pkt->iph.saddr.s6_addr16[i]);
|
||||
chksum += bpf_ntohs(pkt->iph.daddr.s6_addr16[i]);
|
||||
}
|
||||
chksum += bpf_ntohs(pkt->udp.source);
|
||||
chksum += bpf_ntohs(pkt->udp.dest);
|
||||
chksum += bpf_ntohs(pkt->udp.len);
|
||||
|
||||
while (chksum >> 16)
|
||||
chksum = (chksum & 0xFFFF) + (chksum >> 16);
|
||||
return bpf_htons(~chksum);
|
||||
}
|
||||
|
||||
static struct test_udp_packet_v4 create_test_udp_packet_v4(void) {
|
||||
struct test_udp_packet_v4 pkt = {0};
|
||||
|
||||
// Ethernet header
|
||||
pkt.eth.h_proto = htons(ETH_P_IP);
|
||||
memcpy(pkt.eth.h_dest, (const unsigned char[]){0xb8, 0x3f, 0xd2, 0x2a, 0xe5, 0x11}, sizeof(pkt.eth.h_dest));
|
||||
memcpy(pkt.eth.h_source, (const unsigned char[]){0xb8, 0x3f, 0xd2, 0x2a, 0xe7, 0x69}, sizeof(pkt.eth.h_source));
|
||||
|
||||
// IPv4 header
|
||||
pkt.iph.version = 4;
|
||||
pkt.iph.ihl = 5;
|
||||
pkt.iph.tot_len = htons(sizeof(struct test_udp_packet_v4) - sizeof(struct ethhdr));
|
||||
pkt.iph.ttl = 64; // default TTL
|
||||
pkt.iph.protocol = IPPROTO_UDP;
|
||||
pkt.iph.saddr = inet_addr(SERVER_IP);
|
||||
pkt.iph.daddr = inet_addr(SERVER_IP);
|
||||
pkt.iph.check = ip_checksum(&pkt.iph, sizeof(struct iphdr));
|
||||
|
||||
// UDP header
|
||||
pkt.udp.source = htons(12345);
|
||||
pkt.udp.dest = htons(PORT);
|
||||
pkt.udp.len = htons(sizeof(struct udphdr) + sizeof(pkt.payload));
|
||||
pkt.udp.check = 0; // Optional for IPv4
|
||||
|
||||
// Payload
|
||||
memset(pkt.payload, 0x42, sizeof(pkt.payload));
|
||||
|
||||
return pkt;
|
||||
}
|
||||
|
||||
#endif // TEST_UDP_PKT_H
|
||||
12
src/46-xdp-test/xdp-pktgen.bpf.c
Normal file
12
src/46-xdp-test/xdp-pktgen.bpf.c
Normal file
@@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
#include "vmlinux.h"
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
||||
SEC("xdp")
|
||||
int xdp_redirect_notouch(struct xdp_md *ctx)
|
||||
{
|
||||
return XDP_TX;
|
||||
}
|
||||
172
src/46-xdp-test/xdp-pktgen.c
Normal file
172
src/46-xdp-test/xdp-pktgen.c
Normal file
@@ -0,0 +1,172 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <net/if.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#include <bpf/bpf.h>
|
||||
#include <bpf/bpf_endian.h>
|
||||
#include <bpf/libbpf.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/if_link.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if_packet.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/in6.h>
|
||||
#include "xdp-pktgen.skel.h"
|
||||
#include "test_udp_pkt.h"
|
||||
|
||||
#ifndef BPF_F_TEST_XDP_LIVE_FRAMES
|
||||
#define BPF_F_TEST_XDP_LIVE_FRAMES (1U << 1)
|
||||
#endif
|
||||
|
||||
static volatile bool exiting = false;
|
||||
|
||||
static void sig_handler(int sig)
|
||||
{
|
||||
exiting = true;
|
||||
}
|
||||
|
||||
struct config {
|
||||
int ifindex;
|
||||
int xdp_flags;
|
||||
int repeat;
|
||||
int batch_size;
|
||||
};
|
||||
|
||||
struct config cfg = {
|
||||
.ifindex = 6,
|
||||
.repeat = 1 << 20,
|
||||
.batch_size = 0,
|
||||
};
|
||||
|
||||
static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args)
|
||||
{
|
||||
return vfprintf(stderr, format, args);
|
||||
}
|
||||
|
||||
static int run_prog(int run_prog_fd, int count)
|
||||
{
|
||||
// struct test_udp_packet pkt_udp = create_test_udp_packet_v6();
|
||||
char* pkt_file = NULL;
|
||||
unsigned char pkt_file_buffer[1024];
|
||||
int size = 0;
|
||||
if ((pkt_file = getenv("PKTGEN_FILE")) != NULL) {
|
||||
FILE* file = fopen(pkt_file, "r");
|
||||
if (file == NULL) {
|
||||
printf("Error opening file\n");
|
||||
return -1;
|
||||
}
|
||||
// read the the file length of data into the buffer
|
||||
size = fread(pkt_file_buffer, 1, 1024, file);
|
||||
fclose(file);
|
||||
} else {
|
||||
struct test_udp_packet_v4 pkt_udp = create_test_udp_packet_v4();
|
||||
size = sizeof(pkt_udp);
|
||||
memcpy(pkt_file_buffer, &pkt_udp, size);
|
||||
}
|
||||
struct xdp_md ctx_in = {
|
||||
.data_end = size,
|
||||
.ingress_ifindex = cfg.ifindex
|
||||
};
|
||||
// struct xdp_md ctx_in_array[64];
|
||||
// for (int i = 0; i < 64; i++) {
|
||||
// ctx_in_array[i].data_end = sizeof(pkt_udp);
|
||||
// ctx_in_array[i].ingress_ifindex = cfg.ifindex;
|
||||
// }
|
||||
|
||||
printf("pkt size: %ld\n", size);
|
||||
DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
|
||||
.data_in = pkt_file_buffer,
|
||||
.data_size_in = size,
|
||||
.ctx_in = &ctx_in,
|
||||
.ctx_size_in = sizeof(ctx_in),
|
||||
.repeat = cfg.repeat,
|
||||
.flags = BPF_F_TEST_XDP_LIVE_FRAMES,
|
||||
.batch_size = cfg.batch_size,
|
||||
.cpu = 0,
|
||||
);
|
||||
__u64 iterations = 0;
|
||||
cpu_set_t cpu_cores;
|
||||
int err;
|
||||
|
||||
CPU_ZERO(&cpu_cores);
|
||||
CPU_SET(0, &cpu_cores);
|
||||
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu_cores);
|
||||
do {
|
||||
err = bpf_prog_test_run_opts(run_prog_fd, &opts);
|
||||
if (err)
|
||||
return -errno;
|
||||
iterations += opts.repeat;
|
||||
} while ((count == 0 || iterations < count) && !exiting);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int probe_kernel_support(int run_prog_fd)
|
||||
{
|
||||
int err = run_prog(run_prog_fd, 1);
|
||||
if (err == -EOPNOTSUPP) {
|
||||
printf("BPF_PROG_RUN with batch size support is missing from libbpf.\n");
|
||||
} else if (err == -EINVAL) {
|
||||
err = -EOPNOTSUPP;
|
||||
printf("Kernel doesn't support live packet mode for XDP BPF_PROG_RUN.\n");
|
||||
} else if (err) {
|
||||
printf("Error probing kernel support: %s\n", strerror(-err));
|
||||
} else {
|
||||
printf("Kernel supports live packet mode for XDP BPF_PROG_RUN.\n");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
struct xdp_pktgen_bpf *skel = NULL;
|
||||
int err = 0;
|
||||
__u32 key = 0;
|
||||
|
||||
/* Set up libbpf errors and debug info callback */
|
||||
libbpf_set_print(libbpf_print_fn);
|
||||
/* Cleaner handling of Ctrl-C */
|
||||
signal(SIGINT, sig_handler);
|
||||
signal(SIGTERM, sig_handler);
|
||||
|
||||
skel = xdp_pktgen_bpf__open();
|
||||
if (!skel) {
|
||||
err = -errno;
|
||||
printf("Couldn't open XDP program: %s\n", strerror(-err));
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = xdp_pktgen_bpf__load(skel);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
int run_prog_fd = bpf_program__fd(skel->progs.xdp_redirect_notouch);
|
||||
// probe kernel support for BPF_PROG_RUN
|
||||
err = probe_kernel_support(run_prog_fd);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = run_prog(run_prog_fd, 0);
|
||||
if (err) {
|
||||
printf("run xdp program error: %d\n", err);
|
||||
}
|
||||
|
||||
out:
|
||||
xdp_pktgen_bpf__destroy(skel);
|
||||
return err;
|
||||
}
|
||||
@@ -211,8 +211,8 @@ def generate_toc_cn(base_dir, project_root):
|
||||
return toc
|
||||
|
||||
# Example usage
|
||||
base_directory = "/root/bpf-developer-tutorial/src/" # Replace with the actual base directory
|
||||
project_root = "/root/bpf-developer-tutorial/" # The root of the project
|
||||
base_directory = "src/" # Replace with the actual base directory
|
||||
project_root = "./" # The root of the project
|
||||
toc_output = generate_toc(base_directory, project_root)
|
||||
# toc_output = generate_toc_cn(base_directory, project_root)
|
||||
# Output the TOC
|
||||
|
||||
Reference in New Issue
Block a user