[libvirt] [PATCH 3/4] parallels: better bridge network interface support

Maxim Nestratov mnestratov at parallels.com
Fri Jan 30 19:58:35 UTC 2015


In order to support 'bridge' network adapters in parallels
driver we need to plug our veth devices into corresponding
linux bridges.
We are going to do this by reusing our abstraction of
Virtual Networks in terms of PCS. On a domain creation, we
create a new Virtual Network naming it with the same name
as a source bridge for each network  interface.
Thus, we plug PCS veth interfaces created with names of
target dev with specified bridges using our standard PCS
procedures.

Signed-off-by: Maxim Nestratov <mnestratov at parallels.com>
---
 src/parallels/parallels_sdk.c   |  112 ++++++++++++++++++++++++++++++++-------
 src/parallels/parallels_utils.h |    1 +
 2 files changed, 94 insertions(+), 19 deletions(-)

diff --git a/src/parallels/parallels_sdk.c b/src/parallels/parallels_sdk.c
index 795ba31..f200074 100644
--- a/src/parallels/parallels_sdk.c
+++ b/src/parallels/parallels_sdk.c
@@ -689,12 +689,8 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt)
 
     net->type = VIR_DOMAIN_NET_TYPE_NETWORK;
 
-
     /* use device name, shown by prlctl as target device
      * for identifying network adapter in virDomainDefineXML */
-    pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex);
-    prlsdkCheckRetGoto(pret, cleanup);
-
     pret = PrlVmDevNet_GetHostInterfaceName(netAdapter, NULL, &buflen);
     prlsdkCheckRetGoto(pret, cleanup);
 
@@ -702,7 +698,10 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt)
         goto cleanup;
 
     pret = PrlVmDevNet_GetHostInterfaceName(netAdapter, net->ifname, &buflen);
