CIM
  Threads by month 
                
            - ----- 2025 -----
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2024 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2023 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2022 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2021 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2020 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2019 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2018 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2017 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2016 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2015 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2014 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2013 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2012 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2011 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2010 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2009 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2008 -----
 - December
 - November
 - October
 - September
 - August
 - July
 - June
 - May
 - April
 - March
 - February
 - January
 - ----- 2007 -----
 - December
 - November
 - October
 
January 2012
- 7 participants
 - 48 discussions
 
31 Jan '12
                    
                        From: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
    This patch add EthernetPort. EthernetPort is always a port on a switch,
So eth0.10 is modeled as VS_eth0/EP_eth0.10,
eth0 is modeled as VS_eth0/EP_Eth0.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
 schema/EthernetPort.mof          |    4 +
 schema/EthernetPort.registration |    3 +
 src/Virt_EthernetPort.c          |  561 ++++++++++++++++++++++++++++++++++++++
 src/Virt_EthernetPort.h          |   58 ++++
 4 files changed, 626 insertions(+), 0 deletions(-)
 create mode 100644 schema/EthernetPort.mof
 create mode 100644 schema/EthernetPort.registration
 create mode 100644 src/Virt_EthernetPort.c
 create mode 100644 src/Virt_EthernetPort.h
