netlink-socket: New function nl_lookup_genl_mcgroup().
authorEthan Jackson <ethan@nicira.com>
Tue, 23 Aug 2011 20:13:34 +0000 (13:13 -0700)
committerEthan Jackson <ethan@nicira.com>
Fri, 2 Sep 2011 00:18:52 +0000 (17:18 -0700)
lib/netlink-socket.c
lib/netlink-socket.h

index 719f6589d9eeae8b82b1062620c53b32a52926c5..394107e4d9bf76d895a1063914e9f2775d2d270a 100644 (file)
@@ -680,6 +680,7 @@ static struct hmap genl_families = HMAP_INITIALIZER(&genl_families);
 
 static const struct nl_policy family_policy[CTRL_ATTR_MAX + 1] = {
     [CTRL_ATTR_FAMILY_ID] = {.type = NL_A_U16},
+    [CTRL_ATTR_MCAST_GROUPS] = {.type = NL_A_NESTED},
 };
 
 static struct genl_family *
@@ -725,11 +726,11 @@ genl_family_to_name(uint16_t id)
     }
 }
 
-static int do_lookup_genl_family(const char *name)
+static int
+do_lookup_genl_family(const char *name, struct nlattr **attrs)
 {
     struct nl_sock *sock;
     struct ofpbuf request, *reply;
-    struct nlattr *attrs[ARRAY_SIZE(family_policy)];
     int retval;
 
     retval = nl_sock_create(NETLINK_GENERIC, &sock);
@@ -767,6 +768,51 @@ static int do_lookup_genl_family(const char *name)
     return retval;
 }
 
+/* Finds the multicast group called 'group_name' in genl family 'family_name'.
+ * When successful, writes its result to 'multicast_group' and returns 0.
+ * Otherwise, clears 'multicast_group' and returns a positive error code. */
+int
+nl_lookup_genl_mcgroup(const char *family_name, const char *group_name,
+                       unsigned int *multicast_group)
+{
+    struct nlattr *family_attrs[ARRAY_SIZE(family_policy)];
+    struct ofpbuf all_mcs;
+    struct nlattr *mc;
+    unsigned int left;
+    int retval;
+
+    *multicast_group = 0;
+    retval = do_lookup_genl_family(family_name, family_attrs);
+    if (retval <= 0) {
+        assert(retval);
+        return -retval;
+    }
+
+    nl_attr_get_nested(family_attrs[CTRL_ATTR_MCAST_GROUPS], &all_mcs);
+    NL_ATTR_FOR_EACH (mc, left, all_mcs.data, all_mcs.size) {
+        static const struct nl_policy mc_policy[] = {
+            [CTRL_ATTR_MCAST_GRP_ID] = {.type = NL_A_U32},
+            [CTRL_ATTR_MCAST_GRP_NAME] = {.type = NL_A_STRING},
+        };
+
+        struct nlattr *mc_attrs[ARRAY_SIZE(mc_policy)];
+        const char *mc_name;
+
+        if (!nl_parse_nested(mc, mc_policy, mc_attrs, ARRAY_SIZE(mc_policy))) {
+            return EPROTO;
+        }
+
+        mc_name = nl_attr_get_string(mc_attrs[CTRL_ATTR_MCAST_GRP_NAME]);
+        if (!strcmp(group_name, mc_name)) {
+            *multicast_group =
+                nl_attr_get_u32(mc_attrs[CTRL_ATTR_MCAST_GRP_ID]);
+            return 0;
+        }
+    }
+
+    return EPROTO;
+}
+
 /* If '*number' is 0, translates the given Generic Netlink family 'name' to a
  * number and stores it in '*number'.  If successful, returns 0 and the caller
  * may use '*number' as the family number.  On failure, returns a positive
@@ -774,8 +820,10 @@ static int do_lookup_genl_family(const char *name)
 int
 nl_lookup_genl_family(const char *name, int *number)
 {
+    struct nlattr *attrs[ARRAY_SIZE(family_policy)];
+
     if (*number == 0) {
-        *number = do_lookup_genl_family(name);
+        *number = do_lookup_genl_family(name, attrs);
         assert(*number != 0);
     }
     return *number > 0 ? 0 : -*number;
index 43b4b023da046fef490c8258ea47c191bc56b0a9..f43c3d004dadb4b0a721c669b2c93937bc7bb24d 100644 (file)
@@ -75,5 +75,7 @@ int nl_dump_done(struct nl_dump *);
 
 /* Miscellaneous */
 int nl_lookup_genl_family(const char *name, int *number);
+int nl_lookup_genl_mcgroup(const char *family_name, const char *group_name,
+                           unsigned int *multicast_group);
 
 #endif /* netlink-socket.h */