[vbox-dev] [PATCH] VDE native support for VirtualBox v0.1

Michael Thayer Michael.Thayer at Sun.COM
Tue Apr 13 21:54:17 GMT 2010


Le lundi 12 avril 2010 à 12:46 +0200, Renzo Davoli a écrit :
> Okay. Here is the patch including an MIT license header as required.
> The license applies to the patch itself, not to the code already released
> under GPL by Innotek/Sun/Oracle.
Thank you.  I am attaching an updated version of the patch against the
current svn version of VirtualBox so that you can take a look.  I didn't
include your libvdeplug header in the patch.  (By the way, shouldn't
that header be trying to load libvdeplug.so.2, rather than
libvdeplug.so?  As far as I know, the version-less name is just a
symlink for the compiler's benefit, and should not be present on
non-developers' systems.)

Regards,

Michael

Index: src/VBox/Devices/Builtins.h
===================================================================
--- src/VBox/Devices/Builtins.h	(révision 59975)
+++ src/VBox/Devices/Builtins.h	(copie de travail)
@@ -106,6 +106,9 @@
 #if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
 extern const PDMDRVREG g_DrvHostInterface;
 #endif
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
+extern const PDMDRVREG g_DrvVDE;
+#endif
 extern const PDMDRVREG g_DrvIntNet;
 extern const PDMDRVREG g_DrvNAT;
 extern const PDMDRVREG g_DrvNetSniffer;
Index: src/VBox/Devices/Network/DrvVDE.cpp
===================================================================
--- src/VBox/Devices/Network/DrvVDE.cpp	(révision 0)
+++ src/VBox/Devices/Network/DrvVDE.cpp	(révision 0)
@@ -0,0 +1,650 @@
+/** $Id: DrvVDE.cpp $ */
+/** @file
+ * VDE network transport driver.
+ */
+
+/*
+ * Copyright (C) 2010 Renzo Davoli. VirtualSquare. University of
Bologna.
+ * Copyright (C) 2006-2010 Sun Microsystems, Inc.
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free
software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ */
+
+/*******************************************************************************
+*   Header Files
*
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_DRV_TUN
+#include <VBox/log.h>
+#include <VBox/pdmdrv.h>
+#include <VBox/pdmnetifs.h>
+#include <VBox/pdmnetinline.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/ctype.h>
+#include <iprt/file.h>
+#include <iprt/mem.h>
+#include <iprt/path.h>
+#include <iprt/semaphore.h>
+#include <iprt/string.h>
+#include <iprt/thread.h>
+#include <iprt/uuid.h>
+
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include "Builtins.h"
+#include "libvdeplug_dyn.h"
+
+struct vdepluglib      vdeplughdl;
+
+/*******************************************************************************
+*   Structures and Typedefs
*
+*******************************************************************************/
+/**
+ * Block driver instance data.
+ */
+typedef struct DRVVDE
+{
+    /** The network interface. */
+    PDMINETWORKUP           INetworkUp;
+    /** The network interface. */
+    PPDMINETWORKDOWN        pIAboveNet;
+    /** Pointer to the driver instance. */
+    PPDMDRVINS              pDrvIns;
+    /** VDE device file handle. */
+    RTFILE                  FileDevice;
+    /** The configured VDE device name. */
+    char                   *pszDeviceName;
+    /** VDE setup application. */
+    char                   *pszSetupApplication;
+    /** VDE terminate application. */
+    char                   *pszTerminateApplication;
+    /** The write end of the control pipe. */
+    RTFILE                  PipeWrite;
+    /** The read end of the control pipe. */
+    RTFILE                  PipeRead;
+    /** Reader thread. */
+    PPDMTHREAD              pThread;
+
+               VDECONN                 *vdeconn;
+#ifdef VBOX_WITH_STATISTICS
+    /** Number of sent packets. */
+    STAMCOUNTER             StatPktSent;
+    /** Number of sent bytes. */
+    STAMCOUNTER             StatPktSentBytes;
+    /** Number of received packets. */
+    STAMCOUNTER             StatPktRecv;
+    /** Number of received bytes. */
+    STAMCOUNTER             StatPktRecvBytes;
+    /** Profiling packet transmit runs. */
+    STAMPROFILE             StatTransmit;
+    /** Profiling packet receive runs. */
+    STAMPROFILEADV          StatReceive;
+#endif /* VBOX_WITH_STATISTICS */
+
+#ifdef LOG_ENABLED
+    /** The nano ts of the last transfer. */
+    uint64_t                u64LastTransferTS;
+    /** The nano ts of the last receive. */
+    uint64_t                u64LastReceiveTS;
+#endif
+} DRVVDE, *PDRVVDE;
+
+
+/** Converts a pointer to VDE::INetworkUp to a PRDVVDE. */
+#define PDMINETWORKUP_2_DRVVDE(pInterface)
( (PDRVVDE)((uintptr_t)pInterface - RT_OFFSETOF(DRVVDE, INetworkUp)) )
+
+
+/*******************************************************************************
+*   Internal Functions
*
+*******************************************************************************/
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
+ */
+static DECLCALLBACK(int) drvVDENetworkUp_AllocBuf(PPDMINETWORKUP
pInterface, size_t cbMin,
+                                                  PCPDMNETWORKGSO pGso,
PPPDMSCATTERGATHER ppSgBuf)
+{
+    PDRVVDE pThis = PDMINETWORKUP_2_DRVVDE(pInterface);
+
+    /*
+     * Allocate a scatter / gather buffer descriptor that is
immediately
+     * followed by the buffer space of its single segment.  The GSO
context
+     * comes after that again.
+     */
+    PPDMSCATTERGATHER pSgBuf = (PPDMSCATTERGATHER)RTMemAlloc(
RT_ALIGN_Z(sizeof(*pSgBuf), 16)
+                                                             +
RT_ALIGN_Z(cbMin, 16)
+                                                             + (pGso ?
RT_ALIGN_Z(sizeof(*pGso), 16) : 0));
+    if (!pSgBuf)
+        return VERR_NO_MEMORY;
+    /*
+     * Initialize the S/G buffer and return.
+     */
+    pSgBuf->fFlags         = PDMSCATTERGATHER_FLAGS_MAGIC |
PDMSCATTERGATHER_FLAGS_OWNER_1;
+    pSgBuf->cbUsed         = 0;
+    pSgBuf->cbAvailable    = RT_ALIGN_Z(cbMin, 16);
+    pSgBuf->pvAllocator    = NULL;
+    if (!pGso)
+        pSgBuf->pvUser     = NULL;
+    else
+    {
+        pSgBuf->pvUser     = (uint8_t *)(pSgBuf + 1) +
pSgBuf->cbAvailable;
+        *(PPDMNETWORKGSO)pSgBuf->pvUser = *pGso;
+    }
+    pSgBuf->cSegs          = 1;
+    pSgBuf->aSegs[0].cbSeg = pSgBuf->cbAvailable;
+    pSgBuf->aSegs[0].pvSeg = pSgBuf + 1;
+
+#if 0 /* poison */
+    memset(pSgBuf->aSegs[0].pvSeg, 'F', pSgBuf->aSegs[0].cbSeg);
+#endif
+    *ppSgBuf = pSgBuf;
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnFreeBuf}
+ */
+static DECLCALLBACK(int) drvVDENetworkUp_FreeBuf(PPDMINETWORKUP
pInterface, PPDMSCATTERGATHER pSgBuf)
+{
+    PDRVVDE pThis = PDMINETWORKUP_2_DRVVDE(pInterface);
+    if (pSgBuf)
+    {
+        Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) ==
PDMSCATTERGATHER_FLAGS_MAGIC);
+        pSgBuf->fFlags = 0;
+        RTMemFree(pSgBuf);
+    }
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
+ */
+static DECLCALLBACK(int) drvVDENetworkUp_SendBuf(PPDMINETWORKUP
pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
+{
+    PDRVVDE pThis = PDMINETWORKUP_2_DRVVDE(pInterface);
+    STAM_COUNTER_INC(&pThis->StatPktSent);
+    STAM_COUNTER_ADD(&pThis->StatPktSentBytes, pSgBuf->cbUsed);
+    STAM_PROFILE_START(&pThis->StatTransmit, a);
+
+    AssertPtr(pSgBuf);
+    Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) ==
PDMSCATTERGATHER_FLAGS_MAGIC);
+
+    int rc = VINF_SUCCESS;
+    if (!pSgBuf->pvUser)
+    {
+#ifdef LOG_ENABLED
+        uint64_t u64Now = RTTimeProgramNanoTS();
+        LogFlow(("drvVDESend: %-4d bytes at %llu ns  deltas: r=%llu t=%
llu\n",
+                 pSgBuf->cbUsed, u64Now, u64Now -
pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS));
+        pThis->u64LastTransferTS = u64Now;
+#endif
+        Log2(("drvVDESend: pSgBuf->aSegs[0].pvSeg=%p pSgBuf->cbUsed=%#x
\n"
+              "%.*Rhxd\n",
+              pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, pSgBuf->cbUsed,
pSgBuf->aSegs[0].pvSeg));
+
+        ssize_t prc = vdeplughdl.vde_send(pThis->vdeconn,
pSgBuf->aSegs[0].pvSeg, pSgBuf->cbUsed, 0);
+        if (prc < 0)
+            rc = RTErrConvertFromErrno(-prc);
+    }
+    else
+    {
+        uint8_t         abHdrScratch[256];
+        uint8_t const  *pbFrame = (uint8_t const
*)pSgBuf->aSegs[0].pvSeg;
+        PCPDMNETWORKGSO pGso    = (PCPDMNETWORKGSO)pSgBuf->pvUser;
+        uint32_t const  cSegs   = PDMNetGsoCalcSegmentCount(pGso,
pSgBuf->cbUsed);  Assert(cSegs > 1);
+        for (size_t iSeg = 0; iSeg < cSegs; iSeg++)
+        {
+            uint32_t cbSegFrame;
+            void *pvSegFrame = PDMNetGsoCarveSegmentQD(pGso, (uint8_t
*)pbFrame, pSgBuf->cbUsed, abHdrScratch,
+                                                       iSeg, cSegs,
&cbSegFrame);
+            ssize_t prc = vdeplughdl.vde_send(pThis->vdeconn,
pvSegFrame, cbSegFrame, 0);
+            if (prc < 0)
+            {
+                rc = RTErrConvertFromErrno(-prc);
+                break;
+            }
+        }
+    }
+
+    pSgBuf->fFlags = 0;
+    RTMemFree(pSgBuf);
+
+    STAM_PROFILE_STOP(&pThis->StatTransmit, a);
+    AssertRC(rc);
+    if (RT_FAILURE(rc))
+        rc = rc == VERR_NO_MEMORY ? VERR_NET_NO_BUFFER_SPACE :
VERR_NET_DOWN;
+    return rc;
+}
+
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
+ */
+static DECLCALLBACK(void) drvVDESetPromiscuousMode(PPDMINETWORKUP
pInterface, bool fPromiscuous)
+{
+    LogFlow(("drvVDESetPromiscuousMode: fPromiscuous=%d\n",
fPromiscuous));
+    /* nothing to do */
+}
+
+
+/**
+ * Notification on link status changes.
+ *
+ * @param   pInterface      Pointer to the interface structure
containing the called function pointer.
+ * @param   enmLinkState    The new link state.
+ * @thread  EMT
+ */
+static DECLCALLBACK(void) drvVDENotifyLinkChanged(PPDMINETWORKUP
pInterface, PDMNETWORKLINKSTATE enmLinkState)
+{
+    LogFlow(("drvNATNotifyLinkChanged: enmLinkState=%d\n",
enmLinkState));
+    /** @todo take action on link down and up. Stop the polling and
such like. */
+}
+
+
+/**
+ * Asynchronous I/O thread for handling receive.
+ *
+ * @returns VINF_SUCCESS (ignored).
+ * @param   Thread          Thread handle.
+ * @param   pvUser          Pointer to a DRVVDE structure.
+ */
+static DECLCALLBACK(int) drvVDEAsyncIoThread(PPDMDRVINS pDrvIns,
PPDMTHREAD pThread)
+{
+    PDRVVDE pThis = PDMINS_2_DATA(pDrvIns, PDRVVDE);
+    LogFlow(("drvVDEAsyncIoThread: pThis=%p\n", pThis));
+
+    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
+        return VINF_SUCCESS;
+
+    STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
+
+    /*
+     * Polling loop.
+     */
+    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
+    {
+        /*
+         * Wait for something to become available.
+         */
+        struct pollfd aFDs[2];
+        aFDs[0].fd      = vdeplughdl.vde_datafd(pThis->vdeconn);
+        aFDs[0].events  = POLLIN | POLLPRI;
+        aFDs[0].revents = 0;
+        aFDs[1].fd      = pThis->PipeRead;
+        aFDs[1].events  = POLLIN | POLLPRI | POLLERR | POLLHUP;
+        aFDs[1].revents = 0;
+        STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a);
+        errno=0;
+        int rc = poll(&aFDs[0], RT_ELEMENTS(aFDs), -1 /* infinite */);
+
+        /* this might have changed in the meantime */
+        if (pThread->enmState != PDMTHREADSTATE_RUNNING)
+            break;
+
+        STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
+        if (    rc > 0
+            &&  (aFDs[0].revents & (POLLIN | POLLPRI))
+            &&  !aFDs[1].revents)
+        {
+            /*
+             * Read the frame.
+             */
+            char achBuf[16384];
+            ssize_t cbRead = 0;
+                                               cbRead =
vdeplughdl.vde_recv(pThis->vdeconn, achBuf, sizeof(achBuf), 0);
+            if (cbRead >= 0)
+            {
+                /*
+                 * Wait for the device to have space for this frame.
+                 * Most guests use frame-sized receive buffers, hence
non-zero cbMax
+                 * automatically means there is enough room for entire
frame. Some
+                 * guests (eg. Solaris) use large chains of small
receive buffers
+                 * (each 128 or so bytes large). We will still start
receiving as soon
+                 * as cbMax is non-zero because:
+                 *  - it would be quite expensive for pfnCanReceive to
accurately
+                 *    determine free receive buffer space
+                 *  - if we were waiting for enough free buffers, there
is a risk
+                 *    of deadlocking because the guest could be waiting
for a receive
+                 *    overflow error to allocate more receive buffers
+                 */
+                STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a);
+                int rc1 =
pThis->pIAboveNet->pfnWaitReceiveAvail(pThis->pIAboveNet,
RT_INDEFINITE_WAIT);
+
+                STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
+
+                /*
+                 * A return code != VINF_SUCCESS means that we were
woken up during a VM
+                 * state transistion. Drop the packet and wait for the
next one.
+                 */
+                if (RT_FAILURE(rc1))
+                    continue;
+
+                /*
+                 * Pass the data up.
+                 */
+#ifdef LOG_ENABLED
+                uint64_t u64Now = RTTimeProgramNanoTS();
+                LogFlow(("drvVDEAsyncIoThread: %-4d bytes at %llu ns
deltas: r=%llu t=%llu\n",
+                         cbRead, u64Now, u64Now -
pThis->u64LastReceiveTS, u64Now - pThis->u64LastTransferTS));
+                pThis->u64LastReceiveTS = u64Now;
+#endif
+                Log2(("drvVDEAsyncIoThread: cbRead=%#x\n" "%.*Rhxd\n",
cbRead, cbRead, achBuf));
+                STAM_COUNTER_INC(&pThis->StatPktRecv);
+                STAM_COUNTER_ADD(&pThis->StatPktRecvBytes, cbRead);
+                rc = pThis->pIAboveNet->pfnReceive(pThis->pIAboveNet,
achBuf, cbRead);
+                AssertRC(rc);
+            }
+            else
+            {
+                LogFlow(("drvVDEAsyncIoThread: RTFileRead -> %Rrc\n",
rc));
+                if (rc == VERR_INVALID_HANDLE)
+                    break;
+                RTThreadYield();
+            }
+        }
+        else if (   rc > 0
+                 && aFDs[1].revents)
+        {
+            LogFlow(("drvVDEAsyncIoThread: Control message: enmState=%d
revents=%#x\n", pThread->enmState, aFDs[1].revents));
+            if (aFDs[1].revents & (POLLHUP | POLLERR | POLLNVAL))
+                break;
+
+            /* drain the pipe */
+            char ch;
+            size_t cbRead;
+            RTFileRead(pThis->PipeRead, &ch, 1, &cbRead);
+        }
+        else
+        {
+            /*
+             * poll() failed for some reason. Yield to avoid eating too
much CPU.
+             *
+             * EINTR errors have been seen frequently. They should be
harmless, even
+             * if they are not supposed to occur in our setup.
+             */
+            if (errno == EINTR)
+                Log(("rc=%d revents=%#x,%#x errno=%p %s\n", rc,
aFDs[0].revents, aFDs[1].revents, errno, strerror(errno)));
+            else
+                AssertMsgFailed(("rc=%d revents=%#x,%#x errno=%p %s\n",
rc, aFDs[0].revents, aFDs[1].revents, errno, strerror(errno)));
+            RTThreadYield();
+        }
+    }
+
+
+    LogFlow(("drvVDEAsyncIoThread: returns %Rrc\n", VINF_SUCCESS));
+    STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Unblock the send thread so it can respond to a state change.
+ *
+ * @returns VBox status code.
+ * @param   pDevIns     The pcnet device instance.
+ * @param   pThread     The send thread.
+ */
+static DECLCALLBACK(int) drvVDEAsyncIoWakeup(PPDMDRVINS pDrvIns,
PPDMTHREAD pThread)
+{
+    PDRVVDE pThis = PDMINS_2_DATA(pDrvIns, PDRVVDE);
+
+    int rc = RTFileWrite(pThis->PipeWrite, "", 1, NULL);
+    AssertRC(rc);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Queries an interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param   pInterface          Pointer to this interface structure.
+ * @param   enmInterface        The requested interface identification.
+ * @thread  Any thread.
+ */
+static DECLCALLBACK(void *) drvVDEQueryInterface(PPDMIBASE pInterface,
const char *pszIID)
+{
+    PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
+    PDRVVDE pThis      = PDMINS_2_DATA(pDrvIns, PDRVVDE);
+
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
+    PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKUP,
&pThis->INetworkUp);
+    return NULL;
+}
+
+
+/**
+ * Destruct a driver instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so
that any non-VM
+ * resources can be freed correctly.
+ *
+ * @param   pDrvIns     The driver instance data.
+ */
+static DECLCALLBACK(void) drvVDEDestruct(PPDMDRVINS pDrvIns)
+{
+    LogFlow(("drvVDEDestruct\n"));
+    PDRVVDE pThis = PDMINS_2_DATA(pDrvIns, PDRVVDE);
+
+    /*
+     * Terminate the control pipe.
+     */
+    if (pThis->PipeWrite != NIL_RTFILE)
+    {
+        int rc = RTFileClose(pThis->PipeWrite);
+        AssertRC(rc);
+        pThis->PipeWrite = NIL_RTFILE;
+    }
+    if (pThis->PipeRead != NIL_RTFILE)
+    {
+        int rc = RTFileClose(pThis->PipeRead);
+        AssertRC(rc);
+        pThis->PipeRead = NIL_RTFILE;
+    }
+
+    MMR3HeapFree(pThis->pszDeviceName);
+    MMR3HeapFree(pThis->pszSetupApplication);
+    MMR3HeapFree(pThis->pszTerminateApplication);
+
+#ifdef VBOX_WITH_STATISTICS
+    /*
+     * Deregister statistics.
+     */
+    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatPktSent);
+    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatPktSentBytes);
+    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatPktRecv);
+    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatPktRecvBytes);
+    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatTransmit);
+    PDMDrvHlpSTAMDeregister(pDrvIns, &pThis->StatReceive);
+#endif /* VBOX_WITH_STATISTICS */
+}
+
+
+/**
+ * Construct a VDE network transport driver instance.
+ *
+ * @copydoc FNPDMDRVCONSTRUCT
+ */
+static DECLCALLBACK(int) drvVDEConstruct(PPDMDRVINS pDrvIns, PCFGMNODE
pCfgHandle, uint32_t fFlags)
+{
+    PDRVVDE pThis = PDMINS_2_DATA(pDrvIns, PDRVVDE);
+
+    /*
+     * Init the static parts.
+     */
+    pThis->pDrvIns                      = pDrvIns;
+    pThis->pszDeviceName                = NULL;
+    pThis->pszSetupApplication          = NULL;
+    pThis->pszTerminateApplication      = NULL;
+    pThis->PipeRead                     = NIL_RTFILE;
+    pThis->PipeWrite                    = NIL_RTFILE;
+
+    /* IBase */
+    pDrvIns->IBase.pfnQueryInterface    = drvVDEQueryInterface;
+    /* INetwork */
+    pThis->INetworkUp.pfnSendBuf             = drvVDENetworkUp_SendBuf;
+    pThis->INetworkUp.pfnAllocBuf            =
drvVDENetworkUp_AllocBuf;
+    pThis->INetworkUp.pfnFreeBuf             = drvVDENetworkUp_FreeBuf;
+    pThis->INetworkUp.pfnSetPromiscuousMode  =
drvVDESetPromiscuousMode;
+    pThis->INetworkUp.pfnNotifyLinkChanged   = drvVDENotifyLinkChanged;
+
+               if (!CFGMR3AreValuesValid(pCfgHandle,
+                                       "Network\0"
+                                       "Trunk\0"
+                                       "TrunkType\0"
+                                       "ReceiveBufferSize\0"
+                                       "SendBufferSize\0"
+                                       "RestrictAccess\0"
+                                       "SharedMacOnWire\0"
+                                       "IgnoreAllPromisc\0"
+                                       "QuietlyIgnoreAllPromisc\0"
+                                       "IgnoreClientPromisc\0"
+                                       "QuietlyIgnoreClientPromisc\0"
+                                       "IgnoreTrunkWirePromisc\0"
+                                       "QuietlyIgnoreTrunkWirePromisc
\0"
+                                       "IgnoreTrunkHostPromisc\0"
+                                       "QuietlyIgnoreTrunkHostPromisc
\0"
+                                       "IsService\0"))
+                       return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
+
+               /*
+                * Query the network port interface.
+                */
+               pThis->pIAboveNet =
PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN);
+               if (!pThis->pIAboveNet)
+               {
+                       AssertMsgFailed(("Configuration error: the above
device/driver didn't export the network port interface!\n"));
+                       return VERR_PDM_MISSING_INTERFACE_ABOVE;
+               }
+
+               char szNetwork[PATH_MAX]; /* PATH_MAX */
+               int rc = CFGMR3QueryString(pCfgHandle, "Network",
szNetwork, sizeof(szNetwork));
+               if (RT_FAILURE(rc))
+                       *szNetwork=0;
+
+               /* LogRel(("VDEXXXXXX %s\n",szNetwork));*/
+
+    /*
+     * Read the configuration.
+     */
+               if (vdeplughdl.dl_handle == NULL)
+                       libvdeplug_dynopen(vdeplughdl);
+               if (vdeplughdl.dl_handle == NULL) {
+                       return PDMDrvHlpVMSetError(pThis->pDrvIns,
VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
+
N_("VDEplug library: not found"));
+               }
+
pThis->vdeconn=vdeplughdl.vde_open(szNetwork,"VirtualBOX",NULL);
+               if (pThis->vdeconn == NULL) {
+                       return PDMDrvHlpVMSetError(pThis->pDrvIns,
VERR_PDM_HIF_OPEN_FAILED, RT_SRC_POS,
+
N_("Failed to connect to the VDE SWITCH"));
+               }
+
+
+    rc = VINF_SUCCESS;
+
+    /*
+     * Create the control pipe.
+     */
+    int fds[2];
+    if (pipe(&fds[0]) != 0) /** @todo RTPipeCreate() or something... */
+    {
+        rc = RTErrConvertFromErrno(errno);
+        AssertRC(rc);
+        return rc;
+    }
+    pThis->PipeRead = fds[0];
+    pThis->PipeWrite = fds[1];
+
+    /*
+     * Create the async I/O thread.
+     */
+    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis,
drvVDEAsyncIoThread, drvVDEAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO,
"VDE");
+    AssertRCReturn(rc, rc);
+
+#ifdef VBOX_WITH_STATISTICS
+    /*
+     * Statistics.
+     */
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSent,
STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
"Number of sent packets.",          "/Drivers/VDE%d/Packets/Sent",
pDrvIns->iInstance);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktSentBytes,
STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
"Number of sent bytes.",            "/Drivers/VDE%d/Bytes/Sent",
pDrvIns->iInstance);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecv,
STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,
"Number of received packets.",      "/Drivers/VDE%d/Packets/Received",
pDrvIns->iInstance);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatPktRecvBytes,
STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
"Number of received bytes.",        "/Drivers/VDE%d/Bytes/Received",
pDrvIns->iInstance);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit,
STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
"Profiling packet transmit runs.",  "/Drivers/VDE%d/Transmit",
pDrvIns->iInstance);
+    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive,
STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,
"Profiling packet receive runs.",   "/Drivers/VDE%d/Receive",
pDrvIns->iInstance);
+#endif /* VBOX_WITH_STATISTICS */
+
+    return rc;
+}
+
+
+/**
+ * VDE network transport driver registration record.
+ */
+const PDMDRVREG g_DrvVDE =
+{
+    /* u32Version */
+    PDM_DRVREG_VERSION,
+    /* szDriverName */
+    "VDE",
+    /* szRCMod */
+    "",
+    /* szR0Mod */
+    "",
+    /* pszDescription */
+    "VDE Network Transport Driver",
+    /* fFlags */
+    PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
+    /* fClass. */
+    PDM_DRVREG_CLASS_NETWORK,
+    /* cMaxInstances */
+    ~0,
+    /* cbInstance */
+    sizeof(DRVVDE),
+    /* pfnConstruct */
+    drvVDEConstruct,
+    /* pfnDestruct */
+    drvVDEDestruct,
+    /* pfnRelocate */
+    NULL,
+    /* pfnIOCtl */
+    NULL,
+    /* pfnPowerOn */
+    NULL,
+    /* pfnReset */
+    NULL,
+    /* pfnSuspend */
+    NULL, /** @todo Do power on, suspend and resume handlers! */
+    /* pfnResume */
+    NULL,
+    /* pfnAttach */
+    NULL,
+    /* pfnDetach */
+    NULL,
+    /* pfnPowerOff */
+    NULL,
+    /* pfnSoftReset */
+    NULL,
+    /* u32EndVersion */
+    PDM_DRVREG_VERSION
+};
+
Index: src/VBox/Devices/Makefile.kmk
===================================================================
--- src/VBox/Devices/Makefile.kmk	(révision 59975)
+++ src/VBox/Devices/Makefile.kmk	(copie de travail)
@@ -1003,6 +1003,7 @@
 
 Drivers_SOURCES.linux = \
 	Network/DrvTAP.cpp \