diff --git a/schema/EthernetPort.mof b/schema/EthernetPort.mof
new file mode 100644
index 0000000..9d5e23e
--- /dev/null
+++ b/schema/EthernetPort.mof
@@ -0,0 +1,4 @@
+// Copyright IBM Corp. 2012
+class Net_EthernetPort : CIM_EthernetPort
+{
+};
diff --git a/schema/EthernetPort.registration b/schema/EthernetPort.registration
new file mode 100644
index 0000000..e0e0f0c
--- /dev/null
+++ b/schema/EthernetPort.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2012
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Net_EthernetPort root/virt Virt_EthernetPort Virt_EthernetPort instance
diff --git a/src/Virt_EthernetPort.c b/src/Virt_EthernetPort.c
new file mode 100644
index 0000000..cdef910
--- /dev/null
+++ b/src/Virt_EthernetPort.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright IBM Corp. 2007
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/stat.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "misc_util.h"
+#include "cs_util.h"
+#include "device_parsing.h"
+#include "network_model_helper.h"
+
+#include "Virt_EthernetPort.h"
+
+static const CMPIBroker *_BROKER;
+
+static int set_primary_for_ep(const CMPIBroker *broker, const char* prefix,
+                           struct EthIface *piface, CMPIInstance *instance)
+{
+        char *eth_name, *ep_name;
+        const char *syscls_name = "Virt_VirtualEthernetSwitchSystem";
+        int asret;
+
+        if (piface->name == NULL) {
+            return 0;
+        }
+
+        eth_name = get_ethport_name_from_iface(piface->name);
+        asret = asprintf(&ep_name, "%s/%s", prefix, eth_name);
+
+        CMSetProperty(instance, "DeviceID",
+                      (CMPIValue *)ep_name, CMPI_chars);
+
+        CMSetProperty(instance, "InstanceID",
+                      (CMPIValue *)ep_name, CMPI_chars);
+
+        CMSetProperty(instance, "ElementName",
+                      (CMPIValue *)eth_name, CMPI_chars);
+        CU_FREE(ep_name);
+        CU_FREE(eth_name);
+
+        CMSetProperty(instance, "SystemCreationClassName",
+                      (CMPIValue *)syscls_name, CMPI_chars);
+
+        CMSetProperty(instance, "SystemName",
+                      (CMPIValue *)prefix, CMPI_chars);
+
+        return 1;
+}
+
+static int set_secondary_for_ep(const CMPIBroker *broker,
+                          struct EthIface *piface, CMPIInstance *instance)
+{
+        int state;
+        uint16_t cim_type;
+        CMPIArray *array;
+        CMPIStatus s;
+        CMPIString *str;
+
+        if (piface->run_prop.status == ETH_STATE_INACTIVE) {
+                state = CIM_STATE_DISABLED;
+        } else if (piface->run_prop.status == ETH_STATE_ACTIVE) {
+                state = CIM_STATE_ENABLED;
+        } else {
+                state = CIM_STATE_UNKNOWN;
+        }
+        CMSetProperty(instance, "EnabledState",
+                      (CMPIValue *)&state, CMPI_uint16);
+        CMSetProperty(instance, "RequestedState",
+                      (CMPIValue *)&state, CMPI_uint16);
+
+        cim_type = CIM_NUM_NET_ETHERNET;
+        CMSetProperty(instance, "LinkTechnology",
+                      (CMPIValue *)&cim_type, CMPI_uint16);
+
+        if (piface->mac != NULL) {
+                array = CMNewArray(broker, 1, CMPI_string, &s);
+                if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) {
+                        CU_DEBUG("failed to create array.");
+                        return 0;
+                }
+                str = CMNewString(broker, piface->mac, &s);
+                if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(str))) {
+                        CU_DEBUG("failed to create array.");
+                        return 0;
+                }
+
+                CMSetArrayElementAt(array, 0, &str, CMPI_string);
+
+                CMSetProperty(instance, "NetworkAddresses",
+                              (CMPIValue *)&array, CMPI_stringA);
+        }
+
+        return 1;
+}
+
+static CMPIStatus set_properties(const CMPIBroker *broker,
+                                 struct EthIface *piface,
+                                 const char *prefix,
+                                 CMPIInstance *instance)
+{
+        CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
+        char *errstr = NULL;
+
+        if (!set_primary_for_ep(broker, prefix, piface, instance)) {
+                errstr = "failed to set primary properties for instance.";
+                CU_DEBUG("%s, iface name %s.", errstr, piface->name);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+                goto out;
+         }
+
+        if (!set_secondary_for_ep(broker, piface, instance)) {
+                errstr = "failed to set secondary properties for instance.";
+                CU_DEBUG("%s, iface name %s.", errstr, piface->name);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+                goto out;
+        }
+
+        cu_statusf(broker, &s,
+                   CMPI_RC_OK,
+                   "");
+
+ out:
+        return s;
+}
+
+
+static CMPIStatus instance_from_ep_build(const CMPIBroker *broker,
+                                         struct EthIface *piface,
+                                         const char *prefix,
+                                         const CMPIObjectPath *reference,
+                                         const char **properties,
+                                         CMPIInstance **_inst)
+{
+        CMPIInstance *inst = NULL;
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        const char *keys[] = {"InstanceID", NULL};
+
+        inst = get_typed_instance(broker,
+                                  NETWORK_CLASS_PREFIX,
+                                  "EthernetPort",
+                                  NAMESPACE(reference));
+        if (inst == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Unable to init ep instance");
+                goto out;
+        }
+
+        s = CMSetPropertyFilter(inst, properties, keys);
+        if (s.rc != CMPI_RC_OK) {
+                CU_DEBUG("Unable to set property filter: %d", s.rc);
+        }
+
+        s = set_properties(broker,
+                           piface,
+                           prefix,
+                           inst);
+
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        *_inst = inst;
+
+ out:
+        return s;
+}
+
+
+static CMPIStatus instance_from_ep(const CMPIBroker *broker,
+                                   struct EthIface *piface,
+                                   const char *vsname,
+                                   const CMPIObjectPath *reference,
+                                   const char **properties,
+                                   struct inst_list *plist)
+{
+
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+        char *br1_name = NULL, *br2_name = NULL;
+
+        get_possible_bridge_name_for_cim_model(piface, &br1_name, &br2_name);
+        if (br1_name == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "failed to find any bridge for the port.");
+                CU_DEBUG("failed to find any bridge for the port %s.",
+                          piface->name);
+                goto out;
+        }
+
+        /* building up the instance */
+        if ((vsname == NULL) || (0 == strcmp(vsname, br1_name))) {
+                inst = NULL;
+                s = instance_from_ep_build(broker,
+                                           piface,
+                                           br1_name,
+                                           reference,
+                                           properties,
+                                           &inst);
+                if (s.rc != CMPI_RC_OK) {
+                        goto out;
+                }
+                inst_list_add(plist, inst);
+        }
+
+        /* following is to make it comform to CIM profile which require two
+        ethports connectted to pNIC and vswitch, but we have only one piface
+        on linux indicating it is connected to pNIC and bridge at sametime */
+        if (br2_name == NULL) {
+                goto out;
+        }
+
+        if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) {
+                inst = NULL;
+                s = instance_from_ep_build(broker,
+                                           piface,
+                                           br2_name,
+                                           reference,
+                                           properties,
+                                           &inst);
+                if (s.rc != CMPI_RC_OK) {
+                        goto out;
+                }
+                inst_list_add(plist, inst);
+        }
+
+
+ out:
+        CU_FREE(br1_name);
+        CU_FREE(br2_name);
+        return s;
+}
+
+CMPIStatus get_ep_by_name(const CMPIBroker *broker,
+                            const char *prefix,
+                            const char *name,
+                            const CMPIObjectPath *reference,
+                            const char **properties,
+                            CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+        char *eth_name = NULL;
+        char *dest = NULL;
+        char *errstr;
+        int ret;
+        struct EthIfacesList ifaces_list;
+        struct inst_list list;
+
+        eth_ifaceslist_init(&ifaces_list);
+        inst_list_init(&list);
+
+        eth_name = get_iface_name_from_ethport(name);
+        if (eth_name == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "failed to convert instance name");
+                CU_DEBUG("ethport name %s failed to convert.", name);
+                goto out;
+        }
+
+        ret = get_host_ifaces(&ifaces_list,
+                            eth_iface_filter_cim_ethport_for_name, eth_name);
+
+        if (ret != 1) {
+            errstr = get_host_iface_error_reason(ret);
+            CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+        if (ifaces_list.count != 1) {
+            errstr = "expected ethport not found.";
+            CU_DEBUG("%s\n", errstr);
+            eth_ifaceslist_print(&ifaces_list);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+
+        inst = NULL;
+        s = instance_from_ep(broker,
+                             ifaces_list.pifaces[0],
+                             prefix,
+                             reference,
+                             properties,
+                             &list);
+
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        if (list.cur == 0) {
+                CU_DEBUG("%d instance found, expect is 1.", list.cur);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       "no such instance.");
+                goto out;
+        }
+
+        if (list.cur > 1) {
+                CU_DEBUG("%d instance found, expect is 1.", list.cur);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       "instance found do not match expectation");
+                goto out;
+        }
+
+        *_inst = list.list[0];
+        list.list[0] = NULL;
+
+ out:
+        eth_ifaceslist_uninit(&ifaces_list);
+        inst_list_free(&list);
+        CU_FREE(eth_name);
+        CU_FREE(dest);
+        return s;
+}
+
+CMPIStatus get_ep_by_id(const CMPIBroker *broker,
+                            const char *id,
+                            const CMPIObjectPath *reference,
+                            const char **properties,
+                            CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        char *prefix = NULL;
+        char *suffix = NULL;
+        if (id == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_INVALID_PARAMETER,
+                           "ID is NULL'", id);
+        }
+        if (!parse_fq_devid(id, &prefix, &suffix) || (prefix == NULL) ||
+                                                   (suffix == NULL)) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_INVALID_PARAMETER,
+                           "Invalid InstanceID `%s'", id);
+                goto out;
+        }
+        s = get_ep_by_name(broker, prefix, suffix, reference,
+                             properties, _inst);
+
+ out:
+        CU_FREE(prefix);
+        CU_FREE(suffix);
+        return s;
+}
+
+CMPIStatus get_ep_by_ref(const CMPIBroker *broker,
+                           const CMPIObjectPath *reference,
+                           const char **properties,
+                           CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+        char *name = NULL;
+        char *prefix = NULL;
+        const char *id;
+
+        if (cu_get_str_path(reference, "DeviceID", &id) != CMPI_RC_OK) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_NOT_FOUND,
+                           "No such instance (InstanceID)");
+                goto out;
+        }
+        if ((!parse_fq_devid(id, &prefix, &name)) ||
+                (name == NULL) || (prefix == NULL)) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_NOT_FOUND,
+                           "Failed to translate (InstanceID)");
+                goto out;
+        }
+
+        s = get_ep_by_name(broker, prefix, name, reference,
+                                properties, &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        s = cu_validate_ref(broker, reference, inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        *_inst = inst;
+
+ out:
+        free(name);
+        free(prefix);
+
+        return s;
+}
+
+
+CMPIStatus enum_eps(const CMPIBroker *broker,
+                      const char *ref_vsname,
+                      const CMPIObjectPath *reference,
+                      const char **properties,
+                      struct inst_list *plist)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        struct EthIfacesList ifaces_list;
+        int ret, i;
+        char *errstr;
+
+        eth_ifaceslist_init(&ifaces_list);
+
+        ret = get_host_ifaces(&ifaces_list,
+                                eth_iface_filter_cim_ethport, NULL);
+        if (ret != 1) {
+            errstr = get_host_iface_error_reason(ret);
+            CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+        CU_DEBUG("enum ep, found following devices.")
+        eth_ifaceslist_print(&ifaces_list);
+
+        i = 0;
+        while (i < ifaces_list.count) {
+                s = instance_from_ep(broker,
+                                       ifaces_list.pifaces[i],
+                                       ref_vsname,
+                                      reference,
+                                       properties,
+                                       plist);
+                i++;
+                /* this should never fail */
+                if (s.rc != CMPI_RC_OK) {
+                        CU_DEBUG("unexpected fail.");
+                        break;
+                }
+        }
+
+
+ out:
+        eth_ifaceslist_uninit(&ifaces_list);
+
+        return s;
+}
+
+static CMPIStatus return_enum_eps(const CMPIBroker *broker,
+                             const CMPIObjectPath *reference,
+                             const CMPIResult *results,
+                             const char **properties,
+                             const bool names_only)
+{
+        struct inst_list list;
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        inst_list_init(&list);
+        s = enum_eps(broker, NULL, reference, properties, &list);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        if (names_only) {
+                cu_return_instance_names(results, &list);
+        } else {
+                cu_return_instances(results, &list);
+        }
+
+ out:
+        inst_list_free(&list);
+        return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+                                    const CMPIContext *context,
+                                    const CMPIResult *results,
+                                    const CMPIObjectPath *reference)
+{
+        return return_enum_eps(_BROKER, reference, results, NULL, true);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+                                const CMPIContext *context,
+                                const CMPIResult *results,
+                                const CMPIObjectPath *reference,
+                                const char **properties)
+{
+
+        return return_enum_eps(_BROKER, reference, results, properties, false);
+}
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+                              const CMPIContext *context,
+                              const CMPIResult *results,
+                              const CMPIObjectPath *ref,
+                              const char **properties)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+
+        s = get_ep_by_ref(_BROKER, ref, properties, &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        CMReturnInstance(results, inst);
+
+ out:
+        return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_INST_CLEANUP();
+DEFAULT_EQ();
+
+STD_InstanceMIStub(,
+                   Virt_EthernetPort,
+                   _BROKER,
+                   libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_EthernetPort.h b/src/Virt_EthernetPort.h
new file mode 100644
index 0000000..f474af2
--- /dev/null
+++ b/src/Virt_EthernetPort.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wencao 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
+ */
+#ifndef __VIRT_ETHERNETPORT_H
+#define __VIRT_ETHERNETPORT_H
+
+CMPIStatus enum_eps(const CMPIBroker *broker,
+                      const char *ref_vsname,
+                      const CMPIObjectPath *reference,
+                      const char **properties,
+                      struct inst_list *plist);
+
+CMPIStatus get_ep_by_name(const CMPIBroker *broker,
+                            const char *prefix,
+                            const char *name,
+                            const CMPIObjectPath *reference,
+                            const char **properties,
+                            CMPIInstance **_inst);
+
+CMPIStatus get_ep_by_id(const CMPIBroker *broker,
+                            const char *id,
+                            const CMPIObjectPath *reference,
+                            const char **properties,
+                            CMPIInstance **_inst);
+
+CMPIStatus get_ep_by_ref(const CMPIBroker *broker,
+                           const CMPIObjectPath *reference,
+                           const char **properties,
+                           CMPIInstance **_inst);
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.1
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        From: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
    This patch add VESSSD, VirtualSwitch are bridge and pNIC on host.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
 schema/VirtualEthernetSwitchSystemSettingData.mof  |   31 ++
 ...ualEthernetSwitchSystemSettingData.registration |    3 +
 src/Virt_VESSSD.c                                  |  382 ++++++++++++++++++++
 src/Virt_VESSSD.h                                  |   39 ++
 4 files changed, 455 insertions(+), 0 deletions(-)
 create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.mof
 create mode 100644 schema/VirtualEthernetSwitchSystemSettingData.registration
 create mode 100644 src/Virt_VESSSD.c
 create mode 100644 src/Virt_VESSSD.h
diff --git a/schema/VirtualEthernetSwitchSystemSettingData.mof b/schema/VirtualEthernetSwitchSystemSettingData.mof
new file mode 100644
index 0000000..b6ecc65
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystemSettingData.mof
@@ -0,0 +1,31 @@
+// Copyright IBM Corp. 2012
+
+
+/* fix me: the libvirt-cim lacks parent class
+  "VirtualEthernetSwitchSettingData" defined in DSP1050 */
+[Description (
+	"A class derived from Virt_VirtualEthernetSystemSettingData to represent "
+	"the config of ."),
+ Provider("cmpi::Virt_VESSSD")
+]
+class Net_VirtualEthernetSwitchSystemSettingData : CIM_VirtualSystemSettingData
+{
+
+  [Description ("Virtual Switch System type number")]
+  string VirtualSystemType;
+
+  string AssociatedResourcePool;
+
+  uint16 VLAN_Connection[];
+
+  uint16 MaxNumAddress;
+
+  uint16 EVBMode;
+
+  uint16 STP;
+
+  uint16 AutoStart;
+
+  uint16 DHCP;
+
+};
diff --git a/schema/VirtualEthernetSwitchSystemSettingData.registration b/schema/VirtualEthernetSwitchSystemSettingData.registration
new file mode 100644
index 0000000..1ba7e0c
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystemSettingData.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2012
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Net_VirtualEthernetSwitchSystemSettingData root/virt Virt_VESSSD Virt_VESSSD instance
diff --git a/src/Virt_VESSSD.c b/src/Virt_VESSSD.c
new file mode 100644
index 0000000..587741e
--- /dev/null
+++ b/src/Virt_VESSSD.c
@@ -0,0 +1,382 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_instance.h>
+
+#include "cs_util.h"
+#include "misc_util.h"
+#include "device_parsing.h"
+
+#include "Virt_VESSSD.h"
+#include "network_model_helper.h"
+
+static const CMPIBroker *_BROKER;
+
+static int set_primary_for_vesssd(const char *prefix, const CMPIBroker *broker,
+                             struct EthIface *piface, CMPIInstance *instance)
+{
+        char *name, *vesssd_name;
+        int asret;
+
+        if (piface->name == NULL) {
+            return 0;
+        }
+
+        CMSetProperty(instance, "VirtualSystemType",
+                      (CMPIValue *)"DMTF:VirtualEthernetSwitch", CMPI_chars);
+
+        name = get_switch_name_from_iface(piface->name);
+        asret = asprintf(&vesssd_name, "%s:%s", prefix, name);
+
+        CMSetProperty(instance, "InstanceID",
+                      (CMPIValue *)vesssd_name, CMPI_chars);
+        CMSetProperty(instance, "ElementName",
+                      (CMPIValue *)name, CMPI_chars);
+        CMSetProperty(instance, "VirtualSystemIdentifier",
+                      (CMPIValue *)name, CMPI_chars);
+        CMSetProperty(instance, "VirtualSystemType",
+                      (CMPIValue *)prefix, CMPI_chars);
+
+
+
+        free(vesssd_name);
+        CU_FREE(name);
+
+        return 1;
+}
+
+static int set_secondary_for_vesssd(const CMPIBroker *broker,
+                         struct EthIface *piface, CMPIInstance *instance)
+{
+        if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) {
+                CMSetProperty(instance, "STP",
+                      (CMPIValue *)&piface->pbr_prop->STP, CMPI_uint16);
+        }
+
+        if (piface->protocol_prop.ipv4_prop.DHCP >= 0) {
+                CMSetProperty(instance, "DHCP",
+                      (CMPIValue *)&piface->protocol_prop.ipv4_prop.DHCP,
+                      CMPI_uint16);
+        }
+
+        if (piface->run_prop.boot_mode >= 0) {
+                CMSetProperty(instance, "AutoStart",
+                      (CMPIValue *)&piface->run_prop.boot_mode,
+                      CMPI_uint16);
+        }
+
+        return 1;
+}
+
+/* Populate an instance with information from a switch */
+static CMPIStatus set_properties(const CMPIBroker *broker,
+                                 struct EthIface *piface,
+                                 const char *prefix,
+                                 CMPIInstance *instance)
+{
+        CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
+        char *errstr;
+
+        if (!set_primary_for_vesssd(prefix, broker, piface, instance)) {
+                errstr = "failed to set primary properties for instance.";
+                CU_DEBUG("%s, iface name %s.", errstr, piface->name);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+                goto out;
+         }
+        if (!set_secondary_for_vesssd(broker, piface, instance)) {
+                errstr = "failed to set secondary properties for instance.";
+                CU_DEBUG("%s, iface name %s.", errstr, piface->name);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+                goto out;
+         }
+
+        cu_statusf(broker, &s,
+                   CMPI_RC_OK,
+                   "");
+
+ out:
+        return s;
+}
+
+static CMPIStatus instance_from_vesssd(const CMPIBroker *broker,
+                                const CMPIObjectPath *reference,
+                                struct EthIface *piface,
+                                CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+
+        inst = get_typed_instance(broker,
+                                  NETWORK_CLASS_PREFIX,
+                                  "VirtualEthernetSwitchSystemSettingData",
+                                  NAMESPACE(reference));
+        if (inst == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Unable to init SwitchSystem instance");
+                goto out;
+        }
+
+        s = set_properties(broker,
+                           piface,
+                           VESSD_SYSTEM_PREFIX,
+                           inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        *_inst = inst;
+
+ out:
+        return s;
+}
+
+CMPIStatus enum_vesssd(const CMPIBroker *broker,
+                      const CMPIObjectPath *reference,
+                      struct inst_list *plist)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        struct EthIfacesList ifaces_list;
+        int ret, i;
+        char *errstr;
+
+        eth_ifaceslist_init(&ifaces_list);
+
+        ret = get_host_ifaces(&ifaces_list,
+                                eth_iface_filter_cim_switch, NULL);
+
+        if (ret != 1) {
+            errstr = get_host_iface_error_reason(ret);
+            CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+
+        i = 0;
+        while (i < ifaces_list.count) {
+                CMPIInstance *inst = NULL;
+
+                s = instance_from_vesssd(broker,
+                                      reference,
+                                      ifaces_list.pifaces[i],
+                                      &inst);
+                if (s.rc != CMPI_RC_OK) {
+                        goto out;
+                }
+
+                inst_list_add(plist, inst);
+                i++;
+        }
+
+ out:
+        eth_ifaceslist_uninit(&ifaces_list);
+
+        return s;
+}
+
+static CMPIStatus return_enum_vesssd(const CMPIBroker *broker,
+                                    const CMPIObjectPath *reference,
+                                    const CMPIResult *results,
+                                    bool names_only)
+{
+        struct inst_list list;
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        inst_list_init(&list);
+
+        s = enum_vesssd(broker, reference, &list);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        if (names_only) {
+                cu_return_instance_names(results, &list);
+        } else {
+                cu_return_instances(results, &list);
+        }
+ out:
+        inst_list_free(&list);
+        return s;
+}
+
+CMPIStatus get_vesssd_by_name(const CMPIBroker *broker,
+                              const char *name,
+                              const CMPIObjectPath *reference,
+                              CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+        char *eth_name = NULL;
+        char *errstr;
+        int ret;
+        struct EthIfacesList ifaces_list;
+
+        eth_ifaceslist_init(&ifaces_list);
+
+        eth_name = get_iface_name_from_switch(name);
+        if (eth_name == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "failed to convert switch_name");
+                CU_DEBUG("switch name %s failed to convert.", name);
+                goto out;
+        }
+
+        ret = get_host_ifaces(&ifaces_list,
+                            eth_iface_filter_cim_switch_for_name, eth_name);
+
+        if (ret != 1) {
+            errstr = get_host_iface_error_reason(ret);
+            CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+        if (ifaces_list.count != 1) {
+            errstr = "expected switch not found.";
+            CU_DEBUG("%s\n", errstr);
+            eth_ifaceslist_print(&ifaces_list);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+
+        s = instance_from_vesssd(broker,
+                              reference,
+                              ifaces_list.pifaces[0],
+                              &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        *_inst = inst;
+
+ out:
+        eth_ifaceslist_uninit(&ifaces_list);
+        CU_FREE(eth_name);
+        return s;
+}
+
+CMPIStatus get_vesssd_by_ref(const CMPIBroker *broker,
+                           const CMPIObjectPath *reference,
+                           CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+        char *name = NULL;
+
+        if ((!parse_instanceid(reference, NULL, &name)) || (name == NULL)) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_NOT_FOUND,
+                           "No such instance (InstanceID)");
+                goto out;
+        }
+
+        s = get_vesssd_by_name(broker, name, reference, &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        s = cu_validate_ref(broker, reference, inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        *_inst = inst;
+
+ out:
+        free(name);
+
+        return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+                                    const CMPIContext *context,
+                                    const CMPIResult *results,
+                                    const CMPIObjectPath *reference)
+{
+        return return_enum_vesssd(_BROKER, reference, results, true);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+                                const CMPIContext *context,
+                                const CMPIResult *results,
+                                const CMPIObjectPath *reference,
+                                const char **properties)
+{
+        return return_enum_vesssd(_BROKER, reference, results, false);
+}
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+                              const CMPIContext *context,
+                              const CMPIResult *results,
+                              const CMPIObjectPath *reference,
+                              const char **properties)
+{
+        CMPIStatus s;
+        CMPIInstance *inst = NULL;
+
+        s = get_vesssd_by_ref(_BROKER, reference, &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        CMReturnInstance(results, inst);
+
+ out:
+        return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+STD_InstanceMIStub(,
+                   Virt_VESSSD,
+                   _BROKER,
+                   libvirt_cim_init());
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_VESSSD.h b/src/Virt_VESSSD.h
new file mode 100644
index 0000000..5105057
--- /dev/null
+++ b/src/Virt_VESSSD.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * 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
+ */
+#ifndef __VIRT_VESSSD_H
+#define __VIRT_VESSSD_H
+
+
+CMPIStatus enum_vesssd(const CMPIBroker *broker,
+                       const CMPIObjectPath *reference,
+                       struct inst_list *plist);
+
+CMPIStatus get_vesssd_by_ref(const CMPIBroker *broker,
+                             const CMPIObjectPath *reference,
+                             CMPIInstance **_inst);
+
+CMPIStatus get_vesssd_by_name(const CMPIBroker *broker,
+                              const char *name,
+                              const CMPIObjectPath *reference,
+                              CMPIInstance **_inst);
+
+
+#endif
-- 
1.7.1
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        From: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
    This patch add VESS according DSP1097.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
 schema/VirtualEthernetSwitchSystem.mof          |   10 +
 schema/VirtualEthernetSwitchSystem.registration |    3 +
 src/Virt_VirtualEthernetSwitchSystem.c          |  478 +++++++++++++++++++++++
 src/Virt_VirtualEthernetSwitchSystem.h          |   52 +++
 4 files changed, 543 insertions(+), 0 deletions(-)
 create mode 100644 schema/VirtualEthernetSwitchSystem.mof
 create mode 100644 schema/VirtualEthernetSwitchSystem.registration
 create mode 100644 src/Virt_VirtualEthernetSwitchSystem.c
 create mode 100644 src/Virt_VirtualEthernetSwitchSystem.h
diff --git a/schema/VirtualEthernetSwitchSystem.mof b/schema/VirtualEthernetSwitchSystem.mof
new file mode 100644
index 0000000..6c43719
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystem.mof
@@ -0,0 +1,10 @@
+// Copyright IBM Corp. 2012
+[Description (
+	"A class derived from CIM_ComputerSystem to represent "
+	"the Virtual Bridge on the host."),
+ Provider("cmpi::Virt_VirtualEthernetSwitchSystem")
+]
+class Net_VirtualEthernetSwitchSystem : CIM_ComputerSystem
+{
+
+};
diff --git a/schema/VirtualEthernetSwitchSystem.registration b/schema/VirtualEthernetSwitchSystem.registration
new file mode 100644
index 0000000..ac94e7c
--- /dev/null
+++ b/schema/VirtualEthernetSwitchSystem.registration
@@ -0,0 +1,3 @@
+# Copyright IBM Corp. 2012
+# Classname Namespace ProviderName ProviderModule ProviderTypes
+Net_VirtualEthernetSwitchSystem root/virt Virt_VirtualEthernetSwitchSystem Virt_VirtualEthernetSwitchSystem instance method
diff --git a/src/Virt_VirtualEthernetSwitchSystem.c b/src/Virt_VirtualEthernetSwitchSystem.c
new file mode 100644
index 0000000..14fb340
--- /dev/null
+++ b/src/Virt_VirtualEthernetSwitchSystem.c
@@ -0,0 +1,478 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * 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 <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include <cmpidt.h>
+#include <cmpift.h>
+#include <cmpimacs.h>
+
+#include <libcmpiutil/libcmpiutil.h>
+#include <libcmpiutil/std_invokemethod.h>
+#include <libcmpiutil/std_instance.h>
+#include <libcmpiutil/std_indication.h>
+
+#include "Virt_VirtualEthernetSwitchSystem.h"
+#include "device_parsing.h"
+#include "network_model_helper.h"
+
+static const CMPIBroker *_BROKER;
+
+static int set_primary_for_switch(const CMPIBroker *broker,
+                        const struct EthIface *piface, CMPIInstance *instance)
+{
+        char *name;
+        uint16_t dedicated;
+        CMPIArray *array;
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+
+        if (piface->name == NULL) {
+            return 0;
+        }
+
+        name = get_switch_name_from_iface(piface->name);
+        CMSetProperty(instance, "Name",
+                      (CMPIValue *)name, CMPI_chars);
+        CMSetProperty(instance, "ElementName",
+                      (CMPIValue *)name, CMPI_chars);
+        CU_FREE(name);
+
+        array = CMNewArray(broker, 1, CMPI_uint16, &s);
+        if ((s.rc != CMPI_RC_OK) || (CMIsNullObject(array))) {
+                return 0;
+        }
+        dedicated = CIM_NUM_SWITCH_DEDICATED;
+        CMSetArrayElementAt(array, 0, &dedicated, CMPI_uint16);
+        CMSetProperty(instance, "Dedicated",
+                      (CMPIValue *)&array, CMPI_uint16A);
+
+        return 1;
+}
+
+static int set_secondary_for_switch(const CMPIBroker *broker,
+                     struct EthIface *piface, CMPIInstance *instance)
+{
+        int state;
+        if (piface->run_prop.status == ETH_STATE_INACTIVE) {
+                state = CIM_STATE_DISABLED;
+        } else if (piface->run_prop.status == ETH_STATE_ACTIVE) {
+                state = CIM_STATE_ENABLED;
+        } else {
+                state = CIM_STATE_UNKNOWN;
+        }
+        CMSetProperty(instance, "EnabledState",
+                      (CMPIValue *)&state, CMPI_uint16);
+        CMSetProperty(instance, "RequestedState",
+                      (CMPIValue *)&state, CMPI_uint16);
+
+        return 1;
+}
+
+/* Populate an instance with information from a switch */
+static CMPIStatus set_properties(const CMPIBroker *broker,
+                                 struct EthIface *piface,
+                                 const char *prefix,
+                                 CMPIInstance *instance)
+{
+        CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL};
+        char *errstr;
+
+        if (!set_primary_for_switch(broker, piface, instance)) {
+                errstr = "failed to set primary properties for instance.";
+                CU_DEBUG("%s, iface name %s.", errstr, piface->name);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+                goto out;
+         }
+        if (!set_secondary_for_switch(broker, piface, instance)) {
+                errstr = "failed to set secondary properties for instance.";
+                CU_DEBUG("%s, iface name %s.", errstr, piface->name);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+                goto out;
+         }
+
+        cu_statusf(broker, &s,
+                   CMPI_RC_OK,
+                   "");
+
+ out:
+        return s;
+}
+
+static CMPIStatus instance_from_switch(const CMPIBroker *broker,
+                                const CMPIObjectPath *reference,
+                                struct EthIface *piface,
+                                CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+
+        inst = get_typed_instance(broker,
+                                  NETWORK_CLASS_PREFIX,
+                                  "VirtualEthernetSwitchSystem",
+                                  NAMESPACE(reference));
+        if (inst == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Unable to init VirtualEthernetSwitchSystem instance");
+                goto out;
+        }
+
+        s = set_properties(broker,
+                           piface,
+                           NETWORK_CLASS_PREFIX,
+                           inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+        *_inst = inst;
+
+ out:
+        return s;
+}
+
+CMPIStatus enum_switches(const CMPIBroker *broker,
+                         const CMPIObjectPath *reference,
+                         const CMPIResult *results,
+                         bool names_only)
+{
+        struct inst_list list;
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        struct EthIfacesList ifaces_list;
+        int ret, i;
+        char *errstr;
+
+        inst_list_init(&list);
+        eth_ifaceslist_init(&ifaces_list);
+
+        ret = get_host_ifaces(&ifaces_list,
+                                eth_iface_filter_cim_switch, NULL);
+
+        if (ret != 1) {
+            errstr = get_host_iface_error_reason(ret);
+            CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+        eth_ifaceslist_print(&ifaces_list);
+
+        i = 0;
+        while (i < ifaces_list.count) {
+                CMPIInstance *inst = NULL;
+
+                s = instance_from_switch(broker,
+                                      reference,
+                                      ifaces_list.pifaces[i],
+                                      &inst);
+                if (s.rc != CMPI_RC_OK) {
+                        goto out;
+                }
+                inst_list_add(&list, inst);
+                i++;
+        }
+
+        if (names_only) {
+                cu_return_instance_names(results, &list);
+        } else {
+                cu_return_instances(results, &list);
+        }
+
+ out:
+        inst_list_free(&list);
+        eth_ifaceslist_uninit(&ifaces_list);
+
+        return s;
+}
+
+CMPIStatus get_switch_by_name(const CMPIBroker *broker,
+                              const char *name,
+                              const CMPIObjectPath *reference,
+                              CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+        char *eth_name = NULL;
+        char *errstr;
+        int ret;
+        struct EthIfacesList ifaces_list;
+
+        eth_ifaceslist_init(&ifaces_list);
+
+        eth_name = get_iface_name_from_switch(name);
+        if (eth_name == NULL) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "failed to convert switch_name");
+                CU_DEBUG("switch name %s failed to convert.", name);
+                goto out;
+        }
+
+        ret = get_host_ifaces(&ifaces_list,
+                            eth_iface_filter_cim_switch_for_name, eth_name);
+        if (ret != 1) {
+            errstr = get_host_iface_error_reason(ret);
+            CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+        if (ifaces_list.count != 1) {
+            errstr = "expected switch not found.";
+            CU_DEBUG("%s\n", errstr);
+            eth_ifaceslist_print(&ifaces_list);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+
+        s = instance_from_switch(broker,
+                              reference,
+                              ifaces_list.pifaces[0],
+                              &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        *_inst = inst;
+
+ out:
+        eth_ifaceslist_uninit(&ifaces_list);
+        CU_FREE(eth_name);
+        return s;
+}
+
+CMPIStatus get_switch_by_ref(const CMPIBroker *broker,
+                             const CMPIObjectPath *reference,
+                             CMPIInstance **_inst)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+        const char *name = NULL;
+
+        if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "No domain name specified");
+                goto out;
+        }
+
+        s = get_switch_by_name(broker, name, reference, &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        s = cu_validate_ref(broker, reference, inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        *_inst = inst;
+
+ out:
+
+        return s;
+}
+
+static CMPIStatus __state_change(const CMPIBroker *broker,
+                                 const char *name,
+                                 uint16_t state,
+                                 const CMPIObjectPath *ref)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        struct EthIface iface;
+        int iface_state;
+        int ret;
+        char *errstr;
+
+        eth_iface_init(&iface);
+        iface.name = get_iface_name_from_switch(name);
+        if (iface.name == NULL) {
+                errstr = "failed to get iface name.";
+                CU_DEBUG("for %s, %s.", name, errstr);
+                cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+                goto out;
+        }
+        if (state == CIM_STATE_ENABLED) {
+                iface_state = ETH_STATE_ACTIVE;
+        } else if (state == CIM_STATE_DISABLED) {
+                iface_state = ETH_STATE_INACTIVE;
+        } else {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_NOT_SUPPORTED,
+                           "State not supported");
+                goto out;
+        }
+
+        /* TBD in next patch
+           ret = change_state_host_iface(&iface, iface_state); */
+        if (ret != 1) {
+            errstr = get_host_iface_error_reason(ret);
+            CU_DEBUG("error num %d returned, reason %s.", ret, errstr);
+            cu_statusf(broker, &s,
+                       CMPI_RC_ERR_FAILED,
+                       errstr);
+            goto out;
+        }
+
+
+ out:
+        eth_iface_uninit(&iface);
+        return s;
+}
+
+static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self,
+                                    const CMPIContext *context,
+                                    const CMPIResult *results,
+                                    const CMPIObjectPath *reference)
+{
+    return  enum_switches(_BROKER, reference, results, true);
+}
+
+static CMPIStatus EnumInstances(CMPIInstanceMI *self,
+                                const CMPIContext *context,
+                                const CMPIResult *results,
+                                const CMPIObjectPath *reference,
+                                const char **properties)
+{
+    return  enum_switches(_BROKER, reference, results, false);
+}
+
+static CMPIStatus GetInstance(CMPIInstanceMI *self,
+                              const CMPIContext *context,
+                              const CMPIResult *results,
+                              const CMPIObjectPath *reference,
+                              const char **properties)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIInstance *inst = NULL;
+
+        s = get_switch_by_ref(_BROKER, reference, &inst);
+        if (s.rc != CMPI_RC_OK) {
+                goto out;
+        }
+
+        CMReturnInstance(results, inst);
+
+ out:
+        return s;
+}
+
+DEFAULT_CI();
+DEFAULT_MI();
+DEFAULT_DI();
+DEFAULT_EQ();
+DEFAULT_INST_CLEANUP();
+
+static CMPIStatus state_change(CMPIMethodMI *self,
+                               const CMPIContext *context,
+                               const CMPIResult *results,
+                               const CMPIObjectPath *reference,
+                               const CMPIArgs *argsin,
+                               CMPIArgs *argsout)
+{
+        CMPIStatus s;
+        CMPIInstance *prev_inst = NULL;
+        uint16_t state;
+        int ret;
+        const char *name = NULL;
+        uint32_t rc = 1;
+
+        ret = cu_get_u16_arg(argsin, "RequestedState", &state);
+        if (ret != CMPI_RC_OK) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_INVALID_PARAMETER,
+                           "Invalid RequestedState");
+                goto out;
+        }
+
+        if (cu_get_str_path(reference, "Name", &name) != CMPI_RC_OK) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "Name key not specified");
+                goto out;
+        }
+
+        s = get_switch_by_name(_BROKER, name, reference, &prev_inst);
+        if (s.rc != CMPI_RC_OK || prev_inst == NULL) {
+                cu_statusf(_BROKER, &s,
+                           CMPI_RC_ERR_INVALID_PARAMETER,
+                           "Unable to get instance for guest '%s'",
+                           name);
+                goto out;
+        }
+
+        s = __state_change(_BROKER, name, state, reference);
+
+        if (s.rc == CMPI_RC_OK) {
+                rc = 0;
+        }
+ out:
+        CMReturnData(results, &rc, CMPI_uint32);
+
+        return s;
+}
+
+STD_InstanceMIStub(,
+                   Virt_VirtualEthernetSwitchSystem,
+                   _BROKER,
+                   libvirt_cim_init());
+
+static struct method_handler RequestStateChange = {
+        .name = "RequestStateChange",
+        .handler = state_change,
+        .args = {{"RequestedState", CMPI_uint16, false},
+                 {"TimeoutPeriod", CMPI_dateTime, true},
+                 ARG_END
+        }
+};
+
+static struct method_handler *my_handlers[] = {
+        &RequestStateChange,
+        NULL
+};
+
+STDIM_MethodMIStub(,
+                   Virt_VirtualEthernetSwitchSystem,
+                   _BROKER,
+                   libvirt_cim_init(),
+                   my_handlers);
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/src/Virt_VirtualEthernetSwitchSystem.h b/src/Virt_VirtualEthernetSwitchSystem.h
new file mode 100644
index 0000000..de8587b
--- /dev/null
+++ b/src/Virt_VirtualEthernetSwitchSystem.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * 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
+ */
+#ifndef __VIRT_VIRTUALETHERNETSWITCHSYSTEM_H
+#define __VIRT_VIRTUALETHERNETSWITCHSYSTEM_H
+
+#include "misc_util.h"
+
+CMPIStatus enum_switches(const CMPIBroker *broker,
+                         const CMPIObjectPath *reference,
+                         const CMPIResult *results,
+                         bool names_only);
+
+CMPIStatus get_switch_by_ref(const CMPIBroker *broker,
+                             const CMPIObjectPath *reference,
+                             CMPIInstance **_inst);
+
+
+CMPIStatus get_switch_by_name(const CMPIBroker *broker,
+                              const char *name,
+                              const CMPIObjectPath *reference,
+                              CMPIInstance **_inst);
+
+
+#endif
+
+/*
+ * Local Variables:
+ * mode: C
+ * c-set-style: "K&R"
+ * tab-width: 8
+ * c-basic-offset: 8
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
1.7.1
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    31 Jan '12
                    
                        From: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
    This patch change the Makefile to add new classes.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
 Makefile.am     |   14 ++++++++++++--
 src/Makefile.am |   23 ++++++++++++++++++++---
 2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 94dc5f3..86c155b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -63,7 +63,12 @@ MOFS = \
 	$(top_srcdir)/schema/EntriesInFilterList.mof \
 	$(top_srcdir)/schema/NestedFilterList.mof \
 	$(top_srcdir)/schema/AppliedFilterList.mof \
-	$(top_srcdir)/schema/HostedFilterList.mof
+	$(top_srcdir)/schema/HostedFilterList.mof \
+	$(top_srcdir)/schema/HostedFilterList.mof \
+	$(top_srcdir)/schema/VirtualEthernetSwitchSystem.mof \
+	$(top_srcdir)/schema/VirtualEthernetSwitchSystemSettingData.mof \
+	$(top_srcdir)/schema/EthernetPort.mof \
+	$(top_srcdir)/schema/EthernetPortAllocationSettingData.mof
 
 INTEROP_MOFS = \
 	$(top_srcdir)/schema/ComputerSystem.mof \
@@ -150,7 +155,12 @@ REGS = \
 	$(top_srcdir)/schema/EntriesInFilterList.registration \
 	$(top_srcdir)/schema/NestedFilterList.registration \
 	$(top_srcdir)/schema/AppliedFilterList.registration \
-	$(top_srcdir)/schema/HostedFilterList.registration
+	$(top_srcdir)/schema/HostedFilterList.registration \
+	$(top_srcdir)/schema/HostedFilterList.registration \
+	$(top_srcdir)/schema/VirtualEthernetSwitchSystem.registration \
+	$(top_srcdir)/schema/VirtualEthernetSwitchSystemSettingData.registration \
+	$(top_srcdir)/schema/EthernetPort.registration \
+	$(top_srcdir)/schema/EthernetPortAllocationSettingData.registration
 
 INTEROP_REGS = \
 	$(top_srcdir)/schema/RegisteredProfile.registration \
diff --git a/src/Makefile.am b/src/Makefile.am
index c28dc9a..5570b13 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,11 +24,16 @@ noinst_HEADERS = profiles.h svpc_types.h	\
     Virt_ConsoleRedirectionServiceCapabilities.h \
     Virt_KVMRedirectionSAP.h \
     Virt_FilterList.h \
-    Virt_FilterEntry.h
+    Virt_FilterEntry.h \
+    Virt_VirtualEthernetSwitchSystem.h \
+    Virt_VESSSD.h \
+    Virt_EthernetPort.h \
+    Virt_EASD.h
 
 XKUADD = $(top_builddir)/libxkutil/libxkutil.la
+NTWADD = $(top_builddir)/libnetwork/libnetwork.la
 
-CFLAGS += -I$(top_srcdir)/libxkutil $(CFLAGS_STRICT)
+CFLAGS += -I$(top_srcdir)/libxkutil -I$(top_srcdir)/libnetwork $(CFLAGS_STRICT)
 
 AM_LDFLAGS = $(XKUADD) \
 	     -version-info @VERSION_INFO@
@@ -85,7 +90,11 @@ provider_LTLIBRARIES = libVirt_ComputerSystem.la \
                        libVirt_EntriesInFilterList.la \
                        libVirt_NestedFilterList.la \
                        libVirt_HostedFilterList.la \
-                       libVirt_AppliedFilterList.la
+                       libVirt_AppliedFilterList.la \
+                       libVirt_VirtualEthernetSwitchSystem.la \
+                       libVirt_VESSSD.la \
+                       libVirt_EthernetPort.la \
+                       libVirt_EASD.la
 
 libVirt_ComputerSystem_la_SOURCES = Virt_ComputerSystem.c
 libVirt_ComputerSystem_la_DEPENDENCIES = libVirt_VirtualSystemSnapshotService.la
@@ -274,3 +283,11 @@ libVirt_HostedFilterList_la_LIBADD = -lVirt_HostSystem -lVirt_FilterList
 libVirt_AppliedFilterList_la_DEPENDENCIES = libVirt_Device.la libVirt_FilterList.la
 libVirt_AppliedFilterList_la_SOURCES = Virt_AppliedFilterList.c
 libVirt_AppliedFilterList_la_LIBADD = -lVirt_Device -lVirt_FilterList
+
+libVirt_VirtualEthernetSwitchSystem_la_SOURCES = Virt_VirtualEthernetSwitchSystem.c
+
+libVirt_VESSSD_la_SOURCES = Virt_VESSSD.c
+
+libVirt_EthernetPort_la_SOURCES = Virt_EthernetPort.c
+
+libVirt_EASD_la_SOURCES = Virt_EASD.c
-- 
1.7.1
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        From: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
    This patch add helper functions for building up CIM network model.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
 libxkutil/network_model_helper.c |  473 ++++++++++++++++++++++++++++++++++++++
 libxkutil/network_model_helper.h |  101 ++++++++
 2 files changed, 574 insertions(+), 0 deletions(-)
 create mode 100644 libxkutil/network_model_helper.c
 create mode 100644 libxkutil/network_model_helper.h
diff --git a/libxkutil/network_model_helper.c b/libxkutil/network_model_helper.c
new file mode 100644
index 0000000..9bb3e83
--- /dev/null
+++ b/libxkutil/network_model_helper.c
@@ -0,0 +1,473 @@
+/*
+ * 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 <string.h>
+
+#include "network_model_helper.h"
+#include "device_parsing.h"
+
+#include "cmpidt.h"
+#include "cmpift.h"
+#include "cmpimacs.h"
+
+/* this function would return a new allocated string or NULL */
+char *compare_and_switch_prefix(const char *orig_str,
+                                const char *orig_prefix,
+                                const char *dest_prefix)
+{
+        int orig_prefix_len, dest_prefix_len, asret;
+        char *retstr = NULL;
+        const char *suffix;
+        if (orig_str == NULL) {
+                goto out;
+        }
+        orig_prefix_len = strlen(orig_prefix);
+        dest_prefix_len = strlen(dest_prefix);
+        if (0 != strncmp(orig_str, orig_prefix, orig_prefix_len)) {
+                goto out;
+        }
+        suffix = orig_str + orig_prefix_len;
+        asret = asprintf(&retstr, "%s%s", dest_prefix, suffix);
+        if (asret == -1) {
+                free(retstr);
+                retstr = NULL;
+        }
+ out:
+        return retstr;
+}
+
+char *switch_device_id_prefix(const char *whole_id,
+                              const char *orig_prefix,
+                              const char *dest_prefix)
+{
+        char *system = NULL;
+        char *device = NULL;
+        char *new_id = NULL;
+        char *retstr = NULL;
+        int asret;
+
+
+        if (0 == parse_fq_devid(whole_id, &system, &device)) {
+                goto out;
+        }
+
+        new_id = compare_and_switch_prefix(device,
+                           orig_prefix, dest_prefix);
+
+        if (new_id == NULL) {
+                goto out;
+        }
+        asret = asprintf(&retstr, "%s/%s", system, new_id);
+        if (asret == -1) {
+                free(retstr);
+                retstr = NULL;
+        }
+
+ out:
+        free(system);
+        free(device);
+        free(new_id);
+        return retstr;
+}
+
+char *ep_id_to_easdea_id(const char *epid)
+{
+        return switch_device_id_prefix(epid,
+                      ETHPORT_PREFIX, ETHPORT_ALLOCATION_SD_PREFIX);
+}
+
+char *easdea_id_to_ep_id(const char *epid)
+{
+        return switch_device_id_prefix(epid,
+                      ETHPORT_ALLOCATION_SD_PREFIX, ETHPORT_PREFIX);
+}
+
+char *ep_id_to_easdec_id(const char *epid)
+{
+        return switch_device_id_prefix(epid,
+                      ETHPORT_PREFIX, ETHPORT_CONNECTION_SD_PREFIX);
+}
+
+char *easdec_id_to_ep_id(const char *epid)
+{
+        return switch_device_id_prefix(epid,
+                      ETHPORT_CONNECTION_SD_PREFIX, ETHPORT_PREFIX);
+}
+
+char *vlanid_to_connection_name(const int id)
+{
+        int asret;
+        char *str = NULL;
+        char *prefix = CONNECTION_VLAN_PREFIX;
+        asret = asprintf(&str, "%s%d", prefix, id);
+        if (asret == -1) {
+                return NULL;
+        }
+        return str;
+}
+
+int vlanid_from_connection_name(const char *name)
+{
+        int id = -1;
+        int temp = -1;
+        char *prefix = CONNECTION_VLAN_PREFIX;
+        char *dig_start, *dig_end;
+        if (name == NULL) {
+                goto out;
+        }
+        dig_start = strstr(name, prefix);
+        if (dig_start == NULL) {
+                goto out;
+        }
+        dig_start += strlen(prefix);
+        temp = strtol(dig_start, &dig_end, 10);
+        if ((dig_start == dig_end) || (temp < 0) || (temp > 4095)) {
+                goto out;
+        }
+        id = temp;
+ out:
+        return id;
+}
+
+int eth_iface_filter_cim_ethport(const struct EthIface *piface,
+                                             void *nouse)
+{
+        if ((piface->eth_type != ETH_TYPE_NOT_GOT) &&
+            (piface->eth_type != ETH_TYPE_ETHER_BRIDGE)) {
+            return 1;
+        }
+        return 0;
+}
+
+int eth_iface_filter_cim_ethport_for_name(const struct EthIface *piface,
+                                             void *name)
+{
+        int cim_ethport_flag;
+        cim_ethport_flag = eth_iface_filter_cim_ethport(piface, NULL);
+        if (cim_ethport_flag == 1) {
+                if (0 == strcmp(piface->name, name)) {
+                        return 1;
+                }
+        }
+        return 0;
+}
+
+/* returned value need to be freed */
+char *get_ethportsd_name_from_iface(const char *iface_name, const int type)
+{
+        char *prefix;
+        char *name;
+        int size;
+
+        if (iface_name == NULL) {
+                return NULL;
+        }
+
+        if (type == EASD_TYPE_EA) {
+                prefix = ETHPORT_ALLOCATION_SD_PREFIX;
+        } else {
+                prefix = ETHPORT_CONNECTION_SD_PREFIX;
+        }
+
+        size = strlen(iface_name)+strlen(prefix)+1;
+        CU_MALLOC(name, size);
+        snprintf(name, size, "%s%s", prefix, iface_name);
+        return name;
+}
+
+/* returned value need to be freed */
+char *get_iface_name_from_ethportsd(const char *ethport_name, int *ptype)
+{
+        char *prefix;
+        char *name = NULL;
+        int size;
+        int prefix_len;
+        int t = -1;
+
+        if (ethport_name == NULL) {
+                goto out;
+        }
+
+        prefix = ETHPORT_ALLOCATION_SD_PREFIX;
+        prefix_len = strlen(prefix);
+        if (0 != strncmp(ethport_name, prefix, prefix_len)) {
+                prefix = ETHPORT_CONNECTION_SD_PREFIX;
+                prefix_len = strlen(prefix);
+                if (0 != strncmp(ethport_name, prefix, prefix_len)) {
+                        goto out;
+                } else {
+                        t = EASD_TYPE_EC;
+                }
+        } else {
+                t = EASD_TYPE_EA;
+        }
+        size = strlen(ethport_name)-strlen(prefix)+1;
+        CU_MALLOC(name, size);
+        snprintf(name, size, "%s", ethport_name+prefix_len);
+
+ out:
+        if (ptype != NULL) {
+                *ptype = t;
+        }
+        return name;
+}
+
+int eth_iface_filter_cim_switch(const struct EthIface *piface,
+                                             void *nouse)
+{
+        if (piface->eth_type == ETH_TYPE_ETHER_BRIDGE) {
+            return 1;
+        }
+        return eth_iface_filter_peths(piface, nouse);
+}
+
+int eth_iface_filter_cim_switch_for_name(const struct EthIface *piface,
+                                             void *name)
+{
+        int cim_switch_flag;
+        cim_switch_flag = eth_iface_filter_cim_switch(piface, NULL);
+        if (cim_switch_flag == 1) {
+                if (0 == strcmp(piface->name, name)) {
+                        return 1;
+                }
+        }
+        return 0;
+}
+
+/* returned value need to be freed */
+char *get_switch_name_from_iface(const char *iface_name)
+{
+    char *prefix = SWITCH_PREFIX;
+    char *name;
+    int size;
+
+    size = strlen(iface_name)+strlen(prefix)+1;
+    CU_MALLOC(name, size);
+    snprintf(name, size, "%s%s", prefix, iface_name);
+    return name;
+}
+
+/* returned value need to be freed */
+char *get_iface_name_from_switch(const char *switch_name)
+{
+    char *prefix = SWITCH_PREFIX;
+    char *name;
+    int size;
+    int prefix_len;
+
+    prefix_len = strlen(prefix);
+    if (0 != strncmp(switch_name, prefix, prefix_len)) {
+        return NULL;
+    }
+    size = strlen(switch_name)-strlen(prefix)+1;
+    CU_MALLOC(name, size);
+    snprintf(name, size, "%s", switch_name+prefix_len);
+    return name;
+}
+
+/* returned value need to be freed */
+char *get_ethport_name_from_iface(const char *iface_name)
+{
+        char *prefix;
+        char *name;
+        int size;
+
+        if (iface_name == NULL) {
+                return NULL;
+        }
+
+        prefix = ETHPORT_PREFIX;
+        size = strlen(iface_name)+strlen(prefix)+1;
+        CU_MALLOC(name, size);
+        snprintf(name, size, "%s%s", prefix, iface_name);
+        return name;
+}
+
+/* returned value need to be freed */
+char *get_iface_name_from_ethport(const char *ethport_name)
+{
+        char *prefix = ETHPORT_PREFIX;
+        char *name = NULL;
+        int size;
+        int prefix_len;
+
+        if (ethport_name == NULL) {
+                goto out;
+        }
+
+        prefix = ETHPORT_PREFIX;
+        prefix_len = strlen(prefix);
+        if (0 != strncmp(ethport_name, prefix, prefix_len)) {
+                goto out;
+        }
+        size = strlen(ethport_name)-prefix_len+1;
+        CU_MALLOC(name, size);
+        snprintf(name, size, "%s", ethport_name+prefix_len);
+
+ out:
+        return name;
+}
+
+/* determine the CIM switch from the piface */
+int get_possible_bridge_name_for_cim_model(struct EthIface *piface,
+                                    char **pbr1name, char **pbr2name)
+{
+        char *br1_name;
+        char *br2_name;
+        if (piface->attach_bridge != NULL) {
+                br1_name = get_switch_name_from_iface(piface->attach_bridge);
+        } else if (piface->dep_ifname != NULL) {
+                br1_name = get_switch_name_from_iface(piface->dep_ifname);
+        } else if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) {
+                br1_name = get_switch_name_from_iface(piface->name);
+        } else {
+                br1_name = NULL;
+        }
+
+        if ((piface->attach_bridge != NULL) && (piface->dep_ifname != NULL)) {
+                br2_name = get_switch_name_from_iface(piface->dep_ifname);
+        } else if ((piface->attach_bridge != NULL) &&
+                   (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL)) {
+                br2_name = get_switch_name_from_iface(piface->name);
+        } else {
+                br2_name = NULL;
+        }
+
+        /* incase some pifaces such as "lo" have no parent nor attaching
+           bridge */
+        if (br1_name == NULL) {
+                br1_name = get_switch_name_from_iface(piface->name);
+        }
+        *pbr1name = br1_name;
+        *pbr2name = br2_name;
+        return 1;
+}
+
+CMPIStatus get_array_uint16_from_instance(const CMPIBroker *broker,
+                                                 CMPIInstance *inst,
+                                                 char *array_name,
+                                                 int *ret_result,
+                                                 int *ret_size,
+                                                 int max_size)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIArray *array;
+        CMPICount array_size;
+        CMPIData elem;
+        int i, ret, count = 0;
+
+        ret = cu_get_array_prop(inst, array_name, &array);
+        if (ret != CMPI_RC_OK) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "array property not found.");
+                CU_DEBUG("Failed to get array property %s.", array_name);
+                goto out;
+        }
+        array_size = CMGetArrayCount(array, &s);
+        if ((s.rc != CMPI_RC_OK) || (array_size > max_size) ||
+                                  (array_size <= 0)) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "failed to get size of array property,"
+                           " or its size is 0 or too big.");
+                CU_DEBUG("failed in getting size of %s property.", array_name);
+                goto out;
+        }
+        for (i = 0; i < array_size; i++) {
+                elem = CMGetArrayElementAt(array, i, NULL);
+                if (CMIsNullValue(elem)) {
+                        cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "NULL content of array property.");
+                        CU_DEBUG("NULL content of %s property.", array_name);
+                        goto out;
+                }
+                if (!(elem.type & CMPI_INTEGER)) {
+                        cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "wrong type of array property.");
+                        CU_DEBUG("wrong type of %s property.", array_name);
+                        goto out;
+                }
+                ret_result[count] = elem.value.uint16;
+                count++;
+        }
+ out:
+        *ret_size = count;
+        return s;
+}
+
+CMPIStatus get_array_string_from_instance(const CMPIBroker *broker,
+                                                 CMPIInstance *inst,
+                                                 char *array_name,
+                                                 char **ret_result,
+                                                 int *ret_size,
+                                                 int max_size)
+{
+        CMPIStatus s = {CMPI_RC_OK, NULL};
+        CMPIArray *array;
+        CMPICount array_size;
+        CMPIData elem;
+        const char *str;
+        int i, ret, count = 0;
+
+        ret = cu_get_array_prop(inst, array_name, &array);
+        if (ret != CMPI_RC_OK) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "array property not found.");
+                CU_DEBUG("Failed to get array property %s.", array_name);
+                goto out;
+        }
+        array_size = CMGetArrayCount(array, &s);
+        if ((s.rc != CMPI_RC_OK) || (array_size > max_size) ||
+                                  (array_size <= 0)) {
+                cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "failed to get size of array property,"
+                           " or its size is 0 or too big.");
+                CU_DEBUG("failed in getting size of %s property.", array_name);
+                goto out;
+        }
+        for (i = 0; i < array_size; i++) {
+                elem = CMGetArrayElementAt(array, i, NULL);
+                if (CMIsNullValue(elem)) {
+                        cu_statusf(broker, &s,
+                           CMPI_RC_ERR_FAILED,
+                           "NULL content of array property.");
+                        CU_DEBUG("NULL content of %s property.", array_name);
+                        goto out;
+                }
+                str = NULL;
+                str = CMGetCharPtr(elem.value.string);
+                if (str == NULL) {
+                        CU_DEBUG("Could not extract char pointer from "
+                                 "CMPIArray %s.", array_name);
+                        goto out;
+                }
+                ret_result[count] = CU_STRDUP(str);
+                count++;
+        }
+ out:
+        *ret_size = count;
+        return s;
+}
diff --git a/libxkutil/network_model_helper.h b/libxkutil/network_model_helper.h
new file mode 100644
index 0000000..6b3f151
--- /dev/null
+++ b/libxkutil/network_model_helper.h
@@ -0,0 +1,101 @@
+/*
+ * 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
+ */
+
+#ifndef NETWORK_MODEL_HELPER_H
+#define NETWORK_MODEL_HELPER_H
+
+#include "network_parsing.h"
+
+#define EASD_TYPE_EA 1
+#define EASD_TYPE_EC 2
+
+#define NETWORK_CLASS_PREFIX "Net"
+
+#define SWITCH_PREFIX "VS_"
+#define VESSD_SYSTEM_PREFIX "Virt"
+#define ETHPORT_PREFIX "EP_"
+#define ETHPORT_ALLOCATION_SD_PREFIX "EA_"
+#define ETHPORT_CONNECTION_SD_PREFIX "EC_"
+
+#define CONNECTION_VLAN_PREFIX "VLAN"
+
+#define CIM_NUM_NET_ETHERNET 2
+#define CIM_NUM_SWITCH_DEDICATED 38
+#define CIM_NUM_SWITCHPORT 30
+#define CIM_NUM_VLAN_MODE_TRUNK 5
+#define CIM_NUM_CONSUMERVISIBILITY_PASSEDTHROUGH 2
+#define CIM_NUM_CONSUMERVISIBILITY_VIRTUALIZED 3
+
+char *get_switch_name_from_iface(const char *iface_name);
+char *get_iface_name_from_switch(const char *switch_name);
+
+char *get_ethport_name_from_iface(const char *iface_name);
+char *get_iface_name_from_ethport(const char *ethport_name);
+
+char *get_ethportsd_name_from_iface(const char *iface_name, const int type);
+char *get_iface_name_from_ethportsd(const char *ethport_name, int *ptype);
+
+char *ep_id_to_easdea_id(const char *epid);
+char *easdea_id_to_ep_id(const char *epid);
+char *ep_id_to_easdec_id(const char *epid);
+char *easdec_id_to_ep_id(const char *epid);
+
+char *vlanid_to_connection_name(const int id);
+int vlanid_from_connection_name(const char *name);
+
+int eth_iface_filter_cim_switch(const struct EthIface *piface,
+                                             void *nouse);
+int eth_iface_filter_cim_switch_for_name(const struct EthIface *piface,
+                                             void *name);
+int eth_iface_filter_cim_ethport(const struct EthIface *piface,
+                                             void *nouse);
+int eth_iface_filter_cim_ethport_for_name(const struct EthIface *piface,
+                                             void *name);
+
+int get_possible_bridge_name_for_cim_model(struct EthIface *piface,
+                                    char **pbr1name, char **pbr2name);
+
+
+char *compare_and_switch_prefix(const char *orig_str,
+                                const char *orig_prefix,
+                                const char *dest_prefix);
+
+char *switch_device_id_prefix(const char *whole_id,
+                              const char *orig_prefix,
+                              const char *dest_prefix);
+
+/* other help function related to CIM */
+CMPIStatus get_array_uint16_from_instance(const CMPIBroker *broker,
+                                                 CMPIInstance *inst,
+                                                 char *array_name,
+                                                 int *ret_result,
+                                                 int *ret_size,
+                                                 int max_size);
+
+CMPIStatus get_array_string_from_instance(const CMPIBroker *broker,
+                                                 CMPIInstance *inst,
+                                                 char *array_name,
+                                                 char **ret_result,
+                                                 int *ret_size,
+                                                 int max_size);
+
+
+#endif
-- 
1.7.1
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    31 Jan '12
                    
                        From: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
    This patch add function libarary and test program with libvirt API.
