mirror of
https://git.kernel.org/pub/scm/network/iproute2/iproute2.git
synced 2024-12-13 19:54:11 +08:00
c7272ca720
Now that we made the BPF loader generic as a library, reuse it for loading XDP programs as well. This basically adds a minimal start of a facility for iproute2 to load XDP programs. There currently only exists the xdp1_user.c sample code in the kernel tree that sets up netlink directly and an iovisor/bcc front-end. Since we have all the necessary infrastructure in place already from tc side, we can just reuse its loader back-end and thus facilitate migration and usability among the two for people familiar with tc/bpf already. Sharing maps, performing tail calls, etc works the same way as with tc. Naturally, once kernel configuration API evolves, we will extend new features for XDP here as well, resp. extend dumping of related netlink attributes. Minimal example: clang -target bpf -O2 -Wall -c prog.c -o prog.o ip [-force] link set dev em1 xdp obj prog.o # attaching ip [-d] link # dumping ip link set dev em1 xdp off # detaching For the dump, intention is that in the first line for each ip link entry, we'll see "xdp" to indicate that this device has an XDP program attached. Once we dump some more useful information via netlink (digest, etc), idea is that 'ip -d link' will then display additional relevant program information below the "link/ ether [...]" output line for such devices, for example. Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Alexei Starovoitov <ast@kernel.org>
76 lines
1.7 KiB
C
76 lines
1.7 KiB
C
/*
|
|
* iplink_xdp.c XDP program loader
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*
|
|
* Authors: Daniel Borkmann <daniel@iogearbox.net>
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <linux/bpf.h>
|
|
|
|
#include "xdp.h"
|
|
#include "bpf_util.h"
|
|
|
|
extern int force;
|
|
|
|
static void xdp_ebpf_cb(void *raw, int fd, const char *annotation)
|
|
{
|
|
__u32 flags = !force ? XDP_FLAGS_UPDATE_IF_NOEXIST : 0;
|
|
struct iplink_req *req = raw;
|
|
struct rtattr *xdp;
|
|
|
|
xdp = addattr_nest(&req->n, sizeof(*req), IFLA_XDP);
|
|
addattr32(&req->n, sizeof(*req), IFLA_XDP_FD, fd);
|
|
addattr32(&req->n, sizeof(*req), IFLA_XDP_FLAGS, flags);
|
|
addattr_nest_end(&req->n, xdp);
|
|
}
|
|
|
|
static const struct bpf_cfg_ops bpf_cb_ops = {
|
|
.ebpf_cb = xdp_ebpf_cb,
|
|
};
|
|
|
|
static int xdp_delete(struct iplink_req *req)
|
|
{
|
|
xdp_ebpf_cb(req, -1, NULL);
|
|
return 0;
|
|
}
|
|
|
|
int xdp_parse(int *argc, char ***argv, struct iplink_req *req)
|
|
{
|
|
struct bpf_cfg_in cfg = {
|
|
.argc = *argc,
|
|
.argv = *argv,
|
|
};
|
|
|
|
if (*argc == 1) {
|
|
if (strcmp(**argv, "none") == 0 ||
|
|
strcmp(**argv, "off") == 0)
|
|
return xdp_delete(req);
|
|
}
|
|
if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, req))
|
|
return -1;
|
|
|
|
*argc = cfg.argc;
|
|
*argv = cfg.argv;
|
|
return 0;
|
|
}
|
|
|
|
void xdp_dump(FILE *fp, struct rtattr *xdp)
|
|
{
|
|
struct rtattr *tb[IFLA_XDP_MAX + 1];
|
|
|
|
parse_rtattr_nested(tb, IFLA_XDP_MAX, xdp);
|
|
if (!tb[IFLA_XDP_ATTACHED] ||
|
|
!rta_getattr_u8(tb[IFLA_XDP_ATTACHED]))
|
|
return;
|
|
|
|
fprintf(fp, "xdp ");
|
|
/* More to come here in future for 'ip -d link' (digest, etc) ... */
|
|
}
|