[netcf-devel] [PATCH] Add required vlan properties to live xml.

Laine Stump laine at laine.org
Thu Oct 29 06:26:38 UTC 2009


Grab the vlan id and master interface name during the libnl "link"
cache traversal callback, and add it to the xml for vlans.

This is necessary for the xml to pass libvirt's parsing.
---
 src/dutil.c |  127 +++++++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 98 insertions(+), 29 deletions(-)

diff --git a/src/dutil.c b/src/dutil.c
index d4eea90..93bb597 100644
--- a/src/dutil.c
+++ b/src/dutil.c
@@ -50,6 +50,9 @@
 #include <netlink/cache.h>
 #include <netlink/route/addr.h>
 #include <netlink/route/link.h>
+/* For some reason, the headers for libnl vlan functions aren't installed */
+extern int rtnl_link_vlan_get_id(struct rtnl_link *link);
+
 
 #include <libxml/parser.h>
 #include <libxml/relaxng.h>
@@ -611,6 +614,7 @@ struct nl_callback_data {
     xmlNodePtr protov4;
     xmlNodePtr protov6;
     xmlNodePtr mac;
+    xmlNodePtr vlan;
     struct netcf_if *nif;
 };
 
@@ -709,58 +713,123 @@ error:
     return;
 }
 
