summaryrefslogtreecommitdiff
path: root/src/VBox/Devices/Network/DevVirtioNet.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2014-03-26 19:21:20 +0000
committer <>2014-05-08 15:03:54 +0000
commitfb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch)
treec2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Devices/Network/DevVirtioNet.cpp
parent58ed4748338f9466599adfc8a9171280ed99e23f (diff)
downloadVirtualBox-master.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Devices/Network/DevVirtioNet.cpp')
-rw-r--r--src/VBox/Devices/Network/DevVirtioNet.cpp1229
1 files changed, 595 insertions, 634 deletions
diff --git a/src/VBox/Devices/Network/DevVirtioNet.cpp b/src/VBox/Devices/Network/DevVirtioNet.cpp
index ead10809..729ae659 100644
--- a/src/VBox/Devices/Network/DevVirtioNet.cpp
+++ b/src/VBox/Devices/Network/DevVirtioNet.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009-2011 Oracle Corporation
+ * Copyright (C) 2009-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -16,6 +16,9 @@
*/
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DEV_VIRTIO_NET
#define VNET_GC_SUPPORT
#define VNET_WITH_GSO
@@ -34,10 +37,13 @@
#include "../VirtIO/Virtio.h"
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
-#define INSTANCE(pState) pState->VPCI.szInstance
-#define STATUS pState->config.uStatus
+#define INSTANCE(pThis) pThis->VPCI.szInstance
+#define STATUS pThis->config.uStatus
#ifdef IN_RING3
@@ -56,46 +62,45 @@
#endif /* IN_RING3 */
-/* Forward declarations ******************************************************/
-RT_C_DECLS_BEGIN
-PDMBOTHCBDECL(int) vnetIOPortIn (PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb);
-PDMBOTHCBDECL(int) vnetIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb);
-RT_C_DECLS_END
-
#endif /* VBOX_DEVICE_STRUCT_TESTCASE */
-#define VNET_TX_DELAY 150 /* 150 microseconds */
-#define VNET_MAX_FRAME_SIZE 65536 // TODO: Is it the right limit?
+#define VNET_TX_DELAY 150 /**< 150 microseconds */
+#define VNET_MAX_FRAME_SIZE 65535 + 18 /**< Max IP packet size + Ethernet header with VLAN tag */
#define VNET_MAC_FILTER_LEN 32
#define VNET_MAX_VID (1 << 12)
-/* Virtio net features */
-#define VNET_F_CSUM 0x00000001 /* Host handles pkts w/ partial csum */
-#define VNET_F_GUEST_CSUM 0x00000002 /* Guest handles pkts w/ partial csum */
-#define VNET_F_MAC 0x00000020 /* Host has given MAC address. */
-#define VNET_F_GSO 0x00000040 /* Host handles pkts w/ any GSO type */
-#define VNET_F_GUEST_TSO4 0x00000080 /* Guest can handle TSOv4 in. */
-#define VNET_F_GUEST_TSO6 0x00000100 /* Guest can handle TSOv6 in. */
-#define VNET_F_GUEST_ECN 0x00000200 /* Guest can handle TSO[6] w/ ECN in. */
-#define VNET_F_GUEST_UFO 0x00000400 /* Guest can handle UFO in. */
-#define VNET_F_HOST_TSO4 0x00000800 /* Host can handle TSOv4 in. */
-#define VNET_F_HOST_TSO6 0x00001000 /* Host can handle TSOv6 in. */
-#define VNET_F_HOST_ECN 0x00002000 /* Host can handle TSO[6] w/ ECN in. */
-#define VNET_F_HOST_UFO 0x00004000 /* Host can handle UFO in. */
-#define VNET_F_MRG_RXBUF 0x00008000 /* Host can merge receive buffers. */
-#define VNET_F_STATUS 0x00010000 /* virtio_net_config.status available */
-#define VNET_F_CTRL_VQ 0x00020000 /* Control channel available */
-#define VNET_F_CTRL_RX 0x00040000 /* Control channel RX mode support */
-#define VNET_F_CTRL_VLAN 0x00080000 /* Control channel VLAN filtering */
+/** @name Virtio net features
+ * @{ */
+#define VNET_F_CSUM 0x00000001 /**< Host handles pkts w/ partial csum */
+#define VNET_F_GUEST_CSUM 0x00000002 /**< Guest handles pkts w/ partial csum */
+#define VNET_F_MAC 0x00000020 /**< Host has given MAC address. */
+#define VNET_F_GSO 0x00000040 /**< Host handles pkts w/ any GSO type */
+#define VNET_F_GUEST_TSO4 0x00000080 /**< Guest can handle TSOv4 in. */
+#define VNET_F_GUEST_TSO6 0x00000100 /**< Guest can handle TSOv6 in. */
+#define VNET_F_GUEST_ECN 0x00000200 /**< Guest can handle TSO[6] w/ ECN in. */
+#define VNET_F_GUEST_UFO 0x00000400 /**< Guest can handle UFO in. */
+#define VNET_F_HOST_TSO4 0x00000800 /**< Host can handle TSOv4 in. */
+#define VNET_F_HOST_TSO6 0x00001000 /**< Host can handle TSOv6 in. */
+#define VNET_F_HOST_ECN 0x00002000 /**< Host can handle TSO[6] w/ ECN in. */
+#define VNET_F_HOST_UFO 0x00004000 /**< Host can handle UFO in. */
+#define VNET_F_MRG_RXBUF 0x00008000 /**< Host can merge receive buffers. */
+#define VNET_F_STATUS 0x00010000 /**< virtio_net_config.status available */
+#define VNET_F_CTRL_VQ 0x00020000 /**< Control channel available */
+#define VNET_F_CTRL_RX 0x00040000 /**< Control channel RX mode support */
+#define VNET_F_CTRL_VLAN 0x00080000 /**< Control channel VLAN filtering */
+/** @} */
#define VNET_S_LINK_UP 1
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
#ifdef _MSC_VER
struct VNetPCIConfig
#else /* !_MSC_VER */
-struct __attribute__ ((__packed__)) VNetPCIConfig
+struct __attribute__ ((__packed__)) VNetPCIConfig /** @todo r=bird: Use #pragma pack if necessary, that's portable! */
#endif /* !_MSC_VER */
{
RTMAC mac;
@@ -110,7 +115,7 @@ AssertCompileMemberOffset(struct VNetPCIConfig, uStatus, 6);
* @implements PDMINETWORKDOWN
* @implements PDMINETWORKCONFIG
*/
-struct VNetState_st
+typedef struct VNetState_st
{
/* VPCISTATE must be the first member! */
VPCISTATE VPCI;
@@ -190,8 +195,8 @@ struct VNetState_st
/** EMT: Gets signalled when more RX descriptors become available. */
RTSEMEVENT hEventMoreRxDescAvail;
- /* Statistic fields ******************************************************/
-
+ /** @name Statistic
+ * @{ */
STAMCOUNTER StatReceiveBytes;
STAMCOUNTER StatTransmitBytes;
STAMCOUNTER StatReceiveGSO;
@@ -206,9 +211,9 @@ struct VNetState_st
STAMPROFILE StatRxOverflow;
STAMCOUNTER StatRxOverflowWakeup;
#endif /* VBOX_WITH_STATISTICS */
-
-};
-typedef struct VNetState_st VNETSTATE;
+ /** @} */
+} VNETSTATE;
+/** Pointer to a virtual I/O network device state. */
typedef VNETSTATE *PVNETSTATE;
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
@@ -270,49 +275,49 @@ typedef struct VNetCtlHdr VNETCTLHDR;
typedef VNETCTLHDR *PVNETCTLHDR;
AssertCompileSize(VNETCTLHDR, 2);
-/* Returns true if large packets are written into several RX buffers. */
-DECLINLINE(bool) vnetMergeableRxBuffers(PVNETSTATE pState)
+/** Returns true if large packets are written into several RX buffers. */
+DECLINLINE(bool) vnetMergeableRxBuffers(PVNETSTATE pThis)
{
- return !!(pState->VPCI.uGuestFeatures & VNET_F_MRG_RXBUF);
+ return !!(pThis->VPCI.uGuestFeatures & VNET_F_MRG_RXBUF);
}
-DECLINLINE(int) vnetCsEnter(PVNETSTATE pState, int rcBusy)
+DECLINLINE(int) vnetCsEnter(PVNETSTATE pThis, int rcBusy)
{
- return vpciCsEnter(&pState->VPCI, rcBusy);
+ return vpciCsEnter(&pThis->VPCI, rcBusy);
}
-DECLINLINE(void) vnetCsLeave(PVNETSTATE pState)
+DECLINLINE(void) vnetCsLeave(PVNETSTATE pThis)
{
- vpciCsLeave(&pState->VPCI);
+ vpciCsLeave(&pThis->VPCI);
}
-DECLINLINE(int) vnetCsRxEnter(PVNETSTATE pState, int rcBusy)
+DECLINLINE(int) vnetCsRxEnter(PVNETSTATE pThis, int rcBusy)
{
- // STAM_PROFILE_START(&pState->CTXSUFF(StatCsRx), a);
- // int rc = PDMCritSectEnter(&pState->csRx, rcBusy);
- // STAM_PROFILE_STOP(&pState->CTXSUFF(StatCsRx), a);
+ // STAM_PROFILE_START(&pThis->CTXSUFF(StatCsRx), a);
+ // int rc = PDMCritSectEnter(&pThis->csRx, rcBusy);
+ // STAM_PROFILE_STOP(&pThis->CTXSUFF(StatCsRx), a);
// return rc;
return VINF_SUCCESS;
}
-DECLINLINE(void) vnetCsRxLeave(PVNETSTATE pState)
+DECLINLINE(void) vnetCsRxLeave(PVNETSTATE pThis)
{
- // PDMCritSectLeave(&pState->csRx);
+ // PDMCritSectLeave(&pThis->csRx);
}
/**
* Dump a packet to debug log.
*
- * @param pState The device state structure.
+ * @param pThis The device state structure.
* @param cpPacket The packet.
* @param cb The size of the packet.
* @param cszText A string denoting direction of packet transfer.
*/
-DECLINLINE(void) vnetPacketDump(PVNETSTATE pState, const uint8_t *cpPacket, size_t cb, const char *cszText)
+DECLINLINE(void) vnetPacketDump(PVNETSTATE pThis, const uint8_t *cpPacket, size_t cb, const char *cszText)
{
#ifdef DEBUG
Log(("%s %s packet #%d (%d bytes):\n",
- INSTANCE(pState), cszText, ++pState->u32PktNo, cb));
+ INSTANCE(pThis), cszText, ++pThis->u32PktNo, cb));
Log3(("%.*Rhxd\n", cb, cpPacket));
#endif
}
@@ -320,18 +325,19 @@ DECLINLINE(void) vnetPacketDump(PVNETSTATE pState, const uint8_t *cpPacket, size
/**
* Print features given in uFeatures to debug log.
*
- * @param pState The device state structure.
- * @param uFeatures Descriptions of which features to print.
+ * @param pThis The device state structure.
+ * @param fFeatures Descriptions of which features to print.
* @param pcszText A string to print before the list of features.
*/
-DECLINLINE(void) vnetPrintFeatures(PVNETSTATE pState, uint32_t uFeatures, const char *pcszText)
+DECLINLINE(void) vnetPrintFeatures(PVNETSTATE pThis, uint32_t fFeatures, const char *pcszText)
{
#ifdef DEBUG
static struct
{
uint32_t uMask;
const char *pcszDesc;
- } aFeatures[] = {
+ } const s_aFeatures[] =
+ {
{ VNET_F_CSUM, "host handles pkts w/ partial csum" },
{ VNET_F_GUEST_CSUM, "guest handles pkts w/ partial csum" },
{ VNET_F_MAC, "host has given MAC address" },
@@ -351,16 +357,16 @@ DECLINLINE(void) vnetPrintFeatures(PVNETSTATE pState, uint32_t uFeatures, const
{ VNET_F_CTRL_VLAN, "control channel VLAN filtering" }
};
- Log3(("%s %s:\n", INSTANCE(pState), pcszText));
- for (unsigned i = 0; i < RT_ELEMENTS(aFeatures); ++i)
+ Log3(("%s %s:\n", INSTANCE(pThis), pcszText));
+ for (unsigned i = 0; i < RT_ELEMENTS(s_aFeatures); ++i)
{
- if (aFeatures[i].uMask & uFeatures)
- Log3(("%s --> %s\n", INSTANCE(pState), aFeatures[i].pcszDesc));
+ if (s_aFeatures[i].uMask & fFeatures)
+ Log3(("%s --> %s\n", INSTANCE(pThis), s_aFeatures[i].pcszDesc));
}
#endif /* DEBUG */
}
-PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pvState)
+static DECLCALLBACK(uint32_t) vnetIoCb_GetHostFeatures(void *pvState)
{
/* We support:
* - Host-provided MAC address
@@ -380,6 +386,7 @@ PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pvState)
| VNET_F_HOST_TSO4
| VNET_F_HOST_TSO6
| VNET_F_HOST_UFO
+ | VNET_F_GUEST_CSUM /* We expect the guest to accept partial TCP checksums (see @bugref{4796}) */
| VNET_F_GUEST_TSO4
| VNET_F_GUEST_TSO6
| VNET_F_GUEST_UFO
@@ -390,86 +397,87 @@ PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pvState)
;
}
-PDMBOTHCBDECL(uint32_t) vnetGetHostMinimalFeatures(void *pvState)
+static DECLCALLBACK(uint32_t) vnetIoCb_GetHostMinimalFeatures(void *pvState)
{
return VNET_F_MAC;
}
-PDMBOTHCBDECL(void) vnetSetHostFeatures(void *pvState, uint32_t uFeatures)
+static DECLCALLBACK(void) vnetIoCb_SetHostFeatures(void *pvState, uint32_t fFeatures)
{
- // TODO: Nothing to do here yet
- VNETSTATE *pState = (VNETSTATE *)pvState;
- LogFlow(("%s vnetSetHostFeatures: uFeatures=%x\n", INSTANCE(pState), uFeatures));
- vnetPrintFeatures(pState, uFeatures, "The guest negotiated the following features");
+ /** @todo Nothing to do here yet */
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
+ LogFlow(("%s vnetIoCb_SetHostFeatures: uFeatures=%x\n", INSTANCE(pThis), fFeatures));
+ vnetPrintFeatures(pThis, fFeatures, "The guest negotiated the following features");
}
-PDMBOTHCBDECL(int) vnetGetConfig(void *pvState, uint32_t port, uint32_t cb, void *data)
+static DECLCALLBACK(int) vnetIoCb_GetConfig(void *pvState, uint32_t offCfg, uint32_t cb, void *data)
{
- VNETSTATE *pState = (VNETSTATE *)pvState;
- if (port + cb > sizeof(struct VNetPCIConfig))
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
+ if (offCfg + cb > sizeof(struct VNetPCIConfig))
{
- Log(("%s vnetGetConfig: Read beyond the config structure is attempted (port=%RTiop cb=%x).\n", INSTANCE(pState), port, cb));
+ Log(("%s vnetIoCb_GetConfig: Read beyond the config structure is attempted (offCfg=%#x cb=%x).\n", INSTANCE(pThis), offCfg, cb));
return VERR_IOM_IOPORT_UNUSED;
}
- memcpy(data, ((uint8_t*)&pState->config) + port, cb);
+ memcpy(data, (uint8_t *)&pThis->config + offCfg, cb);
return VINF_SUCCESS;
}
-PDMBOTHCBDECL(int) vnetSetConfig(void *pvState, uint32_t port, uint32_t cb, void *data)
+static DECLCALLBACK(int) vnetIoCb_SetConfig(void *pvState, uint32_t offCfg, uint32_t cb, void *data)
{
- VNETSTATE *pState = (VNETSTATE *)pvState;
- if (port + cb > sizeof(struct VNetPCIConfig))
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
+ if (offCfg + cb > sizeof(struct VNetPCIConfig))
{
- Log(("%s vnetGetConfig: Write beyond the config structure is attempted (port=%RTiop cb=%x).\n", INSTANCE(pState), port, cb));
- if (port < sizeof(struct VNetPCIConfig))
- memcpy(((uint8_t*)&pState->config) + port, data,
- sizeof(struct VNetPCIConfig) - port);
+ Log(("%s vnetIoCb_SetConfig: Write beyond the config structure is attempted (offCfg=%#x cb=%x).\n", INSTANCE(pThis), offCfg, cb));
+ if (offCfg < sizeof(struct VNetPCIConfig))
+ memcpy((uint8_t *)&pThis->config + offCfg, data,
+ sizeof(struct VNetPCIConfig) - offCfg);
return VINF_SUCCESS;
}
- memcpy(((uint8_t*)&pState->config) + port, data, cb);
+ memcpy((uint8_t *)&pThis->config + offCfg, data, cb);
return VINF_SUCCESS;
}
/**
* Hardware reset. Revert all registers to initial values.
*
- * @param pState The device state structure.
+ * @param pThis The device state structure.
*/
-PDMBOTHCBDECL(int) vnetReset(void *pvState)
+static DECLCALLBACK(int) vnetIoCb_Reset(void *pvState)
{
- VNETSTATE *pState = (VNETSTATE*)pvState;
- Log(("%s Reset triggered\n", INSTANCE(pState)));
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
+ Log(("%s Reset triggered\n", INSTANCE(pThis)));
- int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
+ int rc = vnetCsRxEnter(pThis, VERR_SEM_BUSY);
if (RT_UNLIKELY(rc != VINF_SUCCESS))
{
- LogRel(("vnetReset failed to enter RX critical section!\n"));
+ LogRel(("vnetIoCb_Reset failed to enter RX critical section!\n"));
return rc;
}
- vpciReset(&pState->VPCI);
- vnetCsRxLeave(pState);
+ vpciReset(&pThis->VPCI);
+ vnetCsRxLeave(pThis);
// TODO: Implement reset
- if (pState->fCableConnected)
+ if (pThis->fCableConnected)
STATUS = VNET_S_LINK_UP;
else
STATUS = 0;
+ Log(("%s vnetIoCb_Reset: Link is %s\n", INSTANCE(pThis), pThis->fCableConnected ? "up" : "down"));
/*
* By default we pass all packets up since the older guests cannot control
* virtio mode.
*/
- pState->fPromiscuous = true;
- pState->fAllMulti = false;
- pState->nMacFilterEntries = 0;
- memset(pState->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC));
- memset(pState->aVlanFilter, 0, sizeof(pState->aVlanFilter));
- pState->uIsTransmitting = 0;
+ pThis->fPromiscuous = true;
+ pThis->fAllMulti = false;
+ pThis->nMacFilterEntries = 0;
+ memset(pThis->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC));
+ memset(pThis->aVlanFilter, 0, sizeof(pThis->aVlanFilter));
+ pThis->uIsTransmitting = 0;
#ifndef IN_RING3
return VINF_IOM_R3_IOPORT_WRITE;
#else
- if (pState->pDrv)
- pState->pDrv->pfnSetPromiscuousMode(pState->pDrv, true);
+ if (pThis->pDrv)
+ pThis->pDrv->pfnSetPromiscuousMode(pThis->pDrv, true);
return VINF_SUCCESS;
#endif
}
@@ -481,42 +489,64 @@ PDMBOTHCBDECL(int) vnetReset(void *pvState)
*/
static void vnetWakeupReceive(PPDMDEVINS pDevIns)
{
- VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE *);
- if ( pState->fMaybeOutOfSpace
- && pState->hEventMoreRxDescAvail != NIL_RTSEMEVENT)
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
+ if ( pThis->fMaybeOutOfSpace
+ && pThis->hEventMoreRxDescAvail != NIL_RTSEMEVENT)
{
- STAM_COUNTER_INC(&pState->StatRxOverflowWakeup);
- Log(("%s Waking up Out-of-RX-space semaphore\n", INSTANCE(pState)));
- RTSemEventSignal(pState->hEventMoreRxDescAvail);
+ STAM_COUNTER_INC(&pThis->StatRxOverflowWakeup);
+ Log(("%s Waking up Out-of-RX-space semaphore\n", INSTANCE(pThis)));
+ RTSemEventSignal(pThis->hEventMoreRxDescAvail);
}
}
+
/**
- * Link Up Timer handler.
+ * Takes down the link temporarily if it's current status is up.
*
- * @param pDevIns Pointer to device instance structure.
- * @param pTimer Pointer to the timer.
- * @param pvUser NULL.
- * @thread EMT
+ * This is used during restore and when replumbing the network link.
+ *
+ * The temporary link outage is supposed to indicate to the OS that all network
+ * connections have been lost and that it for instance is appropriate to
+ * renegotiate any DHCP lease.
+ *
+ * @param pThis The Virtual I/O network device state.
+ */
+static void vnetTempLinkDown(PVNETSTATE pThis)
+{
+ if (STATUS & VNET_S_LINK_UP)
+ {
+ STATUS &= ~VNET_S_LINK_UP;
+ vpciRaiseInterrupt(&pThis->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
+ /* Restore the link back in 5 seconds. */
+ int rc = TMTimerSetMillies(pThis->pLinkUpTimer, pThis->cMsLinkUpDelay);
+ AssertRC(rc);
+ Log(("%s vnetTempLinkDown: Link is down temporarily\n", INSTANCE(pThis)));
+ }
+}
+
+
+/**
+ * @callback_method_impl{FNTMTIMERDEV, Link Up Timer handler.}
*/
static DECLCALLBACK(void) vnetLinkUpTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
{
- VNETSTATE *pState = (VNETSTATE *)pvUser;
+ PVNETSTATE pThis = (PVNETSTATE)pvUser;
- int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
+ int rc = vnetCsEnter(pThis, VERR_SEM_BUSY);
if (RT_UNLIKELY(rc != VINF_SUCCESS))
return;
STATUS |= VNET_S_LINK_UP;
- vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
+ vpciRaiseInterrupt(&pThis->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
vnetWakeupReceive(pDevIns);
- vnetCsLeave(pState);
+ vnetCsLeave(pThis);
+ Log(("%s vnetLinkUpTimer: Link is up\n", INSTANCE(pThis)));
+ if (pThis->pDrv)
+ pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, PDMNETWORKLINKSTATE_UP);
}
-
-
/**
- * Handler for the wakeup signaller queue.
+ * @callback_method_impl{FNPDMQUEUEDEV, Handler for the wakeup signaller queue.}
*/
static DECLCALLBACK(bool) vnetCanRxQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem)
{
@@ -529,64 +559,52 @@ static DECLCALLBACK(bool) vnetCanRxQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEIT
/**
* This function is called when the driver becomes ready.
*
- * @param pState The device state structure.
+ * @param pThis The device state structure.
*/
-PDMBOTHCBDECL(void) vnetReady(void *pvState)
+static DECLCALLBACK(void) vnetIoCb_Ready(void *pvState)
{
- VNETSTATE *pState = (VNETSTATE*)pvState;
- Log(("%s Driver became ready, waking up RX thread...\n", INSTANCE(pState)));
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
+ Log(("%s Driver became ready, waking up RX thread...\n", INSTANCE(pThis)));
#ifdef IN_RING3
- vnetWakeupReceive(pState->VPCI.CTX_SUFF(pDevIns));
+ vnetWakeupReceive(pThis->VPCI.CTX_SUFF(pDevIns));
#else
- PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(pState->CTX_SUFF(pCanRxQueue));
+ PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(pThis->CTX_SUFF(pCanRxQueue));
if (pItem)
- PDMQueueInsert(pState->CTX_SUFF(pCanRxQueue), pItem);
+ PDMQueueInsert(pThis->CTX_SUFF(pCanRxQueue), pItem);
#endif
}
+
/**
- * Port I/O Handler for IN operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser Pointer to the device state structure.
- * @param port Port number used for the IN operation.
- * @param pu32 Where to store the result.
- * @param cb Number of bytes read.
- * @thread EMT
+ * I/O port callbacks.
+ */
+static const VPCIIOCALLBACKS g_IOCallbacks =
+{
+ vnetIoCb_GetHostFeatures,
+ vnetIoCb_GetHostMinimalFeatures,
+ vnetIoCb_SetHostFeatures,
+ vnetIoCb_GetConfig,
+ vnetIoCb_SetConfig,
+ vnetIoCb_Reset,
+ vnetIoCb_Ready,
+};
+
+
+/**
+ * @callback_method_impl{FNIOMIOPORTIN}
*/
-PDMBOTHCBDECL(int) vnetIOPortIn(PPDMDEVINS pDevIns, void *pvUser,
- RTIOPORT port, uint32_t *pu32, unsigned cb)
+PDMBOTHCBDECL(int) vnetIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t *pu32, unsigned cb)
{
- return vpciIOPortIn(pDevIns, pvUser, port, pu32, cb,
- vnetGetHostFeatures,
- vnetGetConfig);
+ return vpciIOPortIn(pDevIns, pvUser, port, pu32, cb, &g_IOCallbacks);
}
/**
- * Port I/O Handler for OUT operations.
- *
- * @returns VBox status code.
- *
- * @param pDevIns The device instance.
- * @param pvUser User argument.
- * @param Port Port number used for the IN operation.
- * @param u32 The value to output.
- * @param cb The value size in bytes.
- * @thread EMT
+ * @callback_method_impl{FNIOMIOPORTOUT}
*/
-PDMBOTHCBDECL(int) vnetIOPortOut(PPDMDEVINS pDevIns, void *pvUser,
- RTIOPORT port, uint32_t u32, unsigned cb)
-{
- return vpciIOPortOut(pDevIns, pvUser, port, u32, cb,
- vnetGetHostMinimalFeatures,
- vnetGetHostFeatures,
- vnetSetHostFeatures,
- vnetReset,
- vnetReady,
- vnetSetConfig);
+PDMBOTHCBDECL(int) vnetIOPortOut(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port, uint32_t u32, unsigned cb)
+{
+ return vpciIOPortOut(pDevIns, pvUser, port, u32, cb, &g_IOCallbacks);
}
@@ -604,29 +622,29 @@ PDMBOTHCBDECL(int) vnetIOPortOut(PPDMDEVINS pDevIns, void *pvUser,
* @param pInterface Pointer to the interface structure containing the called function pointer.
* @thread RX
*/
-static int vnetCanReceive(VNETSTATE *pState)
+static int vnetCanReceive(PVNETSTATE pThis)
{
- int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
+ int rc = vnetCsRxEnter(pThis, VERR_SEM_BUSY);
AssertRCReturn(rc, rc);
- LogFlow(("%s vnetCanReceive\n", INSTANCE(pState)));
- if (!(pState->VPCI.uStatus & VPCI_STATUS_DRV_OK))
+ LogFlow(("%s vnetCanReceive\n", INSTANCE(pThis)));
+ if (!(pThis->VPCI.uStatus & VPCI_STATUS_DRV_OK))
rc = VERR_NET_NO_BUFFER_SPACE;
- else if (!vqueueIsReady(&pState->VPCI, pState->pRxQueue))
+ else if (!vqueueIsReady(&pThis->VPCI, pThis->pRxQueue))
rc = VERR_NET_NO_BUFFER_SPACE;
- else if (vqueueIsEmpty(&pState->VPCI, pState->pRxQueue))
+ else if (vqueueIsEmpty(&pThis->VPCI, pThis->pRxQueue))
{
- vringSetNotification(&pState->VPCI, &pState->pRxQueue->VRing, true);
+ vringSetNotification(&pThis->VPCI, &pThis->pRxQueue->VRing, true);
rc = VERR_NET_NO_BUFFER_SPACE;
}
else
{
- vringSetNotification(&pState->VPCI, &pState->pRxQueue->VRing, false);
+ vringSetNotification(&pThis->VPCI, &pThis->pRxQueue->VRing, false);
rc = VINF_SUCCESS;
}
- LogFlow(("%s vnetCanReceive -> %Rrc\n", INSTANCE(pState), rc));
- vnetCsRxLeave(pState);
+ LogFlow(("%s vnetCanReceive -> %Rrc\n", INSTANCE(pThis), rc));
+ vnetCsRxLeave(pThis);
return rc;
}
@@ -635,9 +653,9 @@ static int vnetCanReceive(VNETSTATE *pState)
*/
static DECLCALLBACK(int) vnetNetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
{
- VNETSTATE *pState = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown);
- LogFlow(("%s vnetNetworkDown_WaitReceiveAvail(cMillies=%u)\n", INSTANCE(pState), cMillies));
- int rc = vnetCanReceive(pState);
+ PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown);
+ LogFlow(("%s vnetNetworkDown_WaitReceiveAvail(cMillies=%u)\n", INSTANCE(pThis), cMillies));
+ int rc = vnetCanReceive(pThis);
if (RT_SUCCESS(rc))
return VINF_SUCCESS;
@@ -645,27 +663,27 @@ static DECLCALLBACK(int) vnetNetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInte
return VERR_NET_NO_BUFFER_SPACE;
rc = VERR_INTERRUPTED;
- ASMAtomicXchgBool(&pState->fMaybeOutOfSpace, true);
- STAM_PROFILE_START(&pState->StatRxOverflow, a);
+ ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, true);
+ STAM_PROFILE_START(&pThis->StatRxOverflow, a);
VMSTATE enmVMState;
- while (RT_LIKELY( (enmVMState = PDMDevHlpVMState(pState->VPCI.CTX_SUFF(pDevIns))) == VMSTATE_RUNNING
+ while (RT_LIKELY( (enmVMState = PDMDevHlpVMState(pThis->VPCI.CTX_SUFF(pDevIns))) == VMSTATE_RUNNING
|| enmVMState == VMSTATE_RUNNING_LS))
{
- int rc2 = vnetCanReceive(pState);
+ int rc2 = vnetCanReceive(pThis);
if (RT_SUCCESS(rc2))
{
rc = VINF_SUCCESS;
break;
}
Log(("%s vnetNetworkDown_WaitReceiveAvail: waiting cMillies=%u...\n",
- INSTANCE(pState), cMillies));
- RTSemEventWait(pState->hEventMoreRxDescAvail, cMillies);
+ INSTANCE(pThis), cMillies));
+ RTSemEventWait(pThis->hEventMoreRxDescAvail, cMillies);
}
- STAM_PROFILE_STOP(&pState->StatRxOverflow, a);
- ASMAtomicXchgBool(&pState->fMaybeOutOfSpace, false);
+ STAM_PROFILE_STOP(&pThis->StatRxOverflow, a);
+ ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, false);
- LogFlow(("%s vnetNetworkDown_WaitReceiveAvail -> %d\n", INSTANCE(pState), rc));
+ LogFlow(("%s vnetNetworkDown_WaitReceiveAvail -> %d\n", INSTANCE(pThis), rc));
return rc;
}
@@ -675,7 +693,7 @@ static DECLCALLBACK(int) vnetNetworkDown_WaitReceiveAvail(PPDMINETWORKDOWN pInte
*/
static DECLCALLBACK(void *) vnetQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
{
- VNETSTATE *pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, VPCI.IBase);
+ PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, VPCI.IBase);
Assert(&pThis->VPCI.IBase == pInterface);
PDMIBASE_RETURN_INTERFACE(pszIID, PDMINETWORKDOWN, &pThis->INetworkDown);
@@ -711,42 +729,42 @@ DECLINLINE(bool) vnetIsMulticast(const void *pvBuf)
* Determines if the packet is to be delivered to upper layer.
*
* @returns true if packet is intended for this node.
- * @param pState Pointer to the state structure.
+ * @param pThis Pointer to the state structure.
* @param pvBuf The ethernet packet.
* @param cb Number of bytes available in the packet.
*/
-static bool vnetAddressFilter(PVNETSTATE pState, const void *pvBuf, size_t cb)
+static bool vnetAddressFilter(PVNETSTATE pThis, const void *pvBuf, size_t cb)
{
- if (pState->fPromiscuous)
+ if (pThis->fPromiscuous)
return true;
/* Ignore everything outside of our VLANs */
uint16_t *u16Ptr = (uint16_t*)pvBuf;
/* Compare TPID with VLAN Ether Type */
if ( u16Ptr[6] == RT_H2BE_U16(0x8100)
- && !ASMBitTest(pState->aVlanFilter, RT_BE2H_U16(u16Ptr[7]) & 0xFFF))
+ && !ASMBitTest(pThis->aVlanFilter, RT_BE2H_U16(u16Ptr[7]) & 0xFFF))
{
- Log4(("%s vnetAddressFilter: not our VLAN, returning false\n", INSTANCE(pState)));
+ Log4(("%s vnetAddressFilter: not our VLAN, returning false\n", INSTANCE(pThis)));
return false;
}
if (vnetIsBroadcast(pvBuf))
return true;
- if (pState->fAllMulti && vnetIsMulticast(pvBuf))
+ if (pThis->fAllMulti && vnetIsMulticast(pvBuf))
return true;
- if (!memcmp(pState->config.mac.au8, pvBuf, sizeof(RTMAC)))
+ if (!memcmp(pThis->config.mac.au8, pvBuf, sizeof(RTMAC)))
return true;
Log4(("%s vnetAddressFilter: %RTmac (conf) != %RTmac (dest)\n",
- INSTANCE(pState), pState->config.mac.au8, pvBuf));
+ INSTANCE(pThis), pThis->config.mac.au8, pvBuf));
- for (unsigned i = 0; i < pState->nMacFilterEntries; i++)
- if (!memcmp(&pState->aMacFilter[i], pvBuf, sizeof(RTMAC)))
+ for (unsigned i = 0; i < pThis->nMacFilterEntries; i++)
+ if (!memcmp(&pThis->aMacFilter[i], pvBuf, sizeof(RTMAC)))
return true;
- Log2(("%s vnetAddressFilter: failed all tests, returning false, packet dump follows:\n", INSTANCE(pState)));
- vnetPacketDump(pState, (const uint8_t*)pvBuf, cb, "<-- Incoming");
+ Log2(("%s vnetAddressFilter: failed all tests, returning false, packet dump follows:\n", INSTANCE(pThis)));
+ vnetPacketDump(pThis, (const uint8_t*)pvBuf, cb, "<-- Incoming");
return false;
}
@@ -758,23 +776,22 @@ static bool vnetAddressFilter(PVNETSTATE pState, const void *pvBuf, size_t cb)
* from real Ethernet: pad it and insert FCS.
*
* @returns VBox status code.
- * @param pState The device state structure.
+ * @param pThis The device state structure.
* @param pvBuf The available data.
* @param cb Number of bytes available in the buffer.
* @thread RX
*/
-static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb,
+static int vnetHandleRxPacket(PVNETSTATE pThis, const void *pvBuf, size_t cb,
PCPDMNETWORKGSO pGso)
{
VNETHDRMRX Hdr;
- PVNETHDRMRX pHdr;
unsigned uHdrLen;
RTGCPHYS addrHdrMrx = 0;
if (pGso)
{
Log2(("%s vnetHandleRxPacket: gso type=%x cbHdrsTotal=%u cbHdrsSeg=%u mss=%u"
- " off1=0x%x off2=0x%x\n", INSTANCE(pState), pGso->u8Type,
+ " off1=0x%x off2=0x%x\n", INSTANCE(pThis), pGso->u8Type,
pGso->cbHdrsTotal, pGso->cbHdrsSeg, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2));
Hdr.Hdr.u8Flags = VNETHDR_F_NEEDS_CSUM;
switch (pGso->u8Type)
@@ -797,7 +814,7 @@ static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb,
Hdr.Hdr.u16HdrLen = pGso->cbHdrsTotal;
Hdr.Hdr.u16GSOSize = pGso->cbMaxSeg;
Hdr.Hdr.u16CSumStart = pGso->offHdr2;
- STAM_REL_COUNTER_INC(&pState->StatReceiveGSO);
+ STAM_REL_COUNTER_INC(&pThis->StatReceiveGSO);
}
else
{
@@ -805,12 +822,12 @@ static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb,
Hdr.Hdr.u8GSOType = VNETHDR_GSO_NONE;
}
- if (vnetMergeableRxBuffers(pState))
+ if (vnetMergeableRxBuffers(pThis))
uHdrLen = sizeof(VNETHDRMRX);
else
uHdrLen = sizeof(VNETHDR);
- vnetPacketDump(pState, (const uint8_t*)pvBuf, cb, "<-- Incoming");
+ vnetPacketDump(pThis, (const uint8_t*)pvBuf, cb, "<-- Incoming");
unsigned int uOffset = 0;
unsigned int nElem;
@@ -819,25 +836,25 @@ static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb,
VQUEUEELEM elem;
unsigned int nSeg = 0, uElemSize = 0, cbReserved = 0;
- if (!vqueueGet(&pState->VPCI, pState->pRxQueue, &elem))
+ if (!vqueueGet(&pThis->VPCI, pThis->pRxQueue, &elem))
{
/*
* @todo: It is possible to run out of RX buffers if only a few
* were added and we received a big packet.
*/
- Log(("%s vnetHandleRxPacket: Suddenly there is no space in receive queue!\n", INSTANCE(pState)));
+ Log(("%s vnetHandleRxPacket: Suddenly there is no space in receive queue!\n", INSTANCE(pThis)));
return VERR_INTERNAL_ERROR;
}
if (elem.nIn < 1)
{
- Log(("%s vnetHandleRxPacket: No writable descriptors in receive queue!\n", INSTANCE(pState)));
+ Log(("%s vnetHandleRxPacket: No writable descriptors in receive queue!\n", INSTANCE(pThis)));
return VERR_INTERNAL_ERROR;
}
if (nElem == 0)
{
- if (vnetMergeableRxBuffers(pState))
+ if (vnetMergeableRxBuffers(pThis))
{
addrHdrMrx = elem.aSegsIn[nSeg].addr;
cbReserved = uHdrLen;
@@ -847,7 +864,7 @@ static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb,
/* The very first segment of the very first element gets the header. */
if (elem.aSegsIn[nSeg].cb != sizeof(VNETHDR))
{
- Log(("%s vnetHandleRxPacket: The first descriptor does match the header size!\n", INSTANCE(pState)));
+ Log(("%s vnetHandleRxPacket: The first descriptor does match the header size!\n", INSTANCE(pThis)));
return VERR_INTERNAL_ERROR;
}
elem.aSegsIn[nSeg++].pv = &Hdr;
@@ -862,30 +879,30 @@ static int vnetHandleRxPacket(PVNETSTATE pState, const void *pvBuf, size_t cb,
uOffset += uSize;
uElemSize += uSize;
}
- STAM_PROFILE_START(&pState->StatReceiveStore, a);
- vqueuePut(&pState->VPCI, pState->pRxQueue, &elem, uElemSize, cbReserved);
- STAM_PROFILE_STOP(&pState->StatReceiveStore, a);
- if (!vnetMergeableRxBuffers(pState))
+ STAM_PROFILE_START(&pThis->StatReceiveStore, a);
+ vqueuePut(&pThis->VPCI, pThis->pRxQueue, &elem, uElemSize, cbReserved);
+ STAM_PROFILE_STOP(&pThis->StatReceiveStore, a);
+ if (!vnetMergeableRxBuffers(pThis))
break;
cbReserved = 0;
}
- if (vnetMergeableRxBuffers(pState))
+ if (vnetMergeableRxBuffers(pThis))
{
Hdr.u16NumBufs = nElem;
- int rc = PDMDevHlpPhysWrite(pState->VPCI.CTX_SUFF(pDevIns), addrHdrMrx,
- &Hdr, sizeof(Hdr));
+ int rc = PDMDevHlpPCIPhysWrite(pThis->VPCI.CTX_SUFF(pDevIns), addrHdrMrx,
+ &Hdr, sizeof(Hdr));
if (RT_FAILURE(rc))
{
Log(("%s vnetHandleRxPacket: Failed to write merged RX buf header: %Rrc\n",
- INSTANCE(pState), rc));
+ INSTANCE(pThis), rc));
return rc;
}
}
- vqueueSync(&pState->VPCI, pState->pRxQueue);
+ vqueueSync(&pThis->VPCI, pThis->pRxQueue);
if (uOffset < cb)
{
Log(("%s vnetHandleRxPacket: Packet did not fit into RX queue (packet size=%u)!\n",
- INSTANCE(pState), cb));
+ INSTANCE(pThis), cb));
return VERR_TOO_MUCH_DATA;
}
@@ -899,11 +916,11 @@ static DECLCALLBACK(int) vnetNetworkDown_ReceiveGso(PPDMINETWORKDOWN pInterface,
const void *pvBuf, size_t cb,
PCPDMNETWORKGSO pGso)
{
- VNETSTATE *pState = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown);
+ PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown);
if (pGso)
{
- uint32_t uFeatures = pState->VPCI.uGuestFeatures;
+ uint32_t uFeatures = pThis->VPCI.uGuestFeatures;
switch (pGso->u8Type)
{
@@ -924,38 +941,38 @@ static DECLCALLBACK(int) vnetNetworkDown_ReceiveGso(PPDMINETWORKDOWN pInterface,
if (!uFeatures)
{
Log2(("%s vnetNetworkDown_ReceiveGso: GSO type (0x%x) not supported\n",
- INSTANCE(pState), pGso->u8Type));
+ INSTANCE(pThis), pGso->u8Type));
return VERR_NOT_SUPPORTED;
}
}
Log2(("%s vnetNetworkDown_ReceiveGso: pvBuf=%p cb=%u pGso=%p\n",
- INSTANCE(pState), pvBuf, cb, pGso));
- int rc = vnetCanReceive(pState);
+ INSTANCE(pThis), pvBuf, cb, pGso));
+ int rc = vnetCanReceive(pThis);
if (RT_FAILURE(rc))
return rc;
/* Drop packets if VM is not running or cable is disconnected. */
- VMSTATE enmVMState = PDMDevHlpVMState(pState->VPCI.CTX_SUFF(pDevIns));
+ VMSTATE enmVMState = PDMDevHlpVMState(pThis->VPCI.CTX_SUFF(pDevIns));
if (( enmVMState != VMSTATE_RUNNING
&& enmVMState != VMSTATE_RUNNING_LS)
|| !(STATUS & VNET_S_LINK_UP))
return VINF_SUCCESS;
- STAM_PROFILE_START(&pState->StatReceive, a);
- vpciSetReadLed(&pState->VPCI, true);
- if (vnetAddressFilter(pState, pvBuf, cb))
+ STAM_PROFILE_START(&pThis->StatReceive, a);
+ vpciSetReadLed(&pThis->VPCI, true);
+ if (vnetAddressFilter(pThis, pvBuf, cb))
{
- rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
+ rc = vnetCsRxEnter(pThis, VERR_SEM_BUSY);
if (RT_SUCCESS(rc))
{
- rc = vnetHandleRxPacket(pState, pvBuf, cb, pGso);
- STAM_REL_COUNTER_ADD(&pState->StatReceiveBytes, cb);
- vnetCsRxLeave(pState);
+ rc = vnetHandleRxPacket(pThis, pvBuf, cb, pGso);
+ STAM_REL_COUNTER_ADD(&pThis->StatReceiveBytes, cb);
+ vnetCsRxLeave(pThis);
}
}
- vpciSetReadLed(&pState->VPCI, false);
- STAM_PROFILE_STOP(&pState->StatReceive, a);
+ vpciSetReadLed(&pThis->VPCI, false);
+ STAM_PROFILE_STOP(&pThis->StatReceive, a);
return rc;
}
@@ -977,8 +994,8 @@ static DECLCALLBACK(int) vnetNetworkDown_Receive(PPDMINETWORKDOWN pInterface, co
*/
static DECLCALLBACK(int) vnetGetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
{
- VNETSTATE *pState = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig);
- memcpy(pMac, pState->config.mac.au8, sizeof(RTMAC));
+ PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig);
+ memcpy(pMac, pThis->config.mac.au8, sizeof(RTMAC));
return VINF_SUCCESS;
}
@@ -991,7 +1008,7 @@ static DECLCALLBACK(int) vnetGetMac(PPDMINETWORKCONFIG pInterface, PRTMAC pMac)
*/
static DECLCALLBACK(PDMNETWORKLINKSTATE) vnetGetLinkState(PPDMINETWORKCONFIG pInterface)
{
- VNETSTATE *pState = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig);
+ PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig);
if (STATUS & VNET_S_LINK_UP)
return PDMNETWORKLINKSTATE_UP;
return PDMNETWORKLINKSTATE_DOWN;
@@ -1007,35 +1024,51 @@ static DECLCALLBACK(PDMNETWORKLINKSTATE) vnetGetLinkState(PPDMINETWORKCONFIG pIn
*/
static DECLCALLBACK(int) vnetSetLinkState(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState)
{
- VNETSTATE *pState = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig);
+ PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkConfig);
bool fOldUp = !!(STATUS & VNET_S_LINK_UP);
bool fNewUp = enmState == PDMNETWORKLINKSTATE_UP;
- if (fNewUp != fOldUp)
+ Log(("%s vnetSetLinkState: enmState=%d\n", INSTANCE(pThis), enmState));
+ if (enmState == PDMNETWORKLINKSTATE_DOWN_RESUME)
+ {
+ if (fOldUp)
+ {
+ /*
+ * We bother to bring the link down only if it was up previously. The UP link state
+ * notification will be sent when the link actually goes up in vnetLinkUpTimer().
+ */
+ vnetTempLinkDown(pThis);
+ if (pThis->pDrv)
+ pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, enmState);
+ }
+ }
+ else if (fNewUp != fOldUp)
{
if (fNewUp)
{
- Log(("%s Link is up\n", INSTANCE(pState)));
+ Log(("%s Link is up\n", INSTANCE(pThis)));
STATUS |= VNET_S_LINK_UP;
- vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
+ vpciRaiseInterrupt(&pThis->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
}
else
{
- Log(("%s Link is down\n", INSTANCE(pState)));
+ /* The link was brought down explicitly, make sure it won't come up by timer. */
+ TMTimerStop(pThis->pLinkUpTimer);
+ Log(("%s Link is down\n", INSTANCE(pThis)));
STATUS &= ~VNET_S_LINK_UP;
- vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
+ vpciRaiseInterrupt(&pThis->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
}
- if (pState->pDrv)
- pState->pDrv->pfnNotifyLinkChanged(pState->pDrv, enmState);
+ if (pThis->pDrv)
+ pThis->pDrv->pfnNotifyLinkChanged(pThis->pDrv, enmState);
}
return VINF_SUCCESS;
}
static DECLCALLBACK(void) vnetQueueReceive(void *pvState, PVQUEUE pQueue)
{
- VNETSTATE *pState = (VNETSTATE*)pvState;
- Log(("%s Receive buffers has been added, waking up receive thread.\n", INSTANCE(pState)));
- vnetWakeupReceive(pState->VPCI.CTX_SUFF(pDevIns));
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
+ Log(("%s Receive buffers has been added, waking up receive thread.\n", INSTANCE(pThis)));
+ vnetWakeupReceive(pThis->VPCI.CTX_SUFF(pDevIns));
}
/**
@@ -1105,97 +1138,99 @@ DECLINLINE(void) vnetCompleteChecksum(uint8_t *pBuf, unsigned cbSize, uint16_t u
*(uint16_t*)(pBuf + uStart + uOffset) = vnetCSum16(pBuf + uStart, cbSize - uStart);
}
-static void vnetTransmitPendingPackets(PVNETSTATE pState, PVQUEUE pQueue, bool fOnWorkerThread)
+static void vnetTransmitPendingPackets(PVNETSTATE pThis, PVQUEUE pQueue, bool fOnWorkerThread)
{
/*
* Only one thread is allowed to transmit at a time, others should skip
* transmission as the packets will be picked up by the transmitting
* thread.
*/
- if (!ASMAtomicCmpXchgU32(&pState->uIsTransmitting, 1, 0))
+ if (!ASMAtomicCmpXchgU32(&pThis->uIsTransmitting, 1, 0))
return;
- if ((pState->VPCI.uStatus & VPCI_STATUS_DRV_OK) == 0)
+ if ((pThis->VPCI.uStatus & VPCI_STATUS_DRV_OK) == 0)
{
Log(("%s Ignoring transmit requests from non-existent driver (status=0x%x).\n",
- INSTANCE(pState), pState->VPCI.uStatus));
+ INSTANCE(pThis), pThis->VPCI.uStatus));
return;
}
- PPDMINETWORKUP pDrv = pState->pDrv;
+ PPDMINETWORKUP pDrv = pThis->pDrv;
if (pDrv)
{
int rc = pDrv->pfnBeginXmit(pDrv, fOnWorkerThread);
Assert(rc == VINF_SUCCESS || rc == VERR_TRY_AGAIN);
if (rc == VERR_TRY_AGAIN)
{
- ASMAtomicWriteU32(&pState->uIsTransmitting, 0);
+ ASMAtomicWriteU32(&pThis->uIsTransmitting, 0);
return;
}
}
unsigned int uHdrLen;
- if (vnetMergeableRxBuffers(pState))
+ if (vnetMergeableRxBuffers(pThis))
uHdrLen = sizeof(VNETHDRMRX);
else
uHdrLen = sizeof(VNETHDR);
- Log3(("%s vnetTransmitPendingPackets: About to transmit %d pending packets\n", INSTANCE(pState),
- vringReadAvailIndex(&pState->VPCI, &pState->pTxQueue->VRing) - pState->pTxQueue->uNextAvailIndex));
+ Log3(("%s vnetTransmitPendingPackets: About to transmit %d pending packets\n", INSTANCE(pThis),
+ vringReadAvailIndex(&pThis->VPCI, &pThis->pTxQueue->VRing) - pThis->pTxQueue->uNextAvailIndex));
- vpciSetWriteLed(&pState->VPCI, true);
+ vpciSetWriteLed(&pThis->VPCI, true);
VQUEUEELEM elem;
/*
* Do not remove descriptors from available ring yet, try to allocate the
* buffer first.
*/
- while (vqueuePeek(&pState->VPCI, pQueue, &elem))
+ while (vqueuePeek(&pThis->VPCI, pQueue, &elem))
{
unsigned int uOffset = 0;
if (elem.nOut < 2 || elem.aSegsOut[0].cb != uHdrLen)
{
Log(("%s vnetQueueTransmit: The first segment is not the header! (%u < 2 || %u != %u).\n",
- INSTANCE(pState), elem.nOut, elem.aSegsOut[0].cb, uHdrLen));
+ INSTANCE(pThis), elem.nOut, elem.aSegsOut[0].cb, uHdrLen));
break; /* For now we simply ignore the header, but it must be there anyway! */
}
else
{
unsigned int uSize = 0;
- STAM_PROFILE_ADV_START(&pState->StatTransmit, a);
+ STAM_PROFILE_ADV_START(&pThis->StatTransmit, a);
/* Compute total frame size. */
for (unsigned int i = 1; i < elem.nOut; i++)
uSize += elem.aSegsOut[i].cb;
+ Log5(("%s vnetTransmitPendingPackets: complete frame is %u bytes.\n",
+ INSTANCE(pThis), uSize));
Assert(uSize <= VNET_MAX_FRAME_SIZE);
- if (pState->pDrv)
+ if (pThis->pDrv)
{
VNETHDR Hdr;
PDMNETWORKGSO Gso, *pGso;
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[0].addr,
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[0].addr,
&Hdr, sizeof(Hdr));
- STAM_REL_COUNTER_INC(&pState->StatTransmitPackets);
+ STAM_REL_COUNTER_INC(&pThis->StatTransmitPackets);
- STAM_PROFILE_START(&pState->StatTransmitSend, a);
+ STAM_PROFILE_START(&pThis->StatTransmitSend, a);
pGso = vnetSetupGsoCtx(&Gso, &Hdr);
/** @todo Optimize away the extra copying! (lazy bird) */
PPDMSCATTERGATHER pSgBuf;
- int rc = pState->pDrv->pfnAllocBuf(pState->pDrv, uSize, pGso, &pSgBuf);
+ int rc = pThis->pDrv->pfnAllocBuf(pThis->pDrv, uSize, pGso, &pSgBuf);
if (RT_SUCCESS(rc))
{
Assert(pSgBuf->cSegs == 1);
/* Assemble a complete frame. */
for (unsigned int i = 1; i < elem.nOut; i++)
{
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[i].addr,
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns), elem.aSegsOut[i].addr,
((uint8_t*)pSgBuf->aSegs[0].pvSeg) + uOffset,
elem.aSegsOut[i].cb);
uOffset += elem.aSegsOut[i].cb;
}
pSgBuf->cbUsed = uSize;
- vnetPacketDump(pState, (uint8_t*)pSgBuf->aSegs[0].pvSeg, uSize, "--> Outgoing");
+ vnetPacketDump(pThis, (uint8_t*)pSgBuf->aSegs[0].pvSeg, uSize, "--> Outgoing");
if (pGso)
{
/* Some guests (RHEL) may report HdrLen excluding transport layer header! */
@@ -1206,7 +1241,7 @@ static void vnetTransmitPendingPackets(PVNETSTATE pState, PVQUEUE pQueue, bool f
//if (pGso->cbHdrs < Hdr.u16CSumStart + Hdr.u16CSumOffset + 2)
{
Log4(("%s vnetTransmitPendingPackets: HdrLen before adjustment %d.\n",
- INSTANCE(pState), pGso->cbHdrsTotal));
+ INSTANCE(pThis), pGso->cbHdrsTotal));
switch (pGso->u8Type)
{
case PDMNETWORKGSOTYPE_IPV4_TCP:
@@ -1216,24 +1251,24 @@ static void vnetTransmitPendingPackets(PVNETSTATE pState, PVQUEUE pQueue, bool f
pGso->cbHdrsSeg = pGso->cbHdrsTotal;
break;
case PDMNETWORKGSOTYPE_IPV4_UDP:
- pGso->cbHdrsTotal = Hdr.u16CSumStart + sizeof(RTNETUDP);
+ pGso->cbHdrsTotal = (uint8_t)(Hdr.u16CSumStart + sizeof(RTNETUDP));
pGso->cbHdrsSeg = Hdr.u16CSumStart;
break;
}
/* Update GSO structure embedded into the frame */
((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsTotal = pGso->cbHdrsTotal;
- ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsSeg = pGso->cbHdrsTotal;
+ ((PPDMNETWORKGSO)pSgBuf->pvUser)->cbHdrsSeg = pGso->cbHdrsSeg;
Log4(("%s vnetTransmitPendingPackets: adjusted HdrLen to %d.\n",
- INSTANCE(pState), pGso->cbHdrsTotal));
+ INSTANCE(pThis), pGso->cbHdrsTotal));
}
Log2(("%s vnetTransmitPendingPackets: gso type=%x cbHdrsTotal=%u cbHdrsSeg=%u mss=%u"
- " off1=0x%x off2=0x%x\n", INSTANCE(pState), pGso->u8Type,
+ " off1=0x%x off2=0x%x\n", INSTANCE(pThis), pGso->u8Type,
pGso->cbHdrsTotal, pGso->cbHdrsSeg, pGso->cbMaxSeg, pGso->offHdr1, pGso->offHdr2));
- STAM_REL_COUNTER_INC(&pState->StatTransmitGSO);
+ STAM_REL_COUNTER_INC(&pThis->StatTransmitGSO);
}
else if (Hdr.u8Flags & VNETHDR_F_NEEDS_CSUM)
{
- STAM_REL_COUNTER_INC(&pState->StatTransmitCSum);
+ STAM_REL_COUNTER_INC(&pThis->StatTransmitCSum);
/*
* This is not GSO frame but checksum offloading is requested.
*/
@@ -1241,32 +1276,32 @@ static void vnetTransmitPendingPackets(PVNETSTATE pState, PVQUEUE pQueue, bool f
Hdr.u16CSumStart, Hdr.u16CSumOffset);
}
- rc = pState->pDrv->pfnSendBuf(pState->pDrv, pSgBuf, false);
+ rc = pThis->pDrv->pfnSendBuf(pThis->pDrv, pSgBuf, false);
}
else
{
Log4(("virtio-net: failed to allocate SG buffer: size=%u rc=%Rrc\n", uSize, rc));
- STAM_PROFILE_STOP(&pState->StatTransmitSend, a);
- STAM_PROFILE_ADV_STOP(&pState->StatTransmit, a);
+ STAM_PROFILE_STOP(&pThis->StatTransmitSend, a);
+ STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a);
/* Stop trying to fetch TX descriptors until we get more bandwidth. */
break;
}
- STAM_PROFILE_STOP(&pState->StatTransmitSend, a);
- STAM_REL_COUNTER_ADD(&pState->StatTransmitBytes, uOffset);
+ STAM_PROFILE_STOP(&pThis->StatTransmitSend, a);
+ STAM_REL_COUNTER_ADD(&pThis->StatTransmitBytes, uOffset);
}
}
/* Remove this descriptor chain from the available ring */
- vqueueSkip(&pState->VPCI, pQueue);
- vqueuePut(&pState->VPCI, pQueue, &elem, sizeof(VNETHDR) + uOffset);
- vqueueSync(&pState->VPCI, pQueue);
- STAM_PROFILE_ADV_STOP(&pState->StatTransmit, a);
+ vqueueSkip(&pThis->VPCI, pQueue);
+ vqueuePut(&pThis->VPCI, pQueue, &elem, sizeof(VNETHDR) + uOffset);
+ vqueueSync(&pThis->VPCI, pQueue);
+ STAM_PROFILE_ADV_STOP(&pThis->StatTransmit, a);
}
- vpciSetWriteLed(&pState->VPCI, false);
+ vpciSetWriteLed(&pThis->VPCI, false);
if (pDrv)
pDrv->pfnEndXmit(pDrv);
- ASMAtomicWriteU32(&pState->uIsTransmitting, 0);
+ ASMAtomicWriteU32(&pThis->uIsTransmitting, 0);
}
/**
@@ -1274,7 +1309,7 @@ static void vnetTransmitPendingPackets(PVNETSTATE pState, PVQUEUE pQueue, bool f
*/
static DECLCALLBACK(void) vnetNetworkDown_XmitPending(PPDMINETWORKDOWN pInterface)
{
- VNETSTATE *pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown);
+ PVNETSTATE pThis = RT_FROM_MEMBER(pInterface, VNETSTATE, INetworkDown);
vnetTransmitPendingPackets(pThis, pThis->pTxQueue, false /*fOnWorkerThread*/);
}
@@ -1282,109 +1317,102 @@ static DECLCALLBACK(void) vnetNetworkDown_XmitPending(PPDMINETWORKDOWN pInterfac
static DECLCALLBACK(void) vnetQueueTransmit(void *pvState, PVQUEUE pQueue)
{
- VNETSTATE *pState = (VNETSTATE*)pvState;
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
- if (TMTimerIsActive(pState->CTX_SUFF(pTxTimer)))
+ if (TMTimerIsActive(pThis->CTX_SUFF(pTxTimer)))
{
- int rc = TMTimerStop(pState->CTX_SUFF(pTxTimer));
+ int rc = TMTimerStop(pThis->CTX_SUFF(pTxTimer));
Log3(("%s vnetQueueTransmit: Got kicked with notification disabled, "
- "re-enable notification and flush TX queue\n", INSTANCE(pState)));
- vnetTransmitPendingPackets(pState, pQueue, false /*fOnWorkerThread*/);
- if (RT_FAILURE(vnetCsEnter(pState, VERR_SEM_BUSY)))
+ "re-enable notification and flush TX queue\n", INSTANCE(pThis)));
+ vnetTransmitPendingPackets(pThis, pQueue, false /*fOnWorkerThread*/);
+ if (RT_FAILURE(vnetCsEnter(pThis, VERR_SEM_BUSY)))
LogRel(("vnetQueueTransmit: Failed to enter critical section!/n"));
else
{
- vringSetNotification(&pState->VPCI, &pState->pTxQueue->VRing, true);
- vnetCsLeave(pState);
+ vringSetNotification(&pThis->VPCI, &pThis->pTxQueue->VRing, true);
+ vnetCsLeave(pThis);
}
}
else
{
- if (RT_FAILURE(vnetCsEnter(pState, VERR_SEM_BUSY)))
+ if (RT_FAILURE(vnetCsEnter(pThis, VERR_SEM_BUSY)))
LogRel(("vnetQueueTransmit: Failed to enter critical section!/n"));
else
{
- vringSetNotification(&pState->VPCI, &pState->pTxQueue->VRing, false);
- TMTimerSetMicro(pState->CTX_SUFF(pTxTimer), VNET_TX_DELAY);
- pState->u64NanoTS = RTTimeNanoTS();
- vnetCsLeave(pState);
+ vringSetNotification(&pThis->VPCI, &pThis->pTxQueue->VRing, false);
+ TMTimerSetMicro(pThis->CTX_SUFF(pTxTimer), VNET_TX_DELAY);
+ pThis->u64NanoTS = RTTimeNanoTS();
+ vnetCsLeave(pThis);
}
}
}
/**
- * Transmit Delay Timer handler.
- *
- * @remarks We only get here when the timer expires.
- *
- * @param pDevIns Pointer to device instance structure.
- * @param pTimer Pointer to the timer.
- * @param pvUser NULL.
- * @thread EMT
+ * @callback_method_impl{FNTMTIMERDEV, Transmit Delay Timer handler.}
*/
static DECLCALLBACK(void) vnetTxTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
{
- VNETSTATE *pState = (VNETSTATE*)pvUser;
+ PVNETSTATE pThis = (PVNETSTATE)pvUser;
- uint32_t u32MicroDiff = (uint32_t)((RTTimeNanoTS() - pState->u64NanoTS)/1000);
- if (u32MicroDiff < pState->u32MinDiff)
- pState->u32MinDiff = u32MicroDiff;
- if (u32MicroDiff > pState->u32MaxDiff)
- pState->u32MaxDiff = u32MicroDiff;
- pState->u32AvgDiff = (pState->u32AvgDiff * pState->u32i + u32MicroDiff) / (pState->u32i + 1);
- pState->u32i++;
+ uint32_t u32MicroDiff = (uint32_t)((RTTimeNanoTS() - pThis->u64NanoTS)/1000);
+ if (u32MicroDiff < pThis->u32MinDiff)
+ pThis->u32MinDiff = u32MicroDiff;
+ if (u32MicroDiff > pThis->u32MaxDiff)
+ pThis->u32MaxDiff = u32MicroDiff;
+ pThis->u32AvgDiff = (pThis->u32AvgDiff * pThis->u32i + u32MicroDiff) / (pThis->u32i + 1);
+ pThis->u32i++;
Log3(("vnetTxTimer: Expired, diff %9d usec, avg %9d usec, min %9d usec, max %9d usec\n",
- u32MicroDiff, pState->u32AvgDiff, pState->u32MinDiff, pState->u32MaxDiff));
+ u32MicroDiff, pThis->u32AvgDiff, pThis->u32MinDiff, pThis->u32MaxDiff));
-// Log3(("%s vnetTxTimer: Expired\n", INSTANCE(pState)));
- vnetTransmitPendingPackets(pState, pState->pTxQueue, false /*fOnWorkerThread*/);
- if (RT_FAILURE(vnetCsEnter(pState, VERR_SEM_BUSY)))
+// Log3(("%s vnetTxTimer: Expired\n", INSTANCE(pThis)));
+ vnetTransmitPendingPackets(pThis, pThis->pTxQueue, false /*fOnWorkerThread*/);
+ if (RT_FAILURE(vnetCsEnter(pThis, VERR_SEM_BUSY)))
{
LogRel(("vnetTxTimer: Failed to enter critical section!/n"));
return;
}
- vringSetNotification(&pState->VPCI, &pState->pTxQueue->VRing, true);
- vnetCsLeave(pState);
+ vringSetNotification(&pThis->VPCI, &pThis->pTxQueue->VRing, true);
+ vnetCsLeave(pThis);
}
#else /* !VNET_TX_DELAY */
static DECLCALLBACK(void) vnetQueueTransmit(void *pvState, PVQUEUE pQueue)
{
- VNETSTATE *pState = (VNETSTATE*)pvState;
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
- vnetTransmitPendingPackets(pState, pQueue, false /*fOnWorkerThread*/);
+ vnetTransmitPendingPackets(pThis, pQueue, false /*fOnWorkerThread*/);
}
#endif /* !VNET_TX_DELAY */
-static uint8_t vnetControlRx(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
+static uint8_t vnetControlRx(PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
{
uint8_t u8Ack = VNET_OK;
- uint8_t fOn, fDrvWasPromisc = pState->fPromiscuous | pState->fAllMulti;
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns),
+ uint8_t fOn, fDrvWasPromisc = pThis->fPromiscuous | pThis->fAllMulti;
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
pElem->aSegsOut[1].addr,
&fOn, sizeof(fOn));
- Log(("%s vnetControlRx: uCommand=%u fOn=%u\n", INSTANCE(pState), pCtlHdr->u8Command, fOn));
+ Log(("%s vnetControlRx: uCommand=%u fOn=%u\n", INSTANCE(pThis), pCtlHdr->u8Command, fOn));
switch (pCtlHdr->u8Command)
{
case VNET_CTRL_CMD_RX_MODE_PROMISC:
- pState->fPromiscuous = !!fOn;
+ pThis->fPromiscuous = !!fOn;
break;
case VNET_CTRL_CMD_RX_MODE_ALLMULTI:
- pState->fAllMulti = !!fOn;
+ pThis->fAllMulti = !!fOn;
break;
default:
u8Ack = VNET_ERROR;
}
- if (fDrvWasPromisc != (pState->fPromiscuous | pState->fAllMulti) && pState->pDrv)
- pState->pDrv->pfnSetPromiscuousMode(pState->pDrv,
- (pState->fPromiscuous | pState->fAllMulti));
+ if (fDrvWasPromisc != (pThis->fPromiscuous | pThis->fAllMulti) && pThis->pDrv)
+ pThis->pDrv->pfnSetPromiscuousMode(pThis->pDrv,
+ (pThis->fPromiscuous | pThis->fAllMulti));
return u8Ack;
}
-static uint8_t vnetControlMac(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
+static uint8_t vnetControlMac(PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
{
uint32_t nMacs = 0;
@@ -1394,82 +1422,82 @@ static uint8_t vnetControlMac(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEELE
|| pElem->aSegsOut[2].cb < sizeof(nMacs))
{
Log(("%s vnetControlMac: Segment layout is wrong "
- "(u8Command=%u nOut=%u cb1=%u cb2=%u)\n", INSTANCE(pState),
+ "(u8Command=%u nOut=%u cb1=%u cb2=%u)\n", INSTANCE(pThis),
pCtlHdr->u8Command, pElem->nOut,
pElem->aSegsOut[1].cb, pElem->aSegsOut[2].cb));
return VNET_ERROR;
}
/* Load unicast addresses */
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns),
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
pElem->aSegsOut[1].addr,
&nMacs, sizeof(nMacs));
if (pElem->aSegsOut[1].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs))
{
Log(("%s vnetControlMac: The unicast mac segment is too small "
- "(nMacs=%u cb=%u)\n", INSTANCE(pState), pElem->aSegsOut[1].cb));
+ "(nMacs=%u cb=%u)\n", INSTANCE(pThis), pElem->aSegsOut[1].cb));
return VNET_ERROR;
}
if (nMacs > VNET_MAC_FILTER_LEN)
{
Log(("%s vnetControlMac: MAC table is too big, have to use promiscuous"
- " mode (nMacs=%u)\n", INSTANCE(pState), nMacs));
- pState->fPromiscuous = true;
+ " mode (nMacs=%u)\n", INSTANCE(pThis), nMacs));
+ pThis->fPromiscuous = true;
}
else
{
if (nMacs)
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns),
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
pElem->aSegsOut[1].addr + sizeof(nMacs),
- pState->aMacFilter, nMacs * sizeof(RTMAC));
- pState->nMacFilterEntries = nMacs;
+ pThis->aMacFilter, nMacs * sizeof(RTMAC));
+ pThis->nMacFilterEntries = nMacs;
#ifdef DEBUG
- Log(("%s vnetControlMac: unicast macs:\n", INSTANCE(pState)));
+ Log(("%s vnetControlMac: unicast macs:\n", INSTANCE(pThis)));
for(unsigned i = 0; i < nMacs; i++)
- Log((" %RTmac\n", &pState->aMacFilter[i]));
+ Log((" %RTmac\n", &pThis->aMacFilter[i]));
#endif /* DEBUG */
}
/* Load multicast addresses */
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns),
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
pElem->aSegsOut[2].addr,
&nMacs, sizeof(nMacs));
if (pElem->aSegsOut[2].cb < nMacs * sizeof(RTMAC) + sizeof(nMacs))
{
Log(("%s vnetControlMac: The multicast mac segment is too small "
- "(nMacs=%u cb=%u)\n", INSTANCE(pState), pElem->aSegsOut[2].cb));
+ "(nMacs=%u cb=%u)\n", INSTANCE(pThis), pElem->aSegsOut[2].cb));
return VNET_ERROR;
}
- if (nMacs > VNET_MAC_FILTER_LEN - pState->nMacFilterEntries)
+ if (nMacs > VNET_MAC_FILTER_LEN - pThis->nMacFilterEntries)
{
Log(("%s vnetControlMac: MAC table is too big, have to use allmulti"
- " mode (nMacs=%u)\n", INSTANCE(pState), nMacs));
- pState->fAllMulti = true;
+ " mode (nMacs=%u)\n", INSTANCE(pThis), nMacs));
+ pThis->fAllMulti = true;
}
else
{
if (nMacs)
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns),
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
pElem->aSegsOut[2].addr + sizeof(nMacs),
- &pState->aMacFilter[pState->nMacFilterEntries],
+ &pThis->aMacFilter[pThis->nMacFilterEntries],
nMacs * sizeof(RTMAC));
#ifdef DEBUG
- Log(("%s vnetControlMac: multicast macs:\n", INSTANCE(pState)));
+ Log(("%s vnetControlMac: multicast macs:\n", INSTANCE(pThis)));
for(unsigned i = 0; i < nMacs; i++)
Log((" %RTmac\n",
- &pState->aMacFilter[i+pState->nMacFilterEntries]));
+ &pThis->aMacFilter[i+pThis->nMacFilterEntries]));
#endif /* DEBUG */
- pState->nMacFilterEntries += nMacs;
+ pThis->nMacFilterEntries += nMacs;
}
return VNET_OK;
}
-static uint8_t vnetControlVlan(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
+static uint8_t vnetControlVlan(PVNETSTATE pThis, PVNETCTLHDR pCtlHdr, PVQUEUEELEM pElem)
{
uint8_t u8Ack = VNET_OK;
uint16_t u16Vid;
@@ -1477,32 +1505,32 @@ static uint8_t vnetControlVlan(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEEL
if (pElem->nOut != 2 || pElem->aSegsOut[1].cb != sizeof(u16Vid))
{
Log(("%s vnetControlVlan: Segment layout is wrong "
- "(u8Command=%u nOut=%u cb=%u)\n", INSTANCE(pState),
+ "(u8Command=%u nOut=%u cb=%u)\n", INSTANCE(pThis),
pCtlHdr->u8Command, pElem->nOut, pElem->aSegsOut[1].cb));
return VNET_ERROR;
}
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns),
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
pElem->aSegsOut[1].addr,
&u16Vid, sizeof(u16Vid));
if (u16Vid >= VNET_MAX_VID)
{
Log(("%s vnetControlVlan: VLAN ID is out of range "
- "(VID=%u)\n", INSTANCE(pState), u16Vid));
+ "(VID=%u)\n", INSTANCE(pThis), u16Vid));
return VNET_ERROR;
}
- Log(("%s vnetControlVlan: uCommand=%u VID=%u\n", INSTANCE(pState),
+ Log(("%s vnetControlVlan: uCommand=%u VID=%u\n", INSTANCE(pThis),
pCtlHdr->u8Command, u16Vid));
switch (pCtlHdr->u8Command)
{
case VNET_CTRL_CMD_VLAN_ADD:
- ASMBitSet(pState->aVlanFilter, u16Vid);
+ ASMBitSet(pThis->aVlanFilter, u16Vid);
break;
case VNET_CTRL_CMD_VLAN_DEL:
- ASMBitClear(pState->aVlanFilter, u16Vid);
+ ASMBitClear(pThis->aVlanFilter, u16Vid);
break;
default:
u8Ack = VNET_ERROR;
@@ -1514,16 +1542,16 @@ static uint8_t vnetControlVlan(PVNETSTATE pState, PVNETCTLHDR pCtlHdr, PVQUEUEEL
static DECLCALLBACK(void) vnetQueueControl(void *pvState, PVQUEUE pQueue)
{
- VNETSTATE *pState = (VNETSTATE*)pvState;
+ PVNETSTATE pThis = (PVNETSTATE)pvState;
uint8_t u8Ack;
VQUEUEELEM elem;
- while (vqueueGet(&pState->VPCI, pQueue, &elem))
+ while (vqueueGet(&pThis->VPCI, pQueue, &elem))
{
unsigned int uOffset = 0;
if (elem.nOut < 1 || elem.aSegsOut[0].cb < sizeof(VNETCTLHDR))
{
Log(("%s vnetQueueControl: The first 'out' segment is not the "
- "header! (%u < 1 || %u < %u).\n", INSTANCE(pState), elem.nOut,
+ "header! (%u < 1 || %u < %u).\n", INSTANCE(pThis), elem.nOut,
elem.aSegsOut[0].cb,sizeof(VNETCTLHDR)));
break; /* Skip the element and hope the next one is good. */
}
@@ -1532,272 +1560,224 @@ static DECLCALLBACK(void) vnetQueueControl(void *pvState, PVQUEUE pQueue)
{
Log(("%s vnetQueueControl: The last 'in' segment is too small "
"to hold the acknowledge! (%u < 1 || %u < %u).\n",
- INSTANCE(pState), elem.nIn, elem.aSegsIn[elem.nIn - 1].cb,
+ INSTANCE(pThis), elem.nIn, elem.aSegsIn[elem.nIn - 1].cb,
sizeof(VNETCTLACK)));
break; /* Skip the element and hope the next one is good. */
}
else
{
VNETCTLHDR CtlHdr;
- PDMDevHlpPhysRead(pState->VPCI.CTX_SUFF(pDevIns),
+ PDMDevHlpPhysRead(pThis->VPCI.CTX_SUFF(pDevIns),
elem.aSegsOut[0].addr,
&CtlHdr, sizeof(CtlHdr));
switch (CtlHdr.u8Class)
{
case VNET_CTRL_CLS_RX_MODE:
- u8Ack = vnetControlRx(pState, &CtlHdr, &elem);
+ u8Ack = vnetControlRx(pThis, &CtlHdr, &elem);
break;
case VNET_CTRL_CLS_MAC:
- u8Ack = vnetControlMac(pState, &CtlHdr, &elem);
+ u8Ack = vnetControlMac(pThis, &CtlHdr, &elem);
break;
case VNET_CTRL_CLS_VLAN:
- u8Ack = vnetControlVlan(pState, &CtlHdr, &elem);
+ u8Ack = vnetControlVlan(pThis, &CtlHdr, &elem);
break;
default:
u8Ack = VNET_ERROR;
}
- Log(("%s Processed control message %u, ack=%u.\n", INSTANCE(pState),
+ Log(("%s Processed control message %u, ack=%u.\n", INSTANCE(pThis),
CtlHdr.u8Class, u8Ack));
- PDMDevHlpPhysWrite(pState->VPCI.CTX_SUFF(pDevIns),
- elem.aSegsIn[elem.nIn - 1].addr,
- &u8Ack, sizeof(u8Ack));
+ PDMDevHlpPCIPhysWrite(pThis->VPCI.CTX_SUFF(pDevIns),
+ elem.aSegsIn[elem.nIn - 1].addr,
+ &u8Ack, sizeof(u8Ack));
}
- vqueuePut(&pState->VPCI, pQueue, &elem, sizeof(u8Ack));
- vqueueSync(&pState->VPCI, pQueue);
+ vqueuePut(&pThis->VPCI, pQueue, &elem, sizeof(u8Ack));
+ vqueueSync(&pThis->VPCI, pQueue);
}
}
+
+/* -=-=-=-=- Saved state -=-=-=-=- */
+
/**
* Saves the configuration.
*
- * @param pState The VNET state.
+ * @param pThis The VNET state.
* @param pSSM The handle to the saved state.
*/
-static void vnetSaveConfig(VNETSTATE *pState, PSSMHANDLE pSSM)
+static void vnetSaveConfig(PVNETSTATE pThis, PSSMHANDLE pSSM)
{
- SSMR3PutMem(pSSM, &pState->macConfigured, sizeof(pState->macConfigured));
+ SSMR3PutMem(pSSM, &pThis->macConfigured, sizeof(pThis->macConfigured));
}
+
/**
- * Live save - save basic configuration.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The handle to the saved state.
- * @param uPass
+ * @callback_method_impl{FNSSMDEVLIVEEXEC}
*/
static DECLCALLBACK(int) vnetLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
{
- VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
- vnetSaveConfig(pState, pSSM);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
+ vnetSaveConfig(pThis, pSSM);
return VINF_SSM_DONT_CALL_AGAIN;
}
+
/**
- * Prepares for state saving.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The handle to the saved state.
+ * @callback_method_impl{FNSSMDEVSAVEPREP}
*/
static DECLCALLBACK(int) vnetSavePrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
- int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
+ int rc = vnetCsRxEnter(pThis, VERR_SEM_BUSY);
if (RT_UNLIKELY(rc != VINF_SUCCESS))
return rc;
- vnetCsRxLeave(pState);
+ vnetCsRxLeave(pThis);
return VINF_SUCCESS;
}
+
/**
- * Saves the state of device.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The handle to the saved state.
+ * @callback_method_impl{FNSSMDEVSAVEEXEC}
*/
static DECLCALLBACK(int) vnetSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
/* Save config first */
- vnetSaveConfig(pState, pSSM);
+ vnetSaveConfig(pThis, pSSM);
/* Save the common part */
- int rc = vpciSaveExec(&pState->VPCI, pSSM);
+ int rc = vpciSaveExec(&pThis->VPCI, pSSM);
AssertRCReturn(rc, rc);
/* Save device-specific part */
- rc = SSMR3PutMem( pSSM, pState->config.mac.au8, sizeof(pState->config.mac));
+ rc = SSMR3PutMem( pSSM, pThis->config.mac.au8, sizeof(pThis->config.mac));
AssertRCReturn(rc, rc);
- rc = SSMR3PutBool(pSSM, pState->fPromiscuous);
+ rc = SSMR3PutBool(pSSM, pThis->fPromiscuous);
AssertRCReturn(rc, rc);
- rc = SSMR3PutBool(pSSM, pState->fAllMulti);
+ rc = SSMR3PutBool(pSSM, pThis->fAllMulti);
AssertRCReturn(rc, rc);
- rc = SSMR3PutU32( pSSM, pState->nMacFilterEntries);
+ rc = SSMR3PutU32( pSSM, pThis->nMacFilterEntries);
AssertRCReturn(rc, rc);
- rc = SSMR3PutMem( pSSM, pState->aMacFilter,
- pState->nMacFilterEntries * sizeof(RTMAC));
+ rc = SSMR3PutMem( pSSM, pThis->aMacFilter,
+ pThis->nMacFilterEntries * sizeof(RTMAC));
AssertRCReturn(rc, rc);
- rc = SSMR3PutMem( pSSM, pState->aVlanFilter, sizeof(pState->aVlanFilter));
+ rc = SSMR3PutMem( pSSM, pThis->aVlanFilter, sizeof(pThis->aVlanFilter));
AssertRCReturn(rc, rc);
- Log(("%s State has been saved\n", INSTANCE(pState)));
+ Log(("%s State has been saved\n", INSTANCE(pThis)));
return VINF_SUCCESS;
}
/**
- * Serializes the receive thread, it may be working inside the critsect.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The handle to the saved state.
+ * @callback_method_impl{FNSSMDEVLOADPREP, Serializes the receive thread, it may
+ * be working inside the critsect. }
*/
static DECLCALLBACK(int) vnetLoadPrep(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
- int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
+ int rc = vnetCsRxEnter(pThis, VERR_SEM_BUSY);
if (RT_UNLIKELY(rc != VINF_SUCCESS))
return rc;
- vnetCsRxLeave(pState);
+ vnetCsRxLeave(pThis);
return VINF_SUCCESS;
}
-/**
- * Takes down the link temporarily if it's current status is up.
- *
- * This is used during restore and when replumbing the network link.
- *
- * The temporary link outage is supposed to indicate to the OS that all network
- * connections have been lost and that it for instance is appropriate to
- * renegotiate any DHCP lease.
- *
- * @param pThis The PCNet instance data.
- */
-static void vnetTempLinkDown(PVNETSTATE pState)
-{
- if (STATUS & VNET_S_LINK_UP)
- {
- STATUS &= ~VNET_S_LINK_UP;
- vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
- /* Restore the link back in 5 seconds. */
- int rc = TMTimerSetMillies(pState->pLinkUpTimer, pState->cMsLinkUpDelay);
- AssertRC(rc);
- }
-}
-
/**
- * Restore previously saved state of device.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The handle to the saved state.
- * @param uVersion The data unit version number.
- * @param uPass The data pass.
+ * @callback_method_impl{FNSSMDEVLOADEXEC}
*/
static DECLCALLBACK(int) vnetLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
{
- VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
int rc;
/* config checks */
RTMAC macConfigured;
rc = SSMR3GetMem(pSSM, &macConfigured, sizeof(macConfigured));
AssertRCReturn(rc, rc);
- if (memcmp(&macConfigured, &pState->macConfigured, sizeof(macConfigured))
+ if (memcmp(&macConfigured, &pThis->macConfigured, sizeof(macConfigured))
&& (uPass == 0 || !PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns)))
- LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n", INSTANCE(pState), &pState->macConfigured, &macConfigured));
+ LogRel(("%s: The mac address differs: config=%RTmac saved=%RTmac\n", INSTANCE(pThis), &pThis->macConfigured, &macConfigured));
- rc = vpciLoadExec(&pState->VPCI, pSSM, uVersion, uPass, VNET_N_QUEUES);
+ rc = vpciLoadExec(&pThis->VPCI, pSSM, uVersion, uPass, VNET_N_QUEUES);
AssertRCReturn(rc, rc);
if (uPass == SSM_PASS_FINAL)
{
- rc = SSMR3GetMem( pSSM, pState->config.mac.au8,
- sizeof(pState->config.mac));
+ rc = SSMR3GetMem( pSSM, pThis->config.mac.au8,
+ sizeof(pThis->config.mac));
AssertRCReturn(rc, rc);
if (uVersion > VIRTIO_SAVEDSTATE_VERSION_3_1_BETA1)
{
- rc = SSMR3GetBool(pSSM, &pState->fPromiscuous);
+ rc = SSMR3GetBool(pSSM, &pThis->fPromiscuous);
AssertRCReturn(rc, rc);
- rc = SSMR3GetBool(pSSM, &pState->fAllMulti);
+ rc = SSMR3GetBool(pSSM, &pThis->fAllMulti);
AssertRCReturn(rc, rc);
- rc = SSMR3GetU32(pSSM, &pState->nMacFilterEntries);
+ rc = SSMR3GetU32(pSSM, &pThis->nMacFilterEntries);
AssertRCReturn(rc, rc);
- rc = SSMR3GetMem(pSSM, pState->aMacFilter,
- pState->nMacFilterEntries * sizeof(RTMAC));
+ rc = SSMR3GetMem(pSSM, pThis->aMacFilter,
+ pThis->nMacFilterEntries * sizeof(RTMAC));
AssertRCReturn(rc, rc);
/* Clear the rest. */
- if (pState->nMacFilterEntries < VNET_MAC_FILTER_LEN)
- memset(&pState->aMacFilter[pState->nMacFilterEntries],
+ if (pThis->nMacFilterEntries < VNET_MAC_FILTER_LEN)
+ memset(&pThis->aMacFilter[pThis->nMacFilterEntries],
0,
- (VNET_MAC_FILTER_LEN - pState->nMacFilterEntries)
+ (VNET_MAC_FILTER_LEN - pThis->nMacFilterEntries)
* sizeof(RTMAC));
- rc = SSMR3GetMem(pSSM, pState->aVlanFilter,
- sizeof(pState->aVlanFilter));
+ rc = SSMR3GetMem(pSSM, pThis->aVlanFilter,
+ sizeof(pThis->aVlanFilter));
AssertRCReturn(rc, rc);
}
else
{
- pState->fPromiscuous = true;
- pState->fAllMulti = false;
- pState->nMacFilterEntries = 0;
- memset(pState->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC));
- memset(pState->aVlanFilter, 0, sizeof(pState->aVlanFilter));
- if (pState->pDrv)
- pState->pDrv->pfnSetPromiscuousMode(pState->pDrv, true);
+ pThis->fPromiscuous = true;
+ pThis->fAllMulti = false;
+ pThis->nMacFilterEntries = 0;
+ memset(pThis->aMacFilter, 0, VNET_MAC_FILTER_LEN * sizeof(RTMAC));
+ memset(pThis->aVlanFilter, 0, sizeof(pThis->aVlanFilter));
+ if (pThis->pDrv)
+ pThis->pDrv->pfnSetPromiscuousMode(pThis->pDrv, true);
}
}
return rc;
}
+
/**
- * Link status adjustments after loading.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param pSSM The handle to the saved state.
+ * @callback_method_impl{FNSSMDEVLOADDONE, Link status adjustments after
+ * loading.}
*/
static DECLCALLBACK(int) vnetLoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
{
- VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
- if (pState->pDrv)
- pState->pDrv->pfnSetPromiscuousMode(pState->pDrv,
- (pState->fPromiscuous | pState->fAllMulti));
+ if (pThis->pDrv)
+ pThis->pDrv->pfnSetPromiscuousMode(pThis->pDrv,
+ (pThis->fPromiscuous | pThis->fAllMulti));
/*
* Indicate link down to the guest OS that all network connections have
* been lost, unless we've been teleported here.
*/
if (!PDMDevHlpVMTeleportedAndNotFullyResumedYet(pDevIns))
- vnetTempLinkDown(pState);
+ vnetTempLinkDown(pThis);
return VINF_SUCCESS;
}
+
+/* -=-=-=-=- PCI Device -=-=-=-=- */
+
/**
- * Map PCI I/O region.
- *
- * @return VBox status code.
- * @param pPciDev Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
- * @param iRegion The region number.
- * @param GCPhysAddress Physical address of the region. If iType is PCI_ADDRESS_SPACE_IO, this is an
- * I/O port, else it's a physical address.
- * This address is *NOT* relative to pci_mem_base like earlier!
- * @param cb Region size.
- * @param enmType One of the PCI_ADDRESS_SPACE_* values.
- * @thread EMT
+ * @callback_method_impl{FNPCIIOREGIONMAP}
*/
static DECLCALLBACK(int) vnetMap(PPCIDEVICE pPciDev, int iRegion,
RTGCPHYS GCPhysAddress, uint32_t cb, PCIADDRESSSPACE enmType)
{
+ PVNETSTATE pThis = PDMINS_2_DATA(pPciDev->pDevIns, PVNETSTATE);
int rc;
- VNETSTATE *pState = PDMINS_2_DATA(pPciDev->pDevIns, VNETSTATE*);
if (enmType != PCI_ADDRESS_SPACE_IO)
{
@@ -1806,17 +1786,17 @@ static DECLCALLBACK(int) vnetMap(PPCIDEVICE pPciDev, int iRegion,
return VERR_INTERNAL_ERROR;
}
- pState->VPCI.addrIOPort = (RTIOPORT)GCPhysAddress;
- rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns, pState->VPCI.addrIOPort,
+ pThis->VPCI.IOPortBase = (RTIOPORT)GCPhysAddress;
+ rc = PDMDevHlpIOPortRegister(pPciDev->pDevIns, pThis->VPCI.IOPortBase,
cb, 0, vnetIOPortOut, vnetIOPortIn,
NULL, NULL, "VirtioNet");
#ifdef VNET_GC_SUPPORT
AssertRCReturn(rc, rc);
- rc = PDMDevHlpIOPortRegisterR0(pPciDev->pDevIns, pState->VPCI.addrIOPort,
+ rc = PDMDevHlpIOPortRegisterR0(pPciDev->pDevIns, pThis->VPCI.IOPortBase,
cb, 0, "vnetIOPortOut", "vnetIOPortIn",
NULL, NULL, "VirtioNet");
AssertRCReturn(rc, rc);
- rc = PDMDevHlpIOPortRegisterRC(pPciDev->pDevIns, pState->VPCI.addrIOPort,
+ rc = PDMDevHlpIOPortRegisterRC(pPciDev->pDevIns, pThis->VPCI.IOPortBase,
cb, 0, "vnetIOPortOut", "vnetIOPortIn",
NULL, NULL, "VirtioNet");
#endif
@@ -1828,22 +1808,16 @@ static DECLCALLBACK(int) vnetMap(PPCIDEVICE pPciDev, int iRegion,
/* -=-=-=-=- PDMDEVREG -=-=-=-=- */
/**
- * Detach notification.
- *
- * One port on the network card has been disconnected from the network.
- *
- * @param pDevIns The device instance.
- * @param iLUN The logical unit which is being detached.
- * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
+ * @interface_method_impl{PDMDEVREG,pfnDetach}
*/
static DECLCALLBACK(void) vnetDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
{
- VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
- Log(("%s vnetDetach:\n", INSTANCE(pState)));
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
+ Log(("%s vnetDetach:\n", INSTANCE(pThis)));
AssertLogRelReturnVoid(iLUN == 0);
- int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
+ int rc = vnetCsEnter(pThis, VERR_SEM_BUSY);
if (RT_FAILURE(rc))
{
LogRel(("vnetDetach failed to enter critical section!\n"));
@@ -1853,32 +1827,24 @@ static DECLCALLBACK(void) vnetDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t
/*
* Zero some important members.
*/
- pState->pDrvBase = NULL;
- pState->pDrv = NULL;
+ pThis->pDrvBase = NULL;
+ pThis->pDrv = NULL;
- vnetCsLeave(pState);
+ vnetCsLeave(pThis);
}
+
/**
- * Attach the Network attachment.
- *
- * One port on the network card has been connected to a network.
- *
- * @returns VBox status code.
- * @param pDevIns The device instance.
- * @param iLUN The logical unit which is being attached.
- * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
- *
- * @remarks This code path is not used during construction.
+ * @interface_method_impl{PDMDEVREG,pfnAttach}
*/
static DECLCALLBACK(int) vnetAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
{
- VNETSTATE *pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
- LogFlow(("%s vnetAttach:\n", INSTANCE(pState)));
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
+ LogFlow(("%s vnetAttach:\n", INSTANCE(pThis)));
AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN);
- int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
+ int rc = vnetCsEnter(pThis, VERR_SEM_BUSY);
if (RT_FAILURE(rc))
{
LogRel(("vnetAttach failed to enter critical section!\n"));
@@ -1888,7 +1854,7 @@ static DECLCALLBACK(int) vnetAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t
/*
* Attach the driver.
*/
- rc = PDMDevHlpDriverAttach(pDevIns, 0, &pState->VPCI.IBase, &pState->pDrvBase, "Network Port");
+ rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->VPCI.IBase, &pThis->pDrvBase, "Network Port");
if (RT_SUCCESS(rc))
{
if (rc == VINF_NAT_DNS)
@@ -1901,8 +1867,8 @@ static DECLCALLBACK(int) vnetAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t
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"));
#endif
}
- pState->pDrv = PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMINETWORKUP);
- AssertMsgStmt(pState->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),
+ pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP);
+ AssertMsgStmt(pThis->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),
rc = VERR_PDM_MISSING_INTERFACE_BELOW);
}
else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
@@ -1910,7 +1876,7 @@ static DECLCALLBACK(int) vnetAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t
{
/* This should never happen because this function is not called
* if there is no driver to attach! */
- Log(("%s No attached driver!\n", INSTANCE(pState)));
+ Log(("%s No attached driver!\n", INSTANCE(pThis)));
}
/*
@@ -1919,15 +1885,16 @@ static DECLCALLBACK(int) vnetAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t
* network card
*/
if (RT_SUCCESS(rc))
- vnetTempLinkDown(pState);
+ vnetTempLinkDown(pThis);
- vnetCsLeave(pState);
+ vnetCsLeave(pThis);
return rc;
}
+
/**
- * @copydoc FNPDMDEVSUSPEND
+ * @interface_method_impl{PDMDEVREG,pfnSuspend}
*/
static DECLCALLBACK(void) vnetSuspend(PPDMDEVINS pDevIns)
{
@@ -1935,8 +1902,9 @@ static DECLCALLBACK(void) vnetSuspend(PPDMDEVINS pDevIns)
vnetWakeupReceive(pDevIns);
}
+
/**
- * @copydoc FNPDMDEVPOWEROFF
+ * @interface_method_impl{PDMDEVREG,pfnPowerOff}
*/
static DECLCALLBACK(void) vnetPowerOff(PPDMDEVINS pDevIns)
{
@@ -1944,84 +1912,73 @@ static DECLCALLBACK(void) vnetPowerOff(PPDMDEVINS pDevIns)
vnetWakeupReceive(pDevIns);
}
+
/**
- * Device relocation callback.
- *
- * When this callback is called the device instance data, and if the
- * device have a GC component, is being relocated, or/and the selectors
- * have been changed. The device must use the chance to perform the
- * necessary pointer relocations and data updates.
- *
- * Before the GC code is executed the first time, this function will be
- * called with a 0 delta so GC pointer calculations can be one in one place.
- *
- * @param pDevIns Pointer to the device instance.
- * @param offDelta The relocation delta relative to the old location.
- *
- * @remark A relocation CANNOT fail.
+ * @interface_method_impl{PDMDEVREG,pfnRelocate}
*/
static DECLCALLBACK(void) vnetRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
{
- VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
vpciRelocate(pDevIns, offDelta);
- pState->pCanRxQueueRC = PDMQueueRCPtr(pState->pCanRxQueueR3);
+ pThis->pCanRxQueueRC = PDMQueueRCPtr(pThis->pCanRxQueueR3);
#ifdef VNET_TX_DELAY
- pState->pTxTimerRC = TMTimerRCPtr(pState->pTxTimerR3);
+ pThis->pTxTimerRC = TMTimerRCPtr(pThis->pTxTimerR3);
#endif /* VNET_TX_DELAY */
// TBD
}
+
/**
- * Destruct a device instance.
- *
- * We need to free non-VM resources only.
- *
- * @returns VBox status.
- * @param pDevIns The device instance data.
- * @thread EMT
+ * @interface_method_impl{PDMDEVREG,pfnDestruct}
*/
static DECLCALLBACK(int) vnetDestruct(PPDMDEVINS pDevIns)
{
- VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
LogRel(("TxTimer stats (avg/min/max): %7d usec %7d usec %7d usec\n",
- pState->u32AvgDiff, pState->u32MinDiff, pState->u32MaxDiff));
- Log(("%s Destroying instance\n", INSTANCE(pState)));
- if (pState->hEventMoreRxDescAvail != NIL_RTSEMEVENT)
+ pThis->u32AvgDiff, pThis->u32MinDiff, pThis->u32MaxDiff));
+ Log(("%s Destroying instance\n", INSTANCE(pThis)));
+ if (pThis->hEventMoreRxDescAvail != NIL_RTSEMEVENT)
{
- RTSemEventSignal(pState->hEventMoreRxDescAvail);
- RTSemEventDestroy(pState->hEventMoreRxDescAvail);
- pState->hEventMoreRxDescAvail = NIL_RTSEMEVENT;
+ RTSemEventSignal(pThis->hEventMoreRxDescAvail);
+ RTSemEventDestroy(pThis->hEventMoreRxDescAvail);
+ pThis->hEventMoreRxDescAvail = NIL_RTSEMEVENT;
}
- // if (PDMCritSectIsInitialized(&pState->csRx))
- // PDMR3CritSectDelete(&pState->csRx);
+ // if (PDMCritSectIsInitialized(&pThis->csRx))
+ // PDMR3CritSectDelete(&pThis->csRx);
- return vpciDestruct(&pState->VPCI);
+ return vpciDestruct(&pThis->VPCI);
}
+
/**
* @interface_method_impl{PDMDEVREG,pfnConstruct}
*/
static DECLCALLBACK(int) vnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
{
- VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
+ PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
int rc;
PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
- /* Initialize PCI part first. */
- pState->VPCI.IBase.pfnQueryInterface = vnetQueryInterface;
- rc = vpciConstruct(pDevIns, &pState->VPCI, iInstance,
+ /* Initialize the instance data suffiencently for the destructor not to blow up. */
+ pThis->hEventMoreRxDescAvail = NIL_RTSEMEVENT;
+
+ /* Do our own locking. */
+ rc = PDMDevHlpSetDeviceCritSect(pDevIns, PDMDevHlpCritSectGetNop(pDevIns));
+ AssertRCReturn(rc, rc);
+
+ /* Initialize PCI part. */
+ pThis->VPCI.IBase.pfnQueryInterface = vnetQueryInterface;
+ rc = vpciConstruct(pDevIns, &pThis->VPCI, iInstance,
VNET_NAME_FMT, VNET_PCI_SUBSYSTEM_ID,
VNET_PCI_CLASS, VNET_N_QUEUES);
- pState->pRxQueue = vpciAddQueue(&pState->VPCI, 256, vnetQueueReceive, "RX ");
- pState->pTxQueue = vpciAddQueue(&pState->VPCI, 256, vnetQueueTransmit, "TX ");
- pState->pCtlQueue = vpciAddQueue(&pState->VPCI, 16, vnetQueueControl, "CTL");
+ pThis->pRxQueue = vpciAddQueue(&pThis->VPCI, 256, vnetQueueReceive, "RX ");
+ pThis->pTxQueue = vpciAddQueue(&pThis->VPCI, 256, vnetQueueTransmit, "TX ");
+ pThis->pCtlQueue = vpciAddQueue(&pThis->VPCI, 16, vnetQueueControl, "CTL");
- Log(("%s Constructing new instance\n", INSTANCE(pState)));
-
- pState->hEventMoreRxDescAvail = NIL_RTSEMEVENT;
+ Log(("%s Constructing new instance\n", INSTANCE(pThis)));
/*
* Validate configuration.
@@ -2031,52 +1988,52 @@ static DECLCALLBACK(int) vnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
N_("Invalid configuration for VirtioNet device"));
/* Get config params */
- rc = CFGMR3QueryBytes(pCfg, "MAC", pState->macConfigured.au8,
- sizeof(pState->macConfigured));
+ rc = CFGMR3QueryBytes(pCfg, "MAC", pThis->macConfigured.au8,
+ sizeof(pThis->macConfigured));
if (RT_FAILURE(rc))
return PDMDEV_SET_ERROR(pDevIns, rc,
N_("Configuration error: Failed to get MAC address"));
- rc = CFGMR3QueryBool(pCfg, "CableConnected", &pState->fCableConnected);
+ rc = CFGMR3QueryBool(pCfg, "CableConnected", &pThis->fCableConnected);
if (RT_FAILURE(rc))
return PDMDEV_SET_ERROR(pDevIns, rc,
N_("Configuration error: Failed to get the value of 'CableConnected'"));
- rc = CFGMR3QueryU32Def(pCfg, "LinkUpDelay", (uint32_t*)&pState->cMsLinkUpDelay, 5000); /* ms */
+ rc = CFGMR3QueryU32Def(pCfg, "LinkUpDelay", (uint32_t*)&pThis->cMsLinkUpDelay, 5000); /* ms */
if (RT_FAILURE(rc))
return PDMDEV_SET_ERROR(pDevIns, rc,
N_("Configuration error: Failed to get the value of 'LinkUpDelay'"));
- Assert(pState->cMsLinkUpDelay <= 300000); /* less than 5 minutes */
- if (pState->cMsLinkUpDelay > 5000 || pState->cMsLinkUpDelay < 100)
+ Assert(pThis->cMsLinkUpDelay <= 300000); /* less than 5 minutes */
+ if (pThis->cMsLinkUpDelay > 5000 || pThis->cMsLinkUpDelay < 100)
{
LogRel(("%s WARNING! Link up delay is set to %u seconds!\n",
- INSTANCE(pState), pState->cMsLinkUpDelay / 1000));
+ INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000));
}
Log(("%s Link up delay is set to %u seconds\n",
- INSTANCE(pState), pState->cMsLinkUpDelay / 1000));
+ INSTANCE(pThis), pThis->cMsLinkUpDelay / 1000));
- vnetPrintFeatures(pState, vnetGetHostFeatures(pState), "Device supports the following features");
+ vnetPrintFeatures(pThis, vnetIoCb_GetHostFeatures(pThis), "Device supports the following features");
/* Initialize PCI config space */
- memcpy(pState->config.mac.au8, pState->macConfigured.au8, sizeof(pState->config.mac.au8));
- pState->config.uStatus = 0;
+ memcpy(pThis->config.mac.au8, pThis->macConfigured.au8, sizeof(pThis->config.mac.au8));
+ pThis->config.uStatus = 0;
/* Initialize state structure */
- pState->u32PktNo = 1;
+ pThis->u32PktNo = 1;
/* Interfaces */
- pState->INetworkDown.pfnWaitReceiveAvail = vnetNetworkDown_WaitReceiveAvail;
- pState->INetworkDown.pfnReceive = vnetNetworkDown_Receive;
- pState->INetworkDown.pfnReceiveGso = vnetNetworkDown_ReceiveGso;
- pState->INetworkDown.pfnXmitPending = vnetNetworkDown_XmitPending;
+ pThis->INetworkDown.pfnWaitReceiveAvail = vnetNetworkDown_WaitReceiveAvail;
+ pThis->INetworkDown.pfnReceive = vnetNetworkDown_Receive;
+ pThis->INetworkDown.pfnReceiveGso = vnetNetworkDown_ReceiveGso;
+ pThis->INetworkDown.pfnXmitPending = vnetNetworkDown_XmitPending;
- pState->INetworkConfig.pfnGetMac = vnetGetMac;
- pState->INetworkConfig.pfnGetLinkState = vnetGetLinkState;
- pState->INetworkConfig.pfnSetLinkState = vnetSetLinkState;
+ pThis->INetworkConfig.pfnGetMac = vnetGetMac;
+ pThis->INetworkConfig.pfnGetLinkState = vnetGetLinkState;
+ pThis->INetworkConfig.pfnSetLinkState = vnetSetLinkState;
/* Initialize critical section. */
- // char szTmp[sizeof(pState->VPCI.szInstance) + 2];
- // RTStrPrintf(szTmp, sizeof(szTmp), "%sRX", pState->VPCI.szInstance);
- // rc = PDMDevHlpCritSectInit(pDevIns, &pState->csRx, szTmp);
+ // char szTmp[sizeof(pThis->VPCI.szInstance) + 2];
+ // RTStrPrintf(szTmp, sizeof(szTmp), "%sRX", pThis->VPCI.szInstance);
+ // rc = PDMDevHlpCritSectInit(pDevIns, &pThis->csRx, szTmp);
// if (RT_FAILURE(rc))
// return rc;
@@ -2098,34 +2055,34 @@ static DECLCALLBACK(int) vnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
/* Create the RX notifier signaller. */
rc = PDMDevHlpQueueCreate(pDevIns, sizeof(PDMQUEUEITEMCORE), 1, 0,
- vnetCanRxQueueConsumer, true, "VNet-Rcv", &pState->pCanRxQueueR3);
+ vnetCanRxQueueConsumer, true, "VNet-Rcv", &pThis->pCanRxQueueR3);
if (RT_FAILURE(rc))
return rc;
- pState->pCanRxQueueR0 = PDMQueueR0Ptr(pState->pCanRxQueueR3);
- pState->pCanRxQueueRC = PDMQueueRCPtr(pState->pCanRxQueueR3);
+ pThis->pCanRxQueueR0 = PDMQueueR0Ptr(pThis->pCanRxQueueR3);
+ pThis->pCanRxQueueRC = PDMQueueRCPtr(pThis->pCanRxQueueR3);
/* Create Link Up Timer */
- rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetLinkUpTimer, pState,
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetLinkUpTimer, pThis,
TMTIMER_FLAGS_NO_CRIT_SECT,
- "VirtioNet Link Up Timer", &pState->pLinkUpTimer);
+ "VirtioNet Link Up Timer", &pThis->pLinkUpTimer);
if (RT_FAILURE(rc))
return rc;
#ifdef VNET_TX_DELAY
/* Create Transmit Delay Timer */
- rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetTxTimer, pState,
+ rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetTxTimer, pThis,
TMTIMER_FLAGS_NO_CRIT_SECT,
- "VirtioNet TX Delay Timer", &pState->pTxTimerR3);
+ "VirtioNet TX Delay Timer", &pThis->pTxTimerR3);
if (RT_FAILURE(rc))
return rc;
- pState->pTxTimerR0 = TMTimerR0Ptr(pState->pTxTimerR3);
- pState->pTxTimerRC = TMTimerRCPtr(pState->pTxTimerR3);
+ pThis->pTxTimerR0 = TMTimerR0Ptr(pThis->pTxTimerR3);
+ pThis->pTxTimerRC = TMTimerRCPtr(pThis->pTxTimerR3);
- pState->u32i = pState->u32AvgDiff = pState->u32MaxDiff = 0;
- pState->u32MinDiff = ~0;
+ pThis->u32i = pThis->u32AvgDiff = pThis->u32MaxDiff = 0;
+ pThis->u32MinDiff = ~0;
#endif /* VNET_TX_DELAY */
- rc = PDMDevHlpDriverAttach(pDevIns, 0, &pState->VPCI.IBase, &pState->pDrvBase, "Network Port");
+ rc = PDMDevHlpDriverAttach(pDevIns, 0, &pThis->VPCI.IBase, &pThis->pDrvBase, "Network Port");
if (RT_SUCCESS(rc))
{
if (rc == VINF_NAT_DNS)
@@ -2133,39 +2090,42 @@ static DECLCALLBACK(int) vnetConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMN
PDMDevHlpVMSetRuntimeError(pDevIns, 0 /*fFlags*/, "NoDNSforNAT",
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"));
}
- pState->pDrv = PDMIBASE_QUERY_INTERFACE(pState->pDrvBase, PDMINETWORKUP);
- AssertMsgReturn(pState->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),
+ pThis->pDrv = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMINETWORKUP);
+ AssertMsgReturn(pThis->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),
VERR_PDM_MISSING_INTERFACE_BELOW);
}
else if ( rc == VERR_PDM_NO_ATTACHED_DRIVER
|| rc == VERR_PDM_CFG_MISSING_DRIVER_NAME )
{
/* No error! */
- Log(("%s This adapter is not attached to any network!\n", INSTANCE(pState)));
+ Log(("%s This adapter is not attached to any network!\n", INSTANCE(pThis)));
}
else
return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the network LUN"));
- rc = RTSemEventCreate(&pState->hEventMoreRxDescAvail);
+ rc = RTSemEventCreate(&pThis->hEventMoreRxDescAvail);
if (RT_FAILURE(rc))
return rc;
- rc = vnetReset(pState);
+ rc = vnetIoCb_Reset(pThis);
AssertRC(rc);
- PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Devices/VNet%d/Bytes/Receive", iInstance);
- PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Devices/VNet%d/Bytes/Transmit", iInstance);
- PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatReceiveGSO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of received GSO packets", "/Devices/VNet%d/Packets/ReceiveGSO", iInstance);
- PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitPackets, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of sent packets", "/Devices/VNet%d/Packets/Transmit", iInstance);
- PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitGSO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of sent GSO packets", "/Devices/VNet%d/Packets/Transmit-Gso", iInstance);
- PDMDevHlpSTAMRegisterF(pDevIns, &pState->StatTransmitCSum, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of completed TX checksums", "/Devices/VNet%d/Packets/Transmit-Csum", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Public/Net/VNet%u/BytesReceived", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Public/Net/VNet%u/BytesTransmitted", iInstance);
+
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data received", "/Devices/VNet%d/ReceiveBytes", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitBytes, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, "Amount of data transmitted", "/Devices/VNet%d/TransmitBytes", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveGSO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of received GSO packets", "/Devices/VNet%d/Packets/ReceiveGSO", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitPackets, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of sent packets", "/Devices/VNet%d/Packets/Transmit", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitGSO, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of sent GSO packets", "/Devices/VNet%d/Packets/Transmit-Gso", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitCSum, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT, "Number of completed TX checksums", "/Devices/VNet%d/Packets/Transmit-Csum", 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);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceive, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling receive", "/Devices/VNet%d/Receive/Total", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatReceiveStore, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling receive storing", "/Devices/VNet%d/Receive/Store", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatRxOverflow, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling RX overflows", "/Devices/VNet%d/RxOverflow", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatRxOverflowWakeup, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of RX overflow wakeups", "/Devices/VNet%d/RxOverflowWakeup", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmit, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in HC", "/Devices/VNet%d/Transmit/Total", iInstance);
+ PDMDevHlpSTAMRegisterF(pDevIns, &pThis->StatTransmitSend, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling send transmit in HC", "/Devices/VNet%d/Transmit/Send", iInstance);
#endif /* VBOX_WITH_STATISTICS */
return VINF_SUCCESS;
@@ -2203,34 +2163,35 @@ const PDMDEVREG g_DeviceVirtioNet =
/* Size of the instance data. */
sizeof(VNETSTATE),
- /* Construct instance - required. */
+ /* pfnConstruct */
vnetConstruct,
- /* Destruct instance - optional. */
+ /* pfnDestruct */
vnetDestruct,
- /* Relocation command - optional. */
+ /* pfnRelocate */
vnetRelocate,
- /* I/O Control interface - optional. */
+ /* pfnMemSetup. */
NULL,
- /* Power on notification - optional. */
+ /* pfnPowerOn */
NULL,
- /* Reset notification - optional. */
+ /* pfnReset */
NULL,
- /* Suspend notification - optional. */
+ /* pfnSuspend */
vnetSuspend,
- /* Resume notification - optional. */
+ /* pfnResume */
NULL,
- /* Attach command - optional. */
+ /* pfnAttach */
vnetAttach,
- /* Detach notification - optional. */
+ /* pfnDetach */
vnetDetach,
- /* Query a LUN base interface - optional. */
+ /* pfnQueryInterface */
NULL,
- /* Init complete notification - optional. */
+ /* pfnInitComplete */
NULL,
- /* Power off notification - optional. */
+ /* pfnPowerOff */
vnetPowerOff,
/* pfnSoftReset */
NULL,
+
/* u32VersionEnd */
PDM_DEVREG_VERSION
};