diff mbox series

[bpf-next,2/2] bpftool: show flow_dissector attachment status

Message ID 20190423232200.101627-2-sdf@google.com
State Changes Requested
Delegated to: BPF Maintainers
Headers show
Series [bpf-next,1/2] bpf: support BPF_PROG_QUERY for BPF_FLOW_DISSECTOR attach_type | expand

Commit Message

Stanislav Fomichev April 23, 2019, 11:22 p.m. UTC
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

Signed-off-by: Stanislav Fomichev <sdf@google.com>
---
 tools/bpf/bpftool/net.c | 52 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

Comments

Jakub Kicinski April 23, 2019, 11:32 p.m. UTC | #1
On Tue, 23 Apr 2019 16:22:00 -0700, Stanislav Fomichev wrote:
> +static int query_flow_dissector(struct bpf_attach_info *attach_info)
> +{
> +	__u32 prog_ids[1] = {0};
> +	__u32 prog_cnt = ARRAY_SIZE(prog_ids);
> +	__u32 attach_flags;
> +	int fd;
> +	int err;

reverse christmas tree, please :)

Move the init into the code if necessary.

> +	fd = open("/proc/self/ns/net", O_RDONLY);
> +	if (fd < 0) {
> +		p_err("can't open /proc/self/ns/net: %d",
> +		      strerror(errno));
> +		return -1;
> +	}
> +	err = bpf_prog_query(fd, BPF_FLOW_DISSECTOR, 0,
> +			     &attach_flags, prog_ids, &prog_cnt);
> +	close(fd);
> +	if (err) {
> +		if (errno == EINVAL) {
> +			/* Older kernel's don't support querying
> +			 * flow dissector programs.
> +			 */
> +			return 0;
> +		}
> +		p_err("can't query prog: %s", strerror(errno));
> +		return -1;
> +	}
> +
> +	if (prog_cnt == 1)
> +		attach_info->flow_dissector_id = prog_ids[0];

So the count can only be 0 or 1?  Hm.

> +	return 0;
> +}
Stanislav Fomichev April 24, 2019, 12:13 a.m. UTC | #2
On 04/23, Jakub Kicinski wrote:
> On Tue, 23 Apr 2019 16:22:00 -0700, Stanislav Fomichev wrote:
> > +static int query_flow_dissector(struct bpf_attach_info *attach_info)
> > +{
> > +	__u32 prog_ids[1] = {0};
> > +	__u32 prog_cnt = ARRAY_SIZE(prog_ids);
> > +	__u32 attach_flags;
> > +	int fd;
> > +	int err;
> 
> reverse christmas tree, please :)
> 
> Move the init into the code if necessary.
Ack, initialization didn't let me do that. But I think I can drop it, I
don't look prog_cnt in the syscall, maybe I should :-/

> > +	fd = open("/proc/self/ns/net", O_RDONLY);
> > +	if (fd < 0) {
> > +		p_err("can't open /proc/self/ns/net: %d",
> > +		      strerror(errno));
> > +		return -1;
> > +	}
> > +	err = bpf_prog_query(fd, BPF_FLOW_DISSECTOR, 0,
> > +			     &attach_flags, prog_ids, &prog_cnt);
> > +	close(fd);
> > +	if (err) {
> > +		if (errno == EINVAL) {
> > +			/* Older kernel's don't support querying
> > +			 * flow dissector programs.
> > +			 */
> > +			return 0;
> > +		}
> > +		p_err("can't query prog: %s", strerror(errno));
> > +		return -1;
> > +	}
> > +
> > +	if (prog_cnt == 1)
> > +		attach_info->flow_dissector_id = prog_ids[0];
> 
> So the count can only be 0 or 1?  Hm.
Yes, its either attached or not; there is nothing like prog_array.

> > +	return 0;
> > +}
Quentin Monnet April 24, 2019, 8:12 a.m. UTC | #3
2019-04-23 16:22 UTC-0700 ~ Stanislav Fomichev <sdf@google.com>
> 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
> 
> Signed-off-by: Stanislav Fomichev <sdf@google.com>
> ---
>   tools/bpf/bpftool/net.c | 52 +++++++++++++++++++++++++++++++++++++++++
>   1 file changed, 52 insertions(+)
> 
> diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
> index db0e7de49d49..afe0903201e2 100644
> --- a/tools/bpf/bpftool/net.c
> +++ b/tools/bpf/bpftool/net.c