Signed-off-by: Wenchao Xia <xiawenc(a)linux.vnet.ibm.com>
---
 libxkutil/Makefile.am            |   12 +-
 libxkutil/misc_util.c            |   48 +++
 libxkutil/misc_util.h            |    3 +
 libxkutil/network_parsing.c      |  762 ++++++++++++++++++++++++++++++++++++++
 libxkutil/network_parsing.h      |  176 +++++++++
 libxkutil/network_parsing_test.c |   70 ++++
 libxkutil/xmlgen.c               |    4 +-
 libxkutil/xmlgen.h               |    4 +
 8 files changed, 1074 insertions(+), 5 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..a1fc0b3 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 network_model_helper.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 network_model_helper.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..564c6f2 100644
--- a/libxkutil/misc_util.c
+++ b/libxkutil/misc_util.c
@@ -184,6 +184,54 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker,
         return conn;
 }
 
+virConnectPtr connect_any(void)
+{
+        const char *uri = NULL;
+        virConnectPtr conn = NULL;
+        hypervisor_status_t *h = NULL;
+        const char *classname = NULL;
+
+        for (h = &hypervisor_list[0]; h != NULL; h++) {
+                if (h->enabled) {
+
+                        classname = h->name;
+
+                        uri = cn_to_uri(classname);
+                        if (!uri) {
+                                CU_DEBUG("Unable to gen URI from classname,"
+                                 " uri is %s.", uri);
+                                return NULL;
+                        }
+                        CU_DEBUG("Connecting to libvirt with uri `%s'", uri);
+
+                        pthread_mutex_lock(&libvirt_mutex);
+
+                        if (is_read_only())
+                                conn = virConnectOpenReadOnly(uri);
+                        else
+                                conn = virConnectOpen(uri);
+
+                        pthread_mutex_unlock(&libvirt_mutex);
+
+                        if (!conn) {
+                                virErrorPtr error = virGetLastError();
+                                if (error->code == VIR_ERR_NO_CONNECT)
+                                        set_hypervisor_disabled(classname);
+
+                                CU_DEBUG("Unable to connect to `%s'", uri);
+                                continue;
+                        } else {
+                                break;
+                        }
+                }
+        }
+
+        if (classname == NULL) {
+                CU_DEBUG("Failed to find any hypervisor.");
+        }
+        return conn;
+}
+
 void free_domain_list(virDomainPtr *list, int count)
 {
         int i;
diff --git a/libxkutil/misc_util.h b/libxkutil/misc_util.h
index c7a2122..d1cc081 100644
--- a/libxkutil/misc_util.h
+++ b/libxkutil/misc_util.h
@@ -57,6 +57,9 @@ virConnectPtr connect_by_classname(const CMPIBroker *broker,
                                    const char *classname,
                                    CMPIStatus *s);
 
+/* Try connect to any hypervisor available */
+virConnectPtr connect_any(void);
+
 /* Establish a libvirt connection to the appropriate hypervisor,
  * as determined by the state of the system, or the value of the
  * HYPURI environment variable, if set.
diff --git a/libxkutil/network_parsing.c b/libxkutil/network_parsing.c
new file mode 100644
index 0000000..aa1b2e7
--- /dev/null
+++ b/libxkutil/network_parsing.c
@@ -0,0 +1,762 @@
+/*
+ * 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 LIST_INACTIVE_IFACE 1
+#define LIST_ACTIVE_IFACE 2
+
+static void vlan_prop_print(struct VLAN_Prop *pvlan_prop)
+{
+    struct VLAN_Prop_8021q *p_8021q;
+    CU_DEBUG_OP(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);
+        CU_DEBUG_OP(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;
+    CU_DEBUG_OP(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) {
+        CU_DEBUG_OP(1, "----Ports attached: ");
+        while (i < pbr_prop->port_num) {
+            CU_DEBUG_OP(1, " %s,", *(pbr_prop->port_names+i));
+            i++;
+        }
+        CU_DEBUG_OP(1, "\n");
+    }
+}
+
+void eth_iface_print(struct EthIface *piface)
+{
+    CU_DEBUG_OP(1, "Iface device: name %s.\n"
+        "--Main Props: parent %s, attach to %s, mac %s, iface type %d,"
+        " status %d, boot_mode %d,"
+        " protocol ipv4 dhcp %d.\n",
+        piface->name,
+        piface->dep_ifname, piface->attach_bridge, piface->mac, piface->eth_type,
+        piface->run_prop.status, piface->run_prop.boot_mode,
+        piface->protocol_prop.ipv4_prop.DHCP);
+    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;
+    CU_DEBUG_OP(1, "Have %d ifaces in the list:\n", plist->count);
+    while (i < plist->count) {
+        CU_DEBUG_OP(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_NONE;
+    }
+}
+
+static void br_prop_init(struct BR_Prop *pbr_prop)
+{
+    memset(pbr_prop, 0, sizeof(struct BR_Prop));
+    pbr_prop->STP = NUM_NONE;
+    pbr_prop->delay = NUM_NONE;
+    pbr_prop->port_num = NUM_NONE;
+}
+
+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_NONE;
+    piface->run_prop.boot_mode = BOOT_MODE_NOT_GOT;
+    piface->protocol_prop.ipv4_prop.DHCP = NUM_NONE;
+    return;
+}
+
+void eth_iface_add_br_prop(struct EthIface *piface)
+{
+    if (piface->pbr_prop != NULL) {
+        return;
+    }
+    CU_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;
+    }
+    CU_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);
+        CU_FREE(p_8021q->parent);
+    }
+}
+
+static void br_prop_uninit(struct BR_Prop *pbr_prop)
+{
+    int i = 0;
+    if (pbr_prop == NULL) {
+        return;
+    }
+    if (pbr_prop->port_names != NULL) {
+        while (i < pbr_prop->port_num) {
+            CU_FREE(pbr_prop->port_names[i]);
+            i++;
+        }
+        CU_FREE(pbr_prop->port_names);
+    }
+}
+
+void eth_iface_uninit(struct EthIface *piface)
+{
+    if (piface == NULL) {
+        return;
+    }
+    CU_FREE(piface->name);
+    CU_FREE(piface->dep_ifname);
+    CU_FREE(piface->attach_bridge);
+    CU_FREE(piface->mac);
+    br_prop_uninit(piface->pbr_prop);
+    CU_FREE(piface->pbr_prop);
+    vlan_prop_uninit(piface->pvlan_prop);
+    CU_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 = NULL;
+    int i = 0;
+    if (plist->count <= 0) {
+        return;
+    }
+    t = plist->pifaces;
+    while (i < plist->count) {
+        if (*t != NULL) {
+            eth_iface_uninit(*t);
+            CU_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 (strcmp(piface->name, name) == 0) {
+                return piface;
+            }
+        }
+    }
+    return NULL;
+}
+
+/* the judgement condition is weak, but I can't find a better way */
+int eth_iface_filter_peths(const struct EthIface *piface, void *nouse)
+{
+    if ((piface->eth_type != ETH_TYPE_ETHER_ANY) &&
+        (piface->eth_type != ETH_TYPE_ETHER_PHYSICAL)) {
+        return 0;
+    }
+    if (piface->dep_ifname != NULL) {
+        return 0;
+    }
+    if (NULL != strstr(piface->name, ".")) {
+        return 0;
+    }
+    /* this filter NetUSB etc */
+    if (NULL == strstr(piface->name, "eth")) {
+        return 0;
+    }
+
+    return 1;
+}
+
+char *get_host_iface_error_reason(int errno)
+{
+    char *ret = NULL;
+    switch (errno) {
+    case ERR_CONNECT:
+        ret = "Error in connect to hypervisor.";
+        break;
+
+    case ERR_LIST_INTERFACE:
+        ret = "Error in listing the interfaces.";
+        break;
+
+    default:
+        ret = "Internal error in calling libvirt API for interfaces.";
+        break;
+    }
+    return ret;
+}
+
+/* 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 = NULL, buf[16] = {0,};
+    int i = 0;
+    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)) {
+        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_BRIDGE) {
+        str = "bridge";
+    } else if (piface->eth_type == ETH_TYPE_ETHER_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->protocol_prop.ipv4_prop.DHCP == 1) {
+        temp_node2 = xmlNewChild(temp_node1, NULL, BAD_CAST "protocol", NULL);
+        xmlNewProp(temp_node2, BAD_CAST "family", BAD_CAST "ipv4");
+        temp_node3 = xmlNewChild(temp_node2, NULL, BAD_CAST "dhcp", NULL);
+    }
+
+    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 host_iface_adjust(struct EthIface *piface)
+{
+    if (1 == eth_iface_filter_peths(piface, NULL)) {
+        piface->eth_type = ETH_TYPE_ETHER_PHYSICAL;
+    }
+    return 1;
+}
+
+static int parse_eth_xmlnode(struct EthIfacesList *plist, xmlNode *inode,
+                             int status, char *attached,
+                             eth_iface_filter_func filter_func,
+                             void *filter_opaque)
+{
+    struct EthIface *piface = NULL;
+    xmlNode *child1 = NULL, *child2 = NULL;
+    char *temp = NULL, **ppchar;
+    int filter_ret = 0;
+
+    CU_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 (strcmp(temp, "ethernet") == 0) {
+            piface->eth_type = ETH_TYPE_ETHER_ANY;
+        }
+        if (strcmp(temp, "bridge") == 0) {
+            piface->eth_type = ETH_TYPE_ETHER_BRIDGE;
+        }
+        if (strcmp(temp, "vlan") == 0) {
+            piface->eth_type = ETH_TYPE_ETHER_VLAN;
+        }
+        CU_FREE(temp);
+    }
+
+    for (child1 = inode->children; child1 != NULL; child1 = child1->next) {
+        if (XSTREQ(child1->name, "start")) {
+            temp = get_attr_value(child1, "mode");
+            if (strcmp(temp, "onboot") == 0) {
+                piface->run_prop.boot_mode = BOOT_MODE_AUTOSTART;
+            }
+            if (strcmp(temp, "none") == 0) {
+                piface->run_prop.boot_mode = BOOT_MODE_NONE;
+            }
+            CU_FREE(temp);
+        }
+        if (XSTREQ(child1->name, "mac")) {
+            piface->mac = get_attr_value(child1, "address");
+        }
+        if (XSTREQ(child1->name, "protocol")) {
+            temp = get_attr_value(child1, "family");
+            if (strcmp(temp, "ipv4") == 0) {
+                for (child2 = child1->children; child2 != NULL;
+                                            child2 = child2->next) {
+                    if (XSTREQ(child2->name, "dhcp")) {
+                        piface->protocol_prop.ipv4_prop.DHCP = 1;
+                        break;
+                    }
+                }
+            }
+            CU_FREE(temp);
+        }
+        if (XSTREQ(child1->name, "bridge")) {
+            eth_iface_add_br_prop(piface);
+            temp = get_attr_value(child1, "stp");
+            if (strcmp(temp, "on") == 0) {
+                piface->pbr_prop->STP = 1;
+            }
+            if (strcmp(temp, "off") == 0) {
+                piface->pbr_prop->STP = 0;
+            }
+            CU_FREE(temp);
+            temp = get_attr_value(child1, "delay");
+            piface->pbr_prop->delay = strtol(temp, NULL, 10);
+            CU_FREE(temp);
+        }
+        if (XSTREQ(child1->name, "bridge")) {
+            eth_iface_add_br_prop(piface);
+            temp = get_attr_value(child1, "stp");
+            if (strcmp(temp, "on") == 0) {
+                piface->pbr_prop->STP = 1;
+            }
+            if (strcmp(temp, "off") == 0) {
+                piface->pbr_prop->STP = 0;
+            }
+            CU_FREE(temp);
+            temp = get_attr_value(child1, "delay");
+            piface->pbr_prop->delay = strtol(temp, NULL, 10);
+            CU_FREE(temp);
+            for (child2 = child1->children; child2 != NULL;
+                                            child2 = child2->next) {
+                if (XSTREQ(child2->name, "interface")) {
+                    if (piface->pbr_prop->port_names == NULL) {
+                        CU_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,
+                                      filter_func, filter_opaque);
+                }
+            }
+        }
+        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);
+            CU_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");
+                }
+            }
+        }
+    }
+
+    host_iface_adjust(piface);
+
+    filter_ret = 1;
+    if (filter_func != NULL) {
+        filter_ret = filter_func(piface, filter_opaque);
+    }
+    if (filter_ret == 1) {
+        eth_ifaceslist_add(plist, &piface);
+    }
+    return 1;
+}
+
+static const char *XMLToEthIfaceList(struct EthIfacesList *plist,
+                                     const char *xml,
+                                     int status,
+                                     eth_iface_filter_func filter_func,
+                                     void *filter_opaque)
+{
+    xmlDoc *xmldoc = NULL;
+    xmlXPathContext *xpathCtx = NULL;
+    xmlXPathObject *xpathObj = NULL;
+    xmlChar *xpathstr = NULL;
+    xmlNode **dev_nodes = NULL;
+    xmlNodeSet *nsv = NULL;
+    int count = 0;
+    int len = 0, devidx = 0;
+    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,
+                          filter_func, filter_opaque);
+    }
+
+ out:
+    xmlSetGenericErrorFunc(NULL, NULL);
+    xmlXPathFreeObject(xpathObj);
+
+ err3:
+    xmlXPathFreeContext(xpathCtx);
+ err2:
+    xmlFreeDoc(xmldoc);
+ err1:
+    return msg;
+}
+
+int get_host_ifaces(struct EthIfacesList *plist,
+                    eth_iface_filter_func filter_func, void *filter_opaque)
+{
+    virConnectPtr conn = NULL;
+    virInterfacePtr iface = NULL;
+    int ret = 0;
+    int num = 0, listnum = 0, i = 0;
+    char **names = NULL;
+    char *xml = NULL;
+    int flags = 0;
+    const char *msg = NULL;
+    int list_flag = LIST_INACTIVE_IFACE | LIST_ACTIVE_IFACE;
+    int xml_flag = VIR_INTERFACE_XML_INACTIVE;
+    //CMPIStatus s;
+
+    //conn = connect_by_classname(NULL, "xen", &s);
+    conn = connect_any();
+    if (conn == NULL) {
+        CU_DEBUG("Connect for network failed.");
+        ret = ERR_CONNECT;
+        goto out;
+    }
+
+    /* list defined interfaces*/
+    if ((list_flag & LIST_INACTIVE_IFACE) == 0) {
+        goto list_active;
+    }
+    num = virConnectNumOfDefinedInterfaces(conn);
+    if (num < 0) {
+        CU_DEBUG("Failed to find number of defined interfaces.");
+        ret = ERR_LIST_INTERFACE;
+        goto out;
+    }
+    names = malloc(num * sizeof(char *));
+    listnum = virConnectListDefinedInterfaces(conn, names, num);
+    if (listnum < 0) {
+        CU_DEBUG("Failed to list names of defined interfaces.");
+        ret = ERR_LIST_INTERFACE;
+        goto out;
+    }
+    CU_DEBUG("%d defined ifaces found from libvirt API.\n", listnum);
+
+    flags = xml_flag;
+    for (i = 0; i < listnum; i++) {
+        iface = virInterfaceLookupByName(conn, names[i]);
+        if (!iface) {
+            CU_DEBUG("Failed to look up %s.\n", names[i]);
+            CU_FREE(names[i]);
+            continue;
+        }
+        CU_FREE(names[i]);
+        xml = virInterfaceGetXMLDesc(iface, flags);
+        CU_DEBUG("Defined interface %d xml:\n%s", i, xml);
+        msg = XMLToEthIfaceList(plist, xml, ETH_STATE_INACTIVE,
+                               filter_func, filter_opaque);
+        if (msg != NULL) {
+            CU_DEBUG("Failed parsing eth xml, msg is: %s.", msg);
+        }
+        CU_FREE(xml);
+        virInterfaceFree(iface);
+    }
+    CU_FREE(names);
+
+ list_active:
+    /* list active interfaces*/
+    if ((list_flag & LIST_ACTIVE_IFACE) == 0) {
+        goto out;
+    }
+    num = virConnectNumOfInterfaces(conn);
+    if (num < 0) {
+        CU_DEBUG("Failed to find number of active interfaces.");
+        ret = ERR_LIST_INTERFACE;
+        goto out;
+    }
+    names = malloc(num * sizeof(char *));
+
+    listnum = virConnectListInterfaces(conn, names, num);
+    if (listnum < 0) {
+        CU_DEBUG("Failed to list names of active interfacess.");
+        ret = ERR_LIST_INTERFACE;
+        goto out;
+    }
+    CU_DEBUG("%d active ifaces found from libvirt API.\n", listnum);
+
+    flags = xml_flag;
+    for (i = 0; i < listnum; i++) {
+        iface = virInterfaceLookupByName(conn, names[i]);
+        if (!iface) {
+            CU_DEBUG("Failed to look up %s.\n", names[i]);
+            CU_FREE(names[i]);
+            continue;
+        }
+        CU_FREE(names[i]);
+        xml = virInterfaceGetXMLDesc(iface, flags);
+        CU_DEBUG("Active interface %d xml:\n%s", i, xml);
+        msg = XMLToEthIfaceList(plist, xml, ETH_STATE_ACTIVE,
+                                filter_func, filter_opaque);
+        if (msg != NULL) {
+            CU_DEBUG("Failed parsing eth xml, msg is: %s.", msg);
+        }
+        CU_FREE(xml);
+        virInterfaceFree(iface);
+    }
+    ret = 1;
+
+ out:
+    virConnectClose(conn);
+    CU_FREE(names);
+    return ret;
+}
+/*
+ * 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..5994f78
--- /dev/null
+++ b/libxkutil/network_parsing.h
@@ -0,0 +1,176 @@
+/*
+ * 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_NONE -1
+
+#define CU_DEBUG_LEVEL 2
+
+/* macro functions */
+#define CU_DEBUG_OP(lvl, fmt, args...) do { \
+    if (CU_DEBUG_LEVEL && (lvl) <= CU_DEBUG_LEVEL) { \
+        debug_print(fmt, ##args); \
+    } \
+} while (0)
+
+#define CU_MALLOC(p, size) \
+{ \
+    (p) = malloc((size)); \
+    if ((p) == NULL) { \
+        CU_DEBUG("malloc failed."); \
+    } \
+}
+
+#define CU_CALLOC(p, nmen, size) \
+{ \
+    (p) = calloc((nmen), (size)); \
+    if ((p) == NULL) { \
+        CU_DEBUG("calloc failed."); \
+    } \
+}
+
+#define CU_FREE(p) {free(p); (p) = NULL; }
+
+#define CU_STRDUP(p) (p) == NULL ? NULL : strdup(p);
+
+#define ERR_CONNECT -1
+#define ERR_LIST_INTERFACE -2
+
+typedef enum {
+    ETH_TYPE_NOT_GOT = NUM_NONE,
+    ETH_TYPE_ETHER_ANY = 0x0001,
+    ETH_TYPE_ETHER_PHYSICAL = 0x0002,
+    ETH_TYPE_ETHER_BRIDGE = 0x0004,
+    ETH_TYPE_ETHER_VLAN = 0x0008
+} EthType;
+
+typedef enum {
+    VLAN_TYPE_NOT_GOT = NUM_NONE,
+    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_NONE,
+    BOOT_MODE_NONE = 0,
+    BOOT_MODE_AUTOSTART = 1
+} BootMode;
+
+typedef enum {
+    ETH_STATE_INACTIVE = 0,
+    ETH_STATE_ACTIVE = 1
+} Status;
+
+struct IPV4_Prop {
+    int DHCP;
+} ;
+
+struct Protocol_Prop {
+    struct IPV4_Prop ipv4_prop;
+} ;
+
+struct BR_Prop {
+    int STP;
+    int delay;
+    char **port_names;
+    int port_num;
+} ;
+
+struct Run_Prop {
+    Status 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;
+    struct Protocol_Prop protocol_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);
+
+typedef int (*eth_iface_filter_func)(const struct EthIface *piface,
+                                     void *opaque);
+
+int eth_iface_filter_peths(const struct EthIface *piface, void *nouse);
+
+int get_host_ifaces(struct EthIfacesList *plist,
+                    eth_iface_filter_func filter_func, void *filter_opaque);
+
+char *get_host_iface_error_reason(int errno);
+
+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..31a1a3b
--- /dev/null
+++ b/libxkutil/network_parsing_test.c
@@ -0,0 +1,70 @@
+/*
+ * 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.
+ */
+
+#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 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;
+    long start_time, end_time;
+
+    CU_MALLOC(plist, sizeof(struct EthIfacesList));
+    eth_ifaceslist_init(plist);
+
+    start_time = print_and_ret_time_stamp();
+    get_host_ifaces(plist, NULL, NULL);
+    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);
+    CU_FREE(genxml);
+
+    eth_ifaceslist_uninit(plist);
+    CU_FREE(plist);
+    return 0;
+}
diff --git a/libxkutil/xmlgen.c b/libxkutil/xmlgen.c
index 9a2ada9..33da52b 100644
--- a/libxkutil/xmlgen.c
+++ b/libxkutil/xmlgen.c
@@ -35,8 +35,6 @@
 #include "cmpimacs.h"
 #endif
 
