📄 netbuf.h
字号:
/*****************************************************************************
* netbuf.h - Network Buffers header file.
*
* Copyright (c) 1998 Global Election Systems Inc.
*
* The authors hereby grant permission to use, copy, modify, distribute,
* and license this software and its documentation for any purpose, provided
* that existing copyright notices are retained in all copies and that this
* notice and the following disclaimer are included verbatim in any
* distributions. No written agreement, license, or royalty fee is required
* for any of the authorized uses.
*
* THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
* REVISION HISTORY
*
* 98-01-30 Guy Lancaster <glanca@gesn.com>, Global Election Systems Inc.
* Original based on BSD and ka9q mbufs.
******************************************************************************
* THEORY OF OPERATION
*
* The network buffers (nBufs) form the basis for passing data between the
* protocols in the protocol stacks. They are extensible in that they can be
* chained together when a data block is larger than the data area of a single
* buffer or if you need to prepend or append data that won't fit on the
* beginning or end (respectively) of a buffer. This avoids expensive copy
* operations at the expense of consuming more memory.
*
* This buffer structure is based on the mbuf structure in the BSD network
* codes except that it does not support clusters, types, or flags which were
* not needed in this stack. Also, these are designed to be allocated from a
* static array rather than being malloc'd to avoid the overhead of heap memory
* management. This design is for use in real-time embedded systems where the
* operating parameters are known beforehand and performance is critical.
*
* To set up this buffer system, set the buffer size NBUFSZ in the header
* file and MAXNBUFS in the program file. NBUFSZ should be set so that
* the link layer packets fit in a single buffer (normally). You can monitor
* the minFreeBufs variable to ensure that your setting of MAXNBUFS is
* appropriate for your system.
*
* Note that the prepend operation frees the current nBuf chain if it fails
* while the append operation does not. This assumes that a prepend failure
* is catastrophic (if you can't add a header, you can't send it) while an
* append failure may mean that you send what you've got and try again.
*****************************************************************************/
#ifndef NETBUF_H
#define NETBUF_H
/*************************
*** PUBLIC DEFINITIONS ***
*************************/
/*
* By making NBUFSZ large enough to contain the largest mtu of all the
* interfaces, no packet need ever be split across buffers.
*/
#if ETHER_SUPPORT
#define NBUFSZ 1580 /* Max data size of an nBuf. */
#else
#define NBUFSZ 128 /* Max data size of an nBuf. */
#endif
/************************
*** PUBLIC DATA TYPES ***
************************/
/* The network buffer structure. */
typedef struct NBuf_s {
struct NBuf_s *nextBuf; /* Next buffer in chain. */
struct NBuf_s *nextChain; /* Next chain in queue. */
char * data; /* Location of data. */
u_int len; /* Bytes (octets) of data in this nBuf. */
u_int chainLen; /* Total bytes in this chain - valid on top only. */
u_long sortOrder; /* Sort order value for sorted queues. */
char body[NBUFSZ]; /* Data area of the nBuf. */
} NBuf;
/* The chain queue header structure. */
typedef struct NBufQHdr_s {
NBuf *qHead; /* The first nBuf chain in the queue. */
NBuf *qTail; /* The last nBuf chain in the queue. */
u_int qLen; /* The number of chains in the queue. */
} NBufQHdr;
/* Network buffer statistics. */
typedef struct NBufStats_s {
DiagStat headLine; /* Headline text. */
DiagStat curFreeBufs; /* The current number of free nBufs. */
DiagStat minFreeBufs; /* The minimum number of free nBufs during operation. */
DiagStat maxFreeBufs; /* The maximum number of free nBufs during operation. */
DiagStat maxChainLen; /* Size of largest chain (from nChainLen). */
DiagStat endRec;
} NBufStats;
/*****************************
*** PUBLIC DATA STRUCTURES ***
*****************************/
extern NBuf *topNBuf;
#if STATS_SUPPORT > 0
extern NBufStats nBufStats;
#else
extern u_int curFreeBufs;
#endif
/***********************
*** PUBLIC FUNCTIONS ***
***********************/
/* Initialize the memory buffer sub-system. */
void nBufInit (void);
/* nBUFTOPTR - Return nBuf's data pointer casted to type t. */
#define nBUFTOPTR(n, t) ((t)((n)->data))
#if STATS_SUPPORT > 0
/* nBUFSFREE - Return the number of free buffers. */
#define nBUFSFREE() nBufStats.curFreeBufs.val
#else
#define nBUFSFREE() curFreeBufs
#endif
/*
* nGET - Allocate an nBuf off the free list.
* Return n pointing to new nBuf on success, n set to NULL on failure.
*/
#if STATS_SUPPORT > 0
#define nGET(n) { \
OS_ENTER_CRITICAL(); \
if (((n) = topNBuf) != NULL) { \
topNBuf = (n)->nextBuf; \
(n)->nextBuf = NULL; \
(n)->nextChain = NULL; \
(n)->data = (n)->body; \
(n)->len = 0; \
(n)->chainLen = 0; \
if (--nBufStats.curFreeBufs.val < nBufStats.minFreeBufs.val) \
nBufStats.minFreeBufs.val = nBufStats.curFreeBufs.val; \
} \
OS_EXIT_CRITICAL(); \
}
#else
#define nGET(n) { \
OS_ENTER_CRITICAL(); \
if (((n) = topNBuf) != NULL) { \
topNBuf = (n)->nextBuf; \
(n)->nextBuf = NULL; \
(n)->nextChain = NULL; \
(n)->data = (n)->body; \
(n)->len = 0; \
(n)->chainLen = 0; \
--curFreeBufs; \
} \
OS_EXIT_CRITICAL(); \
}
#endif
/*
* nFREE - Free a single nBuf and place the successor, if any, in out.
* The value of n is invalid but unchanged. If the buffer is already
* free (nextChain references self), do nothing.
*
* nFree - Free a single nBuf and associated external storage.
* Return the next nBuf in the chain, if any.
*
* nFreeChain - Free all nBufs in a chain.
* Return the next chain in the queue, if any.
*/
#if STATS_SUPPORT > 0
#define nFREE(n, out) { \
OS_ENTER_CRITICAL(); \
if (n) { \
if ((n)->nextChain == (n)) { \
panic("nFREE"); \
} else { \
if (((out) = (n)->nextBuf) != NULL) \
(out)->nextChain = (n)->nextChain; \
(n)->nextBuf = topNBuf; \
topNBuf = (n); \
nBufStats.curFreeBufs.val++; \
} \
} else (out) = NULL; \
OS_EXIT_CRITICAL(); \
}
#else
#define nFREE(n, out) { \
OS_ENTER_CRITICAL(); \
if (n) { \
if ((n)->nextChain == (n)) \
panic("nFREE"); \
else { \
if (((out) = (n)->nextBuf) != NULL) \
(out)->nextChain = (n)->nextChain; \
(n)->nextBuf = topNBuf; \
topNBuf = (n); \
curFreeBufs++; \
} \
} else (out) = NULL; \
OS_EXIT_CRITICAL(); \
}
#endif
NBuf *nFree(NBuf *n);
NBuf *nFreeChain(NBuf *n);
/*
* nALIGN - Position the data pointer of a new nBuf so that it is len bytes
* away from the end of the data area.
*/
#define nALIGN(n, len) ((n)->data = (n)->body + NBUFSZ - (len))
/*
* nADVANCE - Advance the data pointer of a new nBuf so that it is len bytes
* away from the beginning of the data area.
*/
#define nADVANCE(n, len) ((n)->data = (n)->body + (len))
/*
* nLEADINGSPACE - Return the amount of space available before the current
* start of data in an nBuf.
*/
#define nLEADINGSPACE(n) ((n)->len > 0 ? (n)->data - (n)->body : NBUFSZ)
/*
* nTRAILINGSPACE - Return the amount of space available after the end of data
* in an nBuf.
*/
#define nTRAILINGSPACE(n) (NBUFSZ - (u_int)((n)->data - (n)->body) - (n)->len)
/*
* nPREPEND - Prepend plen bytes to nBuf n and load data from s if non-null.
* Note that plen must be <= NBUFSZ.
* If a new nBuf must be allocated but if allocation fails, the original nBuf chain
* is freed and n is set to NULL. Otherwise n is set to the new top of the chain.
* Note that the chain length is updated but the chain is assumed to not be in
* a queue.
*
* nPrepend - Same as above except return the new nBuf chain on success, NULL
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -