DrvDedicatedNic.cpp revision ad48e47654d22f79b025dc4b21cb162cb123801a
/* $Id$ */
/** @file
* DrvDedicatedNic - Experimental network driver for using a dedicated (V)NIC.
*/
/*
* Copyright (C) 2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_DEFAULT
#include <VBox/intnetinline.h>
#include "VBoxDD.h"
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Instance data for the dedicated (V)NIC driver.
*
* @implements PDMINETWORKUP
*/
typedef struct DRVDEDICATEDNIC
{
/** The network interface. */
/** The network interface. */
/** The network config interface.
* Can (in theory at least) be NULL. */
/** Pointer to the driver instance. */
/** Ring-3 base interface for the ring-0 context. */
/** Ring-3 base interface for the raw-mode context. */
/** The network interface for the ring-0 context. */
/** Pointer to the driver instance. */
/** The interface we're talking to. */
/** Set if the link is up, clear if its down. */
bool fLinkDown;
/** Set if the current transmit operation is done the XMIT thread. If clear,
* we assume its an EMT. */
bool fXmitOnXmitThread;
/** The name of the interface that we're connected to. */
/** Critical section serializing transmission. */
/** The transmit scatter gather buffer (ring-3 -> ring-0). */
/** The transmit GSO context (when applicable). */
/** The transmit buffer (ring-3 -> ring-0). */
/** The receive scatter gather buffer. */
/** The receive buffer (ring-0 -> ring-3). */
/** Pointer to the instance data for the dedicated (V)NIC driver. */
typedef DRVDEDICATEDNIC *PDRVDEDICATEDNIC;
/**
* Ring-0 operations.
*/
typedef enum DRVDEDICATEDNICR0OP
{
/** Invalid zero value.. */
/** Initialize the connection to the NIC. */
/** Terminate the connection to the NIC. */
/** Suspend the operation. */
/** Resume the operation. */
/** Wait for and do receive work.
* We do this in ring-0 instead of ring-3 to save 1-2 buffer copies and
* unnecessary context switching. */
/** Wait for and do transmit work.
* We do this in ring-0 instead of ring-3 to save 1-2 buffer copies and
* unnecessary context switching. */
/** Changes the promiscuousness of the interface (guest point of view). */
/** End of the valid operations. */
/** The usual 32-bit hack. */
DRVDEDICATEDNICR0OP_32BIT_HACK = 0x7fffffff
#ifdef IN_RING0
/**
* @interface_method_impl{FNPDMDRVREQHANDLERR0}
*/
PDMBOTHCBDECL(int) drvR0DedicatedNicReqHandler(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg)
{
switch ((DRVDEDICATEDNICR0OP)uOperation)
{
case DRVDEDICATEDNICR0OP_INIT:
return VERR_NOT_IMPLEMENTED;//drvR0DedicatedNicReqInit(pDrvIns, u64Arg);
case DRVDEDICATEDNICR0OP_TERM:
return VERR_NOT_IMPLEMENTED;//drvR0DedicatedNicReqTerm(pDrvIns);
return VERR_NOT_IMPLEMENTED;//drvR0DedicatedNicReqSuspend(pDrvIns);
return VERR_NOT_IMPLEMENTED;//drvR0DedicatedNicReqResume(pDrvIns);
case DRVDEDICATEDNICR0OP_RECV:
return VERR_NOT_IMPLEMENTED;//drvR0DedicatedNicReqRecv(pDrvIns);
case DRVDEDICATEDNICR0OP_SEND:
return VERR_NOT_IMPLEMENTED;//drvR0DedicatedNicReqSend(pDrvIns);
return VERR_NOT_IMPLEMENTED;//drvR0DedicatedNicReqPromisc(pDrvIns, !!u64Arg);
case DRVDEDICATEDNICR0OP_END:
default:
return VERR_INVALID_FUNCTION;
}
return VINF_SUCCESS;
}
#endif /* IN_RING0 */
/* -=-=-=-=- PDMINETWORKUP -=-=-=-=- */
/**
* @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
*/
{
if (RT_SUCCESS(rc))
return rc;
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
*/
{
/*
* If the net is down, we can return immediately.
*/
return VERR_NET_DOWN;
#ifdef IN_RING0
/** @todo Ask the driver for a buffer, atomically if we're called on EMT. */
return VERR_TRY_AGAIN;
#else /* IN_RING3 */
/*
* Are we busy or is the request too big?
*/
if (RT_UNLIKELY((pThis->XmitSg.fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC))
return VERR_TRY_AGAIN;
return VERR_NO_MEMORY;
/*
* Initialize the S/G buffer and return.
*/
if (!pGso)
{
}
else
{
}
# if 0 /* poison */
# endif
return VINF_SUCCESS;
#endif /* IN_RING3 */
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnFreeBuf}
*/
{
if (pSgBuf)
{
#ifdef IN_RING0
// ...
#else
#endif
}
return VINF_SUCCESS;
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnSendBuf}
*/
PDMBOTHCBDECL(int) drvDedicatedNicUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread)
{
#ifdef IN_RING0
#endif
#ifdef IN_RING0
/*
* Tell the driver to send the packet.
*/
return VERR_INTERNAL_ERROR_4;
#else /* IN_RING3 */
/*
* Call ring-0 to start the transfer.
*/
return rc;
#endif /* IN_RING3 */
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
*/
{
}
/**
* @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
*/
PDMBOTHCBDECL(void) drvDedicatedNicUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous)
{
}
#ifdef IN_RING3
/**
* @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged}
*/
static DECLCALLBACK(void) drvR3DedicatedNicUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState)
{
bool fLinkDown;
switch (enmLinkState)
{
case PDMNETWORKLINKSTATE_DOWN:
fLinkDown = true;
break;
default:
case PDMNETWORKLINKSTATE_UP:
fLinkDown = false;
break;
}
LogFlow(("drvR3DedicatedNicUp_NotifyLinkChanged: enmLinkState=%d %d->%d\n", enmLinkState, pThis->fLinkDown, fLinkDown));
}
/* -=-=-=-=- PDMIBASER0 -=-=-=-=- */
/**
* @interface_method_impl{PDMIBASER0,pfnQueryInterface}
*/
static DECLCALLBACK(RTR0PTR) drvR3DedicatedNicIBaseR0_QueryInterface(PPDMIBASER0 pInterface, const char *pszIID)
{
return NIL_RTR0PTR;
}
/* -=-=-=-=- PDMIBASE -=-=-=-=- */
/**
* @interface_method_impl{PDMIBASE,pfnQueryInterface}
*/
static DECLCALLBACK(void *) drvR3DedicatedNicIBase_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
{
return NULL;
}
/* -=-=-=-=- PDMDRVREG -=-=-=-=- */
/**
* @interface_method_impl{PDMDRVREG,pfnPowerOff}
*/
{
LogFlow(("drvR3DedicatedNicPowerOff\n"));
}
/**
* @interface_method_impl{PDMDRVREG,pfnResume}
*/
{
LogFlow(("drvR3DedicatedNicPowerResume\n"));
}
/**
* @interface_method_impl{PDMDRVREG,pfnSuspend}
*/
{
LogFlow(("drvR3DedicatedNicPowerSuspend\n"));
}
/**
* @interface_method_impl{PDMDRVREG,pfnPowerOn}
*/
{
LogFlow(("drvR3DedicatedNicPowerOn\n"));
}
/**
* @interface_method_impl{PDMDRVREG,pfnDestruct}
*/
{
LogFlow(("drvR3DedicatedNicDestruct\n"));
{
}
}
/**
* @interface_method_impl{PDMDRVREG,pfnConstruct}
*/
static DECLCALLBACK(int) drvR3DedicatedNicConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
bool f;
/*
* Init the static parts.
*/
#if 0
pThis->fActivateEarlyDeactivateLate = false;
/* IBase* */
/* INetworkUp */
#endif
/** @todo
* Need to create a generic way of calling into the ring-0 side of the driver so
* we can initialize the thing as well as send and receive. Hmm ... the
* sending could be done more efficiently from a ring-0 kernel thread actually
* (saves context switching and 1-2 copy operations). Ditto for receive, except
* we need to tie the thread to the process or we cannot access the guest ram so
* easily.
*/
return VERR_NOT_IMPLEMENTED;
}
/**
* Internal networking transport driver registration record.
*/
const PDMDRVREG g_DrvDedicatedNic =
{
/* u32Version */
/* szName */
"DedicatedNic",
/* szRCMod */
"",
/* szR0Mod */
"VBoxDDR0.r0",
/* pszDescription */
"Dedicated (V)NIC Driver",
/* fFlags */
/* fClass. */
/* cMaxInstances */
~0U,
/* cbInstance */
sizeof(DRVDEDICATEDNIC),
/* pfnConstruct */
/* pfnDestruct */
/* pfnRelocate */
NULL,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
/* pfnReset */
NULL,
/* pfnSuspend */
/* pfnResume */
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
/* pfnSoftReset */
NULL,
/* u32EndVersion */
};
#endif /* IN_RING3 */