On Fri, Apr 24, 2009 at 4:07 AM, Antonio Augusto (Mancha)
<[email protected]> wrote:
> Hey Guys,
>
> I'm working on a security project and would like to do some
> experiments with arp/dns poisoning, but to do so I'd need that the
> network the VMs are connected behaved like a switched one, that is:
> packets arrive only on the interface to where they are destined.
> I've tried looking on the code, specially in
> src/VBox/Devices/Network/DrvIntNet.cpp but I couldn't quite understand
> how the "receiving" works ...
> I see that there is a ringbuffer one the drvIntNetAsyncIoRun , but i
> don't get if this buffer is exclusive for each interface or if its the
> "network" buffer.
>
> Its a bit late in my side of the world, and my eyes are heavy, so I
> might be misunderstanding something, but if one of the developers
> could point me on the right direction, and maybe elaborate a bit on
> how network work on VBox It'd be of great help.
>
> Thanks a lot!
Hola!
Precisely I'm working in a patch to make virtualbox host-only and
internal networks work in "mesh" mode. So that I can configure each
interface connected to a network to which other network interfaces is
it directly connected to. I want to do that for testing using
virtuabox my final project which is an implementation of the AODV mesh
networks routing protocol. Yesterday I "finished" the patch i.e. it
compiles and in theory it should work but I didn't have enough time
yet to test it. I attach it to this email so that others can review
the patch and/or help me developing it. My final aim is that it works
and it gets integrated in trunk :P. Any comments about this patch are
welcome!
Regards,
Eduardo Robles Elvira.
Index: include/VBox/intnet.h
===================================================================
--- include/VBox/intnet.h (revisión: 18845)
+++ include/VBox/intnet.h (copia de trabajo)
@@ -35,6 +35,7 @@
#include <VBox/sup.h>
#include <iprt/assert.h>
#include <iprt/asm.h>
+#include <iprt/types.h>
__BEGIN_DECLS
@@ -664,12 +665,14 @@
#define INTNET_OPEN_FLAGS_IGNORE_PROMISC_TRUNK_HOST RT_BIT_32(6)
/** Ignore any requests for promiscuous mode on the trunk host connection, quietly applied/ignored on open. */
#define INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC_TRUNK_HOST RT_BIT_32(7)
+/** Mesh mode. */
+#define INTNET_OPEN_FLAGS_MESH_MODE RT_BIT_32(8)
/** The mask of flags which causes flag incompatibilities. */
#define INTNET_OPEN_FLAGS_COMPATIBILITY_XOR_MASK (RT_BIT_32(0) | RT_BIT_32(1) | RT_BIT_32(2) | RT_BIT_32(4) | RT_BIT_32(6))
/** The mask of flags is always ORed in, even on open. (the quiet stuff) */
#define INTNET_OPEN_FLAGS_SECURITY_OR_MASK (RT_BIT_32(3) | RT_BIT_32(5) | RT_BIT_32(7))
/** The mask of valid flags. */
-#define INTNET_OPEN_FLAGS_MASK UINT32_C(0x000000ff)
+#define INTNET_OPEN_FLAGS_MASK UINT32_C(0x0000008f)
/** @} */
/** The maximum length of a network name. */
@@ -678,7 +681,6 @@
/** The maximum length of a trunk name. */
#define INTNET_MAX_TRUNK_NAME 64
-
/**
* Request buffer for INTNETR0OpenReq / VMMR0_DO_INTNET_OPEN.
* @see INTNETR0Open.
@@ -695,6 +697,10 @@
/** What to connect to the trunk port. (input)
* This is specific to the trunk type below. */
char szTrunk[INTNET_MAX_TRUNK_NAME];
+ /** The uuid of the machine in which the network interface resides */
+ char machineId[RTUUID_STR_LENGTH];
+ /** The port in which this interface is connected in the above machine. */
+ uint32_t machinePort;
/** The type of trunk link (NAT, Filter, TAP, etc). (input) */
INTNETTRUNKTYPE enmTrunkType;
/** Flags, see INTNET_OPEN_FLAGS_*. (input) */
@@ -703,6 +709,8 @@
uint32_t cbSend;
/** The size of the receive buffer. (input) */
uint32_t cbRecv;
+ /** The slot to which the network interface is connected to */
+ uint32_t slot;
/** The handle to the network interface. (output) */
INTNETIFHANDLE hIf;
} INTNETOPENREQ;
@@ -797,7 +805,30 @@
INTNETR0DECL(int) INTNETR0IfSetMacAddressReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFSETMACADDRESSREQ pReq);
+/**
+ * Request buffer for INTNETR0IfAddMeshNode / VMMR0_DO_INTNET_IF_ADD_MESH_NODE
+ * @see INTNETR0IfSetMacAddress.
+ */
+typedef struct INTNETIFADDMESHNODEREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Alternative to passing the taking the session from the VM handle.
+ * Either use this member or use the VM handle, don't do both. */
+ PSUPDRVSESSION pSession;
+ /** Handle to the interface. */
+ INTNETIFHANDLE hIf;
+ /** The slot to which the network interface is associated with. */
+ uint32_t slot;
+ /** The uuid of the machine in which the network interface resides */
+ char machineId[RTUUID_STR_LENGTH];
+} INTNETIFADDMESHNODEREQ;
+/** Pointer to an INTNETIFADDMESHNODEREQ request buffer. */
+typedef INTNETIFADDMESHNODEREQ *PINTNETIFADDMESHNODEREQ;
+INTNETR0DECL(int) INTNETR0IfAddMeshNodeReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFADDMESHNODEREQ pReq);
+
+
/**
* Request buffer for INTNETR0IfSetActiveReq / VMMR0_DO_INTNET_IF_SET_ACTIVE.
* @see INTNETR0IfSetActive.
@@ -896,10 +927,13 @@
* @param cbSend The send buffer size.
* @param cbRecv The receive buffer size.
* @param phIf Where to store the handle to the network interface.
+ * @param machineId The id of machine the machine to which this interface is connected to.
+ * @param slot The slot to which this interface is associated with in the parent machine.
*/
INTNETR0DECL(int) INTNETR0Open(PINTNET pIntNet, PSUPDRVSESSION pSession, const char *pszNetwork,
INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags,
- unsigned cbSend, unsigned cbRecv, PINTNETIFHANDLE phIf);
+ unsigned cbSend, unsigned cbRecv, PINTNETIFHANDLE phIf, const char *machineId,
+ unsigned slot);
/**
* Close an interface.
@@ -944,6 +978,7 @@
*/
INTNETR0DECL(int) INTNETR0IfSetPromiscuousMode( PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fPromiscuous);
INTNETR0DECL(int) INTNETR0IfSetMacAddress( PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, PCRTMAC pMac);
+INTNETR0DECL(int) INTNETR0IfAddMeshNode( PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, const char* machineId, uint32_t slot);
INTNETR0DECL(int) INTNETR0IfSetActive( PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, bool fActive);
/**
Index: include/VBox/vmm.h
===================================================================
--- include/VBox/vmm.h (revisión: 18845)
+++ include/VBox/vmm.h (copia de trabajo)
@@ -251,6 +251,8 @@
VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,
/** Call INTNETR0IfSetMacAddress(). */
VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS,
+ /** Call INTNETR0IfAddMeshNode(). */
+ VMMR0_DO_INTNET_IF_ADD_MESH_NODE,
/** Call INTNETR0IfSetActive(). */
VMMR0_DO_INTNET_IF_SET_ACTIVE,
/** Call INTNETR0IfSend(). */
Index: src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- src/VBox/VMM/VMMR0/VMMR0.cpp (revisión: 18845)
+++ src/VBox/VMM/VMMR0/VMMR0.cpp (copia de trabajo)
@@ -931,6 +931,13 @@
return VERR_NOT_SUPPORTED;
return INTNETR0IfSetMacAddressReq(g_pIntNet, pSession, (PINTNETIFSETMACADDRESSREQ)pReqHdr);
+ case VMMR0_DO_INTNET_IF_ADD_MESH_NODE:
+ if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFADDMESHNODEREQ)pReqHdr)->pSession, pSession))
+ return VERR_INVALID_PARAMETER;
+ if (!g_pIntNet)
+ return VERR_NOT_SUPPORTED;
+ return INTNETR0IfAddMeshNodeReq(g_pIntNet, pSession, (PINTNETIFADDMESHNODEREQ)pReqHdr);
+
case VMMR0_DO_INTNET_IF_SET_ACTIVE:
if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSETACTIVEREQ)pReqHdr)->pSession, pSession))
return VERR_INVALID_PARAMETER;
Index: src/VBox/Devices/Network/SrvIntNetR0.cpp
===================================================================
--- src/VBox/Devices/Network/SrvIntNetR0.cpp (revisión: 18845)
+++ src/VBox/Devices/Network/SrvIntNetR0.cpp (copia de trabajo)
@@ -107,6 +107,7 @@
/** Pointer to a const address cache. */
typedef INTNETADDRCACHE const *PCINTNETADDRCACHE;
+struct INTNETMESHNODE;
/**
* A network interface.
@@ -159,10 +160,35 @@
void *pvObj;
/** The network layer address cache. (Indexed by type, 0 entry isn't used.) */
INTNETADDRCACHE aAddrCache[kIntNetAddrType_End];
+ /** The slot to which the network interface is associated with. */
+ uint32_t slot;
+ /** The uuid of the machine in which the network interface resides */
+ char machineId[RTUUID_STR_LENGTH];
+ /** The list of mesh neighbours to which this interface is connected to */
+ struct INTNETMESHNODE *meshNeighbours;
} INTNETIF;
/** Pointer to an internal network interface. */
typedef INTNETIF *PINTNETIF;
+/**
+ * A reference to a mesh node (which ultimately is a pointer to a network
+ * interface).
+ *
+ * Unless explicitly stated, all members are protect by the network semaphore.
+ */
+typedef struct INTNETMESHNODE
+{
+ /** The slot to which the network interface of the node is associated with. */
+ uint32_t slot;
+ /** The uuid of the machine in which the network interface of the node resides */
+ char machineId[RTUUID_STR_LENGTH];
+ /** The network interface of the node */
+ PINTNETIF pIf;
+ /** Pointer to the next mesh node.
+ * This is protected by the INTNET::FastMutex. */
+ struct INTNETMESHNODE *pNext;
+} INTNETMESHNODE;
+typedef INTNETMESHNODE *PINTNETMESHNODE;
/**
* A trunk interface.
@@ -2089,9 +2115,14 @@
*
* Write the packet to all the interfaces and signal them.
*/
- for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
- if (pIf != pIfSender)
- intnetR0IfSend(pIf, pIfSender, pSG, NULL);
+ if(!pIfSender || !(pIfSender->pNetwork->fFlags & INTNET_OPEN_FLAGS_MESH_MODE))
+ for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
+ if (pIf != pIfSender)
+ intnetR0IfSend(pIf, pIfSender, pSG, NULL);
+ else
+ for (PINTNETMESHNODE neighbour = pIfSender->meshNeighbours; neighbour; neighbour = neighbour->pNext)
+ if (neighbour->pIf)
+ intnetR0IfSend(neighbour->pIf, pIfSender, pSG, NULL);
/*
* Unless the trunk is the origin, broadcast it to both the wire
@@ -2279,20 +2310,36 @@
* Only send to the interfaces with matching a MAC address.
*/
bool fExactIntNetRecipient = false;
- for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
- {
- bool fIt = false;
- if ( ( !pIf->fMacSet
- || (fIt = !memcmp(&pIf->Mac, &pEthHdr->DstMac, sizeof(pIf->Mac))) )
- || ( pIf->fPromiscuous
- && !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC))
- && pIf != pIfSender /* promiscuous mode: omit the sender */))
+ if(!pIfSender || !(pIfSender->pNetwork->fFlags & INTNET_OPEN_FLAGS_MESH_MODE))
+ for (PINTNETIF pIf = pNetwork->pIFs; pIf; pIf = pIf->pNext)
{
- Log2(("Dst=%.6Rhxs => %.6Rhxs\n", &pEthHdr->DstMac, &pIf->Mac));
- fExactIntNetRecipient |= fIt;
- intnetR0IfSend(pIf, pIfSender, pSG, NULL);
+ bool fIt = false;
+ if ( ( !pIf->fMacSet
+ || (fIt = !memcmp(&pIf->Mac, &pEthHdr->DstMac, sizeof(pIf->Mac))) )
+ || ( pIf->fPromiscuous
+ && !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC))
+ && pIf != pIfSender /* promiscuous mode: omit the sender */))
+ {
+ Log2(("Dst=%.6Rhxs => %.6Rhxs\n", &pEthHdr->DstMac, &pIf->Mac));
+ fExactIntNetRecipient |= fIt;
+ intnetR0IfSend(pIf, pIfSender, pSG, NULL);
+ }
}
- }
+ else
+ for (PINTNETMESHNODE neighbour = pIfSender->meshNeighbours; neighbour; neighbour = neighbour->pNext)
+ if (neighbour->pIf)
+ {
+ bool fIt = false;
+ if ( ( !neighbour->pIf->fMacSet
+ || (fIt = !memcmp(&neighbour->pIf->Mac, &pEthHdr->DstMac, sizeof(neighbour->pIf->Mac))) )
+ || ( neighbour->pIf->fPromiscuous
+ && !(pNetwork->fFlags & (INTNET_OPEN_FLAGS_IGNORE_PROMISC | INTNET_OPEN_FLAGS_QUIETLY_IGNORE_PROMISC))))
+ {
+ Log2(("Dst=%.6Rhxs => %.6Rhxs\n", &pEthHdr->DstMac, &neighbour->pIf->Mac));
+ fExactIntNetRecipient |= fIt;
+ intnetR0IfSend(neighbour->pIf, pIfSender, pSG, NULL);
+ }
+ }
/*
* Send it to the trunk?
@@ -2829,6 +2876,76 @@
/**
+ * Add a new mesh node to the interface, but only if it's in mesh mode.
+ *
+ * @returns VBox status code.
+ * @param pIntNet The instance handle.
+ * @param hIf The interface handle.
+ * @param pSession The caller's session.
+ * @param machineId The id of machine the machine to which this interface is connected to.
+ * @param slot The slot to which this interface is associated with in the parent machine.
+ */
+INTNETR0DECL(int) INTNETR0IfAddMeshNode(PINTNET pIntNet, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, const char *machineId, uint32_t slot)
+{
+ LogFlow(("INTNETR0IfAddMeshNode: pIntNet=%p hIf=%RX32 machineId=%p:{%s}, slot=%u\n", pIntNet, hIf, pMac, machineId, slot));
+
+ /*
+ * Validate & translate input.
+ */
+ AssertPtrReturn(pIntNet, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(machineId, VERR_INVALID_PARAMETER);
+ PINTNETIF pIf = (PINTNETIF)RTHandleTableLookupWithCtx(pIntNet->hHtIfs, hIf, pSession);
+ if (!pIf)
+ {
+ Log(("INTNETR0IfAddMeshNode: returns VERR_INVALID_HANDLE\n"));
+ return VERR_INVALID_HANDLE;
+ }
+
+ /*
+ * Grab the network semaphore and make the change.
+ */
+ int rc;
+ PINTNETNETWORK pNetwork = pIf->pNetwork;
+ if (pNetwork)
+ {
+ rc = RTSemFastMutexRequest(pNetwork->FastMutex);
+ if (RT_SUCCESS(rc))
+ {
+ Assert(strlen(machineId) < sizeof(pIf->machineId)); /* caller's responsibility. */
+
+ /*
+ * Allocate and initialize the interface structure.
+ */
+ PINTNETMESHNODE pMeshNode = (PINTNETMESHNODE)RTMemAllocZ(sizeof(*pMeshNode));
+ if (!pMeshNode)
+ return VERR_NO_MEMORY;
+ strcpy(pMeshNode->machineId, machineId);
+ pMeshNode->slot = slot;
+ pMeshNode->pIf = 0;
+ /*
+ * Find if the interface already exists
+ */
+ for (PINTNETIF pIfi = pIf->pNetwork->pIFs; pIfi; pIfi = pIfi->pNext)
+ {
+ if(pIfi->slot == slot && strncmp(pIfi->machineId, machineId, sizeof(machineId)) == 0)
+ pMeshNode->pIf = pIfi;
+ }
+ // Add the mesh node
+
+ pMeshNode->pNext = pIf->meshNeighbours;
+ pIf->meshNeighbours = pMeshNode;
+
+ rc = RTSemFastMutexRelease(pNetwork->FastMutex);
+ }
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+
+ intnetR0IfRelease(pIf, pSession);
+ return rc;
+}
+
+/**
* VMMR0 request wrapper for INTNETR0IfSetMacAddress.
*
* @returns see INTNETR0IfSetMacAddress.
@@ -2845,6 +2962,21 @@
/**
+ * VMMR0 request wrapper for INTNETR0IfAddMeshNode.
+ *
+ * @returns see INTNETR0IfAddMeshNode.
+ * @param pIntNet The internal networking instance.
+ * @param pSession The caller's session.
+ * @param pReq The request packet.
+ */
+INTNETR0DECL(int) INTNETR0IfAddMeshNodeReq(PINTNET pIntNet, PSUPDRVSESSION pSession, PINTNETIFADDMESHNODEREQ pReq)
+{
+ if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
+ return VERR_INVALID_PARAMETER;
+ return INTNETR0IfAddMeshNode(pIntNet, pReq->hIf, pSession, pReq->machineId, pReq->slot);
+}
+
+/**
* Worker for intnetR0IfSetActive.
*
* This function will update the active interface count on the network and
@@ -3198,7 +3330,28 @@
RTSemFastMutexRelease(pIntNet->FastMutex);
SUPR0ObjRelease(pNetwork->pvObj, pIf->pSession);
- pIf->pNetwork = NULL;
+ pIf->pNetwork = NULL;
+
+ /*
+ * Update the mesh nodes
+ */
+ for (PINTNETIF pIfi = pNetwork->pIFs; pIfi; pIfi = pIfi->pNext)
+ {
+ for (PINTNETMESHNODE neighbour = pIfi->meshNeighbours; neighbour; neighbour = neighbour->pNext)
+ {
+ if(pIf->slot == neighbour->slot && strncmp(pIf->machineId, neighbour->machineId, sizeof(neighbour->machineId)) == 0)
+ neighbour->pIf = 0;
+ }
+ }
+ /*
+ * Free the mallocs for our neighbours list
+ */
+ PINTNETMESHNODE nextNeighbour = 0;
+ for (PINTNETMESHNODE neighbour = pIf->meshNeighbours; neighbour; neighbour = nextNeighbour)
+ {
+ PINTNETMESHNODE next = neighbour->pNext;
+ RTMemFree(neighbour);
+ }
}
else
RTSemFastMutexRelease(pIntNet->FastMutex);
@@ -3276,8 +3429,10 @@
* @param cbSend The size of the send buffer.
* @param cbRecv The size of the receive buffer.
* @param phIf Where to store the interface handle.
+ * @param machineId The id of machine the machine to which this interface is connected to.
+ * @param slot The slot to which this interface is associated with in the parent machine.
*/
-static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession, unsigned cbSend, unsigned cbRecv, bool *pfCloseNetwork, PINTNETIFHANDLE phIf)
+static int intnetR0NetworkCreateIf(PINTNETNETWORK pNetwork, PSUPDRVSESSION pSession, unsigned cbSend, unsigned cbRecv, bool *pfCloseNetwork, PINTNETIFHANDLE phIf, const char *machineId, unsigned slot)
{
LogFlow(("intnetR0NetworkCreateIf: pNetwork=%p pSession=%p cbSend=%u cbRecv=%u phIf=%p\n",
pNetwork, pSession, cbSend, cbRecv, phIf));
@@ -3312,6 +3467,23 @@
pIf->hIf = INTNET_HANDLE_INVALID;
pIf->pNetwork = pNetwork;
pIf->pSession = pSession;
+ Assert(strlen(machineId) < sizeof(pIf->machineId)); /* caller's responsibility. */
+ strcpy(pIf->machineId, machineId);
+ pIf->slot = slot;
+ pIf->meshNeighbours = 0;
+
+ /*
+ * Update the mesh nodes
+ */
+ for (PINTNETIF pIfi = pNetwork->pIFs; pIfi; pIfi = pIfi->pNext)
+ {
+ for (PINTNETMESHNODE neighbour = pIfi->meshNeighbours; neighbour; neighbour = neighbour->pNext)
+ {
+ if(slot == neighbour->slot && strncmp(machineId, neighbour->machineId, sizeof(neighbour->machineId)) == 0)
+ neighbour->pIf = pIf;
+ }
+ }
+
//pIf->pvObj = NULL;
//pIf->aAddrCache[kIntNetAddrType_Invalid] = {0};
//pIf->aAddrCache[kIntNetAddrType_IPv4].pbEntries = NULL;
@@ -4091,13 +4263,16 @@
* @param cbSend The send buffer size.
* @param cbRecv The receive buffer size.
* @param phIf Where to store the handle to the network interface.
+ * @param machineId The id of machine the machine to which this interface is connected to.
+ * @param slot The slot to which this interface is associated with in the parent machine.
*/
INTNETR0DECL(int) INTNETR0Open(PINTNET pIntNet, PSUPDRVSESSION pSession, const char *pszNetwork,
INTNETTRUNKTYPE enmTrunkType, const char *pszTrunk, uint32_t fFlags,
- unsigned cbSend, unsigned cbRecv, PINTNETIFHANDLE phIf)
+ unsigned cbSend, unsigned cbRecv, PINTNETIFHANDLE phIf, const char* machineId,
+ unsigned slot)
{
- LogFlow(("INTNETR0Open: pIntNet=%p pSession=%p pszNetwork=%p:{%s} enmTrunkType=%d pszTrunk=%p:{%s} fFlags=%#x cbSend=%u cbRecv=%u phIf=%p\n",
- pIntNet, pSession, pszNetwork, pszNetwork, pszTrunk, pszTrunk, enmTrunkType, fFlags, cbSend, cbRecv, phIf));
+ LogFlow(("INTNETR0Open: pIntNet=%p pSession=%p pszNetwork=%p:{%s} enmTrunkType=%d pszTrunk=%p:{%s} fFlags=%#x cbSend=%u cbRecv=%u phIf=%p machineId=%p:{%s} slot=%u\n",
+ pIntNet, pSession, pszNetwork, pszNetwork, pszTrunk, pszTrunk, enmTrunkType, fFlags, cbSend, cbRecv, phIf, machineId, slot));
/*
* Validate input.
@@ -4110,6 +4285,10 @@
size_t cchNetwork = pszNetworkEnd - pszNetwork;
AssertReturn(cchNetwork, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(machineId, VERR_INVALID_PARAMETER);
+ const char *machineIdEnd = (const char *)memchr(machineId, '\0', RTUUID_STR_LENGTH);
+ AssertReturn(machineIdEnd, VERR_INVALID_PARAMETER);
+
if (pszTrunk)
{
AssertPtrReturn(pszTrunk, VERR_INVALID_PARAMETER);
@@ -4163,7 +4342,7 @@
if (fNewNet)
rc = intnetR0CreateNetwork(pIntNet, pSession, pszNetwork, enmTrunkType, pszTrunk, fFlags, &pNetwork);
if (RT_SUCCESS(rc))
- rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, &fCloseNetwork, phIf);
+ rc = intnetR0NetworkCreateIf(pNetwork, pSession, cbSend, cbRecv, &fCloseNetwork, phIf, machineId, slot);
RTSemFastMutexRelease(pIntNet->FastMutex);
@@ -4196,7 +4375,8 @@
if (RT_UNLIKELY(pReq->Hdr.cbReq != sizeof(*pReq)))
return VERR_INVALID_PARAMETER;
return INTNETR0Open(pIntNet, pSession, &pReq->szNetwork[0], pReq->enmTrunkType, pReq->szTrunk,
- pReq->fFlags, pReq->cbSend, pReq->cbRecv, &pReq->hIf);
+ pReq->fFlags, pReq->cbSend, pReq->cbRecv, &pReq->hIf, &pReq->machineId[0],
+ pReq->slot);
}
Index: src/VBox/Devices/Network/DrvIntNet.cpp
===================================================================
--- src/VBox/Devices/Network/DrvIntNet.cpp (revisión: 18845)
+++ src/VBox/Devices/Network/DrvIntNet.cpp (copia de trabajo)
@@ -89,6 +89,14 @@
/** Set if data transmission should start immediately and deactivate
* as late as possible. */
bool fActivateEarlyDeactivateLate;
+#if defined(VBOX_WITH_NETFLT)
+ /** Set if the interface is in mesh mode */
+ bool fMeshMode;
+ /** The slot to which the network interface is associated with. */
+ uint32_t slot;
+ /** The uuid of the machine in which the network interface resides */
+ char machineId[RTUUID_STR_LENGTH];
+#endif
#ifdef VBOX_WITH_STATISTICS
/** Profiling packet transmit runs. */
@@ -762,6 +770,7 @@
if (!CFGMR3AreValuesValid(pCfgHandle,
"Network\0"
"Trunk\0"
+ "MeshEnabled\0"
"TrunkType\0"
"ReceiveBufferSize\0"
"SendBufferSize\0"
@@ -951,6 +960,29 @@
N_("Configuration error: Failed to get the \"SharedMacOnWire\" value"));
if (fSharedMacOnWire)
OpenReq.fFlags |= INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE;
+#if defined(VBOX_WITH_NETFLT)
+ /** @cfgm{MeshMode, boolean, false}
+ * Whether this network is in mesh mode.
+ */
+ rc = CFGMR3QueryBoolDef(pCfgHandle, "MeshMode", &(pThis->fMeshMode), false);
+ if (RT_FAILURE(rc))
+ return PDMDRV_SET_ERROR(pDrvIns, rc,
+ N_("Configuration error: Failed to get the \"MeshMode\" value"));
+ if (pThis->fMeshMode)
+ {
+ OpenReq.fFlags |= INTNET_OPEN_FLAGS_MESH_MODE;
+ rc = CFGMR3QueryU32(pCfgHandle, "MeshNeighbours/Slot", &(pThis->slot));
+ if (RT_FAILURE(rc))
+ return PDMDRV_SET_ERROR(pDrvIns, rc,
+ N_("Configuration error: Failed to get the \"MeshNeighbours/Slot\" value"));
+ OpenReq.slot = pThis->slot;
+ rc = CFGMR3QueryString(pCfgHandle, "MeshNeighbours/MachineId", pThis->machineId, sizeof(pThis->machineId));
+ if (RT_FAILURE(rc))
+ return PDMDRV_SET_ERROR(pDrvIns, rc,
+ N_("Configuration error: Failed to get the \"MeshNeighbours/MachineId\" value"));
+ strcpy(pThis->machineId, OpenReq.machineId);
+ }
+#endif
/** @cfgm{ReceiveBufferSize, uint32_t, 218 KB}
* The size of the receive buffer.
@@ -1079,6 +1111,35 @@
#endif
/*
+ * If in mesh mode, add the mesh nodes one by one to the network interface.
+ */
+ if(pThis->fMeshMode)
+ {
+ uint32_t numMeshNodes = 0;
+ rc = CFGMR3QueryU32(pCfgHandle, "MeshNeighbours/NumMeshNeighbours", &numMeshNodes);
+ if (RT_FAILURE(rc))
+ return PDMDRV_SET_ERROR(pDrvIns, rc,
+ N_("Configuration error: Failed to get the \"MeshNeighbours/numMeshNodes\" value"));
+
+ for(uint32_t i = 0; i < numMeshNodes; i++)
+ {
+ PCFGMNODE pNodeCfg = CFGMR3GetChildF (pCfgHandle, "MeshNeighbours/#%d/", i);
+ uint32_t slot;
+ char machineId[RTUUID_STR_LENGTH];
+ rc = CFGMR3QueryU32(pNodeCfg, "Slot", &slot);
+ if (RT_FAILURE(rc))
+ return PDMDRV_SET_ERROR(pDrvIns, rc,
+ N_("Configuration error: Failed to get a \"MeshNeighbour/Slot\" value"));
+ rc = CFGMR3QueryString(pNodeCfg, "MachineId", machineId, sizeof(machineId));
+ if (RT_FAILURE(rc))
+ return PDMDRV_SET_ERROR(pDrvIns, rc,
+ N_("Configuration error: Failed to get a \"MeshNeighbour/MachineId\" value"));
+ // TODO:
+ // drvIntAddMeshNode(pThis);
+ }
+ }
+
+ /*
* Activate data transmission as early as possible
*/
if (pThis->fActivateEarlyDeactivateLate)
Index: src/VBox/Devices/Network/testcase/tstIntNetR0.cpp
===================================================================
--- src/VBox/Devices/Network/testcase/tstIntNetR0.cpp (revisión: 18845)
+++ src/VBox/Devices/Network/testcase/tstIntNetR0.cpp (copia de trabajo)
@@ -448,13 +448,14 @@
* Create two interfaces.
*/
INTNETIFHANDLE hIf0 = INTNET_HANDLE_INVALID;
- rc = INTNETR0Open(pIntNet, g_pSession, "test", kIntNetTrunkType_None, "", 0, 1536*2 + 4, 0x8000, &hIf0);
+ char machineId[RTUUID_STR_LENGTH];
+ rc = INTNETR0Open(pIntNet, g_pSession, "test", kIntNetTrunkType_None, "", 0, 1536*2 + 4, 0x8000, &hIf0, machineId, 0);
if (RT_SUCCESS(rc))
{
if (hIf0 != INTNET_HANDLE_INVALID)
{
INTNETIFHANDLE hIf1 = INTNET_HANDLE_INVALID;
- rc = INTNETR0Open(pIntNet, g_pSession, "test", kIntNetTrunkType_None, NULL, 0, 1536*2 + 4, 0x8000, &hIf1);
+ rc = INTNETR0Open(pIntNet, g_pSession, "test", kIntNetTrunkType_None, NULL, 0, 1536*2 + 4, 0x8000, &hIf1, machineId, 1);
if (RT_SUCCESS(rc))
{
if (hIf1 != INTNET_HANDLE_INVALID)
Index: src/VBox/Devices/Network/testcase/tstIntNet-1.cpp
===================================================================
--- src/VBox/Devices/Network/testcase/tstIntNet-1.cpp (revisión: 18845)
+++ src/VBox/Devices/Network/testcase/tstIntNet-1.cpp (copia de trabajo)
@@ -873,6 +873,10 @@
OpenReq.fFlags = fMacSharing ? INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE : 0;
OpenReq.cbSend = cbSend;
OpenReq.cbRecv = cbRecv;
+
+ char machineId[RTUUID_STR_LENGTH];
+ strncpy(OpenReq.machineId, machineId, sizeof(machineId));
+ OpenReq.slot = 0;
OpenReq.hIf = INTNET_HANDLE_INVALID;
/*
Index: src/VBox/Main/include/NetworkAdapterImpl.h
===================================================================
--- src/VBox/Main/include/NetworkAdapterImpl.h (revisión: 18845)
+++ src/VBox/Main/include/NetworkAdapterImpl.h (copia de trabajo)
@@ -25,6 +25,7 @@
#define ____H_NETWORKADAPTER
#include "VirtualBoxBase.h"
+#include "NetworkAdapterRefImpl.h"
class Machine;
class GuestOSType;
@@ -36,14 +37,14 @@
public INetworkAdapter
{
public:
-
+ typedef std::list <ComObjPtr <NetworkAdapterRef> > NetworkAdapterRefList;
struct Data
{
Data()
: mSlot (0), mEnabled (FALSE)
, mAttachmentType (NetworkAttachmentType_Null)
, mCableConnected (TRUE), mLineSpeed (0), mTraceEnabled (FALSE)
- , mHostInterface ("") /* cannot be null */
+ , mHostInterface ("") /* cannot be null */, mMesh (FALSE)
{}
bool operator== (const Data &that) const
@@ -58,7 +59,8 @@
mTraceEnabled == that.mTraceEnabled &&
mHostInterface == that.mHostInterface &&
mInternalNetwork == that.mInternalNetwork &&
- mNATNetwork == that.mNATNetwork);
+ mNATNetwork == that.mNATNetwork &&
+ mMesh == that.mMesh);
}
NetworkAdapterType_T mAdapterType;
@@ -73,6 +75,8 @@
Bstr mHostInterface;
Bstr mInternalNetwork;
Bstr mNATNetwork;
+ BOOL mMesh;
+ NetworkAdapterRefList mMeshNeighbours;
};
VIRTUALBOXBASE_ADD_ERRORINFO_SUPPORT (NetworkAdapter)
@@ -122,6 +126,10 @@
STDMETHOD(COMSETTER(LineSpeed)) (ULONG aSpeed);
STDMETHOD(COMGETTER(TraceFile)) (BSTR *aTraceFile);
STDMETHOD(COMSETTER(TraceFile)) (IN_BSTR aTraceFile);
+ STDMETHOD(COMGETTER(MeshEnabled)) (BOOL *aEnabled);
+ STDMETHOD(COMSETTER(MeshEnabled)) (BOOL aEnabled);
+ STDMETHOD(COMGETTER(MeshNeighbours)) (ComSafeArrayOut (INetworkAdapterRef *, aNetworkAdapterRefs));
+ STDMETHOD(COMGETTER(Parent)) (IMachine **aMachine);
// INetworkAdapter methods
STDMETHOD(AttachToNAT)();
@@ -146,6 +154,7 @@
// (ensure there is a caller and a read lock before calling them!)
const Backupable <Data> &data() const { return mData; }
+ const ComObjPtr <Machine, ComWeakRef> &parent() const { return mParent; }
// for VirtualBoxSupportErrorInfoImpl
static const wchar_t *getComponentName() { return L"NetworkAdapter"; }
Index: src/VBox/Main/NetworkAdapterImpl.cpp
===================================================================
--- src/VBox/Main/NetworkAdapterImpl.cpp (revisión: 18845)
+++ src/VBox/Main/NetworkAdapterImpl.cpp (copia de trabajo)
@@ -682,6 +682,80 @@
return S_OK;
}
+
+STDMETHODIMP NetworkAdapter::COMGETTER(MeshEnabled) (BOOL *aEnabled)
+{
+ CheckComArgOutPointerValid(aEnabled);
+
+ AutoCaller autoCaller (this);
+ CheckComRCReturnRC (autoCaller.rc());
+
+ AutoReadLock alock (this);
+
+ *aEnabled = mData->mMesh;
+
+ return S_OK;
+}
+
+STDMETHODIMP NetworkAdapter::COMSETTER(MeshEnabled) (BOOL aEnabled)
+{
+ AutoCaller autoCaller (this);
+ CheckComRCReturnRC (autoCaller.rc());
+
+ /* the machine needs to be mutable */
+ Machine::AutoMutableStateDependency adep (mParent);
+ CheckComRCReturnRC (adep.rc());
+
+ AutoWriteLock alock (this);
+
+ if (mData->mMesh != aEnabled)
+ {
+ mData.backup();
+ mData->mMesh = aEnabled;
+
+ /* leave the lock before informing callbacks */
+ alock.unlock();
+
+ mParent->onNetworkAdapterChange (this);
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP NetworkAdapter::
+COMGETTER(MeshNeighbours) (ComSafeArrayOut (INetworkAdapterRef *, aNetworkAdapterRefs))
+{
+ if (ComSafeArrayOutIsNull (aNetworkAdapterRefs))
+ return E_POINTER;
+
+ AssertReturn (mData->mMesh, E_FAIL);
+
+ AutoCaller autoCaller (this);
+ CheckComRCReturnRC (autoCaller.rc());
+
+ AutoReadLock alock (this);
+
+ SafeIfaceArray <INetworkAdapterRef> networkAdapterRefs (mData->mMeshNeighbours);
+ networkAdapterRefs.detachTo (ComSafeArrayOutArg (aNetworkAdapterRefs));
+
+ return S_OK;
+}
+
+STDMETHODIMP NetworkAdapter::COMGETTER(Parent) (IMachine **aParent)
+{
+ CheckComArgOutPointerValid(aParent);
+
+ AutoCaller autoCaller (this);
+ CheckComRCReturnRC (autoCaller.rc());
+
+ AutoReadLock alock (this);
+
+ /* mParent is const, no need to lock */
+ mParent.queryInterfaceTo (aParent);
+
+ return S_OK;
+}
+
// INetworkAdapter methods
////////////////////////////////////////////////////////////////////////////////
@@ -950,6 +1024,22 @@
Bstr name = attachmentNode.stringValue ("name");
/* name can be empty, but not null */
ComAssertRet (!name.isNull(), E_FAIL);
+ mData->mMesh = attachmentNode.value <bool> ("mesh");
+
+ if(mData->mMesh)
+ {
+ Key meshNeighbourNode;
+ while (!(meshNeighbourNode = attachmentNode.findKey ("MeshNeighbour")).isNull())
+ {
+ Guid machineId = meshNeighbourNode.value<Guid>("machine");
+ ULONG aSlot = meshNeighbourNode.value <ULONG> ("slot");
+
+ NetworkAdapterRef *networkAdapterRef = new NetworkAdapterRef();
+ networkAdapterRef->init(machineId, aSlot);
+ ComObjPtr <NetworkAdapterRef> aRef(networkAdapterRef);
+ mData->mMeshNeighbours.push_back(aRef);
+ }
+ }
rc = COMSETTER(HostInterface) (name);
CheckComRCReturnRC (rc);
@@ -1060,6 +1150,17 @@
#if defined(VBOX_WITH_NETFLT)
Assert (!mData->mHostInterface.isNull());
attachmentNode.setValue <Bstr> ("name", mData->mHostInterface);
+ attachmentNode.setValue <bool> ("mesh", mData->mMesh);
+
+ if(mData->mMesh)
+ {
+ for (NetworkAdapterRefList::const_iterator it = mData->mMeshNeighbours.begin(); it != mData->mMeshNeighbours.end(); ++ it)
+ {
+ Key meshNeighbourNode = attachmentNode.createKey ("MeshNeighbour");
+ meshNeighbourNode.setValue <Guid> ("machine", (*it)->machineId());
+ meshNeighbourNode.setValue <ULONG> ("slot", (*it)->slot());
+ }
+ }
#endif
break;
}
@@ -1253,4 +1354,5 @@
LogFlowThisFunc (("generated MAC: '%s'\n", strMAC));
mData->mMACAddress = strMAC;
}
+
/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Index: src/VBox/Main/Makefile.kmk
===================================================================
--- src/VBox/Main/Makefile.kmk (revisión: 18845)
+++ src/VBox/Main/Makefile.kmk (copia de trabajo)
@@ -295,6 +295,7 @@
DHCPServerRunner.cpp \
GuestOSTypeImpl.cpp \
NetworkAdapterImpl.cpp \
+ NetworkAdapterRefImpl.cpp \
SerialPortImpl.cpp \
ParallelPortImpl.cpp \
USBControllerImpl.cpp \
Index: src/VBox/Main/xpcom/module.cpp
===================================================================
--- src/VBox/Main/xpcom/module.cpp (revisión: 18845)
+++ src/VBox/Main/xpcom/module.cpp (copia de trabajo)
@@ -43,6 +43,7 @@
#include "FramebufferImpl.h"
#include "ProgressImpl.h"
#include "NetworkAdapterImpl.h"
+#include "NetworkAdapterRefImpl.h"
#include "SessionImpl.h"
#include "ConsoleImpl.h"
@@ -76,6 +77,8 @@
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(SharedFolder, ISharedFolder)
NS_DECL_CLASSINFO(RemoteDisplayInfo)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(RemoteDisplayInfo, IRemoteDisplayInfo)
+NS_DECL_CLASSINFO(NetworkAdapterRef)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(NetworkAdapterRef, INetworkAdapterRef)
NS_DECL_CLASSINFO(Session)
NS_IMPL_THREADSAFE_ISUPPORTS2_CI(Session, ISession, IInternalSessionControl)
Index: src/VBox/Main/xpcom/server.cpp
===================================================================
--- src/VBox/Main/xpcom/server.cpp (revisión: 18845)
+++ src/VBox/Main/xpcom/server.cpp (copia de trabajo)
@@ -204,6 +204,9 @@
NS_DECL_CLASSINFO(NetworkAdapter)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(NetworkAdapter, INetworkAdapter)
+NS_DECL_CLASSINFO(NetworkAdapterRef)
+NS_IMPL_THREADSAFE_ISUPPORTS1_CI(NetworkAdapterRef, INetworkAdapterRef)
+
NS_DECL_CLASSINFO(SerialPort)
NS_IMPL_THREADSAFE_ISUPPORTS1_CI(SerialPort, ISerialPort)
Index: src/VBox/Main/ConsoleImpl2.cpp
===================================================================
--- src/VBox/Main/ConsoleImpl2.cpp (revisión: 18845)
+++ src/VBox/Main/ConsoleImpl2.cpp (copia de trabajo)
@@ -1348,8 +1348,49 @@
STR_FREE();
}
}
-
-
+#if defined(VBOX_WITH_NETFLT)
+ /*
+ * Check if mesh mode is enabled and set up the ocnfiguration if so.
+ */
+ BOOL fMesh;
+ hrc = networkAdapter->COMGETTER(MeshEnabled)(&fMesh); H();
+ rc = CFGMR3InsertInteger(pCfg, "MeshEnabled", (fMesh) ? 1 : 0); /* bool */ RC_CHECK();
+ if (fMesh)
+ {
+ com::SafeIfaceArray <INetworkAdapterRef> meshNeighbours;
+ networkAdapter->COMGETTER(MeshNeighbours) (ComSafeArrayAsOutParam (meshNeighbours));
+ PCFGMNODE pMeshNode = NULL;
+ PCFGMNODE pParentMesh = NULL;
+ char aNumStr[16];
+ rc = CFGMR3InsertNode(pCfg, "MeshNeighbours", &pParentMesh); RC_CHECK();
+ rc = CFGMR3InsertInteger(pParentMesh, "NumMeshNeighbours", meshNeighbours.size());
+ RC_CHECK();
+ ULONG aSlot;
+ hrc = networkAdapter->COMGETTER(Slot)(&aSlot); H();
+ ComPtr<IMachine> aMachine;
+ hrc = networkAdapter->COMGETTER(Parent)(aMachine.asOutParam()); H();
+
+ Bstr aName;
+ hrc = aMachine->COMGETTER(Name)(aName.asOutParam()); H();
+ rc = CFGMR3InsertInteger(pMeshNode, "Slot", aSlot); RC_CHECK();
+ rc = CFGMR3InsertString(pMeshNode, "MachineId", Utf8Str(aName) ); RC_CHECK();
+
+ for (size_t a = 0; a < meshNeighbours.size(); ++ a)
+ {
+ RTStrPrintf (aNumStr, sizeof(aNumStr), "#%d", a);
+ rc = CFGMR3InsertNode(pParentMesh, aNumStr, &pMeshNode); RC_CHECK();
+ ULONG aSlot;
+ hrc = meshNeighbours[a]->COMGETTER(Slot)(&aSlot); H();
+ Guid machineId;
+ hrc = meshNeighbours[a]->COMGETTER(MachineId)(machineId.asOutParam());
+ H();
+ char bufId[RTUUID_STR_LENGTH];
+ RTUuidToStr(machineId.raw(), bufId, RTUUID_STR_LENGTH);
+ rc = CFGMR3InsertInteger(pMeshNode, "Slot", aSlot); RC_CHECK();
+ rc = CFGMR3InsertString(pMeshNode, "MachineId", bufId); RC_CHECK();
+ }
+ }
+#endif
NetworkAttachmentType_T networkAttachment;
hrc = networkAdapter->COMGETTER(AttachmentType)(&networkAttachment); H();
Bstr networkName, trunkName, trunkType;
Index: src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- src/VBox/Main/idl/VirtualBox.xidl (revisión: 18845)
+++ src/VBox/Main/idl/VirtualBox.xidl (copia de trabajo)
@@ -10929,6 +10929,26 @@
<desc>Intel PRO/1000 MT Server network card (82545EM).</desc>
</const>
</enum>
+
+ <interface
+ name="INetworkAdapterRef" extends="$unknown"
+ uuid="2a90d238-5eb4-109b-ce14-1488a720c2dd"
+ wsmap="managed"
+ >
+ <desc>
+ Represents a reference to a virtual network adapter using two attributes:
+ the machine to which the network adpater is attached, and the slot in
+ which the network adapter is attached in that machine. It's used instead
+ of INetworkAdapter to reference NetworkAdapters that might not have been
+ created yet.
+ </desc>
+ <attribute name="machineId" type="uuid" readonly="yes">
+ <desc>The machine ID to which this network interface is attached to.</desc>
+ </attribute>
+ <attribute name="slot" type="unsigned long" readonly="yes">
+ <desc>The slot in which the network adapter is attached to.</desc>
+ </attribute>
+ </interface>
<interface
name="INetworkAdapter" extends="$unknown"
@@ -11026,6 +11046,29 @@
</desc>
</attribute>
+
+ <attribute name="meshEnabled" type="boolean">
+ <desc>
+ Flag whether this network will be mesh, meaning that instead of everyone
+ being neighbours, a given network interface is connected to a subset of
+ other network interfaces, forming a mesh network.
+ </desc>
+ </attribute>
+
+ <attribute name="parent" type="IMachine" readonly="yes">
+ <desc>
+ Associated parent object.
+ </desc>
+ </attribute>
+
+ <attribute name="meshNeighbours" type="INetworkAdapterRef" safearray="yes" readonly="yes">
+ <desc>
+ List of all the other network adapters connected to this one in a mesh
+ network. In order to call get the list, the network adapter must be
+ in mesh mode or else it will return E_FAIL.
+ </desc>
+ </attribute>
+
<method name="attachToNAT">
<desc>
Attach the network adapter to the Network Address Translation (NAT) interface.
_______________________________________________
vbox-dev mailing list
[email protected]
http://vbox.innotek.de/mailman/listinfo/vbox-dev