-#define XML_ERROR "Failed to allocate XML memory"
-
 typedef const char *(*devfn_t)(xmlNodePtr node, struct domain *dominfo);
 typedef const char *(*poolfn_t)(xmlNodePtr node, struct virt_pool *pool);
 typedef const char *(*resfn_t)(xmlNodePtr node, struct virt_pool_res *res);
@@ -830,7 +828,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..9c88986 100644
--- a/libxkutil/xmlgen.h
+++ b/libxkutil/xmlgen.h
@@ -27,11 +27,15 @@
 
 #include "cmpidt.h"
 
+#define XML_ERROR "Failed to allocate XML memory"
+
 struct kv {
 	const char *key;
 	const char *val;
 };
 
+char *tree_to_xml(xmlNodePtr root);
+
 char *system_to_xml(struct domain *dominfo);
 char *device_to_xml(struct virt_device *dev);
 
-- 
1.7.1
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                        
                            
                                
                            
                            [PATCH v5] vlan extention - add function library for readonly usage
                        
                        
by xiaxia347work@163.com 27 Jan '12
                    by xiaxia347work@163.com 27 Jan '12
27 Jan '12
                    
                        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)) {
+                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)) {
+        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) {
+        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")) {
+            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")) {
+                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);
 
-- 
1.7.1
                    
                  
                  
                          
                            
                            4
                            
                          
                          
                            
                            4
                            
                          
                          
                            
    
                          
                        
                    
                    
                        We are now entering the freeze for libvirt-cim-0.6.1. The plan is to spend the next week testing and fix anything needed for cimtest to pass. My testing will focus on libvirt-0.9.4+, but I welcome input from any version.