+	Network/DrvVDE.cpp \
 	Audio/ossaudio.c \
 	Parallel/DrvHostParallel.cpp \
 	Serial/DrvHostSerial.cpp
Index: src/VBox/Devices/Builtins.cpp
===================================================================
--- src/VBox/Devices/Builtins.cpp	(révision 59975)
+++ src/VBox/Devices/Builtins.cpp	(copie de travail)
@@ -237,6 +237,13 @@
     if (RT_FAILURE(rc))
         return rc;
 #endif
+               /* ENABLE VDE */
+#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD)
+    rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvVDE);
+    if (RT_FAILURE(rc))
+        return rc;
+#endif
+               /* /ENABLE VDE */
     rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvIntNet);
     if (RT_FAILURE(rc))
         return rc;
Index: src/VBox/Main/include/NetworkAdapterImpl.h
===================================================================
--- src/VBox/Main/include/NetworkAdapterImpl.h	(révision 59975)
+++ src/VBox/Main/include/NetworkAdapterImpl.h	(copie de travail)
@@ -49,6 +49,9 @@
                  mCableConnected(TRUE), mLineSpeed(0),
mTraceEnabled(FALSE),
                  mHostInterface("") /* cannot be null */,
                  mNATNetwork("") /* cannot be null */
+                                                                /*
ENABLE VDE */
+                 , mVDENetwork("") /* can be null */
+                                                                /* /ENABLE VDE */
         {}
 
         NetworkAdapterType_T mAdapterType;
