[Libvirt-cim] [PATCH v5] vlan extention - add function library for readonly usage

xiaxia347work xiaxia347work at 163.com
Fri Jan 27 14:05:28 UTC 2012


> Code looks good. I have marked some nits. Take a look.
> I have not yet applied the patch or done any testing. 
>
> When do we see the actual provider? This patch is more of a
> backend/infrastructure. We will also need a CIM layer.
>
> -Sharad Mishra
>
OK,  Soon I will send the provider with improved library code.


> On Thu, 2012-01-26 at 04:04 +0800, xiaxia347work at 163.com wrote:
>> From: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
>>
>>     This patch contain 1 test program and 1 c file doing xml and structure
>> mapping. It expose some API to translate xml to device structure, in a similar
>> way to code in device_parsing.c. Also some other files are changed to let new
>> code use their internal functions. Type following Command in libxkutil
>> directory:
>> sudo CU_DEBUG=stdout .libs/network_parsing_test
>> could see what it have done.
>>
>> v5: calling libvirt API which employ netcf instead of using libnl. From git log
>> these API are available since 0.9.2, and this patch is tested with libvirt
>> 0.9.4.
>>
>> Signed-off-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
>> ---
>>  libxkutil/Makefile.am            |   12 +-
>>  libxkutil/misc_util.c            |   10 +-
>>  libxkutil/network_parsing.c      |  665 ++++++++++++++++++++++++++++++++++++++
>>  libxkutil/network_parsing.h      |  160 +++++++++
>>  libxkutil/network_parsing_test.c |   61 ++++
>>  libxkutil/xmlgen.c               |    2 +-
>>  libxkutil/xmlgen.h               |    2 +
>>  7 files changed, 906 insertions(+), 6 deletions(-)
>>  create mode 100644 libxkutil/network_parsing.c
>>  create mode 100644 libxkutil/network_parsing.h
>>  create mode 100644 libxkutil/network_parsing_test.c
>>
>> diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
>> index f1adc03..c0e62eb 100644
>> --- a/libxkutil/Makefile.am
>> +++ b/libxkutil/Makefile.am
>> @@ -4,12 +4,14 @@ AM_CFLAGS = $(CFLAGS_STRICT) \
>>              -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\"
>>
>>  noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \
>> -                 pool_parsing.h acl_parsing.h
>> +                 pool_parsing.h acl_parsing.h \
>> +                 network_parsing.h
>>
>>  lib_LTLIBRARIES = libxkutil.la
>>
>>  libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \
>> -                       xmlgen.c infostore.c pool_parsing.c acl_parsing.c
>> +                       xmlgen.c infostore.c pool_parsing.c acl_parsing.c \
>> +                       network_parsing.c
>>  libxkutil_la_LDFLAGS = -version-info @VERSION_INFO@
>>  libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \
>>  		      @LIBUUID_LIBS@
>> @@ -19,3 +21,9 @@ noinst_PROGRAMS = xml_parse_test
>>  xml_parse_test_SOURCES = xml_parse_test.c
>>  xml_parse_test_LDADD = libxkutil.la \
>>  		       @LIBVIRT_LIBS@
>> +
>> +noinst_PROGRAMS += network_parsing_test
>> +
>> +network_parsing_test_SOURCES = network_parsing_test.c
>> +network_parsing_test_LDADD = libxkutil.la \
>> +		       @LIBVIRT_LIBS@
>> diff --git a/libxkutil/misc_util.c b/libxkutil/misc_util.c
>> index 61893c3..1c18c33 100644
>> --- a/libxkutil/misc_util.c
>> +++ b/libxkutil/misc_util.c
>> @@ -152,9 +152,13 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker,
>>
>>          uri = cn_to_uri(classname);
>>          if (!uri) {
>> -                cu_statusf(broker, s,
>> -                           CMPI_RC_ERR_FAILED,
>> -                           "Unable to generate URI from classname");
>> +                if (broker) {
>> +                        cu_statusf(broker, s,
>> +                              CMPI_RC_ERR_FAILED,
>> +                              "Unable to generate URI from classname");
>> +                }
>> +                CU_DEBUG("Unable to generate URI from classname,"
>> +                         " uri is %s.", uri);
>>                  return NULL;
>>          }
>>
>> diff --git a/libxkutil/network_parsing.c b/libxkutil/network_parsing.c
>> new file mode 100644
>> index 0000000..932000c
>> --- /dev/null
>> +++ b/libxkutil/network_parsing.c
>> @@ -0,0 +1,665 @@
>> +/*
>> + * Copyright IBM Corp. 2012
>> + *
>> + * Authors:
>> + *  Wenchao Xia <xiawenc at cn.ibm.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + *
>> + * This library is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, write to the Free Software
>> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
>> + */
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <stdlib.h>
>> +#include <stdbool.h>
>> +#include <inttypes.h>
>> +#include <sys/stat.h>
>> +
>> +#include <libvirt/libvirt.h>
>> +#include <libxml/tree.h>
>> +#include <libxml/parser.h>
>> +#include <libxml/xpath.h>
>> +#include <libcmpiutil/libcmpiutil.h>
>> +
>> +#include "misc_util.h"
>> +#include "xmlgen.h"
>> +#include "device_parsing.h"
>> +#include "network_parsing.h"
>> +
>> +#define XML_ERROR "Failed to allocate XML memory"
>> +
>> +static void vlan_prop_print(struct VLAN_Prop *pvlan_prop)
>> +{
>> +    struct VLAN_Prop_8021q *p_8021q;
>> +    CMD_DEBUG(1, "--VLAN props: type %d.\n",
>> +            pvlan_prop->vlan_type);
>> +    if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
>> +        p_8021q = &(pvlan_prop->props.prop_8021q);
>> +        CMD_DEBUG(1, "----IEEE802.1.Q: id %d, parent %s.\n",
>> +                p_8021q->vlan_id, p_8021q->parent);
>> +    }
>> +}
>> +
>> +static void br_prop_print(struct BR_Prop *pbr_prop)
>> +{
>> +    int i = 0;
>> +    CMD_DEBUG(1, "--Bridge props: stp %d, delay %d, port_num %d.\n",
>> +            pbr_prop->STP, pbr_prop->delay, pbr_prop->port_num);
>> +    if (pbr_prop->port_names != NULL) {
>> +        CMD_DEBUG(1, "----Ports attached: ");
>> +        while (i < pbr_prop->port_num) {
>> +            CMD_DEBUG(1, " %s,", *(pbr_prop->port_names+i));
>> +            i++;
>> +        }
>> +        CMD_DEBUG(1, "\n");
>> +    }
>> +}
>> +
>> +void eth_iface_print(struct EthIface *piface)
>> +{
>> +    CMD_DEBUG(1, "Iface device: name %s.\n"
>> +        "--Main Props: parent %s, attach to %s, mac %s,"
>> +        " status %d, boot_mode %d, iface type 0x%x.\n",
>> +        piface->name, piface->dep_ifname, piface->attach_bridge,
>> +        piface->mac,
>> +        piface->run_prop.status, piface->run_prop.boot_mode, piface->eth_type);
>> +    if (piface->pbr_prop != NULL) {
>> +        br_prop_print(piface->pbr_prop);
>> +    }
>> +    if (piface->pvlan_prop != NULL) {
>> +        vlan_prop_print(piface->pvlan_prop);
>> +    }
>> +    return;
>> +}
>> +
>> +void eth_ifaceslist_print(struct EthIfacesList *plist)
>> +{
>> +    int i = 0;
>> +    CMD_DEBUG(1, "Have %d ifaces in the list:\n", plist->count);
>> +    while (i < plist->count) {
>> +        CMD_DEBUG(1, "%04d ", i);
>> +        eth_iface_print(plist->pifaces[i]);
>> +        i++;
>> +    }
>> +}
>> +
>> +static void vlan_prop_init(struct VLAN_Prop *pvlan_prop, int vlan_type)
>> +{
>> +    struct VLAN_Prop_8021q *p_8021q;
>> +    memset(pvlan_prop, 0, sizeof(struct VLAN_Prop));
>> +    pvlan_prop->vlan_type = vlan_type;
>> +    if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
>> +        p_8021q = &(pvlan_prop->props.prop_8021q);
>> +        p_8021q->vlan_id = NUM_NOT_GOT;
>> +    }
>> +}
>> +
>> +static void br_prop_init(struct BR_Prop *pbr_prop)
>> +{
>> +    memset(pbr_prop, 0, sizeof(struct BR_Prop));
>> +    pbr_prop->STP = NUM_NOT_GOT;
>> +    pbr_prop->delay = NUM_NOT_GOT;
>> +    pbr_prop->port_num = NUM_NOT_GOT;
>> +}
>> +
>> +void eth_iface_init(struct EthIface *piface)
>> +{
>> +    memset(piface, 0, sizeof(struct EthIface));
>> +    piface->eth_type = ETH_TYPE_NOT_GOT;
>> +    piface->run_prop.status = NUM_NOT_GOT;
>> +    piface->run_prop.boot_mode = BOOT_MODE_NOT_GOT;
>> +    return;
>> +}
>> +
>> +void eth_iface_add_br_prop(struct EthIface *piface)
>> +{
>> +    if (piface->pbr_prop != NULL) {
>> +        return;
>> +    }
>> +    SAFE_MALLOC(piface->pbr_prop, sizeof(struct BR_Prop));
>> +    br_prop_init(piface->pbr_prop);
>> +}
>> +
>> +void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type)
>> +{
>> +   if (piface->pvlan_prop != NULL) {
>> +        return;
>> +    }
>> +    SAFE_MALLOC(piface->pvlan_prop, sizeof(struct VLAN_Prop));
>> +    vlan_prop_init(piface->pvlan_prop, vlan_type);
>> +}
>> +
>> +static void vlan_prop_uninit(struct VLAN_Prop *pvlan_prop)
>> +{
>> +    struct VLAN_Prop_8021q *p_8021q;
>> +    if (pvlan_prop == NULL) {
>> +        return;
>> +    }
>> +    if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
>> +        p_8021q = &(pvlan_prop->props.prop_8021q);
>> +        SAFE_FREE(p_8021q->parent);
>> +    }
>> +}
>> +
>> +static void br_prop_uninit(struct BR_Prop *pbr_prop)
>> +{
>> +    int i;
>> +    if (pbr_prop == NULL) {
>> +        return;
>> +    }
>> +    i = 0;
>> +    if (pbr_prop->port_names != NULL) {
>> +        while (i < pbr_prop->port_num) {
>> +            SAFE_FREE(pbr_prop->port_names[i]);
>> +            i++;
>> +        }
>> +        SAFE_FREE(pbr_prop->port_names);
>> +    }
>> +}
>> +
>> +void eth_iface_uninit(struct EthIface *piface)
>> +{
>> +    if (piface == NULL) {
>> +        return;
>> +    }
>> +    SAFE_FREE(piface->name);
>> +    SAFE_FREE(piface->dep_ifname);
>> +    SAFE_FREE(piface->attach_bridge);
>> +    SAFE_FREE(piface->mac);
>> +    br_prop_uninit(piface->pbr_prop);
>> +    SAFE_FREE(piface->pbr_prop);
>> +    vlan_prop_uninit(piface->pvlan_prop);
>> +    SAFE_FREE(piface->pvlan_prop);
>> +    return;
>> +}
>> +
>> +void eth_ifaceslist_init(struct EthIfacesList *plist)
>> +{
>> +    plist->count = 0;
>> +}
>> +
>> +void eth_ifaceslist_uninit(struct EthIfacesList *plist)
>> +{
>> +    struct EthIface **t;
>> +    int i;
>> +    if (plist->count <= 0) {
>> +        return;
>> +    }
>> +    t = plist->pifaces;
>> +    i = 0;
>> +    while (i < plist->count) {
>> +        if (*t != NULL) {
>> +            eth_iface_uninit(*t);
>> +            SAFE_FREE(*t);
>> +        }
>> +        t++;
>> +        i++;
>> +    }
>> +    return;
>> +}
>> +
>> +int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface)
>> +{
>> +    if (plist->count >= MAX_IFACE_NUM) {
>> +        CU_DEBUG("too much device found.");
>> +        return 0;
>> +    }
>> +    plist->pifaces[plist->count] = *ppiface;
>> +    *ppiface = NULL;
>> +    plist->count++;
>> +    return 1;
>> +}
>> +
>> +struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist,
>> +                                       char *name)
>> +{
>> +    int i = 0;
>> +    struct EthIface *piface = NULL;
>> +
>> +    while (i < plist->count) {
>> +        piface = plist->pifaces[i];
>> +        i++;
>> +        if (piface != NULL) {
>> +            if (0 == strcmp(piface->name, name)) {
>
> can we do "if (strcmp(piface->name, name) == 0) { " ?
OK, just my custom.

>> +                return piface;
>> +            }
>> +        }
>> +    }
>> +    return NULL;
>> +}
>> +
>> +/* Dummy function to suppress error message from libxml2 */
>> +static void swallow_err_msg(void *ctx, const char *msg, ...)
>> +{
>> +        /* do nothing, just swallow the message. */
>> +}
>> +
>> +
>> +static const char *gen_eth_xmlnode_iface(xmlNodePtr root,
>> +                                   struct EthIface *piface,
>> +                                   struct EthIfacesList *plist,
>> +                                   int bridge_port_flag)
>> +{
>> +    const char *msg = NULL;
>> +    xmlNodePtr temp_node1 = NULL, temp_node2 = NULL, temp_node3 = NULL;
>> +    char *str, buf[16];
>> +    int i;
>> +    struct EthIface *pifaceport;
>> +
>> +    if (piface->name == NULL) {
>> +        msg = "iface have no name.\n";
>> +        goto out;
>> +    }
>> +    /* netcfg have no xml for iface attatched to bridge */
>> +    if ((piface->attach_bridge != NULL) && (bridge_port_flag != 1)) {
>
> What are you trying to eliminate here?
>
what I observed is that in netcf, if one eth is attached to a bridge, it have no a "stand along" xml for it, so jump out.
and if bride_port_flag == 1, it means try to generate a embbed xml node with limited property, do not jump out.
the function is re-entered later so need this flag making difference.

>> +        goto out;
>> +    }
>> +
>> +    temp_node1 = xmlNewChild(root, NULL, BAD_CAST "interface", NULL);
>> +    if (temp_node1 == NULL) {
>> +        msg = XML_ERROR;
>> +        goto out;
>> +    }
>> +    xmlNewProp(temp_node1, BAD_CAST "name", BAD_CAST piface->name);
>> +    if (piface->eth_type & ETH_TYPE_ETHER_ANY) {
>
> why do we require the above check? Can it be eliminated and just use the
> checks below?
>
right.

>> +        if (piface->eth_type & ETH_TYPE_ETHER_SUB_BRIDGE) {
>> +            str = "bridge";
>> +        } else if (piface->eth_type & ETH_TYPE_ETHER_SUB_VLAN) {
>> +            str = "vlan";
>> +        } else {
>> +            str = "ethernet";
>> +        }
>> +        xmlNewProp(temp_node1, BAD_CAST "type", BAD_CAST str);
>> +    }
>> +
>> +    if ((piface->pvlan_prop != NULL) &&
>> +        (piface->pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q)) {
>> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "vlan", NULL);
>> +        snprintf(buf, sizeof(buf),
>> +                 "%d", piface->pvlan_prop->props.prop_8021q.vlan_id);
>> +        xmlNewProp(temp_node2, BAD_CAST "tag", BAD_CAST buf);
>> +        temp_node3 = xmlNewChild(temp_node2, NULL, BAD_CAST "interface", NULL);
>> +        xmlNewProp(temp_node3, BAD_CAST "name",
>> +                   BAD_CAST piface->pvlan_prop->props.prop_8021q.parent);
>> +    }
>> +
>> +    /* if it is attached to bridge, only above properties could be set */
>> +    if (bridge_port_flag == 1) {
>> +        goto out;
>> +    }
>> +
>> +    if (piface->pbr_prop != NULL) {
>> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "bridge", NULL);
>> +        if (piface->pbr_prop->STP == 1) {
>> +            snprintf(buf, sizeof(buf), "on");
>> +        } else {
>> +            snprintf(buf, sizeof(buf), "off");
>> +        }
>> +        xmlNewProp(temp_node2, BAD_CAST "stp", BAD_CAST buf);
>> +        if (piface->pbr_prop->delay >= 0) {
>> +            snprintf(buf, sizeof(buf), "%d", piface->pbr_prop->delay);
>> +            xmlNewProp(temp_node2, BAD_CAST "delay", BAD_CAST buf);
>> +        }
>> +        if ((piface->pbr_prop->port_names != NULL) &&
>> +            (piface->pbr_prop->port_num > 0)) {
>> +            for (i = 0; i < piface->pbr_prop->port_num; i++) {
>> +                pifaceport = eth_ifaceslist_search(plist,
>> +                                     piface->pbr_prop->port_names[i]);
>> +                if (pifaceport == NULL) {
>> +                    CU_DEBUG("failed to find port %s of bridge %s in list.",
>> +                             piface->pbr_prop->port_names[i], piface->name);
>> +                } else {
>> +                    gen_eth_xmlnode_iface(temp_node2, pifaceport, plist, 1);
>> +                }
>> +            }
>> +        }
>> +    }
>> +
>> +    if (piface->run_prop.boot_mode == BOOT_MODE_AUTOSTART) {
>> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL);
>> +        xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "onboot");
>> +    } else if (piface->run_prop.boot_mode == BOOT_MODE_NONE) {
>> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL);
>> +        xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "none");
>> +    }
>> +    if (piface->mac != NULL) {
>> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "mac", NULL);
>> +        xmlNewProp(temp_node2, BAD_CAST "address", BAD_CAST piface->mac);
>> +    }
>> +
>> + out:
>> +    return msg;
>> +}
>> +
>> +static const char *gen_eth_xmlnode(xmlNodePtr root,
>> +                                   struct EthIfacesList *plist)
>> +{
>> +    const char *msg = NULL;
>> +    int i = 0;
>> +    struct EthIface *piface = NULL;
>> +
>> +    while (i < plist->count) {
>> +        piface = plist->pifaces[i];
>> +        i++;
>> +        msg = gen_eth_xmlnode_iface(root, piface, plist, 0);
>> +        if (msg != NULL) {
>> +            goto out;
>> +        }
>> +    }
>> +
>> + out:
>> +    return msg;
>> +}
>> +
>> +const char *EthIfaceListTOXML(char **ppxml,
>> +                              struct EthIfacesList *plist,
>> +                              int dump_all_flag)
>> +{
>> +    const char *msg = NULL;
>> +    xmlNodePtr root = NULL;
>> +
>> +    root = xmlNewNode(NULL, BAD_CAST "tmp");
>> +    if (root == NULL) {
>> +        msg = "failed to create root node.";
>> +        goto out;
>> +    }
>> +    msg = gen_eth_xmlnode(root, plist);
>> +    if (msg == NULL) {
>> +        if (dump_all_flag == 1) {
>> +            *ppxml = tree_to_xml(root);
>> +        } else {
>> +            *ppxml = tree_to_xml(root->children);
>> +        }
>> +    }
>> +
>> + out:
>> +    xmlFreeNode(root);
>> +    return msg;
>> +}
>> +
>> +static int parse_eth_xmlnode(struct EthIfacesList *plist, xmlNode *inode,
>> +                             int status, char *attached)
>> +{
>> +    struct EthIface *piface = NULL;
>> +    xmlNode *child1 = NULL, *child2 = NULL;
>> +    char *temp = NULL, **ppchar;
>> +
>> +    SAFE_MALLOC(piface, sizeof(struct EthIface));
>> +    eth_iface_init(piface);
>> +
>> +    piface->name = get_attr_value(inode, "name");
>> +    piface->run_prop.status = status;
>> +    if (attached != NULL) {
>> +        piface->attach_bridge = strdup(attached);
>> +    }
>> +    temp = get_attr_value(inode, "type");
>> +    if (temp != NULL) {
>> +        if (0 == strcmp(temp, "ethernet")) {
>
> can you change to if(strcmp() == 0)
>
OK.

>> +            piface->eth_type = ETH_TYPE_ETHER_ANY;
>> +        }
>> +        if (0 == strcmp(temp, "bridge")) {
>> +            piface->eth_type = ETH_TYPE_ETHER_ANY | ETH_TYPE_ETHER_SUB_BRIDGE;
>> +        }
>> +        if (0 == strcmp(temp, "vlan")) {
>> +            piface->eth_type = ETH_TYPE_ETHER_ANY | ETH_TYPE_ETHER_SUB_VLAN;
>> +        }
>> +        SAFE_FREE(temp);
>> +    }
>> +
>> +    for (child1 = inode->children; child1 != NULL; child1 = child1->next) {
>> +        if (XSTREQ(child1->name, "start")) {
>> +            temp = get_attr_value(child1, "mode");
>> +            if (0 == strcmp(temp, "onboot")) {
>
> change as above
>
>> +                piface->run_prop.boot_mode = BOOT_MODE_AUTOSTART;
>> +            }
>> +            if (0 == strcmp(temp, "none")) {
>> +                piface->run_prop.boot_mode = BOOT_MODE_NONE;
>> +            }
>> +            SAFE_FREE(temp);
>> +        }
>> +        if (XSTREQ(child1->name, "mac")) {
>> +            piface->mac = get_attr_value(child1, "address");
>> +        }
>> +        if (XSTREQ(child1->name, "bridge")) {
>> +            eth_iface_add_br_prop(piface);
>> +            temp = get_attr_value(child1, "stp");
>> +            if (0 == strcmp(temp, "on")) {
>> +                piface->pbr_prop->STP = 1;
>> +            }
>> +            if (0 == strcmp(temp, "off")) {
>> +                piface->pbr_prop->STP = 0;
>> +            }
>> +            SAFE_FREE(temp);
>> +            temp = get_attr_value(child1, "delay");
>> +            piface->pbr_prop->delay = strtol(temp, NULL, 10);
>> +            SAFE_FREE(temp);
>> +        }
>> +        if (XSTREQ(child1->name, "bridge")) {
>> +            eth_iface_add_br_prop(piface);
>> +            temp = get_attr_value(child1, "stp");
>> +            if (0 == strcmp(temp, "on")) {
>> +                piface->pbr_prop->STP = 1;
>> +            }
>> +            if (0 == strcmp(temp, "off")) {
>> +                piface->pbr_prop->STP = 0;
>> +            }
>> +            SAFE_FREE(temp);
>> +            temp = get_attr_value(child1, "delay");
>> +            piface->pbr_prop->delay = strtol(temp, NULL, 10);
>> +            SAFE_FREE(temp);
>> +            for (child2 = child1->children; child2 != NULL;
>> +                                            child2 = child2->next) {
>> +                if (XSTREQ(child2->name, "interface")) {
>> +                    if (piface->pbr_prop->port_names == NULL) {
>> +                        SAFE_CALLOC(piface->pbr_prop->port_names,
>> +                                    MAX_IFACE_NUM, sizeof(char *));
>> +                        piface->pbr_prop->port_num = 0;
>> +                    }
>> +                    ppchar = piface->pbr_prop->port_names +
>> +                             (piface->pbr_prop->port_num)++;
>> +                    *ppchar = get_attr_value(child2, "name");
>> +                    parse_eth_xmlnode(plist, child2, status, piface->name);
>> +                }
>> +            }
>> +        }
>> +        if (XSTREQ(child1->name, "vlan")) {
>> +            eth_iface_add_vlan_prop(piface, VLAN_TYPE_802_1_Q);
>> +            temp = get_attr_value(child1, "tag");
>> +            piface->pvlan_prop->props.prop_8021q.vlan_id =
>> +                                       strtol(temp, NULL, 10);
>> +            SAFE_FREE(temp);
>> +            for (child2 = child1->children; child2 != NULL;
>> +                                            child2 = child2->next) {
>> +                if (XSTREQ(child2->name, "interface")) {
>> +                    piface->pvlan_prop->props.prop_8021q.parent =
>> +                                      get_attr_value(child2, "name");
>> +                    piface->dep_ifname =
>> +                                      get_attr_value(child2, "name");
>> +                }
>> +            }
>> +        }
>> +    }
>> +
>> +    eth_ifaceslist_add(plist, &piface);
>> +    return 1;
>> +}
>> +
>> +static const char *XMLToEthIfaceList(struct EthIfacesList *plist,
>> +                                     const char *xml,
>> +                                     int status)
>> +{
>> +    xmlDoc *xmldoc;
>> +    xmlXPathContext *xpathCtx;
>> +    xmlXPathObject *xpathObj;
>> +    xmlChar *xpathstr;
>> +    xmlNode **dev_nodes = NULL;
>> +    xmlNodeSet *nsv = NULL;
>> +    int count = 0;
>> +    int len, devidx;
>> +    const char *msg = NULL;
>> +
>> +    len = strlen(xml) + 1;
>> +    xpathstr = (xmlChar *)"/interface";
>> +
>> +    xmlSetGenericErrorFunc(NULL, swallow_err_msg);
>> +    if ((xmldoc = xmlParseMemory(xml, len)) == NULL) {
>> +        msg = "failed to get xmldoc.";
>> +        goto err1;
>> +    }
>> +
>> +    if ((xpathCtx = xmlXPathNewContext(xmldoc)) == NULL) {
>> +        msg = "failed to get pathCtx";
>> +        goto err2;
>> +    }
>> +
>> +    if ((xpathObj = xmlXPathEvalExpression(xpathstr, xpathCtx))
>> +                == NULL) {
>> +        msg = "failed to get xpathObj";
>> +        goto err3;
>> +    }
>> +
>> +    nsv = xpathObj->nodesetval;
>> +    if (nsv == NULL) {
>> +        msg = "failed to get nodesetval.";
>> +        goto out;
>> +    }
>> +
>> +    dev_nodes = nsv->nodeTab;
>> +    count = nsv->nodeNr;
>> +
>> +    if (count <= 0) {
>> +        msg = "nodesetval have less that 1 values.";
>> +        goto out;
>> +    }
>> +
>> +    for (devidx = 0; devidx < count; devidx++) {
>> +        parse_eth_xmlnode(plist, dev_nodes[devidx], status, NULL);
>> +    }
>> +
>> + out:
>> +    xmlSetGenericErrorFunc(NULL, NULL);
>> +    xmlXPathFreeObject(xpathObj);
>> +
>> + err3:
>> +    xmlXPathFreeContext(xpathCtx);
>> + err2:
>> +    xmlFreeDoc(xmldoc);
>> + err1:
>> +    return msg;
>> +}
>> +
>> +CMPIStatus get_host_ifaces(struct EthIfacesList *plist,
>> +                           const CMPIBroker *broker, char *prefix)
>> +{
>> +    virConnectPtr conn = NULL;
>> +    virInterfacePtr iface;
>> +    CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
>> +    int num, listnum, i;
>> +    char **names = NULL;
>> +    char *dump = NULL;
>> +    int flags = 0;
>> +    const char *msg;
>> +
>> +    conn = connect_by_classname(broker, prefix, &s);
>> +    if (conn == NULL) {
>> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED, "connect failed.");
>> +        goto out;
>> +    }
>> +
>> +    /* list defined interfaces*/
>> +    num = virConnectNumOfDefinedInterfaces(conn);
>> +    if (num < 0) {
>> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
>> +                   "failed to find number of defined interfaces.");
>> +        goto out;
>> +    }
>> +    names = malloc(num * sizeof(char *));
>> +    listnum = virConnectListDefinedInterfaces(conn, names, num);
>> +    if (listnum < 0) {
>> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
>> +                   "failed to list names of defined interfaces.");
>> +        goto out;
>> +    }
>> +    CU_DEBUG("%d defined ifaces found from libvirt API.\n", listnum);
>> +
>> +    flags |= VIR_INTERFACE_XML_INACTIVE;
>> +    for (i = 0; i < listnum; i++) {
>> +        iface = virInterfaceLookupByName(conn, names[i]);
>> +        if (!iface) {
>> +            CU_DEBUG("failed to look up %s.\n", names[i]);
>> +            SAFE_FREE(names[i]);
>> +            continue;
>> +        }
>> +        SAFE_FREE(names[i]);
>> +        dump = virInterfaceGetXMLDesc(iface, flags);
>> +        CU_DEBUG("defined interface %d xml:\n%s", i, dump);
>> +        msg = XMLToEthIfaceList(plist, dump, 0);
>> +        if (msg != NULL) {
>> +            CU_DEBUG("failed parsing eth xml, msg is: %s.", msg);
>> +        }
>> +        SAFE_FREE(dump);
>> +        virInterfaceFree(iface);
>> +    }
>> +    SAFE_FREE(names);
>> +
>> +    /* list active interfaces*/
>> +    num = virConnectNumOfInterfaces(conn);
>> +    if (num < 0) {
>> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
>> +                   "failed to find number of active interfaces.");
>> +        goto out;
>> +    }
>> +    names = malloc(num * sizeof(char *));
>> +
>> +    listnum = virConnectListInterfaces(conn, names, num);
>> +    if (listnum < 0) {
>> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
>> +                   "failed to list names of active interfacess.");
>> +        goto out;
>> +    }
>> +    CU_DEBUG("%d active ifaces found from libvirt API.\n", listnum);
>> +
>> +    flags |= VIR_INTERFACE_XML_INACTIVE;
>> +    for (i = 0; i < listnum; i++) {
>> +        iface = virInterfaceLookupByName(conn, names[i]);
>> +        if (!iface) {
>> +            CU_DEBUG("failed to look up %s.\n", names[i]);
>> +            SAFE_FREE(names[i]);
>> +            continue;
>> +        }
>> +        SAFE_FREE(names[i]);
>> +        dump = virInterfaceGetXMLDesc(iface, flags);
>> +        CU_DEBUG("active interface %d xml:\n%s", i, dump);
>> +        msg = XMLToEthIfaceList(plist, dump, 1);
>> +        if (msg != NULL) {
>> +            CU_DEBUG("failed parsing eth xml, msg is: %s.", msg);
>> +        }
>> +        SAFE_FREE(dump);
>> +        virInterfaceFree(iface);
>> +    }
>> +    s.rc = CMPI_RC_OK;
>> +
>> + out:
>> +    virConnectClose(conn);
>> +    SAFE_FREE(names);
>> +    return s;
>> +}
>> +/*
>> + * Local Variables:
>> + * mode: C
>> + * c-set-style: "K&R"
>> + * tab-width: 8
>> + * c-basic-offset: 8
>> + * indent-tabs-mode: nil
>> + * End:
>> + */
>> diff --git a/libxkutil/network_parsing.h b/libxkutil/network_parsing.h
>> new file mode 100644
>> index 0000000..bbfe729
>> --- /dev/null
>> +++ b/libxkutil/network_parsing.h
>> @@ -0,0 +1,160 @@
>> +/*
>> + * Copyright IBM Corp. 2012
>> + *
>> + * Authors:
>> + *  Wenchao Xia <xiawenc at cn.ibm.com>
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2.1 of the License, or (at your option) any later version.
>> + */
>> +
>> +#ifndef NETWORK_PARSING_H
>> +#define NETWORK_PARSING_H
>> +
>> +#include <cmpidt.h>
>> +#include <cmpift.h>
>> +#include <cmpimacs.h>
>> +
>> +/* value defines */
>> +#define MAX_IFACE_NUM 4096
>> +
>> +#define NUM_NOT_GOT -1
>> +
>> +#define ETH_TYPE_BASE_MASK 0xff00
>> +#define ETH_TYPE_SUB_MASK 0x00ff
>> +
>> +#define CMD_DEBUG_LEVEL 2
>> +
>> +/* macro functions */
>> +#define CMD_DEBUG(lvl, fmt, args...) do { \
>> +    if (CMD_DEBUG_LEVEL && (lvl) <= CMD_DEBUG_LEVEL) { \
>> +        debug_print(fmt, ##args); \
>> +    } \
>> +} while (0)
>> +
>> +#define SAFE_MALLOC(p, size) \
>> +{ \
>> +    (p) = malloc((size)); \
>> +    if ((p) == NULL) { \
>> +        CU_DEBUG("malloc failed."); \
>> +    } \
>> +}
>> +
>> +#define SAFE_CALLOC(p, nmen, size) \
>> +{ \
>> +    (p) = calloc((nmen), (size)); \
>> +    if ((p) == NULL) { \
>> +        CU_DEBUG("calloc failed."); \
>> +    } \
>> +}
>> +
>> +#define SAFE_FREE(p) {free(p); (p) = NULL; }
>> +
>> +#define RECORD_MSG(broker, ps, rc, fmt, args...) do { \
>> +    CU_DEBUG(fmt, ##args); \
>> +    if (broker) { \
>> +        cu_statusf((broker), (ps), (rc), fmt, ##args); \
>> +    } \
>> +} while (0)
>> +
>> +typedef enum {
>> +    ETH_TYPE_NOT_GOT = 0x0000,
>> +    ETH_TYPE_ETHER_ANY = 0x0100,
>> +    ETH_TYPE_ETHER_SUB_PHYSICAL = 0x0001,
>> +    ETH_TYPE_ETHER_SUB_BRIDGE = 0x0002,
>> +    ETH_TYPE_ETHER_SUB_VLAN = 0x0004
>> +} EthType;
>> +
>> +typedef enum {
>> +    VLAN_TYPE_NOT_GOT = NUM_NOT_GOT,
>> +    VLAN_TYPE_802_1_Q = 1,
>> +    VLAN_TYPE_802_1_QBG = 2,
>> +    VLAN_TYPE_802_1_QBH = 4
>> +} VLANType;
>> +
>> +typedef enum {
>> +    BOOT_MODE_NOT_GOT = NUM_NOT_GOT,
>> +    BOOT_MODE_AUTOSTART = 1,
>> +    BOOT_MODE_NONE = 2
>> +} BootMode;
>> +
>> +struct BR_Prop {
>> +    int STP;
>> +    int delay;
>> +    char **port_names;
>> +    int port_num;
>> +} ;
>> +
>> +struct Run_Prop {
>> +    int status;
>> +    BootMode boot_mode;
>> +} ;
>> +
>> +struct VLAN_Prop_8021q {
>> +    int vlan_id;
>> +    char *parent;
>> +} ;
>> +
>> +/* HP vlan standard, TBD */
>> +struct VLAN_Prop_8021qbg {
>> +    int invalid;
>> +} ;
>> +
>> +/* Cisco and VMware vlan standard, TBD */
>> +struct VLAN_Prop_8021qbh {
>> +    int invalid;
>> +} ;
>> +
>> +struct VLAN_Prop {
>> +    int vlan_type;
>> +    union {
>> +        struct VLAN_Prop_8021q prop_8021q;
>> +        struct VLAN_Prop_8021qbg prop_8021qbg;
>> +        struct VLAN_Prop_8021qbh prop_8021qbh;
>> +    } props;
>> +} ;
>> +
>> +/* EthIface is logical devices include eth ports and bridges */
>> +struct EthIface {
>> +    char *name;
>> +    char *dep_ifname; /* parent dev name */
>> +    char *attach_bridge; /* bridge the iface is attached to */
>> +    char *mac;
>> +    EthType eth_type;
>> +    struct Run_Prop run_prop;
>> +    /* optional properties */
>> +    struct BR_Prop *pbr_prop;
>> +    struct VLAN_Prop *pvlan_prop;
>> +} ;
>> +
>> +struct EthIfacesList {
>> +    struct EthIface *pifaces[MAX_IFACE_NUM];
>> +    int count;
>> +} ;
>> +
>> +void eth_iface_init(struct EthIface *piface);
>> +void eth_iface_add_br_prop(struct EthIface *piface);
>> +void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type);
>> +void eth_iface_uninit(struct EthIface *piface);
>> +
>> +void eth_ifaceslist_init(struct EthIfacesList *plist);
>> +void eth_ifaceslist_uninit(struct EthIfacesList *plist);
>> +/* ppiface must be allocated from heap, to save code of struct duplication */
>> +int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface);
>> +/* returned pointer is direct reference to a member in plist */
>> +struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist,
>> +                                       char *name);
>> +
>> +void eth_iface_print(struct EthIface *piface);
>> +void eth_ifaceslist_print(struct EthIfacesList *plist);
>> +
>> +CMPIStatus get_host_ifaces(struct EthIfacesList *plist,
>> +                           const CMPIBroker *broker, char *prefix);
>> +
>> +const char *EthIfaceListTOXML(char **ppxml,
>> +                              struct EthIfacesList *plist,
>> +                              int dump_all_flag);
>> +
>> +#endif
>> diff --git a/libxkutil/network_parsing_test.c b/libxkutil/network_parsing_test.c
>> new file mode 100644
>> index 0000000..593bfd0
>> --- /dev/null
>> +++ b/libxkutil/network_parsing_test.c
>> @@ -0,0 +1,61 @@
>> +#include <stdio.h>
>> +#include <stdlib.h>
>> +#include <string.h>
>> +#include <pthread.h>
>> +#include <unistd.h>
>> +#include <time.h>
>> +#include <assert.h>
>> +#include <sys/time.h>
>> +#include <libvirt/libvirt.h>
>> +#include <libxml/tree.h>
>> +#include <libxml/parser.h>
>> +#include <libxml/xpath.h>
>> +
>> +#include <cmpidt.h>
>> +#include <cmpift.h>
>> +#include <cmpimacs.h>
>> +
>> +#include "misc_util.h"
>> +#include "device_parsing.h"
>> +#include "network_parsing.h"
>> +
>> +static const CMPIBroker *broker;
>> +
>> +static long print_and_ret_time_stamp(void)
>> +{
>> +    struct timeval tv;
>> +    long ret;
>> +    gettimeofday(&tv, NULL);
>> +    ret = tv.tv_sec*1000 + tv.tv_usec/1000;
>> +    CU_DEBUG("time is [%ld] ms.", ret);
>> +    return ret;
>> +}
>> +
>> +/* try retrieve all information, and then map them back to xml. */
>> +int main(int argc, char **argv)
>> +{
>> +    libvirt_cim_init();
>> +    struct EthIfacesList *plist = NULL;
>> +    const char *msg = NULL;
>> +    char *genxml = NULL;
>> +    CMPIStatus s;
>> +    long start_time, end_time;
>> +
>> +    SAFE_MALLOC(plist, sizeof(struct EthIfacesList));
>> +    eth_ifaceslist_init(plist);
>> +
>> +    start_time = print_and_ret_time_stamp();
>> +    s = get_host_ifaces(plist, broker, "kvm");
>> +    end_time = print_and_ret_time_stamp();
>> +    CU_DEBUG("cost [%d]ms in discovering host network. Result:",
>> +             end_time - start_time);
>> +    eth_ifaceslist_print(plist);
>> +
>> +    msg = EthIfaceListTOXML(&genxml, plist, 1);
>> +    CU_DEBUG("xml gen msg is %s. xml is:\n%s", msg, genxml);
>> +    SAFE_FREE(genxml);
>> +
>> +    eth_ifaceslist_uninit(plist);
>> +    SAFE_FREE(plist);
>> +    return 0;
>> +}
>> diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
>> index 9a2ada9..001246a 100644
>> --- a/libxkutil/xmlgen.c
>> +++ b/libxkutil/xmlgen.c
>> @@ -830,7 +830,7 @@ static char *features_xml(xmlNodePtr root, struct domain *domain)
>>          return NULL;
>>  }
>>
>> -static char *tree_to_xml(xmlNodePtr root)
>> +char *tree_to_xml(xmlNodePtr root)
>>  {
>>          xmlBufferPtr buffer = NULL;
>>          xmlSaveCtxtPtr savectx = NULL;
>> diff --git a/libxkutil/xmlgen.h b/libxkutil/xmlgen.h
>> index 743fc82..5d21a94 100644
>> --- a/libxkutil/xmlgen.h
>> +++ b/libxkutil/xmlgen.h
>> @@ -32,6 +32,8 @@ struct kv {
>>  	const char *val;
>>  };
>>
>> +char *tree_to_xml(xmlNodePtr root);
>> +
>>  char *system_to_xml(struct domain *dominfo);
>>  char *device_to_xml(struct virt_device *dev);
>>
>
>
> _______________________________________________
> Libvirt-cim mailing list
> Libvirt-cim at redhat.com
> https://www.redhat.com/mailman/listinfo/libvirt-cim



------------------				 
Best Regards
 
                                                                                      Wayne Xia
2012-01-27

-------------------------------------------------------------
发件人:Sharad Mishra <snmishra at linux.vnet.ibm.com>
发送日期:2012-01-27 02:37
收件人:List for discussion and development of libvirt CIM
抄送:
主题:Re: [Libvirt-cim] [PATCH v5] vlan extention - add function library
 for readonly usage

Code looks good. I have marked some nits. Take a look.
I have not yet applied the patch or done any testing. 

When do we see the actual provider? This patch is more of a
backend/infrastructure. We will also need a CIM layer.

-Sharad Mishra

On Thu, 2012-01-26 at 04:04 +0800, xiaxia347work at 163.com wrote:
> From: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
> 
>     This patch contain 1 test program and 1 c file doing xml and structure
> mapping. It expose some API to translate xml to device structure, in a similar
> way to code in device_parsing.c. Also some other files are changed to let new
> code use their internal functions. Type following Command in libxkutil
> directory:
> sudo CU_DEBUG=stdout .libs/network_parsing_test
> could see what it have done.
> 
> v5: calling libvirt API which employ netcf instead of using libnl. From git log
> these API are available since 0.9.2, and this patch is tested with libvirt
> 0.9.4.
> 
> Signed-off-by: Wenchao Xia <xiawenc at linux.vnet.ibm.com>
> ---
>  libxkutil/Makefile.am            |   12 +-
>  libxkutil/misc_util.c            |   10 +-
>  libxkutil/network_parsing.c      |  665 ++++++++++++++++++++++++++++++++++++++
>  libxkutil/network_parsing.h      |  160 +++++++++
>  libxkutil/network_parsing_test.c |   61 ++++
>  libxkutil/xmlgen.c               |    2 +-
>  libxkutil/xmlgen.h               |    2 +
>  7 files changed, 906 insertions(+), 6 deletions(-)
>  create mode 100644 libxkutil/network_parsing.c
>  create mode 100644 libxkutil/network_parsing.h
>  create mode 100644 libxkutil/network_parsing_test.c
> 
> diff --git a/libxkutil/Makefile.am b/libxkutil/Makefile.am
> index f1adc03..c0e62eb 100644
> --- a/libxkutil/Makefile.am
> +++ b/libxkutil/Makefile.am
> @@ -4,12 +4,14 @@ AM_CFLAGS = $(CFLAGS_STRICT) \
>              -DLIBVIRTCIM_CONF=\"@sysconfdir@/@PACKAGE at .conf\"
> 
>  noinst_HEADERS = cs_util.h misc_util.h device_parsing.h xmlgen.h infostore.h \
> -                 pool_parsing.h acl_parsing.h
> +                 pool_parsing.h acl_parsing.h \
> +                 network_parsing.h
> 
>  lib_LTLIBRARIES = libxkutil.la
> 
>  libxkutil_la_SOURCES = cs_util_instance.c misc_util.c device_parsing.c \
> -                       xmlgen.c infostore.c pool_parsing.c acl_parsing.c
> +                       xmlgen.c infostore.c pool_parsing.c acl_parsing.c \
> +                       network_parsing.c
>  libxkutil_la_LDFLAGS = -version-info @VERSION_INFO@
>  libxkutil_la_LIBADD = @LIBVIRT_LIBS@ \
>  		      @LIBUUID_LIBS@
> @@ -19,3 +21,9 @@ noinst_PROGRAMS = xml_parse_test
>  xml_parse_test_SOURCES = xml_parse_test.c
>  xml_parse_test_LDADD = libxkutil.la \
>  		       @LIBVIRT_LIBS@
> +
> +noinst_PROGRAMS += network_parsing_test
> +
> +network_parsing_test_SOURCES = network_parsing_test.c
> +network_parsing_test_LDADD = libxkutil.la \
> +		       @LIBVIRT_LIBS@
> diff --git a/libxkutil/misc_util.c b/libxkutil/misc_util.c
> index 61893c3..1c18c33 100644
> --- a/libxkutil/misc_util.c
> +++ b/libxkutil/misc_util.c
> @@ -152,9 +152,13 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker,
> 
>          uri = cn_to_uri(classname);
>          if (!uri) {
> -                cu_statusf(broker, s,
> -                           CMPI_RC_ERR_FAILED,
> -                           "Unable to generate URI from classname");
> +                if (broker) {
> +                        cu_statusf(broker, s,
> +                              CMPI_RC_ERR_FAILED,
> +                              "Unable to generate URI from classname");
> +                }
> +                CU_DEBUG("Unable to generate URI from classname,"
> +                         " uri is %s.", uri);
>                  return NULL;
>          }
> 
> diff --git a/libxkutil/network_parsing.c b/libxkutil/network_parsing.c
> new file mode 100644
> index 0000000..932000c
> --- /dev/null
> +++ b/libxkutil/network_parsing.c
> @@ -0,0 +1,665 @@
> +/*
> + * Copyright IBM Corp. 2012
> + *
> + * Authors:
> + *  Wenchao Xia <xiawenc at cn.ibm.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
> + */
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <stdbool.h>
> +#include <inttypes.h>
> +#include <sys/stat.h>
> +
> +#include <libvirt/libvirt.h>
> +#include <libxml/tree.h>
> +#include <libxml/parser.h>
> +#include <libxml/xpath.h>
> +#include <libcmpiutil/libcmpiutil.h>
> +
> +#include "misc_util.h"
> +#include "xmlgen.h"
> +#include "device_parsing.h"
> +#include "network_parsing.h"
> +
> +#define XML_ERROR "Failed to allocate XML memory"
> +
> +static void vlan_prop_print(struct VLAN_Prop *pvlan_prop)
> +{
> +    struct VLAN_Prop_8021q *p_8021q;
> +    CMD_DEBUG(1, "--VLAN props: type %d.\n",
> +            pvlan_prop->vlan_type);
> +    if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
> +        p_8021q = &(pvlan_prop->props.prop_8021q);
> +        CMD_DEBUG(1, "----IEEE802.1.Q: id %d, parent %s.\n",
> +                p_8021q->vlan_id, p_8021q->parent);
> +    }
> +}
> +
> +static void br_prop_print(struct BR_Prop *pbr_prop)
> +{
> +    int i = 0;
> +    CMD_DEBUG(1, "--Bridge props: stp %d, delay %d, port_num %d.\n",
> +            pbr_prop->STP, pbr_prop->delay, pbr_prop->port_num);
> +    if (pbr_prop->port_names != NULL) {
> +        CMD_DEBUG(1, "----Ports attached: ");
> +        while (i < pbr_prop->port_num) {
> +            CMD_DEBUG(1, " %s,", *(pbr_prop->port_names+i));
> +            i++;
> +        }
> +        CMD_DEBUG(1, "\n");
> +    }
> +}
> +
> +void eth_iface_print(struct EthIface *piface)
> +{
> +    CMD_DEBUG(1, "Iface device: name %s.\n"
> +        "--Main Props: parent %s, attach to %s, mac %s,"
> +        " status %d, boot_mode %d, iface type 0x%x.\n",
> +        piface->name, piface->dep_ifname, piface->attach_bridge,
> +        piface->mac,
> +        piface->run_prop.status, piface->run_prop.boot_mode, piface->eth_type);
> +    if (piface->pbr_prop != NULL) {
> +        br_prop_print(piface->pbr_prop);
> +    }
> +    if (piface->pvlan_prop != NULL) {
> +        vlan_prop_print(piface->pvlan_prop);
> +    }
> +    return;
> +}
> +
> +void eth_ifaceslist_print(struct EthIfacesList *plist)
> +{
> +    int i = 0;
> +    CMD_DEBUG(1, "Have %d ifaces in the list:\n", plist->count);
> +    while (i < plist->count) {
> +        CMD_DEBUG(1, "%04d ", i);
> +        eth_iface_print(plist->pifaces[i]);
> +        i++;
> +    }
> +}
> +
> +static void vlan_prop_init(struct VLAN_Prop *pvlan_prop, int vlan_type)
> +{
> +    struct VLAN_Prop_8021q *p_8021q;
> +    memset(pvlan_prop, 0, sizeof(struct VLAN_Prop));
> +    pvlan_prop->vlan_type = vlan_type;
> +    if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
> +        p_8021q = &(pvlan_prop->props.prop_8021q);
> +        p_8021q->vlan_id = NUM_NOT_GOT;
> +    }
> +}
> +
> +static void br_prop_init(struct BR_Prop *pbr_prop)
> +{
> +    memset(pbr_prop, 0, sizeof(struct BR_Prop));
> +    pbr_prop->STP = NUM_NOT_GOT;
> +    pbr_prop->delay = NUM_NOT_GOT;
> +    pbr_prop->port_num = NUM_NOT_GOT;
> +}
> +
> +void eth_iface_init(struct EthIface *piface)
> +{
> +    memset(piface, 0, sizeof(struct EthIface));
> +    piface->eth_type = ETH_TYPE_NOT_GOT;
> +    piface->run_prop.status = NUM_NOT_GOT;
> +    piface->run_prop.boot_mode = BOOT_MODE_NOT_GOT;
> +    return;
> +}
> +
> +void eth_iface_add_br_prop(struct EthIface *piface)
> +{
> +    if (piface->pbr_prop != NULL) {
> +        return;
> +    }
> +    SAFE_MALLOC(piface->pbr_prop, sizeof(struct BR_Prop));
> +    br_prop_init(piface->pbr_prop);
> +}
> +
> +void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type)
> +{
> +   if (piface->pvlan_prop != NULL) {
> +        return;
> +    }
> +    SAFE_MALLOC(piface->pvlan_prop, sizeof(struct VLAN_Prop));
> +    vlan_prop_init(piface->pvlan_prop, vlan_type);
> +}
> +
> +static void vlan_prop_uninit(struct VLAN_Prop *pvlan_prop)
> +{
> +    struct VLAN_Prop_8021q *p_8021q;
> +    if (pvlan_prop == NULL) {
> +        return;
> +    }
> +    if (pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q) {
> +        p_8021q = &(pvlan_prop->props.prop_8021q);
> +        SAFE_FREE(p_8021q->parent);
> +    }
> +}
> +
> +static void br_prop_uninit(struct BR_Prop *pbr_prop)
> +{
> +    int i;
> +    if (pbr_prop == NULL) {
> +        return;
> +    }
> +    i = 0;
> +    if (pbr_prop->port_names != NULL) {
> +        while (i < pbr_prop->port_num) {
> +            SAFE_FREE(pbr_prop->port_names[i]);
> +            i++;
> +        }
> +        SAFE_FREE(pbr_prop->port_names);
> +    }
> +}
> +
> +void eth_iface_uninit(struct EthIface *piface)
> +{
> +    if (piface == NULL) {
> +        return;
> +    }
> +    SAFE_FREE(piface->name);
> +    SAFE_FREE(piface->dep_ifname);
> +    SAFE_FREE(piface->attach_bridge);
> +    SAFE_FREE(piface->mac);
> +    br_prop_uninit(piface->pbr_prop);
> +    SAFE_FREE(piface->pbr_prop);
> +    vlan_prop_uninit(piface->pvlan_prop);
> +    SAFE_FREE(piface->pvlan_prop);
> +    return;
> +}
> +
> +void eth_ifaceslist_init(struct EthIfacesList *plist)
> +{
> +    plist->count = 0;
> +}
> +
> +void eth_ifaceslist_uninit(struct EthIfacesList *plist)
> +{
> +    struct EthIface **t;
> +    int i;
> +    if (plist->count <= 0) {
> +        return;
> +    }
> +    t = plist->pifaces;
> +    i = 0;
> +    while (i < plist->count) {
> +        if (*t != NULL) {
> +            eth_iface_uninit(*t);
> +            SAFE_FREE(*t);
> +        }
> +        t++;
> +        i++;
> +    }
> +    return;
> +}
> +
> +int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface)
> +{
> +    if (plist->count >= MAX_IFACE_NUM) {
> +        CU_DEBUG("too much device found.");
> +        return 0;
> +    }
> +    plist->pifaces[plist->count] = *ppiface;
> +    *ppiface = NULL;
> +    plist->count++;
> +    return 1;
> +}
> +
> +struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist,
> +                                       char *name)
> +{
> +    int i = 0;
> +    struct EthIface *piface = NULL;
> +
> +    while (i < plist->count) {
> +        piface = plist->pifaces[i];
> +        i++;
> +        if (piface != NULL) {
> +            if (0 == strcmp(piface->name, name)) {

can we do "if (strcmp(piface->name, name) == 0) { " ?
> +                return piface;
> +            }
> +        }
> +    }
> +    return NULL;
> +}
> +
> +/* Dummy function to suppress error message from libxml2 */
> +static void swallow_err_msg(void *ctx, const char *msg, ...)
> +{
> +        /* do nothing, just swallow the message. */
> +}
> +
> +
> +static const char *gen_eth_xmlnode_iface(xmlNodePtr root,
> +                                   struct EthIface *piface,
> +                                   struct EthIfacesList *plist,
> +                                   int bridge_port_flag)
> +{
> +    const char *msg = NULL;
> +    xmlNodePtr temp_node1 = NULL, temp_node2 = NULL, temp_node3 = NULL;
> +    char *str, buf[16];
> +    int i;
> +    struct EthIface *pifaceport;
> +
> +    if (piface->name == NULL) {
> +        msg = "iface have no name.\n";
> +        goto out;
> +    }
> +    /* netcfg have no xml for iface attatched to bridge */
> +    if ((piface->attach_bridge != NULL) && (bridge_port_flag != 1)) {

What are you trying to eliminate here?

> +        goto out;
> +    }
> +
> +    temp_node1 = xmlNewChild(root, NULL, BAD_CAST "interface", NULL);
> +    if (temp_node1 == NULL) {
> +        msg = XML_ERROR;
> +        goto out;
> +    }
> +    xmlNewProp(temp_node1, BAD_CAST "name", BAD_CAST piface->name);
> +    if (piface->eth_type & ETH_TYPE_ETHER_ANY) {

why do we require the above check? Can it be eliminated and just use the
checks below?

> +        if (piface->eth_type & ETH_TYPE_ETHER_SUB_BRIDGE) {
> +            str = "bridge";
> +        } else if (piface->eth_type & ETH_TYPE_ETHER_SUB_VLAN) {
> +            str = "vlan";
> +        } else {
> +            str = "ethernet";
> +        }
> +        xmlNewProp(temp_node1, BAD_CAST "type", BAD_CAST str);
> +    }
> +
> +    if ((piface->pvlan_prop != NULL) &&
> +        (piface->pvlan_prop->vlan_type == VLAN_TYPE_802_1_Q)) {
> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "vlan", NULL);
> +        snprintf(buf, sizeof(buf),
> +                 "%d", piface->pvlan_prop->props.prop_8021q.vlan_id);
> +        xmlNewProp(temp_node2, BAD_CAST "tag", BAD_CAST buf);
> +        temp_node3 = xmlNewChild(temp_node2, NULL, BAD_CAST "interface", NULL);
> +        xmlNewProp(temp_node3, BAD_CAST "name",
> +                   BAD_CAST piface->pvlan_prop->props.prop_8021q.parent);
> +    }
> +
> +    /* if it is attached to bridge, only above properties could be set */
> +    if (bridge_port_flag == 1) {
> +        goto out;
> +    }
> +
> +    if (piface->pbr_prop != NULL) {
> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "bridge", NULL);
> +        if (piface->pbr_prop->STP == 1) {
> +            snprintf(buf, sizeof(buf), "on");
> +        } else {
> +            snprintf(buf, sizeof(buf), "off");
> +        }
> +        xmlNewProp(temp_node2, BAD_CAST "stp", BAD_CAST buf);
> +        if (piface->pbr_prop->delay >= 0) {
> +            snprintf(buf, sizeof(buf), "%d", piface->pbr_prop->delay);
> +            xmlNewProp(temp_node2, BAD_CAST "delay", BAD_CAST buf);
> +        }
> +        if ((piface->pbr_prop->port_names != NULL) &&
> +            (piface->pbr_prop->port_num > 0)) {
> +            for (i = 0; i < piface->pbr_prop->port_num; i++) {
> +                pifaceport = eth_ifaceslist_search(plist,
> +                                     piface->pbr_prop->port_names[i]);
> +                if (pifaceport == NULL) {
> +                    CU_DEBUG("failed to find port %s of bridge %s in list.",
> +                             piface->pbr_prop->port_names[i], piface->name);
> +                } else {
> +                    gen_eth_xmlnode_iface(temp_node2, pifaceport, plist, 1);
> +                }
> +            }
> +        }
> +    }
> +
> +    if (piface->run_prop.boot_mode == BOOT_MODE_AUTOSTART) {
> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL);
> +        xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "onboot");
> +    } else if (piface->run_prop.boot_mode == BOOT_MODE_NONE) {
> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "start", NULL);
> +        xmlNewProp(temp_node2, BAD_CAST "mode", BAD_CAST "none");
> +    }
> +    if (piface->mac != NULL) {
> +        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "mac", NULL);
> +        xmlNewProp(temp_node2, BAD_CAST "address", BAD_CAST piface->mac);
> +    }
> +
> + out:
> +    return msg;
> +}
> +
> +static const char *gen_eth_xmlnode(xmlNodePtr root,
> +                                   struct EthIfacesList *plist)
> +{
> +    const char *msg = NULL;
> +    int i = 0;
> +    struct EthIface *piface = NULL;
> +
> +    while (i < plist->count) {
> +        piface = plist->pifaces[i];
> +        i++;
> +        msg = gen_eth_xmlnode_iface(root, piface, plist, 0);
> +        if (msg != NULL) {
> +            goto out;
> +        }
> +    }
> +
> + out:
> +    return msg;
> +}
> +
> +const char *EthIfaceListTOXML(char **ppxml,
> +                              struct EthIfacesList *plist,
> +                              int dump_all_flag)
> +{
> +    const char *msg = NULL;
> +    xmlNodePtr root = NULL;
> +
> +    root = xmlNewNode(NULL, BAD_CAST "tmp");
> +    if (root == NULL) {
> +        msg = "failed to create root node.";
> +        goto out;
> +    }
> +    msg = gen_eth_xmlnode(root, plist);
> +    if (msg == NULL) {
> +        if (dump_all_flag == 1) {
> +            *ppxml = tree_to_xml(root);
> +        } else {
> +            *ppxml = tree_to_xml(root->children);
> +        }
> +    }
> +
> + out:
> +    xmlFreeNode(root);
> +    return msg;
> +}
> +
> +static int parse_eth_xmlnode(struct EthIfacesList *plist, xmlNode *inode,
> +                             int status, char *attached)
> +{
> +    struct EthIface *piface = NULL;
> +    xmlNode *child1 = NULL, *child2 = NULL;
> +    char *temp = NULL, **ppchar;
> +
> +    SAFE_MALLOC(piface, sizeof(struct EthIface));
> +    eth_iface_init(piface);
> +
> +    piface->name = get_attr_value(inode, "name");
> +    piface->run_prop.status = status;
> +    if (attached != NULL) {
> +        piface->attach_bridge = strdup(attached);
> +    }
> +    temp = get_attr_value(inode, "type");
> +    if (temp != NULL) {
> +        if (0 == strcmp(temp, "ethernet")) {

can you change to if(strcmp() == 0)

> +            piface->eth_type = ETH_TYPE_ETHER_ANY;
> +        }
> +        if (0 == strcmp(temp, "bridge")) {
> +            piface->eth_type = ETH_TYPE_ETHER_ANY | ETH_TYPE_ETHER_SUB_BRIDGE;
> +        }
> +        if (0 == strcmp(temp, "vlan")) {
> +            piface->eth_type = ETH_TYPE_ETHER_ANY | ETH_TYPE_ETHER_SUB_VLAN;
> +        }
> +        SAFE_FREE(temp);
> +    }
> +
> +    for (child1 = inode->children; child1 != NULL; child1 = child1->next) {
> +        if (XSTREQ(child1->name, "start")) {
> +            temp = get_attr_value(child1, "mode");
> +            if (0 == strcmp(temp, "onboot")) {

change as above

> +                piface->run_prop.boot_mode = BOOT_MODE_AUTOSTART;
> +            }
> +            if (0 == strcmp(temp, "none")) {
> +                piface->run_prop.boot_mode = BOOT_MODE_NONE;
> +            }
> +            SAFE_FREE(temp);
> +        }
> +        if (XSTREQ(child1->name, "mac")) {
> +            piface->mac = get_attr_value(child1, "address");
> +        }
> +        if (XSTREQ(child1->name, "bridge")) {
> +            eth_iface_add_br_prop(piface);
> +            temp = get_attr_value(child1, "stp");
> +            if (0 == strcmp(temp, "on")) {
> +                piface->pbr_prop->STP = 1;
> +            }
> +            if (0 == strcmp(temp, "off")) {
> +                piface->pbr_prop->STP = 0;
> +            }
> +            SAFE_FREE(temp);
> +            temp = get_attr_value(child1, "delay");
> +            piface->pbr_prop->delay = strtol(temp, NULL, 10);
> +            SAFE_FREE(temp);
> +        }
> +        if (XSTREQ(child1->name, "bridge")) {
> +            eth_iface_add_br_prop(piface);
> +            temp = get_attr_value(child1, "stp");
> +            if (0 == strcmp(temp, "on")) {
> +                piface->pbr_prop->STP = 1;
> +            }
> +            if (0 == strcmp(temp, "off")) {
> +                piface->pbr_prop->STP = 0;
> +            }
> +            SAFE_FREE(temp);
> +            temp = get_attr_value(child1, "delay");
> +            piface->pbr_prop->delay = strtol(temp, NULL, 10);
> +            SAFE_FREE(temp);
> +            for (child2 = child1->children; child2 != NULL;
> +                                            child2 = child2->next) {
> +                if (XSTREQ(child2->name, "interface")) {
> +                    if (piface->pbr_prop->port_names == NULL) {
> +                        SAFE_CALLOC(piface->pbr_prop->port_names,
> +                                    MAX_IFACE_NUM, sizeof(char *));
> +                        piface->pbr_prop->port_num = 0;
> +                    }
> +                    ppchar = piface->pbr_prop->port_names +
> +                             (piface->pbr_prop->port_num)++;
> +                    *ppchar = get_attr_value(child2, "name");
> +                    parse_eth_xmlnode(plist, child2, status, piface->name);
> +                }
> +            }
> +        }
> +        if (XSTREQ(child1->name, "vlan")) {
> +            eth_iface_add_vlan_prop(piface, VLAN_TYPE_802_1_Q);
> +            temp = get_attr_value(child1, "tag");
> +            piface->pvlan_prop->props.prop_8021q.vlan_id =
> +                                       strtol(temp, NULL, 10);
> +            SAFE_FREE(temp);
> +            for (child2 = child1->children; child2 != NULL;
> +                                            child2 = child2->next) {
> +                if (XSTREQ(child2->name, "interface")) {
> +                    piface->pvlan_prop->props.prop_8021q.parent =
> +                                      get_attr_value(child2, "name");
> +                    piface->dep_ifname =
> +                                      get_attr_value(child2, "name");
> +                }
> +            }
> +        }
> +    }
> +
> +    eth_ifaceslist_add(plist, &piface);
> +    return 1;
> +}
> +
> +static const char *XMLToEthIfaceList(struct EthIfacesList *plist,
> +                                     const char *xml,
> +                                     int status)
> +{
> +    xmlDoc *xmldoc;
> +    xmlXPathContext *xpathCtx;
> +    xmlXPathObject *xpathObj;
> +    xmlChar *xpathstr;
> +    xmlNode **dev_nodes = NULL;
> +    xmlNodeSet *nsv = NULL;
> +    int count = 0;
> +    int len, devidx;
> +    const char *msg = NULL;
> +
> +    len = strlen(xml) + 1;
> +    xpathstr = (xmlChar *)"/interface";
> +
> +    xmlSetGenericErrorFunc(NULL, swallow_err_msg);
> +    if ((xmldoc = xmlParseMemory(xml, len)) == NULL) {
> +        msg = "failed to get xmldoc.";
> +        goto err1;
> +    }
> +
> +    if ((xpathCtx = xmlXPathNewContext(xmldoc)) == NULL) {
> +        msg = "failed to get pathCtx";
> +        goto err2;
> +    }
> +
> +    if ((xpathObj = xmlXPathEvalExpression(xpathstr, xpathCtx))
> +                == NULL) {
> +        msg = "failed to get xpathObj";
> +        goto err3;
> +    }
> +
> +    nsv = xpathObj->nodesetval;
> +    if (nsv == NULL) {
> +        msg = "failed to get nodesetval.";
> +        goto out;
> +    }
> +
> +    dev_nodes = nsv->nodeTab;
> +    count = nsv->nodeNr;
> +
> +    if (count <= 0) {
> +        msg = "nodesetval have less that 1 values.";
> +        goto out;
> +    }
> +
> +    for (devidx = 0; devidx < count; devidx++) {
> +        parse_eth_xmlnode(plist, dev_nodes[devidx], status, NULL);
> +    }
> +
> + out:
> +    xmlSetGenericErrorFunc(NULL, NULL);
> +    xmlXPathFreeObject(xpathObj);
> +
> + err3:
> +    xmlXPathFreeContext(xpathCtx);
> + err2:
> +    xmlFreeDoc(xmldoc);
> + err1:
> +    return msg;
> +}
> +
> +CMPIStatus get_host_ifaces(struct EthIfacesList *plist,
> +                           const CMPIBroker *broker, char *prefix)
> +{
> +    virConnectPtr conn = NULL;
> +    virInterfacePtr iface;
> +    CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
> +    int num, listnum, i;
> +    char **names = NULL;
> +    char *dump = NULL;
> +    int flags = 0;
> +    const char *msg;
> +
> +    conn = connect_by_classname(broker, prefix, &s);
> +    if (conn == NULL) {
> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED, "connect failed.");
> +        goto out;
> +    }
> +
> +    /* list defined interfaces*/
> +    num = virConnectNumOfDefinedInterfaces(conn);
> +    if (num < 0) {
> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
> +                   "failed to find number of defined interfaces.");
> +        goto out;
> +    }
> +    names = malloc(num * sizeof(char *));
> +    listnum = virConnectListDefinedInterfaces(conn, names, num);
> +    if (listnum < 0) {
> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
> +                   "failed to list names of defined interfaces.");
> +        goto out;
> +    }
> +    CU_DEBUG("%d defined ifaces found from libvirt API.\n", listnum);
> +
> +    flags |= VIR_INTERFACE_XML_INACTIVE;
> +    for (i = 0; i < listnum; i++) {
> +        iface = virInterfaceLookupByName(conn, names[i]);
> +        if (!iface) {
> +            CU_DEBUG("failed to look up %s.\n", names[i]);
> +            SAFE_FREE(names[i]);
> +            continue;
> +        }
> +        SAFE_FREE(names[i]);
> +        dump = virInterfaceGetXMLDesc(iface, flags);
> +        CU_DEBUG("defined interface %d xml:\n%s", i, dump);
> +        msg = XMLToEthIfaceList(plist, dump, 0);
> +        if (msg != NULL) {
> +            CU_DEBUG("failed parsing eth xml, msg is: %s.", msg);
> +        }
> +        SAFE_FREE(dump);
> +        virInterfaceFree(iface);
> +    }
> +    SAFE_FREE(names);
> +
> +    /* list active interfaces*/
> +    num = virConnectNumOfInterfaces(conn);
> +    if (num < 0) {
> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
> +                   "failed to find number of active interfaces.");
> +        goto out;
> +    }
> +    names = malloc(num * sizeof(char *));
> +
> +    listnum = virConnectListInterfaces(conn, names, num);
> +    if (listnum < 0) {
> +        RECORD_MSG(broker, &s, CMPI_RC_ERR_FAILED,
> +                   "failed to list names of active interfacess.");
> +        goto out;
> +    }
> +    CU_DEBUG("%d active ifaces found from libvirt API.\n", listnum);
> +
> +    flags |= VIR_INTERFACE_XML_INACTIVE;
> +    for (i = 0; i < listnum; i++) {
> +        iface = virInterfaceLookupByName(conn, names[i]);
> +        if (!iface) {
> +            CU_DEBUG("failed to look up %s.\n", names[i]);
> +            SAFE_FREE(names[i]);
> +            continue;
> +        }
> +        SAFE_FREE(names[i]);
> +        dump = virInterfaceGetXMLDesc(iface, flags);
> +        CU_DEBUG("active interface %d xml:\n%s", i, dump);
> +        msg = XMLToEthIfaceList(plist, dump, 1);
> +        if (msg != NULL) {
> +            CU_DEBUG("failed parsing eth xml, msg is: %s.", msg);
> +        }
> +        SAFE_FREE(dump);
> +        virInterfaceFree(iface);
> +    }
> +    s.rc = CMPI_RC_OK;
> +
> + out:
> +    virConnectClose(conn);
> +    SAFE_FREE(names);
> +    return s;
> +}
> +/*
> + * Local Variables:
> + * mode: C
> + * c-set-style: "K&R"
> + * tab-width: 8
> + * c-basic-offset: 8
> + * indent-tabs-mode: nil
> + * End:
> + */
> diff --git a/libxkutil/network_parsing.h b/libxkutil/network_parsing.h
> new file mode 100644
> index 0000000..bbfe729
> --- /dev/null
> +++ b/libxkutil/network_parsing.h
> @@ -0,0 +1,160 @@
> +/*
> + * Copyright IBM Corp. 2012
> + *
> + * Authors:
> + *  Wenchao Xia <xiawenc at cn.ibm.com>
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public
> + * License as published by the Free Software Foundation; either
> + * version 2.1 of the License, or (at your option) any later version.
> + */
> +
> +#ifndef NETWORK_PARSING_H
> +#define NETWORK_PARSING_H
> +
> +#include <cmpidt.h>
> +#include <cmpift.h>
> +#include <cmpimacs.h>
> +
> +/* value defines */
> +#define MAX_IFACE_NUM 4096
> +
> +#define NUM_NOT_GOT -1
> +
> +#define ETH_TYPE_BASE_MASK 0xff00
> +#define ETH_TYPE_SUB_MASK 0x00ff
> +
> +#define CMD_DEBUG_LEVEL 2
> +
> +/* macro functions */
> +#define CMD_DEBUG(lvl, fmt, args...) do { \
> +    if (CMD_DEBUG_LEVEL && (lvl) <= CMD_DEBUG_LEVEL) { \
> +        debug_print(fmt, ##args); \
> +    } \
> +} while (0)
> +
> +#define SAFE_MALLOC(p, size) \
> +{ \
> +    (p) = malloc((size)); \
> +    if ((p) == NULL) { \
> +        CU_DEBUG("malloc failed."); \
> +    } \
> +}
> +
> +#define SAFE_CALLOC(p, nmen, size) \
> +{ \
> +    (p) = calloc((nmen), (size)); \
> +    if ((p) == NULL) { \
> +        CU_DEBUG("calloc failed."); \
> +    } \
> +}
> +
> +#define SAFE_FREE(p) {free(p); (p) = NULL; }
> +
> +#define RECORD_MSG(broker, ps, rc, fmt, args...) do { \
> +    CU_DEBUG(fmt, ##args); \
> +    if (broker) { \
> +        cu_statusf((broker), (ps), (rc), fmt, ##args); \
> +    } \
> +} while (0)
> +
> +typedef enum {
> +    ETH_TYPE_NOT_GOT = 0x0000,
> +    ETH_TYPE_ETHER_ANY = 0x0100,
> +    ETH_TYPE_ETHER_SUB_PHYSICAL = 0x0001,
> +    ETH_TYPE_ETHER_SUB_BRIDGE = 0x0002,
> +    ETH_TYPE_ETHER_SUB_VLAN = 0x0004
> +} EthType;
> +
> +typedef enum {
> +    VLAN_TYPE_NOT_GOT = NUM_NOT_GOT,
> +    VLAN_TYPE_802_1_Q = 1,
> +    VLAN_TYPE_802_1_QBG = 2,
> +    VLAN_TYPE_802_1_QBH = 4
> +} VLANType;
> +
> +typedef enum {
> +    BOOT_MODE_NOT_GOT = NUM_NOT_GOT,
> +    BOOT_MODE_AUTOSTART = 1,
> +    BOOT_MODE_NONE = 2
> +} BootMode;
> +
> +struct BR_Prop {
> +    int STP;
> +    int delay;
> +    char **port_names;
> +    int port_num;
> +} ;
> +
> +struct Run_Prop {
> +    int status;
> +    BootMode boot_mode;
> +} ;
> +
> +struct VLAN_Prop_8021q {
> +    int vlan_id;
> +    char *parent;
> +} ;
> +
> +/* HP vlan standard, TBD */
> +struct VLAN_Prop_8021qbg {
> +    int invalid;
> +} ;
> +
> +/* Cisco and VMware vlan standard, TBD */
> +struct VLAN_Prop_8021qbh {
> +    int invalid;
> +} ;
> +
> +struct VLAN_Prop {
> +    int vlan_type;
> +    union {
> +        struct VLAN_Prop_8021q prop_8021q;
> +        struct VLAN_Prop_8021qbg prop_8021qbg;
> +        struct VLAN_Prop_8021qbh prop_8021qbh;
> +    } props;
> +} ;
> +
> +/* EthIface is logical devices include eth ports and bridges */
> +struct EthIface {
> +    char *name;
> +    char *dep_ifname; /* parent dev name */
> +    char *attach_bridge; /* bridge the iface is attached to */
> +    char *mac;
> +    EthType eth_type;
> +    struct Run_Prop run_prop;
> +    /* optional properties */
> +    struct BR_Prop *pbr_prop;
> +    struct VLAN_Prop *pvlan_prop;
> +} ;
> +
> +struct EthIfacesList {
> +    struct EthIface *pifaces[MAX_IFACE_NUM];
> +    int count;
> +} ;
> +
> +void eth_iface_init(struct EthIface *piface);
> +void eth_iface_add_br_prop(struct EthIface *piface);
> +void eth_iface_add_vlan_prop(struct EthIface *piface, int vlan_type);
> +void eth_iface_uninit(struct EthIface *piface);
> +
> +void eth_ifaceslist_init(struct EthIfacesList *plist);
> +void eth_ifaceslist_uninit(struct EthIfacesList *plist);
> +/* ppiface must be allocated from heap, to save code of struct duplication */
> +int eth_ifaceslist_add(struct EthIfacesList *plist, struct EthIface **ppiface);
> +/* returned pointer is direct reference to a member in plist */
> +struct EthIface *eth_ifaceslist_search(struct EthIfacesList *plist,
> +                                       char *name);
> +
> +void eth_iface_print(struct EthIface *piface);
> +void eth_ifaceslist_print(struct EthIfacesList *plist);
> +
> +CMPIStatus get_host_ifaces(struct EthIfacesList *plist,
> +                           const CMPIBroker *broker, char *prefix);
> +
> +const char *EthIfaceListTOXML(char **ppxml,
> +                              struct EthIfacesList *plist,
> +                              int dump_all_flag);
> +
> +#endif
> diff --git a/libxkutil/network_parsing_test.c b/libxkutil/network_parsing_test.c
> new file mode 100644
> index 0000000..593bfd0
> --- /dev/null
> +++ b/libxkutil/network_parsing_test.c
> @@ -0,0 +1,61 @@
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <pthread.h>
> +#include <unistd.h>
> +#include <time.h>
> +#include <assert.h>
> +#include <sys/time.h>
> +#include <libvirt/libvirt.h>
> +#include <libxml/tree.h>
> +#include <libxml/parser.h>
> +#include <libxml/xpath.h>
> +
> +#include <cmpidt.h>
> +#include <cmpift.h>
> +#include <cmpimacs.h>
> +
> +#include "misc_util.h"
> +#include "device_parsing.h"
> +#include "network_parsing.h"
> +
> +static const CMPIBroker *broker;
> +
> +static long print_and_ret_time_stamp(void)
> +{
> +    struct timeval tv;
> +    long ret;
> +    gettimeofday(&tv, NULL);
> +    ret = tv.tv_sec*1000 + tv.tv_usec/1000;
> +    CU_DEBUG("time is [%ld] ms.", ret);
> +    return ret;
> +}
> +
> +/* try retrieve all information, and then map them back to xml. */
> +int main(int argc, char **argv)
> +{
> +    libvirt_cim_init();
> +    struct EthIfacesList *plist = NULL;
> +    const char *msg = NULL;
> +    char *genxml = NULL;
> +    CMPIStatus s;
> +    long start_time, end_time;
> +
> +    SAFE_MALLOC(plist, sizeof(struct EthIfacesList));
> +    eth_ifaceslist_init(plist);
> +
> +    start_time = print_and_ret_time_stamp();
> +    s = get_host_ifaces(plist, broker, "kvm");
> +    end_time = print_and_ret_time_stamp();
> +    CU_DEBUG("cost [%d]ms in discovering host network. Result:",
> +             end_time - start_time);
> +    eth_ifaceslist_print(plist);
> +
> +    msg = EthIfaceListTOXML(&genxml, plist, 1);
> +    CU_DEBUG("xml gen msg is %s. xml is:\n%s", msg, genxml);
> +    SAFE_FREE(genxml);
> +
> +    eth_ifaceslist_uninit(plist);
> +    SAFE_FREE(plist);
> +    return 0;
> +}
> diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
> index 9a2ada9..001246a 100644
> --- a/libxkutil/xmlgen.c
> +++ b/libxkutil/xmlgen.c
> @@ -830,7 +830,7 @@ static char *features_xml(xmlNodePtr root, struct domain *domain)
>          return NULL;
>  }
> 
> -static char *tree_to_xml(xmlNodePtr root)
> +char *tree_to_xml(xmlNodePtr root)
>  {
>          xmlBufferPtr buffer = NULL;
>          xmlSaveCtxtPtr savectx = NULL;
> diff --git a/libxkutil/xmlgen.h b/libxkutil/xmlgen.h
> index 743fc82..5d21a94 100644
> --- a/libxkutil/xmlgen.h
> +++ b/libxkutil/xmlgen.h
> @@ -32,6 +32,8 @@ struct kv {
>  	const char *val;
>  };
> 
> +char *tree_to_xml(xmlNodePtr root);
> +
>  char *system_to_xml(struct domain *dominfo);
>  char *device_to_xml(struct virt_device *dev);
> 


_______________________________________________
Libvirt-cim mailing list
Libvirt-cim at redhat.com
https://www.redhat.com/mailman/listinfo/libvirt-cim






More information about the Libvirt-cim mailing list