[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