From eb8a0da45bdb3bed2fd6052088eddf4c54499688 Mon Sep 17 00:00:00 2001 From: xiaozhangchannel Date: Mon, 3 Jun 2024 19:18:53 +0800 Subject: [PATCH] common --- .../net_manager/common/Makefile | 18 ++ .../net_manager/common/README.org | 8 + .../net_manager/common/common.mk | 128 ++++++++ .../net_manager/common/common_defines.h | 49 +++ .../net_manager/common/common_libbpf.c | 162 ++++++++++ .../net_manager/common/common_libbpf.h | 24 ++ .../net_manager/common/common_params.c | 299 ++++++++++++++++++ .../net_manager/common/common_params.h | 22 ++ .../net_manager/common/common_params.o | Bin 0 -> 35472 bytes .../net_manager/common/common_user_bpf_xdp.c | 289 +++++++++++++++++ .../net_manager/common/common_user_bpf_xdp.h | 18 ++ .../net_manager/common/common_user_bpf_xdp.o | Bin 0 -> 32768 bytes .../net_manager/common/parsing_helpers.h | 272 ++++++++++++++++ .../net_manager/common/rewrite_helpers.h | 144 +++++++++ .../net_manager/common/xdp_stats_kern.h | 44 +++ .../net_manager/common/xdp_stats_kern_user.h | 19 ++ 16 files changed, 1496 insertions(+) create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/Makefile create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/README.org create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common.mk create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_defines.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.c create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.c create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.o create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.c create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.o create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/parsing_helpers.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/rewrite_helpers.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern.h create mode 100644 eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern_user.h diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/Makefile b/eBPF_Supermarket/Network_Subsystem/net_manager/common/Makefile new file mode 100644 index 000000000..ab8a7457a --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: (GPL-2.0) +LIB_DIR = ../lib +include $(LIB_DIR)/defines.mk + +all: common_params.o common_user_bpf_xdp.o + +CFLAGS += -I$(LIB_DIR)/install/include + +common_params.o: common_params.c common_params.h + $(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $< + +common_user_bpf_xdp.o: common_user_bpf_xdp.c common_user_bpf_xdp.h + $(QUIET_CC)$(CC) $(CFLAGS) -c -o $@ $< + +.PHONY: clean + +clean: + $(Q)rm -f *.o diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/README.org b/eBPF_Supermarket/Network_Subsystem/net_manager/common/README.org new file mode 100644 index 000000000..561fdbced --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/README.org @@ -0,0 +1,8 @@ +# -*- fill-column: 76; -*- +#+TITLE: Common files +#+OPTIONS: ^:nil + +This directory contains code that is common between the different +assignments. This reduce code duplication in each tutorial assignment, and +allow us to hideaway code that is irrelevant or have been seen/introduced in +earlier assignments. diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common.mk b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common.mk new file mode 100644 index 000000000..094c6c0c4 --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common.mk @@ -0,0 +1,128 @@ +# Common Makefile parts for BPF-building with libbpf +# -------------------------------------------------- +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +# +# This file should be included from your Makefile like: +# COMMON_DIR = ../common +# include $(COMMON_DIR)/common.mk +# +# It is expected that you define the variables: +# XDP_TARGETS and USER_TARGETS +# as a space-separated list +# +LLC ?= llc +CLANG ?= clang +CC ?= gcc + +XDP_C = ${XDP_TARGETS:=.c} +XDP_OBJ = ${XDP_C:.c=.o} +USER_C := ${USER_TARGETS:=.c} +USER_OBJ := ${USER_C:.c=.o} + +# Expect this is defined by including Makefile, but define if not +COMMON_DIR ?= ../common +LIB_DIR ?= ../lib + +COPY_LOADER ?= +LOADER_DIR ?= $(LIB_DIR)/xdp-tools/xdp-loader +STATS_DIR ?= $(COMMON_DIR)/../basic-solutions + +COMMON_OBJS += $(COMMON_DIR)/common_params.o +include $(LIB_DIR)/defines.mk + +# Create expansions for dependencies +COMMON_H := ${COMMON_OBJS:.o=.h} + +EXTRA_DEPS += + +XLB_OBJS += + +# BPF-prog kern and userspace shares struct via header file: +KERN_USER_H ?= $(wildcard common_kern_user.h) + +CFLAGS += -I$(LIB_DIR)/install/include $(EXTRA_CFLAGS) -g +BPF_CFLAGS += -I$(LIB_DIR)/install/include $(EXTRA_CFLAGS) -g +LDFLAGS += -L$(LIB_DIR)/install/lib + +BPF_HEADERS := $(wildcard $(HEADER_DIR)/*/*.h) $(wildcard $(INCLUDE_DIR)/*/*.h) + +all: llvm-check $(USER_TARGETS) $(XDP_OBJ) $(COPY_LOADER) $(COPY_STATS) + +.PHONY: clean $(CLANG) $(LLC) + +clean: + $(Q)rm -f $(USER_TARGETS) $(XDP_OBJ) $(USER_OBJ) $(COPY_LOADER) $(COPY_STATS) *.ll $(XLB_OBJS) + +ifdef COPY_LOADER +$(LOADER_DIR)/$(COPY_LOADER): + $(Q)make -C $(LOADER_DIR) + +$(COPY_LOADER): $(LOADER_DIR)/$(COPY_LOADER) + $(QUIET_COPY)cp $(LOADER_DIR)/$(COPY_LOADER) $(COPY_LOADER) +endif + +ifdef COPY_STATS +$(STATS_DIR)/$(COPY_STATS): $(STATS_DIR)/${COPY_STATS:=.c} $(COMMON_H) + $(Q)make -C $(STATS_DIR) $(COPY_STATS) + +$(COPY_STATS): $(STATS_DIR)/$(COPY_STATS) + $(QUIET_COPY)cp $(STATS_DIR)/$(COPY_STATS) $(COPY_STATS) +# Needing xdp_stats imply depending on header files: +EXTRA_DEPS += $(COMMON_DIR)/xdp_stats_kern.h $(COMMON_DIR)/xdp_stats_kern_user.h +endif + +# For build dependency on this file, if it gets updated +COMMON_MK = $(COMMON_DIR)/common.mk + +llvm-check: $(CLANG) $(LLC) + @for TOOL in $^ ; do \ + if [ ! $$(command -v $${TOOL} 2>/dev/null) ]; then \ + echo "*** ERROR: Cannot find tool $${TOOL}" ;\ + exit 1; \ + else true; fi; \ + done + +$(OBJECT_LIBBPF): + @if [ ! -d $(LIBBPF_DIR) ]; then \ + echo "Error: Need libbpf submodule" $(LIBBPF_DIR); \ + echo "May need to run git submodule update --init"; \ + exit 1; \ + else \ + cd $(LIBBPF_DIR) && $(MAKE) all OBJDIR=.; \ + mkdir -p build; $(MAKE) install_headers DESTDIR=build OBJDIR=.; \ + fi + +$(OBJECT_LIBXDP): + @if [ ! -d $(LIBXDP_DIR) ]; then \ + echo "Error: Need libxdp submodule" $(LIBXDP_DIR); \ + echo "May need to run git submodule update --init"; \ + exit 1; \ + else \ + cd $(LIBXDP_DIR) && $(MAKE) all OBJDIR=.; \ + fi + +# Create dependency: detect if C-file change and touch H-file, to trigger +# target $(COMMON_OBJS) +$(COMMON_H): %.h: %.c + touch $@ + +# Detect if any of common obj changed and create dependency on .h-files +$(COMMON_OBJS): %.o: %.h + $(Q)$(MAKE) -C $(COMMON_DIR) + +$(USER_TARGETS): %: %.c $(OBJECT_LIBBPF) $(OBJECT_LIBXDP) Makefile $(COMMON_MK) $(COMMON_OBJS) $(KERN_USER_H) $(EXTRA_DEPS) $(XLB_OBJS) + $(QUIET_CC)$(CC) -Wall $(CFLAGS) $(LDFLAGS) -o $@ $(COMMON_OBJS) $(XLB_OBJS) $(LIB_OBJS) \ + $< $(LDLIBS) + +$(XDP_OBJ): %.o: %.c Makefile $(COMMON_MK) $(KERN_USER_H) $(EXTRA_DEPS) $(OBJECT_LIBBPF) + $(QUIET_CLANG)$(CLANG) -S \ + -target bpf \ + -D __BPF_TRACING__ \ + $(BPF_CFLAGS) \ + -Wall \ + -Wno-unused-value \ + -Wno-pointer-sign \ + -Wno-compare-distinct-pointer-types \ + -Werror \ + -O2 -emit-llvm -c -g -o ${@:.o=.ll} $< + $(QUIET_LLC)$(LLC) -march=bpf -filetype=obj -o $@ ${@:.o=.ll} \ No newline at end of file diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_defines.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_defines.h new file mode 100644 index 000000000..12c822f8e --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_defines.h @@ -0,0 +1,49 @@ +#ifndef __COMMON_DEFINES_H +#define __COMMON_DEFINES_H + +#include +#include +#include +#include + +struct config { + enum xdp_attach_mode attach_mode; + __u32 xdp_flags; + int ifindex; + char *ifname; + char ifname_buf[IF_NAMESIZE]; + int redirect_ifindex; + char *redirect_ifname; + char redirect_ifname_buf[IF_NAMESIZE]; + bool do_unload; + __u32 prog_id; + bool reuse_maps; + char pin_dir[512]; + char filename[512]; + char progname[32]; + char src_mac[18]; + char dest_mac[18]; + __u16 xsk_bind_flags; + int xsk_if_queue; + bool xsk_poll_mode; + bool unload_all; + bool show_stats; // 数据统计 + bool ip_filter; //ip过滤 + bool mac_filter; //mac过滤 + bool router; //路由 + bool state; //会话保持 + bool clear; //清理 + +}; + +/* Defined in common_params.o */ +extern int verbose; + +/* Exit return codes */ +#define EXIT_OK 0 /* == EXIT_SUCCESS (stdlib.h) man exit(3) */ +#define EXIT_FAIL 1 /* == EXIT_FAILURE (stdlib.h) man exit(3) */ +#define EXIT_FAIL_OPTION 2 +#define EXIT_FAIL_XDP 30 +#define EXIT_FAIL_BPF 40 + +#endif /* __COMMON_DEFINES_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.c b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.c new file mode 100644 index 000000000..5788ecd9e --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.c @@ -0,0 +1,162 @@ +/* Common function that with time should be moved to libbpf */ + +#include +#include + +#include +#include + +#include "common_libbpf.h" + +/* From: include/linux/err.h */ +#define MAX_ERRNO 4095 +#define IS_ERR_VALUE(x) ((x) >= (unsigned long)-MAX_ERRNO) +static inline bool IS_ERR_OR_NULL(const void *ptr) +{ + return (!ptr) || IS_ERR_VALUE((unsigned long)ptr); +} + +#define pr_warning printf + +/* As close as possible to libbpf bpf_prog_load_xattr(), with the + * difference of handling pinned maps. + */ +int bpf_prog_load_xattr_maps(const struct bpf_prog_load_attr_maps *attr, + struct bpf_object **pobj, int *prog_fd) +{ + struct bpf_object_open_attr open_attr = { + .file = attr->file, + .prog_type = attr->prog_type, + }; + struct bpf_program *prog, *first_prog = NULL; + enum bpf_attach_type expected_attach_type; + enum bpf_prog_type prog_type; + struct bpf_object *obj; + struct bpf_map *map; + int err; + int i; + + if (!attr) + return -EINVAL; + if (!attr->file) + return -EINVAL; + + + obj = bpf_object__open_xattr(&open_attr); + if (IS_ERR_OR_NULL(obj)) + return -ENOENT; + + bpf_object__for_each_program(prog, obj) { + /* + * If type is not specified, try to guess it based on + * section name. + */ + prog_type = attr->prog_type; + // Was: prog->prog_ifindex = attr->ifindex; + bpf_program__set_ifindex(prog, attr->ifindex); + + expected_attach_type = attr->expected_attach_type; +#if 0 /* Use internal libbpf variables */ + if (prog_type == BPF_PROG_TYPE_UNSPEC) { + err = bpf_program__identify_section(prog, &prog_type, + &expected_attach_type); + if (err < 0) { + bpf_object__close(obj); + return -EINVAL; + } + } +#endif + + bpf_program__set_type(prog, prog_type); + bpf_program__set_expected_attach_type(prog, + expected_attach_type); + + if (!first_prog) + first_prog = prog; + } + + /* Reset attr->pinned_maps.map_fd to identify successful file load */ + for (i = 0; i < attr->nr_pinned_maps; i++) + attr->pinned_maps[i].map_fd = -1; + + bpf_map__for_each(map, obj) { + const char* mapname = bpf_map__name(map); + + if (!bpf_map__is_offload_neutral(map)) + bpf_map__set_ifindex(map, attr->ifindex); + /* Was: map->map_ifindex = attr->ifindex; */ + + for (i = 0; i < attr->nr_pinned_maps; i++) { + struct bpf_pinned_map *pin_map = &attr->pinned_maps[i]; + int fd; + + if (strcmp(mapname, pin_map->name) != 0) + continue; + + /* Matched, try opening pinned file */ + fd = bpf_obj_get(pin_map->filename); + if (fd > 0) { + /* Use FD from pinned map as replacement */ + bpf_map__reuse_fd(map, fd); + /* TODO: Might want to set internal map "name" + * if opened pinned map didn't, to allow + * bpf_object__find_map_fd_by_name() to work. + */ + pin_map->map_fd = fd; + continue; + } + /* Could not open pinned filename map, then this prog + * should then pin the map, BUT this can only happen + * after bpf_object__load(). + */ + } + } + + if (!first_prog) { + pr_warning("object file doesn't contain bpf program\n"); + bpf_object__close(obj); + return -ENOENT; + } + + err = bpf_object__load(obj); + if (err) { + bpf_object__close(obj); + return -EINVAL; + } + + /* Pin the maps that were not loaded via pinned filename */ + bpf_map__for_each(map, obj) { + const char* mapname = bpf_map__name(map); + + for (i = 0; i < attr->nr_pinned_maps; i++) { + struct bpf_pinned_map *pin_map = &attr->pinned_maps[i]; + int err; + + if (strcmp(mapname, pin_map->name) != 0) + continue; + + /* Matched, check if map is already loaded */ + if (pin_map->map_fd != -1) + continue; + + /* Needs to be pinned */ + err = bpf_map__pin(map, pin_map->filename); + if (err) + continue; + pin_map->map_fd = bpf_map__fd(map); + } + } + + /* Help user if requested map name that doesn't exist */ + for (i = 0; i < attr->nr_pinned_maps; i++) { + struct bpf_pinned_map *pin_map = &attr->pinned_maps[i]; + + if (pin_map->map_fd < 0) + pr_warning("%s() requested mapname:%s not seen\n", + __func__, pin_map->name); + } + + *pobj = obj; + *prog_fd = bpf_program__fd(first_prog); + return 0; +} diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.h new file mode 100644 index 000000000..4754bd8ca --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_libbpf.h @@ -0,0 +1,24 @@ +/* Common function that with time should be moved to libbpf */ +#ifndef __COMMON_LIBBPF_H +#define __COMMON_LIBBPF_H + +struct bpf_pinned_map { + const char *name; + const char *filename; + int map_fd; +}; + +/* bpf_prog_load_attr extended */ +struct bpf_prog_load_attr_maps { + const char *file; + enum bpf_prog_type prog_type; + enum bpf_attach_type expected_attach_type; + int ifindex; + int nr_pinned_maps; + struct bpf_pinned_map *pinned_maps; +}; + +int bpf_prog_load_xattr_maps(const struct bpf_prog_load_attr_maps *attr, + struct bpf_object **pobj, int *prog_fd); + +#endif /* __COMMON_LIBBPF_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.c b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.c new file mode 100644 index 000000000..e0fc2ca8b --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.c @@ -0,0 +1,299 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include /* XDP_FLAGS_* depend on kernel-headers installed */ +#include + +#include "common_params.h" + +int verbose = 1; + +#define BUFSIZE 30 + +/** + * @brief 打印选项的帮助信息 + * + * @param long_options 包含所有长选项的结构体数组 + * @param required 标志位,用于指示是否打印必需的选项 + */ +void _print_options(const struct option_wrapper *long_options, bool required) +{ + int i, pos; + char buf[BUFSIZE]; + + // 遍历所有的长选项 + for (i = 0; long_options[i].option.name != 0; i++) { + // 如果选项的必需性与参数不符,则跳过 + if (long_options[i].required != required) + continue; + + // 如果选项的短名称为大写字母,打印其短名称 + if (long_options[i].option.val > 64) /* ord('A') = 65 */ + printf(" -%c,", long_options[i].option.val); + else + // 否则不打印短名称,保留空白对齐 + printf(" "); + + // 将选项的长名称及其元变量(如果有)格式化到 buf 中 + pos = snprintf(buf, BUFSIZE, " --%s", long_options[i].option.name); + if (long_options[i].metavar) + snprintf(&buf[pos], BUFSIZE-pos, " %s", long_options[i].metavar); + + // 打印格式化后的选项名称和帮助信息 + printf("%-22s", buf); + printf(" %s", long_options[i].help); + printf("\n"); + } +} + + +/** + * @brief 打印程序的用法信息 + * + * @param prog_name 程序名 + * @param doc 程序的文档说明 + * @param long_options 包含所有长选项的结构体数组 + * @param full 标志位,是否打印完整的帮助信息 + */ +void usage(const char *prog_name, const char *doc, + const struct option_wrapper *long_options, bool full) +{ + // 打印用法信息的基本格式 + printf("Usage: %s [options]\n", prog_name); + + // 如果不需要打印完整的帮助信息 + if (!full) { + // 提示用户使用 --help 或 -h 查看完整的选项列表 + printf("Use --help (or -h) to see full option list.\n"); + return; + } + + // 打印文档说明 + printf("\nDOCUMENTATION:\n %s\n", doc); + + // 打印必需选项 + printf("Required options:\n"); + _print_options(long_options, true); + printf("\n"); + + // 打印其他选项 + printf("Other options:\n"); + _print_options(long_options, false); + printf("\n"); +} + + +/** + * @brief 将 option_wrapper 结构体数组转换为标准的 option 结构体数组 + * + * @param wrapper 包含所有长选项的结构体数组 + * @param options 输出参数,用于存储转换后的 option 结构体数组 + * @return int 成功返回0,失败返回-1 + */ +int option_wrappers_to_options(const struct option_wrapper *wrapper, + struct option **options) +{ + int i, num; + struct option *new_options; + + // 计算 wrapper 数组中的选项数量 + for (i = 0; wrapper[i].option.name != 0; i++) {} + num = i; + + // 分配新的 option 数组内存 + new_options = malloc(sizeof(struct option) * num); + if (!new_options) + // 如果内存分配失败,返回 -1 + return -1; + + // 将 wrapper 数组中的每个 option 复制到新的 option 数组中 + for (i = 0; i < num; i++) { + memcpy(&new_options[i], &wrapper[i], sizeof(struct option)); + } + + // 将新分配并填充的 option 数组赋值给输出参数 *options + *options = new_options; + + // 成功返回 0 + return 0; +} + + +/** + * @brief 解析命令行参数 + * + * @param argc 参数个数 + * @param argv 参数值数组 + * @param options_wrapper 包含所有长选项的结构体数组 + * @param cfg 配置结构体,用于存储解析结果 + * @param doc 程序的文档说明 + */ +void parse_cmdline_args(int argc, char **argv, + const struct option_wrapper *options_wrapper, + struct config *cfg, const char *doc) +{ + struct option *long_options; + bool full_help = false; + int longindex = 0; + char *dest; + int opt; + + // 将 option_wrapper 结构体数组转换为标准的 option 结构体数组 + if (option_wrappers_to_options(options_wrapper, &long_options)) { + fprintf(stderr, "Unable to malloc()\n"); + exit(EXIT_FAIL_OPTION); + } + + /* 解析命令行参数 */ + while ((opt = getopt_long(argc, argv, "hd:r:L:R:ASNFU:MQ:czpq:i:m:k:g:n:t", + long_options, &longindex)) != -1) { + switch (opt) { + case 'd': + // 检查设备名称长度是否超出限制 + if (strlen(optarg) >= IF_NAMESIZE) { + fprintf(stderr, "ERR: --dev name too long\n"); + goto error; + } + // 设置设备名称 + cfg->ifname = (char *)&cfg->ifname_buf; + strncpy(cfg->ifname, optarg, IF_NAMESIZE); + // 获取设备索引 + cfg->ifindex = if_nametoindex(cfg->ifname); + if (cfg->ifindex == 0) { + fprintf(stderr, + "ERR: --dev name unknown err(%d):%s\n", + errno, strerror(errno)); + goto error; + } + break; + case 'r': + // 检查重定向设备名称长度是否超出限制 + if (strlen(optarg) >= IF_NAMESIZE) { + fprintf(stderr, "ERR: --redirect-dev name too long\n"); + goto error; + } + // 设置重定向设备名称 + cfg->redirect_ifname = (char *)&cfg->redirect_ifname_buf; + strncpy(cfg->redirect_ifname, optarg, IF_NAMESIZE); + // 获取重定向设备索引 + cfg->redirect_ifindex = if_nametoindex(cfg->redirect_ifname); + if (cfg->redirect_ifindex == 0) { + fprintf(stderr, + "ERR: --redirect-dev name unknown err(%d):%s\n", + errno, strerror(errno)); + goto error; + } + break; + case 't': + cfg->show_stats = true; + break; + case 'i': + cfg->ip_filter = true; + break; + case 'm': + cfg->mac_filter = true; + break; + case 'k': + cfg->router = true; + break; + case 'g': + cfg->state = true; + break; + case 'n': + cfg->clear = true; + break; + case 'A': + // 设置附加模式为未指定模式 + cfg->attach_mode = XDP_MODE_UNSPEC; + break; + case 'S': + // 设置附加模式为 SKB 模式 + cfg->attach_mode = XDP_MODE_SKB; + cfg->xsk_bind_flags &= ~XDP_ZEROCOPY; + cfg->xsk_bind_flags |= XDP_COPY; + break; + case 'N': + // 设置附加模式为原生模式 + cfg->attach_mode = XDP_MODE_NATIVE; + break; + case 3: /* --offload-mode */ + // 设置附加模式为硬件模式 + cfg->attach_mode = XDP_MODE_HW; + break; + case 'M': + // 启用重用地图 + cfg->reuse_maps = true; + break; + case 'U': + // 设置卸载标志 + cfg->do_unload = true; + cfg->unload_all = true; + // cfg->prog_id = atoi(optarg); + break; + case 'p': + // 启用轮询模式 + cfg->xsk_poll_mode = true; + break; + case 'q': + // 设置为非详细模式 + verbose = false; + break; + case 'Q': + // 设置接口队列 + cfg->xsk_if_queue = atoi(optarg); + break; + case 1: /* --filename */ + // 设置文件名 + dest = (char *)&cfg->filename; + strncpy(dest, optarg, sizeof(cfg->filename)); + break; + case 2: /* --progname */ + // 设置程序名称 + dest = (char *)&cfg->progname; + strncpy(dest, optarg, sizeof(cfg->progname)); + break; + case 'L': /* --src-mac */ + // 设置源 MAC 地址 + dest = (char *)&cfg->src_mac; + strncpy(dest, optarg, sizeof(cfg->src_mac)); + break; + case 'R': /* --dest-mac */ + // 设置目的 MAC 地址 + dest = (char *)&cfg->dest_mac; + strncpy(dest, optarg, sizeof(cfg->dest_mac)); + break; + case 'c': + // 设置绑定标志为复制模式 + cfg->xsk_bind_flags &= ~XDP_ZEROCOPY; + cfg->xsk_bind_flags |= XDP_COPY; + break; + case 'z': + // 设置绑定标志为零拷贝模式 + cfg->xsk_bind_flags &= ~XDP_COPY; + cfg->xsk_bind_flags |= XDP_ZEROCOPY; + break; + case 4: /* --unload-all */ + // 设置卸载所有标志 + cfg->unload_all = true; + break; + case 'h': + // 设置显示完整帮助信息的标志 + full_help = true; + /* fall-through */ + error: + default: + // 打印使用信息并退出 + usage(argv[0], doc, options_wrapper, full_help); + free(long_options); + exit(EXIT_FAIL_OPTION); + } + } + // 释放分配的内存 + free(long_options); +} diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.h new file mode 100644 index 000000000..6f64c82e3 --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.h @@ -0,0 +1,22 @@ +/* This common_user.h is used by userspace programs */ +#ifndef __COMMON_PARAMS_H +#define __COMMON_PARAMS_H + +#include +#include "common_defines.h" + +struct option_wrapper { + struct option option; + char *help; + char *metavar; + bool required; +}; + +void usage(const char *prog_name, const char *doc, + const struct option_wrapper *long_options, bool full); + +void parse_cmdline_args(int argc, char **argv, + const struct option_wrapper *long_options, + struct config *cfg, const char *doc); + +#endif /* __COMMON_PARAMS_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.o b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_params.o new file mode 100644 index 0000000000000000000000000000000000000000..f16259d6cd59222a1a07a06eb3f3087663a01dc6 GIT binary patch literal 35472 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 Fe*w%*dd~m= literal 0 HcmV?d00001 diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.c b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.c new file mode 100644 index 000000000..85ef31f8a --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.c @@ -0,0 +1,289 @@ +#include /* bpf_get_link_xdp_id + bpf_set_link_xdp_id */ +#include /* strerror */ +#include /* IF_NAMESIZE */ +#include /* exit(3) */ +#include +#include +#include +#include +#include + +#include /* Need XDP flags */ + +#include "common_defines.h" + +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif + +static int reuse_maps(struct bpf_object *obj, const char *path) +{ + struct bpf_map *map; + + if (!obj) + return -ENOENT; + + if (!path) + return -EINVAL; + + bpf_object__for_each_map(map, obj) { + int len, err; + int pinned_map_fd; + char buf[PATH_MAX]; + + len = snprintf(buf, PATH_MAX, "%s/%s", path, bpf_map__name(map)); + if (len < 0) { + return -EINVAL; + } else if (len >= PATH_MAX) { + return -ENAMETOOLONG; + } + + pinned_map_fd = bpf_obj_get(buf); + if (pinned_map_fd < 0) + return pinned_map_fd; + + err = bpf_map__reuse_fd(map, pinned_map_fd); + if (err) + return err; + } + + return 0; +} + +#if 0 +struct bpf_object *load_bpf_object_file_reuse_maps(const char *file, + int ifindex, + const char *pin_dir) +{ + int err; + struct bpf_object *obj; + + obj = open_bpf_object(file, ifindex); + if (!obj) { + fprintf(stderr, "ERR: failed to open object %s\n", file); + return NULL; + } + + err = reuse_maps(obj, pin_dir); + if (err) { + fprintf(stderr, "ERR: failed to reuse maps for object %s, pin_dir=%s\n", + file, pin_dir); + return NULL; + } + + err = bpf_object__load(obj); + if (err) { + fprintf(stderr, "ERR: loading BPF-OBJ file(%s) (%d): %s\n", + file, err, strerror(-err)); + return NULL; + } + + return obj; +} +#endif + +struct xdp_program *load_bpf_and_xdp_attach(struct config *cfg) +{ + /* In next assignment this will be moved into ../common/ */ + int prog_fd = -1; + int err; + + DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts); + DECLARE_LIBXDP_OPTS(xdp_program_opts, xdp_opts, 0); + + xdp_opts.open_filename = cfg->filename; + xdp_opts.prog_name = cfg->progname; + xdp_opts.opts = &opts; + + /* If flags indicate hardware offload, supply ifindex */ + /* if (cfg->xdp_flags & XDP_FLAGS_HW_MODE) */ + /* offload_ifindex = cfg->ifindex; */ + + struct xdp_program *prog = xdp_program__create(&xdp_opts); + err = libxdp_get_error(prog); + if (err) { + char errmsg[1024]; + libxdp_strerror(err, errmsg, sizeof(errmsg)); + fprintf(stderr, "ERR: loading program: %s\n", errmsg); + exit(EXIT_FAIL_BPF); + } + + /* At this point: All XDP/BPF programs from the cfg->filename have been + * loaded into the kernel, and evaluated by the verifier. Only one of + * these gets attached to XDP hook, the others will get freed once this + * process exit. + */ + + /* At this point: BPF-progs are (only) loaded by the kernel, and prog_fd + * is our select file-descriptor handle. Next step is attaching this FD + * to a kernel hook point, in this case XDP net_device link-level hook. + */ + err = xdp_program__attach(prog, cfg->ifindex, cfg->attach_mode, 0); + if (err) + exit(err); + + prog_fd = xdp_program__fd(prog); + if (prog_fd < 0) { + fprintf(stderr, "ERR: xdp_program__fd failed: %s\n", strerror(errno)); + exit(EXIT_FAIL_BPF); + } + + return prog; +} + + +#define XDP_UNKNOWN XDP_REDIRECT + 1 +#ifndef XDP_ACTION_MAX +#define XDP_ACTION_MAX (XDP_UNKNOWN + 1) +#endif + +static const char *xdp_action_names[XDP_ACTION_MAX] = { + [XDP_ABORTED] = "XDP_ABORTED", + [XDP_DROP] = "XDP_DROP", + [XDP_PASS] = "XDP_PASS", + [XDP_TX] = "XDP_TX", + [XDP_REDIRECT] = "XDP_REDIRECT", + [XDP_UNKNOWN] = "XDP_UNKNOWN", +}; + +const char *action2str(__u32 action) +{ + if (action < XDP_ACTION_MAX) + return xdp_action_names[action]; + return NULL; +} + +int check_map_fd_info(const struct bpf_map_info *info, + const struct bpf_map_info *exp) +{ + if (exp->key_size && exp->key_size != info->key_size) { + fprintf(stderr, "ERR: %s() " + "Map key size(%d) mismatch expected size(%d)\n", + __func__, info->key_size, exp->key_size); + return EXIT_FAIL; + } + if (exp->value_size && exp->value_size != info->value_size) { + fprintf(stderr, "ERR: %s() " + "Map value size(%d) mismatch expected size(%d)\n", + __func__, info->value_size, exp->value_size); + return EXIT_FAIL; + } + if (exp->max_entries && exp->max_entries != info->max_entries) { + fprintf(stderr, "ERR: %s() " + "Map max_entries(%d) mismatch expected size(%d)\n", + __func__, info->max_entries, exp->max_entries); + return EXIT_FAIL; + } + if (exp->type && exp->type != info->type) { + fprintf(stderr, "ERR: %s() " + "Map type(%d) mismatch expected type(%d)\n", + __func__, info->type, exp->type); + return EXIT_FAIL; + } + + return 0; +} + +int open_bpf_map_file(const char *pin_dir, + const char *mapname, + struct bpf_map_info *info) +{ + char filename[PATH_MAX]; + int err, len, fd; + __u32 info_len = sizeof(*info); + + len = snprintf(filename, PATH_MAX, "%s/%s", pin_dir, mapname); + if (len < 0) { + fprintf(stderr, "ERR: constructing full mapname path\n"); + return -1; + } + + fd = bpf_obj_get(filename); + if (fd < 0) { + fprintf(stderr, + "WARN: Failed to open bpf map file:%s err(%d):%s\n", + filename, errno, strerror(errno)); + return fd; + } + + if (info) { + err = bpf_obj_get_info_by_fd(fd, info, &info_len); + if (err) { + fprintf(stderr, "ERR: %s() can't get info - %s\n", + __func__, strerror(errno)); + return EXIT_FAIL_BPF; + } + } + + return fd; +} + +int do_unload(struct config *cfg) +{ + struct xdp_multiprog *mp = NULL; + enum xdp_attach_mode mode; + int err = EXIT_FAILURE; + DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts); + + mp = xdp_multiprog__get_from_ifindex(cfg->ifindex); + if (libxdp_get_error(mp)) { + fprintf(stderr, "Unable to get xdp_dispatcher program: %s\n", + strerror(errno)); + goto out; + } else if (!mp) { + fprintf(stderr, "No XDP program loaded on %s\n", cfg->ifname); + mp = NULL; + goto out; + } + + if (cfg->unload_all) { + err = xdp_multiprog__detach(mp); + if (err) { + fprintf(stderr, "Unable to detach XDP program: %s\n", + strerror(-err)); + goto out; + } + } else { + struct xdp_program *prog = NULL; + + while ((prog = xdp_multiprog__next_prog(prog, mp))) { + if (xdp_program__id(prog) == cfg->prog_id) { + mode = xdp_multiprog__attach_mode(mp); + goto found; + } + } + + if (xdp_multiprog__is_legacy(mp)) { + prog = xdp_multiprog__main_prog(mp); + if (xdp_program__id(prog) == cfg->prog_id) { + mode = xdp_multiprog__attach_mode(mp); + goto found; + } + } + + prog = xdp_multiprog__hw_prog(mp); + if (xdp_program__id(prog) == cfg->prog_id) { + mode = XDP_MODE_HW; + goto found; + } + + printf("Program with ID %u not loaded on %s\n", + cfg->prog_id, cfg->ifname); + err = -ENOENT; + goto out; + +found: + printf("Detaching XDP program with ID %u from %s\n", + xdp_program__id(prog), cfg->ifname); + err = xdp_program__detach(prog, cfg->ifindex, mode, 0); + if (err) { + fprintf(stderr, "Unable to detach XDP program: %s\n", + strerror(-err)); + goto out; + } + } + +out: + xdp_multiprog__close(mp); + return err ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.h new file mode 100644 index 000000000..01df3e2ed --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.h @@ -0,0 +1,18 @@ +/* Common BPF/XDP functions used by userspace side programs */ +#ifndef __COMMON_USER_BPF_XDP_H +#define __COMMON_USER_BPF_XDP_H + +struct bpf_object *load_bpf_object_file(const char *filename, int ifindex); +struct xdp_program *load_bpf_and_xdp_attach(struct config *cfg); + +const char *action2str(__u32 action); + +int check_map_fd_info(const struct bpf_map_info *info, + const struct bpf_map_info *exp); + +int open_bpf_map_file(const char *pin_dir, + const char *mapname, + struct bpf_map_info *info); +int do_unload(struct config *cfg); + +#endif /* __COMMON_USER_BPF_XDP_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.o b/eBPF_Supermarket/Network_Subsystem/net_manager/common/common_user_bpf_xdp.o new file mode 100644 index 0000000000000000000000000000000000000000..758fe3b3c0464bddc5b4b26ab2a12fb1155cb8db GIT binary patch literal 32768 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 F{15#I_tF3W literal 0 HcmV?d00001 diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/parsing_helpers.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/parsing_helpers.h new file mode 100644 index 000000000..877602bbf --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/parsing_helpers.h @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-clause) */ +/* + * This file contains parsing functions that are used in the packetXX XDP + * programs. The functions are marked as __always_inline, and fully defined in + * this header file to be included in the BPF program. + * + * Each helper parses a packet header, including doing bounds checking, and + * returns the type of its contents if successful, and -1 otherwise. + * + * For Ethernet and IP headers, the content type is the type of the payload + * (h_proto for Ethernet, nexthdr for IPv6), for ICMP it is the ICMP type field. + * All return values are in host byte order. + * + * The versions of the functions included here are slightly expanded versions of + * the functions in the packet01 lesson. For instance, the Ethernet header + * parsing has support for parsing VLAN tags. + */ + +#ifndef __PARSING_HELPERS_H +#define __PARSING_HELPERS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Header cursor to keep track of current parsing position */ +struct hdr_cursor { + void *pos; +}; + +/* + * struct vlan_hdr - vlan header + * @h_vlan_TCI: priority and VLAN ID + * @h_vlan_encapsulated_proto: packet type ID or len + */ +struct vlan_hdr { + __be16 h_vlan_TCI; + __be16 h_vlan_encapsulated_proto; +}; + +/* + * Struct icmphdr_common represents the common part of the icmphdr and icmp6hdr + * structures. + */ +struct icmphdr_common { + __u8 type; + __u8 code; + __sum16 cksum; +}; + +/* Allow users of header file to redefine VLAN max depth */ +#ifndef VLAN_MAX_DEPTH +#define VLAN_MAX_DEPTH 2 +#endif + +#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ +/* Struct for collecting VLANs after parsing via parse_ethhdr_vlan */ +struct collect_vlans { + __u16 id[VLAN_MAX_DEPTH]; +}; + +static __always_inline int proto_is_vlan(__u16 h_proto) +{ + return !!(h_proto == bpf_htons(ETH_P_8021Q) || + h_proto == bpf_htons(ETH_P_8021AD)); +} + +/* Notice, parse_ethhdr() will skip VLAN tags, by advancing nh->pos and returns + * next header EtherType, BUT the ethhdr pointer supplied still points to the + * Ethernet header. Thus, caller can look at eth->h_proto to see if this was a + * VLAN tagged packet. + */ +static __always_inline int parse_ethhdr_vlan(struct hdr_cursor *nh, + void *data_end, + struct ethhdr **ethhdr, + struct collect_vlans *vlans) +{ + struct ethhdr *eth = nh->pos; + int hdrsize = sizeof(*eth); + struct vlan_hdr *vlh; + __u16 h_proto; + int i; + + /* Byte-count bounds check; check if current pointer + size of header + * is after data_end. + */ + if (nh->pos + hdrsize > data_end) + return -1; + + nh->pos += hdrsize; + *ethhdr = eth; + vlh = nh->pos; + h_proto = eth->h_proto; + + /* Use loop unrolling to avoid the verifier restriction on loops; + * support up to VLAN_MAX_DEPTH layers of VLAN encapsulation. + */ + #pragma unroll + for (i = 0; i < VLAN_MAX_DEPTH; i++) { + if (!proto_is_vlan(h_proto)) + break; + + if (vlh + 1 > data_end) + break; + + h_proto = vlh->h_vlan_encapsulated_proto; + if (vlans) /* collect VLAN ids */ + vlans->id[i] = + (bpf_ntohs(vlh->h_vlan_TCI) & VLAN_VID_MASK); + + vlh++; + } + + nh->pos = vlh; + return h_proto; /* network-byte-order */ +} + +static __always_inline int parse_ethhdr(struct hdr_cursor *nh, + void *data_end, + struct ethhdr **ethhdr) +{ + /* Expect compiler removes the code that collects VLAN ids */ + return parse_ethhdr_vlan(nh, data_end, ethhdr, NULL); +} + +static __always_inline int parse_ip6hdr(struct hdr_cursor *nh, + void *data_end, + struct ipv6hdr **ip6hdr) +{ + struct ipv6hdr *ip6h = nh->pos; + + /* Pointer-arithmetic bounds check; pointer +1 points to after end of + * thing being pointed to. We will be using this style in the remainder + * of the tutorial. + */ + if (ip6h + 1 > data_end) + return -1; + + nh->pos = ip6h + 1; + *ip6hdr = ip6h; + + return ip6h->nexthdr; +} + +static __always_inline int parse_iphdr(struct hdr_cursor *nh, + void *data_end, + struct iphdr **iphdr) +{ + struct iphdr *iph = nh->pos; + int hdrsize; + + if (iph + 1 > data_end) + return -1; + + hdrsize = iph->ihl * 4; + /* Sanity check packet field is valid */ + if(hdrsize < sizeof(*iph)) + return -1; + + /* Variable-length IPv4 header, need to use byte-based arithmetic */ + if (nh->pos + hdrsize > data_end) + return -1; + + nh->pos += hdrsize; + *iphdr = iph; + + return iph->protocol; +} + +static __always_inline int parse_icmp6hdr(struct hdr_cursor *nh, + void *data_end, + struct icmp6hdr **icmp6hdr) +{ + struct icmp6hdr *icmp6h = nh->pos; + + if (icmp6h + 1 > data_end) + return -1; + + nh->pos = icmp6h + 1; + *icmp6hdr = icmp6h; + + return icmp6h->icmp6_type; +} + +static __always_inline int parse_icmphdr(struct hdr_cursor *nh, + void *data_end, + struct icmphdr **icmphdr) +{ + struct icmphdr *icmph = nh->pos; + + if (icmph + 1 > data_end) + return -1; + + nh->pos = icmph + 1; + *icmphdr = icmph; + + return icmph->type; +} + +static __always_inline int parse_icmphdr_common(struct hdr_cursor *nh, + void *data_end, + struct icmphdr_common **icmphdr) +{ + struct icmphdr_common *h = nh->pos; + + if (h + 1 > data_end) + return -1; + + nh->pos = h + 1; + *icmphdr = h; + + return h->type; +} + +/* + * parse_udphdr: parse the udp header and return the length of the udp payload + */ +static __always_inline int parse_udphdr(struct hdr_cursor *nh, + void *data_end, + struct udphdr **udphdr) +{ + int len; + struct udphdr *h = nh->pos; + + if (h + 1 > data_end) + return -1; + + nh->pos = h + 1; + *udphdr = h; + + len = bpf_ntohs(h->len) - sizeof(struct udphdr); + if (len < 0) + return -1; + + return len; +} + +/* + * parse_tcphdr: parse and return the length of the tcp header + */ +static __always_inline int parse_tcphdr(struct hdr_cursor *nh, + void *data_end, + struct tcphdr **tcphdr) +{ + int len; + struct tcphdr *h = nh->pos; + + if (h + 1 > data_end) + return -1; + + len = h->doff * 4; + /* Sanity check packet field is valid */ + if(len < sizeof(*h)) + return -1; + + /* Variable-length TCP header, need to use byte-based arithmetic */ + if (nh->pos + len > data_end) + return -1; + + nh->pos += len; + *tcphdr = h; + + return len; +} + +#endif /* __PARSING_HELPERS_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/rewrite_helpers.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/rewrite_helpers.h new file mode 100644 index 000000000..a5d3e671d --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/rewrite_helpers.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-clause) */ +/* + * This file contains functions that are used in the packetXX XDP programs to + * manipulate on packets data. The functions are marked as __always_inline, and + * fully defined in this header file to be included in the BPF program. + */ + +#ifndef __REWRITE_HELPERS_H +#define __REWRITE_HELPERS_H + +#include +#include +#include +#include + +#include +#include + +/* Pops the outermost VLAN tag off the packet. Returns the popped VLAN ID on + * success or negative errno on failure. + */ +static __always_inline int vlan_tag_pop(struct xdp_md *ctx, struct ethhdr *eth) +{ + void *data_end = (void *)(long)ctx->data_end; + struct ethhdr eth_cpy; + struct vlan_hdr *vlh; + __be16 h_proto; + int vlid; + + if (!proto_is_vlan(eth->h_proto)) + return -1; + + /* Careful with the parenthesis here */ + vlh = (void *)(eth + 1); + + /* Still need to do bounds checking */ + if (vlh + 1 > data_end) + return -1; + + /* Save vlan ID for returning, h_proto for updating Ethernet header */ + vlid = bpf_ntohs(vlh->h_vlan_TCI); + h_proto = vlh->h_vlan_encapsulated_proto; + + /* Make a copy of the outer Ethernet header before we cut it off */ + __builtin_memcpy(ð_cpy, eth, sizeof(eth_cpy)); + + /* Actually adjust the head pointer */ + if (bpf_xdp_adjust_head(ctx, (int)sizeof(*vlh))) + return -1; + + /* Need to re-evaluate data *and* data_end and do new bounds checking + * after adjusting head + */ + eth = (void *)(long)ctx->data; + data_end = (void *)(long)ctx->data_end; + if (eth + 1 > data_end) + return -1; + + /* Copy back the old Ethernet header and update the proto type */ + __builtin_memcpy(eth, ð_cpy, sizeof(*eth)); + eth->h_proto = h_proto; + + return vlid; +} + +/* Pushes a new VLAN tag after the Ethernet header. Returns 0 on success, + * -1 on failure. + */ +static __always_inline int vlan_tag_push(struct xdp_md *ctx, + struct ethhdr *eth, int vlid) +{ + void *data_end = (void *)(long)ctx->data_end; + struct ethhdr eth_cpy; + struct vlan_hdr *vlh; + + /* First copy the original Ethernet header */ + __builtin_memcpy(ð_cpy, eth, sizeof(eth_cpy)); + + /* Then add space in front of the packet */ + if (bpf_xdp_adjust_head(ctx, 0 - (int)sizeof(*vlh))) + return -1; + + /* Need to re-evaluate data_end and data after head adjustment, and + * bounds check, even though we know there is enough space (as we + * increased it). + */ + data_end = (void *)(long)ctx->data_end; + eth = (void *)(long)ctx->data; + + if (eth + 1 > data_end) + return -1; + + /* Copy back Ethernet header in the right place, populate VLAN tag with + * ID and proto, and set outer Ethernet header to VLAN type. + */ + __builtin_memcpy(eth, ð_cpy, sizeof(*eth)); + + vlh = (void *)(eth + 1); + + if (vlh + 1 > data_end) + return -1; + + vlh->h_vlan_TCI = bpf_htons(vlid); + vlh->h_vlan_encapsulated_proto = eth->h_proto; + + eth->h_proto = bpf_htons(ETH_P_8021Q); + return 0; +} + +/* + * Swaps destination and source MAC addresses inside an Ethernet header + */ +static __always_inline void swap_src_dst_mac(struct ethhdr *eth) +{ + __u8 h_tmp[ETH_ALEN]; + + __builtin_memcpy(h_tmp, eth->h_source, ETH_ALEN); + __builtin_memcpy(eth->h_source, eth->h_dest, ETH_ALEN); + __builtin_memcpy(eth->h_dest, h_tmp, ETH_ALEN); +} + +/* + * Swaps destination and source IPv6 addresses inside an IPv6 header + */ +static __always_inline void swap_src_dst_ipv6(struct ipv6hdr *ipv6) +{ + struct in6_addr tmp = ipv6->saddr; + + ipv6->saddr = ipv6->daddr; + ipv6->daddr = tmp; +} + +/* + * Swaps destination and source IPv4 addresses inside an IPv4 header + */ +static __always_inline void swap_src_dst_ipv4(struct iphdr *iphdr) +{ + __be32 tmp = iphdr->saddr; + + iphdr->saddr = iphdr->daddr; + iphdr->daddr = tmp; +} + +#endif /* __REWRITE_HELPERS_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern.h new file mode 100644 index 000000000..c061a149d --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* Used *ONLY* by BPF-prog running kernel side. */ +#ifndef __XDP_STATS_KERN_H +#define __XDP_STATS_KERN_H + +/* Data record type 'struct datarec' is defined in common/xdp_stats_kern_user.h, + * programs using this header must first include that file. + */ +#ifndef __XDP_STATS_KERN_USER_H +#warning "You forgot to #include <../common/xdp_stats_kern_user.h>" +#include <../common/xdp_stats_kern_user.h> +#endif + +/* Keeps stats per (enum) xdp_action */ +struct { + __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); + __type(key, __u32); + __type(value, struct datarec); + __uint(max_entries, XDP_ACTION_MAX); +} xdp_stats_map SEC(".maps"); + +static __always_inline +__u32 xdp_stats_record_action(struct xdp_md *ctx, __u32 action) +{ + if (action >= XDP_ACTION_MAX) + return XDP_ABORTED; + + /* Lookup in kernel BPF-side return pointer to actual data record */ + struct datarec *rec = bpf_map_lookup_elem(&xdp_stats_map, &action); + if (!rec) + return XDP_ABORTED; + + /* BPF_MAP_TYPE_PERCPU_ARRAY returns a data record specific to current + * CPU and XDP hooks runs under Softirq, which makes it safe to update + * without atomic operations. + */ + rec->rx_packets++; + rec->rx_bytes += (ctx->data_end - ctx->data); + + return action; +} + +#endif /* __XDP_STATS_KERN_H */ diff --git a/eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern_user.h b/eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern_user.h new file mode 100644 index 000000000..d7b8d05e6 --- /dev/null +++ b/eBPF_Supermarket/Network_Subsystem/net_manager/common/xdp_stats_kern_user.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* Used by BPF-prog kernel side BPF-progs and userspace programs, + * for sharing xdp_stats common struct and DEFINEs. + */ +#ifndef __XDP_STATS_KERN_USER_H +#define __XDP_STATS_KERN_USER_H + +/* This is the data record stored in the map */ +struct datarec { + __u64 rx_packets; + __u64 rx_bytes; +}; + +#ifndef XDP_ACTION_MAX +#define XDP_ACTION_MAX (XDP_REDIRECT + 1) +#endif + +#endif /* __XDP_STATS_KERN_USER_H */