[PATCH V6 7/7] vlan extention - CIM model add EASD

From: Wenchao Xia <xiawenc@linux.vnet.ibm.com> Add EASD for EthernetPort. According DSP1097, There are two kinds of EASD: EA stands for Settings of EthernetPort, EC stands for Settings for Connection between EthernetPort. Signed-off-by: Wenchao Xia <xiawenc@linux.vnet.ibm.com> --- schema/EthernetPortAllocationSettingData.mof | 22 + .../EthernetPortAllocationSettingData.registration | 3 + src/Virt_EASD.c | 709 ++++++++++++++++++++ src/Virt_EASD.h | 59 ++ 4 files changed, 793 insertions(+), 0 deletions(-) create mode 100644 schema/EthernetPortAllocationSettingData.mof create mode 100644 schema/EthernetPortAllocationSettingData.registration create mode 100644 src/Virt_EASD.c create mode 100644 src/Virt_EASD.h diff --git a/schema/EthernetPortAllocationSettingData.mof b/schema/EthernetPortAllocationSettingData.mof new file mode 100644 index 0000000..726bb1f --- /dev/null +++ b/schema/EthernetPortAllocationSettingData.mof @@ -0,0 +1,22 @@ +// Copyright IBM Corp. 2012 + +[Description ("Virtutal EthernetPort Setting Data"), + Provider("cmpi::Virt_EASD") +] + +class Net_EthernetPortAllocationSettingData : CIM_EthernetPortAllocationSettingData +{ + uint16 PortVID; + uint16 DesiredEndPointMode; + + [Description("VLAN type of the port, " + "Now only support IEEE 802.1.q."), + ValueMap { "0", "1", "2", "3" }, + Values { "Not VLAN", "IEEE 802.1.q", "IEEE 802.1.qbg", "IEEE 802.1.qbh" }] + uint16 VLANType; + + uint16 AutoStart; + + uint16 DHCP; + +}; diff --git a/schema/EthernetPortAllocationSettingData.registration b/schema/EthernetPortAllocationSettingData.registration new file mode 100644 index 0000000..8925739 --- /dev/null +++ b/schema/EthernetPortAllocationSettingData.registration @@ -0,0 +1,3 @@ +# Copyright IBM Corp. 2012 +# Classname Namespace ProviderName ProviderModule ProviderTypes +Net_EthernetPortAllocationSettingData root/virt Virt_EASD Virt_EASD instance diff --git a/src/Virt_EASD.c b/src/Virt_EASD.c new file mode 100644 index 0000000..bdcf125 --- /dev/null +++ b/src/Virt_EASD.c @@ -0,0 +1,709 @@ +/* + * 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <inttypes.h> +#include <sys/stat.h> + +#include <cmpidt.h> +#include <cmpift.h> +#include <cmpimacs.h> + +#include <libcmpiutil/libcmpiutil.h> +#include <libcmpiutil/std_instance.h> + +#include "misc_util.h" +#include "cs_util.h" +#include "device_parsing.h" +#include "network_model_helper.h" + +#include "Virt_EASD.h" + +static const CMPIBroker *_BROKER; + +static int set_primary_for_easd(const CMPIBroker *broker, const char* prefix, + struct EthIface *piface, int type, CMPIInstance *instance) +{ + char *eth_name, *easd_name; + int asret; + uint16_t res_type = CIM_NUM_SWITCHPORT; + uint16_t vlan_mode; + + if (piface->name == NULL) { + return 0; + } + + eth_name = get_ethportsd_name_from_iface(piface->name, type); + asret = asprintf(&easd_name, "%s/%s", prefix, eth_name); + + CMSetProperty(instance, "InstanceID", + (CMPIValue *)easd_name, CMPI_chars); + CMSetProperty(instance, "ElementName", + (CMPIValue *)eth_name, CMPI_chars); + CU_FREE(easd_name); + CU_FREE(eth_name); + + CMSetProperty(instance, "ResourceType", + (CMPIValue *)&res_type, CMPI_uint16); + + if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) { + vlan_mode = CIM_NUM_VLAN_MODE_TRUNK; + CMSetProperty(instance, "DesiredEndPointMode", + (CMPIValue *)&vlan_mode, CMPI_uint16); + } + + + if (piface->mac != NULL) { + CMSetProperty(instance, "Address", + (CMPIValue *)piface->mac, CMPI_chars); + } + + return 1; +} + +static int set_secondary_for_easd(const CMPIBroker *broker, + struct EthIface *piface, CMPIInstance *instance) +{ + struct VLAN_Prop *pvlan; + struct VLAN_Prop_8021q *pvlan8021q; + uint16_t vid; + CMPIArray *conn_array; + CMPIString *cm_str; + char *str = NULL; + CMPIStatus s; + uint16_t vlantype = 0; + uint16_t visibility = CIM_NUM_CONSUMERVISIBILITY_VIRTUALIZED; + + if (piface->eth_type == ETH_TYPE_ETHER_PHYSICAL) { + visibility = CIM_NUM_CONSUMERVISIBILITY_PASSEDTHROUGH; + } + CMSetProperty(instance, "ConsumerVisibility", + (CMPIValue *)&visibility, CMPI_uint16); + + if (piface->protocol_prop.ipv4_prop.DHCP >= 0) { + CMSetProperty(instance, "DHCP", + (CMPIValue *)&piface->protocol_prop.ipv4_prop.DHCP, + CMPI_uint16); + } + + if (piface->run_prop.boot_mode >= 0) { + CMSetProperty(instance, "AutoStart", + (CMPIValue *)&piface->run_prop.boot_mode, + CMPI_uint16); + } + + if ((piface->eth_type != ETH_TYPE_ETHER_VLAN) || + (piface->pvlan_prop == NULL)) { + goto out; + } + pvlan = piface->pvlan_prop; + + if (pvlan->vlan_type == VLAN_TYPE_802_1_Q) { + pvlan8021q = &(pvlan->props.prop_8021q); + vid = pvlan8021q->vlan_id; + CMSetProperty(instance, "PortVID", + (CMPIValue *)&vid, CMPI_uint16); + + str = vlanid_to_connection_name(vid); + conn_array = CMNewArray(broker, 1, CMPI_string, &s); + if ((s.rc != CMPI_RC_OK) || (str == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Error creating Connection " + "list and its string"); + CU_DEBUG("CMNewArray or string creation failed"); + goto out; + } + cm_str = CMNewString(broker, str, &s); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Error creating CMPIString"); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Error creating CMPIString for " + "BootDevices item"); + + goto out; + } + CMSetArrayElementAt(conn_array, 0, (CMPIValue *)&cm_str, + CMPI_string); + CMSetProperty(instance, "Connection", + (CMPIValue *)&conn_array, CMPI_stringA); + + vlantype = 1; + } + CMSetProperty(instance, "VLANType", + (CMPIValue *)&vlantype, CMPI_uint16); + +out: + CU_FREE(str); + return 1; +} + +static CMPIStatus add_conn_properties(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + const char *dest, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *eth_name, *easd_name; + int asret; + CMPIArray *array; + CMPIString *tmp; + + if (piface->name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "device name not set"); + goto out; + } + if (dest == NULL) { + CU_DEBUG("warn: connection dest is NULL."); + } + + eth_name = get_ethportsd_name_from_iface(piface->name, EASD_TYPE_EA); + asret = asprintf(&easd_name, "%s:%s", prefix, eth_name); + CMSetProperty(instance, "Parent", + (CMPIValue *)easd_name, CMPI_chars); + CU_FREE(easd_name); + CU_FREE(eth_name); + + array = CMNewArray(broker, 1, CMPI_string, &s); + tmp = CMNewString(broker, dest, NULL); + CMSetArrayElementAt(array, 0, &(tmp), CMPI_string); + CMSetProperty(instance, "HostResource", + (CMPIValue *)&array, CMPI_stringA); + + + out: + return s; +} + +static CMPIStatus set_properties(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + const char *dest, + int type, + CMPIInstance *instance) +{ + CMPIStatus s = {CMPI_RC_ERR_FAILED, NULL}; + char *errstr; + + if (!set_primary_for_easd(broker, prefix, piface, type, instance)) { + errstr = "failed to set primary properties for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + if (type == EASD_TYPE_EA) { + if (!set_secondary_for_easd(broker, piface, instance)) { + errstr = "failed to set secondary properties" + " for instance."; + CU_DEBUG("%s, iface name %s.", errstr, piface->name); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + } else { + s = add_conn_properties(broker, + piface, + prefix, + dest, + instance); + if (s.rc != CMPI_RC_OK) { + goto out; + } + } + + cu_statusf(broker, &s, + CMPI_RC_OK, + ""); + + out: + return s; +} + +static CMPIStatus instance_from_easd_build(const CMPIBroker *broker, + struct EthIface *piface, + const char *prefix, + const char *dest, + int type, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIInstance *inst = NULL; + CMPIStatus s = {CMPI_RC_OK, NULL}; + const char *keys[] = {"InstanceID", NULL}; + + inst = get_typed_instance(broker, + NETWORK_CLASS_PREFIX, + "EthernetPortAllocationSettingData", + NAMESPACE(reference)); + if (inst == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "Unable to init SwitchSystem instance"); + goto out; + } + + + s = CMSetPropertyFilter(inst, properties, keys); + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("Unable to set property filter: %d", s.rc); + } + + s = set_properties(broker, + piface, + prefix, + dest, + type, + inst); + + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + return s; +} + +/* vsname and req_type are filter conditions */ +static CMPIStatus instance_from_easd(const CMPIBroker *broker, + struct EthIface *piface, + const char *vsname, + int req_type, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist) +{ + + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *br1_name = NULL, *br2_name = NULL; + + CU_DEBUG("enter instance_for_easd with vsname %s, type %d.", + vsname, req_type); + get_possible_bridge_name_for_cim_model(piface, &br1_name, &br2_name); + if (br1_name == NULL) { + CU_DEBUG("failed to find any bridge for the port %s.", + piface->name); + } + + /* building the EA instance */ + if (!(req_type&EASD_TYPE_EA)) { + goto ea_build_end; + } + if ((vsname == NULL) || (br1_name == NULL) || + (0 == strcmp(vsname, br1_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br1_name, + NULL, + EASD_TYPE_EA, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + + /* following is to make it comform to CIM profile which require two + ethports connectted to pNIC and vswitch, but we have only one piface + on linux indicating it is connected to pNIC and bridge at sametime */ + if (br2_name == NULL) { + goto out; + } + + if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br2_name, + NULL, + EASD_TYPE_EA, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + ea_build_end: + + /* building the EC instance */ + if (!(req_type&EASD_TYPE_EC)) { + goto ec_build_end; + } + if ((br1_name == NULL) || (br2_name == NULL)) { + goto ec_build_end; + } + /* connection exist, so a EC_easd should be added for each bridge */ + if ((vsname == NULL) || (0 == strcmp(vsname, br1_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br1_name, + br2_name, + EASD_TYPE_EC, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + if ((vsname == NULL) || (0 == strcmp(vsname, br2_name))) { + inst = NULL; + s = instance_from_easd_build(broker, + piface, + br2_name, + br1_name, + EASD_TYPE_EC, + reference, + properties, + &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + inst_list_add(plist, inst); + } + ec_build_end: + + out: + CU_FREE(br1_name); + CU_FREE(br2_name); + return s; +} + +CMPIStatus get_easd_by_name(const CMPIBroker *broker, + const char *prefix, + const char *name, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *eth_name = NULL; + char *dest = NULL; + char *errstr; + int ret; + int type; + struct EthIfacesList ifaces_list; + struct inst_list list; + + CU_DEBUG("####prefix %s", prefix); + eth_ifaceslist_init(&ifaces_list); + inst_list_init(&list); + + eth_name = get_iface_name_from_ethportsd(name, &type); + if (eth_name == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "failed to convert instance name"); + CU_DEBUG("ethport name %s failed to convert.", name); + goto out; + } + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_ethport_for_name, eth_name); + + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + if (ifaces_list.count != 1) { + errstr = "expected ethport not found."; + CU_DEBUG("%d ethportd found.", ifaces_list.count); + eth_ifaceslist_print(&ifaces_list); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + + inst = NULL; + s = instance_from_easd(broker, + ifaces_list.pifaces[0], + prefix, + type, + reference, + properties, + &list); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (list.cur == 0) { + CU_DEBUG("%d instance found, expect is 1.", list.cur); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "no such instance."); + goto out; + } + + if (list.cur > 1) { + CU_DEBUG("%d instance found, expect is 1.", list.cur); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + "instance found do not match expectation"); + goto out; + } + + *_inst = list.list[0]; + list.list[0] = NULL; + + out: + eth_ifaceslist_uninit(&ifaces_list); + inst_list_free(&list); + CU_FREE(eth_name); + CU_FREE(dest); + return s; +} + +CMPIStatus get_easd_by_id(const CMPIBroker *broker, + const char *id, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + char *prefix = NULL; + char *suffix = NULL; + if (id == NULL) { + cu_statusf(broker, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "ID is NULL'", id); + } + if (!parse_fq_devid(id, &prefix, &suffix) || (prefix == NULL) || + (suffix == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_INVALID_PARAMETER, + "Invalid InstanceID `%s'", id); + goto out; + } + s = get_easd_by_name(broker, prefix, suffix, reference, + properties, _inst); + + out: + CU_FREE(prefix); + CU_FREE(suffix); + return s; +} + +CMPIStatus get_easd_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + char *name = NULL; + char *prefix = NULL; + const char *id; + + if (cu_get_str_path(reference, "InstanceID", &id) != CMPI_RC_OK) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "No such instance (InstanceID)"); + goto out; + } + if ((!parse_fq_devid(id, &prefix, &name)) || + (name == NULL) || (prefix == NULL)) { + cu_statusf(broker, &s, + CMPI_RC_ERR_NOT_FOUND, + "Failed to translate (InstanceID)"); + goto out; + } + + s = get_easd_by_name(broker, prefix, name, reference, + properties, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + s = cu_validate_ref(broker, reference, inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + *_inst = inst; + + out: + free(name); + free(prefix); + + return s; +} + + +CMPIStatus enum_easds(const CMPIBroker *broker, + const char *ref_vsname, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + struct EthIfacesList ifaces_list; + int ret, i; + char *errstr; + + eth_ifaceslist_init(&ifaces_list); + + ret = get_host_ifaces(&ifaces_list, + eth_iface_filter_cim_ethport, NULL); + if (ret != 1) { + errstr = get_host_iface_error_reason(ret); + CU_DEBUG("error num %d returned, reason %s.", ret, errstr); + cu_statusf(broker, &s, + CMPI_RC_ERR_FAILED, + errstr); + goto out; + } + CU_DEBUG("enum easd, found following devices.") + eth_ifaceslist_print(&ifaces_list); + + i = 0; + while (i < ifaces_list.count) { + s = instance_from_easd(broker, + ifaces_list.pifaces[i], + ref_vsname, + EASD_TYPE_EA|EASD_TYPE_EC, + reference, + properties, + plist); + i++; + /* this should never fail */ + if (s.rc != CMPI_RC_OK) { + CU_DEBUG("unexpected fail."); + break; + } + } + + + out: + eth_ifaceslist_uninit(&ifaces_list); + + return s; +} + +static CMPIStatus return_enum_easds(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const CMPIResult *results, + const char **properties, + const bool names_only) +{ + struct inst_list list; + CMPIStatus s = {CMPI_RC_OK, NULL}; + inst_list_init(&list); + s = enum_easds(broker, NULL, reference, properties, &list); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + if (names_only) { + cu_return_instance_names(results, &list); + } else { + cu_return_instances(results, &list); + } + + out: + inst_list_free(&list); + return s; +} + +static CMPIStatus EnumInstanceNames(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference) +{ + return return_enum_easds(_BROKER, reference, results, + NULL, true); +} + +static CMPIStatus EnumInstances(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *reference, + const char **properties) +{ + + return return_enum_easds(_BROKER, reference, results, + properties, false); +} + +static CMPIStatus GetInstance(CMPIInstanceMI *self, + const CMPIContext *context, + const CMPIResult *results, + const CMPIObjectPath *ref, + const char **properties) +{ + CMPIStatus s = {CMPI_RC_OK, NULL}; + CMPIInstance *inst = NULL; + + s = get_easd_by_ref(_BROKER, ref, properties, &inst); + if (s.rc != CMPI_RC_OK) { + goto out; + } + + CMReturnInstance(results, inst); + + out: + return s; +} + +DEFAULT_CI(); +DEFAULT_MI(); +DEFAULT_DI(); +DEFAULT_INST_CLEANUP(); +DEFAULT_EQ(); + +STD_InstanceMIStub(, + Virt_EASD, + _BROKER, + libvirt_cim_init()); + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ diff --git a/src/Virt_EASD.h b/src/Virt_EASD.h new file mode 100644 index 0000000..f9d13ec --- /dev/null +++ b/src/Virt_EASD.h @@ -0,0 +1,59 @@ +/* + * 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. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __VIRT_EASD_H +#define __VIRT_EASD_H + +CMPIStatus enum_easds(const CMPIBroker *broker, + const char *ref_vsname, + const CMPIObjectPath *reference, + const char **properties, + struct inst_list *plist); + +CMPIStatus get_easd_by_name(const CMPIBroker *broker, + const char *prefix, + const char *name, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + +CMPIStatus get_easd_by_id(const CMPIBroker *broker, + const char *id, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + +CMPIStatus get_easd_by_ref(const CMPIBroker *broker, + const CMPIObjectPath *reference, + const char **properties, + CMPIInstance **_inst); + + +#endif + +/* + * Local Variables: + * mode: C + * c-set-style: "K&R" + * tab-width: 8 + * c-basic-offset: 8 + * indent-tabs-mode: nil + * End: + */ -- 1.7.1
participants (1)
-
xiaxia347work@163.com