[ovs-dev] [PATCH v4 1/3] Windows: Add internal switch port per OVS bridge
Sairam Venugopal
vsairam at vmware.com
Thu Nov 10 18:31:57 UTC 2016
+Alin
Guru – Sorry for the confusion. Alin is currently respinning this series. There was an associated bug that got fixed and he is updating the documentation for 3rd patch. I will ack v6 of this series.
Alin – Can you provide an update on this? Should we get this series into master and then update it instead?
Thanks,
Sairam
From: Guru Shetty <guru at ovn.org<mailto:guru at ovn.org>>
Date: Thursday, November 10, 2016 at 10:25 AM
To: Sairam Venugopal <vsairam at vmware.com<mailto:vsairam at vmware.com>>
Cc: "dev at openvswitch.org<mailto:dev at openvswitch.org>" <dev at openvswitch.org<mailto:dev at openvswitch.org>>
Subject: Re: [ovs-dev] [PATCH v4 1/3] Windows: Add internal switch port per OVS bridge
On 7 November 2016 at 13:47, Sairam Venugopal <vsairam at vmware.com<mailto:vsairam at vmware.com>> wrote:
I had acked it earlier. Will re-ack that patch if needed.
Sai, I meant v5 of the series and not patch 5. I guess, that was the confusion?
It is here:
https://patchwork.ozlabs.org/patch/669585/<https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.ozlabs.org_patch_669585_&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=VKtO-HY4GAbaVjtPhMHt7u-D6Jam2Vj9dGEdSfXWHCc&e=>
Thanks,
Sairam
On 11/4/16, 7:55 AM, "Guru Shetty" <guru at ovn.org<mailto:guru at ovn.org>> wrote:
>On 10 October 2016 at 15:47, Sairam Venugopal <vsairam at vmware.com<mailto:vsairam at vmware.com>> wrote:
>
>> Sorry for the delay in the review.
>>
>> Acked-by: Sairam Venugopal <vsairam at vmware.com<mailto:vsairam at vmware.com>>
>>
>
>There is a v5 of this series. Would you mind looking at that.
>
>
>>
>>
>>
>> On 8/12/16, 6:06 PM, "Alin Serdean" <aserdean at cloudbasesolutions.com<mailto:aserdean at cloudbasesolutions.com>>
>> wrote:
>>
>> >This patch updates the following commands in the vswitch:
>> >ovs-vsctl add-br br-test
>> >ovs-vsctl del-br br-test
>> >
>> >ovs-vsctl add-br br-test:
>> > This command will now create an internal port on the MSFT virtual
>> >switch
>> > using the WMI interface from Msvm_VirtualEthernetSwitchManagemen
>> tService
>> > leveraging the method AddResourceSettings.
>> > Before creating the actual port, the switch will be queried to see
>>if
>> >there
>> > is not a port already created (good for restarts when restarting the
>> > vswitch daemon). If there is a port defined it will return success
>>and
>> >log
>> > a message.
>> > After checking if the port already exists the command will also
>>verify
>> > if the forwarding extension (windows datapath) is enabled and on a
>> >single
>> > switch. If it is not activated or if it is activated on multiple
>> >switches
>> > it will return an error and a message will be logged.
>> > After the port was created on the switch, we will disable the
>>adapter
>> >on
>> > the host and rename to the corresponding OVS bridge name for
>> >consistency.
>> > The user will enable and set the values he wants after creation.
>> >
>> >ovs-vsctl del-br br-test
>> > This command will remove an internal port on the MSFT virtual
>>switch
>> > using the Msvm_VirtualEthernetSwitchManagementService class and
>> >executing
>> > the method RemoveResourceSettings.
>> >
>> >Both commands will be blocking until the WMI job is finished, this
>>allows
>> >us
>> >to guarantee that the ports are created and their name are set before
>> >issuing
>> >a netlink message to the windows datapath.
>> >
>> >This patch also includes helpers for normal WMI retrievals and
>> >initializations.
>> >Appveyor and documentation has been modified to include the libraries
>> >needed
>> >for COM objects.
>> >
>> >This patch was tested individually using IMallocSpy and CRT heap checks
>> >to ensure no new memory leaks are introduced.
>> >
>> >Tested on the following OS's:
>> >Windows 2012 and Windows 2012r2
>> >
>> >Signed-off-by: Alin Gabriel Serdean <aserdean at cloudbasesolutions.com<mailto:aserdean at cloudbasesolutions.com>>
>> >Acked-by: Paul Boca <pboca at cloudbasesolutions.com<mailto:pboca at cloudbasesolutions.com>>
>> >---
>> >v4: address comments (sanitize input, short refactor)
>> > use full stop on comments
>> > update coding style
>> >v3: rebase, add acked
>> >v2: Address comments. Rebase
>> >---
>> > appveyor.yml | 2 +-
>> > lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=> | 4 +-
>> > lib/dpif-netlink.c | 21 +
>> > lib/wmi.c | 1276
>> >++++++++++++++++++++++++++++++++++++++++++++++++++++
>> > lib/wmi.h | 51 +++
>> > 5 files changed, 1352 insertions(+), 2 deletions(-)
>> > create mode 100644 lib/wmi.c
>> > create mode 100644 lib/wmi.h
>> >
>> >diff --git a/appveyor.yml b/appveyor.yml
>> >index 0fd003b..1061df6 100644
>> >--- a/appveyor.yml
>> >+++ b/appveyor.yml
>> >@@ -41,5 +41,5 @@ build_script:
>> > - C:\MinGW\msys\1.0\bin\bash -lc "cp
>> >/c/pthreads-win32/Pre-built.2/dll/x86/*.dll /c/openvswitch/."
>> > - C:\MinGW\msys\1.0\bin\bash -lc "mv /bin/link.exe /bin/link_copy.exe"
>> > - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./boot.sh"
>> >-- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure
>> >CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi\"
>> >--with-pthread=C:/pthreads-win32/Pre-built.2
>> >--with-openssl=C:/OpenSSL-Win32 --with-vstudiotarget=\"Debug\""
>> >+- C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure
>> >CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi
>> >-lwbemuuid -lole32 -loleaut32\"
>> >--with-pthread=C:/pthreads-win32/Pre-built.2
>> >--with-openssl=C:/OpenSSL-Win32 --with-vstudiotarget=\"Debug\""
>> > - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && make"
>> >diff --git a/lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=> b/lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=>
>> >index 2faaeac..99bbdc0 100644
>> >--- a/lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=>
>> >+++ b/lib/automake.mk<https://urldefense.proofpoint.com/v2/url?u=http-3A__automake.mk&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=7FMBKJHDwQ9SgM1pJC4UrMKEVV71xBFOUmT7cbbJ-lA&e=>
>> >@@ -387,7 +387,9 @@ lib_libopenvswitch_la_SOURCES += \
>> > lib/netlink-notifier.h \
>> > lib/netlink-protocol.h \
>> > lib/netlink-socket.c \
>> >- lib/netlink-socket.h
>> >+ lib/netlink-socket.h \
>> >+ lib/wmi.c \
>> >+ lib/wmi.h
>> > endif
>> >
>> > if HAVE_POSIX_AIO
>> >diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
>> >index a39faa2..c8b0e37 100644
>> >--- a/lib/dpif-netlink.c
>> >+++ b/lib/dpif-netlink.c
>> >@@ -58,6 +58,7 @@
>> >
>> > VLOG_DEFINE_THIS_MODULE(dpif_netlink);
>> > #ifdef _WIN32
>> >+#include "wmi.h"
>> > enum { WINDOWS = 1 };
>> > #else
>> > enum { WINDOWS = 0 };
>> >@@ -849,6 +850,16 @@ dpif_netlink_port_add__(struct dpif_netlink *dpif,
>> >struct netdev *netdev,
>> > #endif
>> > }
>> >
>> >+#ifdef _WIN32
>> >+ if (request.type == OVS_VPORT_TYPE_INTERNAL) {
>> >+ if (!create_wmi_port(name)){
>> >+ VLOG_ERR("Could not create wmi internal port with
>>name:%s",
>> >name);
>> >+ vport_del_socksp(dpif, socksp);
>> >+ return EINVAL;
>> >+ };
>> >+ }
>> >+#endif
>> >+
>> > tnl_cfg = netdev_get_tunnel_config(netdev);
>> > if (tnl_cfg && (tnl_cfg->dst_port != 0 || tnl_cfg->exts)) {
>> > ofpbuf_use_stack(&options, options_stub, sizeof options_stub);
>> >@@ -940,6 +951,16 @@ dpif_netlink_port_del__(struct dpif_netlink *dpif,
>> >odp_port_t port_no)
>> > vport.cmd = OVS_VPORT_CMD_DEL;
>> > vport.dp_ifindex = dpif->dp_ifindex;
>> > vport.port_no = port_no;
>> >+#ifdef _WIN32
>> >+ struct dpif_port temp_dpif_port;
>> >+ dpif_netlink_port_query__(dpif, port_no, NULL, &temp_dpif_port);
>> >+ if (!strcmp(temp_dpif_port.type, "internal")) {
>> >+ if (!delete_wmi_port(temp_dpif_port.name<https://urldefense.proofpoint.com/v2/url?u=http-3A__temp-5Fdpif-5Fport.name&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=eQpxJWvhyOqNpoxEJmUQUV937loNokfnCs8JBuRfsZg&e=>)){
>> >+ VLOG_ERR("Could not delete wmi port with name: %s",
>> >+ temp_dpif_port.name<https://urldefense.proofpoint.com/v2/url?u=http-3A__temp-5Fdpif-5Fport.name&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=eQpxJWvhyOqNpoxEJmUQUV937loNokfnCs8JBuRfsZg&e=>);
>> >+ };
>> >+ }
>> >+#endif
>> > error = dpif_netlink_vport_transact(&vport, NULL, NULL);
>> >
>> > vport_del_channels(dpif, port_no);
>> >diff --git a/lib/wmi.c b/lib/wmi.c
>> >new file mode 100644
>> >index 0000000..67f0873
>> >--- /dev/null
>> >+++ b/lib/wmi.c
>> >@@ -0,0 +1,1276 @@
>> >+/*
>> >+ * Copyright (c) 2016 Cloudbase Solutions Srl
>> >+ *
>> >+ * Licensed under the Apache License, Version 2.0 (the "License");
>> >+ * you may not use this file except in compliance with the License.
>> >+ * You may obtain a copy of the License at
>> >+ *
>> >+ *
>> >https://urldefense.proofpoint.com/v2/url?u=http-
>> 3A__www.apache.org_license
>> >s_LICENSE-2D2.0&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
>> YihVMNtXt-uEs&r=D
>> >cruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=
>> 1NgcutJOUfLwjikmUhz6W0zVXDR35
>> >T75FV8sqiZ8ki8&s=6YJXIuUkmHpuGcJw64GoPVKdYVnqhnBsGxStg7axmxs&e=
>> >+ *
>> >+ * Unless required by applicable law or agreed to in writing, software
>> >+ * distributed under the License is distributed on an "AS IS" BASIS,
>> >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> >implied.
>> >+ * See the License for the specific language governing permissions and
>> >+ * limitations under the License.
>> >+ */
>> >+
>> >+#include <config.h>
>> >+#include "wmi.h"
>> >+#include <stdlib.h>
>> >+#include <stdio.h>
>> >+#include <tchar.h>
>> >+#include <Windows.h>
>> >+#include "openvswitch/vlog.h"
>> >+
>> >+VLOG_DEFINE_THIS_MODULE(wmi);
>> >+
>> >+/* WMI Job values. */
>> >+enum job_status
>> >+{
>> >+ job_starting = 3,
>> >+ job_running = 4,
>> >+ job_completed = 7,
>> >+ job_wait = 4096
>> >+};
>> >+
>> >+static char *
>> >+sanitize_port_name(char *name)
>> >+{
>> >+ char *p1, *p2;
>> >+ p1 = p2 = name;
>> >+
>> >+ while (*p1) {
>> >+ if ((*p1) == '\'' || (*p1) == '\"') {
>> >+ p1++;
>> >+ } else {
>> >+ *p2 = *p1;
>> >+ p2++;
>> >+ p1++;
>> >+ }
>> >+ }
>> >+ *p2 = '\0';
>> >+ return name;
>> >+}
>> >+
>> >+/* This function will output the appropriate message for a given
>> >HRESULT.*/
>> >+static void
>> >+get_hres_error(HRESULT hres)
>> >+{
>> >+ char *error_msg = NULL;
>> >+
>> >+ if (FACILITY_WINDOWS == HRESULT_FACILITY(hres)) {
>> >+ hres = HRESULT_CODE(hres);
>> >+ }
>> >+
>> >+ VLOG_ERR("%s", ovs_format_message(hres));
>> >+}
>> >+
>> >+static boolean
>> >+check_return_value(HRESULT hres)
>> >+{
>> >+ if (FAILED(hres)) {
>> >+ get_hres_error(hres);
>> >+ return false;
>> >+ }
>> >+
>> >+ return true;
>> >+}
>> >+
>> >+static HRESULT
>> >+get_variant_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>> >+ VARIANT *value)
>> >+{
>> >+ HRESULT hres;
>> >+
>> >+ VariantInit(value);
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, field_name, 0, value, 0,
>>0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ VariantClear(value);
>> >+ }
>> >+
>> >+ return hres;
>> >+}
>> >+
>> >+/* This function retrieves the uint16_t value from a given class
>>object
>> >with
>> >+ * the field name field_name. */
>> >+static HRESULT
>> >+get_uint16_t_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>> >+ uint16_t *value)
>> >+{
>> >+ VARIANT vt_prop;
>> >+ HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>> >+ *value = V_UI2(&vt_prop);
>> >+
>> >+ return hres;
>> >+}
>> >+
>> >+/* This function retrieves the unsigned int values from a given class
>> >object
>> >+ * with the field name field_name. */
>> >+static HRESULT
>> >+get_uint_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>> >+ unsigned int *value)
>> >+{
>> >+ VARIANT vt_prop;
>> >+ HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>> >+ *value = V_UI4(&vt_prop);
>> >+
>> >+ return hres;
>> >+}
>> >+
>> >+/* This function retrieves the unsigned short value from a given class
>> >object
>> >+ * with the field name field_name. */
>> >+static HRESULT
>> >+get_ushort_value(IWbemClassObject *pcls_obj, wchar_t *field_name,
>> >+ unsigned short *value)
>> >+{
>> >+ VARIANT vt_prop;
>> >+ HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>> >+ *value = V_UI2(&vt_prop);
>> >+
>> >+ return hres;
>> >+}
>> >+
>> >+/* This function retrieves the BSTR value from a given class object
>>with
>> >+ * the field name field_name, to a preallocated destination dest and
>> >with the
>> >+ * maximum length max_dest_lgth. */
>> >+static HRESULT
>> >+get_str_value(IWbemClassObject *pcls_obj, wchar_t *field_name, wchar_t
>> >*dest,
>> >+ int max_dest_lgth)
>> >+{
>> >+ VARIANT vt_prop;
>> >+ HRESULT hres = get_variant_value(pcls_obj, field_name, &vt_prop);
>> >+
>> >+ if (wcscpy_s(dest, max_dest_lgth, vt_prop.bstrVal)) {
>> >+ VariantClear(&vt_prop);
>> >+ VLOG_WARN("get_str_value, wcscpy_s failed :%s",
>> >ovs_strerror(errno));
>> >+ return WBEM_E_FAILED;
>> >+ }
>> >+
>> >+ VariantClear(&vt_prop);
>> >+ return S_OK;
>> >+}
>> >+
>> >+/* This function waits for a WMI job to finish and retrieves the error
>> >code
>> >+ * if the job failed */
>> >+static HRESULT
>> >+wait_for_job(IWbemServices *psvc, wchar_t *job_path)
>> >+{
>> >+ IWbemClassObject *pcls_obj = NULL;
>> >+ HRESULT retval = 0;
>> >+ uint16_t job_state = 0;
>> >+ uint16_t error = 0;
>> >+
>> >+ do {
>> >+ if(!check_return_value(psvc->lpVtbl->GetObject(psvc, job_path,
>> >0, NULL,
>> >+ &pcls_obj,
>> >NULL))) {
>> >+ retval = WBEM_E_FAILED;
>> >+ break;
>> >+ }
>> >+
>> >+ retval = get_uint16_t_value(pcls_obj, L"JobState",
>>&job_state);
>> >+ if (FAILED(retval)) {
>> >+ break;
>> >+ }
>> >+
>> >+ if (job_state == job_starting || job_state == job_running) {
>> >+ Sleep(200);
>> >+ } else if (job_state == job_completed) {
>> >+ break;
>> >+ } else {
>> >+ /* Error occurred. */
>> >+ retval = get_uint16_t_value(pcls_obj, L"ErrorCode",
>>&error);
>> >+ if (FAILED(retval)) {
>> >+ break;
>> >+ }
>> >+ VLOG_WARN("Job failed with error: %d", error);
>> >+ retval = WBEM_E_FAILED;;
>> >+ break;
>> >+ }
>> >+
>> >+ if (pcls_obj != NULL) {
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+ }
>> >+ } while(TRUE);
>> >+
>> >+ if (pcls_obj != NULL) {
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+ }
>> >+
>> >+ return retval;
>> >+}
>> >+
>> >+/* This function will initialize DCOM retrieving the WMI locator's
>>ploc
>> >and
>> >+ * the context associated to it. */
>> >+static boolean
>> >+initialize_wmi(IWbemLocator **ploc, IWbemContext **pcontext)
>> >+{
>> >+ HRESULT hres = 0;
>> >+
>> >+ /* Initialize COM. */
>> >+ hres = CoInitialize(NULL);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ return false;
>> >+ }
>> >+
>> >+ /* Initialize COM security. */
>> >+ hres = CoInitializeSecurity(NULL,
>> >+ -1,
>> >+ NULL,
>> >+ NULL,
>> >+ RPC_C_AUTHN_LEVEL_DEFAULT,
>> >+ RPC_C_IMP_LEVEL_IMPERSONATE,
>> >+ NULL,
>> >+ EOAC_NONE,
>> >+ NULL);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ return false;
>> >+ }
>> >+
>> >+ /* Fill context. */
>> >+ hres = CoCreateInstance(&CLSID_WbemContext,
>> >+ NULL,
>> >+ CLSCTX_INPROC_SERVER,
>> >+ &IID_IWbemContext,
>> >+ (void**)pcontext);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ return false;
>> >+ }
>> >+
>> >+ fill_context(*pcontext);
>> >+
>> >+ /* Initialize locator's (ploc) to WMI. */
>> >+ hres = CoCreateInstance(&CLSID_WbemLocator,
>> >+ NULL,
>> >+ CLSCTX_INPROC_SERVER,
>> >+ &IID_IWbemLocator,
>> >+ (LPVOID *)ploc);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ return false;
>> >+ }
>> >+
>> >+ return true;
>> >+}
>> >+
>> >+/* This function connects the WMI locator's ploc to a given WMI
>>provider
>> >+ * defined in server and also sets the required security levels for a
>> >local
>> >+ * connection to it. */
>> >+static boolean
>> >+connect_set_security(IWbemLocator *ploc, IWbemContext *pcontext,
>> >+ wchar_t *server, IWbemServices **psvc)
>> >+{
>> >+ HRESULT hres = 0;
>> >+
>> >+ /* Connect to server. */
>> >+ hres = ploc->lpVtbl->ConnectServer(ploc,
>> >+ server,
>> >+ NULL,
>> >+ NULL,
>> >+ 0,
>> >+ 0,
>> >+ 0,
>> >+ pcontext,
>> >+ psvc);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ return false;
>> >+ }
>> >+
>> >+ /* Set security levels. */
>> >+ hres = CoSetProxyBlanket((IUnknown *) *psvc,
>> >+ RPC_C_AUTHN_WINNT,
>> >+ RPC_C_AUTHZ_NONE,
>> >+ NULL,
>> >+ RPC_C_AUTHN_LEVEL_CALL,
>> >+ RPC_C_IMP_LEVEL_IMPERSONATE,
>> >+ NULL,
>> >+ EOAC_NONE);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ return false;
>> >+ }
>> >+
>> >+ return true;
>> >+}
>> >+
>> >+/* This function retrieves the first class object of a given
>>enumeration
>> >+ * outputted by a query and fails if it could not retrieve the object
>>or
>> >there
>> >+ * was no object to retrieve */
>> >+static boolean
>> >+get_first_element(IEnumWbemClassObject *penumerate,
>> >+ IWbemClassObject **pcls_obj)
>> >+{
>> >+ unsigned long retval = 0;
>> >+
>> >+ if (penumerate == NULL) {
>> >+ VLOG_WARN("Enumeration Class Object is NULL. Cannot get the
>> >first"
>> >+ "object");
>> >+ return false;
>> >+ }
>> >+
>> >+ HRESULT hres = penumerate->lpVtbl->Next(penumerate, WBEM_INFINITE,
>> 1,
>> >+ pcls_obj, &retval);
>> >+
>> >+
>> >+ if (!check_return_value(hres) || retval == 0) {
>> >+ return false;
>> >+ }
>> >+
>> >+ return true;
>> >+}
>> >+
>> >+/* This function is a wrapper that transforms a char * into a wchar_t
>>*
>> >*/
>> >+static boolean
>> >+tranform_wide(char *name, wchar_t *wide_name)
>> >+{
>> >+ unsigned long size = strlen(name) + 1;
>> >+ long long ret = 0;
>> >+
>> >+ if (wide_name == NULL) {
>> >+ VLOG_WARN("Provided wide string is NULL");
>> >+ return false;
>> >+ }
>> >+
>> >+ ret = mbstowcs(wide_name, name, size);
>> >+
>> >+ if (ret == -1) {
>> >+ VLOG_WARN("Invalid multibyte character is encountered");
>> >+ return false;
>> >+ } else if (ret == size) {
>> >+ VLOG_WARN("Returned wide string not NULL terminated");
>> >+ return false;
>> >+ }
>> >+
>> >+ return true;
>> >+}
>> >+
>> >+/* This function will delete a switch internal port with a given name
>>as
>> >input
>> >+ * executing "RemoveResourceSettings" as per documentation:
>> >+ *
>> >https://urldefense.proofpoint.com/v2/url?u=https-
>> 3A__msdn.microsoft.com_en
>> >-2Dus_library_hh850277-2528v-3Dvs.85-2529.aspx&d=CwIGaQ&c=
>> Sqcl0Ez6M0X8aeM6
>> >7LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOW
>> pJgEcEmNR3JEQ&
>> >m=1NgcutJOUfLwjikmUhz6W0zVXDR35T75FV8sqiZ8ki8&s=
>> tLEsQhF14PQ5LahGIKh2T8Z5h-
>> >JPdlzvoU3ecWYc9hg&e=
>> >+ * allocating the data and populating the needed fields to execute the
>> >+ * method */
>> >+boolean
>> >+delete_wmi_port(char *name)
>> >+{
>> >+ HRESULT hres = 0;
>> >+ boolean retval = true;
>> >+
>> >+ IWbemLocator *ploc = NULL;
>> >+ IWbemServices *psvc = NULL;
>> >+ IWbemContext *pcontext = NULL;
>> >+ IWbemClassObject *pclass_instance = NULL;
>> >+ IWbemClassObject *pinput_params = NULL;
>> >+ IWbemClassObject *pcls_obj = NULL;
>> >+ IWbemClassObject *pout_params = NULL;
>> >+ IEnumWbemClassObject *penumerate = NULL;
>> >+
>> >+ sanitize_port_name(name);
>> >+ VARIANT vt_prop;
>> >+ VARIANT variant_array;
>> >+ wchar_t *wide_name = NULL;
>> >+ VariantInit(&vt_prop);
>> >+ VariantInit(&variant_array);
>> >+
>> >+ LONG count[1];
>> >+ SAFEARRAY* psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
>> >+ if (psa == NULL) {
>> >+ VLOG_WARN("Could not allocate memory for a SAFEARRAY");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!initialize_wmi(&ploc, &pcontext)) {
>> >+ VLOG_WARN("Could not initialize DCOM");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!connect_set_security(ploc, pcontext,
>> >L"Root\\Virtualization\\v2",
>> >+ &psvc)) {
>> >+ VLOG_WARN("Could not connect and set security for
>> >virtualization");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+
>> >+ /* Get the port with the element name equal to the name input. */
>> >+ wchar_t internal_port_query[2048] = L"SELECT * from "
>> >+ L"Msvm_EthernetPortAllocationSettingData WHERE ElementName =
>> >\"" ;
>> >+
>> >+ wide_name = malloc((strlen(name) + 1) * sizeof(wchar_t));
>> >+ if (wide_name == NULL) {
>> >+ VLOG_WARN("Could not allocate memory for wide string");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!tranform_wide(name, wide_name)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >wide_name);
>> >+
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
>> >+
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ internal_port_query,
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ /* Get the element path on the switch which will be deleted. */
>> >+ if (!get_first_element(penumerate, &pcls_obj)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0,
>> 0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ /* Get the class object and the parameters it can have. */
>> >+ hres = psvc->lpVtbl->GetObject(psvc,
>> >+ L"Msvm_VirtualEthernetSwitchManagementService", 0, NULL,
>> >&pcls_obj,
>> >+ NULL);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = pcls_obj->lpVtbl->GetMethod(pcls_obj,
>> >L"RemoveResourceSettings", 0,
>> >+ &pinput_params, NULL);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
>> >+ &pclass_instance);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ count[0] = 0;
>> >+
>> >+ hres = SafeArrayPutElement(psa, count, vt_prop.bstrVal);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ VariantClear(&vt_prop);
>> >+ VariantInit(&vt_prop);
>> >+ variant_array.vt = VT_ARRAY | VT_BSTR;
>> >+ variant_array.parray = psa;
>> >+
>> >+ hres = pclass_instance->lpVtbl->Put(pclass_instance,
>> >L"ResourceSettings", 0,
>> >+ &variant_array, 0);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ /* Get the object of the
>>Msvm_VirtualEthernetSwitchManagementService
>> >which
>> >+ * we need to invoke the port deletion. */
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ L"SELECT * FROM "
>> >+
>> >L"Msvm_VirtualEthernetSwitchManagementService",
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!get_first_element(penumerate, &pcls_obj)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0,
>> 0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ /* Invoke the delete port method. */
>> >+ hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal,
>> >+ L"RemoveResourceSettings", 0,
>> >+ pcontext, pclass_instance,
>> >&pout_params,
>> >+ NULL);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ VariantClear(&vt_prop);
>> >+ VariantInit(&vt_prop);
>> >+
>> >+ hres = pout_params->lpVtbl->Get(pout_params, L"ReturnValue", 0,
>> >+ &vt_prop, NULL, 0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ unsigned int retvalue = 0;
>> >+ hres = get_uint_value(pout_params, L"ReturnValue", &retvalue);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (retvalue != 0 && retvalue != job_wait) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (retvalue == job_wait) {
>> >+ WCHAR job_path[2048];
>> >+ hres = get_str_value(pout_params, L"Job", job_path,
>> >+ sizeof(job_path) / sizeof(WCHAR));
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ hres = wait_for_job(psvc, job_path);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ }
>> >+ }
>> >+
>> >+error:
>> >+ VariantClear(&vt_prop);
>> >+
>> >+ if (pcontext != NULL) {
>> >+ pcontext->lpVtbl->Release(pcontext);
>> >+ pcontext = NULL;
>> >+ }
>> >+ if (psa != NULL) {
>> >+ SafeArrayDestroy(psa);
>> >+ psa = NULL;
>> >+ }
>> >+ if (pcls_obj != NULL) {
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+ }
>> >+ if (wide_name != NULL) {
>> >+ free(wide_name);
>> >+ wide_name = NULL;
>> >+ }
>> >+ if (!retval) {
>> >+ get_hres_error(hres);
>> >+ }
>> >+ if (pinput_params != NULL) {
>> >+ pinput_params->lpVtbl->Release(pinput_params);
>> >+ pinput_params = NULL;
>> >+ }
>> >+ if (pout_params != NULL) {
>> >+ pout_params->lpVtbl->Release(pout_params);
>> >+ pout_params = NULL;
>> >+ }
>> >+ if (psvc != NULL) {
>> >+ psvc->lpVtbl->Release(psvc);
>> >+ psvc = NULL;
>> >+ }
>> >+ if (ploc != NULL) {
>> >+ ploc->lpVtbl->Release(ploc);
>> >+ ploc = NULL;
>> >+ }
>> >+ if (pclass_instance != NULL) {
>> >+ pclass_instance->lpVtbl->Release(pclass_instance);
>> >+ pclass_instance = NULL;
>> >+ }
>> >+ if (penumerate != NULL) {
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+ }
>> >+
>> >+ CoUninitialize();
>> >+ return retval;
>> >+}
>> >+
>> >+/* This function will create an internal port on the switch given a
>> >given name
>> >+ * executing the method AddResourceSettings as per documentation:
>> >+ *
>> >https://urldefense.proofpoint.com/v2/url?u=https-
>> 3A__msdn.microsoft.com_en
>> >-2Dus_library_hh850019-2528v-3Dvs.85-2529.aspx&d=CwIGaQ&c=
>> Sqcl0Ez6M0X8aeM6
>> >7LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOW
>> pJgEcEmNR3JEQ&
>> >m=1NgcutJOUfLwjikmUhz6W0zVXDR35T75FV8sqiZ8ki8&s=
>> KtkOaMFPsRkI7S8YEFN7XDLQgu
>> >UWKnLJ-moHTsCF8Mo&e= .
>> >+ * It will verify if the port is already defined, in which case it
>>will
>> >use
>> >+ * the specific port, and if the forwarding extension "Open vSwitch
>> >Extension"
>> >+ * is enabled and running only on a single switch.
>> >+ * After the port is created and bound to the switch we will disable
>>the
>> >+ * created net adapter and rename it to match the OVS bridge name .*/
>> >+boolean
>> >+create_wmi_port(char *name) {
>> >+ HRESULT hres = 0;
>> >+ boolean retval = true;
>> >+
>> >+ BSTR text_object_string = NULL;
>> >+
>> >+ IWbemLocator *ploc = NULL;
>> >+ IWbemContext *pcontext = NULL;
>> >+ IWbemServices *psvc = NULL;
>> >+ IEnumWbemClassObject *penumerate = NULL;
>> >+ IWbemClassObject *default_settings_data = NULL;
>> >+ IWbemClassObject *default_system = NULL;
>> >+ IWbemClassObject *pcls_obj = NULL;
>> >+ IWbemClassObject *pclass = NULL;
>> >+ IWbemClassObject *pinput_params = NULL;
>> >+ IWbemClassObject *pclass_instance = NULL;
>> >+ IWbemObjectTextSrc *text_object = NULL;
>> >+ IWbemClassObject *pout_params = NULL;
>> >+
>> >+ wchar_t *wide_name = NULL;
>> >+ VARIANT vt_prop;
>> >+ VARIANT switch_setting_path;
>> >+ VARIANT new_name;
>> >+ SAFEARRAY *psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
>> >+ VARIANT variant_array;
>> >+ LONG count[1];
>> >+
>> >+ VariantInit(&vt_prop);
>> >+ VariantInit(&switch_setting_path);
>> >+ sanitize_port_name(name);
>> >+
>> >+ if (psa == NULL) {
>> >+ VLOG_WARN("Could not allocate memory for a SAFEARRAY");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!initialize_wmi(&ploc, &pcontext)) {
>> >+ VLOG_WARN("Could not initialize DCOM");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!connect_set_security(ploc, pcontext,
>> >L"Root\\Virtualization\\v2",
>> >+ &psvc)) {
>> >+ VLOG_WARN("Could not connect and set security for
>> >virtualization");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ /* Check if the element already exists on the switch. */
>> >+ wchar_t internal_port_query[2048] = L"SELECT * FROM "
>> >+ L"Msvm_InternalEthernetPort WHERE ElementName = \"";
>> >+
>> >+ wide_name = malloc((strlen(name) + 1) * sizeof(wchar_t));
>> >+ if (wide_name == NULL) {
>> >+ VLOG_WARN("Could not allocate memory for wide string");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!tranform_wide(name, wide_name)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >wide_name);
>> >+
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ internal_port_query,
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (get_first_element(penumerate, &pcls_obj)) {
>> >+ VLOG_WARN("Port with name: %s already defined on the switch",
>> >name);
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ /* Check if the extension is enabled and running. Also check if
>>the
>> >+ * the extension is enabled on more than one switch. */
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ L"SELECT * "
>> >+ L"FROM
>>Msvm_EthernetSwitchExtension "
>> >+ L"WHERE "
>> >+ L"ElementName=\"Open vSwitch
>> >Extension\" "
>> >+ L"AND EnabledState=2 "
>> >+ L"AND HealthState=5",
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!get_first_element(penumerate, &pcls_obj)) {
>> >+ VLOG_WARN("Open vSwitch Extension is not enabled on any
>>switch");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ wcscpy_s(internal_port_query, sizeof(internal_port_query),
>> >+ L"SELECT * FROM Msvm_VirtualEthernetSwitch WHERE Name =
>> >\"");
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, L"SystemName", 0,
>> >+ &vt_prop, 0, 0);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >+ vt_prop.bstrVal);
>> >+
>> >+ VariantClear(&vt_prop);
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ if (get_first_element(penumerate, &pcls_obj)) {
>> >+ VLOG_WARN("The extension is activated on more than one
>>switch, "
>> >+ "aborting operation. Please activate the extension
>>on
>> >a "
>> >+ "single switch");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+ if (pcls_obj != NULL) {
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+ }
>> >+
>> >+ /* Get the switch object on which the extension is activated. */
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query), L"\"");
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ internal_port_query,
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!get_first_element(penumerate, &pcls_obj)) {
>> >+ VLOG_WARN("Could not get the switch object on which the
>> >extension is"
>> >+ "activated");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, L"ElementName", 0,
>>&vt_prop,
>> >0, 0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ wcscpy_s(internal_port_query, sizeof(internal_port_query),
>> >+ L"SELECT * FROM Msvm_VirtualEthernetSwitchSettingData
>>WHERE
>> >"
>> >+ L"ElementName = \"");
>> >+
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >+ vt_prop.bstrVal);
>> >+ VariantClear(&vt_prop);
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, L"Name", 0, &vt_prop, 0,
>>0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >+ L"\" AND VirtualSystemIdentifier = \"");
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >+ vt_prop.bstrVal);
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >+ L"\" AND InstanceID = \"Microsoft:");
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >+ vt_prop.bstrVal);
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >+ L"\" AND Caption = \"Virtual Ethernet Switch Settings\"
>>AND
>> >"
>> >+ L"VirtualSystemType = \"DMTF:Virtual Ethernet Switch\"");
>> >+
>> >+ VariantClear(&vt_prop);
>> >+
>> >+ /* Retrieve the Msvm_VirtualEthernetSwitchSettingData pinned to
>>the
>> >switch
>> >+ * object on which the extension is activated. */
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ internal_port_query,
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!get_first_element(penumerate, &pcls_obj)) {
>> >+ VLOG_WARN("Could not get the first "
>> >+ "Msvm_VirtualEthernetSwitchSettingData object");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0,
>> >&switch_setting_path,
>> >+ 0, 0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ /* Retrieve a default allocation port. This object will be later
>> >filled
>> >+ * with optional data to create an switch internal port. */
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ L"SELECT * FROM "
>> >+
>> >L"Msvm_EthernetPortAllocationSettingData "
>> >+ L"WHERE InstanceID LIKE
>> >'%%%%\\\\Default' "
>> >+ L"AND ResourceSubType = "
>> >+ L"'Microsoft:Hyper-V:Ethernet
>> >Connection'",
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!get_first_element(penumerate, &default_settings_data)) {
>> >+ VLOG_WARN("Could not retrieve default allocation port
>>object");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ /* Retrieve the default computer system on which the port
>>allocation
>> >will
>> >+ * be hosted. */
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ L"SELECT * FROM Msvm_ComputerSystem
>> >WHERE "
>> >+ L"Description = \"Microsoft
>>Hosting "
>> >+ L"Computer System\"",
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!get_first_element(penumerate, &default_system)) {
>> >+ VLOG_WARN("Could not retrieve default computer system
>>object");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = default_system->lpVtbl->Get(default_system, L"__PATH",
>> >+ 0, &vt_prop, 0, 0);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ count[0] = 0;
>> >+ hres = SafeArrayPutElement(psa, count, vt_prop.bstrVal);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ VariantClear(&vt_prop);
>> >+ variant_array.vt = VT_ARRAY | VT_BSTR;
>> >+ variant_array.parray = psa;
>> >+ hres = default_settings_data->lpVtbl->Put(default_settings_data,
>> >+ L"HostResource", 0,
>> >+ &variant_array, 0);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = psvc->lpVtbl->GetObject(psvc,
>> >+
>> >L"Msvm_VirtualEthernetSwitchManagementService",
>> >+ 0, NULL, &pclass, NULL);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = pclass->lpVtbl->GetMethod(pclass, L"AddResourceSettings",
>>0,
>> >+ &pinput_params, NULL);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
>> >+ &pclass_instance);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ /* Store the switch setting path retrieved above in the affected
>> >+ * configuration field of the class instance. */
>> >+ hres = pclass_instance->lpVtbl->Put(pclass_instance,
>> >+ L"AffectedConfiguration", 0,
>> >+ &switch_setting_path, 0);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ /* Store the port name in the ElementName field of the default
>> >allocation
>> >+ * data. */
>> >+ vt_prop.vt = VT_BSTR;
>> >+ vt_prop.bstrVal = SysAllocString(wide_name);
>> >+ hres = default_settings_data->lpVtbl->Put(default_settings_data,
>> >+ L"ElementName", 0,
>> >+ &vt_prop, 0);
>> >+ VariantClear(&vt_prop);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ /* Retrieve and store the serialized data of the modified default
>> >switch
>> >+ * settings data. */
>> >+ hres = CoCreateInstance(&CLSID_WbemObjectTextSrc,
>> >+ NULL,
>> >+ CLSCTX_INPROC_SERVER,
>> >+ &IID_IWbemObjectTextSrc,
>> >+ (void**)&text_object);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = text_object->lpVtbl->GetText(text_object, 0,
>> >+ default_settings_data,
>> >+ WMI_OBJ_TEXT_WMI_DTD_2_0,
>> >+ pcontext,
>> >+ &text_object_string);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ hres = SafeArrayDestroy(psa);
>> >+ if (FAILED(hres)) {
>> >+ VLOG_WARN("Could not clear the data of the array");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ psa = SafeArrayCreateVector(VT_BSTR, 0, 1);
>> >+
>> >+ if (psa == NULL) {
>> >+ VLOG_WARN("Could not allocate memory for a SAFEARRAY");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ count[0] = 0;
>> >+ variant_array.parray = psa;
>> >+ hres = SafeArrayPutElement(psa, count, text_object_string);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ hres = pclass_instance->lpVtbl->Put(pclass_instance,
>> >L"ResourceSettings",
>> >+ 0, &variant_array, 0);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ /* Get the object of the switch service. */
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ L"SELECT * FROM "
>> >+
>> >L"Msvm_VirtualEthernetSwitchManagementService",
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (!get_first_element(penumerate, &pcls_obj)) {
>> >+ VLOG_WARN("Could not get the object of the switch service");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+
>> >+ hres = pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0,
>> 0);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ /* Try to add the port to the switch. */
>> >+ hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal,
>> >+ L"AddResourceSettings", 0,
>> >+ pcontext, pclass_instance,
>> >&pout_params,
>> >+ NULL);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ unsigned int retvalue = 0;
>> >+ hres = get_uint_value(pout_params, L"ReturnValue", &retvalue);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (retvalue != 0 && retvalue != job_wait) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ if (retvalue == job_wait) {
>> >+ WCHAR job_path[2048];
>> >+ hres = get_str_value(pout_params, L"Job", job_path,
>> >+ sizeof(job_path) / sizeof(WCHAR));
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ hres = wait_for_job(psvc, job_path);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ }
>> >+
>> >+ pclass->lpVtbl->Release(pclass);
>> >+ pclass = NULL;
>> >+ pclass_instance->lpVtbl->Release(pclass_instance);
>> >+ pclass_instance = NULL;
>> >+ pinput_params->lpVtbl->Release(pinput_params);
>> >+ pinput_params = NULL;
>> >+ psvc->lpVtbl->Release(psvc);
>> >+ psvc = NULL;
>> >+ VariantClear(&vt_prop);
>> >+
>> >+ if (!connect_set_security(ploc, pcontext, L"Root\\StandardCimv2",
>> >+ &psvc)) {
>> >+ VLOG_WARN("Could not connect and set security for CIM");
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ wcscpy_s(internal_port_query, sizeof(internal_port_query),
>> >+ L"SELECT * FROM MSFT_NetAdapter WHERE Name LIKE '%%");
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>> >wide_name);
>> >+ wcscat_s(internal_port_query, sizeof(internal_port_query),
>>L"%%'");
>> >+
>> >+ /* Get the object with the port name equal to name on the CIM. */
>> >+ hres = psvc->lpVtbl->ExecQuery(psvc,
>> >+ L"WQL",
>> >+ internal_port_query,
>> >+ WBEM_FLAG_FORWARD_ONLY |
>> >+ WBEM_FLAG_RETURN_IMMEDIATELY,
>> >+ NULL,
>> >+ &penumerate);
>> >+
>> >+ if (!get_first_element(penumerate, &pcls_obj)) {
>> >+ VLOG_WARN("Element name: %s not found in CIM", name);
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+ pcls_obj->lpVtbl->Get(pcls_obj, L"__PATH", 0, &vt_prop, 0, 0);
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+
>> >+ /* Disable the adapter with port name equal with name. */
>> >+ hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal,
>>L"Disable", 0,
>> >+ pcontext, NULL, NULL, NULL);
>> >+
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = psvc->lpVtbl->GetObject(psvc, L"MSFT_NetAdapter", 0, NULL,
>> >&pclass,
>> >+ NULL);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = pclass->lpVtbl->GetMethod(pclass, L"Rename", 0,
>> >&pinput_params,
>> >+ NULL);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ hres = pinput_params->lpVtbl->SpawnInstance(pinput_params, 0,
>> >+ &pclass_instance);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+
>> >+ VariantInit(&new_name);
>> >+ new_name.vt = VT_BSTR;
>> >+ new_name.bstrVal = wide_name;
>> >+ hres = pclass_instance->lpVtbl->Put(pclass_instance, L"NewName",
>>0,
>> >+ &new_name, 0);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ goto error;
>> >+ }
>> >+ hres = psvc->lpVtbl->ExecMethod(psvc, vt_prop.bstrVal, L"Rename",
>>0,
>> >+ pcontext, pclass_instance, NULL,
>> >NULL);
>> >+ if (FAILED(hres)) {
>> >+ retval = false;
>> >+ }
>> >+
>> >+error:
>> >+ if (text_object_string != NULL) {
>> >+ SysFreeString(text_object_string);
>> >+ text_object_string = NULL;
>> >+ }
>> >+ if (psa != NULL) {
>> >+ SafeArrayDestroy(psa);
>> >+ psa = NULL;
>> >+ }
>> >+ if (ploc != NULL) {
>> >+ ploc->lpVtbl->Release(ploc);
>> >+ ploc = NULL;
>> >+ }
>> >+ if (pcontext != NULL) {
>> >+ pcontext->lpVtbl->Release(pcontext);
>> >+ pcontext = NULL;
>> >+ }
>> >+ if (psvc != NULL) {
>> >+ psvc->lpVtbl->Release(psvc);
>> >+ psvc = NULL;
>> >+ }
>> >+ if (penumerate != NULL) {
>> >+ penumerate->lpVtbl->Release(penumerate);
>> >+ penumerate = NULL;
>> >+ }
>> >+ if (default_settings_data != NULL) {
>> >+ default_settings_data->lpVtbl->Release(default_settings_data);
>> >+ default_settings_data = NULL;
>> >+ }
>> >+ if (default_system != NULL) {
>> >+ default_system->lpVtbl->Release(default_system);
>> >+ default_system = NULL;
>> >+ }
>> >+ if (pcls_obj != NULL) {
>> >+ pcls_obj->lpVtbl->Release(pcls_obj);
>> >+ pcls_obj = NULL;
>> >+ }
>> >+ if (pclass != NULL) {
>> >+ pclass->lpVtbl->Release(pclass);
>> >+ pclass = NULL;
>> >+ }
>> >+ if (pinput_params != NULL) {
>> >+ pinput_params->lpVtbl->Release(pinput_params);
>> >+ pinput_params = NULL;
>> >+ }
>> >+ if (pclass_instance != NULL) {
>> >+ pclass_instance->lpVtbl->Release(pclass_instance);
>> >+ pclass_instance = NULL;
>> >+ }
>> >+ if (text_object != NULL) {
>> >+ text_object->lpVtbl->Release(text_object);
>> >+ text_object = NULL;
>> >+ }
>> >+ if (pout_params != NULL) {
>> >+ pout_params->lpVtbl->Release(pout_params);
>> >+ pout_params = NULL;
>> >+ }
>> >+ if (wide_name != NULL) {
>> >+ free(wide_name);
>> >+ wide_name = NULL;
>> >+ }
>> >+ VariantClear(&vt_prop);
>> >+ VariantClear(&switch_setting_path);
>> >+
>> >+ if (!retval) {
>> >+ get_hres_error(hres);
>> >+ }
>> >+ CoUninitialize();
>> >+ return retval;
>> >+}
>> >diff --git a/lib/wmi.h b/lib/wmi.h
>> >new file mode 100644
>> >index 0000000..28910e7
>> >--- /dev/null
>> >+++ b/lib/wmi.h
>> >@@ -0,0 +1,51 @@
>> >+/*
>> >+ * Copyright (c) 2016 Cloudbase Solutions Srl
>> >+ *
>> >+ * Licensed under the Apache License, Version 2.0 (the "License");
>> >+ * you may not use this file except in compliance with the License.
>> >+ * You may obtain a copy of the License at
>> >+ *
>> >+ *
>> >https://urldefense.proofpoint.com/v2/url?u=http-
>> 3A__www.apache.org_license
>> >s_LICENSE-2D2.0&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
>> YihVMNtXt-uEs&r=D
>> >cruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=
>> 1NgcutJOUfLwjikmUhz6W0zVXDR35
>> >T75FV8sqiZ8ki8&s=6YJXIuUkmHpuGcJw64GoPVKdYVnqhnBsGxStg7axmxs&e=
>> >+ *
>> >+ * Unless required by applicable law or agreed to in writing, software
>> >+ * distributed under the License is distributed on an "AS IS" BASIS,
>> >+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>> >implied.
>> >+ * See the License for the specific language governing permissions and
>> >+ * limitations under the License.
>> >+ */
>> >+
>> >+#ifndef WMI_H
>> >+#define WMI_H 1
>> >+
>> >+#include <windefs.h>
>> >+#include <Wbemidl.h>
>> >+
>> >+static inline void fill_context(IWbemContext *pContext)
>> >+{
>> >+ VARIANT var;
>> >+
>> >+ /* IncludeQualifiers. */
>> >+ VariantInit(&var);
>> >+ var.vt = VT_BOOL;
>> >+ var.boolVal = VARIANT_TRUE;
>> >+ pContext->lpVtbl->SetValue(pContext, L"IncludeQualifiers", 0,
>>&var);
>> >+ VariantClear(&var);
>> >+
>> >+ VariantInit(&var);
>> >+ var.vt = VT_I4;
>> >+ var.lVal = 0;
>> >+ pContext->lpVtbl->SetValue(pContext, L"PathLevel", 0, &var);
>> >+ VariantClear(&var);
>> >+
>> >+ /* ExcludeSystemProperties. */
>> >+ VariantInit(&var);
>> >+ var.vt = VT_BOOL;
>> >+ var.boolVal = VARIANT_FALSE;
>> >+ pContext->lpVtbl->SetValue(pContext, L"ExcludeSystemProperties",
>>0,
>> >&var);
>> >+ VariantClear(&var);
>> >+}
>> >+
>> >+boolean create_wmi_port(char *name);
>> >+boolean delete_wmi_port(char *name);
>> >+
>> >+#endif /* wmi.h */
>> >--
>> >2.9.2.windows.1
>> >
>> >_______________________________________________
>> >dev mailing list
>> >dev at openvswitch.org<mailto:dev at openvswitch.org>
>> >https://urldefense.proofpoint.com/v2/url?u=http-
>> 3A__openvswitch.org_mailma
>> >n_listinfo_dev&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-
>> YihVMNtXt-uEs&r=Dc
>> >ruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=
>> 1NgcutJOUfLwjikmUhz6W0zVXDR35T
>> >75FV8sqiZ8ki8&s=YMq7EI4iHIjlQKCYB1Lil7Pq3-80pelN7ZKYA4JvBb4&e=
>>
>> _______________________________________________
>> dev mailing list
>> dev at openvswitch.org<mailto:dev at openvswitch.org>
>>
>>https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailm
>>an_listinfo_dev&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=
>>Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=s5NiOORo9oYojV_md5W4no7jk3y
>>aVMhSM32myrFonRk&s=a2UZKIcPi4J9xe5RSgLj-CacGcP6Hrg_3HmYsCfPqyc&e=
>>
>_______________________________________________
>dev mailing list
>dev at openvswitch.org<mailto:dev at openvswitch.org>
>https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailma
>n_listinfo_dev&d=CwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dc
>ruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=s5NiOORo9oYojV_md5W4no7jk3yaVM
>hSM32myrFonRk&s=a2UZKIcPi4J9xe5RSgLj-CacGcP6Hrg_3HmYsCfPqyc&e=
_______________________________________________
dev mailing list
dev at openvswitch.org<mailto:dev at openvswitch.org>
https://mail.openvswitch.org/mailman/listinfo/ovs-dev<https://urldefense.proofpoint.com/v2/url?u=https-3A__mail.openvswitch.org_mailman_listinfo_ovs-2Ddev&d=CwMFaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Dcruz40PROJ40ROzSpxyQSLw6fcrOWpJgEcEmNR3JEQ&m=YE4a4YjWTlfIBRI7iUN864ENo3hsEM75CCIN6Fl53Sg&s=s7c7FvsOER1vHmCsJ9OFhdzWlk39ORsnlLSNPtZ14j0&e=>
More information about the dev
mailing list