summaryrefslogtreecommitdiff
path: root/src/xdp/utils
diff options
context:
space:
mode:
authorChristian Breunig <christian@breunig.cc>2023-06-12 19:57:28 +0200
committerChristian Breunig <christian@breunig.cc>2023-06-12 19:57:28 +0200
commitfcb5d0fdafeebe49f42799b1d0d056c4b67bcc16 (patch)
tree28a5a272cc66cd5c6b4bc1132b4db5a455ca3214 /src/xdp/utils
parentf9fa1e99e042846a8089ae2b4bc41dd8f3e3eb7c (diff)
downloadvyos-1x-fcb5d0fdafeebe49f42799b1d0d056c4b67bcc16.tar.gz
vyos-1x-fcb5d0fdafeebe49f42799b1d0d056c4b67bcc16.zip
T5286: drop XDP support for ethernet and bonding interfaces
... this is a step towards a new and better implementation that will utilize VPP.
Diffstat (limited to 'src/xdp/utils')
-rw-r--r--src/xdp/utils/Makefile11
-rw-r--r--src/xdp/utils/xdp_loader.c165
-rw-r--r--src/xdp/utils/xdp_stats.c298
3 files changed, 0 insertions, 474 deletions
diff --git a/src/xdp/utils/Makefile b/src/xdp/utils/Makefile
deleted file mode 100644
index 42d6e63e3..000000000
--- a/src/xdp/utils/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
-USER_TARGETS := xdp_stats xdp_loader
-
-LIBBPF_DIR = ../libbpf/src/
-COMMON_DIR = ../common/
-
-# Extend with another COMMON_OBJS
-COMMON_OBJS += $(COMMON_DIR)/common_libbpf.o
-
-include $(COMMON_DIR)/common.mk
diff --git a/src/xdp/utils/xdp_loader.c b/src/xdp/utils/xdp_loader.c
deleted file mode 100644
index d3b05d0c0..000000000
--- a/src/xdp/utils/xdp_loader.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-static const char *__doc__ = "XDP loader\n"
- " - Allows selecting BPF section --progsec name to XDP-attach to --dev\n";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <getopt.h>
-
-#include <locale.h>
-#include <unistd.h>
-#include <time.h>
-
-#include <bpf/bpf.h>
-#include <bpf/libbpf.h>
-
-#include <net/if.h>
-#include <linux/if_link.h> /* depend on kernel-headers installed */
-
-#include "../common/common_params.h"
-#include "../common/common_user_bpf_xdp.h"
-#include "../common/common_libbpf.h"
-
-static const char *default_filename = "xdp_prog_kern.o";
-
-static const struct option_wrapper long_options[] = {
-
- {{"help", no_argument, NULL, 'h' },
- "Show help", false},
-
- {{"dev", required_argument, NULL, 'd' },
- "Operate on device <ifname>", "<ifname>", true},
-
- {{"skb-mode", no_argument, NULL, 'S' },
- "Install XDP program in SKB (AKA generic) mode"},
-
- {{"native-mode", no_argument, NULL, 'N' },
- "Install XDP program in native mode"},
-
- {{"auto-mode", no_argument, NULL, 'A' },
- "Auto-detect SKB or native mode"},
-
- {{"force", no_argument, NULL, 'F' },
- "Force install, replacing existing program on interface"},
-
- {{"unload", no_argument, NULL, 'U' },
- "Unload XDP program instead of loading"},
-
- {{"reuse-maps", no_argument, NULL, 'M' },
- "Reuse pinned maps"},
-
- {{"quiet", no_argument, NULL, 'q' },
- "Quiet mode (no output)"},
-
- {{"filename", required_argument, NULL, 1 },
- "Load program from <file>", "<file>"},
-
- {{"progsec", required_argument, NULL, 2 },
- "Load program in <section> of the ELF file", "<section>"},
-
- {{0, 0, NULL, 0 }, NULL, false}
-};
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-const char *pin_basedir = "/sys/fs/bpf";
-const char *map_name = "xdp_stats_map";
-
-/* Pinning maps under /sys/fs/bpf in subdir */
-int pin_maps_in_bpf_object(struct bpf_object *bpf_obj, struct config *cfg)
-{
- char map_filename[PATH_MAX];
- int err, len;
-
- len = snprintf(map_filename, PATH_MAX, "%s/%s/%s",
- pin_basedir, cfg->ifname, map_name);
- if (len < 0) {
- fprintf(stderr, "ERR: creating map_name\n");
- return EXIT_FAIL_OPTION;
- }
-
- /* Existing/previous XDP prog might not have cleaned up */
- if (access(map_filename, F_OK ) != -1 ) {
- if (verbose)
- printf(" - Unpinning (remove) prev maps in %s/\n",
- cfg->pin_dir);
-
- /* Basically calls unlink(3) on map_filename */
- err = bpf_object__unpin_maps(bpf_obj, cfg->pin_dir);
- if (err) {
- fprintf(stderr, "ERR: UNpinning maps in %s\n", cfg->pin_dir);
- return EXIT_FAIL_BPF;
- }
- }
- if (verbose)
- printf(" - Pinning maps in %s/\n", cfg->pin_dir);
-
- /* This will pin all maps in our bpf_object */
- err = bpf_object__pin_maps(bpf_obj, cfg->pin_dir);
- if (err)
- return EXIT_FAIL_BPF;
-
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- struct bpf_object *bpf_obj;
- int err, len;
-
- struct config cfg = {
- .xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST | XDP_FLAGS_DRV_MODE,
- .ifindex = -1,
- .do_unload = false,
- };
- /* Set default BPF-ELF object file and BPF program name */
- strncpy(cfg.filename, default_filename, sizeof(cfg.filename));
- /* Cmdline options can change progsec */
- parse_cmdline_args(argc, argv, long_options, &cfg, __doc__);
-
- /* Required option */
- if (cfg.ifindex == -1) {
- fprintf(stderr, "ERR: required option --dev missing\n\n");
- usage(argv[0], __doc__, long_options, (argc == 1));
- return EXIT_FAIL_OPTION;
- }
- if (cfg.do_unload) {
- if (!cfg.reuse_maps) {
- /* TODO: Miss unpin of maps on unload */
- }
- return xdp_link_detach(cfg.ifindex, cfg.xdp_flags, 0);
- }
-
- len = snprintf(cfg.pin_dir, PATH_MAX, "%s/%s", pin_basedir, cfg.ifname);
- if (len < 0) {
- fprintf(stderr, "ERR: creating pin dirname\n");
- return EXIT_FAIL_OPTION;
- }
-
-
- bpf_obj = load_bpf_and_xdp_attach(&cfg);
- if (!bpf_obj)
- return EXIT_FAIL_BPF;
-
- if (verbose) {
- printf("Success: Loaded BPF-object(%s) and used section(%s)\n",
- cfg.filename, cfg.progsec);
- printf(" - XDP prog attached on device:%s(ifindex:%d)\n",
- cfg.ifname, cfg.ifindex);
- }
-
- /* Use the --dev name as subdir for exporting/pinning maps */
- if (!cfg.reuse_maps) {
- err = pin_maps_in_bpf_object(bpf_obj, &cfg);
- if (err) {
- fprintf(stderr, "ERR: pinning maps\n");
- return err;
- }
- }
-
- return EXIT_OK;
-}
diff --git a/src/xdp/utils/xdp_stats.c b/src/xdp/utils/xdp_stats.c
deleted file mode 100644
index f9fa7438f..000000000
--- a/src/xdp/utils/xdp_stats.c
+++ /dev/null
@@ -1,298 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-static const char *__doc__ = "XDP stats program\n"
- " - Finding xdp_stats_map via --dev name info\n";
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <getopt.h>
-
-#include <locale.h>
-#include <unistd.h>
-#include <time.h>
-
-#include <bpf/bpf.h>
-/* Lesson#1: this prog does not need to #include <bpf/libbpf.h> as it only uses
- * the simple bpf-syscall wrappers, defined in libbpf #include<bpf/bpf.h>
- */
-
-#include <net/if.h>
-#include <linux/if_link.h> /* depend on kernel-headers installed */
-
-#include "../common/common_params.h"
-#include "../common/common_user_bpf_xdp.h"
-#include "../common/xdp_stats_kern_user.h"
-
-#include "../include/bpf_util.h" /* bpf_num_possible_cpus */
-
-static const struct option_wrapper long_options[] = {
- {{"help", no_argument, NULL, 'h' },
- "Show help", false},
-
- {{"dev", required_argument, NULL, 'd' },
- "Operate on device <ifname>", "<ifname>", true},
-
- {{"quiet", no_argument, NULL, 'q' },
- "Quiet mode (no output)"},
-
- {{0, 0, NULL, 0 }}
-};
-
-#define NANOSEC_PER_SEC 1000000000 /* 10^9 */
-static __u64 gettime(void)
-{
- struct timespec t;
- int res;
-
- res = clock_gettime(CLOCK_MONOTONIC, &t);
- if (res < 0) {
- fprintf(stderr, "Error with gettimeofday! (%i)\n", res);
- exit(EXIT_FAIL);
- }
- return (__u64) t.tv_sec * NANOSEC_PER_SEC + t.tv_nsec;
-}
-
-struct record {
- __u64 timestamp;
- struct datarec total; /* defined in common_kern_user.h */
-};
-
-struct stats_record {
- struct record stats[XDP_ACTION_MAX];
-};
-
-static double calc_period(struct record *r, struct record *p)
-{
- double period_ = 0;
- __u64 period = 0;
-
- period = r->timestamp - p->timestamp;
- if (period > 0)
- period_ = ((double) period / NANOSEC_PER_SEC);
-
- return period_;
-}
-
-static void stats_print_header()
-{
- /* Print stats "header" */
- printf("%-12s\n", "XDP-action");
-}
-
-static void stats_print(struct stats_record *stats_rec,
- struct stats_record *stats_prev)
-{
- struct record *rec, *prev;
- __u64 packets, bytes;
- double period;
- double pps; /* packets per sec */
- double bps; /* bits per sec */
- int i;
-
- stats_print_header(); /* Print stats "header" */
-
- /* Print for each XDP actions stats */
- for (i = 0; i < XDP_ACTION_MAX; i++)
- {
- char *fmt = "%-12s %'11lld pkts (%'10.0f pps)"
- " %'11lld Kbytes (%'6.0f Mbits/s)"
- " period:%f\n";
- const char *action = action2str(i);
-
- rec = &stats_rec->stats[i];
- prev = &stats_prev->stats[i];
-
- period = calc_period(rec, prev);
- if (period == 0)
- return;
-
- packets = rec->total.rx_packets - prev->total.rx_packets;
- pps = packets / period;
-
- bytes = rec->total.rx_bytes - prev->total.rx_bytes;
- bps = (bytes * 8)/ period / 1000000;
-
- printf(fmt, action, rec->total.rx_packets, pps,
- rec->total.rx_bytes / 1000 , bps,
- period);
- }
- printf("\n");
-}
-
-
-/* BPF_MAP_TYPE_ARRAY */
-void map_get_value_array(int fd, __u32 key, struct datarec *value)
-{
- if ((bpf_map_lookup_elem(fd, &key, value)) != 0) {
- fprintf(stderr,
- "ERR: bpf_map_lookup_elem failed key:0x%X\n", key);
- }
-}
-
-/* BPF_MAP_TYPE_PERCPU_ARRAY */
-void map_get_value_percpu_array(int fd, __u32 key, struct datarec *value)
-{
- /* For percpu maps, userspace gets a value per possible CPU */
- unsigned int nr_cpus = bpf_num_possible_cpus();
- struct datarec values[nr_cpus];
- __u64 sum_bytes = 0;
- __u64 sum_pkts = 0;
- int i;
-
- if ((bpf_map_lookup_elem(fd, &key, values)) != 0) {
- fprintf(stderr,
- "ERR: bpf_map_lookup_elem failed key:0x%X\n", key);
- return;
- }
-
- /* Sum values from each CPU */
- for (i = 0; i < nr_cpus; i++) {
- sum_pkts += values[i].rx_packets;
- sum_bytes += values[i].rx_bytes;
- }
- value->rx_packets = sum_pkts;
- value->rx_bytes = sum_bytes;
-}
-
-static bool map_collect(int fd, __u32 map_type, __u32 key, struct record *rec)
-{
- struct datarec value;
-
- /* Get time as close as possible to reading map contents */
- rec->timestamp = gettime();
-
- switch (map_type) {
- case BPF_MAP_TYPE_ARRAY:
- map_get_value_array(fd, key, &value);
- break;
- case BPF_MAP_TYPE_PERCPU_ARRAY:
- map_get_value_percpu_array(fd, key, &value);
- break;
- default:
- fprintf(stderr, "ERR: Unknown map_type(%u) cannot handle\n",
- map_type);
- return false;
- break;
- }
-
- rec->total.rx_packets = value.rx_packets;
- rec->total.rx_bytes = value.rx_bytes;
- return true;
-}
-
-static void stats_collect(int map_fd, __u32 map_type,
- struct stats_record *stats_rec)
-{
- /* Collect all XDP actions stats */
- __u32 key;
-
- for (key = 0; key < XDP_ACTION_MAX; key++) {
- map_collect(map_fd, map_type, key, &stats_rec->stats[key]);
- }
-}
-
-static int stats_poll(const char *pin_dir, int map_fd, __u32 id,
- __u32 map_type, int interval)
-{
- struct bpf_map_info info = {};
- struct stats_record prev, record = { 0 };
- int counter = 0;
-
- /* Trick to pretty printf with thousands separators use %' */
- setlocale(LC_NUMERIC, "en_US");
-
- /* Get initial reading quickly */
- stats_collect(map_fd, map_type, &record);
- usleep(1000000/4);
-
- while (1) {
- prev = record; /* struct copy */
-
- map_fd = open_bpf_map_file(pin_dir, "xdp_stats_map", &info);
- if (map_fd < 0) {
- return EXIT_FAIL_BPF;
- } else if (id != info.id) {
- printf("BPF map xdp_stats_map changed its ID, restarting\n");
- return 0;
- }
-
- stats_collect(map_fd, map_type, &record);
- stats_print(&record, &prev);
- sleep(interval);
- counter++;
- if (counter > 1) {
- return 0;
- }
- }
-
- return 0;
-}
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
-
-const char *pin_basedir = "/sys/fs/bpf";
-
-int main(int argc, char **argv)
-{
- const struct bpf_map_info map_expect = {
- .key_size = sizeof(__u32),
- .value_size = sizeof(struct datarec),
- .max_entries = XDP_ACTION_MAX,
- };
- struct bpf_map_info info = { 0 };
- char pin_dir[PATH_MAX];
- int stats_map_fd;
- int interval = 2;
- int len, err;
-
- struct config cfg = {
- .ifindex = -1,
- .do_unload = false,
- };
-
- /* Cmdline options can change progsec */
- parse_cmdline_args(argc, argv, long_options, &cfg, __doc__);
-
- /* Required option */
- if (cfg.ifindex == -1) {
- fprintf(stderr, "ERR: required option --dev missing\n\n");
- usage(argv[0], __doc__, long_options, (argc == 1));
- return EXIT_FAIL_OPTION;
- }
-
- /* Use the --dev name as subdir for finding pinned maps */
- len = snprintf(pin_dir, PATH_MAX, "%s/%s", pin_basedir, cfg.ifname);
- if (len < 0) {
- fprintf(stderr, "ERR: creating pin dirname\n");
- return EXIT_FAIL_OPTION;
- }
-
- stats_map_fd = open_bpf_map_file(pin_dir, "xdp_stats_map", &info);
- if (stats_map_fd < 0) {
- return EXIT_FAIL_BPF;
- }
-
- /* check map info, e.g. datarec is expected size */
- err = check_map_fd_info(&info, &map_expect);
- if (err) {
- fprintf(stderr, "ERR: map via FD not compatible\n");
- return err;
- }
- if (verbose) {
- printf("\nCollecting stats from BPF map\n");
- printf(" - BPF map (bpf_map_type:%d) id:%d name:%s"
- " key_size:%d value_size:%d max_entries:%d\n",
- info.type, info.id, info.name,
- info.key_size, info.value_size, info.max_entries
- );
- }
-
- err = stats_poll(pin_dir, stats_map_fd, info.id, info.type, interval);
- if (err < 0)
- return err;
-
- return EXIT_OK;
-}