-        prlsdkCheckRetGoto(pret, cleanup);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVmDev_GetIndex(netAdapter, &netAdapterIndex);
+    prlsdkCheckRetGoto(pret, cleanup);
 
     if (isCt && netAdapterIndex == (PRL_UINT32) -1) {
         /* venet devices don't have mac address and
@@ -741,6 +740,14 @@ prlsdkGetNetInfo(PRL_HANDLE netAdapter, virDomainNetDefPtr net, bool isCt)
                                                net->data.network.name,
                                                &buflen);
         prlsdkCheckRetGoto(pret, cleanup);
+
+        // We use VIR_DOMAIN_NET_TYPE_NETWORK for all network adapters
+        // except those whose Virtual Network Id differ from Parallels
+        // predefined ones such as PARALLELS_BRIDGED_NETWORK_NAME and PARALLELS_ROUTED_NETWORK_NAME
+        if (!STREQ(net->data.network.name, PARALLELS_BRIDGED_NETWORK_NAME)) {
+            net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
+        }
+
     }
 
     pret = PrlVmDev_IsConnected(netAdapter, &isConnected);
@@ -1352,7 +1359,6 @@ prlsdkLoadDomains(parallelsConnPtr privconn)
 
  error:
     PrlHandle_Free(result);
-    PrlHandle_Free(job);
     return -1;
 }
 
@@ -1732,8 +1738,6 @@ prlsdkDomainChangeState(virDomainPtr domain,
 
     pdom = dom->privateData;
     pret = chstate(privconn, pdom->sdkdom);
-    virReportError(VIR_ERR_OPERATION_FAILED,
-                   _("Can't change domain state: %d"), pret);
     if (PRL_FAILED(pret)) {
         virResetLastError();
 
@@ -2562,10 +2566,12 @@ static const char * prlsdkFormatMac(virMacAddrPtr mac, char *macstr)
     return macstr;
 }
 
-static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net)
+static int prlsdkAddNet(PRL_HANDLE sdkdom, parallelsConnPtr privconn, virDomainNetDefPtr net)
 {
     PRL_RESULT pret;
     PRL_HANDLE sdknet = PRL_INVALID_HANDLE;
+    PRL_HANDLE vnet = PRL_INVALID_HANDLE;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
     int ret = -1;
     char macstr[PRL_MAC_STRING_BUFNAME];
 
@@ -2578,7 +2584,7 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net)
     pret = PrlVmDev_SetEnabled(sdknet, 1);
     prlsdkCheckRetGoto(pret, cleanup);
 
-    pret = PrlVmDev_SetConnected(sdknet, net->linkstate);
+    pret = PrlVmDev_SetConnected(sdknet, 1);
     prlsdkCheckRetGoto(pret, cleanup);
 
     if (net->ifname) {
@@ -2590,10 +2596,41 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net)
     pret = PrlVmDevNet_SetMacAddress(sdknet, macstr);
     prlsdkCheckRetGoto(pret, cleanup);
 
-    if (STREQ(net->data.network.name, PARALLELS_ROUTED_NETWORK_NAME)) {
-        pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED);
+    // Other alternatives: PNT_VIRTIO, PNT_RTL
+    pret = PrlVmDevNet_SetAdapterType(sdknet, PNT_E1000);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+        if (STREQ(net->data.network.name, PARALLELS_ROUTED_NETWORK_NAME)) {
+            pret = PrlVmDev_SetEmulatedType(sdknet, PNA_ROUTED);
+            prlsdkCheckRetGoto(pret, cleanup);
+        } else if (STREQ(net->data.network.name, PARALLELS_BRIDGED_NETWORK_NAME)) {
+            pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET);
+            prlsdkCheckRetGoto(pret, cleanup);
+
+            pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
+            prlsdkCheckRetGoto(pret, cleanup);
+        }
+    } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
+        // For this type of adapter we create a new
+        // Virtual Network assuming that bridge with given name exists
+        // Failing creating this means domain creation failure
+        pret = PrlVirtNet_Create(&vnet);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name);
         prlsdkCheckRetGoto(pret, cleanup);
-    } else {
+
+        pret = PrlVirtNet_SetNetworkType(vnet, PVN_BRIDGED_ETHERNET);
+        prlsdkCheckRetGoto(pret, cleanup);
+
+        job = PrlSrv_AddVirtualNetwork(privconn->server, vnet, 0);
+        if(PRL_FAILED(pret = waitJob(job, privconn->jobTimeout)))
+            goto cleanup;
+
+        pret = PrlVmDev_SetEmulatedType(sdknet, PNA_BRIDGED_ETHERNET);
+        prlsdkCheckRetGoto(pret, cleanup);
+
         pret = PrlVmDevNet_SetVirtualNetworkId(sdknet, net->data.network.name);
         prlsdkCheckRetGoto(pret, cleanup);
     }
@@ -2606,10 +2643,35 @@ static int prlsdkAddNet(PRL_HANDLE sdkdom, virDomainNetDefPtr net)
 
     ret = 0;
  cleanup:
+    PrlHandle_Free(vnet);
     PrlHandle_Free(sdknet);
     return ret;
 }
 
+static void prlsdkDelNet(parallelsConnPtr privconn, virDomainNetDefPtr net)
+{
+    PRL_RESULT pret;
+    PRL_HANDLE vnet = PRL_INVALID_HANDLE;
+    PRL_HANDLE job = PRL_INVALID_HANDLE;
+
+    if(net->type != VIR_DOMAIN_NET_TYPE_BRIDGE)
+        // nothing to do
+        return;
+
+    pret = PrlVirtNet_Create(&vnet);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    pret = PrlVirtNet_SetNetworkId(vnet, net->data.network.name);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    PrlSrv_DeleteVirtualNetwork(privconn->server, vnet, 0);
+    if(PRL_FAILED(pret = waitJob(job, privconn->jobTimeout)))
+        goto cleanup;
+
+cleanup:
+    PrlHandle_Free(vnet);
+}
+
 static int prlsdkAddDisk(PRL_HANDLE sdkdom, virDomainDiskDefPtr disk)
 {
     PRL_RESULT pret;
@@ -2769,7 +2831,8 @@ prlsdkAddFS(PRL_HANDLE sdkdom, virDomainFSDefPtr fs)
     return ret;
 }
 static int
-prlsdkDoApplyConfig(PRL_HANDLE sdkdom,
+prlsdkDoApplyConfig(virConnectPtr conn,
+                    PRL_HANDLE sdkdom,
                     virDomainDefPtr def)
 {
     PRL_RESULT pret;
@@ -2830,7 +2893,7 @@ prlsdkDoApplyConfig(PRL_HANDLE sdkdom,
     }
 
     for (i = 0; i < def->nnets; i++) {
-       if (prlsdkAddNet(sdkdom, def->nets[i]) < 0)
+       if (prlsdkAddNet(sdkdom, conn->privateData, def->nets[i]) < 0)
            goto error;
     }
 
@@ -2847,7 +2910,10 @@ prlsdkDoApplyConfig(PRL_HANDLE sdkdom,
     return 0;
 
  error:
-    return -1;
+     for (i = 0; i < def->nnets; i++)
+       prlsdkDelNet(conn->privateData, def->nets[i]);
+
+   return -1;
 }
 
 int
@@ -2868,7 +2934,7 @@ prlsdkApplyConfig(virConnectPtr conn,
     if (PRL_FAILED(waitJob(job, privconn->jobTimeout)))
         return -1;
 
-    ret = prlsdkDoApplyConfig(sdkdom, new);
+    ret = prlsdkDoApplyConfig(conn, sdkdom, new);
 
     if (ret == 0) {
         job = PrlVm_CommitEx(sdkdom, PVCF_DETACH_HDD_BUNDLE);
@@ -2905,7 +2971,10 @@ prlsdkCreateVm(virConnectPtr conn, virDomainDefPtr def)
     pret = PrlVmCfg_SetDefaultConfig(sdkdom, srvconf, PVS_GUEST_VER_LIN_REDHAT, 0);
     prlsdkCheckRetGoto(pret, cleanup);
 
-    ret = prlsdkDoApplyConfig(sdkdom, def);
+    pret = PrlVmCfg_SetOfflineManagementEnabled(sdkdom, 0);
+    prlsdkCheckRetGoto(pret, cleanup);
+
+    ret = prlsdkDoApplyConfig(conn, sdkdom, def);
     if (ret)
         goto cleanup;
 
@@ -2967,7 +3036,7 @@ prlsdkCreateCt(virConnectPtr conn, virDomainDefPtr def)
 
     }
 
-    ret = prlsdkDoApplyConfig(sdkdom, def);
+    ret = prlsdkDoApplyConfig(conn, sdkdom, def);
     if (ret)
         goto cleanup;
 
@@ -2986,8 +3055,13 @@ prlsdkUnregisterDomain(parallelsConnPtr privconn, virDomainObjPtr dom)
 {
     parallelsDomObjPtr privdom = dom->privateData;
     PRL_HANDLE job;
+    int i;
 
+    for (i = 0; i < dom->def->nnets; i++) {
+       prlsdkDelNet(privconn, dom->def->nets[i]);
+    }
     job = PrlVm_Unreg(privdom->sdkdom);
+
     if (PRL_FAILED(waitJob(job, privconn->jobTimeout)))
         return -1;
 
diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h
index bebf841..7296c89 100644
--- a/src/parallels/parallels_utils.h
+++ b/src/parallels/parallels_utils.h
@@ -48,6 +48,7 @@
     } while (0)
 
 # define PARALLELS_ROUTED_NETWORK_NAME   "Routed"
+# define PARALLELS_BRIDGED_NETWORK_NAME  "Bridged"
 
 struct _parallelsConn {
     virMutex lock;
-- 
1.7.1




More information about the libvir-list mailing list