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(a)163.com wrote:
> From: Wenchao Xia <xiawenc(a)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(a)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@.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(a)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(a)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(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvirt-cim
------------------
Best Regards
Wayne Xia
2012-01-27
-------------------------------------------------------------
发件人:Sharad Mishra <snmishra(a)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(a)163.com wrote:
From: Wenchao Xia <xiawenc(a)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(a)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@.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(a)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(a)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(a)redhat.com
https://www.redhat.com/mailman/listinfo/libvirt-cim