[Libvirt-cim] [V3 PATCH 04/10] libnetwork source code with a test program

Wayne Xia xiawenc at linux.vnet.ibm.com
Thu Jan 12 09:46:48 UTC 2012


    source code of libnetwor and test program. Calling stack is:
main->host_network_API->host_network_implement_OSAPI->(libnl3 libbridge).
dll_magic.h is the file used to distinguish whether the symbol is exported
or imported.

Signed-off-by: Wayne Xia <xiawenc at linux.vnet.ibm.com>
---
 libnetwork/dll_magic.h                    |   13 +
 libnetwork/host_network_API.c             |   30 ++
 libnetwork/host_network_API.h             |   25 ++
 libnetwork/host_network_basic.c           |  657 ++++++++++++++++++++++++++++
 libnetwork/host_network_basic.h           |  170 ++++++++
 libnetwork/host_network_error.h           |   31 ++
 libnetwork/host_network_helper.c          |  659 +++++++++++++++++++++++++++++
 libnetwork/host_network_helper.h          |  202 +++++++++
 libnetwork/host_network_implement_OSAPI.c |  453 ++++++++++++++++++++
 libnetwork/host_network_implement_OSAPI.h |   21 +
 libnetwork/libnetwork_test.c              |   82 ++++
 11 files changed, 2343 insertions(+), 0 deletions(-)
 create mode 100644 libnetwork/dll_magic.h
 create mode 100644 libnetwork/host_network_API.c
 create mode 100644 libnetwork/host_network_API.h
 create mode 100644 libnetwork/host_network_basic.c
 create mode 100644 libnetwork/host_network_basic.h
 create mode 100644 libnetwork/host_network_error.h
 create mode 100644 libnetwork/host_network_helper.c
 create mode 100644 libnetwork/host_network_helper.h
 create mode 100644 libnetwork/host_network_implement_OSAPI.c
 create mode 100644 libnetwork/host_network_implement_OSAPI.h
 create mode 100644 libnetwork/libnetwork_test.c

