tools/bpftool: Remove libbpf_internal.h usage in bpftool
authorAndrii Nakryiko <andriin@fb.com>
Wed, 19 Aug 2020 01:36:05 +0000 (18:36 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Wed, 19 Aug 2020 01:38:25 +0000 (18:38 -0700)
Most netlink-related functions were unique to bpftool usage, so I moved them
into net.c. Few functions are still used by both bpftool and libbpf itself
internally, so I've copy-pasted them (libbpf_nl_get_link,
libbpf_netlink_open). It's a bit of duplication of code, but better separation
of libbpf as a library with public API and bpftool, relying on unexposed
functions in libbpf.

Signed-off-by: Andrii Nakryiko <andriin@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200819013607.3607269-3-andriin@fb.com
tools/bpf/bpftool/gen.c
tools/bpf/bpftool/net.c
tools/lib/bpf/libbpf_internal.h
tools/lib/bpf/netlink.c

index f611846..4033c46 100644 (file)
 #include <sys/mman.h>
 #include <bpf/btf.h>
 
-#include "bpf/libbpf_internal.h"
 #include "json_writer.h"
 #include "main.h"
 
-
 #define MAX_OBJ_NAME_LEN 64
 
 static void sanitize_identifier(char *name)
index 56c3a2b..910e7ba 100644 (file)
@@ -6,22 +6,27 @@
 #include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 #include <bpf/bpf.h>
 #include <bpf/libbpf.h>
 #include <net/if.h>
 #include <linux/if.h>
 #include <linux/rtnetlink.h>
+#include <linux/socket.h>
 #include <linux/tc_act/tc_bpf.h>
 #include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
 #include "bpf/nlattr.h"
-#include "bpf/libbpf_internal.h"
 #include "main.h"
 #include "netlink_dumper.h"
 
+#ifndef SOL_NETLINK
+#define SOL_NETLINK 270
+#endif
+
 struct ip_devname_ifindex {
        char    devname[64];
        int     ifindex;
@@ -85,6 +90,266 @@ static enum net_attach_type parse_attach_type(const char *str)
        return net_attach_type_size;
 }
 
