diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6892c87..c37c5b1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: - name: Install LibXDP. run: sudo make libxdp_install - name: Make project - run: LIBBPF_LIBXDP_STATIC=1 make + run: make - name: Install project run: sudo make install - name: Store build artifacts diff --git a/Makefile b/Makefile index 1d797f3..e2701c2 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CC = clang -LIBBPF_LIBXDP_STATIC ?= 0 +LIBXDP_STATIC ?= 1 # Top-level directories. BUILD_DIR = build @@ -61,7 +61,7 @@ LOADER_UTILS_HELPERS_OBJ = helpers.o # Loader objects. LOADER_OBJS = $(BUILD_LOADER_DIR)/$(LOADER_UTILS_CONFIG_OBJ) $(BUILD_LOADER_DIR)/$(LOADER_UTILS_CMDLINE_OBJ) $(BUILD_LOADER_DIR)/$(LOADER_UTILS_XDP_OBJ) $(BUILD_LOADER_DIR)/$(LOADER_UTILS_STATS_OBJ) $(BUILD_LOADER_DIR)/$(LOADER_UTILS_HELPERS_OBJ) -ifeq ($(LIBBPF_LIBXDP_STATIC), 1) +ifeq ($(LIBXDP_STATIC), 1) LOADER_OBJS := $(LIBBPF_OBJS) $(LIBXDP_OBJS) $(LOADER_OBJS) endif @@ -70,13 +70,19 @@ XDP_SRC = prog.c XDP_OBJ = xdp_prog.o # Includes. -INCS = -I $(SRC_DIR) -I $(LIBBPF_SRC) -I /usr/include -I /usr/local/include +INCS = -I $(SRC_DIR) -I /usr/include -I /usr/local/include + +ifeq ($(LIBXDP_STATIC), 1) + INCS += -I $(XDP_TOOLS_HEADERS) -I $(LIBBPF_SRC) +endif # Flags. FLAGS = -O2 -g FLAGS_LOADER = -lconfig -lelf -lz -ifeq ($(LIBBPF_LIBXDP_STATIC), 0) +ifeq ($(LIBXDP_STATIC), 1) + FLAGS += -D__LIBXDP_STATIC__ +else FLAGS_LOADER += -lbpf -lxdp endif diff --git a/README.md b/README.md index 8bd598a..cd278a2 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ Additionally, here is a list of flags you may pass to this script. | --libxdp | Build and install LibXDP before building the tool. | | --no-install | Build the tool and/or LibXDP without installing them. | | --clean | Remove build files for the tool and LibXDP. | -| --static | Statically link LibXDP and LibBPF object files when building the tool. | +| --no-static | Do *not* statically link LibXDP and LibBPF object files when building the tool. This makes the build process faster, but you may need to alter your `LD_LIBRARY_PATH` env variable before running the tool and requires LibXDP to be installed on your system already. | | --help | Displays help message. | ### Without Bash Script @@ -183,7 +183,7 @@ You may additionally specified UDP header options for a filter rule which start * As of right now, you can specify up to 60 total filter rules. You may increase this limit by raising the `MAX_FILTERS` constant in the `src/common/config.h` [file](https://github.com/gamemann/XDP-Firewall/blob/master/src/common/config.h#L5) and then recompile the firewall. If you receive a BPF program too large error, this is due to BPF's limitations with complexity and jumps. You may try increasing BPF limitations manually or with a patch. If you want to do this, please read [this](https://github.com/gamemann/XDP-Forwarding/tree/master/patches) README from my XDP Forwarding project. ### Example -Here's a config example: +Here's a config example. ```squidconf interface = "ens18"; @@ -243,7 +243,7 @@ If you have issues on Ubuntu 20.04 or earlier, please refer to the reply on [thi Basically, Clang/LLVM 12 or above is required and I'd recommend running Linux kernel 5.15 or above. ### BPF For/While Loop Support + Performance Notes -This project requires for/while loop support with BPF. Older kernels will not support this and output an error such as: +This project requires for/while loop support with BPF. Older kernels will not support this and output an error such as the following. ```vim libbpf: load bpf program failed: Invalid argument @@ -287,25 +287,18 @@ By default, client stats including packets and bytes per second are calculated p ``` ### Error While Loading Shared Libraries -If you receive an error similar to the one below when running the program, make sure you have LibXDP globally installed onto your system via [XDP Tools](https://github.com/xdp-project/xdp-tools). You can execute `make libxdp` to install both LibXDP and LibBPF onto your system. +If you receive an error similar to the one below when running the program and have built the program using the no static option, make sure you have LibXDP globally installed onto your system via [XDP Tools](https://github.com/xdp-project/xdp-tools). You can execute `make libxdp && sudo make libxdp_install` to build and install both LibXDP and LibBPF onto your system separately. ```bash ./xdpfw: error while loading shared libraries: libxdp.so.1: cannot open shared object file: No such file or directory ``` -If you don't want to have LibXDP installed on your system after building the program, you can set the `LIBBPF_LIBXDP_STATIC` environmental variable to `1` while building the project with `make` or pass the `--static` flag to the [`install.sh`](./install.sh) Bash script. This will link all of the LibBPF and LibXDP object files while building the loader so you shouldn't need LibXDP installed globally. - -For example: +If you still run into issues, try adding `/usr/local/lib` to your `LD_LIBRARY_PATH` since that's where LibXDP installs the shared objects from my testing. Here's an example. ```bash -# Build with LibBPF and LibXDP object files linked directly from modules/xdp-tools directories. -LIBBPF_LIBXDP_STATIC=1 make +export LD_LIBRARY_PATH=/usr/local/lib -# Install onto system. -sudo make install - -# Build using Bash script with static. -./install.sh --static +sudo xdpfw ``` ## My Other XDP Projects diff --git a/install.sh b/install.sh index 64aeb01..211dd88 100755 --- a/install.sh +++ b/install.sh @@ -1,15 +1,15 @@ #!/bin/bash -WITH_LIBXDP=0 +LIBXDP=0 INSTALL=1 CLEAN=0 -STATIC=0 +STATIC=1 while [[ $# -gt 0 ]]; do key="$1" case $key in --libxdp) - WITH_LIBXDP=1 + LIBXDP=1 shift ;; @@ -26,8 +26,8 @@ while [[ $# -gt 0 ]]; do shift ;; - --static) - STATIC=1 + --no-static) + STATIC=0 shift ;; @@ -39,7 +39,7 @@ while [[ $# -gt 0 ]]; do echo " --libxdp Build and install LibXDP before building the tool." echo " --no-install Build the tool and/or LibXDP without installing them." echo " --clean Remove build files for the tool and LibXDP." - echo " --static Statically link LibXDP and LibBPF object files when building the tool." + echo " --no-static Statically link LibXDP and LibBPF object files when building the tool." echo " --help Display this help message." exit 0 @@ -54,7 +54,7 @@ while [[ $# -gt 0 ]]; do done if [ "$CLEAN" -gt 0 ]; then - if [ "$WITH_LIBXDP" -gt 0 ]; then + if [ "$LIBXDP" -gt 0 ]; then echo "Cleaning LibXDP..." ./scripts/libxdp_clean.sh @@ -67,7 +67,7 @@ if [ "$CLEAN" -gt 0 ]; then exit 0 fi -if [ "$WITH_LIBXDP" -gt 0 ]; then +if [ "$LIBXDP" -gt 0 ]; then echo "Building LibXDP..." ./scripts/libxdp_build.sh diff --git a/scripts/build.sh b/scripts/build.sh index ff6fd1b..efbd00c 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -3,11 +3,11 @@ STATIC="$1" if [ -z "$STATIC" ]; then - STATIC=0 + STATIC=1 fi if [ -z "$ROOT" ]; then - LIBBPF_LIBXDP_STATIC=$STATIC make + LIBXDP_STATIC=$STATIC make else - cd $ROOT && LIBBPF_LIBXDP_STATIC=$STATIC make + cd $ROOT && LIBXDP_STATIC=$STATIC make fi \ No newline at end of file diff --git a/src/loader/prog.c b/src/loader/prog.c index a5e046a..8009134 100644 --- a/src/loader/prog.c +++ b/src/loader/prog.c @@ -159,7 +159,7 @@ int main(int argc, char *argv[]) // Update config. if ((ret = LoadConfig(&cfg, cmd.cfgfile)) != 0) { - fprintf(stderr, "[WARNING] Failed to load config after update check (%d)\n", ret); + fprintf(stderr, "[WARNING] Failed to load config after update check (%d)...\n", ret); } // Update BPF maps. @@ -178,7 +178,7 @@ int main(int argc, char *argv[]) { if (CalculateStats(stats_map, cpus)) { - fprintf(stderr, "[WARNING] Failed to calculate packet stats. Stats map FD => %d.\n", stats_map); + fprintf(stderr, "[WARNING] Failed to calculate packet stats. Stats map FD => %d...\n", stats_map); } } diff --git a/src/loader/utils/config.h b/src/loader/utils/config.h index 04d767b..72c169d 100644 --- a/src/loader/utils/config.h +++ b/src/loader/utils/config.h @@ -6,7 +6,6 @@ #include #include #include -#include #include diff --git a/src/loader/utils/stats.c b/src/loader/utils/stats.c index 96715e0..e19dc8c 100644 --- a/src/loader/utils/stats.c +++ b/src/loader/utils/stats.c @@ -31,7 +31,7 @@ int CalculateStats(int stats_map, int cpus) // Therefore, before accessing stats[i], make sure the pointer to the specific CPU ID is not NULL. if (&stats[i] == NULL) { - fprintf(stderr, "Stats array at CPU ID #%d is NULL! Skipping...\n", i); + fprintf(stderr, "[WARNING] Stats array at CPU ID #%d is NULL! Skipping...\n", i); continue; } diff --git a/src/loader/utils/stats.h b/src/loader/utils/stats.h index 5330910..71cbc91 100644 --- a/src/loader/utils/stats.h +++ b/src/loader/utils/stats.h @@ -1,7 +1,5 @@ #pragma once -#include -#include #include #include diff --git a/src/loader/utils/xdp.c b/src/loader/utils/xdp.c index f473b02..4bc51cc 100644 --- a/src/loader/utils/xdp.c +++ b/src/loader/utils/xdp.c @@ -149,7 +149,7 @@ int AttachXdp(struct xdp_program *prog, int ifidx, u8 detach, cmdline_t *cmd) if (detach < 1) { - fprintf(stdout, "Loaded XDP program on mode %s.\n", smode); + fprintf(stdout, "Loaded XDP program on mode %s...\n", smode); } return EXIT_SUCCESS; @@ -194,7 +194,7 @@ void UpdateFilters(int filters_map, config__t *cfg) // Attempt to update BPF map. if ((ret = bpf_map_update_elem(filters_map, &i, &filter, BPF_ANY)) != 0) { - fprintf(stderr, "[WARNING] Failed to update filter #%d due to BPF update error (%d).\n", i, ret); + fprintf(stderr, "[WARNING] Failed to update filter #%d due to BPF update error (%d)...\n", i, ret); } } } \ No newline at end of file diff --git a/src/loader/utils/xdp.h b/src/loader/utils/xdp.h index e823f5e..9b7b127 100644 --- a/src/loader/utils/xdp.h +++ b/src/loader/utils/xdp.h @@ -1,7 +1,5 @@ #pragma once -#include -#include #include #include diff --git a/src/xdp/utils/helpers.h b/src/xdp/utils/helpers.h index 1e53ab5..14b99e5 100644 --- a/src/xdp/utils/helpers.h +++ b/src/xdp/utils/helpers.h @@ -3,12 +3,16 @@ #include #include -#include -#include #include #include +#ifdef __LIBXDP_STATIC__ +#include +#else +#include +#endif + #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) diff --git a/src/xdp/utils/rl.h b/src/xdp/utils/rl.h index d87bd42..85ec5eb 100644 --- a/src/xdp/utils/rl.h +++ b/src/xdp/utils/rl.h @@ -9,7 +9,6 @@ static __always_inline void UpdateIpStats(u64 *pps, u64 *bps, u32 ip, u16 port, u8 protocol, u16 pkt_len, u64 now); static __always_inline void UpdateIp6Stats(u64 *pps, u64 *bps, u128 *ip, u16 port, u8 protocol, u16 pkt_len, u64 now); - // The source file is included directly below instead of compiled and linked as an object because when linking, there is no guarantee the compiler will inline the function (which is crucial for performance). // I'd prefer not to include the function logic inside of the header file. // More Info: https://stackoverflow.com/questions/24289599/always-inline-does-not-work-when-function-is-implemented-in-different-file