blob: 550a0f537eedd8b0fc0a1b0df7d448916a24690d [file] [log] [blame]
Jakub Kicinski907b2232018-12-12 19:59:26 -08001// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
Yonghong Songf6f3bac2018-09-05 16:58:06 -07002// Copyright (C) 2018 Facebook
3
4#include <stdlib.h>
5#include <string.h>
6#include <libbpf.h>
7#include <linux/rtnetlink.h>
8#include <linux/tc_act/tc_bpf.h>
9
10#include <nlattr.h>
11#include "main.h"
12#include "netlink_dumper.h"
13
14static void xdp_dump_prog_id(struct nlattr **tb, int attr,
Yonghong Song7900efc2018-09-17 16:13:00 -070015 const char *mode,
16 bool new_json_object)
Yonghong Songf6f3bac2018-09-05 16:58:06 -070017{
18 if (!tb[attr])
19 return;
20
Yonghong Song7900efc2018-09-17 16:13:00 -070021 if (new_json_object)
22 NET_START_OBJECT
23 NET_DUMP_STR("mode", " %s", mode);
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -070024 NET_DUMP_UINT("id", " id %u", libbpf_nla_getattr_u32(tb[attr]))
Yonghong Song7900efc2018-09-17 16:13:00 -070025 if (new_json_object)
26 NET_END_OBJECT
Yonghong Songf6f3bac2018-09-05 16:58:06 -070027}
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
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -070035 if (libbpf_nla_parse_nested(tb, IFLA_XDP_MAX, attr, NULL) < 0)
Yonghong Songf6f3bac2018-09-05 16:58:06 -070036 return -1;
37
38 if (!tb[IFLA_XDP_ATTACHED])
39 return 0;
40
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -070041 mode = libbpf_nla_getattr_u8(tb[IFLA_XDP_ATTACHED]);
Yonghong Songf6f3bac2018-09-05 16:58:06 -070042 if (mode == XDP_ATTACHED_NONE)
43 return 0;
44
45 NET_START_OBJECT;
Yonghong Songf6f3bac2018-09-05 16:58:06 -070046 if (name)
Yonghong Song7900efc2018-09-17 16:13:00 -070047 NET_DUMP_STR("devname", "%s", name);
48 NET_DUMP_UINT("ifindex", "(%d)", ifindex);
Yonghong Songf6f3bac2018-09-05 16:58:06 -070049
50 if (mode == XDP_ATTACHED_MULTI) {
Yonghong Song7900efc2018-09-17 16:13:00 -070051 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);
Yonghong Songf6f3bac2018-09-05 16:58:06 -070066 }
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,
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -070078 libbpf_nla_getattr_str(tb[IFLA_IFNAME]));
Yonghong Songf6f3bac2018-09-05 16:58:06 -070079}
80
Yonghong Songf6f3bac2018-09-05 16:58:06 -070081static int do_bpf_dump_one_act(struct nlattr *attr)
82{
83 struct nlattr *tb[TCA_ACT_BPF_MAX + 1];
Yonghong Songf6f3bac2018-09-05 16:58:06 -070084
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -070085 if (libbpf_nla_parse_nested(tb, TCA_ACT_BPF_MAX, attr, NULL) < 0)
Yonghong Songf6f3bac2018-09-05 16:58:06 -070086 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])
Yonghong Song7900efc2018-09-17 16:13:00 -070093 NET_DUMP_STR("name", "%s",
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -070094 libbpf_nla_getattr_str(tb[TCA_ACT_BPF_NAME]));
Yonghong Songf6f3bac2018-09-05 16:58:06 -070095 if (tb[TCA_ACT_BPF_ID])
Yonghong Song7900efc2018-09-17 16:13:00 -070096 NET_DUMP_UINT("id", " id %u",
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -070097 libbpf_nla_getattr_u32(tb[TCA_ACT_BPF_ID]));
Yonghong Songf6f3bac2018-09-05 16:58:06 -070098 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
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -0700109 if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX, attr, NULL) < 0)
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700110 return -LIBBPF_ERRNO__NLPARSE;
111
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -0700112 if (tb[TCA_ACT_KIND] &&
113 strcmp(libbpf_nla_data(tb[TCA_ACT_KIND]), "bpf") == 0)
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700114 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
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -0700124 if (libbpf_nla_parse_nested(tb, TCA_ACT_MAX_PRIO, attr, NULL) < 0)
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700125 return -LIBBPF_ERRNO__NLPARSE;
126
Yonghong Song7900efc2018-09-17 16:13:00 -0700127 NET_START_ARRAY("act", " %s [");
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700128 for (act = 0; act <= TCA_ACT_MAX_PRIO; act++) {
129 ret = do_dump_one_act(tb[act]);
130 if (ret)
131 break;
132 }
Yonghong Song7900efc2018-09-17 16:13:00 -0700133 NET_END_ARRAY("] ");
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700134
135 return ret;
136}
137
138static int do_bpf_filter_dump(struct nlattr *attr)
139{
140 struct nlattr *tb[TCA_BPF_MAX + 1];
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700141 int ret;
142
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -0700143 if (libbpf_nla_parse_nested(tb, TCA_BPF_MAX, attr, NULL) < 0)
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700144 return -LIBBPF_ERRNO__NLPARSE;
145
146 if (tb[TCA_BPF_NAME])
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -0700147 NET_DUMP_STR("name", " %s",
148 libbpf_nla_getattr_str(tb[TCA_BPF_NAME]));
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700149 if (tb[TCA_BPF_ID])
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -0700150 NET_DUMP_UINT("id", " id %u",
151 libbpf_nla_getattr_u32(tb[TCA_BPF_ID]));
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700152 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
Yonghong Song7900efc2018-09-17 16:13:00 -0700161int do_filter_dump(struct tcmsg *info, struct nlattr **tb, const char *kind,
162 const char *devname, int ifindex)
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700163{
164 int ret = 0;
165
Andrey Ignatovf04bc8a42018-10-03 15:26:40 -0700166 if (tb[TCA_OPTIONS] &&
167 strcmp(libbpf_nla_data(tb[TCA_KIND]), "bpf") == 0) {
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700168 NET_START_OBJECT;
Yonghong Song7900efc2018-09-17 16:13:00 -0700169 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);
Yonghong Songf6f3bac2018-09-05 16:58:06 -0700173 ret = do_bpf_filter_dump(tb[TCA_OPTIONS]);
174 NET_END_OBJECT_FINAL;
175 }
176
177 return ret;
178}