+typedef int (*dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
+
+typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, dump_nlmsg_t, void *cookie);
+
+static int netlink_open(__u32 *nl_pid)
+{
+       struct sockaddr_nl sa;
+       socklen_t addrlen;
+       int one = 1, ret;
+       int sock;
+
+       memset(&sa, 0, sizeof(sa));
+       sa.nl_family = AF_NETLINK;
+
+       sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
+       if (sock < 0)
+               return -errno;
+
+       if (setsockopt(sock, SOL_NETLINK, NETLINK_EXT_ACK,
+                      &one, sizeof(one)) < 0) {
+               p_err("Netlink error reporting not supported");
+       }
+
+       if (bind(sock, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
+               ret = -errno;
+               goto cleanup;
+       }
+
+       addrlen = sizeof(sa);
+       if (getsockname(sock, (struct sockaddr *)&sa, &addrlen) < 0) {
+               ret = -errno;
+               goto cleanup;
+       }
+
+       if (addrlen != sizeof(sa)) {
+               ret = -LIBBPF_ERRNO__INTERNAL;
+               goto cleanup;
+       }
+
+       *nl_pid = sa.nl_pid;
+       return sock;
+
+cleanup:
+       close(sock);
+       return ret;
+}
+
+static int netlink_recv(int sock, __u32 nl_pid, __u32 seq,
+                           __dump_nlmsg_t _fn, dump_nlmsg_t fn,
+                           void *cookie)
+{
+       bool multipart = true;
+       struct nlmsgerr *err;
+       struct nlmsghdr *nh;
+       char buf[4096];
+       int len, ret;
+
+       while (multipart) {
+               multipart = false;
+               len = recv(sock, buf, sizeof(buf), 0);
+               if (len < 0) {
+                       ret = -errno;
+                       goto done;
+               }
+
+               if (len == 0)
+                       break;
+
+               for (nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, len);
+                    nh = NLMSG_NEXT(nh, len)) {
+                       if (nh->nlmsg_pid != nl_pid) {
+                               ret = -LIBBPF_ERRNO__WRNGPID;
+                               goto done;
+                       }
+                       if (nh->nlmsg_seq != seq) {
+                               ret = -LIBBPF_ERRNO__INVSEQ;
+                               goto done;
+                       }
+                       if (nh->nlmsg_flags & NLM_F_MULTI)
+                               multipart = true;
+                       switch (nh->nlmsg_type) {
+                       case NLMSG_ERROR:
+                               err = (struct nlmsgerr *)NLMSG_DATA(nh);
+                               if (!err->error)
+                                       continue;
+                               ret = err->error;
+                               libbpf_nla_dump_errormsg(nh);
+                               goto done;
+                       case NLMSG_DONE:
+                               return 0;
+                       default:
+                               break;
+                       }
+                       if (_fn) {
+                               ret = _fn(nh, fn, cookie);
+                               if (ret)
+                                       return ret;
+                       }
+               }
+       }
+       ret = 0;
+done:
+       return ret;
+}
+
+static int __dump_class_nlmsg(struct nlmsghdr *nlh,
+                             dump_nlmsg_t dump_class_nlmsg,
+                             void *cookie)
+{
+       struct nlattr *tb[TCA_MAX + 1], *attr;
+       struct tcmsg *t = NLMSG_DATA(nlh);
+       int len;
+
+       len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
+       attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
+       if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
+               return -LIBBPF_ERRNO__NLPARSE;
+
+       return dump_class_nlmsg(cookie, t, tb);
+}
+
+static int netlink_get_class(int sock, unsigned int nl_pid, int ifindex,
+                            dump_nlmsg_t dump_class_nlmsg, void *cookie)
+{
+       struct {
+               struct nlmsghdr nlh;
+               struct tcmsg t;
+       } req = {
+               .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
+               .nlh.nlmsg_type = RTM_GETTCLASS,
+               .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+               .t.tcm_family = AF_UNSPEC,
+               .t.tcm_ifindex = ifindex,
+       };
+       int seq = time(NULL);
+
+       req.nlh.nlmsg_seq = seq;
+       if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
+               return -errno;
+
+       return netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg,
+                           dump_class_nlmsg, cookie);
+}
+
+static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh,
+                             dump_nlmsg_t dump_qdisc_nlmsg,
+                             void *cookie)
+{
+       struct nlattr *tb[TCA_MAX + 1], *attr;
+       struct tcmsg *t = NLMSG_DATA(nlh);
+       int len;
+
+       len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
+       attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
+       if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
+               return -LIBBPF_ERRNO__NLPARSE;
+
+       return dump_qdisc_nlmsg(cookie, t, tb);
+}
+
+static int netlink_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
+                            dump_nlmsg_t dump_qdisc_nlmsg, void *cookie)
+{
+       struct {
+               struct nlmsghdr nlh;
+               struct tcmsg t;
+       } req = {
+               .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
+               .nlh.nlmsg_type = RTM_GETQDISC,
+               .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+               .t.tcm_family = AF_UNSPEC,
+               .t.tcm_ifindex = ifindex,
+       };
+       int seq = time(NULL);
+
+       req.nlh.nlmsg_seq = seq;
+       if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
+               return -errno;
+
+       return netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg,
+                           dump_qdisc_nlmsg, cookie);
+}
+
+static int __dump_filter_nlmsg(struct nlmsghdr *nlh,
+                              dump_nlmsg_t dump_filter_nlmsg,
+                              void *cookie)
+{
+       struct nlattr *tb[TCA_MAX + 1], *attr;
+       struct tcmsg *t = NLMSG_DATA(nlh);
+       int len;
+
+       len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
+       attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
+       if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
+               return -LIBBPF_ERRNO__NLPARSE;
+
+       return dump_filter_nlmsg(cookie, t, tb);
+}
+
+static int netlink_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
+                             dump_nlmsg_t dump_filter_nlmsg, void *cookie)
+{
+       struct {
+               struct nlmsghdr nlh;
+               struct tcmsg t;
+       } req = {
+               .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
+               .nlh.nlmsg_type = RTM_GETTFILTER,
+               .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+               .t.tcm_family = AF_UNSPEC,
+               .t.tcm_ifindex = ifindex,
+               .t.tcm_parent = handle,
+       };
+       int seq = time(NULL);
+
+       req.nlh.nlmsg_seq = seq;
+       if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
+               return -errno;
+
+       return netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg,
+                           dump_filter_nlmsg, cookie);
+}
+
+static int __dump_link_nlmsg(struct nlmsghdr *nlh,
+                            dump_nlmsg_t dump_link_nlmsg, void *cookie)
+{
+       struct nlattr *tb[IFLA_MAX + 1], *attr;
+       struct ifinfomsg *ifi = NLMSG_DATA(nlh);
+       int len;
+
+       len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*ifi));
+       attr = (struct nlattr *) ((void *) ifi + NLMSG_ALIGN(sizeof(*ifi)));
+       if (libbpf_nla_parse(tb, IFLA_MAX, attr, len, NULL) != 0)
+               return -LIBBPF_ERRNO__NLPARSE;
+
+       return dump_link_nlmsg(cookie, ifi, tb);
+}
+
+static int netlink_get_link(int sock, unsigned int nl_pid,
+                           dump_nlmsg_t dump_link_nlmsg, void *cookie)
+{
+       struct {
+               struct nlmsghdr nlh;
+               struct ifinfomsg ifm;
+       } req = {
+               .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)),
+               .nlh.nlmsg_type = RTM_GETLINK,
+               .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
+               .ifm.ifi_family = AF_PACKET,
+       };
+       int seq = time(NULL);
+
+       req.nlh.nlmsg_seq = seq;
+       if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
+               return -errno;
+
+       return netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg,
+                           dump_link_nlmsg, cookie);
+}
+
 static int dump_link_nlmsg(void *cookie, void *msg, struct nlattr **tb)
 {
        struct bpf_netdev_t *netinfo = cookie;
@@ -168,14 +433,14 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
        tcinfo.array_len = 0;
 
        tcinfo.is_qdisc = false;
-       ret = libbpf_nl_get_class(sock, nl_pid, dev->ifindex,
-                                 dump_class_qdisc_nlmsg, &tcinfo);
+       ret = netlink_get_class(sock, nl_pid, dev->ifindex,
+                               dump_class_qdisc_nlmsg, &tcinfo);
        if (ret)
                goto out;
 
        tcinfo.is_qdisc = true;
-       ret = libbpf_nl_get_qdisc(sock, nl_pid, dev->ifindex,
-                                 dump_class_qdisc_nlmsg, &tcinfo);
+       ret = netlink_get_qdisc(sock, nl_pid, dev->ifindex,
+                               dump_class_qdisc_nlmsg, &tcinfo);
        if (ret)
                goto out;
 
@@ -183,9 +448,9 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
        filter_info.ifindex = dev->ifindex;
        for (i = 0; i < tcinfo.used_len; i++) {
                filter_info.kind = tcinfo.handle_array[i].kind;
-               ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex,
-                                          tcinfo.handle_array[i].handle,
-                                          dump_filter_nlmsg, &filter_info);
+               ret = netlink_get_filter(sock, nl_pid, dev->ifindex,
+                                        tcinfo.handle_array[i].handle,
+                                        dump_filter_nlmsg, &filter_info);
                if (ret)
                        goto out;
        }