@@ -63,6 +66,8 @@
         Bstr mHostInterface;
         Bstr mInternalNetwork;
         Bstr mNATNetwork;
+        /* ENABLE VDE */
+        Bstr mVDENetwork;
         ULONG mBootPriority;
     };
 
@@ -104,6 +109,10 @@
     STDMETHOD(COMSETTER(InternalNetwork)) (IN_BSTR aInternalNetwork);
     STDMETHOD(COMGETTER(NATNetwork)) (BSTR *aNATNetwork);
     STDMETHOD(COMSETTER(NATNetwork)) (IN_BSTR aNATNetwork);
+               /* ENABLE VDE */
+    STDMETHOD(COMGETTER(VDENetwork)) (BSTR *aVDENetwork);
+    STDMETHOD(COMSETTER(VDENetwork)) (IN_BSTR aVDENetwork);
+               /* /ENABLE VDE */
     STDMETHOD(COMGETTER(CableConnected)) (BOOL *aConnected);
     STDMETHOD(COMSETTER(CableConnected)) (BOOL aConnected);
     STDMETHOD(COMGETTER(TraceEnabled)) (BOOL *aEnabled);
@@ -121,6 +130,9 @@
     STDMETHOD(AttachToBridgedInterface)();
     STDMETHOD(AttachToInternalNetwork)();
     STDMETHOD(AttachToHostOnlyInterface)();
