#include "test_utils.h"
#include "../libxdp_internal.h"
-#include "xdp_dispatcher_v1.h"
+#include "xdp_dispatcher.h"
#include <xdp/libxdp.h>
#include <bpf/libbpf.h>
#define PROG_RUN_PRIO 42
#define PROG_CHAIN_CALL_ACTIONS (1 << XDP_DROP)
+#define DISPATCHER_V1_FILE "xdp_dispatcher_v1.o"
+#define DISPATCHER_V2_FILE "xdp_dispatcher_v2.o"
+
+static void print_test_result(const char *func, int ret)
+{
+ fflush(stderr);
+ fprintf(stderr, "%s:\t%s\n", func, ret ? "FAILED" : "PASSED");
+ fflush(stdout);
+}
int get_prog_id(int prog_fd)
{
return info.id;
}
-int load_dispatcher_v1(int ifindex)
+static char* get_dispatcher_file(unsigned int dispatcher_version)
+{
+ switch (dispatcher_version) {
+ case XDP_DISPATCHER_VERSION_V1:
+ return DISPATCHER_V1_FILE;
+
+ case XDP_DISPATCHER_VERSION_V2:
+ return DISPATCHER_V2_FILE;
+
+ default:
+ break;
+ }
+ return NULL;
+}
+
+int load_dispatcher(int ifindex, unsigned int dispatcher_version)
{
- struct xdp_dispatcher_config_v1 dispatcher_config = {};
+ struct xdp_dispatcher_config_v1 dispatcher_config_v1 = {};
+ struct xdp_dispatcher_config_v2 dispatcher_config_v2 = {};
+ char *dispatcher_file = get_dispatcher_file(dispatcher_version);
struct bpf_object *obj_dispatcher, *obj_prog = NULL;
DECLARE_LIBBPF_OPTS(bpf_link_create_opts, opts);
struct bpf_program *dispatcher_prog, *xdp_prog;
- int ret, btf_id, lfd = -1, dispatcher_id;
+ int ret = 0, btf_id, lfd = -1, dispatcher_id;
char pin_path[PATH_MAX], buf[PATH_MAX];
const char *attach_func = "prog0";
struct bpf_map *map;
- if (!ifindex)
+ if (!ifindex || !dispatcher_file)
return -ENOENT;
- obj_dispatcher = open_bpf_file("xdp_dispatcher_v1.o", NULL);
+ obj_dispatcher = open_bpf_file(dispatcher_file, NULL);
if (IS_ERR_OR_NULL(obj_dispatcher))
return -errno;
}
dispatcher_prog = bpf_object__find_program_by_name(obj_dispatcher,
- "xdp_dispatcher");
+ "xdp_dispatcher");
if (!dispatcher_prog) {
ret = -errno;
goto out;
}
- dispatcher_config.num_progs_enabled = 1;
- dispatcher_config.chain_call_actions[0] = PROG_CHAIN_CALL_ACTIONS;
- dispatcher_config.run_prios[0] = PROG_RUN_PRIO;
+ switch (dispatcher_version) {
+ case XDP_DISPATCHER_VERSION_V1:
+ dispatcher_config_v1.num_progs_enabled = 1;
+ dispatcher_config_v1.chain_call_actions[0] = PROG_CHAIN_CALL_ACTIONS;
+ dispatcher_config_v1.run_prios[0] = PROG_RUN_PRIO;
+
+ ret = bpf_map__set_initial_value(map, &dispatcher_config_v1,
+ sizeof(dispatcher_config_v1));
+ break;
+
+ case XDP_DISPATCHER_VERSION_V2:
+ dispatcher_config_v2.magic = XDP_DISPATCHER_MAGIC;
+ dispatcher_config_v2.num_progs_enabled = 1;
+ dispatcher_config_v2.chain_call_actions[0] = PROG_CHAIN_CALL_ACTIONS;
+ dispatcher_config_v2.run_prios[0] = PROG_RUN_PRIO;
+ dispatcher_config_v2.is_xdp_frags = 0;
+ dispatcher_config_v2.program_flags[0] = 0;
+ dispatcher_config_v2.dispatcher_version = XDP_DISPATCHER_VERSION_V2;
+
+ ret = bpf_map__set_initial_value(map, &dispatcher_config_v2,
+ sizeof(dispatcher_config_v2));
+ }
- ret = bpf_map__set_initial_value(map, &dispatcher_config,
- sizeof(dispatcher_config));
if (ret)
goto out;
-
ret = bpf_object__load(obj_dispatcher);
if (ret)
goto out;
goto out;
}
-int check_old_dispatcher(int ifindex)
+int check_old_dispatcher(int ifindex, unsigned int dispatcher_version)
{
struct xdp_multiprog *mp = NULL;
struct xdp_program *xdp_prog;
char buf[100];
int ret;
- ret = load_dispatcher_v1(ifindex);
+ ret = load_dispatcher(ifindex, dispatcher_version);
if (ret)
goto out;
exit(EXIT_FAILURE);
}
+int check_old_dispatcher_v1(int ifindex)
+{
+ int ret = check_old_dispatcher(ifindex, XDP_DISPATCHER_VERSION_V1);
+ print_test_result(__func__, ret);
+ return ret;
+}
+
+int check_old_dispatcher_v2(int ifindex)
+{
+ int ret = check_old_dispatcher(ifindex, XDP_DISPATCHER_VERSION_V2);
+ print_test_result(__func__, ret);
+ return ret;
+}
+
int main(int argc, char **argv)
{
int ifindex, ret;
ifindex = if_nametoindex(argv[1]);
- ret = check_old_dispatcher(ifindex);
+ ret = check_old_dispatcher_v1(ifindex);
+ ret = check_old_dispatcher_v2(ifindex) || ret;
return ret;
}
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __XDP_DISPATCHER_H
+#define __XDP_DISPATCHER_H
+
+#ifndef MAX_DISPATCHER_ACTIONS
+#define MAX_DISPATCHER_ACTIONS 10
+#endif
+
+struct xdp_dispatcher_config_v1 {
+ __u8 num_progs_enabled;
+ __u32 chain_call_actions[MAX_DISPATCHER_ACTIONS];
+ __u32 run_prios[MAX_DISPATCHER_ACTIONS];
+};
+
+#define XDP_DISPATCHER_VERSION_V1 1
+
+struct xdp_dispatcher_config_v2 {
+ __u8 magic; /* Set to XDP_DISPATCHER_MAGIC */
+ __u8 dispatcher_version; /* Set to XDP_DISPATCHER_VERSION */
+ __u8 num_progs_enabled; /* Number of active program slots */
+ __u8 is_xdp_frags; /* Whether this dispatcher is loaded with XDP frags support */
+ __u32 chain_call_actions[MAX_DISPATCHER_ACTIONS];
+ __u32 run_prios[MAX_DISPATCHER_ACTIONS];
+ __u32 program_flags[MAX_DISPATCHER_ACTIONS];
+};
+
+#define XDP_DISPATCHER_MAGIC 236
+#define XDP_DISPATCHER_VERSION_V2 2
+
+#endif
--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_endian.h>
+
+#include "xdp_dispatcher.h"
+
+#define XDP_METADATA_SECTION "xdp_metadata"
+#define XDP_DISPATCHER_RETVAL 31
+
+
+static volatile const struct xdp_dispatcher_config_v2 conf = {};
+
+__attribute__ ((noinline))
+int prog0(struct xdp_md *ctx) {
+ volatile int ret = XDP_DISPATCHER_RETVAL;
+
+ if (!ctx)
+ return XDP_ABORTED;
+ return ret;
+}
+__attribute__ ((noinline))
+
+SEC("xdp")
+int xdp_dispatcher(struct xdp_md *ctx)
+{
+ __u8 num_progs_enabled = conf.num_progs_enabled;
+ int ret;
+
+ if (num_progs_enabled < 1)
+ goto out;
+ ret = prog0(ctx);
+ if (!((1U << ret) & conf.chain_call_actions[0]))
+ return ret;
+
+out:
+ return XDP_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
+__uint(dispatcher_version, XDP_DISPATCHER_VERSION_V2) SEC(XDP_METADATA_SECTION);