@@ -193,22 +458,22 @@ static int show_dev_tc_bpf(int sock, unsigned int nl_pid,
        /* root, ingress and egress handle */
        handle = TC_H_ROOT;
        filter_info.kind = "root";
-       ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
-                                  dump_filter_nlmsg, &filter_info);
+       ret = netlink_get_filter(sock, nl_pid, dev->ifindex, handle,
+                                dump_filter_nlmsg, &filter_info);
        if (ret)
                goto out;
 
        handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_INGRESS);
        filter_info.kind = "clsact/ingress";
-       ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
-                                  dump_filter_nlmsg, &filter_info);
+       ret = netlink_get_filter(sock, nl_pid, dev->ifindex, handle,
+                                dump_filter_nlmsg, &filter_info);
        if (ret)
                goto out;
 
        handle = TC_H_MAKE(TC_H_CLSACT, TC_H_MIN_EGRESS);
        filter_info.kind = "clsact/egress";
-       ret = libbpf_nl_get_filter(sock, nl_pid, dev->ifindex, handle,
-                                  dump_filter_nlmsg, &filter_info);
+       ret = netlink_get_filter(sock, nl_pid, dev->ifindex, handle,
+                                dump_filter_nlmsg, &filter_info);
        if (ret)
                goto out;
 
@@ -386,7 +651,7 @@ 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;
+       unsigned int nl_pid = 0;
        char err_buf[256];
 
        if (argc == 2) {
@@ -401,7 +666,7 @@ static int do_show(int argc, char **argv)
        if (ret)
                return -1;
 
-       sock = libbpf_netlink_open(&nl_pid);
+       sock = netlink_open(&nl_pid);
        if (sock < 0) {
                fprintf(stderr, "failed to open netlink sock\n");
                return -1;
@@ -416,7 +681,7 @@ static int do_show(int argc, char **argv)
                jsonw_start_array(json_wtr);
        NET_START_OBJECT;
        NET_START_ARRAY("xdp", "%s:\n");
-       ret = libbpf_nl_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array);
+       ret = netlink_get_link(sock, nl_pid, dump_link_nlmsg, &dev_array);
        NET_END_ARRAY("\n");
 
        if (!ret) {
index 954bc2b..65931e9 100644 (file)
@@ -130,18 +130,6 @@ int bpf_object__section_size(const struct bpf_object *obj, const char *name,
 int bpf_object__variable_offset(const struct bpf_object *obj, const char *name,
                                __u32 *off);
 
-struct nlattr;
-typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
-int libbpf_netlink_open(unsigned int *nl_pid);
-int libbpf_nl_get_link(int sock, unsigned int nl_pid,
-                      libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie);
-int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
-                       libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie);
-int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
-                       libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie);
-int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
-                        libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie);
-
 struct btf_ext_info {
        /*
         * info points to the individual info section (e.g. func_info and
index 312f887..2465538 100644 (file)
@@ -22,6 +22,8 @@
 #define SOL_NETLINK 270
 #endif
 
+typedef int (*libbpf_dump_nlmsg_t)(void *cookie, void *msg, struct nlattr **tb);
+
 typedef int (*__dump_nlmsg_t)(struct nlmsghdr *nlmsg, libbpf_dump_nlmsg_t,
                              void *cookie);
 
@@ -31,7 +33,7 @@ struct xdp_id_md {
        struct xdp_link_info info;
 };
 
-int libbpf_netlink_open(__u32 *nl_pid)
+static int libbpf_netlink_open(__u32 *nl_pid)
 {
        struct sockaddr_nl sa;
        socklen_t addrlen;
@@ -283,6 +285,9 @@ static int get_xdp_info(void *cookie, void *msg, struct nlattr **tb)
        return 0;
 }
 
+static int libbpf_nl_get_link(int sock, unsigned int nl_pid,
+                             libbpf_dump_nlmsg_t dump_link_nlmsg, void *cookie);
+
 int bpf_get_link_xdp_info(int ifindex, struct xdp_link_info *info,
                          size_t info_size, __u32 flags)
 {
@@ -368,121 +373,3 @@ int libbpf_nl_get_link(int sock, unsigned int nl_pid,
        return bpf_netlink_recv(sock, nl_pid, seq, __dump_link_nlmsg,
                                dump_link_nlmsg, cookie);
 }
-
-static int __dump_class_nlmsg(struct nlmsghdr *nlh,
-                             libbpf_dump_nlmsg_t dump_class_nlmsg,
-                             void *cookie)
-{
-       struct nlattr *tb[TCA_MAX + 1], *attr;
-       struct tcmsg *t = NLMSG_DATA(nlh);
-       int len;
-
-       len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
-       attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
-       if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
-               return -LIBBPF_ERRNO__NLPARSE;
-
-       return dump_class_nlmsg(cookie, t, tb);
-}
-
-int libbpf_nl_get_class(int sock, unsigned int nl_pid, int ifindex,
-                       libbpf_dump_nlmsg_t dump_class_nlmsg, void *cookie)
-{
-       struct {
-               struct nlmsghdr nlh;
-               struct tcmsg t;
-       } req = {
-               .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
-               .nlh.nlmsg_type = RTM_GETTCLASS,
-               .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
-               .t.tcm_family = AF_UNSPEC,
-               .t.tcm_ifindex = ifindex,
-       };
-       int seq = time(NULL);
-
-       req.nlh.nlmsg_seq = seq;
-       if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
-               return -errno;
-
-       return bpf_netlink_recv(sock, nl_pid, seq, __dump_class_nlmsg,
-                               dump_class_nlmsg, cookie);
-}
-
-static int __dump_qdisc_nlmsg(struct nlmsghdr *nlh,
-                             libbpf_dump_nlmsg_t dump_qdisc_nlmsg,
-                             void *cookie)
-{
-       struct nlattr *tb[TCA_MAX + 1], *attr;
-       struct tcmsg *t = NLMSG_DATA(nlh);
-       int len;
-
-       len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
-       attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
-       if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
-               return -LIBBPF_ERRNO__NLPARSE;
-
-       return dump_qdisc_nlmsg(cookie, t, tb);
-}
-
-int libbpf_nl_get_qdisc(int sock, unsigned int nl_pid, int ifindex,
-                       libbpf_dump_nlmsg_t dump_qdisc_nlmsg, void *cookie)
-{
-       struct {
-               struct nlmsghdr nlh;
-               struct tcmsg t;
-       } req = {
-               .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
-               .nlh.nlmsg_type = RTM_GETQDISC,
-               .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
-               .t.tcm_family = AF_UNSPEC,
-               .t.tcm_ifindex = ifindex,
-       };
-       int seq = time(NULL);
-
-       req.nlh.nlmsg_seq = seq;
-       if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
-               return -errno;
-
-       return bpf_netlink_recv(sock, nl_pid, seq, __dump_qdisc_nlmsg,
-                               dump_qdisc_nlmsg, cookie);
-}
-
-static int __dump_filter_nlmsg(struct nlmsghdr *nlh,
-                              libbpf_dump_nlmsg_t dump_filter_nlmsg,
-                              void *cookie)
-{
-       struct nlattr *tb[TCA_MAX + 1], *attr;
-       struct tcmsg *t = NLMSG_DATA(nlh);
-       int len;
-
-       len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*t));
-       attr = (struct nlattr *) ((void *) t + NLMSG_ALIGN(sizeof(*t)));
-       if (libbpf_nla_parse(tb, TCA_MAX, attr, len, NULL) != 0)
-               return -LIBBPF_ERRNO__NLPARSE;
-
-       return dump_filter_nlmsg(cookie, t, tb);
-}
-
-int libbpf_nl_get_filter(int sock, unsigned int nl_pid, int ifindex, int handle,
-                        libbpf_dump_nlmsg_t dump_filter_nlmsg, void *cookie)
-{
-       struct {
-               struct nlmsghdr nlh;
-               struct tcmsg t;
-       } req = {
-               .nlh.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg)),
-               .nlh.nlmsg_type = RTM_GETTFILTER,
-               .nlh.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST,
-               .t.tcm_family = AF_UNSPEC,
-               .t.tcm_ifindex = ifindex,
-               .t.tcm_parent = handle,
-       };
-       int seq = time(NULL);
-
-       req.nlh.nlmsg_seq = seq;
-       if (send(sock, &req, req.nlh.nlmsg_len, 0) < 0)
-               return -errno;
-
-       return bpf_netlink_recv(sock, nl_pid, seq, __dump_filter_nlmsg,
-                               dump_filter_nlmsg, cookie);
-}