In the future we need to access routing table entries in network namespaces. As netlink has no easy way to get a socket in a network namespace we copy the logic of frr where we: 1. enter the target netns 2. open a socket 3. jump back to our original netns
the socket will keep working between these jumps. Signed-off-by: Felix Huettner <[email protected]> --- lib/dpif-netlink-rtnl.c | 6 +-- lib/dpif-netlink.c | 22 ++++---- lib/netdev-linux.c | 6 +-- lib/netlink-conntrack.c | 20 ++++---- lib/netlink-socket.c | 110 ++++++++++++++++++++++++++++++++-------- lib/netlink-socket.h | 7 +-- lib/route-table.c | 6 +-- lib/tc.c | 8 +-- 8 files changed, 127 insertions(+), 58 deletions(-) diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c index f7035333e..2df905d92 100644 --- a/lib/dpif-netlink-rtnl.c +++ b/lib/dpif-netlink-rtnl.c @@ -158,7 +158,7 @@ rtnl_transact(uint32_t type, uint32_t flags, const char *name, ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg)); nl_msg_put_string(&request, IFLA_IFNAME, name); - err = nl_transact(NETLINK_ROUTE, &request, reply); + err = nl_transact(NULL, NETLINK_ROUTE, &request, reply); ofpbuf_uninit(&request); return err; @@ -342,7 +342,7 @@ rtnl_set_mtu(const char *name, uint32_t mtu, struct ofpbuf *request) nl_msg_put_string(request, IFLA_IFNAME, name); nl_msg_put_u32(request, IFLA_MTU, mtu); - return nl_transact(NETLINK_ROUTE, request, NULL); + return nl_transact(NULL, NETLINK_ROUTE, request, NULL); } static int @@ -425,7 +425,7 @@ dpif_netlink_rtnl_create(const struct netdev_tunnel_config *tnl_cfg, nl_msg_end_nested(&request, infodata_off); nl_msg_end_nested(&request, linkinfo_off); - err = nl_transact(NETLINK_ROUTE, &request, NULL); + err = nl_transact(NULL, NETLINK_ROUTE, &request, NULL); if (!err && (type == OVS_VPORT_TYPE_GRE || type == OVS_VPORT_TYPE_IP6GRE)) { /* Work around a bug in kernel GRE driver, which ignores IFLA_MTU in diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 84e2bd8ea..3e4e03697 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -1348,7 +1348,7 @@ dpif_netlink_port_dump_start__(const struct dpif_netlink *dpif, buf = ofpbuf_new(1024); dpif_netlink_vport_to_ofpbuf(&request, buf); - nl_dump_start(dump, NETLINK_GENERIC, buf); + nl_dump_start(NULL, dump, NETLINK_GENERIC, buf); ofpbuf_delete(buf); } @@ -1682,7 +1682,7 @@ dpif_netlink_flow_dump_create(const struct dpif *dpif_, bool terse, buf = ofpbuf_new(1024); dpif_netlink_flow_to_ofpbuf(&request, buf); - nl_dump_start(&dump->nl_dump, NETLINK_GENERIC, buf); + nl_dump_start(NULL, &dump->nl_dump, NETLINK_GENERIC, buf); ofpbuf_delete(buf); } atomic_init(&dump->status, 0); @@ -2141,7 +2141,7 @@ dpif_netlink_operate__(struct dpif_netlink *dpif, for (i = 0; i < n_ops; i++) { txnsp[i] = &auxes[i].txn; } - nl_transact_multiple(NETLINK_GENERIC, txnsp, n_ops); + nl_transact_multiple(NULL, NETLINK_GENERIC, txnsp, n_ops); for (i = 0; i < n_ops; i++) { struct op_auxdata *aux = &auxes[i]; @@ -3391,7 +3391,7 @@ dpif_netlink_ct_set_limits(struct dpif *dpif OVS_UNUSED, } nl_msg_end_nested(request, opt_offset); - int err = nl_transact(NETLINK_GENERIC, request, NULL); + int err = nl_transact(NULL, NETLINK_GENERIC, request, NULL); ofpbuf_delete(request); return err; } @@ -3476,7 +3476,7 @@ dpif_netlink_ct_get_limits(struct dpif *dpif OVS_UNUSED, } struct ofpbuf *reply; - int err = nl_transact(NETLINK_GENERIC, request, &reply); + int err = nl_transact(NULL, NETLINK_GENERIC, request, &reply); if (err) { goto out; } @@ -3520,7 +3520,7 @@ dpif_netlink_ct_del_limits(struct dpif *dpif OVS_UNUSED, nl_msg_end_nested(request, opt_offset); } - int err = nl_transact(NETLINK_GENERIC, request, NULL); + int err = nl_transact(NULL, NETLINK_GENERIC, request, NULL); ofpbuf_delete(request); return err; @@ -4066,7 +4066,7 @@ dpif_netlink_meter_transact(struct ofpbuf *request, struct ofpbuf **replyp, const struct nl_policy *reply_policy, struct nlattr **a, size_t size_a) { - int error = nl_transact(NETLINK_GENERIC, request, replyp); + int error = nl_transact(NULL, NETLINK_GENERIC, request, replyp); ofpbuf_uninit(request); if (error) { @@ -4818,7 +4818,7 @@ dpif_netlink_vport_transact(const struct dpif_netlink_vport *request, request_buf = ofpbuf_new(1024); dpif_netlink_vport_to_ofpbuf(request, request_buf); - error = nl_transact(NETLINK_GENERIC, request_buf, bufp); + error = nl_transact(NULL, NETLINK_GENERIC, request_buf, bufp); ofpbuf_delete(request_buf); if (reply) { @@ -4969,7 +4969,7 @@ dpif_netlink_dp_dump_start(struct nl_dump *dump) buf = ofpbuf_new(1024); dpif_netlink_dp_to_ofpbuf(&request, buf); - nl_dump_start(dump, NETLINK_GENERIC, buf); + nl_dump_start(NULL, dump, NETLINK_GENERIC, buf); ofpbuf_delete(buf); } @@ -4990,7 +4990,7 @@ dpif_netlink_dp_transact(const struct dpif_netlink_dp *request, request_buf = ofpbuf_new(1024); dpif_netlink_dp_to_ofpbuf(request, request_buf); - error = nl_transact(NETLINK_GENERIC, request_buf, bufp); + error = nl_transact(NULL, NETLINK_GENERIC, request_buf, bufp); ofpbuf_delete(request_buf); if (reply) { @@ -5223,7 +5223,7 @@ dpif_netlink_flow_transact(struct dpif_netlink_flow *request, request_buf = ofpbuf_new(1024); dpif_netlink_flow_to_ofpbuf(request, request_buf); - error = nl_transact(NETLINK_GENERIC, request_buf, bufp); + error = nl_transact(NULL, NETLINK_GENERIC, request_buf, bufp); ofpbuf_delete(request_buf); if (reply) { diff --git a/lib/netdev-linux.c b/lib/netdev-linux.c index 0cd0850a3..2353ee1a2 100644 --- a/lib/netdev-linux.c +++ b/lib/netdev-linux.c @@ -3358,7 +3358,7 @@ start_queue_dump(const struct netdev *netdev, struct queue_dump_state *state) return false; } tcmsg->tcm_parent = 0; - nl_dump_start(&state->dump, NETLINK_ROUTE, &request); + nl_dump_start(NULL, &state->dump, NETLINK_ROUTE, &request); ofpbuf_uninit(&request); ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE); @@ -6722,7 +6722,7 @@ get_stats_via_netlink(const struct netdev *netdev_, struct netdev_stats *stats) RTM_GETLINK, NLM_F_REQUEST); ofpbuf_put_zeros(&request, sizeof(struct ifinfomsg)); nl_msg_put_string(&request, IFLA_IFNAME, netdev_get_name(netdev_)); - error = nl_transact(NETLINK_ROUTE, &request, &reply); + error = nl_transact(NULL, NETLINK_ROUTE, &request, &reply); ofpbuf_uninit(&request); if (error) { return error; @@ -6858,7 +6858,7 @@ netdev_linux_update_via_netlink(struct netdev_linux *netdev) nl_msg_put_u32(&request, IFLA_EXT_MASK, RTEXT_FILTER_SKIP_STATS); - error = nl_transact(NETLINK_ROUTE, &request, &reply); + error = nl_transact(NULL, NETLINK_ROUTE, &request, &reply); ofpbuf_uninit(&request); if (error) { ofpbuf_delete(reply); diff --git a/lib/netlink-conntrack.c b/lib/netlink-conntrack.c index 0b3a8adf5..79ca17ec9 100644 --- a/lib/netlink-conntrack.c +++ b/lib/netlink-conntrack.c @@ -144,7 +144,7 @@ nl_ct_dump_start(struct nl_ct_dump_state **statep, const uint16_t *zone, if (zone) { nl_msg_put_be16(&state->buf, CTA_ZONE, htons(*zone)); } - nl_dump_start(&state->dump, NETLINK_NETFILTER, &state->buf); + nl_dump_start(NULL, &state->dump, NETLINK_NETFILTER, &state->buf); ofpbuf_clear(&state->buf); /* Buckets to store connections are not used. */ @@ -236,7 +236,7 @@ nl_ct_flush(void) nl_msg_put_nfgenmsg(&buf, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST); - err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + err = nl_transact(NULL, NETLINK_NETFILTER, &buf, NULL); ofpbuf_uninit(&buf); /* Expectations are flushed automatically, because they do not @@ -260,7 +260,7 @@ nl_ct_flush_tuple(const struct ct_dpif_tuple *tuple, uint16_t zone) err = EOPNOTSUPP; goto out; } - err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + err = nl_transact(NULL, NETLINK_NETFILTER, &buf, NULL); out: ofpbuf_uninit(&buf); return err; @@ -278,7 +278,7 @@ nl_ct_flush_zone_with_cta_zone(uint16_t flush_zone) IPCTNL_MSG_CT_DELETE, NLM_F_REQUEST); nl_msg_put_be16(&buf, CTA_ZONE, htons(flush_zone)); - err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + err = nl_transact(NULL, NETLINK_NETFILTER, &buf, NULL); ofpbuf_uninit(&buf); return err; @@ -340,7 +340,7 @@ nl_ct_flush_zone(uint16_t flush_zone) nl_msg_put_nfgenmsg(&buf, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET, NLM_F_REQUEST); nl_msg_put_be16(&buf, CTA_ZONE, htons(flush_zone)); - nl_dump_start(&dump, NETLINK_NETFILTER, &buf); + nl_dump_start(NULL, &dump, NETLINK_NETFILTER, &buf); ofpbuf_clear(&buf); for (;;) { @@ -374,7 +374,7 @@ nl_ct_flush_zone(uint16_t flush_zone) attrs[CTA_TUPLE_ORIG]->nla_len - NLA_HDRLEN); nl_msg_put_unspec(&delete, CTA_ID, attrs[CTA_ID] + 1, attrs[CTA_ID]->nla_len - NLA_HDRLEN); - nl_transact(NETLINK_NETFILTER, &delete, NULL); + nl_transact(NULL, NETLINK_NETFILTER, &delete, NULL); ofpbuf_clear(&delete); } @@ -1101,7 +1101,7 @@ nl_ct_set_timeout_policy(const struct nl_ct_timeout_policy *nl_tp) } nl_msg_end_nested(&buf, offset); - int err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + int err = nl_transact(NULL, NETLINK_NETFILTER, &buf, NULL); ofpbuf_uninit(&buf); return err; } @@ -1116,7 +1116,7 @@ nl_ct_get_timeout_policy(const char *tp_name, nl_msg_put_nfgenmsg(&request, 0, AF_UNSPEC, NFNL_SUBSYS_CTNETLINK_TIMEOUT, IPCTNL_MSG_TIMEOUT_GET, NLM_F_REQUEST | NLM_F_ACK); nl_msg_put_string(&request, CTA_TIMEOUT_NAME, tp_name); - int err = nl_transact(NETLINK_NETFILTER, &request, &reply); + int err = nl_transact(NULL, NETLINK_NETFILTER, &request, &reply); if (err) { goto out; } @@ -1139,7 +1139,7 @@ nl_ct_del_timeout_policy(const char *tp_name) IPCTNL_MSG_TIMEOUT_DELETE, NLM_F_REQUEST | NLM_F_ACK); nl_msg_put_string(&buf, CTA_TIMEOUT_NAME, tp_name); - int err = nl_transact(NETLINK_NETFILTER, &buf, NULL); + int err = nl_transact(NULL, NETLINK_NETFILTER, &buf, NULL); ofpbuf_uninit(&buf); return err; } @@ -1162,7 +1162,7 @@ nl_ct_timeout_policy_dump_start( IPCTNL_MSG_TIMEOUT_GET, NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP); - nl_dump_start(&state->dump, NETLINK_NETFILTER, &request); + nl_dump_start(NULL, &state->dump, NETLINK_NETFILTER, &request); ofpbuf_uninit(&request); ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE); return 0; diff --git a/lib/netlink-socket.c b/lib/netlink-socket.c index 976ed15e8..801b4badd 100644 --- a/lib/netlink-socket.c +++ b/lib/netlink-socket.c @@ -17,6 +17,7 @@ #include <config.h> #include "netlink-socket.h" #include <errno.h> +#include <fcntl.h> #include <inttypes.h> #include <stdlib.h> #include <sys/socket.h> @@ -25,6 +26,7 @@ #include <unistd.h> #include "coverage.h" #include "openvswitch/dynamic-string.h" +#include "openvswitch/shash.h" #include "hash.h" #include "openvswitch/hmap.h" #include "netlink.h" @@ -94,6 +96,7 @@ struct nl_sock { uint32_t pid; int protocol; unsigned int rcvbuf; /* Receive buffer size (SO_RCVBUF). */ + char *netns; }; /* Compile-time limit on iovecs, so that we can allocate a maximum-size array @@ -106,7 +109,7 @@ struct nl_sock { * Initialized by nl_sock_create(). */ static int max_iovs; -static int nl_pool_alloc(int protocol, struct nl_sock **sockp); +static int nl_pool_alloc(const char *, int protocol, struct nl_sock **sockp); static void nl_pool_release(struct nl_sock *); /* Creates a new netlink socket for the given netlink 'protocol' @@ -145,6 +148,7 @@ nl_sock_create(int protocol, struct nl_sock **sockp) *sockp = NULL; sock = xmalloc(sizeof *sock); + sock->netns = NULL; #ifdef _WIN32 sock->overlapped.hEvent = NULL; @@ -294,6 +298,7 @@ nl_sock_destroy(struct nl_sock *sock) #else close(sock->fd); #endif + free(sock->netns); free(sock); } } @@ -1152,6 +1157,9 @@ nl_sock_drain(struct nl_sock *sock) * Netlink socket created with the given 'protocol', and initializes 'dump' to * reflect the state of the operation. * + * The dump runs in the specified 'netns'. If 'netns' is NULL the current will + * be used. + * * 'request' must contain a Netlink message. Before sending the message, * nlmsg_len will be finalized to match request->size, and nlmsg_pid will be * set to the Netlink socket's pid. NLM_F_DUMP and NLM_F_ACK will be set in @@ -1165,13 +1173,14 @@ nl_sock_drain(struct nl_sock *sock) * The caller must eventually destroy 'request'. */ void -nl_dump_start(struct nl_dump *dump, int protocol, const struct ofpbuf *request) +nl_dump_start(const char *netns, struct nl_dump *dump, int protocol, + const struct ofpbuf *request) { nl_msg_nlmsghdr(request)->nlmsg_flags |= NLM_F_DUMP | NLM_F_ACK; ovs_mutex_init(&dump->mutex); ovs_mutex_lock(&dump->mutex); - dump->status = nl_pool_alloc(protocol, &dump->sock); + dump->status = nl_pool_alloc(netns, protocol, &dump->sock); if (!dump->status) { dump->status = nl_sock_send__(dump->sock, request, nl_sock_allocate_seq(dump->sock, 1), @@ -1725,39 +1734,95 @@ struct nl_pool { int n; }; +struct nl_ns_pool { + struct nl_pool pools[MAX_LINKS]; +}; + static struct ovs_mutex pool_mutex = OVS_MUTEX_INITIALIZER; -static struct nl_pool pools[MAX_LINKS] OVS_GUARDED_BY(pool_mutex); +static struct shash pools OVS_GUARDED_BY(pool_mutex) = + SHASH_INITIALIZER(&pools); static int -nl_pool_alloc(int protocol, struct nl_sock **sockp) +nl_sock_ns_create(const char *netns, int protocol, struct nl_sock **sockp) { + int ret, ns_fd, ns_default_fd, err; + if (netns) { + ns_default_fd = open("/proc/self/ns/net", O_RDONLY); + if (ns_default_fd < 0) { + VLOG_ERR("something wrong when opening self net fd, %d\n", + errno); + return -errno; + } + char *netns_path = xasprintf("/var/run/netns/%s", netns); + ns_fd = open(netns_path, O_RDONLY); + free(netns_path); + if (ns_fd < 0) { + VLOG_ERR("something wrong when opening other net fd, %d\n", + errno); + return -errno; + } + err = setns(ns_fd, CLONE_NEWNET); + if (err < 0) { + VLOG_ABORT("something wrong during setns to target, %d\n", + errno); + } + close(ns_fd); + } + ret = nl_sock_create(protocol, sockp); + if (netns) { + err = setns(ns_default_fd, CLONE_NEWNET); + if (err < 0) { + VLOG_ABORT("something wrong during setns to home, %d\n", + errno); + } + close(ns_default_fd); + if (*sockp) { + (*sockp)->netns = xstrdup(netns); + } + } + return ret; +} + +static int +nl_pool_alloc(const char *netns, int protocol, struct nl_sock **sockp) { struct nl_sock *sock = NULL; struct nl_pool *pool; - ovs_assert(protocol >= 0 && protocol < ARRAY_SIZE(pools)); + ovs_assert(protocol >= 0 && protocol < MAX_LINKS); ovs_mutex_lock(&pool_mutex); - pool = &pools[protocol]; - if (pool->n > 0) { - sock = pool->socks[--pool->n]; + const char * netns_name = netns ? netns : ""; + + struct nl_ns_pool *ns_pools = shash_find_data(&pools, netns_name); + if (ns_pools) { + pool = &ns_pools->pools[protocol]; + if (pool->n > 0) { + sock = pool->socks[--pool->n]; + } + + if (sock) { + ovs_mutex_unlock(&pool_mutex); + *sockp = sock; + return 0; + } } ovs_mutex_unlock(&pool_mutex); - - if (sock) { - *sockp = sock; - return 0; - } else { - return nl_sock_create(protocol, sockp); - } + return nl_sock_ns_create(netns, protocol, sockp); } static void nl_pool_release(struct nl_sock *sock) { if (sock) { - struct nl_pool *pool = &pools[sock->protocol]; + const char * netns_name = sock->netns ? sock->netns : ""; ovs_mutex_lock(&pool_mutex); + struct nl_ns_pool *ns_pools = shash_find_data(&pools, netns_name); + if (!ns_pools) { + ns_pools = xzalloc(sizeof(*ns_pools)); + shash_add(&pools, netns_name, ns_pools); + } + struct nl_pool *pool = &ns_pools->pools[sock->protocol]; if (pool->n < ARRAY_SIZE(pool->socks)) { pool->socks[pool->n++] = sock; sock = NULL; @@ -1772,6 +1837,9 @@ nl_pool_release(struct nl_sock *sock) * (e.g. NETLINK_ROUTE or NETLINK_GENERIC) and waits for a response. If * successful, returns 0. On failure, returns a positive errno value. * + * The 'request' is send in the specified netns. If 'netns' is NULL the current + * namespace is used. + * * If 'replyp' is nonnull, then on success '*replyp' is set to the kernel's * reply, which the caller is responsible for freeing with ofpbuf_delete(), and * on failure '*replyp' is set to NULL. If 'replyp' is null, then the kernel's @@ -1810,13 +1878,13 @@ nl_pool_release(struct nl_sock *sock) * needs to be idempotent. */ int -nl_transact(int protocol, const struct ofpbuf *request, +nl_transact(const char *netns, int protocol, const struct ofpbuf *request, struct ofpbuf **replyp) { struct nl_sock *sock; int error; - error = nl_pool_alloc(protocol, &sock); + error = nl_pool_alloc(netns, protocol, &sock); if (error) { if (replyp) { *replyp = NULL; @@ -1851,13 +1919,13 @@ nl_transact(int protocol, const struct ofpbuf *request, * nl_transact() for some caveats. */ void -nl_transact_multiple(int protocol, +nl_transact_multiple(const char *netns, int protocol, struct nl_transaction **transactions, size_t n) { struct nl_sock *sock; int error; - error = nl_pool_alloc(protocol, &sock); + error = nl_pool_alloc(netns, protocol, &sock); if (!error) { nl_sock_transact_multiple(sock, transactions, n); nl_pool_release(sock); diff --git a/lib/netlink-socket.h b/lib/netlink-socket.h index 7852ad052..e4d645a62 100644 --- a/lib/netlink-socket.h +++ b/lib/netlink-socket.h @@ -251,9 +251,10 @@ struct nl_transaction { }; /* Transactions without an allocated socket. */ -int nl_transact(int protocol, const struct ofpbuf *request, +int nl_transact(const char *netns, int protocol, const struct ofpbuf *request, struct ofpbuf **replyp); -void nl_transact_multiple(int protocol, struct nl_transaction **, size_t n); +void nl_transact_multiple(const char *netns, int protocol, + struct nl_transaction **, size_t n); /* Table dumping. */ #define NL_DUMP_BUFSIZE 4096 @@ -270,7 +271,7 @@ struct nl_dump { struct ovs_mutex mutex; /* Protects 'status', synchronizes recv(). */ }; -void nl_dump_start(struct nl_dump *, int protocol, +void nl_dump_start(const char *netns, struct nl_dump *dump, int protocol, const struct ofpbuf *request); bool nl_dump_next(struct nl_dump *, struct ofpbuf *reply, struct ofpbuf *buf); int nl_dump_done(struct nl_dump *); diff --git a/lib/route-table.c b/lib/route-table.c index c6cb21394..d5d98585e 100644 --- a/lib/route-table.c +++ b/lib/route-table.c @@ -156,7 +156,7 @@ route_table_wait(void) } static bool -route_table_dump_one_table(unsigned char id) +route_table_dump_one_table(const char *netns, unsigned char id) { uint64_t reply_stub[NL_DUMP_BUFSIZE / 8]; struct ofpbuf request, reply, buf; @@ -172,7 +172,7 @@ route_table_dump_one_table(unsigned char id) rq_msg->rtm_family = AF_UNSPEC; rq_msg->rtm_table = id; - nl_dump_start(&dump, NETLINK_ROUTE, &request); + nl_dump_start(netns, &dump, NETLINK_ROUTE, &request); ofpbuf_uninit(&request); ofpbuf_use_stub(&buf, reply_stub, sizeof reply_stub); @@ -212,7 +212,7 @@ route_table_reset(void) COVERAGE_INC(route_table_dump); for (size_t i = 0; i < ARRAY_SIZE(tables); i++) { - if (!route_table_dump_one_table(tables[i])) { + if (!route_table_dump_one_table(NULL, tables[i])) { /* Got unfiltered reply, no need to dump further. */ break; } diff --git a/lib/tc.c b/lib/tc.c index e55ba3b1b..56f4ca7a0 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -244,7 +244,7 @@ static void request_from_tcf_id(struct tcf_id *id, uint16_t eth_type, int tc_transact(struct ofpbuf *request, struct ofpbuf **replyp) { - int error = nl_transact(NETLINK_ROUTE, request, replyp); + int error = nl_transact(NULL, NETLINK_ROUTE, request, replyp); ofpbuf_uninit(request); return error; } @@ -2349,7 +2349,7 @@ tc_dump_flower_start(struct tcf_id *id, struct nl_dump *dump, bool terse) nl_msg_put_unspec(&request, TCA_DUMP_FLAGS, &dump_flags, sizeof dump_flags); } - nl_dump_start(dump, NETLINK_ROUTE, &request); + nl_dump_start(NULL, dump, NETLINK_ROUTE, &request); ofpbuf_uninit(&request); return 0; @@ -2361,7 +2361,7 @@ tc_dump_tc_chain_start(struct tcf_id *id, struct nl_dump *dump) struct ofpbuf request; request_from_tcf_id(id, 0, RTM_GETCHAIN, NLM_F_DUMP, &request); - nl_dump_start(dump, NETLINK_ROUTE, &request); + nl_dump_start(NULL, dump, NETLINK_ROUTE, &request); ofpbuf_uninit(&request); return 0; @@ -2380,7 +2380,7 @@ tc_dump_tc_action_start(char *name, struct nl_dump *dump) nl_msg_end_nested(&request, offset); nl_msg_end_nested(&request, root_offset); - nl_dump_start(dump, NETLINK_ROUTE, &request); + nl_dump_start(NULL, dump, NETLINK_ROUTE, &request); ofpbuf_uninit(&request); return 0; -- 2.47.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
