
this is the core abstraction and structure for ethernet devices. Signed-off-by: Wayne Xia <xiawenc@linux.vnet.ibm.com> --- libxkutil/host_network_basic.c | 639 ++++++++++++++++++++++++++++++++++++++++ libxkutil/host_network_basic.h | 166 +++++++++++ 2 files changed, 805 insertions(+), 0 deletions(-) create mode 100644 libxkutil/host_network_basic.c create mode 100644 libxkutil/host_network_basic.h diff --git a/libxkutil/host_network_basic.c b/libxkutil/host_network_basic.c new file mode 100644 index 0000000..3bcb32e --- /dev/null +++ b/libxkutil/host_network_basic.c @@ -0,0 +1,639 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia <xiawenc@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 %d.\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); + } + NUM_MERGE(dest->eth_type, src->eth_type, ETH_TYPE_NOT_GOT); + 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; + } + + NUM_COMPARE_BY_REF(piface->eth_type, ref->eth_type, + 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/libxkutil/host_network_basic.h b/libxkutil/host_network_basic.h new file mode 100644 index 0000000..d1dd128 --- /dev/null +++ b/libxkutil/host_network_basic.h @@ -0,0 +1,166 @@ +/* + * Copyright IBM Corp. 2011 + * + * Authors: + * Wenchao Xia <xiawenc@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 + +/* 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; + +typedef enum { + ETH_TYPE_NOT_GOT = NUM_NOT_GOT, + ETH_TYPE_UNKNOWN = 0, + ETH_TYPE_LOOPBACK = 1, + ETH_TYPE_PHYSICAL = 2, + ETH_TYPE_NORMAL = 4, + ETH_TYPE_BRIDGE = 8, + ETH_TYPE_VLAN = 16 +} 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 */ +void vlan_prop_init(VLAN_Prop *pvlan_prop, int vlan_type); +void vlan_prop_uninit(VLAN_Prop *pvlan_prop); + +void br_prop_init(BR_Prop *pbr_prop); +void br_prop_uninit(BR_Prop *pbr_prop); + +void eth_iface_print(EthIface *piface); +void eth_iface_init(EthIface *piface); +void eth_iface_add_br_prop(EthIface *piface); +void eth_iface_add_vlan_prop(EthIface *piface, int vlan_type); +void eth_iface_uninit(EthIface *piface); +void eth_ifaces_clear(EthIface **ppifaces, int num); + +void eth_ifaceslist_init(EthIfacesList *plist); +void eth_ifaceslist_uninit(EthIfacesList *plist); +void eth_ifaceslist_print(EthIfacesList *plist); + +/* this function assume dest have been uninited if it was used before*/ +void eth_iface_dup(EthIface *dest, const EthIface *src); + +/* see if it is refered to the same device */ +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. */ +void eth_iface_merge(EthIface *dest, EthIface *src, int style); + +int eth_iface_filter_by_ref(const EthIface *piface, void *pref); +int eth_iface_filter_by_refname(const EthIface *piface, void *pref); +int eth_iface_filter_vlans(const EthIface *piface, void *nouse); +int eth_iface_filter_peths(const EthIface *piface, void *nouse); + + +#endif -- 1.7.6