2 * iplink_xdp.c XDP program loader
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
9 * Authors: Daniel Borkmann <daniel@iogearbox.net>
15 #include <linux/bpf.h>
19 #include "ip_common.h"
24 struct iplink_req
*req
;
28 static void xdp_ebpf_cb(void *raw
, int fd
, const char *annotation
)
30 struct xdp_req
*xdp
= raw
;
31 struct iplink_req
*req
= xdp
->req
;
32 struct rtattr
*xdp_attr
;
34 xdp_attr
= addattr_nest(&req
->n
, sizeof(*req
), IFLA_XDP
);
35 addattr32(&req
->n
, sizeof(*req
), IFLA_XDP_FD
, fd
);
37 addattr32(&req
->n
, sizeof(*req
), IFLA_XDP_FLAGS
, xdp
->flags
);
38 addattr_nest_end(&req
->n
, xdp_attr
);
41 static const struct bpf_cfg_ops bpf_cb_ops
= {
42 .ebpf_cb
= xdp_ebpf_cb
,
45 static int xdp_delete(struct xdp_req
*xdp
)
47 xdp_ebpf_cb(xdp
, -1, NULL
);
51 int xdp_parse(int *argc
, char ***argv
, struct iplink_req
*req
,
52 const char *ifname
, bool generic
, bool drv
, bool offload
)
54 struct bpf_cfg_in cfg
= {
55 .type
= BPF_PROG_TYPE_XDP
,
59 struct xdp_req xdp
= {
64 int ifindex
= ll_name_to_index(ifname
);
68 cfg
.ifindex
= ifindex
;
72 xdp
.flags
|= XDP_FLAGS_UPDATE_IF_NOEXIST
;
74 xdp
.flags
|= XDP_FLAGS_SKB_MODE
;
76 xdp
.flags
|= XDP_FLAGS_DRV_MODE
;
78 xdp
.flags
|= XDP_FLAGS_HW_MODE
;
81 if (strcmp(**argv
, "none") == 0 ||
82 strcmp(**argv
, "off") == 0)
83 return xdp_delete(&xdp
);
86 if (bpf_parse_and_load_common(&cfg
, &bpf_cb_ops
, &xdp
))
94 static void xdp_dump_json_one(struct rtattr
*tb
[IFLA_XDP_MAX
+ 1], __u32 attr
,
100 open_json_object(NULL
);
101 print_uint(PRINT_JSON
, "mode", NULL
, mode
);
102 bpf_dump_prog_info(NULL
, rta_getattr_u32(tb
[attr
]));
106 static void xdp_dump_json(struct rtattr
*tb
[IFLA_XDP_MAX
+ 1])
111 mode
= rta_getattr_u8(tb
[IFLA_XDP_ATTACHED
]);
112 if (tb
[IFLA_XDP_PROG_ID
])
113 prog_id
= rta_getattr_u32(tb
[IFLA_XDP_PROG_ID
]);
115 open_json_object("xdp");
116 print_uint(PRINT_JSON
, "mode", NULL
, mode
);
118 bpf_dump_prog_info(NULL
, prog_id
);
120 open_json_array(PRINT_JSON
, "attached");
121 if (tb
[IFLA_XDP_SKB_PROG_ID
] ||
122 tb
[IFLA_XDP_DRV_PROG_ID
] ||
123 tb
[IFLA_XDP_HW_PROG_ID
]) {
124 xdp_dump_json_one(tb
, IFLA_XDP_SKB_PROG_ID
, XDP_ATTACHED_SKB
);
125 xdp_dump_json_one(tb
, IFLA_XDP_DRV_PROG_ID
, XDP_ATTACHED_DRV
);
126 xdp_dump_json_one(tb
, IFLA_XDP_HW_PROG_ID
, XDP_ATTACHED_HW
);
127 } else if (tb
[IFLA_XDP_PROG_ID
]) {
128 /* Older kernel - use IFLA_XDP_PROG_ID */
129 xdp_dump_json_one(tb
, IFLA_XDP_PROG_ID
, mode
);
131 close_json_array(PRINT_JSON
, NULL
);
136 static void xdp_dump_prog_one(FILE *fp
, struct rtattr
*tb
[IFLA_XDP_MAX
+ 1],
137 __u32 attr
, bool link
, bool details
,
145 prog_id
= rta_getattr_u32(tb
[attr
]);
147 if (prog_id
&& !link
&& attr
== IFLA_XDP_PROG_ID
)
148 fprintf(fp
, "/id:%u", prog_id
);
153 fprintf(fp
, "%s prog/xdp%s ", _SL_
, pfx
);
154 bpf_dump_prog_info(fp
, prog_id
);
158 void xdp_dump(FILE *fp
, struct rtattr
*xdp
, bool link
, bool details
)
160 struct rtattr
*tb
[IFLA_XDP_MAX
+ 1];
163 parse_rtattr_nested(tb
, IFLA_XDP_MAX
, xdp
);
165 if (!tb
[IFLA_XDP_ATTACHED
])
168 mode
= rta_getattr_u8(tb
[IFLA_XDP_ATTACHED
]);
169 if (mode
== XDP_ATTACHED_NONE
)
171 else if (is_json_context())
172 return details
? (void)0 : xdp_dump_json(tb
);
173 else if (details
&& link
)
174 /* don't print mode */;
175 else if (mode
== XDP_ATTACHED_DRV
)
177 else if (mode
== XDP_ATTACHED_SKB
)
178 fprintf(fp
, "xdpgeneric");
179 else if (mode
== XDP_ATTACHED_HW
)
180 fprintf(fp
, "xdpoffload");
181 else if (mode
== XDP_ATTACHED_MULTI
)
182 fprintf(fp
, "xdpmulti");
184 fprintf(fp
, "xdp[%u]", mode
);
186 xdp_dump_prog_one(fp
, tb
, IFLA_XDP_PROG_ID
, link
, details
, "");
188 if (mode
== XDP_ATTACHED_MULTI
) {
189 xdp_dump_prog_one(fp
, tb
, IFLA_XDP_SKB_PROG_ID
, link
, details
,
191 xdp_dump_prog_one(fp
, tb
, IFLA_XDP_DRV_PROG_ID
, link
, details
,
193 xdp_dump_prog_one(fp
, tb
, IFLA_XDP_HW_PROG_ID
, link
, details
,
197 if (!details
|| !link
)