bpf: add support for generic xdp

Follow-up to commit c7272ca720 ("bpf: add initial support for
attaching xdp progs") to also support generic XDP. This adds an
indicator for loaded generic XDP programs when programs are loaded
as shown in c7272ca720, but the driver still lacks native XDP
support.

  # ip link
  [...]
  3: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 xdpgeneric qdisc [...]
      link/ether 0c:c4:7a:03:f9:25 brd ff:ff:ff:ff:ff:ff
  [...]

In case the driver does support native XDP, but the user wants
to load the program as generic XDP (e.g. for testing purposes),
then this can be done with the same semantics as in c7272ca720,
but with 'xdpgeneric' instead of 'xdp' command for loading:

  # ip -force link set dev eno1 xdpgeneric obj xdp.o

Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Daniel Borkmann 2017-04-28 15:44:29 +02:00 committed by Stephen Hemminger
parent 7ff1fce549
commit a872b870a5
4 changed files with 56 additions and 18 deletions

View File

@ -612,9 +612,12 @@ int iplink_parse(int argc, char **argv, struct iplink_req *req,
if (get_integer(&mtu, *argv, 0))
invarg("Invalid \"mtu\" value\n", *argv);
addattr_l(&req->n, sizeof(*req), IFLA_MTU, &mtu, 4);
} else if (strcmp(*argv, "xdp") == 0) {
} else if (strcmp(*argv, "xdpgeneric") == 0 ||
strcmp(*argv, "xdp") == 0) {
bool generic = strcmp(*argv, "xdpgeneric") == 0;
NEXT_ARG();
if (xdp_parse(&argc, &argv, req))
if (xdp_parse(&argc, &argv, req, generic))
exit(-1);
} else if (strcmp(*argv, "netns") == 0) {
NEXT_ARG();

View File

@ -19,41 +19,56 @@
extern int force;
struct xdp_req {
struct iplink_req *req;
__u32 flags;
};
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;
struct xdp_req *xdp = raw;
struct iplink_req *req = xdp->req;
struct rtattr *xdp_attr;
xdp = addattr_nest(&req->n, sizeof(*req), IFLA_XDP);
xdp_attr = 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);
if (xdp->flags)
addattr32(&req->n, sizeof(*req), IFLA_XDP_FLAGS, xdp->flags);
addattr_nest_end(&req->n, xdp_attr);
}
static const struct bpf_cfg_ops bpf_cb_ops = {
.ebpf_cb = xdp_ebpf_cb,
};
static int xdp_delete(struct iplink_req *req)
static int xdp_delete(struct xdp_req *xdp)
{
xdp_ebpf_cb(req, -1, NULL);
xdp_ebpf_cb(xdp, -1, NULL);
return 0;
}
int xdp_parse(int *argc, char ***argv, struct iplink_req *req)
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic)
{
struct bpf_cfg_in cfg = {
.argc = *argc,
.argv = *argv,
};
struct xdp_req xdp = {
.req = req,
};
if (!force)
xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
if (generic)
xdp.flags |= XDP_FLAGS_SKB_MODE;
if (*argc == 1) {
if (strcmp(**argv, "none") == 0 ||
strcmp(**argv, "off") == 0)
return xdp_delete(req);
return xdp_delete(&xdp);
}
if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, req))
if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, &xdp))
return -1;
*argc = cfg.argc;
@ -64,12 +79,17 @@ int xdp_parse(int *argc, char ***argv, struct iplink_req *req)
void xdp_dump(FILE *fp, struct rtattr *xdp)
{
struct rtattr *tb[IFLA_XDP_MAX + 1];
__u32 flags = 0;
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) ... */
if (tb[IFLA_XDP_FLAGS])
flags = rta_getattr_u32(tb[IFLA_XDP_FLAGS]);
fprintf(fp, "xdp%s ",
flags & XDP_FLAGS_SKB_MODE ? "generic" : "");
}

View File

@ -3,7 +3,7 @@
#include "utils.h"
int xdp_parse(int *argc, char ***argv, struct iplink_req *req);
int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic);
void xdp_dump(FILE *fp, struct rtattr *tb);
#endif /* __XDP__ */

View File

@ -126,7 +126,7 @@ ip-link \- network device configuration
.RB "[ " port_guid " eui64 ] ]"
.br
.in -9
.RB "[ " xdp " { " off " | "
.RB "[ { " xdp " | " xdpgeneric " } { " off " | "
.br
.in +8
.BR object
@ -1572,8 +1572,23 @@ which may impact security and/or performance. (e.g. VF multicast promiscuous mod
.TP
.B xdp object "|" pinned "|" off
set (or unset) a XDP ("express data path") BPF program to run on every
set (or unset) a XDP ("eXpress Data Path") BPF program to run on every
packet at driver level.
.B ip link
output will indicate a
.B xdp
flag for the networking device. If the driver does not have native XDP
support, the kernel will fall back to a slower, driver-independent "generic"
XDP variant. The
.B ip link
output will in that case indicate
.B xdpgeneric
instead of
.B xdp
only. If the driver does have native XDP support, but the program is
loaded under
.B xdpgeneric object "|" pinned
then the kernel will use the generic XDP variant instead of the native one.
.B off
(or