+               /* ENABLE VDE */
+    STDMETHOD(AttachToVDE)();
+               /* /ENABLE VDE */
     STDMETHOD(Detach)();
 
     // public methods only for internal purposes
Index: src/VBox/Main/NetworkAdapterImpl.cpp
===================================================================
--- src/VBox/Main/NetworkAdapterImpl.cpp	(révision 59975)
+++ src/VBox/Main/NetworkAdapterImpl.cpp	(copie de travail)
@@ -609,6 +609,52 @@
     return S_OK;
 }
 
+/* ENABLE VDE */
+STDMETHODIMP NetworkAdapter::COMGETTER(VDENetwork) (BSTR *aVDENetwork)
+{
+    CheckComArgOutPointerValid(aVDENetwork);
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    mData->mVDENetwork.cloneTo(aVDENetwork);
+
+    return S_OK;
+}
+
+STDMETHODIMP NetworkAdapter::COMSETTER(VDENetwork) (IN_BSTR
aVDENetwork)
+{
+    Bstr bstrEmpty("");
+    if (!aVDENetwork)
+        aVDENetwork = bstrEmpty;
+
+    AutoCaller autoCaller(this);
+    if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+    /* the machine needs to be mutable */
+    AutoMutableStateDependency adep (mParent);
+    if (FAILED(adep.rc())) return adep.rc();
+
+    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+    if (mData->mVDENetwork != aVDENetwork)
+    {
+        mData.backup();
+        mData->mVDENetwork = aVDENetwork;
+
+        /* leave the lock before informing callbacks */
+        alock.release();
+
+        mParent->onNetworkAdapterChange (this, FALSE);
+    }
+
+    return S_OK;
+}
+
+/* /ENABLE VDE */
+
 STDMETHODIMP NetworkAdapter::COMGETTER(CableConnected) (BOOL
*aConnected)
 {
     CheckComArgOutPointerValid(aConnected);
@@ -1047,6 +1093,51 @@
     return S_OK;
 }
 