I've added the tag 'release_0_6_1_candidate' so you can download and test the release candidate over the next week.
Thanks,
-- 
Chip Vincent
Open Virtualization
IBM Linux Technology Center
cvincent(a)linux.vnet.ibm.com
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0
                            
                          
                          
                            
    
                          
                        
                    
                    
                        From: "Eduardo Lima (Etrunko)" <eblima(a)br.ibm.com>
According to recent changes in FilterList provider.
Note that this is still work in progress. Sending only for testing purposes.
Signed-off-by: Eduardo Lima (Etrunko) <eblima(a)br.ibm.com>
---
 suites/libvirt-cim/cimtest/FilterList/03_create.py |   36 ++++++++++++++++----
 suites/libvirt-cim/cimtest/FilterList/helper.py    |   18 +++++++++-
 2 files changed, 46 insertions(+), 8 deletions(-)
diff --git a/suites/libvirt-cim/cimtest/FilterList/03_create.py b/suites/libvirt-cim/cimtest/FilterList/03_create.py
index 157bd23..4a66f09 100644
--- a/suites/libvirt-cim/cimtest/FilterList/03_create.py
+++ b/suites/libvirt-cim/cimtest/FilterList/03_create.py
@@ -37,6 +37,9 @@ from VirtLib.utils import run_remote
 sup_types = ["KVM",]
 
 domain = None