diff --git a/libnetwork/dll_magic.h b/libnetwork/dll_magic.h
new file mode 100644
index 0000000..36bca83
--- /dev/null
+++ b/libnetwork/dll_magic.h
@@ -0,0 +1,13 @@
+#ifndef DLL_MAGIC_H
+#define DLL_MAGIC_H
+
+
+#if __GNUC__ >= 4
+    #ifdef DLL_BUILD
+        #define DLL_PUBLIC __attribute__ ((visibility ("default")))
+    #else
+        #define DLL_PUBLIC
+    #endif
+#endif
+
+#endif
diff --git a/libnetwork/host_network_API.c b/libnetwork/host_network_API.c
new file mode 100644
index 0000000..d2838ad
--- /dev/null
+++ b/libnetwork/host_network_API.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+
+#include "host_network_API.h"
+#include "host_network_implement_OSAPI.h"
+#include "host_network_error.h"
+
+/* this layer is added to devide the abstraction and implemention, so that
+   different implemention could be used and switched */
+
+int get_host_ifaces(EthIfacesList *plist,
+                        eth_iface_filter_func filter_func, void *filter_opaque)
+{
+    return get_host_eth_ifaces_osapi(plist, filter_func, filter_opaque);
+}
+
+char *get_host_iface_error_reason(int errno)
+{
+    return translate_error_no(errno);
+}
diff --git a/libnetwork/host_network_API.h b/libnetwork/host_network_API.h
new file mode 100644
index 0000000..452aa29
--- /dev/null
+++ b/libnetwork/host_network_API.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+#ifndef HOST_NETWORK_API
+#define HOST_NETWORK_API
+
+#include "dll_magic.h"
+#include "host_network_basic.h"
+#include "host_network_helper.h"
+
+DLL_PUBLIC int get_host_ifaces(EthIfacesList *plist,
+                        eth_iface_filter_func filter_func, void *filter_opaque);
+
+DLL_PUBLIC char *get_host_iface_error_reason(int errno);
+
+#endif
diff --git a/libnetwork/host_network_basic.c b/libnetwork/host_network_basic.c
new file mode 100644
index 0000000..e227091
--- /dev/null
+++ b/libnetwork/host_network_basic.c
@@ -0,0 +1,657 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+#include "host_network_basic.h"
+#include "host_network_helper.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static void vlan_prop_print(VLAN_Prop *pvlan_prop)
+{
+    VLAN_Prop_8021q *p_8021q;
+    char *ingress = NULL, *egress = NULL;
+    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);
+        vlan_8021q_qos_num_to_str(&ingress, &(p_8021q->ingress));
+        vlan_8021q_qos_num_to_str(&egress, &(p_8021q->egress));
+        CMD_DEBUG(1, "----IEEE802.1.Q: id %d, reorder %d, priority %d, "
+                "ingress %s, egress %s, parent %s.\n",
+                p_8021q->vlan_id, p_8021q->reorder_hdr, p_8021q->priv_flag,
+                ingress, egress, p_8021q->parent);
+    }
+    SAFE_FREE(ingress);
+    SAFE_FREE(egress);
+}
+
+static void br_prop_print(BR_Prop *pbr_prop)
+{
+    int i = 0;
+    CMD_DEBUG(1, "--Bridge props: id %s, stp %d, "
+            "bridge type %d, port_num %d.\n",
+            pbr_prop->bridge_id, pbr_prop->STP,
+            pbr_prop->type, 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(EthIface *piface)
+{
+    CMD_DEBUG(1, "Iface device: name %s.\n"
+        "--Main Props: parent %s, attach to %s, mac %s, ip %s, ip_mask %s,"
+        " RX %lld, TX %lld, state %d, iface type 0x%x.\n",
+        piface->name, piface->dep_ifname, piface->attach_bridge,
+        piface->mac, piface->ipv4_prop.ip, piface->ipv4_prop.ip_mask,
+        piface->run_prop.rx_bytes, piface->run_prop.tx_bytes,
+        piface->run_prop.state, 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(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++;
+    }
+}
+
+void vlan_prop_init(VLAN_Prop *pvlan_prop, int vlan_type)
+{
+    VLAN_Prop_8021q *p_8021q;
+    memset(pvlan_prop, 0, sizeof(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->ingress.count = NUM_NOT_GOT;
+        p_8021q->egress.count = NUM_NOT_GOT;
+        p_8021q->vlan_id = NUM_NOT_GOT;
+        p_8021q->reorder_hdr = NUM_NOT_GOT;
+        p_8021q->priv_flag = NUM_NOT_GOT;
+    }
+}
+
+void br_prop_init(BR_Prop *pbr_prop)
+{
+    memset(pbr_prop, 0, sizeof(BR_Prop));
+    pbr_prop->STP = NUM_NOT_GOT;
+    pbr_prop->type = BR_TYPE_NOT_GOT;
+    pbr_prop->port_num = NUM_NOT_GOT;
+}
+
+void eth_iface_init(EthIface *piface)
+{
+    memset(piface, 0, sizeof(EthIface));
+    piface->eth_type = ETH_TYPE_NOT_GOT;
+    piface->run_prop.rx_bytes = NUM_NOT_GOT;
+    piface->run_prop.tx_bytes = NUM_NOT_GOT;
+    piface->run_prop.state = ETH_STATE_NOT_GOT;
+    return;
+}
+
+void eth_iface_add_br_prop(EthIface *piface)
+{
+    SAFE_MALLOC(piface->pbr_prop, sizeof(BR_Prop));
+    br_prop_init(piface->pbr_prop);
+}
+
+void eth_iface_add_vlan_prop(EthIface *piface, int vlan_type)
+{
+    SAFE_MALLOC(piface->pvlan_prop, sizeof(VLAN_Prop));
+    vlan_prop_init(piface->pvlan_prop, vlan_type);
+}
+
+void vlan_prop_uninit(VLAN_Prop *pvlan_prop)
+{
+    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);
+    }
+}
+
+void br_prop_uninit(BR_Prop *pbr_prop)
+{
+    int i;
+    if (pbr_prop == NULL) {
+        return;
+    }
+    SAFE_FREE(pbr_prop->bridge_id);
+    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(EthIface *piface)
+{
+    if (piface == NULL) {
+        return;
+    }
+    SAFE_FREE(piface->name);
+    SAFE_FREE(piface->dep_ifname);
+    SAFE_FREE(piface->attach_bridge);
+    SAFE_FREE(piface->mac);
+    SAFE_FREE(piface->ipv4_prop.ip);
+    SAFE_FREE(piface->ipv4_prop.ip_mask);
+    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_ifaces_clear(EthIface **ppifaces, int num)
+{
+    EthIface **t;
+    int i;
+    if (num <= 0) {
+        return;
+    }
+    t = ppifaces;
+    i = 0;
+    while (i < num) {
+        if (*t != NULL) {
+            eth_iface_uninit(*t);
+            SAFE_FREE(*t);
+        }
+        t++;
+        i++;
+    }
+    return;
+}
+
+void eth_ifaceslist_init(EthIfacesList *plist)
+{
+    plist->count = 0;
+}
+
+void eth_ifaceslist_uninit(EthIfacesList *plist)
+{
+    eth_ifaces_clear(plist->pifaces, plist->count);
+}
+
+static void vlan_prop_dup(VLAN_Prop *dest, const VLAN_Prop *src)
+{
+    VLAN_Prop_8021q *pd_8021q;
+    const VLAN_Prop_8021q *ps_8021q;
+    dest->vlan_type = src->vlan_type;
+    if (dest->vlan_type == VLAN_TYPE_802_1_Q) {
+        pd_8021q = &(dest->props.prop_8021q);
+        ps_8021q = &(src->props.prop_8021q);
+        pd_8021q->vlan_id = ps_8021q->vlan_id;
+        pd_8021q->reorder_hdr = ps_8021q->reorder_hdr;
+        pd_8021q->priv_flag = ps_8021q->priv_flag;
+        pd_8021q->ingress = ps_8021q->ingress;
+        pd_8021q->egress = ps_8021q->egress;
+        pd_8021q->parent = SAFE_STRDUP(ps_8021q->parent);
+    }
+}
+
+static void br_prop_dup(BR_Prop *dest, const BR_Prop *src)
+{
+    int i;
+    dest->bridge_id = SAFE_STRDUP(src->bridge_id);
+    dest->STP = src->STP;
+    dest->type = src->type;
+    SAFE_PSTR_ARRAY_DUP(dest->port_names, dest->port_num,
+                            src->port_names, src->port_num, i);
+}
+
+void eth_iface_dup(EthIface *dest, const EthIface *src)
+{
+    dest->name = SAFE_STRDUP(src->name);
+    dest->dep_ifname = SAFE_STRDUP(src->dep_ifname);
+    dest->attach_bridge = SAFE_STRDUP(src->attach_bridge);
+    dest->mac = SAFE_STRDUP(src->mac);
+    dest->eth_type = src->eth_type;
+    dest->ipv4_prop.ip = SAFE_STRDUP(src->ipv4_prop.ip);
+    dest->ipv4_prop.ip_mask = SAFE_STRDUP(src->ipv4_prop.ip_mask);
+    dest->run_prop.rx_bytes = src->run_prop.rx_bytes;
+    dest->run_prop.tx_bytes = src->run_prop.tx_bytes;
+    dest->run_prop.state = src->run_prop.state;
+
+    if (src->pbr_prop != NULL) {
+        SAFE_MALLOC(dest->pbr_prop, sizeof(BR_Prop));
+        /* doesn't need init it for that it would be copied at once */
+        br_prop_dup(dest->pbr_prop, src->pbr_prop);
+    } else {
+        dest->pbr_prop = NULL;
+    }
+
+    if (src->pvlan_prop != NULL) {
+        SAFE_MALLOC(dest->pvlan_prop, sizeof(VLAN_Prop));
+        /* doesn't need init it for that it would be copied at once */
+        vlan_prop_dup(dest->pvlan_prop, src->pvlan_prop);
+    } else {
+        dest->pvlan_prop = NULL;
+    }
+
+}
+
+int eth_iface_compare(const EthIface *p1, const EthIface *p2)
+{
+    int ret = 0;
+    if ((p1->name != NULL) || (p2->name != NULL)) {
+        if (0 == strcmp(p1->name, p2->name)) {
+            ret = 1;
+        }
+    }
+    return ret;
+}
+
+static void vlan_prop_merge(VLAN_Prop *pdest, VLAN_Prop *psrc, int style)
+{
+    VLAN_Prop_8021q *pd_8021q, *ps_8021q;
+
+    NUM_MERGE(pdest->vlan_type, psrc->vlan_type, VLAN_TYPE_NOT_GOT);
+
+    if (psrc->vlan_type == VLAN_TYPE_802_1_Q) {
+        pd_8021q = &(pdest->props.prop_8021q);
+        ps_8021q = &(psrc->props.prop_8021q);
+        NUM_MERGE(pd_8021q->vlan_id, ps_8021q->vlan_id, NUM_NOT_GOT);
+        NUM_MERGE(pd_8021q->reorder_hdr, ps_8021q->reorder_hdr, NUM_NOT_GOT);
+        NUM_MERGE(pd_8021q->priv_flag, ps_8021q->priv_flag, NUM_NOT_GOT);
+        if (pd_8021q->ingress.count == NUM_NOT_GOT) {
+            pd_8021q->ingress = ps_8021q->ingress;
+        }
+        if (pd_8021q->egress.count == NUM_NOT_GOT) {
+            pd_8021q->egress = ps_8021q->egress;
+        }
+        if (style == 0) {
+            CHARS_MERGE_NORMAL(pd_8021q->parent, ps_8021q->parent);
+        } else {
+            CHARS_MERGE_MOVE(pd_8021q->parent, ps_8021q->parent);
+        }
+    }
+}
+
+static void br_prop_merge(BR_Prop *pdest, BR_Prop *psrc, int style)
+{
+    int i;
+
+    if (style == 0) {
+        CHARS_MERGE_NORMAL(pdest->bridge_id, psrc->bridge_id);
+        /*merge it when dest have not been set */
+        if (pdest->port_names == NULL) {
+            SAFE_PSTR_ARRAY_DUP(pdest->port_names, pdest->port_num,
+                                psrc->port_names, psrc->port_num, i);
+        }
+    } else {
+        CHARS_MERGE_MOVE(pdest->bridge_id, psrc->bridge_id);
+        /*merge it when dest have not been set */
+        if (pdest->port_names == NULL) {
+            pdest->port_names = psrc->port_names;
+            pdest->port_num = psrc->port_num;
+            psrc->port_names = NULL;
+            psrc->port_num = NUM_NOT_GOT;
+        }
+    }
+    NUM_MERGE(pdest->STP, psrc->STP, NUM_NOT_GOT);
+    NUM_MERGE(pdest->type, psrc->type, BR_TYPE_NOT_GOT);
+}
+
+void eth_iface_merge(EthIface *dest, EthIface *src, int style)
+{
+    if (style == 0) {
+        CHARS_MERGE_NORMAL(dest->name, src->name);
+        CHARS_MERGE_NORMAL(dest->dep_ifname, src->dep_ifname);
+        CHARS_MERGE_NORMAL(dest->attach_bridge, src->attach_bridge);
+        CHARS_MERGE_NORMAL(dest->mac, src->mac);
+        CHARS_MERGE_NORMAL(dest->ipv4_prop.ip, src->ipv4_prop.ip);
+        CHARS_MERGE_NORMAL(dest->ipv4_prop.ip_mask, src->ipv4_prop.ip_mask);
+    } else {
+        CHARS_MERGE_MOVE(dest->name, src->name);
+        CHARS_MERGE_MOVE(dest->dep_ifname, src->dep_ifname);
+        CHARS_MERGE_MOVE(dest->attach_bridge, src->attach_bridge);
+        CHARS_MERGE_MOVE(dest->mac, src->mac);
+        CHARS_MERGE_MOVE(dest->ipv4_prop.ip, src->ipv4_prop.ip);
+        CHARS_MERGE_MOVE(dest->ipv4_prop.ip_mask, src->ipv4_prop.ip_mask);
+    }
+
+    /* special case for eth_type*/
+    if (dest->eth_type == ETH_TYPE_NOT_GOT) {
+        dest->eth_type = src->eth_type;
+    } else {
+        if ((src->eth_type & ETH_TYPE_ETHER_ANY) &&
+            (dest->eth_type & ETH_TYPE_ETHER_ANY)) {
+            dest->eth_type |= (src->eth_type & ETH_TYPE_SUB_MASK);
+        }
+    }
+
+    NUM_MERGE(dest->run_prop.rx_bytes, src->run_prop.rx_bytes,
+                                            NUM_NOT_GOT);
+    NUM_MERGE(dest->run_prop.tx_bytes, src->run_prop.tx_bytes,
+                                            NUM_NOT_GOT);
+    NUM_MERGE(dest->run_prop.state, src->run_prop.state, ETH_STATE_NOT_GOT);
+
+    if (src->pbr_prop != NULL) {
+        if (dest->pbr_prop == NULL) {
+            SAFE_MALLOC(dest->pbr_prop, sizeof(BR_Prop));
+            br_prop_init(dest->pbr_prop);
+        }
+    br_prop_merge(dest->pbr_prop, src->pbr_prop, style);
+    }
+
+    if (src->pvlan_prop != NULL) {
+        if (dest->pvlan_prop == NULL) {
+            SAFE_MALLOC(dest->pvlan_prop, sizeof(VLAN_Prop));
+            vlan_prop_init(dest->pvlan_prop, src->pvlan_prop->vlan_type);
+        }
+    vlan_prop_merge(dest->pvlan_prop, src->pvlan_prop, style);
+    }
+
+}
+
+/* compare qos values */
+static int VLAN_Qos_8021q_compare_by_ref(const VLAN_Qos_8021q *pqos,
+                                            const VLAN_Qos_8021q *pref)
+{
+    int ret = 1;
+    int i, j;
+    if (pref->count == NUM_NOT_GOT) {
+        /* do not need to compare*/
+        goto out;
+    }
+    if ((pref->count < 0) || (pref->count > 8)) {
+        ret = 0;
+        goto out;
+    }
+    if ((pqos->count < 0) || (pqos->count > 8)) {
+        ret = 0;
+        goto out;
+    }
+
+    i = 0;
+    while (i < pref->count) {
+        j = 0;
+        while (j < pqos->count) {
+            if (pref->values[i].from == pqos->values[j].from) {
+                if (pref->values[i].to != pqos->values[j].to) {
+                    ret = 0;
+                    goto out;
+                }
+                break;
+            }
+            j++;
+        }
+        if (j == pqos->count) {
+            ret = 0;
+            goto out;
+        }
+        i++;
+    }
+
+ out:
+    return ret;
+}
+
+static int vlan_prop_filter_by_ref(const VLAN_Prop *pvlan_prop, void *pref)
+{
+    int compare_result = 1;
+    VLAN_Prop *ref = (VLAN_Prop *)pref;
+    char *p1, *p2;
+    const VLAN_Prop_8021q *pd_8021q;
+    VLAN_Prop_8021q *pref_8021q;
+
+    NUM_COMPARE_BY_REF(pvlan_prop->vlan_type, ref->vlan_type,
+                        compare_result, VLAN_TYPE_NOT_GOT);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    if (ref->vlan_type == VLAN_TYPE_802_1_Q) {
+        pd_8021q = &(pvlan_prop->props.prop_8021q);
+        pref_8021q = &(ref->props.prop_8021q);
+
+        NUM_COMPARE_BY_REF(pd_8021q->vlan_id, pref_8021q->vlan_id,
+                        compare_result, NUM_NOT_GOT);
+        if (compare_result == 0) {
+            goto out;
+        }
+
+        NUM_COMPARE_BY_REF(pd_8021q->reorder_hdr, pref_8021q->reorder_hdr,
+                        compare_result, NUM_NOT_GOT);
+        if (compare_result == 0) {
+            goto out;
+        }
+
+        NUM_COMPARE_BY_REF(pd_8021q->priv_flag, pref_8021q->priv_flag,
+                        compare_result, NUM_NOT_GOT);
+        if (compare_result == 0) {
+            goto out;
+        }
+
+        compare_result = VLAN_Qos_8021q_compare_by_ref(&(pd_8021q->ingress),
+                                                       &(pref_8021q->ingress));
+        if (compare_result == 0) {
+            goto out;
+        }
+
+        compare_result = VLAN_Qos_8021q_compare_by_ref(&(pd_8021q->egress),
+                                                       &(pref_8021q->egress));
+        if (compare_result == 0) {
+            goto out;
+        }
+
+        p1 = pd_8021q->parent;
+        p2 = pref_8021q->parent;
+        CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+        if (compare_result == 0) {
+            goto out;
+        }
+    }
+
+ out:
+    return compare_result;
+
+}
+
+static int br_prop_filter_by_ref(const BR_Prop *pbr_prop, void *pref)
+{
+    int compare_result = 1;
+    BR_Prop *ref = (BR_Prop *)pref;
+    char *p1, *p2;
+
+    p1 = pbr_prop->bridge_id;
+    p2 = ref->bridge_id;
+    CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    NUM_COMPARE_BY_REF(pbr_prop->STP, ref->STP,
+                        compare_result, NUM_NOT_GOT);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    NUM_COMPARE_BY_REF(pbr_prop->type, ref->type,
+                        compare_result, BR_TYPE_NOT_GOT);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    NUM_COMPARE_BY_REF(pbr_prop->port_num, ref->port_num,
+                        compare_result, NUM_NOT_GOT);
+    /* skip the comparation of ports it attached, user can define
+    a special filter for that */
+ out:
+    return compare_result;
+}
+
+int eth_iface_filter_by_ref(const EthIface *piface, void *pref)
+{
+    int compare_result = 1;
+    EthIface *ref = (EthIface *)pref;
+    char *p1, *p2;
+
+    p1 = piface->name;
+    p2 = ref->name;
+    CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    p1 = piface->dep_ifname;
+    p2 = ref->dep_ifname;
+    CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    p1 = piface->attach_bridge;
+    p2 = ref->attach_bridge;
+    CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    p1 = piface->mac;
+    p2 = ref->mac;
+    CHARS_COMPARE_CASE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    /* special case for eth_type */
+    NUM_COMPARE_BY_REF((piface->eth_type & ETH_TYPE_BASE_MASK),
+                       (ref->eth_type & ETH_TYPE_BASE_MASK),
+                        compare_result, ETH_TYPE_NOT_GOT);
+    if (compare_result == 0) {
+        goto out;
+    }
+    NUM_COMPARE_BY_REF((piface->eth_type & ETH_TYPE_SUB_MASK),
+                       (ref->eth_type & ETH_TYPE_SUB_MASK),
+                        compare_result, ETH_TYPE_NOT_GOT);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    p1 = piface->ipv4_prop.ip;
+    p2 = ref->ipv4_prop.ip;
+    CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    p1 = piface->ipv4_prop.ip_mask;
+    p2 = ref->ipv4_prop.ip_mask;
+    CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    NUM_COMPARE_BY_REF(piface->run_prop.state, ref->run_prop.state,
+                        compare_result, ETH_STATE_NOT_GOT);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+    if (ref->pbr_prop != NULL) {
+        if (piface->pbr_prop != NULL) {
+            compare_result = br_prop_filter_by_ref(piface->pbr_prop,
+                                                ref->pbr_prop);
+        } else {
+            compare_result = 0;
+        }
+        if (compare_result == 0) {
+            goto out;
+        }
+    }
+
+    if (ref->pvlan_prop != NULL) {
+        if (piface->pvlan_prop != NULL) {
+            compare_result = vlan_prop_filter_by_ref(piface->pvlan_prop,
+                                                ref->pvlan_prop);
+
+        } else {
+            compare_result = 0;
+        }
+        if (compare_result == 0) {
+            goto out;
+        }
+    }
+
+ out:
+    return compare_result;
+}
+
+int eth_iface_filter_by_refname(const EthIface *piface, void *pref)
+{
+    int compare_result = 1;
+    EthIface *ref = (EthIface *)pref;
+    char *p1, *p2;
+
+    p1 = piface->name;
+    p2 = ref->name;
+    CHARS_COMPARE_BY_REF(p1, p2, compare_result);
+    if (compare_result == 0) {
+        goto out;
+    }
+
+ out:
+    return compare_result;
+}
+
+int eth_iface_filter_vlans(const EthIface *piface, void *nouse)
+{
+    if (piface->name == NULL) {
+        return 0;
+    }
+    if (NULL == strstr(piface->name, ".")) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
+
+/* the judgement condition is weak, but I can't find a better way */
+int eth_iface_filter_peths(const EthIface *piface, void *nouse)
+{
+    if (piface->name == NULL) {
+        return 0;
+    }
+    if (NULL == strstr(piface->name, ".")) {
+        if (0 == strncmp(piface->name, "eth", 3)) {
+            return 1;
+        } else {
+            return 0;
+        }
+    } else {
+        return 0;
+    }
+}
diff --git a/libnetwork/host_network_basic.h b/libnetwork/host_network_basic.h
new file mode 100644
index 0000000..bb92453
--- /dev/null
+++ b/libnetwork/host_network_basic.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+#ifndef NETWORK_BASIC_HOST_H
+#define NETWORK_BASIC_HOST_H
+
+#include "dll_magic.h"
+
+/* value defines */
+#define MAX_IFACE_NUM 4096
+
+#define NUM_NOT_GOT -1
+
+typedef enum {
+    ETH_STATE_NOT_GOT = NUM_NOT_GOT,
+    ETH_STATE_UNKNOWN = 0,
+    ETH_STATE_DOWN = 1,
+    ETH_STATE_UP = 2
+} EthState;
+
+#define ETH_TYPE_BASE_MASK 0xff00
+#define ETH_TYPE_SUB_MASK 0x00ff
+typedef enum {
+    ETH_TYPE_NOT_GOT = 0x0000,
+    ETH_TYPE_UNKNOWN = 0x0100,
+    ETH_TYPE_OTHER = 0x0200,
+    ETH_TYPE_ETHER_ANY = 0x0400,
+    ETH_TYPE_ETHER_SUB_PHYSICAL = 0x0001,
+    ETH_TYPE_ETHER_SUB_BRIDGE = 0x0002,
+    ETH_TYPE_ETHER_SUB_VLAN = 0x0004
+} EthType;
+
+typedef enum {
+    BR_TYPE_NOT_GOT = NUM_NOT_GOT,
+    BR_TYPE_UNKNOWN = 0,
+    BR_TYPE_SWITCH = 1,
+    BR_TYPE_NAT = 2
+} BrType;
+
+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;
+
+/* structure defines */
+typedef struct IPV4_Prop {
+    char *ip;
+    char *ip_mask;
+} IPV4_Prop;
+
+typedef struct BR_Prop {
+    char *bridge_id;
+    int STP;
+    BrType type;
+    char **port_names;
+    int port_num;
+} BR_Prop;
+
+typedef struct Run_Prop {
+    long long rx_bytes;
+    long long tx_bytes;
+    EthState state;
+} Run_Prop;
+
+typedef struct VLAN_Qos_8021q_elem {
+    int from;
+    int to;
+} VLAN_Qos_8021q_elem;
+
+typedef struct VLAN_Qos_8021q {
+    VLAN_Qos_8021q_elem values[8];
+    int count;
+} VLAN_Qos_8021q;
+
+typedef struct VLAN_Prop_8021q {
+    int vlan_id;
+    int reorder_hdr;
+    int priv_flag;
+    VLAN_Qos_8021q ingress;
+    VLAN_Qos_8021q egress;
+    char *parent;
+} VLAN_Prop_8021q;
+
+/* HP vlan standard, TBD */
+typedef struct VLAN_Prop_8021qbg {
+    int invalid;
+} VLAN_Prop_8021qbg;
+
+/* Cisco and VMware vlan standard, TBD */
+typedef struct VLAN_Prop_8021qbh {
+    int invalid;
+} VLAN_Prop_8021qbh;
+
+typedef struct VLAN_Prop {
+    int vlan_type;
+    union {
+        VLAN_Prop_8021q prop_8021q;
+        VLAN_Prop_8021qbg prop_8021qbg;
+        VLAN_Prop_8021qbh prop_8021qbh;
+    } props;
+} VLAN_Prop;
+
+/* EthIface is logical devices include eth ports and bridges */
+typedef struct EthIface {
+    char *name;
+    char *dep_ifname; /* parent dev name */
+    char *attach_bridge; /* bridge the iface is attached to */
+    char *mac;
+    EthType eth_type;
+    Run_Prop run_prop;
+    IPV4_Prop ipv4_prop;
+    /* optional properties */
+    BR_Prop *pbr_prop;
+    VLAN_Prop *pvlan_prop;
+} EthIface;
+
+typedef struct EthIfacesList {
+    EthIface *pifaces[MAX_IFACE_NUM];
+    int count;
+} EthIfacesList;
+
+typedef int (*eth_iface_filter_func)(const EthIface *piface, void *opaque);
+
+/* uninit functions are only called when there is resource malloc */
+DLL_PUBLIC void vlan_prop_init(VLAN_Prop *pvlan_prop, int vlan_type);
+DLL_PUBLIC void vlan_prop_uninit(VLAN_Prop *pvlan_prop);
+
+DLL_PUBLIC void br_prop_init(BR_Prop *pbr_prop);
+DLL_PUBLIC void br_prop_uninit(BR_Prop *pbr_prop);
+
+DLL_PUBLIC void eth_iface_print(EthIface *piface);
+DLL_PUBLIC void eth_iface_init(EthIface *piface);
+DLL_PUBLIC void eth_iface_add_br_prop(EthIface *piface);
+DLL_PUBLIC void eth_iface_add_vlan_prop(EthIface *piface,  int vlan_type);
+DLL_PUBLIC void eth_iface_uninit(EthIface *piface);
+DLL_PUBLIC void eth_ifaces_clear(EthIface **ppifaces, int num);
+
+DLL_PUBLIC void eth_ifaceslist_init(EthIfacesList *plist);
+DLL_PUBLIC void eth_ifaceslist_uninit(EthIfacesList *plist);
+DLL_PUBLIC void eth_ifaceslist_print(EthIfacesList *plist);
+
+/* this function assume dest have been uninited if it was used before*/
+DLL_PUBLIC void eth_iface_dup(EthIface *dest, const EthIface *src);
+
+/* see if it is refered to the same device */
+DLL_PUBLIC int eth_iface_compare(const EthIface *p1, const EthIface *p2);
+
+/* merge the properties that dest do not have value set, if style is set to 1,
+   the char* properties was moved instead of copy, safely reduce the memory
+   fragments, but src is modified. */
+DLL_PUBLIC void eth_iface_merge(EthIface *dest, EthIface *src, int style);
+
+DLL_PUBLIC int eth_iface_filter_by_ref(const EthIface *piface, void *pref);
+DLL_PUBLIC int eth_iface_filter_by_refname(const EthIface *piface, void *pref);
+DLL_PUBLIC int eth_iface_filter_vlans(const EthIface *piface, void *nouse);
+DLL_PUBLIC int eth_iface_filter_peths(const EthIface *piface, void *nouse);
+
+
+#endif
diff --git a/libnetwork/host_network_error.h b/libnetwork/host_network_error.h
new file mode 100644
index 0000000..5c38dde
--- /dev/null
+++ b/libnetwork/host_network_error.h
@@ -0,0 +1,31 @@
+#ifndef HOST_NETWORK_ERROR_H
+#define HOST_NETWORK_ERROR_H
+
+#define ERR_REQUEST_NOT_SUPPORT -1
+
+#define ERR_COMMAND_NOT_SET -11
+#define ERR_COMMAND_PIPE_ERR -12
+#define ERR_COMMAND_NOT_SUPPORT -13
+#define ERR_COMMAND_NO_PERMISSION -14
+#define ERR_COMMAND_NO_READY -15
+#define ERR_COMMAND_PARAMETER_WRONG -16
+#define ERR_COMMAND_EXECUTION -17
+
+#define ERR_LIBNETLINK -80
+#define ERR_LIBBR -90
+
+#define ERR_DEVICE_EXCEED_MAXNUM -100
+#define ERR_DEVICE_EXIST -101
+#define ERR_DEVICE_NOT_EXIST -102
+#define ERR_DEVICE_ALREADY_DONE -103
+#define ERR_DEVICE_CONNECT_OTHER -104
+
+#define ERR_FILE_OP_FAIL -125
+#define ERR_FILE_EMPTY  -126
+#define ERR_FILE_TOO_LARGE -127
+#define ERR_FILE_CONT_TOO_LARGE -128
+#define ERR_FILE_LOCK_FAIL -129
+
+#define ERR_PERSIST_NOT_REDHAT -200
+
+#endif
diff --git a/libnetwork/host_network_helper.c b/libnetwork/host_network_helper.c
new file mode 100644
index 0000000..dc9f775
--- /dev/null
+++ b/libnetwork/host_network_helper.c
@@ -0,0 +1,659 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "host_network_helper.h"
+#include "host_network_error.h"
+
+#define CONFIGURE_FILE_MAX_SIZE 2048
+
+#define PIPE_CMD_SUFFIX " 2>&1"
+
+static int g_linux_version = LINUX_UNKNOWN;
+
+static int compare_qos_8021q(const void *p1, const void *p2)
+{
+    const VLAN_Qos_8021q_elem *qos1 = (VLAN_Qos_8021q_elem *)p1;
+    const VLAN_Qos_8021q_elem *qos2 = (VLAN_Qos_8021q_elem *)p2;
+    int ret = 0;
+    if ((qos1->from) > (qos2->from)) {
+        ret = 1;
+    }
+    return ret;
+}
+
+/* it need to be checked see whether these are the conditions */
+int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos)
+{
+    int ret = 1;
+    int i = 0;
+    int last_num = -1;
+    if ((pqos->count < 0) || (pqos->count > 8)) {
+        ret = 0;
+        goto out;
+    } else if (pqos->count == 0) {
+        goto out;
+    }
+    qsort((void *)pqos->values, pqos->count, sizeof(VLAN_Qos_8021q_elem),
+                            compare_qos_8021q);
+
+    while (i < pqos->count) {
+        if (pqos->values[i].from == last_num) {
+            CU_DEBUG("error: vlan 802.1.q qos setting have same <from> values: "
+                     "last is %d, new is %d", last_num, pqos->values[i].from);
+            ret = 0;
+            goto out;
+        }
+        last_num = pqos->values[i].from;
+        if ((pqos->values[i].from < 0) || (pqos->values[i].from >= 8)) {
+            CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
+                     "from is %d.", pqos->values[i].from);
+            ret = 0;
+            goto out;
+        }
+        if ((pqos->values[i].to < 0) || (pqos->values[i].to >= 8)) {
+            CU_DEBUG("error: vlan 802.1.q qos setting have outbound value: "
+                     "to is %d.", pqos->values[i].to);
+            ret = 0;
+            goto out;
+        }
+        i++;
+    }
+
+ out:
+    return ret;
+}
+
+int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char* str)
+{
+    int ret = 1;
+    char *str_line = NULL;
+    char *temp;
+    char *saveptr = NULL;
+    char *invalptr1, *invalptr2;
+    int qos_num1, qos_num2;
+    VLAN_Qos_8021q qos;
+
+    if (str == NULL) {
+        ret = 0;
+        goto out;
+    }
+    if (str[0] == '\0') {
+        ret = 1;
+        pqos->count = 0;
+        CU_DEBUG("empty vlan 802.1.q qos string found.");
+        goto out;
+    }
+    str_line = SAFE_STRDUP(str);
+    qos.count = 0;
+
+    temp = strtok_r(str_line, " ", &saveptr);
+    while (temp != NULL) {
+        qos_num1 = strtol(temp, &invalptr1, 10);
+        if (temp == invalptr1) {
+            ret = 0;
+            goto out;
+        }
+        if (*invalptr1 != ':') {
+            ret = 0;
+            goto out;
+        }
+        invalptr1++;
+        qos_num2 = strtol(invalptr1, &invalptr2, 10);
+        if (invalptr1 == invalptr2) {
+            ret = 0;
+            goto out;
+        }
+        if (*invalptr2 != '\0') {
+            ret = 0;
+            goto out;
+        }
+        if (qos.count >= 8) {
+            ret = 0;
+            CU_DEBUG("too many settings found in vlan 802.1.q qos string [%s]",
+                        str);
+            goto out;
+        }
+        qos.values[qos.count].from = qos_num1;
+        qos.values[qos.count].to = qos_num2;
+        qos.count++;
+        temp = strtok_r(NULL, " ", &saveptr);
+    }
+    ret = vlan_8021q_qos_check_valid(&qos);
+    if (ret == 1) {
+        *pqos = qos;
+    }
+
+ out:
+    if (ret != 1) {
+        CU_DEBUG("vlan 802.1.q qos string [%s] is invalid.", str);
+    }
+    SAFE_FREE(str_line);
+    return ret;
+}
+
+int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos)
+{
+    char temp[16];
+    int i;
+    VLAN_Qos_8021q qos = *pqos;
+    int ret = vlan_8021q_qos_check_valid(&qos);
+    if (ret != 1) {
+        goto out;
+    }
+    SAFE_MALLOC(*str, 64);
+    *str[0] = '\0';
+    if (qos.count == 0) {
+        goto out;
+    }
+    i = 0;
+    snprintf(temp, sizeof(temp), "%d:%d",
+            qos.values[i].from, qos.values[i].to);
+    strcat(*str, temp);
+    i++;
+    while (i < qos.count) {
+        strcat(*str, " ");
+        snprintf(temp, sizeof(temp), "%d:%d",
+                qos.values[i].from, qos.values[i].to);
+        strcat(*str, temp);
+        i++;
+    }
+
+ out:
+    return ret;
+}
+
+int netmask_easy_to_inaddr(struct in_addr *paddr, const char* pmask)
+{
+    long mask_one_num = -1;
+    unsigned char *p;
+    int bitnum;
+
+    mask_one_num = strtol(pmask, NULL, 10);
+    if ((mask_one_num < 0) || (mask_one_num > 32)) {
+        return 0;
+    }
+
+    /* use network byte order */
+    p = (unsigned char *)&paddr->s_addr;
+    memset(p, 0, 4);
+    while (mask_one_num > 8) {
+        *(p++) = 255;
+        mask_one_num -= 8;
+    }
+    bitnum = 7;
+    while (mask_one_num > 0) {
+        *p = *p + (1<<bitnum);
+        mask_one_num--;
+        bitnum--;
+    }
+    return 1;
+}
+
+char *strtok_onetime(const char *str, const char *delim)
+{
+    char *t = strstr(str, delim);
+    char *ret_char;
+    int len;
+    if (t == NULL) {
+        return NULL;
+    }
+    len = t - str;
+    if (len <= 0) {
+        return NULL;
+    }
+    SAFE_MALLOC(ret_char, len+1);
+    strncpy(ret_char, str, len);
+    ret_char[len] = '\0';
+
+    return ret_char;
+}
+
+char *combine_file_name(const char *prefix, const char *name)
+{
+    char *ret = NULL;
+    int size;
+    size = strlen(prefix) + strlen(name) + 1;
+    SAFE_CALLOC(ret, size, sizeof(char));
+    snprintf(ret, size, "%s%s", prefix, name);
+    return ret;
+}
+
+/* return the whole content length that need update. The data length keep
+   unchanged in the head part is returned in *unchanged_len which could be
+   used to avoid write whole data later.
+   requriement: cont must contain end character, prefix must be not NULL */
+static int replace_prop_str(char *cont, const int maxsize, const char *prefix,
+                            const char *prop, int *unchanged_len)
+{
+    int target_len, origin_len;
+    int cont_len;
+    int valid_len = 0;
+    int prefix_len, prop_len = 0;
+    char *endchar1 = "\n";
+    char *pprop_start, *pprop_end;
+    int head_len;
+
+    cont_len = strlen(cont);
+    head_len = cont_len;
+    prefix_len = strlen(prefix);
+    if ((prop == NULL) || (*prop == '\0')) {
+        /* want the property removed */
+        target_len = 0;
+    } else {
+        /* want the property changed */
+        prop_len = strlen(prop);
+        target_len = prefix_len + prop_len;
+    }
+
+    pprop_start = strstr(cont, prefix);
+    if (pprop_start == NULL) {
+        /* the content do not exist in original contents */
+        if (target_len > 0) {
+            /* add the property */
+            if ((cont_len + target_len) >= maxsize) {
+                CU_DEBUG("buffer is too small for the operation.");
+                valid_len = -1;
+                goto out;
+            }
+            strcat(cont, prefix);
+            strcat(cont, prop);
+            valid_len = cont_len + target_len;
+        } else {
+           /* remove the property, but it do not exist, so skip */
+        }
+    } else {
+        /* the content exist in original contents */
+        /* locate the end of the property */
+        pprop_end = strstr(pprop_start, endchar1);
+        if (pprop_end == NULL) {
+            /* last line */
+            origin_len = strlen(pprop_start);
+            pprop_end = cont+cont_len;
+        } else {
+            origin_len = pprop_end - pprop_start;
+        }
+        if (target_len > 0) {
+            /* change the property */
+            /* check the bound */
+            if ((cont_len + target_len - origin_len) >= maxsize) {
+                CU_DEBUG("buffer is too small for the operation.");
+                valid_len = -1;
+                goto out;
+            }
+            /* move contents in the tail */
+            memmove(pprop_end+target_len-origin_len, pprop_end,
+                        cont+cont_len+1-pprop_end);
+            /* copy the content of the new string */
+            memcpy(pprop_start+prefix_len, prop, prop_len);
+            head_len = pprop_start - cont + prefix_len;
+        } else {
+           /* remove the property */
+           /* move contents in the tail to replace original string*/
+            memmove(pprop_end+target_len-origin_len, pprop_end,
+                        cont+cont_len+1-pprop_end);
+            head_len = pprop_start - cont;
+        }
+        valid_len = cont_len + target_len - origin_len;
+    }
+
+ out:
+    if (unchanged_len != NULL) {
+        *unchanged_len = head_len;
+    }
+    return valid_len;
+}
+
+int configure_file_replace_attr(const char *path, const char *prefix,
+                                    const char *prop)
+{
+    int fd = -1;
+    int fop_ret;
+    struct stat s;
+    struct flock lock;
+    int lock_state = -1;
+    char *cont = NULL;
+    char *pbuff;
+    int write_len;
+    int cont_len_update;
+    int cont_len_unchanged;
+    int ret = 0;
+
+    if ((prefix == NULL) || (*prefix == '\0')) {
+        CU_DEBUG("no prefix for property set, could not replace the content.");
+        goto out;
+    }
+
+    fd = open(path, O_RDWR, 0644);
+    if (fd < 0) {
+        CU_DEBUG("Unable to open [%s], it does not exist.", path);
+        ret = ERR_FILE_OP_FAIL;
+        goto out;
+    }
+
+    lock.l_type = F_WRLCK;
+    lock.l_start = 0;
+    lock.l_whence = SEEK_SET;
+    lock.l_len = 0;
+    lock_state = fcntl(fd, F_SETLK, &lock);
+    if (lock_state < 0) {
+        CU_DEBUG("Failed to lock file [%s], it may be locked by other.", path);
+        ret = ERR_FILE_LOCK_FAIL;
+        goto out;
+    }
+
+    fstat(fd, &s);
+    if (s.st_size == 0) {
+        CU_DEBUG("file [%s] is empty, will not replace attr for it.", path);
+        ret = ERR_FILE_EMPTY;
+        goto out;
+    } else if (s.st_size >= CONFIGURE_FILE_MAX_SIZE) {
+        CU_DEBUG("file [%s] is too large, "
+                 "it have %lld bytes, will not read it.",
+                 path, (long long)s.st_size);
+        ret = ERR_FILE_TOO_LARGE;
+        goto out;
+    }
+
+    SAFE_MALLOC(cont, CONFIGURE_FILE_MAX_SIZE);
+    lseek(fd, 0, SEEK_SET);
+    fop_ret = read(fd, cont, s.st_size);
+    cont[s.st_size] = '\0';
+    cont_len_update = replace_prop_str(cont, CONFIGURE_FILE_MAX_SIZE,
+                                            prefix, prop, &cont_len_unchanged);
+    if (cont_len_update < 0) {
+        CU_DEBUG("file [%s] is too big to expand it with [%s%s].",
+                        path, prefix, prop);
+        ret = ERR_FILE_TOO_LARGE;
+        goto out;
+    } else if (cont_len_update == 0) {
+        CU_DEBUG("the contents was not changed, do not need update it");
+        ret = 1;
+        goto out;
+    } else {
+        if (ftruncate(fd, cont_len_unchanged) != 0) {
+            CU_DEBUG("file [%s] Unable to truncate it", path);
+            ret = ERR_FILE_OP_FAIL;
+            goto out;
+        }
+        write_len = cont_len_update-cont_len_unchanged;
+        if (write_len > 0) {
+            lseek(fd, cont_len_unchanged, SEEK_SET);
+            CU_DEBUG("writing file [%s] for %d bytes with offset %d,"
+                        " cont is :\n%s\n",
+                    path, write_len, cont_len_unchanged, cont);
+            pbuff = cont+cont_len_unchanged;
+            fop_ret = write(fd, pbuff, write_len);
+        }
+    }
+    ret = 1;
+
+ out:
+    if (fd >= 0) {
+        if (lock_state >= 0) {
+            lock.l_type = F_UNLCK;
+            fcntl(fd, F_SETLK, &lock);
+        }
+        close(fd);
+    }
+    SAFE_FREE(cont);
+    return ret;
+}
+
+int configure_file_update(const char *path, const char *cont)
+{
+    int fd = -1;
+    int fop_ret;
+    struct flock lock;
+    int lock_state = -1;
+    int write_len;
+    int ret = 0;
+
+    fd = open(path, O_RDWR|O_CREAT, 0644);
+    if (fd < 0) {
+        CU_DEBUG("Unable to open [%s], it does not exist.", path);
+        ret = ERR_FILE_OP_FAIL;
+        goto out;
+    }
+
+    lock.l_type = F_WRLCK;
+    lock.l_start = 0;
+    lock.l_whence = SEEK_SET;
+    lock.l_len = 0;
+    lock_state = fcntl(fd, F_SETLK, &lock);
+    if (lock_state < 0) {
+        CU_DEBUG("Failed to lock file [%s], it may be locked by other.", path);
+        ret = ERR_FILE_LOCK_FAIL;
+        goto out;
+    }
+
+    if (ftruncate(fd, 0) != 0) {
+        CU_DEBUG("file [%s] Unable to truncate it", path);
+        ret = ERR_FILE_OP_FAIL;
+        goto out;
+    }
+
+    write_len = strlen(cont);
+    if (write_len > 0) {
+        lseek(fd, 0, SEEK_SET);
+        CU_DEBUG("writing file [%s] for %d bytes with offset 0,"
+                    " cont is :\n%s\n",
+                    path, write_len, cont);
+        fop_ret = write(fd, cont, write_len);
+    }
+    ret = 1;
+
+ out:
+    if (fd >= 0) {
+        if (lock_state >= 0) {
+            lock.l_type = F_UNLCK;
+            fcntl(fd, F_SETLK, &lock);
+        }
+        close(fd);
+    }
+    return ret;
+}
+
+int configure_file_remove(const char *path)
+{
+    int fd_ret;
+    int ret = 0;
+    if (access(path, F_OK) == 0) {
+        CU_DEBUG("Deleting %s.", path);
+        fd_ret = remove(path);
+        if (fd_ret != 0) {
+            CU_DEBUG("failed to remove %s.", path);
+            ret = ERR_FILE_OP_FAIL;
+            goto out;
+        }
+    }
+
+    ret = 1;
+ out:
+    return ret;
+}
+
+FILE *pipe_excute_command_type_read(char *cmd, const int buf_size,
+                                    const char *type, int *errno)
+{
+    FILE *stream = NULL;
+    char *suffix = PIPE_CMD_SUFFIX;
+    if ((strlen(cmd) + strlen(suffix)) >= buf_size) {
+        CU_DEBUG("cmd [%s] is too long to append the suffix", cmd);
+        *errno = ERR_COMMAND_NO_READY;
+        goto out;
+    }
+    strcat(cmd, suffix);
+    CU_DEBUG("excuting readonly cmd [%s].", cmd);
+    stream = popen(cmd, type);
+    if (stream == NULL) {
+        CU_DEBUG("Failed to open pipe to run command");
+        *errno = ERR_COMMAND_PIPE_ERR;
+    }
+
+out:
+    return stream;
+}
+
+FILE *pipe_excute_command_type_write(char *cmd, const int buf_size,
+                                     const char *type, int *errno)
+{
+    FILE *stream = NULL;
+    char *suffix = PIPE_CMD_SUFFIX;
+    if ((strlen(cmd) + strlen(suffix)) >= buf_size) {
+        CU_DEBUG("cmd [%s] is too long to append the suffix", cmd);
+        *errno = ERR_COMMAND_NO_READY;
+        goto out;
+    }
+    strcat(cmd, suffix);
+    CU_DEBUG("excuting system modification cmd [%s].", cmd);
+    stream = popen(cmd, type);
+    if (stream == NULL) {
+        CU_DEBUG("Failed to open pipe to run command");
+        *errno = ERR_COMMAND_PIPE_ERR;
+    }
+    usleep(10000);
+
+out:
+    return stream;
+}
+
+int get_host_linux_version(void)
+{
+    FILE *stream = NULL;
+    char cmd[64];
+    char buff[256];
+    int linenum;
+    int errno;
+
+    if (g_linux_version != LINUX_UNKNOWN) {
+        goto out;
+    }
+
+    cmd[0] = '\0';
+    strcat(cmd, "lsb_release -a");
+    stream = pipe_excute_command_type_read(cmd, sizeof(cmd), "r", &errno);
+    if (stream == NULL) {
+        goto out;
+    }
+
+    linenum = -1;
+    g_linux_version = LINUX_OTHER;
+    while (fgets(buff, 256, stream) != NULL) {
+        linenum++;
+        if (linenum == 0) {
+            if (NULL == strstr(buff, "LSB")) {
+                CU_DEBUG("ERR: unable to get linux distribution version.");
+                g_linux_version = LINUX_FAIL_TO_GET;
+            }
+        }
+        if ((NULL != strstr(buff, "Red Hat")) ||
+            (NULL != strstr(buff, "RedHat"))) {
+            g_linux_version = LINUX_REDHAT;
+            break;
+        }
+    }
+
+ out:
+    if (stream != NULL) {
+        pclose(stream);
+    }
+    return g_linux_version;
+}
+
+char *translate_error_no(int errno)
+{
+    char *ret = NULL;
+    switch (errno) {
+    case ERR_REQUEST_NOT_SUPPORT:
+        ret = "request is not supported now";
+        break;
+
+    case ERR_COMMAND_NOT_SET:
+        ret = "command is not set.";
+        break;
+    case ERR_COMMAND_PIPE_ERR:
+        ret = "failed in creating pipe to execute the command.";
+        break;
+    case ERR_COMMAND_NOT_SUPPORT:
+        ret = "command is not found, check u environment.";
+        break;
+    case ERR_COMMAND_NO_PERMISSION:
+        ret = "not enough authority to execute the command.";
+        break;
+    case ERR_COMMAND_NO_READY:
+        ret = "failed to build up the command line, check your input, "
+              "maybe it is too long.";
+        break;
+    case ERR_COMMAND_PARAMETER_WRONG:
+        ret = "got invalid paramenter, check your input.";
+        break;
+    case ERR_COMMAND_EXECUTION:
+        ret = "error happened in the excution of command.";
+        break;
+
+    case ERR_DEVICE_EXCEED_MAXNUM:
+        ret = "too many devices found or set, check the environment.";
+        break;
+    case ERR_DEVICE_EXIST:
+        ret = "device already exist, can not execute the command.";
+        break;
+    case ERR_DEVICE_NOT_EXIST:
+        ret = "device do not exist, can not execute the command.";
+        break;
+    case ERR_DEVICE_ALREADY_DONE:
+        ret = "the operation you want have been done before, "
+                "will not do it again.";
+        break;
+    case ERR_DEVICE_CONNECT_OTHER:
+        ret = "the device you want to connect have been connect to another"
+              " device, can't change it directly.";
+        break;
+
+    case ERR_FILE_OP_FAIL:
+        ret = "failed in accessing the file.";
+        break;
+    case ERR_FILE_EMPTY:
+        ret = "the file it want is empty.";
+        break;
+    case ERR_FILE_TOO_LARGE:
+        ret = "the file it want is too large.";
+        break;
+    case ERR_FILE_CONT_TOO_LARGE:
+        ret = "the content it want to combine to file is too large.";
+        break;
+    case ERR_FILE_LOCK_FAIL:
+        ret = "failed in locking the file, "
+                    "check if other process is using it.";
+        break;
+
+    case ERR_PERSIST_NOT_REDHAT:
+        ret = "host is not a RedHat distribution, can't persist the "
+             "configuration, it would not take effect after host is "
+             "rebooted. Other version would be supported in the future. "
+             "If you are sure host is RedHat, make sure command "
+             "<lsb_release -a> could work.";
+        break;
+
+    default:
+        ret = "internal error.";
+        break;
+    }
+    return ret;
+}
diff --git a/libnetwork/host_network_helper.h b/libnetwork/host_network_helper.h
new file mode 100644
index 0000000..4170366
--- /dev/null
+++ b/libnetwork/host_network_helper.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+
+#ifndef HOST_NETWORK_HELPER_H
+#define HOST_NETWORK_HELPER_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+
+#include "dll_magic.h"
+#include "host_network_basic.h"
+
+#ifdef TESTLIB
+#include "TestDefines.h"
+#else
+#include <libcmpiutil/libcmpiutil.h>
+#endif
+
+#define LINUX_FAIL_TO_GET -2
+#define LINUX_UNKNOWN -1
+#define LINUX_OTHER 0
+#define LINUX_REDHAT 1
+
+#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; }
+
+
+/* Macro used to compare two char*, it would skip if ref is NULL. It would
+   only set the result when src != ref, user need to set the result to 1 by
+   default before use the macro. If not set, the it could be used to do
+   check multi times in "one fail all die" mode. Empty lines is the place
+   where result should be set to 1. */
+#define CHARS_COMPARE_BY_REF(src, ref, result) do { \
+    if ((ref) == NULL) { \
+        ; \
+    } else { \
+        if ((src) == NULL) { \
+            (result) = 0; \
+        } else { \
+            if (0 == strcmp((src), (ref))) { \
+                ; \
+            } else { \
+                (result) = 0; \
+            } \
+        } \
+    } \
+} while (0)
+
+/* ignore case version */
+#define CHARS_COMPARE_CASE_BY_REF(src, ref, result) do { \
+    if ((ref) == NULL) { \
+        ; \
+    } else { \
+        if ((src) == NULL) { \
+            (result) = 0; \
+        } else { \
+            if (0 == strcasecmp((src), (ref))) { \
+                ; \
+            } else { \
+                (result) = 0; \
+            } \
+        } \
+    } \
+} while (0)
+
+/* compare the value if ref != default */
+#define NUM_COMPARE_BY_REF(src, ref, result, default) do { \
+    if ((ref) == (default)) { \
+        ; \
+    } else { \
+        if ((src) == (ref)) { \
+            ; \
+        } else { \
+            result = 0; \
+        } \
+    } \
+} while (0)
+
+/* merge the char* string to dest, only when dest == NULL */
+#define CHARS_MERGE_NORMAL(dest, src) do { \
+    if (((dest) == NULL) && ((src) != NULL)) { \
+        (dest) = strdup((src)); \
+    } \
+} while (0)
+
+/* merge the char* string to dest, only when dest == NULL,
+   pointer is moved instead of strdup */
+#define CHARS_MERGE_MOVE(dest, src) do { \
+    if (((dest) == NULL) && ((src) != NULL)) { \
+        (dest) = (src); \
+        (src) = NULL; \
+    } \
+} while (0)
+
+/* merge the value, only when dest == default */
+#define NUM_MERGE(dest, src, default) do { \
+    if ((dest) == (default)) { \
+        (dest) = (src); \
+    } \
+} while (0)
+
+/* this macro may cause "p" to be excuted twice if it is a function */
+#define SAFE_STRDUP(p) (p) == NULL ? NULL : strdup(p);
+
+/* this macro make sure "src" to be excuted once if it is function, so it is
+   safe for functions that have state logged, such as "strtok" */
+#define SAFE_STRDUP_WITH_FUNC(dest, src, iter) do { \
+    (iter) = (src); \
+    if ((iter) == NULL) { \
+        (dest) = NULL; \
+    } else { \
+       (dest) = strdup((iter)); \
+    } \
+} while (0)
+
+/* array version of SAFE_STRDUP, dest and src are char**. */
+#define SAFE_PSTR_ARRAY_DUP(ppdest, dest_num, ppsrc, src_num, iter) do { \
+    (dest_num) = (src_num); \
+    (ppdest) = NULL; \
+    if (((ppsrc) != NULL) && ((src_num) > 0)) { \
+        SAFE_CALLOC((ppdest), (src_num), sizeof(char *)); \
+        (iter) = 0; \
+        while ((iter) < (src_num)) { \
+            *((ppdest)+(iter)) = SAFE_STRDUP(*((ppsrc)+(iter))); \
+            (iter)++; \
+        } \
+    } \
+} while (0)
+
+/* functions */
+/* this function convert ip mask "24" in "192.1.0.9/24" to real mask num as
+    255.255.255.0 */
+int netmask_easy_to_inaddr(struct in_addr *paddr, const char *pmask);
+
+/* this function would sort the pqos and check its values. */
+int vlan_8021q_qos_check_valid(VLAN_Qos_8021q *pqos);
+
+/* converting qos string of 802.1.Q, it should be as "0:0 1:0 2:0" */
+DLL_PUBLIC int vlan_8021q_qos_str_to_num(VLAN_Qos_8021q *pqos, const char *str);
+DLL_PUBLIC int vlan_8021q_qos_num_to_str(char **str, const VLAN_Qos_8021q *pqos);
+
+/* following functions would return FILE popened, so it need pclose later,
+   cmd would be appended so it must be writable. */
+FILE *pipe_excute_command_type_read(char *cmd, const int buf_size,
+                                    const char *type, int *errno);
+FILE *pipe_excute_command_type_write(char *cmd, const int buf_size,
+                                    const char *type, int *errno);
+
+/* following functions would return string by malloc, so it need free later */
+char *strtok_onetime(const char *str, const char *delim);
+char *combine_file_name(const char *prefix, const char *name);
+
+/* write the configuration file */
+int configure_file_update(const char *path, const char *cont);
+/* remove the configuration file */
+int configure_file_remove(const char *path);
+/* replace one attribute, the file have format with one line for one propety */
+int configure_file_replace_attr(const char *path, const char *prefix,
+                                    const char *prop);
+
+/* check host linux version */
+int get_host_linux_version(void);
+
+/* err message number to char* */
+char *translate_error_no(int errno);
+
+#endif
diff --git a/libnetwork/host_network_implement_OSAPI.c b/libnetwork/host_network_implement_OSAPI.c
new file mode 100644
index 0000000..24b382e
--- /dev/null
+++ b/libnetwork/host_network_implement_OSAPI.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <net/if_arp.h>
+#include <linux/if_vlan.h>
+
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/list.h>
+#include <netlink/object.h>
+#include <netlink/object-api.h>
+#include <netlink/route/link.h>
+#include <netlink/route/link/vlan.h>
+
+#include "libbridge/libbridge.h"
+
+#include "host_network_implement_OSAPI.h"
+#include "host_network_helper.h"
+#include "host_network_error.h"
+
+/* macro defines */
+#define LN_PRINT_LEVEL 3
+
+struct nl_add2list_param {
+    EthIfacesList *plist;
+    struct nl_cache *cache;
+} ;
+
+/* the bridge seems have 0 value when it is up , so adjust the value,
+   and found out which are physical cards */
+static int host_iface_adjust(EthIface *piface)
+{
+    if ((piface->eth_type & ETH_TYPE_ETHER_ANY) &&
+        (piface->eth_type & ETH_TYPE_ETHER_SUB_BRIDGE)) {
+        if (piface->run_prop.state == ETH_STATE_UNKNOWN) {
+            piface->run_prop.state = ETH_STATE_UP;
+        }
+    }
+    if (1 == eth_iface_filter_peths(piface, NULL)) {
+        piface->eth_type |= (ETH_TYPE_ETHER_ANY | ETH_TYPE_ETHER_SUB_PHYSICAL);
+    }
+    return 1;
+}
+
+static void find_iface_attached_bridge(EthIfacesList *peth_list, EthIface *pbr)
+{
+    int i, j;
+    char *name_on_br, *name_iface;
+    if (pbr->pbr_prop == NULL) {
+        return;
+    }
+    i = 0;
+    while (i < pbr->pbr_prop->port_num) {
+        name_on_br = pbr->pbr_prop->port_names[i];
+        j = 0;
+        while (j < peth_list->count) {
+            name_iface = peth_list->pifaces[j]->name;
+            if (0 == strcmp(name_on_br, name_iface)) {
+                if (peth_list->pifaces[j]->attach_bridge == NULL) {
+                    peth_list->pifaces[j]->attach_bridge =
+                         SAFE_STRDUP(pbr->name);
+                }
+                break;
+            }
+            j++;
+        }
+        i++;
+    }
+}
+
+/* assuming that one peth would be attached to at most 1 bridge */
+static void merge_eth_list_for_bridge(EthIfacesList *peth_list,
+                                      EthIfacesList *pbr_list,
+                                      int flag)
+{
+    int i, j;
+    i = 0;
+    while (i < pbr_list->count) {
+        find_iface_attached_bridge(peth_list, pbr_list->pifaces[i]);
+        j = 0;
+        while (j < peth_list->count) {
+            if (1 == eth_iface_compare(peth_list->pifaces[j],
+                                       pbr_list->pifaces[i])) {
+                /* found the matched device, merge them */
+                eth_iface_merge(peth_list->pifaces[j],
+                                pbr_list->pifaces[i], flag);
+                break;
+            }
+            j++;
+        }
+        i++;
+    }
+    return;
+}
+
+static int br_addports_func(const char *brname, const char *port, void *opaque)
+{
+    BR_Prop *pbr;
+    int ret = 0;
+
+    pbr = (BR_Prop *)opaque;
+
+    if (port != NULL) {
+        /* adding the port */
+        if (pbr->port_names == NULL) {
+            SAFE_CALLOC(pbr->port_names,
+                        MAX_IFACE_NUM, sizeof(char *));
+            pbr->port_num = 0;
+        }
+        if (pbr->port_num >= MAX_IFACE_NUM) {
+            CU_DEBUG("bridge [%s] have too much eth attached!", brname);
+            ret = ERR_DEVICE_EXCEED_MAXNUM;
+            goto out;
+        }
+
+        pbr->port_names[pbr->port_num] = SAFE_STRDUP(port);
+        pbr->port_num++;
+    }
+
+ out:
+    return ret;
+}
+
+static int br_add2list_func(const char *name, void *opaque)
+{
+    int count;
+    EthIfacesList *plist;
+    EthIface tcard;
+    BR_Prop *pbr;
+    struct bridge_info binfo;
+    int ret = 0;
+
+    plist = (EthIfacesList *)opaque;
+    eth_iface_init(&tcard);
+
+    tcard.eth_type = ETH_TYPE_ETHER_ANY | ETH_TYPE_ETHER_SUB_BRIDGE;
+    tcard.name = SAFE_STRDUP(name);
+
+    SAFE_MALLOC(pbr, sizeof(BR_Prop));
+    br_prop_init(pbr);
+    tcard.pbr_prop = pbr;
+
+    if (0 == br_get_bridge_info(name, &binfo)) {
+        pbr->STP = binfo.stp_enabled;
+    } else {
+        CU_DEBUG("failed to get bridge_info for %s.", name);
+    }
+    count = br_foreach_port(name, br_addports_func, pbr);
+
+    /* put result to list */
+    if (plist->count >= MAX_IFACE_NUM) {
+        CU_DEBUG("too much device found.");
+        ret = ERR_DEVICE_EXCEED_MAXNUM;
+        goto out;
+    }
+    SAFE_MALLOC(plist->pifaces[plist->count], sizeof(EthIface));
+    eth_iface_dup(plist->pifaces[plist->count], &tcard);
+    plist->count++;
+
+ out:
+    eth_iface_uninit(&tcard);
+    return ret;
+}
+
+static int get_host_eth_ifaces_osapi_bridge(EthIfacesList *plist)
+{
+    int count;
+    int ret = 0, libret;
+
+    libret = br_init();
+    if (libret != 0) {
+        ret = ERR_LIBBR;
+        CU_DEBUG("erro in init the libbridge, errno is %d.", libret);
+        goto out;
+    }
+
+    count = br_foreach_bridge(br_add2list_func, plist);
+
+    if (plist->count >= MAX_IFACE_NUM) {
+        CU_DEBUG("too much device found.");
+        ret = ERR_DEVICE_EXCEED_MAXNUM;
+        goto out;
+    }
+
+    ret = 1;
+
+ out:
+    br_shutdown();
+    return ret;
+}
+
+static void ln_link_print(struct rtnl_link *link)
+{
+    char *name, *qdisk, *type;
+    const char *ifalias;
+    int  ifindex, flags, mtu, txqlen, family, arptype, getlink, master, operstate, linkmode;
+    uint32_t num_vf = 0;
+    int ret, i;
+    int vlanid, vlanflag, egress_num = 0;
+    uint32_t *ingress_map;
+    struct vlan_map *egress_map;
+
+    qdisk = rtnl_link_get_qdisc(link);
+    name = rtnl_link_get_name(link);
+    flags = rtnl_link_get_flags(link);
+    mtu = rtnl_link_get_mtu(link);
+    txqlen = rtnl_link_get_txqlen(link);
+    ifindex = rtnl_link_get_ifindex(link);
+    family = rtnl_link_get_family(link);
+    arptype = rtnl_link_get_arptype(link);
+    getlink = rtnl_link_get_link(link);
+    master = rtnl_link_get_master(link);
+    operstate = rtnl_link_get_operstate(link);
+    linkmode = rtnl_link_get_linkmode(link);
+    ifalias = rtnl_link_get_ifalias(link);
+    ret = rtnl_link_get_num_vf(link, &num_vf);
+
+    type = rtnl_link_get_type(link);
+    CMD_DEBUG(1, "link name %s, alias %s, qdisk %s, type %s,\n"
+             "--ifindex 0x%x, flags 0x%x, mtu 0x%x, txqlen 0x%x, family 0x%x, arptype 0x%x,\n"
+             "--getlink 0x%x, master 0x%x, operstate 0x%x, linkmode 0x%x, vf_ret %d with num_vf 0x%x.\n",
+              name, ifalias, qdisk, type,
+              ifindex, flags, mtu, txqlen, family, arptype,
+              getlink, master, operstate, linkmode, ret, num_vf);
+
+    if (rtnl_link_is_vlan(link)) {
+        vlanid = rtnl_link_vlan_get_id(link);
+        vlanflag = rtnl_link_vlan_get_flags(link);
+        ingress_map = rtnl_link_vlan_get_ingress_map(link);
+        egress_map = rtnl_link_vlan_get_egress_map(link, &egress_num);
+        CMD_DEBUG(1, "--vlan properties:\n"
+                 "----id %d, vlanflag 0x%x.",
+                 vlanid, vlanflag);
+        CMD_DEBUG(1, "\n----ingress: ");
+        if (ingress_map != NULL) {
+            for (i = 0; i <= VLAN_PRIO_MAX; i++) {
+                CMD_DEBUG(1, "0x%x, ", ingress_map[i]);
+            }
+        }
+        CMD_DEBUG(1, "\n----egress: ");
+        if (egress_map != NULL) {
+            i = 0;
+            while (i < egress_num) {
+                CMD_DEBUG(1, "[%d %d], ", egress_map[i].vm_from, egress_map[i].vm_to);
+                i++;
+            }
+        }
+        CMD_DEBUG(1, "\n");
+    }
+}
+
+static void nl_add2list_func(struct nl_object *obj, void *opaque)
+{
+    struct rtnl_link *link;
+    struct nl_cache *cache;
+    struct rtnl_link *ll;
+    struct nl_addr *addr;
+    uint32_t *ingress_map;
+    int egress_num = 0;
+    struct vlan_map *egress_map;
+    EthIfacesList *plist;
+    EthIface tcard;
+    VLAN_Prop_8021q *pprop_8021q;
+    char buf[128];
+    int t, i;
+
+    struct nl_add2list_param *pparam = (struct nl_add2list_param *)opaque;
+    plist = pparam->plist;
+    cache = pparam->cache;
+    link = (struct rtnl_link *)obj;
+
+    if (CMD_DEBUG_LEVEL && (LN_PRINT_LEVEL) <= CMD_DEBUG_LEVEL) {
+        ln_link_print(link);
+    }
+
+    /* get properties */
+    eth_iface_init(&tcard);
+
+    /* get name */
+    tcard.name = SAFE_STRDUP(rtnl_link_get_name(link));
+
+    /* get parent */
+    t = rtnl_link_get_link(link);
+    if (t > 0) {
+        ll = rtnl_link_get(cache, t);
+        if (ll == NULL) {
+            CU_DEBUG("failed to find interface with index %d.", t);
+            goto out;
+        }
+        tcard.dep_ifname = SAFE_STRDUP(rtnl_link_get_name(ll));
+        rtnl_link_put(ll);
+    }
+
+    /* get mac */
+    addr =rtnl_link_get_addr(link);
+    if (addr && !nl_addr_iszero(addr)) {
+        nl_addr2str(addr, buf, sizeof(buf));
+        tcard.mac = SAFE_STRDUP(buf);
+    }
+
+    /* get main type */
+    t = rtnl_link_get_arptype(link);
+    if (t == ARPHRD_ETHER) {
+        tcard.eth_type = ETH_TYPE_ETHER_ANY;
+    } else {
+        tcard.eth_type = ETH_TYPE_OTHER;
+    }
+
+    /* get vlan */
+    if (rtnl_link_is_vlan(link)) {
+        SAFE_MALLOC(tcard.pvlan_prop, sizeof(VLAN_Prop));
+        vlan_prop_init(tcard.pvlan_prop, VLAN_TYPE_802_1_Q);
+        pprop_8021q = &(tcard.pvlan_prop->props.prop_8021q);
+        tcard.eth_type |= ETH_TYPE_ETHER_SUB_VLAN;
+        pprop_8021q->vlan_id = rtnl_link_vlan_get_id(link);
+        pprop_8021q->reorder_hdr = (rtnl_link_vlan_get_flags(link) &
+                                    VLAN_FLAG_REORDER_HDR);
+        /* at any time parent of vlan8021.q is just what it depends on */
+        pprop_8021q->parent = SAFE_STRDUP(tcard.dep_ifname);
+        ingress_map = rtnl_link_vlan_get_ingress_map(link);
+        egress_map = rtnl_link_vlan_get_egress_map(link, &egress_num);
+        if (ingress_map != NULL) {
+            for (i = 0; i <= VLAN_PRIO_MAX; i++) {
+                pprop_8021q->ingress.values[i].from = i;
+                pprop_8021q->ingress.values[i].to = ingress_map[i];
+            }
+            pprop_8021q->ingress.count = VLAN_PRIO_MAX;
+            i = 0;
+            while (i < egress_num) {
+                pprop_8021q->egress.values[i].from = egress_map[i].vm_from;
+                pprop_8021q->egress.values[i].to = egress_map[i].vm_to;
+                i++;
+            }
+            pprop_8021q->egress.count = egress_num;
+        }
+    }
+
+
+    /* put result to list */
+    if (plist->count >= MAX_IFACE_NUM) {
+        CU_DEBUG("too much device found.");
+        goto out;
+    }
+    SAFE_MALLOC(plist->pifaces[plist->count], sizeof(EthIface));
+    eth_iface_dup(plist->pifaces[plist->count], &tcard);
+    plist->count++;
+
+ out:
+    eth_iface_uninit(&tcard);
+}
+
+static int get_host_eth_ifaces_osapi_netlink(EthIfacesList *plist)
+{
+    struct nl_sock *sk = NULL;
+    struct nl_cache *cache = NULL;
+    int ret, rtnl_ret;
+    struct nl_add2list_param param;
+
+    sk = nl_socket_alloc();
+    nl_connect(sk, NETLINK_ROUTE);
+
+    rtnl_ret = rtnl_link_alloc_cache(sk, AF_UNSPEC, &cache);
+    if (rtnl_ret < 0) {
+        CU_DEBUG("error in talking to kernel, return %d.\n", rtnl_ret);
+        ret = ERR_LIBNETLINK;
+    }
+
+    param.plist = plist;
+    param.cache = cache;
+    nl_cache_foreach(cache, nl_add2list_func, &param);
+    if (plist->count >= MAX_IFACE_NUM) {
+        CU_DEBUG("too much device found.");
+        ret = ERR_DEVICE_EXCEED_MAXNUM;
+        goto out;
+    }
+
+    ret = 1;
+
+ out:
+    nl_cache_free(cache);
+    nl_socket_free(sk);
+
+    return ret;
+}
+
+int get_host_eth_ifaces_osapi(EthIfacesList *plist,
+                    eth_iface_filter_func filter_func, void *filter_opaque)
+{
+    int retvalue;
+    EthIfacesList *ifaces1, *ifaces2;
+    int i;
+    int filter_ret;
+    int count = 0;
+    SAFE_MALLOC(ifaces1, sizeof(EthIfacesList));
+    SAFE_MALLOC(ifaces2, sizeof(EthIfacesList));
+    eth_ifaceslist_init(ifaces1);
+    eth_ifaceslist_init(ifaces2);
+
+    retvalue = get_host_eth_ifaces_osapi_netlink(ifaces1);
+    if (retvalue != 1) {
+        goto out;
+    }
+
+    retvalue = get_host_eth_ifaces_osapi_bridge(ifaces2);
+    if (retvalue != 1) {
+        goto out;
+    }
+    /* merge the information */
+    merge_eth_list_for_bridge(ifaces1, ifaces2, 1);
+    eth_ifaceslist_uninit(ifaces2);
+
+    /* filter the result */
+    i = 0;
+    while (i < ifaces1->count) {
+        /* see if the result need to be put to the list */
+        filter_ret = 1;
+        if (filter_func != NULL) {
+            filter_ret = filter_func(ifaces1->pifaces[i], filter_opaque);
+        }
+        if (filter_ret == 1) {
+            if (count >= MAX_IFACE_NUM) {
+                retvalue = ERR_DEVICE_EXCEED_MAXNUM;
+                goto out;
+            }
+            host_iface_adjust(ifaces1->pifaces[i]);
+            plist->pifaces[count] = ifaces1->pifaces[i];
+            ifaces1->pifaces[i] = NULL;
+            count++;
+        }
+        i++;
+    }
+
+ out:
+    eth_ifaceslist_uninit(ifaces1);
+    SAFE_FREE(ifaces1);
+    eth_ifaceslist_uninit(ifaces2);
+    SAFE_FREE(ifaces2);
+    plist->count = count;
+    return retvalue;
+}
diff --git a/libnetwork/host_network_implement_OSAPI.h b/libnetwork/host_network_implement_OSAPI.h
new file mode 100644
index 0000000..f72bf52
--- /dev/null
+++ b/libnetwork/host_network_implement_OSAPI.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright IBM Corp. 2011
+ *
+ * Authors:
+ *  Wenchao Xia <xiawenc at cn.ibm.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ */
+
+#ifndef HOST_NETWORK_IMPLEMENT_OSAPI_H
+#define HOST_NETWORK_IMPLEMENT_OSAPI_H
+
+#include "host_network_basic.h"
+
+int get_host_eth_ifaces_osapi(EthIfacesList *plist,
+                    eth_iface_filter_func filter_func, void *filter_opaque);
+
+#endif
diff --git a/libnetwork/libnetwork_test.c b/libnetwork/libnetwork_test.c
new file mode 100644
index 0000000..e8168b8
--- /dev/null
+++ b/libnetwork/libnetwork_test.c
@@ -0,0 +1,82 @@
+#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 "host_network_API.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;
+    printf("time is [%ld] ms.", ret);
+    return ret;
+}
+
+int main(int argc, char **argv)
+{
+    EthIfacesList ifaces_list;
+    EthIface iface_ref,iface_br,iface_vlan;
+    int comp_ret = 0;
+    int persist_flag = 1;
+    long timestart, timeend;
+
+
+    printf("executing the program with persist flag %d.\n", persist_flag);
+    comp_ret = 0;
+
+    eth_ifaceslist_init(&ifaces_list);
+    eth_iface_init(&iface_ref);
+    eth_iface_init(&iface_br);
+    eth_iface_init(&iface_vlan);
+
+    eth_iface_add_br_prop(&iface_br);
+    eth_iface_add_vlan_prop(&iface_vlan, VLAN_TYPE_802_1_Q);
+    iface_br.eth_type = ETH_TYPE_ETHER_SUB_BRIDGE | ETH_TYPE_ETHER_ANY;
+    iface_vlan.eth_type = ETH_TYPE_ETHER_SUB_VLAN | ETH_TYPE_ETHER_ANY;
+
+    //iface_ref.name = SAFE_STRDUP("eth1.100");
+    iface_ref.eth_type = ETH_TYPE_ETHER_SUB_BRIDGE | ETH_TYPE_ETHER_ANY;
+
+    iface_br.name = SAFE_STRDUP("test_br");
+    iface_vlan.name = SAFE_STRDUP("eth0.1000");
+
+    iface_br.pbr_prop->STP = 1;
+
+    iface_vlan.pvlan_prop->vlan_type = VLAN_TYPE_802_1_Q;
+    iface_vlan.pvlan_prop->props.prop_8021q.parent = SAFE_STRDUP("eth0");
+    iface_vlan.pvlan_prop->props.prop_8021q.vlan_id = 1000;
+    iface_vlan.pvlan_prop->props.prop_8021q.reorder_hdr = 0;
+    iface_vlan.pvlan_prop->props.prop_8021q.ingress.count = 1;
+    iface_vlan.pvlan_prop->props.prop_8021q.ingress.values[0].from = 2;
+    iface_vlan.pvlan_prop->props.prop_8021q.ingress.values[0].to = 3;
+    iface_vlan.pvlan_prop->props.prop_8021q.egress.count = 1;
+    iface_vlan.pvlan_prop->props.prop_8021q.egress.values[0].from = 4;
+    iface_vlan.pvlan_prop->props.prop_8021q.egress.values[0].to = 6;
+
+    timestart = print_and_ret_time_stamp();
+    printf(" start list the host ifaces.\n");
+
+    get_host_ifaces(&ifaces_list, NULL, NULL);
+    //get_host_ifaces(&ifaces_list, eth_iface_filter_by_ref, &iface_ref);
+    //get_host_ifaces(&ifaces_list, eth_iface_filter_vlans, NULL);
+    //get_host_ifaces(&ifaces_list, eth_iface_filter_peths, NULL);
+
+    timeend = print_and_ret_time_stamp();
+    printf(" end list the host ifaces, cost [%ld]ms.\n", timeend-timestart);
+
+    eth_ifaceslist_print(&ifaces_list);
+    eth_ifaceslist_uninit(&ifaces_list);
+
+    eth_iface_uninit(&iface_ref);
+    eth_iface_uninit(&iface_br);
+    eth_iface_uninit(&iface_vlan);
+
+    return 0;
+}
-- 
1.7.6





More information about the Libvirt-cim mailing list