+/* ENABLE VDE */
+STDMETHODIMP NetworkAdapter::AttachToVDE()
+{
+       AutoCaller autoCaller(this);
+       if (FAILED(autoCaller.rc())) return autoCaller.rc();
+
+       /* the machine needs to be mutable */
+       AutoMutableStateDependency adep (mParent);
+       if (FAILED(adep.rc())) return adep.rc();
+
+       AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
+
+       /* don't do anything if we're already host interface attached */
+       if (mData->mAttachmentType != NetworkAttachmentType_VDE)
+       {
+               mData.backup();
+
+               /* first detach the current attachment */
+               // Commented this for now as it reset the parameter
mData->mHostInterface
+               // which is essential while changing the Attachment
dynamically.
+               //detach();
+
+               mData->mAttachmentType = NetworkAttachmentType_VDE;
+
+               /* leave the lock before informing callbacks */
+               alock.release();
+
+               HRESULT rc = mParent->onNetworkAdapterChange (this,
TRUE);
+               if (FAILED (rc))
+               {
+                       /* If changing the attachment failed then we
can't assume
+                        * that the previous attachment will attach
correctly
+                        * and thus return error along with dettaching
all
+                        * attachments.
+                        */
+                       Detach();
+                       return rc;
+               }
+       }
+
+       return S_OK;
+}
+
+/* /ENABLE VDE */
+
 STDMETHODIMP NetworkAdapter::Detach()
 {
     AutoCaller autoCaller(this);
@@ -1155,6 +1246,15 @@
             if (FAILED(rc)) return rc;
         break;
 
+                               /* ENABLE VDE */
+        case NetworkAttachmentType_VDE:
+                                   mData->mVDENetwork = data.strName;
+                                   rc = AttachToVDE();
+                                   if (FAILED(rc)) return rc;
+                               break;
+                               /* ENABLE VDE */
+
+
         case NetworkAttachmentType_Null:
             rc = Detach();
             if (FAILED(rc)) return rc;
@@ -1219,6 +1319,10 @@
         case NetworkAttachmentType_HostOnly:
             data.strName = mData->mHostInterface;
         break;
+
+        case NetworkAttachmentType_VDE:
+            data.strName = mData->mVDENetwork;
+        break;
     }
 
     // after saving settings, we are no longer different from the XML
