diff options
author | Stanislav Fomichev <sdf@google.com> | 2019-04-25 17:37:24 -0400 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2019-04-25 17:49:06 -0400 |
commit | 7f0c57fec80f198ae9fcd06e5bbca13196815a4b (patch) | |
tree | 85308388727bfaabda0dc9487b2c036b02284a96 /tools/bpf/bpftool/net.c | |
parent | 118c8e9ae629d35fa9b3d27a7b9d59298b1b4183 (diff) |
bpftool: show flow_dissector attachment status
Right now there is no way to query whether BPF flow_dissector program
is attached to a network namespace or not. In previous commit, I added
support for querying that info, show it when doing `bpftool net`:
$ bpftool prog loadall ./bpf_flow.o \
/sys/fs/bpf/flow type flow_dissector \
pinmaps /sys/fs/bpf/flow
$ bpftool prog
3: flow_dissector name _dissect tag 8c9e917b513dd5cc gpl
loaded_at 2019-04-23T16:14:48-0700 uid 0
xlated 656B jited 461B memlock 4096B map_ids 1,2
btf_id 1
...
$ bpftool net -j
[{"xdp":[],"tc":[],"flow_dissector":[]}]
$ bpftool prog attach pinned \
/sys/fs/bpf/flow/flow_dissector flow_dissector
$ bpftool net -j
[{"xdp":[],"tc":[],"flow_dissector":["id":3]}]
Doesn't show up in a different net namespace:
$ ip netns add test
$ ip netns exec test bpftool net -j
[{"xdp":[],"tc":[],"flow_dissector":[]}]
Non-json output:
$ bpftool net
xdp:
tc:
flow_dissector:
id 3
v2:
* initialization order (Jakub Kicinski)
* clear errno for batch mode (Quentin Monnet)
Signed-off-by: Stanislav Fomichev <sdf@google.com>
Reviewed-by: Quentin Monnet <quentin.monnet@netronome.com>
Reviewed-by: Jakub Kicinski <jakub.kicinski@netronome.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Diffstat (limited to 'tools/bpf/bpftool/net.c')
-rw-r--r-- | tools/bpf/bpftool/net.c | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c index db0e7de49d49..67e99c56bc88 100644 --- a/tools/bpf/bpftool/net.c +++ b/tools/bpf/bpftool/net.c | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #define _GNU_SOURCE | 4 | #define _GNU_SOURCE |
5 | #include <errno.h> | 5 | #include <errno.h> |
6 | #include <fcntl.h> | ||
6 | #include <stdlib.h> | 7 | #include <stdlib.h> |
7 | #include <string.h> | 8 | #include <string.h> |
8 | #include <unistd.h> | 9 | #include <unistd.h> |
@@ -12,6 +13,8 @@ | |||
12 | #include <linux/rtnetlink.h> | 13 | #include <linux/rtnetlink.h> |
13 | #include <linux/tc_act/tc_bpf.h> | 14 | #include <linux/tc_act/tc_bpf.h> |
14 | #include <sys/socket.h> | 15 | #include <sys/socket.h> |
16 | #include <sys/stat.h> | ||
17 | #include <sys/types.h> | ||
15 | 18 | ||
16 | #include <bpf.h> | 19 | #include <bpf.h> |
17 | #include <nlattr.h> | 20 | #include <nlattr.h> |
@@ -48,6 +51,10 @@ struct bpf_filter_t { | |||
48 | int ifindex; | 51 | int ifindex; |
49 | }; | 52 | }; |
50 | 53 | ||
54 | struct bpf_attach_info { | ||
55 | __u32 flow_dissector_id; | ||
56 | }; | ||
57 | |||
51 | static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb) | 58 | static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb) |
52 | { | 59 | { |
53 | struct bpf_netdev_t *netinfo = cookie; | 60 | struct bpf_netdev_t *netinfo = cookie; |
@@ -180,8 +187,45 @@ out: | |||
180 | return 0; | 187 | return 0; |
181 | } | 188 | } |
182 | 189 | ||
190 | static int query_flow_dissector(struct bpf_attach_info *attach_info) | ||
191 | { | ||
192 | __u32 attach_flags; | ||
193 | __u32 prog_ids[1]; | ||
194 | __u32 prog_cnt; | ||
195 | int err; | ||
196 | int fd; | ||
197 | |||
198 | fd = open("/proc/self/ns/net", O_RDONLY); | ||
199 | if (fd < 0) { | ||
200 | p_err("can't open /proc/self/ns/net: %d", | ||
201 | strerror(errno)); | ||
202 | return -1; | ||
203 | } | ||
204 | prog_cnt = ARRAY_SIZE(prog_ids); | ||
205 | err = bpf_prog_query(fd, BPF_FLOW_DISSECTOR, 0, | ||
206 | &attach_flags, prog_ids, &prog_cnt); | ||
207 | close(fd); | ||
208 | if (err) { | ||
209 | if (errno == EINVAL) { | ||
210 | /* Older kernel's don't support querying | ||
211 | * flow dissector programs. | ||
212 | */ | ||
213 | errno = 0; | ||
214 | return 0; | ||
215 | } | ||
216 | p_err("can't query prog: %s", strerror(errno)); | ||
217 | return -1; | ||
218 | } | ||
219 | |||
220 | if (prog_cnt == 1) | ||
221 | attach_info->flow_dissector_id = prog_ids[0]; | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
183 | static int do_show(int argc, char **argv) | 226 | static int do_show(int argc, char **argv) |
184 | { | 227 | { |
228 | struct bpf_attach_info attach_info = {}; | ||
185 | int i, sock, ret, filter_idx = -1; | 229 | int i, sock, ret, filter_idx = -1; |
186 | struct bpf_netdev_t dev_array; | 230 | struct bpf_netdev_t dev_array; |
187 | unsigned int nl_pid; | 231 | unsigned int nl_pid; |
@@ -199,6 +243,10 @@ static int do_show(int argc, char **argv) | |||
199 | usage(); | 243 | usage(); |
200 | } | 244 | } |
201 | 245 | ||
246 | ret = query_flow_dissector(&attach_info); | ||
247 | if (ret) | ||
248 | return -1; | ||
249 | |||
202 | sock = libbpf_netlink_open(&nl_pid); | 250 | sock = libbpf_netlink_open(&nl_pid); |
203 | if (sock < 0) { | 251 | if (sock < 0) { |
204 | fprintf(stderr, "failed to open netlink sock\n"); | 252 | fprintf(stderr, "failed to open netlink sock\n"); |
@@ -227,6 +275,12 @@ static int do_show(int argc, char **argv) | |||
227 | } | 275 | } |
228 | NET_END_ARRAY("\n"); | 276 | NET_END_ARRAY("\n"); |
229 | } | 277 | } |
278 | |||
279 | NET_START_ARRAY("flow_dissector", "%s:\n"); | ||
280 | if (attach_info.flow_dissector_id > 0) | ||
281 | NET_DUMP_UINT("id", "id %u", attach_info.flow_dissector_id); | ||
282 | NET_END_ARRAY("\n"); | ||
283 | |||
230 | NET_END_OBJECT; | 284 | NET_END_OBJECT; |
231 | if (json_output) | 285 | if (json_output) |
232 | jsonw_end_array(json_wtr); | 286 | jsonw_end_array(json_wtr); |