intnetinline.h revision c58f1213e628a545081c70e26c6b67a841cff880
/* $Id$ */
/** @file
* INTNET - Internal Networking, Inlined Code. (DEV,++)
*
* This is all inlined because it's too tedious to create 2-3 libraries to
* contain it all. Large parts of this header is only accessible from C++
* sources because of mixed code and variables.
*/
/*
* Copyright (C) 2006-2011 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.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
#ifndef ___VBox_intnetinline_h
#define ___VBox_intnetinline_h
/**
* Valid internal networking frame type.
*
* @returns true / false.
* @param u16Type The frame type to check.
*/
{
|| u16Type == INTNETHDR_TYPE_GSO
|| u16Type == INTNETHDR_TYPE_PADDING))
return true;
return false;
}
/**
* Partly initializes a scatter / gather buffer, leaving the segments to the
* caller.
*
* @returns Pointer to the start of the frame.
* @param pSG Pointer to the scatter / gather structure.
* @param cbTotal The total size.
* @param cSegs The number of segments.
* @param cSegsUsed The number of used segments.
*/
DECLINLINE(void) IntNetSgInitTempSegs(PINTNETSG pSG, uint32_t cbTotal, unsigned cSegs, unsigned cSegsUsed)
{
#if ARCH_BITS == 64
#endif
}
/**
* Partly initializes a scatter / gather buffer w/ GSO, leaving the segments to
* the caller.
*
* @returns Pointer to the start of the frame.
* @param pSG Pointer to the scatter / gather structure.
* @param cbTotal The total size.
* @param cSegs The number of segments.
* @param cSegsUsed The number of used segments.
* @param pGso The GSO context.
*/
{
#if ARCH_BITS == 64
#endif
}
/**
* Initializes a scatter / gather buffer describing a simple linear buffer.
*
* @returns Pointer to the start of the frame.
* @param pSG Pointer to the scatter / gather structure.
* @param pvFrame Pointer to the frame
* @param cbFrame The size of the frame.
*/
{
}
/**
* Initializes a scatter / gather buffer describing a simple linear buffer.
*
* @returns Pointer to the start of the frame.
* @param pSG Pointer to the scatter / gather structure.
* @param pvFrame Pointer to the frame
* @param cbFrame The size of the frame.
* @param pGso The GSO context.
*/
DECLINLINE(void) IntNetSgInitTempGso(PINTNETSG pSG, void *pvFrame, uint32_t cbFrame, PCPDMNETWORKGSO pGso)
{
}
/**
* Reads an entire SG into a fittingly size buffer.
*
* @param pSG The SG list to read.
* @param pvBuf The buffer to read into (at least pSG->cbTotal in size).
*/
{
else
{
unsigned iSeg = 0;
{
}
}
}
/**
* Reads a portion of an SG into a buffer.
*
* @param pSG The SG list to read.
* @param offSrc The offset to start start copying from.
* @param cbToRead The number of bytes to copy.
* @param pvBuf The buffer to read into, cb or more in size.
*/
{
/* validate assumptions */
/* Find the right segment and copy any bits from within the segment. */
while (offSrc)
{
{
{
return;
}
break;
}
/* advance */
iSeg++;
}
/* We're not at the start of a segment, copy until we're done. */
for (;;)
{
{
return;
}
iSeg++;
}
}
#ifdef __cplusplus
/**
* Get the amount of space available for writing.
*
* @returns Number of available bytes.
* @param pRingBuf The ring buffer.
*/
{
return offRead <= offWriteInt
}
/**
* Checks if the ring has more for us to read.
*
* @returns Number of ready bytes.
* @param pRingBuf The ring buffer.
*/
{
return offRead != offWriteCom;
}
/**
* Gets the next frame to read.
*
* @returns Pointer to the next frame. NULL if done.
* @param pRingBuf The ring buffer.
*/
{
if (offRead == offWriteCom)
return NULL;
}
/**
* Get the amount of data ready for reading.
*
* @returns Number of ready bytes.
* @param pRingBuf The ring buffer.
*/
{
return offRead <= offWriteCom
? offWriteCom - offRead
}
/**
* Calculates the pointer to the frame.
*
* @returns Pointer to the start of the frame.
* @param pHdr Pointer to the packet header
* @param pBuf The buffer the header is within. Only used in strict builds.
*/
{
#ifdef VBOX_STRICT
#endif
return pu8;
}
/**
* Calculates the pointer to the GSO context.
*
* ASSUMES the frame is a GSO frame.
*
* The GSO context is immediately followed by the headers and payload. The size
* is INTNETBUF::cbFrame - sizeof(PDMNETWORKGSO).
*
* @returns Pointer to the GSO context.
* @param pHdr Pointer to the packet header
* @param pBuf The buffer the header is within. Only used in strict builds.
*/
{
#ifdef VBOX_STRICT
#endif
return pGso;
}
/**
* Skips to the next (read) frame in the buffer.
*
* @param pRingBuf The ring buffer in question.
*/
{
/* skip the frame */
#ifdef INTNET_POISON_READ_FRAMES
#endif
}
/**
* Allocates a frame in the specified ring.
*
* @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
* @param pRingBuf The ring buffer.
* @param cbFrame The frame size.
* @param ppHdr Where to return the frame header.
* Don't touch this!
* @param ppvFrame Where to return the frame pointer.
*/
DECLINLINE(int) intnetRingAllocateFrameInternal(PINTNETRINGBUF pRingBuf, uint32_t cbFrame, uint16_t u16Type,
{
/*
* Validate input and adjust the input.
*/
if (offRead <= offWriteInt)
{
/*
* Try fit it all before the end of the buffer.
*/
{
return VERR_WRONG_ORDER; /* race */
Log2(("intnetRingAllocateFrameInternal: offWriteInt: %#x -> %#x (1) (R=%#x T=%#x S=%#x)\n", offWriteInt, offNew, offRead, u16Type, cbFrame));
return VINF_SUCCESS;
}
/*
* Try fit the frame at the start of the buffer.
* (The header fits before the end of the buffer because of alignment.)
*/
AssertMsg(pRingBuf->offEnd - offWriteInt >= sizeof(INTNETHDR), ("offEnd=%x offWriteInt=%x\n", pRingBuf->offEnd, offWriteInt));
{
return VERR_WRONG_ORDER; /* race */
Log2(("intnetRingAllocateFrameInternal: offWriteInt: %#x -> %#x (2) (R=%#x T=%#x S=%#x)\n", offWriteInt, offNew, offRead, u16Type, cbFrame));
return VINF_SUCCESS;
}
}
/*
* The reader is ahead of the writer, try fit it into that space.
*/
{
return VERR_WRONG_ORDER; /* race */
Log2(("intnetRingAllocateFrameInternal: offWriteInt: %#x -> %#x (3) (R=%#x T=%#x S=%#x)\n", offWriteInt, offNew, offRead, u16Type, cbFrame));
return VINF_SUCCESS;
}
/* (it didn't fit) */
return VERR_BUFFER_OVERFLOW;
}
/**
* Allocates a normal frame in the specified ring.
*
* @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
* @param pRingBuf The ring buffer.
* @param cbFrame The frame size.
* @param ppHdr Where to return the frame header.
* Don't touch this!
* @param ppvFrame Where to return the frame pointer.
*/
DECLINLINE(int) IntNetRingAllocateFrame(PINTNETRINGBUF pRingBuf, uint32_t cbFrame, PINTNETHDR *ppHdr, void **ppvFrame)
{
}
/**
* Allocates a GSO frame in the specified ring.
*
* @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
* @param pRingBuf The ring buffer.
* @param cbFrame The frame size.
* @param pGso Pointer to the GSO context.
* @param ppHdr Where to return the frame header.
* Don't touch this!
* @param ppvFrame Where to return the frame pointer.
*/
DECLINLINE(int) IntNetRingAllocateGsoFrame(PINTNETRINGBUF pRingBuf, uint32_t cbFrame, PCPDMNETWORKGSO pGso,
{
int rc = intnetRingAllocateFrameInternal(pRingBuf, cbFrame + sizeof(*pGso), INTNETHDR_TYPE_GSO, ppHdr, &pvFrame);
if (RT_SUCCESS(rc))
{
}
return rc;
}
/**
* Commits a frame.
*
* Make sure to commit the frames in the order they've been allocated!
*
* @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
* @param pRingBuf The ring buffer.
* @param pHdr The frame header returned by
* IntNetRingAllocateFrame.
*/
{
/*
* Validate input and commit order.
*/
/*
* Figure out the offWriteCom for this packet and update the ring.
*/
+ cb;
{
}
Log2(("IntNetRingCommitFrame: offWriteCom: %#x -> %#x (R=%#x T=%#x S=%#x)\n", pRingBuf->offWriteCom, offWriteCom, pRingBuf->offReadX, pHdr->u16Type, cbFrame));
}
/**
* Commits a frame and injects a filler frame if not all of the buffer was used.
*
* Make sure to commit the frames in the order they've been allocated!
*
* @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
* @param pRingBuf The ring buffer.
* @param pHdr The frame header returned by
* IntNetRingAllocateFrame.
* @param cbUsed The amount of space actually used. This does
* not include the GSO part.
*/
{
/*
* Validate input and commit order.
*/
cbUsed += sizeof(PDMNETWORKGSO);
/*
* Calc the new write commit offset.
*/
{
}
/*
* Insert a dummy frame to pad any unused space.
*/
if (cbAlignedFrame != cbAlignedUsed)
{
/** @todo Later: Try unallocate the extra memory. */
}
Log2(("IntNetRingCommitFrameEx: offWriteCom: %#x -> %#x (R=%#x T=%#x S=%#x P=%#x)\n", pRingBuf->offWriteCom, offWriteCom, pRingBuf->offReadX, pHdr->u16Type, pHdr->cbFrame, cbAlignedFrame - cbAlignedUsed));
}
/**
* Writes a frame to the specified ring.
*
* Make sure you don't have any uncommitted frames when calling this function!
*
* @returns VINF_SUCCESS or VERR_BUFFER_OVERFLOW.
* @param pRingBuf The ring buffer.
* @param pvFrame The bits to write.
* @param cbFrame How much to write.
*/
{
/*
* Validate input.
*/
/*
* Align the size and read the volatile ring buffer variables.
*/
if (offRead <= offWriteInt)
{
/*
* Try fit it all before the end of the buffer.
*/
{
return VERR_WRONG_ORDER; /* race */
return VINF_SUCCESS;
}
/*
* Try fit the frame at the start of the buffer.
* (The header fits before the end of the buffer because of alignment.)
*/
AssertMsg(pRingBuf->offEnd - offWriteInt >= sizeof(INTNETHDR), ("offEnd=%x offWriteInt=%x\n", pRingBuf->offEnd, offWriteInt));
{
return VERR_WRONG_ORDER; /* race */
return VINF_SUCCESS;
}
}
/*
* The reader is ahead of the writer, try fit it into that space.
*/
{
return VERR_WRONG_ORDER; /* race */
return VINF_SUCCESS;
}
/* (it didn't fit) */
return VERR_BUFFER_OVERFLOW;
}
/**
* Reads the next frame in the buffer and moves the read cursor past it.
*
* @returns Size of the frame in bytes. 0 is returned if nothing in the buffer.
* @param pRingBuff The ring buffer to read from.
* @param pvFrameDst Where to put the frame. The caller is responsible for
* ensuring that there is sufficient space for the frame.
*
* @deprecated Bad interface, do NOT use it! Only for tstIntNetR0.
*/
{
if (offRead == offWriteCom)
return 0;
#ifdef INTNET_POISON_READ_FRAMES
#endif
/* skip the frame */
return cbFrame;
}
/**
* Initializes a buffer structure.
*
* @param pIntBuf The internal networking interface buffer. This
* expected to be cleared prior to calling this
* function.
* @param cbBuf The size of the whole buffer.
* @param cbRecv The receive size.
* @param cbSend The send size.
*/
DECLINLINE(void) IntNetBufInit(PINTNETBUF pIntBuf, uint32_t cbBuf, uint32_t cbRecv, uint32_t cbSend)
{
/* receive ring buffer. */
uint32_t offBuf = RT_ALIGN_32(sizeof(INTNETBUF), INTNETRINGBUF_ALIGNMENT) - RT_OFFSETOF(INTNETBUF, Recv);
/* send ring buffer. */
}
#endif /* __cplusplus */
#endif