on disk
Index: src/VBox/Main/ConsoleImpl2.cpp
===================================================================
--- src/VBox/Main/ConsoleImpl2.cpp	(révision 59975)
+++ src/VBox/Main/ConsoleImpl2.cpp	(copie de travail)
@@ -3412,6 +3412,29 @@
             break;
         }
 
+                               /* ENABLE VDE */
+        case NetworkAttachmentType_VDE:
+        {
+            hrc = aNetworkAdapter->COMGETTER(VDENetwork)(&str);    H();
+#if 0
+                                               if (str) {
+                                                       Utf8Str strUtf8
= str;
+                                                       LogRel(("VDE
Network %s\n",(char *)strUtf8.raw()));
+                                               }
+#endif
+                                               rc =
CFGMR3InsertNode(pInst, "LUN#0", &pLunL0); RC_CHECK();
+                                               rc =
CFGMR3InsertString(pLunL0, "Driver", "VDE");    RC_CHECK();
+                                               rc =
CFGMR3InsertNode(pLunL0, "Config", &pCfg);         RC_CHECK();
+            if (str && *str) {
+                rc = CFGMR3InsertStringW(pCfg, "Network", str);
RC_CHECK();
+
networkName = str;
+                                               }
+                                               rc =
CFGMR3InsertInteger(pCfg, "TrunkType", kIntNetTrunkType_WhateverNone);
RC_CHECK();
+                                               STR_FREE();
+            break;
+                               }
+                               /* /ENABLE VDE */
+
         default:
             AssertMsgFailed(("should not get here!\n"));
             break;
@@ -3429,6 +3452,7 @@
         case NetworkAttachmentType_Internal:
         case NetworkAttachmentType_HostOnly:
         case NetworkAttachmentType_NAT:
+        case NetworkAttachmentType_VDE:
         {
             if (SUCCEEDED(hrc) && SUCCEEDED(rc))
             {
Index: src/VBox/Main/xml/Settings.cpp
===================================================================
--- src/VBox/Main/xml/Settings.cpp	(révision 59975)
+++ src/VBox/Main/xml/Settings.cpp	(copie de travail)
@@ -1888,6 +1888,13 @@
             if (!pelmAdapterChild->getAttributeValue("name",
nic.strName))    // required network name
                 throw ConfigFileError(this, pelmAdapterChild,
N_("Required HostOnlyInterface/@name element is missing"));
         }
+                               /* ENABLE VDE */
+        else if ((pelmAdapterChild =
pelmAdapter->findChildElement("VDE")))
+        {
+            nic.mode = NetworkAttachmentType_VDE;
+            pelmAdapterChild->getAttributeValue("network",
nic.strName);    // optional network name
+                               }
+                               /* /ENABLE VDE */
         // else: default is NetworkAttachmentType_Null
 
         ll.push_back(nic);
@@ -3387,6 +3394,13 @@

pelmAdapter->createChild("HostOnlyInterface")->setAttribute("name",
nic.strName);
             break;
 
+                                               /* ENABLE VDE */
+                                               case
NetworkAttachmentType_VDE:
+                pelmNAT = pelmAdapter->createChild("VDE");
+                                                               if
(nic.strName.length())
+
pelmNAT->setAttribute("network", nic.strName);
+                                               /* /ENABLE VDE */
+
             default: /*case NetworkAttachmentType_Null:*/
             break;
         }
Index: src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- src/VBox/Main/idl/VirtualBox.xidl	(révision 59975)
+++ src/VBox/Main/idl/VirtualBox.xidl	(copie de travail)
@@ -11532,6 +11532,9 @@
     <const name="Bridged"               value="2"/>
     <const name="Internal"              value="3"/>
     <const name="HostOnly"              value="4"/>
+               <!-- ENABLE VDE -->
+    <const name="VDE"                   value="5"/>
+               <!-- /ENABLE VDE -->
   </enum>
 
   <enum
@@ -11634,6 +11637,14 @@
       </desc>
     </attribute>
 
+               <!-- ENABLE VDE -->
+    <attribute name="VDENetwork" type="wstring">
+      <desc>
+        Name of the VDE switch the VM is attached to.
+      </desc>
+    </attribute>
+               <!-- /ENABLE VDE -->
+
     <attribute name="cableConnected" type="boolean">
       <desc>
         Flag whether the adapter reports the cable as connected or not.
@@ -11700,6 +11711,14 @@
       </desc>
     </method>
 
+               <!-- ENABLE VDE -->
+    <method name="attachToVDE">
+      <desc>
+        Attach the network adapter to a VDE network.
+      </desc>
+    </method>
+               <!-- /ENABLE VDE -->
+
     <method name="detach">
       <desc>
         Detach the network adapter
Index:
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.ui
===================================================================
---
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.ui
(révision 59975)
+++
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.ui
(copie de travail)
@@ -110,7 +110,7 @@
          </sizepolicy>
         </property>
         <property name="whatsThis" >
-         <string>Selects the name of the network adapter for
<b>Bridged Adapter</b> or <b>Host-only
Adapter</b> attachments and the name of the network
<b>Internal Network</b> attachments.</string>
+         <string>Selects the name of the network adapter for
<b>Bridged Adapter</b> or <b>Host-only
Adapter</b> attachments and the name of the network
<b>Internal Network</b> or the switch for
<b>VDE</b> attachments.</string>
         </property>
        </widget>
       </item>
Index:
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.h
===================================================================
---
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.h
(révision 59975)
+++
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.h
(copie de travail)
@@ -76,6 +76,9 @@
     QString mBrgName;
     QString mIntName;
     QString mHoiName;
+               /* ENABLE VDE */
+    QString mVDEName;
+               /* /ENABLE VDE */
 
     bool mPolished;
     bool mDisableStaticControls;
@@ -92,6 +95,7 @@
     QStringList brgList (bool aRefresh = false);
     QStringList intList (bool aRefresh = false);
     QStringList hoiList (bool aRefresh = false);
+    QStringList vdeList (bool aRefresh = false);
 
 protected:
 
Index:
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.cpp
===================================================================
---
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.cpp
(révision 59975)
+++
src/VBox/Frontends/VirtualBox/src/settings/vm/VBoxVMSettingsNetwork.cpp
(copie de travail)
@@ -104,6 +104,12 @@
             mHoiName = mAdapter.GetHostInterface();
             if (mHoiName.isEmpty()) mHoiName = QString::null;
             break;
+                                               /* ENABLE VDE */
+        case KNetworkAttachmentType_VDE:
+            mVDEName = mAdapter.GetVDENetwork();
+            if (mVDEName.isEmpty()) mVDEName = QString::null;
+            break;
+                                               /* /ENABLE VDE */
         default:
             break;
     }
@@ -144,6 +150,12 @@
             mAdapter.SetHostInterface (alternativeName());
             mAdapter.AttachToHostOnlyInterface();
             break;
+                                               /* ENABLE VDE */
+                               case KNetworkAttachmentType_VDE:
+                                               mAdapter.SetVDENetwork
(alternativeName());
+                                               mAdapter.AttachToVDE();
+                                               break;
+                                               /* /ENABLE VDE */
         default:
             break;
     }