+flist_name = None
+nested_name = None
+applied_name = None
 
 def get_filter_inst_and_inst_name(name):
     try:
@@ -88,6 +91,7 @@ def create_filter_list(name):
 
     # A NestedFilterList instance will add the "clean-traffic" filter
     # as an entry of the newly created FilterList
+    global nested_name
     logger.info("Creating NestedFilterList instance")
     nested_name = test.CreateFilterListInstance(None, "KVM_NestedFilterList",
                                   {"Antecedent":flist_name,
@@ -124,8 +128,12 @@ def get_nwport_inst_and_inst_name(domain_name):
 
 def cleanup():
     try:
-        # Destroy filter list
-        test.wbem.DeleteInstance(flist_name)
+        # Destroy filter list instances
+        for n in [applied_name, nested_name, flist_name]:
+            if n is not None:
+                logger.info("Deleting instance %s", n)
+                test.wbem.DeleteInstance(n)
+                logger.info("OK")
     except Exception, e:
         logger.error("Error deleting filter list: %s", e)
 
@@ -164,15 +172,29 @@ def main():
 
         # An AppliedFilterList Instance will apply the filter to the network
         # port of the defined domain
-        test.CreateFilterListInstance(None, "KVM_AppliedFilterList",
-                                      {"Antecedent":nwport_name,
-                                       "Dependent":flist_name})
+        global applied_name
+        logger.info ("Creating AppliedFilterList instance")
+        applied_name = test.CreateFilterListInstance(None, "KVM_AppliedFilterList",
+                                                     {"Antecedent":nwport_name,
+                                                      "Dependent":flist_name})
+        logger.info("Got AppliedFilterList name '%s'", applied_name)
+        #applied = test.GetInstance(applied_name)
+        #logger.info("Got AppliedFilterList '%s'", applied)
+
+        # Check results
+        filterref = test.libvirt_applied_filter_lists(domain_name)[0]
+        rule = helper.FilterRule(filterref)
+        if rule.filter != test_flist:
+            raise Exception("AppliedFilterList name '%s' does not match expected '%s'",
+                            rule.filter, test_flist)
+
+        test.cim_applied_filter_lists(domain_name)
+        logger.info("AppliedFilterList created succesfully")
+        result = PASS
     except Exception, e:
         logger.error("Caught exception: %s", e)
         result = FAIL
 
-    # Check results
-
     # Cleanup
     cleanup()
 
diff --git a/suites/libvirt-cim/cimtest/FilterList/helper.py b/suites/libvirt-cim/cimtest/FilterList/helper.py
index 294ae8f..c7e8612 100644
--- a/suites/libvirt-cim/cimtest/FilterList/helper.py
+++ b/suites/libvirt-cim/cimtest/FilterList/helper.py
@@ -307,6 +307,22 @@ class FilterListTest(BaseTestObject):
 
         return self.Associators(_inst_name, result_class="CIM_FilterEntryBase")
     # cim_entries_in_filter_list
+
+    def libvirt_applied_filter_lists(self, dom_name):
+        cmd = "virsh -q -c %s dumpxml %s 2>/dev/null" % (self.uri, dom_name)
+        ret, dom_xml = run_remote(self.server, cmd)
+        if ret:
+            logger.error("Error retrieving domain xml for %s", dom_name)
+            return None
+
+        xdoc = etree.fromstring(dom_xml)
+        filter_list = xdoc.xpath("/domain/devices/interface/filterref")
+        return filter_list
+    # libvirt_applied_filter_lists
+
+    def cim_applied_filter_lists(self, dom_name):
+        pass
+    # cim_applied_filter_lists
 # FilterListTest
 
 
@@ -394,7 +410,7 @@ class FilterRule(object):
 
         for e in element:
             self.__dict = dict(self.__dict, **e.attrib)
-            if not self.__type:
+            if self.__type is None:
                 self.__type = e.tag
 
         try:
-- 
1.7.7.6
                    
                  
                  
                          
                            
                            2
                            
                          
                          
                            
                            2
                            
                          
                          
                            
    
                          
                        
                    
                    
                        From: Chip Vincent <cvincent(a)us.ibm.com>
Fixes many small issues with the current AppliedFilterList provider.
1) Fix Create to properly return a complete object path and fix Delete to
   properly parse that path.
2) Persist applied filer rules. Since it's not possible to dyanmically update
   a single device, I've changed the code to modify and re-define the VM to
   essentially add/remove ACL filter associations.
   I also updated the code to minimize domain/device parsing overhead. For
   some strange reason, our internal APIs sometimes take a virDomainPtr and
   other times a struct domain * forcing providers who work with domains
   *and* devices to parse everything twice. Until the internal APIs are
   cleaned up, I simply parse everything once and then fetch the device
   manually from the struct domain *.
