@@ -16,6 +16,7 @@
#include <config.h>
#include "if-notifier.h"
+#include "netnsid.h"
#include "rtnetlink.h"
#include "util.h"
@@ -30,7 +31,7 @@ if_notifier_cb(const struct rtnetlink_change *change, void *aux)
{
struct if_notifier *notifier;
- if (change && change->irrelevant) {
+ if (change && (change->irrelevant || change->nsid != NETNSID_LOCAL)) {
return;
}
@@ -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,13 +188,14 @@ 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);
+ int group = nln->parse(&buf, nsid, nln->change);
if (group != 0) {
nln_report(nln, nln->change, group);
@@ -37,11 +37,13 @@ typedef void nln_notify_func(const void *change, void *aux);
/* Function called to parse incoming nln notifications. The 'buf' message
* should be parsed into 'change' as specified in nln_create().
+ * 'nsid` is the network namespace id from which the netlink event came from.
* Returns the multicast_group the change belongs to, or 0 for a parse error.
*/
-typedef int nln_parse_func(struct ofpbuf *buf, void *change);
+typedef int nln_parse_func(struct ofpbuf *buf, int nsid, 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);
@@ -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>
@@ -33,6 +33,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"
@@ -84,7 +85,7 @@ static struct nln_notifier *name_notifier = NULL;
static bool route_table_valid = false;
static bool rules_valid = false;
-static int route_nln_parse(struct ofpbuf *, void *change);
+static int route_nln_parse(struct ofpbuf *, int nsid, void *change);
static void rule_handle_msg(const struct route_table_msg *);
static int rule_parse(struct ofpbuf *, void *change);
@@ -137,7 +138,7 @@ route_table_init(void)
ovs_assert(!rule6_notifier);
ovs_router_init();
- nln = nln_create(NETLINK_ROUTE, route_nln_parse, &nln_rtmsg_change);
+ nln = nln_create(NETLINK_ROUTE, false, route_nln_parse, &nln_rtmsg_change);
route_notifier =
nln_notifier_create(nln, RTNLGRP_IPV4_ROUTE,
@@ -295,7 +296,7 @@ rule_handle_msg(const struct route_table_msg *change)
}
static int
-route_nln_parse(struct ofpbuf *buf, void *change_)
+route_nln_parse(struct ofpbuf *buf, int nsid OVS_UNUSED, void *change_)
{
const struct nlmsghdr *nlmsg = buf->data;
@@ -795,10 +796,9 @@ name_table_init(void)
static void
-name_table_change(const struct rtnetlink_change *change,
- void *aux OVS_UNUSED)
+name_table_change(const struct rtnetlink_change *change, void *aux OVS_UNUSED)
{
- if (change && change->irrelevant) {
+ if (change && (change->nsid != NETNSID_LOCAL || change->irrelevant)) {
return;
}
@@ -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,
@@ -24,6 +24,7 @@
#include "netlink.h"
#include "netlink-notifier.h"
+#include "netnsid.h"
#include "openvswitch/ofpbuf.h"
#include "packets.h"
@@ -89,6 +90,7 @@ rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change)
bool parsed = false;
change->irrelevant = false;
+ change->nsid = NETNSID_UNSET;
if (rtnetlink_type_is_rtnlgrp_link(nlmsg->nlmsg_type)) {
/* Policy for RTNLGRP_LINK messages.
@@ -190,9 +192,14 @@ rtnetlink_parse(struct ofpbuf *buf, struct rtnetlink_change *change)
/* Return RTNLGRP_LINK on success, 0 on parse error. */
static int
-rtnetlink_parse_cb(struct ofpbuf *buf, void *change)
+rtnetlink_parse_cb(struct ofpbuf *buf, int nsid, void *change)
{
- return rtnetlink_parse(buf, change) ? RTNLGRP_LINK : 0;
+ bool ret = rtnetlink_parse(buf, change);
+ if (ret) {
+ ((struct rtnetlink_change *) change)->nsid = nsid;
+ return RTNLGRP_LINK;
+ }
+ return 0;
}
/* Registers 'cb' to be called with auxiliary data 'aux' with network device
@@ -210,7 +217,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);
@@ -39,6 +39,8 @@ struct rtnetlink_change {
/* Common attributes. */
int if_index; /* Index of network device. */
const char *ifname; /* Name of network device. */
+ int nsid; /* Network namespace id of the from which
+ the event comes from. */
/* Network device link status. */
int master_ifindex; /* Ifindex of datapath master (0 if none). */
@@ -63,8 +65,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 *aux);
+void rtnetlink_notify_func(const struct rtnetlink_change *change, void *aux);
bool rtnetlink_type_is_rtnlgrp_link(uint16_t type);
bool rtnetlink_type_is_rtnlgrp_addr(uint16_t type);
@@ -129,6 +129,13 @@ test_lib_route_table_change(struct route_table_msg *change,
route_data_destroy(&change->rd);
}
+static int
+test_lib_route_table_parse(struct ofpbuf *buf, int nsid OVS_UNUSED,
+ void *change)
+{
+ return route_table_parse(buf, change);
+}
+
static void
test_lib_route_table_monitor(int argc, char *argv[])
{
@@ -143,7 +150,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, test_lib_route_table_parse, &rtmsg);
route_notifier =
nln_notifier_create(nln, RTNLGRP_IPV4_ROUTE,
@@ -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"
@@ -32,10 +33,14 @@ struct test_change {
};
static int
-event_parse(struct ofpbuf *buf, void *change_)
+event_parse(struct ofpbuf *buf, int nsid, void *change_)
{
struct test_change *change = change_;
+ if (nsid != NETNSID_LOCAL) {
+ return 0;
+ }
+
if (nl_ct_parse_entry(buf, &change->entry, &change->type)) {
switch (change->type) {
case NL_CT_EVENT_NEW:
@@ -80,7 +85,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);
Use a flag to request notifications form all network namespaces and include the namespace id from which notification came from in the parsing callback. Signed-off-by: Adrian Moreno <amorenoz@redhat.com> --- lib/if-notifier.c | 3 ++- lib/netlink-notifier.c | 14 +++++++++++--- lib/netlink-notifier.h | 6 ++++-- lib/netnsid.h | 1 + lib/route-table.c | 12 ++++++------ lib/route-table.h | 2 +- lib/rtnetlink.c | 14 +++++++++++--- lib/rtnetlink.h | 5 +++-- tests/test-lib-route-table.c | 9 ++++++++- tests/test-netlink-conntrack.c | 9 +++++++-- 10 files changed, 54 insertions(+), 21 deletions(-)