xref: /aosp_15_r20/external/iproute2/ip/iplink_xdp.c (revision de1e4e894b0c224df933550f0afdecc354b238c4)
1*de1e4e89SAndroid Build Coastguard Worker /*
2*de1e4e89SAndroid Build Coastguard Worker  * iplink_xdp.c XDP program loader
3*de1e4e89SAndroid Build Coastguard Worker  *
4*de1e4e89SAndroid Build Coastguard Worker  *              This program is free software; you can redistribute it and/or
5*de1e4e89SAndroid Build Coastguard Worker  *              modify it under the terms of the GNU General Public License
6*de1e4e89SAndroid Build Coastguard Worker  *              as published by the Free Software Foundation; either version
7*de1e4e89SAndroid Build Coastguard Worker  *              2 of the License, or (at your option) any later version.
8*de1e4e89SAndroid Build Coastguard Worker  *
9*de1e4e89SAndroid Build Coastguard Worker  * Authors:     Daniel Borkmann <[email protected]>
10*de1e4e89SAndroid Build Coastguard Worker  */
11*de1e4e89SAndroid Build Coastguard Worker 
12*de1e4e89SAndroid Build Coastguard Worker #include <stdio.h>
13*de1e4e89SAndroid Build Coastguard Worker #include <stdlib.h>
14*de1e4e89SAndroid Build Coastguard Worker 
15*de1e4e89SAndroid Build Coastguard Worker #include <linux/bpf.h>
16*de1e4e89SAndroid Build Coastguard Worker 
17*de1e4e89SAndroid Build Coastguard Worker #include "json_print.h"
18*de1e4e89SAndroid Build Coastguard Worker #include "xdp.h"
19*de1e4e89SAndroid Build Coastguard Worker #include "bpf_util.h"
20*de1e4e89SAndroid Build Coastguard Worker 
21*de1e4e89SAndroid Build Coastguard Worker extern int force;
22*de1e4e89SAndroid Build Coastguard Worker 
23*de1e4e89SAndroid Build Coastguard Worker struct xdp_req {
24*de1e4e89SAndroid Build Coastguard Worker 	struct iplink_req *req;
25*de1e4e89SAndroid Build Coastguard Worker 	__u32 flags;
26*de1e4e89SAndroid Build Coastguard Worker };
27*de1e4e89SAndroid Build Coastguard Worker 
xdp_ebpf_cb(void * raw,int fd,const char * annotation)28*de1e4e89SAndroid Build Coastguard Worker static void xdp_ebpf_cb(void *raw, int fd, const char *annotation)
29*de1e4e89SAndroid Build Coastguard Worker {
30*de1e4e89SAndroid Build Coastguard Worker 	struct xdp_req *xdp = raw;
31*de1e4e89SAndroid Build Coastguard Worker 	struct iplink_req *req = xdp->req;
32*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *xdp_attr;
33*de1e4e89SAndroid Build Coastguard Worker 
34*de1e4e89SAndroid Build Coastguard Worker 	xdp_attr = addattr_nest(&req->n, sizeof(*req), IFLA_XDP);
35*de1e4e89SAndroid Build Coastguard Worker 	addattr32(&req->n, sizeof(*req), IFLA_XDP_FD, fd);
36*de1e4e89SAndroid Build Coastguard Worker 	if (xdp->flags)
37*de1e4e89SAndroid Build Coastguard Worker 		addattr32(&req->n, sizeof(*req), IFLA_XDP_FLAGS, xdp->flags);
38*de1e4e89SAndroid Build Coastguard Worker 	addattr_nest_end(&req->n, xdp_attr);
39*de1e4e89SAndroid Build Coastguard Worker }
40*de1e4e89SAndroid Build Coastguard Worker 
41*de1e4e89SAndroid Build Coastguard Worker static const struct bpf_cfg_ops bpf_cb_ops = {
42*de1e4e89SAndroid Build Coastguard Worker 	.ebpf_cb = xdp_ebpf_cb,
43*de1e4e89SAndroid Build Coastguard Worker };
44*de1e4e89SAndroid Build Coastguard Worker 
xdp_delete(struct xdp_req * xdp)45*de1e4e89SAndroid Build Coastguard Worker static int xdp_delete(struct xdp_req *xdp)
46*de1e4e89SAndroid Build Coastguard Worker {
47*de1e4e89SAndroid Build Coastguard Worker 	xdp_ebpf_cb(xdp, -1, NULL);
48*de1e4e89SAndroid Build Coastguard Worker 	return 0;
49*de1e4e89SAndroid Build Coastguard Worker }
50*de1e4e89SAndroid Build Coastguard Worker 
xdp_parse(int * argc,char *** argv,struct iplink_req * req,bool generic,bool drv,bool offload)51*de1e4e89SAndroid Build Coastguard Worker int xdp_parse(int *argc, char ***argv, struct iplink_req *req, bool generic,
52*de1e4e89SAndroid Build Coastguard Worker 	      bool drv, bool offload)
53*de1e4e89SAndroid Build Coastguard Worker {
54*de1e4e89SAndroid Build Coastguard Worker 	struct bpf_cfg_in cfg = {
55*de1e4e89SAndroid Build Coastguard Worker 		.argc = *argc,
56*de1e4e89SAndroid Build Coastguard Worker 		.argv = *argv,
57*de1e4e89SAndroid Build Coastguard Worker 	};
58*de1e4e89SAndroid Build Coastguard Worker 	struct xdp_req xdp = {
59*de1e4e89SAndroid Build Coastguard Worker 		.req = req,
60*de1e4e89SAndroid Build Coastguard Worker 	};
61*de1e4e89SAndroid Build Coastguard Worker 
62*de1e4e89SAndroid Build Coastguard Worker 	if (!force)
63*de1e4e89SAndroid Build Coastguard Worker 		xdp.flags |= XDP_FLAGS_UPDATE_IF_NOEXIST;
64*de1e4e89SAndroid Build Coastguard Worker 	if (generic)
65*de1e4e89SAndroid Build Coastguard Worker 		xdp.flags |= XDP_FLAGS_SKB_MODE;
66*de1e4e89SAndroid Build Coastguard Worker 	if (drv)
67*de1e4e89SAndroid Build Coastguard Worker 		xdp.flags |= XDP_FLAGS_DRV_MODE;
68*de1e4e89SAndroid Build Coastguard Worker 	if (offload)
69*de1e4e89SAndroid Build Coastguard Worker 		xdp.flags |= XDP_FLAGS_HW_MODE;
70*de1e4e89SAndroid Build Coastguard Worker 
71*de1e4e89SAndroid Build Coastguard Worker 	if (*argc == 1) {
72*de1e4e89SAndroid Build Coastguard Worker 		if (strcmp(**argv, "none") == 0 ||
73*de1e4e89SAndroid Build Coastguard Worker 		    strcmp(**argv, "off") == 0)
74*de1e4e89SAndroid Build Coastguard Worker 			return xdp_delete(&xdp);
75*de1e4e89SAndroid Build Coastguard Worker 	}
76*de1e4e89SAndroid Build Coastguard Worker 
77*de1e4e89SAndroid Build Coastguard Worker 	if (bpf_parse_common(BPF_PROG_TYPE_XDP, &cfg, &bpf_cb_ops, &xdp))
78*de1e4e89SAndroid Build Coastguard Worker 		return -1;
79*de1e4e89SAndroid Build Coastguard Worker 
80*de1e4e89SAndroid Build Coastguard Worker 	*argc = cfg.argc;
81*de1e4e89SAndroid Build Coastguard Worker 	*argv = cfg.argv;
82*de1e4e89SAndroid Build Coastguard Worker 	return 0;
83*de1e4e89SAndroid Build Coastguard Worker }
84*de1e4e89SAndroid Build Coastguard Worker 
xdp_dump_json(struct rtattr * tb[IFLA_XDP_MAX+1])85*de1e4e89SAndroid Build Coastguard Worker static void xdp_dump_json(struct rtattr *tb[IFLA_XDP_MAX + 1])
86*de1e4e89SAndroid Build Coastguard Worker {
87*de1e4e89SAndroid Build Coastguard Worker 	__u32 prog_id = 0;
88*de1e4e89SAndroid Build Coastguard Worker 	__u8 mode;
89*de1e4e89SAndroid Build Coastguard Worker 
90*de1e4e89SAndroid Build Coastguard Worker 	mode = rta_getattr_u8(tb[IFLA_XDP_ATTACHED]);
91*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_XDP_PROG_ID])
92*de1e4e89SAndroid Build Coastguard Worker 		prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]);
93*de1e4e89SAndroid Build Coastguard Worker 
94*de1e4e89SAndroid Build Coastguard Worker 	open_json_object("xdp");
95*de1e4e89SAndroid Build Coastguard Worker 	print_uint(PRINT_JSON, "mode", NULL, mode);
96*de1e4e89SAndroid Build Coastguard Worker 	if (prog_id)
97*de1e4e89SAndroid Build Coastguard Worker 		bpf_dump_prog_info(NULL, prog_id);
98*de1e4e89SAndroid Build Coastguard Worker 	close_json_object();
99*de1e4e89SAndroid Build Coastguard Worker }
100*de1e4e89SAndroid Build Coastguard Worker 
xdp_dump(FILE * fp,struct rtattr * xdp,bool link,bool details)101*de1e4e89SAndroid Build Coastguard Worker void xdp_dump(FILE *fp, struct rtattr *xdp, bool link, bool details)
102*de1e4e89SAndroid Build Coastguard Worker {
103*de1e4e89SAndroid Build Coastguard Worker 	struct rtattr *tb[IFLA_XDP_MAX + 1];
104*de1e4e89SAndroid Build Coastguard Worker 	__u32 prog_id = 0;
105*de1e4e89SAndroid Build Coastguard Worker 	__u8 mode;
106*de1e4e89SAndroid Build Coastguard Worker 
107*de1e4e89SAndroid Build Coastguard Worker 	parse_rtattr_nested(tb, IFLA_XDP_MAX, xdp);
108*de1e4e89SAndroid Build Coastguard Worker 
109*de1e4e89SAndroid Build Coastguard Worker 	if (!tb[IFLA_XDP_ATTACHED])
110*de1e4e89SAndroid Build Coastguard Worker 		return;
111*de1e4e89SAndroid Build Coastguard Worker 
112*de1e4e89SAndroid Build Coastguard Worker 	mode = rta_getattr_u8(tb[IFLA_XDP_ATTACHED]);
113*de1e4e89SAndroid Build Coastguard Worker 	if (mode == XDP_ATTACHED_NONE)
114*de1e4e89SAndroid Build Coastguard Worker 		return;
115*de1e4e89SAndroid Build Coastguard Worker 	else if (is_json_context())
116*de1e4e89SAndroid Build Coastguard Worker 		return details ? (void)0 : xdp_dump_json(tb);
117*de1e4e89SAndroid Build Coastguard Worker 	else if (details && link)
118*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "%s    prog/xdp", _SL_);
119*de1e4e89SAndroid Build Coastguard Worker 	else if (mode == XDP_ATTACHED_DRV)
120*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "xdp");
121*de1e4e89SAndroid Build Coastguard Worker 	else if (mode == XDP_ATTACHED_SKB)
122*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "xdpgeneric");
123*de1e4e89SAndroid Build Coastguard Worker 	else if (mode == XDP_ATTACHED_HW)
124*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "xdpoffload");
125*de1e4e89SAndroid Build Coastguard Worker 	else
126*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, "xdp[%u]", mode);
127*de1e4e89SAndroid Build Coastguard Worker 
128*de1e4e89SAndroid Build Coastguard Worker 	if (tb[IFLA_XDP_PROG_ID])
129*de1e4e89SAndroid Build Coastguard Worker 		prog_id = rta_getattr_u32(tb[IFLA_XDP_PROG_ID]);
130*de1e4e89SAndroid Build Coastguard Worker 	if (!details) {
131*de1e4e89SAndroid Build Coastguard Worker 		if (prog_id && !link)
132*de1e4e89SAndroid Build Coastguard Worker 			fprintf(fp, "/id:%u", prog_id);
133*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, " ");
134*de1e4e89SAndroid Build Coastguard Worker 		return;
135*de1e4e89SAndroid Build Coastguard Worker 	}
136*de1e4e89SAndroid Build Coastguard Worker 
137*de1e4e89SAndroid Build Coastguard Worker 	if (prog_id) {
138*de1e4e89SAndroid Build Coastguard Worker 		fprintf(fp, " ");
139*de1e4e89SAndroid Build Coastguard Worker 		bpf_dump_prog_info(fp, prog_id);
140*de1e4e89SAndroid Build Coastguard Worker 	}
141*de1e4e89SAndroid Build Coastguard Worker }
142