DrvIntNet.cpp revision c29d5f9788e36b29b56959b5aee215e8ac3aede5
6133N/A * DrvIntNet - Internal network transport driver. 6133N/A * Copyright (C) 2006-2007 Sun Microsystems, Inc. 6133N/A * This file is part of VirtualBox Open Source Edition (OSE), as 6133N/A * you can redistribute it and/or modify it under the terms of the GNU 6133N/A * General Public License (GPL) as published by the Free Software 6133N/A * Foundation, in version 2 as it comes in the "COPYING" file of the 6133N/A * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 6133N/A * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 6133N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 6133N/A * additional information or have any questions. 6133N/A/******************************************************************************* 6133N/A*******************************************************************************/ 6135N/A/******************************************************************************* 6133N/A*******************************************************************************/ * The state of the asynchronous thread. /** The thread is suspended. */ /** The thread is running. */ /** The thread must (/has) terminate. */ /** The usual 32-bit type blowup. */ * Block driver instance data. /** The network interface. */ /** The network interface. */ /** The network config interface. * Can (in theory at least) be NULL. */ /** Pointer to the driver instance. */ /** Pointer to the communication buffer. */ /** Event semaphore the Thread waits on while the VM is suspended. */ /** Set if the link is down. * When the link is down all incoming packets will be dropped. */ /** Set if data transmission should start immediately and deactivate * as late as possible. */ /** Profiling packet transmit runs. */ /** Profiling packet receive runs. */ #
endif /* VBOX_WITH_STATISTICS */ /** The nano ts of the last transfer. */ /** The nano ts of the last receive. */ /** Converts a pointer to DRVINTNET::INetworkConnector to a PDRVINTNET. */ * Updates the MAC address on the kernel side. * @returns VBox status code. * @param pThis The driver instance. * Sets the kernel interface active or inactive. * Worker for poweron, poweroff, suspend and resume. * @returns VBox status code. * @param pThis The driver instance. * @param fActive The new state. Log((
"drvIntNetUpdateMacAddress: fActive=%d rc=%Rrc\n",
fActive,
rc));
* Writes a frame packet to the buffer. * @returns VBox status code. * @param pBuf The buffer. * @param pRingBuf The ring buffer to read from. * @param pvFrame The frame to write. * @param cbFrame The size of the frame. * @remark This is the same as INTNETRingWriteFrame * Try fit it all before the end of the buffer. * Try fit the frame at the start of the buffer. * (The header fits before the end of the buffer because of alignment.) * The reader is ahead of the writer, try fit it into that space. * Send data to the network. * @returns VBox status code. * @param pInterface Pointer to the interface structure containing the called function pointer. * @param pvBuf Data to send. * @param cb Number of bytes to send. LogFlow((
"drvIntNetSend: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n",
Log2((
"drvIntNetSend: pvBuf=%p cb=%#x\n" * Add the frame to the send buffer and push it onto the network. * This is called when the promiscuous mode is set. This means that there doesn't have * to be a mode change when it's called. * @param pInterface Pointer to the interface structure containing the called function pointer. * @param fPromiscuous Set if the adaptor is now in promiscuous mode. Clear if it is not. * Notification on link status changes. * @param pInterface Pointer to the interface structure containing the called function pointer. * @param enmLinkState The new link state. * Wait for space to become available up the driver/device chain. * @returns VINF_SUCCESS if space is available. * @returns VERR_STATE_CHANGED if the state changed. * @returns VBox status code on other errors. * @param pThis Pointer to the instance data. LogFlow((
"drvIntNetAsyncIoWaitForSpace:\n"));
LogFlow((
"drvIntNetAsyncIoWaitForSpace: returns %Rrc\n",
rc));
* Executes async I/O (RUNNING mode). * @returns VERR_STATE_CHANGED if the state changed. * @returns Appropriate VBox status code (error) on fatal error. * @param pThis The driver instance data. * The running loop - processing received data and waiting for more to arrive. * Process the receive buffer. * Check the state and then inspect the packet. LogFlow((
"drvIntNetAsyncIoRun: returns VERR_STATE_CHANGED (state changed - #0)\n"));
* Check if there is room for the frame and pass it up. LogFlow((
"drvIntNetAsyncIoRun: %-4d bytes at %llu ns deltas: r=%llu t=%llu\n",
Log2((
"drvIntNetAsyncIoRun: cbFrame=%#x\n" /* skip to the next frame. */ * Wait for sufficient space to become available and then retry. * NIC is going down, likely because the VM is being reset. Skip the frame. LogFlow((
"drvIntNetAsyncIoRun: returns %Rrc (wait-for-space)\n",
rc));
* Link down or unknown frame - skip to the next frame. }
/* while more received data */ * Wait for data, checking the state before we block. LogFlow((
"drvIntNetAsyncIoRun: returns VINF_SUCCESS (state changed - #1)\n"));
WaitReq.
cMillies =
30000;
/* 30s - don't wait forever, timeout now and then. */ LogFlow((
"drvIntNetAsyncIoRun: returns %Rrc\n",
rc));
* Asynchronous I/O thread for handling receive. * @returns VINF_SUCCESS (ignored). * @param ThreadSelf Thread handle. * @param pvUser Pointer to a DRVINTNET structure. * The main loop - acting on state. LogFlow((
"drvIntNetAsyncIoThread: returns %Rrc\n",
rc));
LogFlow((
"drvIntNetAsyncIoThread: returns %Rrc\n",
rc));
LogFlow((
"drvIntNetAsyncIoThread: returns VINF_SUCCESS\n"));
* 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. * Power Off notification. * @param pDrvIns The driver instance. * @param pDrvIns The driver instance. LogFlow((
"drvIntNetPowerResume\n"));
* @param pDrvIns The driver instance. LogFlow((
"drvIntNetPowerSuspend\n"));
* @param pDrvIns The driver instance. * 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. * Indicate to the thread that it's time to quit. * Wait for the thread to terminate. * Destroy the semaphores. * Construct a TAP network transport driver instance. * @param pDrvIns The driver instance data. * If the registration structure is needed, pDrvIns->pDrvReg points to it. * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like * iInstance it's expected to be used a bit in this function. "QuietlyIgnoreAllPromisc\0" "QuietlyIgnoreClientPromisc\0" "IgnoreTrunkWirePromisc\0" "QuietlyIgnoreTrunkWirePromisc\0" "IgnoreTrunkHostPromisc\0" "QuietlyIgnoreTrunkHostPromisc\0" * Check that no-one is attached to us. AssertMsgFailed((
"Configuration error: Cannot attach drivers to the TAP driver!\n"));
* Query the network port interface. * Read the configuration. /** @cfgm{Network, string} * The name of the internal network to connect to. N_(
"Configuration error: Failed to get the \"Network\" value"));
/** @cfgm{TrunkType, uint32_t, kIntNetTrunkType_None} * The trunk connection type see INTNETTRUNKTYPE. N_(
"Configuration error: Failed to get the \"TrunkType\" value"));
/** @cfgm{Trunk, string, ""} * The name of the trunk connection. N_(
"Configuration error: Failed to get the \"Trunk\" value"));
/** @cfgm{RestrictAccess, boolean, true} * Whether to restrict the access to the network or if it should be public. Everyone on * the computer can connect to a public network. Don't change this. N_(
"Configuration error: Failed to get the \"RestrictAccess\" value"));
/** @cfgm{IgnoreAllPromisc, boolean, false} * When set all request for operating any interface or trunk in promiscuous * mode will be ignored. */ N_(
"Configuration error: Failed to get the \"IgnoreAllPromisc\" value"));
/** @cfgm{QuietlyIgnoreAllPromisc, boolean, false} * When set all request for operating any interface or trunk in promiscuous * mode will be ignored. This differs from IgnoreAllPromisc in that clients * won't get VERR_INTNET_INCOMPATIBLE_FLAGS. */ N_(
"Configuration error: Failed to get the \"QuietlyIgnoreAllPromisc\" value"));
/** @cfgm{IgnoreClientPromisc, boolean, false} * When set all request for operating any non-trunk interface in promiscuous * mode will be ignored. */ N_(
"Configuration error: Failed to get the \"IgnoreClientPromisc\" value"));
/** @cfgm{QuietlyIgnoreClientPromisc, boolean, false} * When set all request for operating any non-trunk interface promiscuous mode * will be ignored. This differs from IgnoreClientPromisc in that clients won't * get VERR_INTNET_INCOMPATIBLE_FLAGS. */ N_(
"Configuration error: Failed to get the \"QuietlyIgnoreClientPromisc\" value"));
/** @cfgm{IgnoreTrunkWirePromisc, boolean, false} * When set all request for operating the trunk-wire connection in promiscuous * mode will be ignored. */ N_(
"Configuration error: Failed to get the \"IgnoreTrunkWirePromisc\" value"));
/** @cfgm{QuietlyIgnoreTrunkWirePromisc, boolean, false} * When set all request for operating any trunk-wire connection promiscuous mode * will be ignored. This differs from IgnoreTrunkWirePromisc in that clients * won't get VERR_INTNET_INCOMPATIBLE_FLAGS. */ N_(
"Configuration error: Failed to get the \"QuietlyIgnoreTrunkWirePromisc\" value"));
/** @cfgm{IgnoreTrunkHostPromisc, boolean, false} * When set all request for operating the trunk-host connection in promiscuous * mode will be ignored. */ N_(
"Configuration error: Failed to get the \"IgnoreTrunkHostPromisc\" value"));
/** @cfgm{QuietlyIgnoreTrunkHostPromisc, boolean, false} * When set all request for operating any trunk-host connection promiscuous mode * will be ignored. This differs from IgnoreTrunkHostPromisc in that clients * won't get VERR_INTNET_INCOMPATIBLE_FLAGS. */ N_(
"Configuration error: Failed to get the \"QuietlyIgnoreTrunkHostPromisc\" value"));
/** @todo flags for not sending to the host and for setting the trunk-wire * connection in promiscuous mode. */ /** @cfgm{SharedMacOnWire, boolean, false} * Whether to shared the MAC address of the host interface when using the wire. When * attaching to a wireless NIC this option is usally a requirement. N_(
"Configuration error: Failed to get the \"SharedMacOnWire\" value"));
/** @cfgm{ReceiveBufferSize, uint32_t, 218 KB} * The size of the receive buffer. N_(
"Configuration error: Failed to get the \"ReceiveBufferSize\" value"));
/** @cfgm{SendBufferSize, uint32_t, 36 KB} * The size of the send (transmit) buffer. * This should be more than twice the size of the larges frame size because * the ring buffer is very simple and doesn't support splitting up frames * nor inserting padding. So, if this is too close to the frame size the * header will fragment the buffer such that the frame won't fit on either * side of it and the code will get very upset about it all. N_(
"Configuration error: Failed to get the \"SendBufferSize\" value"));
N_(
"Configuration error: The \"SendBufferSize\" value is too small"));
LogRel((
"DrvIntNet: Warning! SendBufferSize=%u, Recommended minimum size %u butes.\n",
OpenReq.
cbSend,
16384*
2 +
64));
/** @cfgm{IsService, boolean, true} * This alterns the way the thread is suspended and resumed. When it's being used by * a service such as LWIP/iSCSI it shouldn't suspend immediately like for a NIC. N_(
"Configuration error: Failed to get the \"IsService\" value"));
LogRel((
"IntNet#%u: szNetwork={%s} enmTrunkType=%d szTrunk={%s} fFlags=%#x cbRecv=%u cbSend=%u\n",
/* Temporary hack: attach to a network with the name 'if=en0' and you're hitting the wire. */ /* Temporary hack: attach to a network with the name 'wif=en0' and you're on the air. */ * We have a ndis filter driver started on system boot before the VBoxDrv, * tell the filter driver to init VBoxNetFlt functionality. * <Describe what this does here or/and in the function docs of drvIntNetWinIfGuidToBindName>. #
endif /* WINDOWS && NETFLT */ * Create the event semaphores /* new network gets created, check if we need to launch a DHCP server for it */ /* this means we have DHCP server enabled */ N_(
"Configuration error: Failed to get the \"DhcpNetworkMask\" value"));
N_(
"Configuration error: Failed to get the \"DhcpLowerIP\" value"));
N_(
"Configuration error: Failed to get the \"DhcpUpperIP\" value"));
N_(
"Configuration error: Failed to get the \"DhcpMacAddress\" value"));
//temporary hack for testing N_(
"Failed to get ring-3 buffer for the newly created interface to '%s'"),
pThis->
szNetwork);
* Create the async I/O thread. * Note! Using a PDM thread here doesn't fit with the IsService=true operation. * Activate data transmission as early as possible * Internal networking transport driver registration record. "Internal Networking Transport Driver",