@@ -256,6 +268,11 @@
         case KNetworkAttachmentType_HostOnly:
             result = mHoiName;
             break;
+                                               /* ENABLE VDE*/
+        case KNetworkAttachmentType_VDE:
+            result = mVDEName;
+            break;
+                                               /* /ENABLE VDE*/
         default:
             break;
     }
@@ -332,6 +349,13 @@
             mCbAdapterName->insertItems (0, mParent->hoiList());
             mCbAdapterName->setEditable (false);
             break;
+                                               /* ENABLE VDE */
+        case KNetworkAttachmentType_VDE:
+
mCbAdapterName->insertItem(0, alternativeName());
+            mCbAdapterName->setEditable (true);
+            mCbAdapterName->setCompleter (0);
+            break;
+                                               /* /ENABLE VDE */
         default:
             break;
     }
@@ -431,6 +455,20 @@
                 mHoiName = newName;
             break;
         }
+                               /* ENABLE VDE */
+        case KNetworkAttachmentType_VDE:
+        {
+            QString newName ((mCbAdapterName->itemData
(mCbAdapterName->currentIndex()).toString() ==
+                              QString (emptyItemCode) &&
+                              mCbAdapterName->currentText() ==
+                              mCbAdapterName->itemText
(mCbAdapterName->currentIndex())) ||
+                              mCbAdapterName->currentText().isEmpty() ?
+                              QString::null :
mCbAdapterName->currentText());
+            if (mVDEName != newName)
+                mVDEName = newName;
+            break;
+        }
+                               /* /ENABLE VDE */
         default:
             break;
     }
@@ -547,6 +585,14 @@
         KNetworkAttachmentType_HostOnly);
     mCbAttachmentType->setItemData (4,
         mCbAttachmentType->itemText (4), Qt::ToolTipRole);
+               /* ENABLE VDE */
+    mCbAttachmentType->insertItem (5,
+        vboxGlobal().toString (KNetworkAttachmentType_VDE));
+    mCbAttachmentType->setItemData (5,
+        KNetworkAttachmentType_VDE);
+    mCbAttachmentType->setItemData (5,
+        mCbAttachmentType->itemText (5), Qt::ToolTipRole);
+               /* /ENABLE VDE */
 
     /* Set the old value */
     mCbAttachmentType->setCurrentIndex (currentAttachment);
Index: src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp	(révision
59975)
+++ src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp	(copie de
travail)
@@ -2154,6 +2154,11 @@
                 else if (type == KNetworkAttachmentType_HostOnly)
                     attType = attType.arg (tr ("Host-only adapter, '%
1'",
                         "details report (network)").arg
(adapter.GetHostInterface()));
+                                                               /*
ENABLE VDE */
+                else if (type == KNetworkAttachmentType_VDE)
+                    attType = attType.arg (tr ("VDE network, '%1'",
+                        "details report (network)").arg
(adapter.GetVDENetwork()));
+                                                               /* /ENABLE VDE */
                 else
                     attType = attType.arg (vboxGlobal().toString
(type));
 
@@ -3112,6 +3117,10 @@
         tr ("Internal Network", "NetworkAttachmentType");
     mNetworkAttachmentTypes [KNetworkAttachmentType_HostOnly] =
         tr ("Host-only Adapter", "NetworkAttachmentType");
+               /* ENABLE VDE */
+    mNetworkAttachmentTypes [KNetworkAttachmentType_VDE] =
+        tr ("VDE Adapter", "NetworkAttachmentType");
+               /* /ENABLE VDE */
 
     mClipboardTypes [KClipboardMode_Disabled] =
         tr ("Disabled", "ClipboardType");


-- 
Sun Microsystems GmbH        Michael Thayer
Werkstrasse 24               VirtualBox engineer
71384 Weinstadt, Germany     mailto:michael.thayer at sun.com

Sitz der Gesellschaft:
Sun Microsystems GmbH, Sonnenallee 1, 85551 Kirchheim-Heimstetten
Amtsgericht Muenchen: HRB 161028
Geschaeftsfuehrer: Jürgen Kunz





More information about the vbox-dev mailing list