-static void add_mac_cb(struct nl_object *obj, void *arg) {
+static void add_link_info_cb(struct nl_object *obj, void *arg) {
     struct nl_callback_data *cb_data = arg;
     struct rtnl_link *iflink = (struct rtnl_link *)obj;
     struct netcf *ncf = cb_data->nif->ncf;
 
     struct nl_addr *addr;
-    char mac_str[64];
+    char *link_type;
     xmlNodePtr cur;
     xmlAttrPtr prop = NULL;
 
-    if (cb_data->mac != NULL)
-        return;
+    /* look for mac address */
+    if ((cb_data->mac == NULL)
+        && ((addr = rtnl_link_get_addr(iflink)) != NULL)
+        && !nl_addr_iszero(addr)) {
 
-    addr = rtnl_link_get_addr(iflink);
-    if ((addr == NULL) || nl_addr_iszero(addr))
-        return;
+        char mac_str[64];
 
-    nl_addr2str(addr, mac_str, sizeof(mac_str));
+        nl_addr2str(addr, mac_str, sizeof(mac_str));
+
+        for (cur = cb_data->root->children; cur != NULL; cur = cur->next) {
+            if ((cur->type == XML_ELEMENT_NODE) &&
+                xmlStrEqual(cur->name, BAD_CAST "mac")) {
+                cb_data->mac = cur;
+                break;
+            }
+        }
 
-    for (cur = cb_data->root->children; cur != NULL; cur = cur->next) {
-        if ((cur->type == XML_ELEMENT_NODE) &&
-            xmlStrEqual(cur->name, BAD_CAST "mac")) {
-            cb_data->mac = cur;
-            break;
+        if (cb_data->mac == NULL) {
+            /* No mac node exists in the document, create a new one.
+             */
+            cb_data->mac = xmlNewDocNode(cb_data->doc, NULL,
+                                         BAD_CAST "mac", NULL);
+            ERR_NOMEM(cb_data->mac == NULL, ncf);
+
+            cur = xmlAddChild(cb_data->root, cb_data->mac);
+            if (cur == NULL) {
+                xmlFreeNode(cb_data->mac);
+                cb_data->mac = NULL;
+                report_error(ncf, NETCF_ENOMEM, NULL);
+                goto error;
+            }
         }
+
+        prop = xmlSetProp(cb_data->mac, BAD_CAST "address", BAD_CAST mac_str);
+        ERR_NOMEM(prop == NULL, ncf);
     }
 
-    if (cb_data->mac == NULL) {
-        /* No mac node exists in the document, create a new one.
-         */
-        cb_data->mac = xmlNewDocNode(cb_data->doc, NULL, BAD_CAST "mac", NULL);
-        ERR_NOMEM(cb_data->mac == NULL, ncf);
+    /* If this is a vlan link, get the master interface and vlan id.
+     */
+    if ((cb_data->vlan == NULL)
+        && ((link_type = rtnl_link_get_info_type(iflink)) != NULL)
+        && STREQ(link_type, "vlan")) {
+
+        struct rtnl_link *master_link;
+        char *master_name = NULL;
+        int vlan_id = rtnl_link_vlan_get_id(iflink);
+        int l_link = rtnl_link_get_link(iflink);
+
+        if ((l_link != RTNL_LINK_NOT_FOUND)
+            && ((master_link = rtnl_link_get(nl_object_get_cache(obj),
+                                             l_link)) != NULL)
+            && ((master_name = rtnl_link_get_name(master_link)) != NULL)) {
+
+            char vlan_id_str[16];
+            xmlNodePtr master;
+
+            for (cur = cb_data->root->children; cur != NULL; cur = cur->next) {
+                if ((cur->type == XML_ELEMENT_NODE) &&
+                    xmlStrEqual(cur->name, BAD_CAST "vlan")) {
+                    cb_data->vlan = cur;
+                    break;
+                }
+            }
 
-        cur = xmlAddChild(cb_data->root, cb_data->mac);
-        if (cur == NULL) {
-            xmlFreeNode(cb_data->mac);
-            cb_data->mac = NULL;
-            report_error(ncf, NETCF_ENOMEM, NULL);
-            goto error;
+            if (cb_data->vlan == NULL) {
+                /* No vlan node exists in the document, create a new one.
+                 */
+                cb_data->vlan = xmlNewDocNode(cb_data->doc, NULL,
+                                              BAD_CAST "vlan", NULL);
+                ERR_NOMEM(cb_data->vlan == NULL, ncf);
+
+                cur = xmlAddChild(cb_data->root, cb_data->vlan);
+                if (cur == NULL) {
+                    xmlFreeNode(cb_data->vlan);
+                    cb_data->vlan = NULL;
+                    report_error(ncf, NETCF_ENOMEM, NULL);
+                    goto error;
+                }
+            }
+
+            snprintf(vlan_id_str, sizeof(vlan_id_str), "%d", vlan_id);
+            prop = xmlSetProp(cb_data->vlan, BAD_CAST "tag",
+                              BAD_CAST vlan_id_str);
+            ERR_NOMEM(prop == NULL, ncf);
+
+            master = xmlNewDocNode(cb_data->doc, NULL,
+                                   BAD_CAST "interface", NULL);
+            ERR_NOMEM(master == NULL, ncf);
+            cur = xmlAddChild(cb_data->vlan, master);
+            if (cur == NULL) {
+                xmlFreeNode(master);
+                report_error(ncf, NETCF_ENOMEM, NULL);
+                goto error;
+            }
+            prop = xmlSetProp(master, BAD_CAST "name", BAD_CAST master_name);
+            ERR_NOMEM(prop == NULL, ncf);
         }
     }
 
-    prop = xmlSetProp(cb_data->mac, BAD_CAST "address", BAD_CAST mac_str);
-    ERR_NOMEM(prop == NULL, ncf);
-
 error:
     return;
 }
 
 void add_state_to_xml_doc(struct netcf_if *nif, xmlDocPtr doc) {
 
-    struct nl_callback_data cb_data = { doc, NULL, NULL, NULL, NULL, nif };
+    struct nl_callback_data cb_data
+        = { doc, NULL, NULL, NULL, NULL, NULL, nif };
     struct rtnl_addr *filter_addr = NULL;
     struct rtnl_link *filter_link = NULL;
     int ifindex, code;
@@ -795,7 +864,7 @@ void add_state_to_xml_doc(struct netcf_if *nif, xmlDocPtr doc) {
 
     rtnl_link_set_ifindex(filter_link, ifindex);
     nl_cache_foreach_filter(nif->ncf->driver->link_cache,
-                            OBJ_CAST(filter_link), add_mac_cb,
+                            OBJ_CAST(filter_link), add_link_info_cb,
                             &cb_data);
 
     /* Build an rtnl_addr with the interface name set. This is used by
-- 
1.6.5.15.gc274d



More information about the netcf-devel mailing list