Linux Audio

Check our new training course

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