[ovs-dev] [genl 3/6] netlink-notifier: New function nln_set_mcgroup().
Ethan Jackson
ethan at nicira.com
Thu Aug 25 23:28:35 UTC 2011
This function will be helpful when the multicast group of a
netlink-notifier isn't known at creation time.
---
lib/netlink-notifier.c | 78 ++++++++++++++++++++++++++++++++++++++++++-----
lib/netlink-notifier.h | 1 +
2 files changed, 70 insertions(+), 9 deletions(-)
diff --git a/lib/netlink-notifier.c b/lib/netlink-notifier.c
index 1b7529d..a4c7406 100644
--- a/lib/netlink-notifier.c
+++ b/lib/netlink-notifier.c
@@ -18,6 +18,7 @@
#include "netlink-notifier.h"
+#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <stdlib.h>
@@ -33,6 +34,7 @@ VLOG_DEFINE_THIS_MODULE(netlink_notifier);
COVERAGE_DEFINE(nln_changed);
static void nln_report(struct nln *nln, void *change);
+static int nln_init_sock(struct nln *nln);
struct nln {
struct nl_sock *notify_sock; /* Netlink socket. */
@@ -50,7 +52,12 @@ struct nln {
* created handle will listen for netlink messages on 'multicast_group' using
* netlink protocol 'protocol' (e.g. NETLINK_ROUTE, NETLINK_GENERIC, ...).
* Incoming messages will be parsed with 'parse' which will be passed 'change'
- * as an argument. */
+ * as an argument.
+ *
+ * Sometimes, a caller may not know the appropriate multicast group at creation
+ * time. In this case, 'multicast_group' may be 0, in which case no
+ * notifications will occur until a valid 'multicast_group' is passed into
+ * nln_set_mcgroup(). */
struct nln *
nln_create(int protocol, int multicast_group, nln_parse_func *parse,
void *change)
@@ -80,6 +87,42 @@ nln_destroy(struct nln *nln)
}
}
+/* Causes 'nln' to listen on the given 'multicast_group'. Returns 0 if
+ * successful, otherwise a positive error code. */
+int
+nln_set_mcgroup(struct nln *nln, int multicast_group)
+{
+ int old_mcg;
+ int error = 0;
+
+ old_mcg = nln->multicast_group;
+ nln->multicast_group = multicast_group;
+
+ if (nln->multicast_group == old_mcg
+ || list_is_empty(&nln->all_notifiers)) {
+ return 0;
+ }
+
+ if (!nln->notify_sock) {
+ return nln_init_sock(nln);
+ } else {
+ assert(old_mcg);
+ }
+
+ error = nl_sock_leave_mcgroup(nln->notify_sock, old_mcg);
+ if (!error) {
+ error = nl_sock_join_mcgroup(nln->notify_sock, nln->multicast_group);
+ }
+
+ if (error) {
+ VLOG_WARN("could not change multicast group: %s", strerror(error));
+ nl_sock_destroy(nln->notify_sock);
+ nln->notify_sock = NULL;
+ }
+
+ return error;
+}
+
/* Registers 'cb' to be called with auxiliary data 'aux' with change
* notifications. The notifier is stored in 'notifier', which the caller must
* not modify or free.
@@ -93,19 +136,12 @@ nln_notifier_register(struct nln *nln, struct nln_notifier *notifier,
nln_notify_func *cb, void *aux)
{
if (!nln->notify_sock) {
- struct nl_sock *sock;
int error;
- error = nl_sock_create(nln->protocol, &sock);
- if (!error) {
- error = nl_sock_join_mcgroup(sock, nln->multicast_group);
- }
+ error = nln_init_sock(nln);
if (error) {
- nl_sock_destroy(sock);
- VLOG_WARN("could not create netlink socket: %s", strerror(error));
return error;
}
- nln->notify_sock = sock;
} else {
/* Catch up on notification work so that the new notifier won't
* receive any stale notifications. */
@@ -192,3 +228,27 @@ nln_report(struct nln *nln, void *change)
notifier->cb(change, notifier->aux);
}
}
+
+static int
+nln_init_sock(struct nln *nln)
+{
+ assert(!nln->notify_sock);
+
+ if (nln->multicast_group) {
+ struct nl_sock *sock;
+ int error;
+
+ error = nl_sock_create(nln->protocol, &sock);
+ if (!error) {
+ error = nl_sock_join_mcgroup(sock, nln->multicast_group);
+ }
+ if (error) {
+ nl_sock_destroy(sock);
+ VLOG_WARN("could not create netlink socket: %s", strerror(error));
+ return error;
+ }
+ nln->notify_sock = sock;
+ }
+
+ return 0;
+}
diff --git a/lib/netlink-notifier.h b/lib/netlink-notifier.h
index 60b5991..42acae7 100644
--- a/lib/netlink-notifier.h
+++ b/lib/netlink-notifier.h
@@ -46,6 +46,7 @@ struct nln_notifier {
struct nln *nln_create(int protocol, int multicast_group, nln_parse_func *,
void *change);
void nln_destroy(struct nln *);
+int nln_set_mcgroup(struct nln *nln, int multicast_group);
int nln_notifier_register(struct nln *, struct nln_notifier *,
nln_notify_func *, void *aux);
void nln_notifier_unregister(struct nln *, struct nln_notifier *);
--
1.7.6
More information about the dev
mailing list