3) Add VIR_DOMAIN_XML_INACTIVE to virDomainGetXML(). By default, libvirt only
   returns the XML of the running domain. We need to fetch the *stored* XML
   that will be used for the next boot so that all changes made while the VM
   is running are preserved.
Changes from v2:
 - Return the correct reference in NestedFilterList
Changes from v1:
 - Fix leak and other comments
 - Fix all cases virDomainGetXML()
 - Fix NestedFilterList Create/Delete instance
Signed-off-by: Chip Vincent <cvincent(a)us.ibm.com>
---
 libxkutil/device_parsing.c          |    6 ++-
 src/Virt_AppliedFilterList.c        |   97 +++++++++++++++++++----------------
 src/Virt_ComputerSystem.c           |    3 +-
 src/Virt_ComputerSystemIndication.c |    3 +-
 src/Virt_FilterList.c               |    5 ++-
 src/Virt_NestedFilterList.c         |   15 ++++-
 src/Virt_VSMigrationService.c       |    3 +-
 7 files changed, 79 insertions(+), 53 deletions(-)
diff --git a/libxkutil/device_parsing.c b/libxkutil/device_parsing.c
index a1e8d6c..ff86f2a 100644
--- a/libxkutil/device_parsing.c
+++ b/libxkutil/device_parsing.c
@@ -996,7 +996,8 @@ int get_devices(virDomainPtr dom, struct virt_device **list, int type)
         char *xml;
         int ret;
 
