xref: /aosp_15_r20/external/bpftool/src/netlink_dumper.c (revision 858ea5e570667251cdc31d3fe7b846b591105938)
1*858ea5e5SAndroid Build Coastguard Worker // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2*858ea5e5SAndroid Build Coastguard Worker // Copyright (C) 2018 Facebook
3*858ea5e5SAndroid Build Coastguard Worker 
4*858ea5e5SAndroid Build Coastguard Worker #include <stdlib.h>
5*858ea5e5SAndroid Build Coastguard Worker #include <string.h>
6*858ea5e5SAndroid Build Coastguard Worker #include <bpf/libbpf.h>
7*858ea5e5SAndroid Build Coastguard Worker #include <linux/rtnetlink.h>
8*858ea5e5SAndroid Build Coastguard Worker #include <linux/tc_act/tc_bpf.h>
9*858ea5e5SAndroid Build Coastguard Worker 
10*858ea5e5SAndroid Build Coastguard Worker #include "bpf/nlattr.h"
11*858ea5e5SAndroid Build Coastguard Worker #include "main.h"
12*858ea5e5SAndroid Build Coastguard Worker #include "netlink_dumper.h"
13*858ea5e5SAndroid Build Coastguard Worker 
xdp_dump_prog_id(struct nlattr ** tb,int attr,const char * mode,bool new_json_object)14*858ea5e5SAndroid Build Coastguard Worker static void xdp_dump_prog_id(struct nlattr **tb, int attr,
15*858ea5e5SAndroid Build Coastguard Worker 			     const char *mode,
16*858ea5e5SAndroid Build Coastguard Worker 			     bool new_json_object)
17*858ea5e5SAndroid Build Coastguard Worker {
18*858ea5e5SAndroid Build Coastguard Worker 	if (!tb[attr])
19*858ea5e5SAndroid Build Coastguard Worker 		return;
20*858ea5e5SAndroid Build Coastguard Worker 
21*858ea5e5SAndroid Build Coastguard Worker 	if (new_json_object)
22*858ea5e5SAndroid Build Coastguard Worker 		NET_START_OBJECT
23*858ea5e5SAndroid Build Coastguard Worker 	NET_DUMP_STR("mode", " %s", mode);
24*858ea5e5SAndroid Build Coastguard Worker 	NET_DUMP_UINT("id", " id %u", libbpf_nla_getattr_u32(tb[attr]))
25*858ea5e5SAndroid Build Coastguard Worker 	if (new_json_object)
26*858ea5e5SAndroid Build Coastguard Worker 		NET_END_OBJECT
27*858ea5e5SAndroid Build Coastguard Worker }
28*858ea5e5SAndroid Build Coastguard Worker 
do_xdp_dump_one(struct nlattr * attr,unsigned int ifindex,const char * name)29*858ea5e5SAndroid Build Coastguard Worker static int do_xdp_dump_one(struct nlattr *attr, unsigned int ifindex,
30*858ea5e5SAndroid Build Coastguard Worker 			   const char *name)
31*858ea5e5SAndroid Build Coastguard Worker {
32*858ea5e5SAndroid Build Coastguard Worker 	struct nlattr *tb[IFLA_XDP_MAX + 1];
33*858ea5e5SAndroid Build Coastguard Worker 	unsigned char mode;
34*858ea5e5SAndroid Build Coastguard Worker 
35*858ea5e5SAndroid Build Coastguard Worker 	if (libbpf_nla_parse_nested(tb, IFLA_XDP_MAX, attr, NULL) < 0)
36*858ea5e5SAndroid Build Coastguard Worker 		return -1;
37*858ea5e5SAndroid Build Coastguard Worker 
38*858ea5e5SAndroid Build Coastguard Worker 	if (!tb[IFLA_XDP_ATTACHED])
39*858ea5e5SAndroid Build Coastguard Worker 		return 0;
40*858ea5e5SAndroid Build Coastguard Worker 
41*858ea5e5SAndroid Build Coastguard Worker 	mode = libbpf_nla_getattr_u8(tb[IFLA_XDP_ATTACHED]);
42*858ea5e5SAndroid Build Coastguard Worker 	if (mode == XDP_ATTACHED_NONE)
43*858ea5e5SAndroid Build Coastguard Worker 		return 0;
44*858ea5e5SAndroid Build Coastguard Worker 
45*858ea5e5SAndroid Build Coastguard Worker 	NET_START_OBJECT;
46*858ea5e5SAndroid Build Coastguard Worker 	if (name)
47*858ea5e5SAndroid Build Coastguard Worker 		NET_DUMP_STR("devname", "%s", name);
48*858ea5e5SAndroid Build Coastguard Worker 	NET_DUMP_UINT("ifindex", "(%d)", ifindex);
49*858ea5e5SAndroid Build Coastguard Worker 
50*858ea5e5SAndroid Build Coastguard Worker 	if (mode == XDP_ATTACHED_MULTI) {
51*858ea5e5SAndroid Build Coastguard Worker 		if (json_output) {
52*858ea5e5SAndroid Build Coastguard Worker 			jsonw_name(json_wtr, "multi_attachments");
53*858ea5e5SAndroid Build Coastguard Worker 			jsonw_start_array(json_wtr);
54*858ea5e5SAndroid Build Coastguard Worker 		}
55*858ea5e5SAndroid Build Coastguard Worker 		xdp_dump_prog_id(tb, IFLA_XDP_SKB_PROG_ID, "generic", true);
56*858ea5e5SAndroid Build Coastguard Worker 		xdp_dump_prog_id(tb, IFLA_XDP_DRV_PROG_ID, "driver", true);
57*858ea5e5SAndroid Build Coastguard Worker 		xdp_dump_prog_id(tb, IFLA_XDP_HW_PROG_ID, "offload", true);
58*858ea5e5SAndroid Build Coastguard Worker 		if (json_output)
59*858ea5e5SAndroid Build Coastguard Worker 			jsonw_end_array(json_wtr);
60*858ea5e5SAndroid Build Coastguard Worker 	} else if (mode == XDP_ATTACHED_DRV) {
61*858ea5e5SAndroid Build Coastguard Worker 		xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "driver", false);
62*858ea5e5SAndroid Build Coastguard Worker 	} else if (mode == XDP_ATTACHED_SKB) {
63*858ea5e5SAndroid Build Coastguard Worker 		xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "generic", false);
64*858ea5e5SAndroid Build Coastguard Worker 	} else if (mode == XDP_ATTACHED_HW) {
65*858ea5e5SAndroid Build Coastguard Worker 		xdp_dump_prog_id(tb, IFLA_XDP_PROG_ID, "offload", false);
66*858ea5e5SAndroid Build Coastguard Worker 	}
67*858ea5e5SAndroid Build Coastguard Worker 
68*858ea5e5SAndroid Build Coastguard Worker 	NET_END_OBJECT_FINAL;
69*858ea5e5SAndroid Build Coastguard Worker 	return 0;
70*858ea5e5SAndroid Build Coastguard Worker }
71*858ea5e5SAndroid Build Coastguard Worker 
do_xdp_dump(struct ifinfomsg * ifinfo,struct nlattr ** tb)72*858ea5e5SAndroid Build Coastguard Worker int do_xdp_dump(struct ifinfomsg *ifinfo, struct nlattr **tb)
73*858ea5e5SAndroid Build Coastguard Worker {
74*858ea5e5SAndroid Build Coastguard Worker 	if (!tb[IFLA_XDP])
75*858ea5e5SAndroid Build Coastguard Worker 		return 0;
76*858ea5e5SAndroid Build Coastguard Worker 
77*858ea5e5SAndroid Build Coastguard Worker 	return do_xdp_dump_one(tb[IFLA_XDP], ifinfo->ifi_index,
78*858ea5e5SAndroid Build Coastguard Worker 			       libbpf_nla_getattr_str(tb[IFLA_IFNAME]));
79*858ea5e5SAndroid Build Coastguard Worker }
80*858ea5e5SAndroid Build Coastguard Worker 
do_bpf_dump_one_act(struct nlattr * attr)81*858ea5e5SAndroid Build Coastguard Worker static int do_bpf_dump_one_act(struct nlattr *attr)
82*858ea5e5SAndroid Build Coastguard Worker {
83*858ea5e5SAndroid Build Coastguard Worker 	struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
84*858ea5e5SAndroid Build Coastguard Worker 
85*858ea5e5SAndroid Build Coastguard Worker 	if (libbpf_nla_parse_nested(tb, TCA_ACT_BPF_MAX, attr, NULL) < 0)
86*858ea5e5SAndroid Build Coastguard Worker 		return -LIBBPF_ERRNO__NLPARSE;
87*858ea5e5SAndroid Build Coastguard Worker 
88*858ea5e5SAndroid Build Coastguard Worker 	if (!tb[TCA_ACT_BPF_PARMS])
89*858ea5e5SAndroid Build Coastguard Worker 		return -LIBBPF_ERRNO__NLPARSE;
90*858ea5e5SAndroid Build Coastguard Worker 
91*858ea5e5SAndroid Build Coastguard Worker 	NET_START_OBJECT_NESTED2;
92*858ea5e5SAndroid Build Coastguard Worker 	if (tb[TCA_ACT_BPF_NAME])
93*858ea5e5SAndroid Build Coastguard Worker 		NET_DUMP_STR("name", "%s",
94*858ea5e5SAndroid Build Coastguard Worker 			     libbpf_nla_getattr_str(tb[TCA_ACT_BPF_NAME]));
95*858ea5e5SAndroid Build Coastguard Worker 	if (tb[TCA_ACT_BPF_ID])
96*858ea5e5SAndroid Build Coastguard Worker 		NET_DUMP_UINT("id", " id %u",
97*858ea5e5SAndroid Build Coastguard Worker 			      libbpf_nla_getattr_u32(tb[TCA_ACT_BPF_ID]));
98*858ea5e5SAndroid Build Coastguard Worker 	NET_END_OBJECT_NESTED;
99*858ea5e5SAndroid Build Coastguard Worker 	return 0;
100*858ea5e5SAndroid Build Coastguard Worker }
101*858ea5e5SAndroid Build Coastguard Worker 
do_dump_one_act(struct nlattr * attr)102*858ea5e5SAndroid Build Coastguard Worker static int do_dump_one_act(struct nlattr *attr)
103*858ea5e5SAndroid Build Coastguard Worker {
104*858ea5e5SAndroid Build Coastguard Worker 	struct nlattr *tb[TCA_ACT_MAX + 1];
105*858ea5e5SAndroid Build Coastguard Worker 
106*858ea5e5SAndroid Build Coastguard Worker 	if (!attr)
107*858ea5e5SAndroid Build Coastguard Worker 		return 0;
108*858ea5e5SAndroid Build Coastguard Worker 
109*858ea5e5SAndroid Build Coastguard Worker 	if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX, attr, NULL) < 0)
110*858ea5e5SAndroid Build Coastguard Worker 		return -LIBBPF_ERRNO__NLPARSE;
111*858ea5e5SAndroid Build Coastguard Worker 
112*858ea5e5SAndroid Build Coastguard Worker 	if (tb[TCA_ACT_KIND] &&
113*858ea5e5SAndroid Build Coastguard Worker 	    strcmp(libbpf_nla_data(tb[TCA_ACT_KIND]), "bpf") == 0)
114*858ea5e5SAndroid Build Coastguard Worker 		return do_bpf_dump_one_act(tb[TCA_ACT_OPTIONS]);
115*858ea5e5SAndroid Build Coastguard Worker 
116*858ea5e5SAndroid Build Coastguard Worker 	return 0;
117*858ea5e5SAndroid Build Coastguard Worker }
118*858ea5e5SAndroid Build Coastguard Worker 
do_bpf_act_dump(struct nlattr * attr)119*858ea5e5SAndroid Build Coastguard Worker static int do_bpf_act_dump(struct nlattr *attr)
120*858ea5e5SAndroid Build Coastguard Worker {
121*858ea5e5SAndroid Build Coastguard Worker 	struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
122*858ea5e5SAndroid Build Coastguard Worker 	int act, ret;
123*858ea5e5SAndroid Build Coastguard Worker 
124*858ea5e5SAndroid Build Coastguard Worker 	if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX_PRIO, attr, NULL) < 0)
125*858ea5e5SAndroid Build Coastguard Worker 		return -LIBBPF_ERRNO__NLPARSE;
126*858ea5e5SAndroid Build Coastguard Worker 
127*858ea5e5SAndroid Build Coastguard Worker 	NET_START_ARRAY("act", " %s [");
128*858ea5e5SAndroid Build Coastguard Worker 	for (act = 0; act <= TCA_ACT_MAX_PRIO; act++) {
129*858ea5e5SAndroid Build Coastguard Worker 		ret = do_dump_one_act(tb[act]);
130*858ea5e5SAndroid Build Coastguard Worker 		if (ret)
131*858ea5e5SAndroid Build Coastguard Worker 			break;
132*858ea5e5SAndroid Build Coastguard Worker 	}
133*858ea5e5SAndroid Build Coastguard Worker 	NET_END_ARRAY("] ");
134*858ea5e5SAndroid Build Coastguard Worker 
135*858ea5e5SAndroid Build Coastguard Worker 	return ret;
136*858ea5e5SAndroid Build Coastguard Worker }
137*858ea5e5SAndroid Build Coastguard Worker 
do_bpf_filter_dump(struct nlattr * attr)138*858ea5e5SAndroid Build Coastguard Worker static int do_bpf_filter_dump(struct nlattr *attr)
139*858ea5e5SAndroid Build Coastguard Worker {
140*858ea5e5SAndroid Build Coastguard Worker 	struct nlattr *tb[TCA_BPF_MAX + 1];
141*858ea5e5SAndroid Build Coastguard Worker 	int ret;
142*858ea5e5SAndroid Build Coastguard Worker 
143*858ea5e5SAndroid Build Coastguard Worker 	if (libbpf_nla_parse_nested(tb, TCA_BPF_MAX, attr, NULL) < 0)
144*858ea5e5SAndroid Build Coastguard Worker 		return -LIBBPF_ERRNO__NLPARSE;
145*858ea5e5SAndroid Build Coastguard Worker 
146*858ea5e5SAndroid Build Coastguard Worker 	if (tb[TCA_BPF_NAME])
147*858ea5e5SAndroid Build Coastguard Worker 		NET_DUMP_STR("name", " %s",
148*858ea5e5SAndroid Build Coastguard Worker 			     libbpf_nla_getattr_str(tb[TCA_BPF_NAME]));
149*858ea5e5SAndroid Build Coastguard Worker 	if (tb[TCA_BPF_ID])
150*858ea5e5SAndroid Build Coastguard Worker 		NET_DUMP_UINT("id", " id %u",
151*858ea5e5SAndroid Build Coastguard Worker 			      libbpf_nla_getattr_u32(tb[TCA_BPF_ID]));
152*858ea5e5SAndroid Build Coastguard Worker 	if (tb[TCA_BPF_ACT]) {
153*858ea5e5SAndroid Build Coastguard Worker 		ret = do_bpf_act_dump(tb[TCA_BPF_ACT]);
154*858ea5e5SAndroid Build Coastguard Worker 		if (ret)
155*858ea5e5SAndroid Build Coastguard Worker 			return ret;
156*858ea5e5SAndroid Build Coastguard Worker 	}
157*858ea5e5SAndroid Build Coastguard Worker 
158*858ea5e5SAndroid Build Coastguard Worker 	return 0;
159*858ea5e5SAndroid Build Coastguard Worker }
160*858ea5e5SAndroid Build Coastguard Worker 
do_filter_dump(struct tcmsg * info,struct nlattr ** tb,const char * kind,const char * devname,int ifindex)161*858ea5e5SAndroid Build Coastguard Worker int do_filter_dump(struct tcmsg *info, struct nlattr **tb, const char *kind,
162*858ea5e5SAndroid Build Coastguard Worker 		   const char *devname, int ifindex)
163*858ea5e5SAndroid Build Coastguard Worker {
164*858ea5e5SAndroid Build Coastguard Worker 	int ret = 0;
165*858ea5e5SAndroid Build Coastguard Worker 
166*858ea5e5SAndroid Build Coastguard Worker 	if (tb[TCA_OPTIONS] &&
167*858ea5e5SAndroid Build Coastguard Worker 	    strcmp(libbpf_nla_data(tb[TCA_KIND]), "bpf") == 0) {
168*858ea5e5SAndroid Build Coastguard Worker 		NET_START_OBJECT;
169*858ea5e5SAndroid Build Coastguard Worker 		if (devname[0] != '\0')
170*858ea5e5SAndroid Build Coastguard Worker 			NET_DUMP_STR("devname", "%s", devname);
171*858ea5e5SAndroid Build Coastguard Worker 		NET_DUMP_UINT("ifindex", "(%u)", ifindex);
172*858ea5e5SAndroid Build Coastguard Worker 		NET_DUMP_STR("kind", " %s", kind);
173*858ea5e5SAndroid Build Coastguard Worker 		ret = do_bpf_filter_dump(tb[TCA_OPTIONS]);
174*858ea5e5SAndroid Build Coastguard Worker 		NET_END_OBJECT_FINAL;
175*858ea5e5SAndroid Build Coastguard Worker 	}
176*858ea5e5SAndroid Build Coastguard Worker 
177*858ea5e5SAndroid Build Coastguard Worker 	return ret;
178*858ea5e5SAndroid Build Coastguard Worker }
179