brintos

brintos / linux-shallow public Read only

0
0
Text · 4.2 KiB · 5f65140 Raw
179 lines · c
1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)2// Copyright (C) 2018 Facebook3 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_OBJECT23	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_OBJECT27}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}179