> @@ -48,6 +51,10 @@ struct bpf_filter_t {
>   	int		ifindex;
>   };
>   
> +struct bpf_attach_info {
> +	__u32 flow_dissector_id;
> +};
> +
>   static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb)
>   {
>   	struct bpf_netdev_t *netinfo = cookie;
> @@ -180,8 +187,43 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
>   	return 0;
>   }
>   
> +static int query_flow_dissector(struct bpf_attach_info *attach_info)
> +{
> +	__u32 prog_ids[1] = {0};
> +	__u32 prog_cnt = ARRAY_SIZE(prog_ids);
> +	__u32 attach_flags;
> +	int fd;
> +	int err;
> +
> +	fd = open("/proc/self/ns/net", O_RDONLY);
> +	if (fd < 0) {
> +		p_err("can't open /proc/self/ns/net: %d",
> +		      strerror(errno));
> +		return -1;
> +	}
> +	err = bpf_prog_query(fd, BPF_FLOW_DISSECTOR, 0,
> +			     &attach_flags, prog_ids, &prog_cnt);
> +	close(fd);
> +	if (err) {
> +		if (errno == EINVAL) {
> +			/* Older kernel's don't support querying
> +			 * flow dissector programs.
> +			 */
> +			return 0;

Hi Stanislav,

If we handle the "error" gracefully here, should we maybe reset errno to 
0 before returning? Batch mode, for example, stops processing commands 
when it sees that errno is set, but we probably want it to continue in 
the current case (commit 39c9f10639a3 addressed something similar for 
"bpftool cgroup tree").

> +		}
> +		p_err("can't query prog: %s", strerror(errno));
> +		return -1;
> +	}
> +
> +	if (prog_cnt == 1)
> +		attach_info->flow_dissector_id = prog_ids[0];
> +
> +	return 0;
> +}
> +
>   static int do_show(int argc, char **argv)
>   {
> +	struct bpf_attach_info attach_info = {};
>   	int i, sock, ret, filter_idx = -1;
>   	struct bpf_netdev_t dev_array;
>   	unsigned int nl_pid;
Stanislav Fomichev April 24, 2019, 3:42 p.m. UTC | #4
On 04/24, Quentin Monnet wrote:
> 2019-04-23 16:22 UTC-0700 ~ Stanislav Fomichev <sdf@google.com>
> > 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
> > 
> > Signed-off-by: Stanislav Fomichev <sdf@google.com>
> > ---
> >   tools/bpf/bpftool/net.c | 52 +++++++++++++++++++++++++++++++++++++++++
> >   1 file changed, 52 insertions(+)
> > 
> > diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
> > index db0e7de49d49..afe0903201e2 100644
> > --- a/tools/bpf/bpftool/net.c
> > +++ b/tools/bpf/bpftool/net.c
> 
> > @@ -48,6 +51,10 @@ struct bpf_filter_t {
> >   	int		ifindex;
> >   };
> > +struct bpf_attach_info {
> > +	__u32 flow_dissector_id;
> > +};
> > +
> >   static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb)
> >   {
> >   	struct bpf_netdev_t *netinfo = cookie;
> > @@ -180,8 +187,43 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
> >   	return 0;
> >   }
> > +static int query_flow_dissector(struct bpf_attach_info *attach_info)
> > +{
> > +	__u32 prog_ids[1] = {0};
> > +	__u32 prog_cnt = ARRAY_SIZE(prog_ids);
> > +	__u32 attach_flags;
> > +	int fd;
> > +	int err;
> > +
> > +	fd = open("/proc/self/ns/net", O_RDONLY);
> > +	if (fd < 0) {
> > +		p_err("can't open /proc/self/ns/net: %d",
> > +		      strerror(errno));
> > +		return -1;
> > +	}
> > +	err = bpf_prog_query(fd, BPF_FLOW_DISSECTOR, 0,
> > +			     &attach_flags, prog_ids, &prog_cnt);
> > +	close(fd);
> > +	if (err) {
> > +		if (errno == EINVAL) {
> > +			/* Older kernel's don't support querying
> > +			 * flow dissector programs.
> > +			 */
> > +			return 0;
> 
> Hi Stanislav,
> 
> If we handle the "error" gracefully here, should we maybe reset errno to 0
> before returning? Batch mode, for example, stops processing commands when it
> sees that errno is set, but we probably want it to continue in the current
> case (commit 39c9f10639a3 addressed something similar for "bpftool cgroup
> tree").
Oh, I didn't know that. Sure, will do!

> > +		}
> > +		p_err("can't query prog: %s", strerror(errno));
> > +		return -1;
> > +	}
> > +
> > +	if (prog_cnt == 1)
> > +		attach_info->flow_dissector_id = prog_ids[0];
> > +
> > +	return 0;
> > +}
> > +
> >   static int do_show(int argc, char **argv)
> >   {
> > +	struct bpf_attach_info attach_info = {};
> >   	int i, sock, ret, filter_idx = -1;
> >   	struct bpf_netdev_t dev_array;
> >   	unsigned int nl_pid;
diff mbox series

Patch

diff --git a/tools/bpf/bpftool/net.c b/tools/bpf/bpftool/net.c
index db0e7de49d49..afe0903201e2 100644
--- a/tools/bpf/bpftool/net.c
+++ b/tools/bpf/bpftool/net.c
@@ -3,6 +3,7 @@ 
 
 #define _GNU_SOURCE
 #include <errno.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
@@ -12,6 +13,8 @@ 
 #include <linux/rtnetlink.h>
 #include <linux/tc_act/tc_bpf.h>
 #include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 
 #include <bpf.h>
 #include <nlattr.h>
@@ -48,6 +51,10 @@  struct bpf_filter_t {
 	int		ifindex;
 };
 
+struct bpf_attach_info {
+	__u32 flow_dissector_id;
+};
+
 static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb)
 {
 	struct bpf_netdev_t *netinfo = cookie;
@@ -180,8 +187,43 @@  static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
 	return 0;
 }
 
+static int query_flow_dissector(struct bpf_attach_info *attach_info)
+{
+	__u32 prog_ids[1] = {0};
+	__u32 prog_cnt = ARRAY_SIZE(prog_ids);
+	__u32 attach_flags;
+	int fd;
+	int err;
+
+	fd = open("/proc/self/ns/net", O_RDONLY);
+	if (fd < 0) {
+		p_err("can't open /proc/self/ns/net: %d",
+		      strerror(errno));
+		return -1;
+	}
+	err = bpf_prog_query(fd, BPF_FLOW_DISSECTOR, 0,
+			     &attach_flags, prog_ids, &prog_cnt);
+	close(fd);
+	if (err) {
+		if (errno == EINVAL) {
+			/* Older kernel's don't support querying
+			 * flow dissector programs.
+			 */
+			return 0;
+		}
+		p_err("can't query prog: %s", strerror(errno));
+		return -1;
+	}
+
+	if (prog_cnt == 1)
+		attach_info->flow_dissector_id = prog_ids[0];
+
+	return 0;
+}
+
 static int do_show(int argc, char **argv)
 {
+	struct bpf_attach_info attach_info = {};
 	int i, sock, ret, filter_idx = -1;
 	struct bpf_netdev_t dev_array;
 	unsigned int nl_pid;
@@ -199,6 +241,10 @@  static int do_show(int argc, char **argv)
 		usage();
 	}
 
+	ret = query_flow_dissector(&attach_info);
+	if (ret)
+		return -1;
+
 	sock = libbpf_netlink_open(&nl_pid);
 	if (sock < 0) {
 		fprintf(stderr, "failed to open netlink sock\n");
@@ -227,6 +273,12 @@  static int do_show(int argc, char **argv)
 		}
 		NET_END_ARRAY("\n");
 	}
+
+	NET_START_ARRAY("flow_dissector", "%s:\n");
+	if (attach_info.flow_dissector_id > 0)
+		NET_DUMP_UINT("id", "id %u", attach_info.flow_dissector_id);
+	NET_END_ARRAY("\n");
+
 	NET_END_OBJECT;
 	if (json_output)
 		jsonw_end_array(json_wtr);