-        xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_SECURE);
+        xml = virDomainGetXMLDesc(dom,
+                VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE);
         if (xml == NULL)
                 return 0;
 
@@ -1241,7 +1242,8 @@ int get_dominfo(virDomainPtr dom, struct domain **dominfo)
         char *xml;
         int ret;
         int start;
-        xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_SECURE);
+        xml = virDomainGetXMLDesc(dom,
+                VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE);
 
         if (xml == NULL)
                 return 0;
diff --git a/src/Virt_AppliedFilterList.c b/src/Virt_AppliedFilterList.c
index bc31c14..538adf4 100644
--- a/src/Virt_AppliedFilterList.c
+++ b/src/Virt_AppliedFilterList.c
@@ -97,67 +97,60 @@ static CMPIrc cu_get_ref_path(const CMPIObjectPath *reference,
         if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
                 return CMPI_RC_ERR_NO_SUCH_PROPERTY;
 
-        /* how to parse and object path? */
+        if ((value.type != CMPI_ref) ||  CMIsNullObject(value.value.ref))
+                return CMPI_RC_ERR_TYPE_MISMATCH;
+
+        *_reference = value.value.ref;
 
         return CMPI_RC_OK;
 }
 
-/* TODO: Port to libxkutil/device_parsing.c */
-static int update_device(virDomainPtr dom,
-                         struct virt_device *dev)
+static int update_domain(virConnectPtr conn,
+                         struct domain *dominfo)
 {
-#if LIBVIR_VERSION_NUMBER > 8000
         char *xml = NULL;
-        int flags = VIR_DOMAIN_DEVICE_MODIFY_CURRENT |
-                    VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
-        int ret = 0;
+        virDomainPtr dom = NULL;
 
-        xml = device_to_xml(dev);
+        xml = system_to_xml(dominfo);
         if (xml == NULL) {
-                CU_DEBUG("Failed to get XML for device '%s'", dev->id);
+                CU_DEBUG("Failed to get XML from domain %s", dominfo->name);
                 goto out;
         }
 
-        if (virDomainUpdateDeviceFlags(dom, xml, flags) != 0) {
-                CU_DEBUG("Failed to dynamically update device");
+        dom = virDomainDefineXML(conn, xml);
+        if (dom == NULL) {
+                CU_DEBUG("Failed to update domain %s", dominfo->name);
                 goto out;
         }
 
-        ret = 1;
  out:
         free(xml);
+        virDomainFree(dom);
 
-        return ret;
-#else
         return 0;
-#endif
 }
 
-/* TODO: Port to libxkutil/device_parsing.c */
-static int get_device_by_devid(virDomainPtr dom,
+static int get_device_by_devid(struct domain *dominfo,
                                const char *devid,
-                               int type,
                                struct virt_device **dev)
 {
-        int i, ret = 0;
-        struct virt_device *devices = NULL;
-        int count = get_devices(dom, &devices, type);
+        int i;
+        struct virt_device *devices = dominfo->dev_net;
+        int count = dominfo->dev_net_ct;
+
+        if (dev == NULL)
+                return 0;
 
         for (i = 0; i < count; i++) {
                 if (STREQC(devid, devices[i].id)) {
                         CU_DEBUG("Found '%s'", devices[i].id);
 
-                        *dev = virt_device_dup(&devices[i]);
-                        if (*dev != NULL)
-                                ret = 1;
-
-                        break;
+                        *dev = &devices[i];
+                        return 0;
                 }
         }
 
-        cleanup_virt_devices(&devices, count);
-
-        return ret;
+        return 1;
 }
 
 /**
@@ -425,6 +418,8 @@ static CMPIStatus CreateInstance(
         struct virt_device *device = NULL;
         virConnectPtr conn = NULL;
         virDomainPtr dom = NULL;
+        struct domain *dominfo = NULL;
+        CMPIObjectPath *_reference = NULL;
 
         conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
         if (conn == NULL)
@@ -487,8 +482,12 @@ static CMPIStatus CreateInstance(
                 goto out;
         }
 
-        get_device_by_devid(dom, net_name, CIM_RES_TYPE_NET, &device);
-        if (device == NULL) {
+        if (get_dominfo(dom, &dominfo) == 0) {
+                CU_DEBUG("Failed to get dominfo");
+                goto out;
+        }
+
+        if (get_device_by_devid(dominfo, net_name, &device) != 0) {
                 cu_statusf(_BROKER, &s,
                         CMPI_RC_ERR_FAILED,
                         "Dependent.Name object does not exist");
@@ -502,14 +501,19 @@ static CMPIStatus CreateInstance(
 
         device->dev.net.filter_ref = strdup(filter_name);
 
-        if (update_device(dom, device) == 0) {
+        if (update_domain(conn, dominfo) != 0) {
                 cu_statusf(_BROKER, &s,
                         CMPI_RC_ERR_FAILED,
-                        "Failed to update device");
+                        "Failed to update domain");
                 goto out;
         }
 
-        CMReturnObjectPath(results, reference);
+        /* create new object path */
+        _reference = CMClone(reference, NULL);
+        CMAddKey(_reference, "Antecedent", (CMPIValue *)&antecedent, CMPI_ref);
+        CMAddKey(_reference, "Dependent", (CMPIValue *)&dependent, CMPI_ref);
+
+        CMReturnObjectPath(results, _reference);
         CU_DEBUG("CreateInstance complete");
 
  out:
@@ -542,6 +546,7 @@ static CMPIStatus DeleteInstance(
         struct virt_device *device = NULL;
         virConnectPtr conn = NULL;
         virDomainPtr dom = NULL;
+        struct domain *dominfo = NULL;
 
         conn = connect_by_classname(_BROKER, CLASSNAME(reference), &s);
         if (conn == NULL)
@@ -557,7 +562,7 @@ static CMPIStatus DeleteInstance(
                 goto out;
         }
 
-        if (cu_get_str_path(reference, "DeviceID",
+        if (cu_get_str_path(antecedent, "DeviceID",
                 &device_name) != CMPI_RC_OK) {
                 cu_statusf(_BROKER, &s,
                         CMPI_RC_ERR_FAILED,
@@ -573,7 +578,7 @@ static CMPIStatus DeleteInstance(
                 goto out;
         }
 
-        if (cu_get_str_path(reference, "Name",
+        if (cu_get_str_path(dependent, "Name",
                 &filter_name) != CMPI_RC_OK) {
                 cu_statusf(_BROKER, &s,
                         CMPI_RC_ERR_FAILED,
@@ -585,7 +590,7 @@ static CMPIStatus DeleteInstance(
         if (filter == NULL) {
                 cu_statusf(_BROKER, &s,
                         CMPI_RC_ERR_FAILED,
-                        "Antecedent.Name object does not exist");
+                        "Dependent.Name object does not exist");
                 goto out;
         }
 
@@ -600,11 +605,15 @@ static CMPIStatus DeleteInstance(
                 goto out;
         }
 
-        get_device_by_devid(dom, net_name, CIM_RES_TYPE_NET, &device);
-        if (device == NULL) {
+        if (get_dominfo(dom, &dominfo) == 0) {
+                CU_DEBUG("Failed to get dominfo");
+                goto out;
+        }
+
+        if (get_device_by_devid(dominfo, net_name, &device) != 0) {
                 cu_statusf(_BROKER, &s,
                         CMPI_RC_ERR_FAILED,
-                        "Dependent.Name object does not exist");
+                        "Antecedent.Name object does not exist");
                 goto out;
         }
 
@@ -613,14 +622,14 @@ static CMPIStatus DeleteInstance(
                 device->dev.net.filter_ref = NULL;
         }
 
-        if (update_device(dom, device) == 0) {
+        if (update_domain(conn, dominfo) != 0) {
                 cu_statusf(_BROKER, &s,
                         CMPI_RC_ERR_FAILED,
-                        "Failed to update device");
+                        "Failed to update domain");
                 goto out;
         }
 
-        CU_DEBUG("CreateInstance complete");
+        CU_DEBUG("DeleteInstance complete");
 
  out:
         free(domain_name);
diff --git a/src/Virt_ComputerSystem.c b/src/Virt_ComputerSystem.c
index 582253a..e6c7e55 100644
--- a/src/Virt_ComputerSystem.c
+++ b/src/Virt_ComputerSystem.c
@@ -926,7 +926,8 @@ static CMPIStatus domain_reset(virDomainPtr dom)
                 return s;
         }
 
-        xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_SECURE);
+        xml = virDomainGetXMLDesc(dom,
+                VIR_DOMAIN_XML_INACTIVE |VIR_DOMAIN_XML_SECURE);
         if (xml == NULL) {
                 CU_DEBUG("Unable to retrieve domain XML");
                 virt_set_status(_BROKER, &s,
diff --git a/src/Virt_ComputerSystemIndication.c b/src/Virt_ComputerSystemIndication.c
index eb1a71c..6ef2ddc 100644
--- a/src/Virt_ComputerSystemIndication.c
+++ b/src/Virt_ComputerSystemIndication.c
@@ -107,7 +107,8 @@ static int csi_dom_xml_set(csi_dom_xml_t *dom, virDomainPtr dom_ptr, CMPIStatus
         dom->name = strdup(name);
 
         /* xml */
-        dom->xml = virDomainGetXMLDesc(dom_ptr, VIR_DOMAIN_XML_SECURE);
+        dom->xml = virDomainGetXMLDesc(dom_ptr,
+                VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE);
         if (dom->xml == NULL) {
                 cu_statusf(_BROKER, s,
                            CMPI_RC_ERR_FAILED,
diff --git a/src/Virt_FilterList.c b/src/Virt_FilterList.c
index 35d18a9..5b1b6e8 100644
--- a/src/Virt_FilterList.c
+++ b/src/Virt_FilterList.c
@@ -358,7 +358,10 @@ static CMPIStatus DeleteInstance(
                 goto out;
         }
 
-        delete_filter(conn, filter);
+        if (delete_filter(conn, filter) != 0) {
+                CU_DEBUG("Failed to delete filter %s", filter->name);
+                goto out;
+        }
 
  out:
         cleanup_filters(&filter, 1);
diff --git a/src/Virt_NestedFilterList.c b/src/Virt_NestedFilterList.c
index 894cd7c..2353e61 100644
--- a/src/Virt_NestedFilterList.c
+++ b/src/Virt_NestedFilterList.c
@@ -98,7 +98,10 @@ static CMPIrc cu_get_ref_path(const CMPIObjectPath *reference,
         if ((s.rc != CMPI_RC_OK) || CMIsNullValue(value))
                 return CMPI_RC_ERR_NO_SUCH_PROPERTY;
 
-        /* how to parse and object path? */
+        if ((value.type != CMPI_ref) ||  CMIsNullObject(value.value.ref))
+                return CMPI_RC_ERR_TYPE_MISMATCH;
+
+        *_reference = value.value.ref;
 
         return CMPI_RC_OK;
 }
@@ -305,6 +308,7 @@ static CMPIStatus CreateInstance(
         const char *child_name = NULL;
         struct acl_filter *child_filter = NULL;
         virConnectPtr conn = NULL;
+        CMPIObjectPath *_reference = NULL;
 
         CU_DEBUG("Reference = %s", REF2STR(reference));
 
@@ -383,7 +387,12 @@ static CMPIStatus CreateInstance(
                 goto out;
         }
 
-        CMReturnObjectPath(results, reference);
+        /* create new object path */
+        _reference = CMClone(reference, NULL);
+        CMAddKey(_reference, "Antecedent", (CMPIValue *)&antecedent, CMPI_ref);
+        CMAddKey(_reference, "Dependent", (CMPIValue *)&dependent, CMPI_ref);
+
+        CMReturnObjectPath(results, _reference);
         CU_DEBUG("CreateInstance completed");
 
  out:
@@ -475,7 +484,7 @@ static CMPIStatus DeleteInstance(
                 goto out;
         }
 
-        CU_DEBUG("CreateInstance completed");
+        CU_DEBUG("DeleteInstance completed");
 
  out:
         cleanup_filters(&parent_filter, 1);
diff --git a/src/Virt_VSMigrationService.c b/src/Virt_VSMigrationService.c
index d393787..76e3d25 100644
--- a/src/Virt_VSMigrationService.c
+++ b/src/Virt_VSMigrationService.c
@@ -1070,7 +1070,8 @@ static CMPIStatus prepare_migrate(virDomainPtr dom,
 {
         CMPIStatus s = {CMPI_RC_OK, NULL};
 
-        *xml = virDomainGetXMLDesc(dom, VIR_DOMAIN_XML_SECURE);
+        *xml = virDomainGetXMLDesc(dom,
+                VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE);
         if (*xml == NULL) {
 
                 virt_set_status(_BROKER, &s,
-- 
1.7.1
                    
                  
                  
                          
                            
                            1
                            
                          
                          
                            
                            0