Use a flag to request notifications form all network namespaces and include the namespace id from which notification came from in the callback.
Signed-off-by: Adrian Moreno <[email protected]> --- lib/if-notifier.c | 5 +++-- lib/netlink-notifier.c | 22 +++++++++++++++------- lib/netlink-notifier.h | 10 ++++++---- lib/netnsid.h | 1 + lib/route-table.c | 17 +++++++++++------ lib/route-table.h | 2 +- lib/rtnetlink.c | 6 ++++-- lib/rtnetlink.h | 2 +- tests/system-route.at | 12 ++++++------ tests/test-lib-route-table.c | 20 +++++++++++++++----- tests/test-netlink-conntrack.c | 7 ++++--- 11 files changed, 67 insertions(+), 37 deletions(-) diff --git a/lib/if-notifier.c b/lib/if-notifier.c index f2d7157b9..9b450fa22 100644 --- a/lib/if-notifier.c +++ b/lib/if-notifier.c @@ -16,6 +16,7 @@ #include <config.h> #include "if-notifier.h" +#include "netnsid.h" #include "rtnetlink.h" #include "util.h" @@ -26,11 +27,11 @@ struct if_notifier { }; static void -if_notifier_cb(const struct rtnetlink_change *change, void *aux) +if_notifier_cb(const struct rtnetlink_change *change, int nsid, void *aux) { struct if_notifier *notifier; - if (change && change->irrelevant) { + if (change && (change->irrelevant || nsid != NETNSID_LOCAL)) { return; } diff --git a/lib/netlink-notifier.c b/lib/netlink-notifier.c index ea4742a90..0d24a45da 100644 --- a/lib/netlink-notifier.c +++ b/lib/netlink-notifier.c @@ -25,6 +25,7 @@ #include "coverage.h" #include "netlink.h" #include "netlink-socket.h" +#include "netnsid.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" @@ -41,6 +42,7 @@ struct nln { int protocol; /* Protocol passed to nl_sock_create(). */ nln_parse_func *parse; /* Message parsing function. */ void *change; /* Change passed to parse. */ + bool all_netns; /* Whether to listen on all namespaces. */ }; struct nln_notifier { @@ -55,10 +57,11 @@ struct nln_notifier { /* Creates an nln handle which may be used to manage change notifications. The * created handle will listen for netlink messages on 'multicast_group' using * netlink protocol 'protocol' (e.g. NETLINK_ROUTE, NETLINK_GENERIC, ...). + * If 'all_netns', it will listen for events on all network namespaces. * Incoming messages will be parsed with 'parse' which will be passed 'change' * as an argument. */ struct nln * -nln_create(int protocol, nln_parse_func *parse, void *change) +nln_create(int protocol, bool all_netns, nln_parse_func *parse, void *change) { struct nln *nln; @@ -68,6 +71,7 @@ nln_create(int protocol, nln_parse_func *parse, void *change) nln->parse = parse; nln->change = change; nln->has_run = false; + nln->all_netns = all_netns; ovs_list_init(&nln->all_notifiers); return nln; @@ -112,6 +116,9 @@ nln_notifier_create(struct nln *nln, int multicast_group, nln_notify_func *cb, ovs_strerror(error)); return NULL; } + if (nln->all_netns) { + nl_sock_listen_all_nsid(sock, true); + } nln->notify_sock = sock; } else { /* Catch up on notification work so that the new notifier won't @@ -181,19 +188,20 @@ nln_run(struct nln *nln) nln->has_run = true; for (;;) { uint64_t buf_stub[4096 / 8]; + int nsid = NETNSID_UNSET; struct ofpbuf buf; int error; ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); - error = nl_sock_recv(nln->notify_sock, &buf, NULL, false); + error = nl_sock_recv(nln->notify_sock, &buf, &nsid, false); if (!error) { int group = nln->parse(&buf, nln->change); if (group != 0) { - nln_report(nln, nln->change, group); + nln_report(nln, nln->change, group, nsid); } else { VLOG_WARN_RL(&rl, "unexpected netlink message contents"); - nln_report(nln, NULL, 0); + nln_report(nln, NULL, 0, nsid); } ofpbuf_uninit(&buf); } else if (error == EAGAIN) { @@ -203,7 +211,7 @@ nln_run(struct nln *nln) nl_sock_drain(nln->notify_sock); /* The socket buffer might be full, there could be too many * notifications, so it makes sense to call nln_report() */ - nln_report(nln, NULL, 0); + nln_report(nln, NULL, 0, NETNSID_UNSET); VLOG_WARN_RL(&rl, "netlink receive buffer overflowed"); } else { VLOG_WARN_RL(&rl, "error reading netlink socket: %s", @@ -225,7 +233,7 @@ nln_wait(struct nln *nln) } void OVS_NO_SANITIZE_FUNCTION -nln_report(const struct nln *nln, void *change, int group) +nln_report(const struct nln *nln, void *change, int group, int nsid) { struct nln_notifier *notifier; @@ -235,7 +243,7 @@ nln_report(const struct nln *nln, void *change, int group) LIST_FOR_EACH (notifier, node, &nln->all_notifiers) { if (!change || group == notifier->multicast_group) { - notifier->cb(change, notifier->aux); + notifier->cb(change, nsid, notifier->aux); } } } diff --git a/lib/netlink-notifier.h b/lib/netlink-notifier.h index dd0c183de..60c002615 100644 --- a/lib/netlink-notifier.h +++ b/lib/netlink-notifier.h @@ -32,8 +32,9 @@ struct ofpbuf; * specific change filled out by an nln_parse_func. It may be null if the * buffer of change information overflowed, in which case the function must * assume that everything may have changed. 'aux' is as specified in - * nln_notifier_register(). */ -typedef void nln_notify_func(const void *change, void *aux); + * nln_notifier_register(). 'nsid` is the network namespace id from which the + * netlink event came from. */ +typedef void nln_notify_func(const void *change, int nsid, void *aux); /* Function called to parse incoming nln notifications. The 'buf' message * should be parsed into 'change' as specified in nln_create(). @@ -41,12 +42,13 @@ typedef void nln_notify_func(const void *change, void *aux); */ typedef int nln_parse_func(struct ofpbuf *buf, void *change); -struct nln *nln_create(int protocol, nln_parse_func *, void *change); +struct nln *nln_create(int protocol, bool all_netns, nln_parse_func *, + void *change); void nln_destroy(struct nln *); struct nln_notifier *nln_notifier_create(struct nln *, int multicast_group, nln_notify_func *, void *aux); void nln_notifier_destroy(struct nln_notifier *); void nln_run(struct nln *); void nln_wait(struct nln *); -void nln_report(const struct nln *nln, void *change, int group); +void nln_report(const struct nln *nln, void *change, int group, int nsid); #endif /* netlink-notifier.h */ diff --git a/lib/netnsid.h b/lib/netnsid.h index 1d5ab83c5..47f55ee6c 100644 --- a/lib/netnsid.h +++ b/lib/netnsid.h @@ -18,6 +18,7 @@ #define NETNSID_H 1 #include <stdbool.h> +#include "util.h" #ifdef HAVE_LINUX_NET_NAMESPACE_H #include <linux/net_namespace.h> diff --git a/lib/route-table.c b/lib/route-table.c index ca87ff7db..3127d9f85 100644 --- a/lib/route-table.c +++ b/lib/route-table.c @@ -32,6 +32,7 @@ #include "netlink.h" #include "netlink-notifier.h" #include "netlink-socket.h" +#include "netnsid.h" #include "openvswitch/list.h" #include "openvswitch/ofpbuf.h" #include "ovs-router.h" @@ -74,11 +75,12 @@ static bool route_table_valid = false; static void route_table_reset(void); static void route_table_handle_msg(const struct route_table_msg *, void *aux); -static void route_table_change(struct route_table_msg *, void *aux); +static void route_table_change(struct route_table_msg *, int nsid, void *aux); static void route_map_clear(void); static void name_table_init(void); -static void name_table_change(const struct rtnetlink_change *, void *); +static void name_table_change(const struct rtnetlink_change *, int nsid, + void *); static void route_data_destroy_nexthops__(struct route_data *rd) @@ -116,7 +118,8 @@ route_table_init(void) ovs_assert(!route6_notifier); ovs_router_init(); - nln = nln_create(NETLINK_ROUTE, route_table_parse, &nln_rtmsg_change); + nln = nln_create(NETLINK_ROUTE, false, route_table_parse, + &nln_rtmsg_change); route_notifier = nln_notifier_create(nln, RTNLGRP_IPV4_ROUTE, @@ -538,10 +541,12 @@ is_standard_table_id(uint32_t table_id) } static void -route_table_change(struct route_table_msg *change, void *aux OVS_UNUSED) +route_table_change(struct route_table_msg *change, int nsid, + void *aux OVS_UNUSED) { if (!change || (change->relevant + && nsid == NETNSID_LOCAL && is_standard_table_id(change->rd.rta_table_id))) { route_table_valid = false; } @@ -599,10 +604,10 @@ name_table_init(void) static void -name_table_change(const struct rtnetlink_change *change, +name_table_change(const struct rtnetlink_change *change, int nsid, void *aux OVS_UNUSED) { - if (change && change->irrelevant) { + if (change && (nsid != NETNSID_LOCAL || change->irrelevant)) { return; } diff --git a/lib/route-table.h b/lib/route-table.h index b805e84dd..1d0e4e3e5 100644 --- a/lib/route-table.h +++ b/lib/route-table.h @@ -79,7 +79,7 @@ * static struct route_table_msg nln_change; * static struct nln *nln = NULL; * - * nln = nln_create(NETLINK_ROUTE, route_table_parse, NULL); + * nln = nln_create(NETLINK_ROUTE, false, nln_route_table_parse, NULL); * * route6_notifier = * nln_notifier_create(nln, RTNLGRP_IPV6_ROUTE, diff --git a/lib/rtnetlink.c b/lib/rtnetlink.c index 37078d00e..82613cfd5 100644 --- a/lib/rtnetlink.c +++ b/lib/rtnetlink.c @@ -24,6 +24,7 @@ #include "netlink.h" #include "netlink-notifier.h" +#include "netnsid.h" #include "openvswitch/ofpbuf.h" #include "packets.h" @@ -210,7 +211,8 @@ struct nln_notifier * rtnetlink_notifier_create(rtnetlink_notify_func *cb, void *aux) { if (!nln) { - nln = nln_create(NETLINK_ROUTE, rtnetlink_parse_cb, &rtn_change); + nln = nln_create(NETLINK_ROUTE, false, rtnetlink_parse_cb, + &rtn_change); } return nln_notifier_create(nln, RTNLGRP_LINK, (nln_notify_func *) cb, aux); @@ -249,6 +251,6 @@ void rtnetlink_report_link(void) { if (nln) { - nln_report(nln, NULL, RTNLGRP_LINK); + nln_report(nln, NULL, RTNLGRP_LINK, NETNSID_UNSET); } } diff --git a/lib/rtnetlink.h b/lib/rtnetlink.h index cf3f600f0..7ca068488 100644 --- a/lib/rtnetlink.h +++ b/lib/rtnetlink.h @@ -63,7 +63,7 @@ struct rtnetlink_change { * have changed. 'aux' is as specified in the call to * rtnetlink_notifier_register(). */ typedef -void rtnetlink_notify_func(const struct rtnetlink_change *change, +void rtnetlink_notify_func(const struct rtnetlink_change *change, int nsid, void *aux); bool rtnetlink_type_is_rtnlgrp_link(uint16_t type); diff --git a/tests/system-route.at b/tests/system-route.at index 66bfd0e8e..5366965fe 100644 --- a/tests/system-route.at +++ b/tests/system-route.at @@ -128,7 +128,7 @@ Cached: 10.0.0.17/32 dev p1-route SRC 10.0.0.17 local Cached: 10.0.0.18/32 dev p1-route SRC 10.0.0.17 ]) AT_CHECK([ovstest test-lib-route-table-dump | \ - awk '/rta_table_id:.*42/{print$1" "$15" "$16}' | sort], [0], [dnl + awk '/rta_table_id:.*42/{print$1" "$17" "$18}' | sort], [0], [dnl 10.0.0.19/32 rta_table_id: 42 10.0.0.20/32 rta_table_id: 1042 ]) @@ -299,7 +299,7 @@ on_exit 'ip link del p1-route' dnl Add ip address. AT_CHECK([ip addr add 10.0.0.17/24 dev p1-route], [0], [stdout]) AT_CHECK([ovstest test-lib-route-table-dump | \ - awk '/^10.0.0.17/{print$1" "$6" "$7}'], [0], [dnl + awk '/^10.0.0.17/{print$1" "$8" "$9}'], [0], [dnl 10.0.0.17/32 rtm_protocol: RTPROT_KERNEL ]) @@ -307,11 +307,11 @@ dnl Add route. AT_CHECK([ip route add 192.168.10.12/32 dev p1-route via 10.0.0.18], [0], [stdout]) AT_CHECK([ovstest test-lib-route-table-dump | \ - awk '/^192.168.10.12/{print$1" "$17" "$18}'], [0], [dnl + awk '/^192.168.10.12/{print$1" "$19" "$20}'], [0], [dnl 192.168.10.12/32 rta_priority: 0 ]) AT_CHECK([ovstest test-lib-route-table-dump | \ - awk '/^192.168.10.12/{print$1" "$6" "$7}'], [0], [dnl + awk '/^192.168.10.12/{print$1" "$8" "$9}'], [0], [dnl 192.168.10.12/32 rtm_protocol: RTPROT_BOOT ]) @@ -323,11 +323,11 @@ dnl Add route with priority. AT_CHECK([ip route add 192.168.10.12/32 dev p1-route via 10.0.0.18 metric 42], [0], [stdout]) AT_CHECK([ovstest test-lib-route-table-dump | \ - awk '/^192.168.10.12/{print$1" "$17" "$18}'], [0], [dnl + awk '/^192.168.10.12/{print$1" "$19" "$20}'], [0], [dnl 192.168.10.12/32 rta_priority: 42 ]) AT_CHECK([ovstest test-lib-route-table-dump | \ - awk '/^192.168.10.12/{print$1" "$6" "$7}'], [0], [dnl + awk '/^192.168.10.12/{print$1" "$8" "$9}'], [0], [dnl 192.168.10.12/32 rtm_protocol: RTPROT_BOOT ]) diff --git a/tests/test-lib-route-table.c b/tests/test-lib-route-table.c index 4ba17826e..e42068dfc 100644 --- a/tests/test-lib-route-table.c +++ b/tests/test-lib-route-table.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include "netlink-notifier.h" +#include "netnsid.h" #include "ovstest.h" #include "packets.h" #include "route-table.h" @@ -72,6 +73,7 @@ rt_table_name(uint32_t id) static void test_lib_route_table_handle_msg(const struct route_table_msg *change, + int nsid, void *data OVS_UNUSED) { struct ds nexthop_addr = DS_EMPTY_INITIALIZER; @@ -83,10 +85,10 @@ test_lib_route_table_handle_msg(const struct route_table_msg *change, ipv6_format_mapped(&change->rd.rta_prefsrc, &rta_prefsrc); ipv6_format_mapped(&change->rd.rta_dst, &rta_dst); - printf("%s/%u relevant: %d nlmsg_type: %d rtm_protocol: %s (%u) " + printf("%s/%u nsid %d relevant: %d nlmsg_type: %d rtm_protocol: %s (%u) " "rtn_local: %d rta_prefsrc: %s rta_mark: %"PRIu32" " "rta_table_id: %s rta_priority: %"PRIu32"\n", - ds_cstr(&rta_dst), rd->rtm_dst_len, change->relevant, + ds_cstr(&rta_dst), rd->rtm_dst_len, nsid, change->relevant, change->nlmsg_type, rt_prot_name(rd->rtm_protocol), rd->rtm_protocol, rd->rtn_local, ds_cstr(&rta_prefsrc), rd->rta_mark, rt_table_name(rd->rta_table_id), rd->rta_priority); @@ -108,19 +110,27 @@ test_lib_route_table_handle_msg(const struct route_table_msg *change, ds_destroy(&rta_dst); } +static void +__test_lib_route_table_dump(const struct route_table_msg *change, + void *data OVS_UNUSED) { + + test_lib_route_table_handle_msg(change, NETNSID_LOCAL, NULL); +} + static void test_lib_route_table_dump(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) { route_table_dump_one_table(RT_TABLE_UNSPEC, - test_lib_route_table_handle_msg, + __test_lib_route_table_dump, NULL); } static void test_lib_route_table_change(struct route_table_msg *change, + int nsid, void *aux OVS_UNUSED) { - test_lib_route_table_handle_msg(change, NULL); + test_lib_route_table_handle_msg(change, nsid, NULL); route_data_destroy(&change->rd); } @@ -138,7 +148,7 @@ test_lib_route_table_monitor(int argc, char *argv[]) exit(EXIT_FAILURE); } - nln = nln_create(NETLINK_ROUTE, route_table_parse, &rtmsg); + nln = nln_create(NETLINK_ROUTE, false, route_table_parse, &rtmsg); route_notifier = nln_notifier_create(nln, RTNLGRP_IPV4_ROUTE, diff --git a/tests/test-netlink-conntrack.c b/tests/test-netlink-conntrack.c index 2a62615b2..61a4d697d 100644 --- a/tests/test-netlink-conntrack.c +++ b/tests/test-netlink-conntrack.c @@ -22,6 +22,7 @@ #include "ct-dpif.h" #include "netlink-conntrack.h" #include "netlink-notifier.h" +#include "netnsid.h" #include "ovstest.h" #include "openvswitch/poll-loop.h" @@ -50,11 +51,11 @@ event_parse(struct ofpbuf *buf, void *change_) } static void -event_print(const void *change_, void *aux OVS_UNUSED) +event_print(const void *change_, int nsid, void *aux OVS_UNUSED) { const struct test_change *change = change_; - if (change) { + if (change && nsid == NETNSID_LOCAL) { struct ds ds = DS_EMPTY_INITIALIZER; nl_ct_format_event_entry(&change->entry, change->type, &ds, true, @@ -80,7 +81,7 @@ test_nl_ct_monitor(struct ovs_cmdl_context *ctx OVS_UNUSED) unsigned i; - nln = nln_create(NETLINK_NETFILTER, event_parse, &change); + nln = nln_create(NETLINK_NETFILTER, false, event_parse, &change); for (i = 0; i < ARRAY_SIZE(groups); i++) { notifiers[i] = nln_notifier_create(nln, groups[i], event_print, NULL); -- 2.52.0 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
