DevVirtioNet.cpp revision d99197f8edcfa672509d9418fa6441c0c66af33c
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * DevVirtioNet - Virtio Network Device
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Copyright (C) 2009 Sun Microsystems, Inc.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * This file is part of VirtualBox Open Source Edition (OSE), as
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * available from http://www.virtualbox.org. This file is free software;
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * you can redistribute it and/or modify it under the terms of the GNU
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * General Public License (GPL) as published by the Free Software
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Foundation, in version 2 as it comes in the "COPYING" file of the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Clara, CA 95054 USA or visit http://www.sun.com if you need
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * additional information or have any questions.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif /* IN_RING3 */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define INSTANCE(pState) pState->VPCI.szInstance
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ((VNETSTATE *)((char*)pIface - RT_OFFSETOF(VNETSTATE, ifaceName)))
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Virtio Block Device */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif /* IN_RING3 */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Forward declarations ******************************************************/
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterPDMBOTHCBDECL(int) vnetIOPortIn (PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterPDMBOTHCBDECL(int) vnetIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb);
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major#endif /* VBOX_DEVICE_STRUCT_TESTCASE */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_MAX_FRAME_SIZE 65536 // TODO: Is it the right limit?
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster/* Virtio net features */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_F_CSUM 0x00000001 /* Host handles pkts w/ partial csum */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_F_GUEST_CSUM 0x00000002 /* Guest handles pkts w/ partial csum */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_F_MAC 0x00000020 /* Host has given MAC address. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_GSO 0x00000040 /* Host handles pkts w/ any GSO type */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_GUEST_TSO4 0x00000080 /* Guest can handle TSOv4 in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_GUEST_TSO6 0x00000100 /* Guest can handle TSOv6 in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_GUEST_ECN 0x00000200 /* Guest can handle TSO[6] w/ ECN in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_GUEST_UFO 0x00000400 /* Guest can handle UFO in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_HOST_TSO4 0x00000800 /* Host can handle TSOv4 in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_HOST_TSO6 0x00001000 /* Host can handle TSOv6 in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_HOST_ECN 0x00002000 /* Host can handle TSO[6] w/ ECN in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_HOST_UFO 0x00004000 /* Host can handle UFO in. */
c070f56622b9a37191894cf0937d85e943ef6033Peter Major#define VNET_F_MRG_RXBUF 0x00008000 /* Host can merge receive buffers. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_F_STATUS 0x00010000 /* virtio_net_config.status available */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_F_CTRL_VQ 0x00020000 /* Control channel available */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_F_CTRL_RX 0x00040000 /* Control channel RX mode support */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#define VNET_F_CTRL_VLAN 0x00080000 /* Control channel VLAN filtering */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#else /* !_MSC_VER */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstruct __attribute__ ((__packed__)) VNetPCIConfig
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif /* !_MSC_VER */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterAssertCompileMemberOffset(struct VNetPCIConfig, uStatus, 6);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Device state structure. Holds the current state of device.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @extends VPCISTATE
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @implements PDMINETWORKPORT
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @implements PDMINETWORKCONFIG
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major /* VPCISTATE must be the first member! */
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major// PDMCRITSECT csRx; /**< Protects RX queue. */
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major R3PTRTYPE(PPDMIBASE) pDrvBase; /**< Attached network driver. */
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major R3PTRTYPE(PPDMINETWORKCONNECTOR) pDrv; /**< Connector of attached network driver. */
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major R3PTRTYPE(PPDMQUEUE) pCanRxQueueR3; /**< Rx wakeup signaller - R3. */
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major R0PTRTYPE(PPDMQUEUE) pCanRxQueueR0; /**< Rx wakeup signaller - R0. */
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major RCPTRTYPE(PPDMQUEUE) pCanRxQueueRC; /**< Rx wakeup signaller - RC. */
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major /** transmit buffer */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /**< Link Up(/Restore) Timer. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /**< Transmit Delay Timer - R3. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /**< Transmit Delay Timer - R0. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /**< Transmit Delay Timer - GC. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif /* VNET_TX_DELAY */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** Indicates transmission in progress -- only one thread is allowed. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** PCI config area holding MAC address as well as TBD. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** MAC address obtained from the configuration. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** True if physical cable is attached in configuration. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** Number of packet being sent/received to show in debug log. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** Promiscuous mode -- RX filter accepts all packets. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** AllMulti mode -- RX filter accepts all multicast packets. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** The number of actually used slots in aMacTable. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** Array of MAC addresses accepted by RX filter. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** Bit array of VLAN filter, one bit per VLAN ID. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster uint8_t aVlanFilter[VNET_MAX_VID / sizeof(uint8_t)];
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Receive-blocking-related fields ***************************************/
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /** EMT: Gets signalled when more RX descriptors become available. */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Statistic fields ******************************************************/
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster#endif /* VBOX_WITH_STATISTICS */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterDECLINLINE(int) vnetCsEnter(PVNETSTATE pState, int rcBusy)
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter MajorDECLINLINE(int) vnetCsRxEnter(PVNETSTATE pState, int rcBusy)
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major // STAM_PROFILE_START(&pState->CTXSUFF(StatCsRx), a);
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major // int rc = PDMCritSectEnter(&pState->csRx, rcBusy);
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major // STAM_PROFILE_STOP(&pState->CTXSUFF(StatCsRx), a);
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major // return rc;
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter MajorDECLINLINE(void) vnetCsRxLeave(PVNETSTATE pState)
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major // PDMCritSectLeave(&pState->csRx);
31e5c48be26b4540b5388450d642bbc38c0afcc0Peter Major * Dump a packet to debug log.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param pState The device state structure.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param cpPacket The packet.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param cb The size of the packet.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * @param cszText A string denoting direction of packet transfer.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterDECLINLINE(void) vnetPacketDump(PVNETSTATE pState, const uint8_t *cpPacket, size_t cb, const char *cszText)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster INSTANCE(pState), cszText, ++pState->u32PktNo, cb));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster //Log3(("%.*Rhxd\n", cb, cpPacket));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterPDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pvState)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* We support:
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - Host-provided MAC address
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - Link status reporting in config space
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - Control queue
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - RX mode setting
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - MAC filter table
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * - VLAN filter
return VNET_F_MAC
return VNET_F_MAC;
Log(("%s vnetGetConfig: Read beyond the config structure is attempted (port=%RTiop cb=%x).\n", INSTANCE(pState), port, cb));
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
Log(("%s vnetGetConfig: Write beyond the config structure is attempted (port=%RTiop cb=%x).\n", INSTANCE(pState), port, cb));
return VINF_SUCCESS;
return VINF_SUCCESS;
STATUS = 0;
#ifdef IN_RING3
#ifdef IN_RING3
if (pItem)
#ifdef IN_RING3
return rc;
return VINF_SUCCESS;
return VERR_NET_NO_BUFFER_SPACE;
while (RT_LIKELY( (enmVMState = PDMDevHlpVMState(pState->VPCI.CTX_SUFF(pDevIns))) == VMSTATE_RUNNING
return rc;
unsigned int uOffset = 0;
return VERR_INTERNAL_ERROR;
return VERR_INTERNAL_ERROR;
if (nElem == 0)
Log(("%s vnetHandleRxPacket: The first descriptor does match the header size!\n", INSTANCE(pState)));
return VERR_INTERNAL_ERROR;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
return PDMNETWORKLINKSTATE_UP;
return PDMNETWORKLINKSTATE_DOWN;
static DECLCALLBACK(int) vnetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
if (fNewUp)
return VINF_SUCCESS;
unsigned int uOffset = 0;
#ifdef VNET_TX_DELAY
return u8Ack;
return VNET_ERROR;
return VNET_ERROR;
if (nMacs)
#ifdef DEBUG
for(unsigned i = 0; i < nMacs; i++)
return VNET_ERROR;
if (nMacs)
#ifdef DEBUG
for(unsigned i = 0; i < nMacs; i++)
return VNET_OK;
return VNET_ERROR;
return VNET_ERROR;
case VNET_CTRL_CMD_VLAN_ADD:
case VNET_CTRL_CMD_VLAN_DEL:
return u8Ack;
unsigned int uOffset = 0;
sizeof(VNETCTLACK)));
case VNET_CTRL_CLS_RX_MODE:
case VNET_CTRL_CLS_MAC:
case VNET_CTRL_CLS_VLAN:
return VINF_SSM_DONT_CALL_AGAIN;
return rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) vnetLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
int rc;
LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n", INSTANCE(pState), &pState->macConfigured, &macConfigured));
* sizeof(RTMAC));
return rc;
return VINF_SUCCESS;
int rc;
return VERR_INTERNAL_ERROR;
#ifdef VNET_GC_SUPPORT
return rc;
#ifdef VBOX_DYNAMIC_NET_ATTACH
return rc;
#ifdef RT_OS_LINUX
N_("A Domain Name Server (DNS) for NAT networking could not be determined. Please check your /etc/resolv.conf for <tt>nameserver</tt> entries. Either add one manually (<i>man resolv.conf</i>) or ensure that your host is correctly connected to an ISP. If you ignore this warning the guest will not be able to perform nameserver lookups and it will probably observe delays if trying so"));
N_("A Domain Name Server (DNS) for NAT networking could not be determined. Ensure that your host is correctly connected to an ISP. If you ignore this warning the guest will not be able to perform nameserver lookups and it will probably observe delays if trying so"));
return rc;
#ifdef VNET_TX_DELAY
int rc;
// char szTmp[sizeof(pState->VPCI.szInstance) + 2];
// RTStrPrintf(szTmp, sizeof(szTmp), "%sRX", pState->VPCI.szInstance);
return rc;
return rc;
return rc;
return rc;
#ifdef VNET_TX_DELAY
return rc;
N_("A Domain Name Server (DNS) for NAT networking could not be determined. Ensure that your host is correctly connected to an ISP. If you ignore this warning the guest will not be able to perform nameserver lookups and it will probably observe delays if trying so"));
return rc;
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Devices/VNet%d/ReceiveBytes", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Devices/VNet%d/TransmitBytes", iInstance);
#if defined(VBOX_WITH_STATISTICS)
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling receive", "/Devices/VNet%d/Receive/Total", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveStore, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling receive storing", "/Devices/VNet%d/Receive/Store", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatRxOverflow, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling RX overflows", "/Devices/VNet%d/RxOverflow", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatRxOverflowWakeup, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of RX overflow wakeups", "/Devices/VNet%d/RxOverflowWakeup", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in HC", "/Devices/VNet%d/Transmit/Total", iInstance);
PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitSend, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling send transmit in HC", "/Devices/VNet%d/Transmit/Send", iInstance);
return VINF_SUCCESS;
#ifdef VNET_GC_SUPPORT
sizeof(VNETSTATE),
NULL,
NULL,
NULL,
NULL,
#ifdef VBOX_DYNAMIC_NET_ATTACH
NULL,
NULL,
NULL,
NULL,
NULL,