/* ********************************************************************************************************* * uC/TCP-IP * The Embedded TCP/IP Suite * * (c) Copyright 2003-2007; Micrium, Inc.; Weston, FL * * All rights reserved. Protected by international copyright laws. * * uC/TCP-IP is provided in source form for FREE evaluation, for educational * use or peaceful research. If you plan on using uC/TCP-IP in a commercial * product you need to contact Micrium to properly license its use in your * product. We provide ALL the source code for your convenience and to help * you experience uC/TCP-IP. The fact that the source code is provided does * NOT mean that you can use it without paying a licensing fee. * * Knowledge of the source code may NOT be used to develop a similar product. * * Please help us continue to provide the Embedded community with the finest * software available. Your honesty is greatly appreciated. ********************************************************************************************************* */ /* ********************************************************************************************************* * * NETWORK BUFFER MANAGEMENT * * Filename : net_buf.c * Version : V1.89 * Programmer(s) : ITJ ********************************************************************************************************* */ /* ********************************************************************************************************* * INCLUDE FILES ********************************************************************************************************* */ #define NET_BUF_MODULE #include /*$PAGE*/ /* ********************************************************************************************************* * LOCAL DEFINES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL CONSTANTS ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL DATA TYPES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL TABLES ********************************************************************************************************* */ /* ********************************************************************************************************* * LOCAL GLOBAL VARIABLES ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * LOCAL FUNCTION PROTOTYPES ********************************************************************************************************* */ #if (NET_BUF_CFG_NBR_SMALL > 0) static void NetBuf_InitSmall(void); #endif #if (NET_BUF_CFG_NBR_LARGE > 0) static void NetBuf_InitLarge(void); #endif static void NetBuf_ClrHdr (NET_BUF_HDR *pbuf_hdr); static void NetBuf_Discard (NET_BUF *pbuf, NET_TYPE type); /* ********************************************************************************************************* * LOCAL CONFIGURATION ERRORS ********************************************************************************************************* */ /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_Init() * * Description : (1) Initialize Network Buffer Management Module : * * (a) Initialize buffers * (b) Initialize buffer error counters * * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : Net_Init(). * * This function is an INTERNAL network protocol suite function & MUST NOT be called by * application function(s). * * Note(s) : none. ********************************************************************************************************* */ void NetBuf_Init (void) { /* -------------------- INIT BUFs --------------------- */ #if (NET_BUF_CFG_NBR_SMALL > 0) NetBuf_InitSmall(); /* Init SMALL bufs. */ #endif #if (NET_BUF_CFG_NBR_LARGE > 0) NetBuf_InitLarge(); /* Init LARGE bufs. */ #endif /* ---------------- INIT BUF ERR CTRS ----------------- */ #if (NET_CTR_CFG_ERR_EN == DEF_ENABLED) NetBuf_ErrNoneAvailCtr = 0; NetBuf_ErrInvalidTypeCtr = 0; NetBuf_ErrSizeCtr = 0; NetBuf_ErrLenCtr = 0; NetBuf_ErrLostCtr = 0; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NetBuf_ErrNullPtrCtr = 0; NetBuf_ErrNotUsedCtr = 0; NetBuf_ErrIxCtr = 0; #endif #endif } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_GetMaxSize() * * Description : Get maximum possible buffer allocation size starting at a specific buffer index. * * Argument(s) : pbuf Pointer to a network buffer. * * ix_start Requested buffer index to store buffer data. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (1) The 'LARGE BUF MAX SIZE' pre-processor conditional does NOT need to verify SMALL * buffer configuration since 'net_buf.h' ensures that NET_BUF_CFG_DATA_SIZE_LARGE * MUST be configured with a value greater than NET_BUF_CFG_DATA_SIZE_SMALL (see * 'net_buf.h CONFIGURATION ERRORS'). * * (2) The 'NO BUFS' pre-processor 'else'-conditional code will never be compiled/linked * since 'net_buf.h' ensures that at least one of the two configuration constants * (NET_BUF_CFG_NBR_SMALL or NET_BUF_CFG_NBR_LARGE) will be configured with a value * greater than zero (see 'net_buf.h CONFIGURATION ERRORS'). The 'else'-conditional * code is included for completeness & as an extra precaution in case 'net_buf.h' is * incorrectly modified. * * (3) Although network buffers' 'Data' buffer declared with an additional CPU word size * (see 'net_buf.h NETWORK BUFFER DATA TYPE Note #4b'), this additional CPU word * size does NOT increase the overall useable network buffer 'Data' size. ********************************************************************************************************* */ /*$PAGE*/ NET_BUF_SIZE NetBuf_GetMaxSize (NET_BUF *pbuf, NET_BUF_SIZE ix_start) { #if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_BUF_HDR *pbuf_hdr; NET_BUF_SIZE max_size; if (pbuf != (NET_BUF *)0) { /* Chk pbuf's max size. */ pbuf_hdr = &pbuf->Hdr; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) switch (pbuf_hdr->Type) { #if (NET_BUF_CFG_NBR_SMALL > 0) case NET_BUF_TYPE_SMALL: #endif #if (NET_BUF_CFG_NBR_LARGE > 0) case NET_BUF_TYPE_LARGE: #endif break; case NET_BUF_TYPE_NONE: default: NET_CTR_ERR_INC(NetBuf_ErrInvalidTypeCtr); return (0); /* Prevent 'break NOT reachable' warning. */ } #endif if (ix_start < pbuf_hdr->Size) { max_size = pbuf_hdr->Size - ix_start; } else { max_size = 0; } } else { /* Else chk buf cfg sizes. */ #if (NET_BUF_CFG_NBR_LARGE > 0) /* ------------ LARGE BUF MAX SIZE ------------ */ if (ix_start < NET_BUF_CFG_DATA_SIZE_LARGE) { max_size = NET_BUF_CFG_DATA_SIZE_LARGE - ix_start; } else { max_size = 0; } #elif (NET_BUF_CFG_NBR_SMALL > 0) /* ------------ SMALL BUF MAX SIZE ------------ */ if (ix_start < NET_BUF_CFG_DATA_SIZE_SMALL) { max_size = NET_BUF_CFG_DATA_SIZE_SMALL - ix_start; } else { max_size = 0; } #else /* ----------------- NO BUFS ------------------ */ /* See Note #2. */ NET_CTR_ERR_INC(NetBuf_ErrSizeCtr); max_size = 0; #endif } return (max_size); } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_Get() * * Description : (1) Allocate & initialize a network buffer of sufficient size : * * (a) Get buffer of sufficient size * (b) Validate buffer * (c) Initialize buffer * (d) Update buffer pool statistics * (e) Return pointer to buffer * OR * Null pointer & error code, on failure * * (2) The buffer pools are implemented as stacks : * * (a) 'NetBuf_SmallPoolPtr'/'NetBuf_LargePoolPtr' point to the heads of the buffer pools. * * (b) Buffers' 'NextBufPtr's link each buffer to form the buffer pool stacks. * * (c) Buffers are inserted & removed at the heads of the buffer pool stacks. * * * Buffers are * inserted & removed * at the head * (see Note #2c) * * | NextBufPtr * | (see Note #2b) * v | * | * ------- ------- v ------- ------- * Buffer Pool ---->| |------>| |------>| |------>| | * Pointer | | | | | | | | * | | | | | | | | * (see Note #2a) ------- ------- ------- ------- * * | | * |<------------ Pool of Free Buffers ----------->| * | (see Note #2) | * * * Argument(s) : size Requested buffer size to store buffer data. * * ix_start Requested buffer index to store buffer data. * * flags Flags to select buffer options; bit-field flags logically OR'd : * * NET_BUF_FLAG_NONE NO buffer flags selected. * NET_BUF_FLAG_CLR_MEM Clear buffer memory (i.e. set each buffer * data octet to 0x00). * * perr Pointer to variable that will receive the return error code from this function : * * NET_BUF_ERR_NONE Network buffer successfully allocated & initialized. * NET_BUF_ERR_INVALID_SIZE Requested size is greater then the maximum buffer * size available. * NET_BUF_ERR_INVALID_LEN Requested size & start index calculation overflows * buffer's DATA area. * NET_BUF_ERR_INVALID_TYPE Network buffer is NOT a valid buffer type. * NET_BUF_ERR_NONE_AVAIL NO available buffers to allocate. * * Return(s) : Pointer to network buffer, if NO errors. * * Pointer to NULL, otherwise. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (3) (a) 'size' & 'ix_start' argument check NOT required unless 'NET_BUF_SIZE's native data * type 'CPU_INT16U' is incorrectly configured as a signed integer in 'cpu.h'. * * (b) 'size' of 0 octets allowed. * * (4) The 'GET BUF : NO BUFS' pre-processor 'else'-conditional code will never be compiled/ * linked since 'net_buf.h' ensures that at least one of the two configuration constants * (NET_BUF_CFG_NBR_SMALL or NET_BUF_CFG_NBR_LARGE) will be configured with a value greater * than zero (see 'net_buf.h CONFIGURATION ERRORS'). The 'else'-conditional code is included * for completeness & as an extra precaution in case 'net_buf.h' is incorrectly modified. * * (5) Buffer memory cleared in NetBuf_Get() instead of in NetBuf_Free() so that the data in * any freed buffer in a buffer pool may be inspected until that buffer is next allocated. ********************************************************************************************************* */ /*$PAGE*/ NET_BUF *NetBuf_Get (NET_BUF_SIZE size, NET_BUF_SIZE ix_start, CPU_INT16U flags, NET_ERR *perr) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NET_TYPE buf_type; #endif NET_BUF_SIZE size_len; NET_STAT_POOL *pbuf_pool_stat; NET_BUF **pbuf_pool; NET_BUF *pbuf; NET_BUF_HDR *pbuf_hdr; CPU_BOOLEAN buf_clr_mem; NET_ERR stat_err; #if 0 /* See Note #3. */ /* ------------------ VALIDATE SIZE ------------------- */ if (size < 0) { /* If neg size or ix req'd, rtn err (see Note #3a). */ NET_CTR_ERR_INC(NetBuf_ErrSizeCtr); *perr = NET_BUF_ERR_INVALID_SIZE; return ((NET_BUF *)0); } if (ix_start < 0) { NET_CTR_ERR_INC(NetBuf_ErrIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return ((NET_BUF *)0); } #endif /*$PAGE*/ /* ----------------- GET BUF ------------------ */ size_len = size + ix_start; /* Calc tot req'd size from start ix. */ /* Discard possible size len ovf's. */ if (size_len < size) { NET_CTR_ERR_INC(NetBuf_ErrLenCtr); *perr = NET_BUF_ERR_INVALID_LEN; return ((NET_BUF *)0); } if (size_len < ix_start) { NET_CTR_ERR_INC(NetBuf_ErrLenCtr); *perr = NET_BUF_ERR_INVALID_LEN; return ((NET_BUF *)0); } #if ((NET_BUF_CFG_NBR_SMALL > 0) && (NET_BUF_CFG_NBR_LARGE > 0)) /* ------------ SMALL & LARGE BUFS ------------ */ if (size_len <= NET_BUF_CFG_DATA_SIZE_SMALL) { /* If size <= SMALL buf, ... */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) buf_type = NET_BUF_TYPE_SMALL; #endif pbuf_pool = (NET_BUF **)&NetBuf_SmallPoolPtr; /* ... get a SMALL buf. */ pbuf_pool_stat = (NET_STAT_POOL *)&NetBuf_SmallPoolStat; } else if (size_len <= NET_BUF_CFG_DATA_SIZE_LARGE) { /* If size <= LARGE buf, ... */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) buf_type = NET_BUF_TYPE_LARGE; #endif pbuf_pool = (NET_BUF **)&NetBuf_LargePoolPtr; /* ... get a LARGE buf. */ pbuf_pool_stat = (NET_STAT_POOL *)&NetBuf_LargePoolStat; } else { /* Else rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrSizeCtr); *perr = NET_BUF_ERR_INVALID_SIZE; return ((NET_BUF *)0); } #elif ((NET_BUF_CFG_NBR_SMALL > 0) && (NET_BUF_CFG_NBR_LARGE == 0)) /* ------------- SMALL BUFS ONLY -------------- */ if (size_len <= NET_BUF_CFG_DATA_SIZE_SMALL) { /* If size <= SMALL buf, ... */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) buf_type = NET_BUF_TYPE_SMALL; #endif pbuf_pool = (NET_BUF **)&NetBuf_SmallPoolPtr; /* ... get a SMALL buf. */ pbuf_pool_stat = (NET_STAT_POOL *)&NetBuf_SmallPoolStat; } else { /* Else rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrSizeCtr); *perr = NET_BUF_ERR_INVALID_SIZE; return ((NET_BUF *)0); } #elif ((NET_BUF_CFG_NBR_SMALL == 0) && (NET_BUF_CFG_NBR_LARGE > 0)) /* ------------- LARGE BUFS ONLY -------------- */ if (size_len <= NET_BUF_CFG_DATA_SIZE_LARGE) { /* If size <= LARGE buf, ... */ #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) buf_type = NET_BUF_TYPE_LARGE; #endif pbuf_pool = (NET_BUF **)&NetBuf_LargePoolPtr; /* ... get a LARGE buf. */ pbuf_pool_stat = (NET_STAT_POOL *)&NetBuf_LargePoolStat; } else { /* Else none avail, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrSizeCtr); *perr = NET_BUF_ERR_INVALID_SIZE; return ((NET_BUF *)0); } #else /* ----------------- NO BUFS ------------------ */ /* See Note #4. */ NET_CTR_ERR_INC(NetBuf_ErrSizeCtr); *perr = NET_BUF_ERR_INVALID_SIZE; return ((NET_BUF *)0); #endif /*$PAGE*/ if (*pbuf_pool != (NET_BUF *)0) { /* If buf pool NOT empty, get buf from pool. */ pbuf = *pbuf_pool; pbuf_hdr = &pbuf->Hdr; *pbuf_pool = (NET_BUF *)pbuf_hdr->NextBufPtr; } else { /* If NO buf avail, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrNoneAvailCtr); *perr = NET_BUF_ERR_NONE_AVAIL; return ((NET_BUF *)0); } #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE BUF ------------------- */ switch (pbuf_hdr->Type) { /* Validate buf Type/Size. */ case NET_BUF_TYPE_SMALL: case NET_BUF_TYPE_LARGE: if (pbuf_hdr->Size < NET_BUF_DATA_SIZE_MIN) { /* If buf size < NET_BUF_DATA_SIZE_MIN, ... */ NetBuf_Discard(pbuf, buf_type); /* ... buf size invalid; discard buf. */ NET_CTR_ERR_INC(NetBuf_ErrSizeCtr); *perr = NET_BUF_ERR_INVALID_SIZE; return ((NET_BUF *)0); } break; case NET_BUF_TYPE_NONE: /* If invalid buf type, discard buf. */ default: NetBuf_Discard(pbuf, NET_BUF_TYPE_NONE); NET_CTR_ERR_INC(NetBuf_ErrInvalidTypeCtr); *perr = NET_BUF_ERR_INVALID_TYPE; return ((NET_BUF *)0); /* Prevent 'break NOT reachable' compiler warning. */ } #endif /* --------------------- INIT BUF --------------------- */ NetBuf_ClrHdr(pbuf_hdr); DEF_BIT_SET(pbuf_hdr->Flags, NET_BUF_FLAG_USED); /* Set buf as used. */ pbuf_hdr->RefCtr = 1; /* Set ref ctr to 1; NetBuf_Get() caller is first ref. */ /* Clr ALL buf data octets to 0x00 (see Note #5). */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) (void)&flags; /* Prevent compiler warning. */ buf_clr_mem = DEF_YES; #else buf_clr_mem = DEF_BIT_IS_SET(flags, NET_BUF_FLAG_CLR_MEM); #endif if (buf_clr_mem == DEF_YES) { DEF_BIT_SET(pbuf_hdr->Flags, NET_BUF_FLAG_CLR_MEM); Mem_Clr((void *)&pbuf->Data[0], (CPU_SIZE_T) pbuf_hdr->Size); } /* --------------- UPDATE BUF POOL STATS -------------- */ NetStat_PoolEntryUsedInc(pbuf_pool_stat, &stat_err); *perr = NET_BUF_ERR_NONE; return (pbuf); /* --------------------- RTN BUF ---------------------- */ } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_Free() * * Description : (1) Free a network buffer : * * (a) Configure buffer free by buffer type * (b) Unlink buffer from network layer(s) See Note #3 * (c) Clear buffer controls * (d) Free buffer back to buffer pool * (e) Update buffer pool statistics * (f) Free IP option buffer See Note #4 * * * Argument(s) : pbuf Pointer to a network buffer. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (2) #### To prevent freeing a buffer already freed via auxiliary pointer(s), NetBuf_Free() * checks the buffer's 'USED' flag BEFORE freeing the buffer. * * This prevention is only best-effort since any invalid duplicate buffer frees MAY be * asynchronous to potentially valid buffer gets. Thus the invalid buffer free(s) MAY * corrupt the buffer's valid operation(s). * * However, since the primary tasks of the network protocol suite are prevented from * running concurrently (see 'net.h Note #2'), it is NOT necessary to protect network * buffer resources from possible corruption since no asynchronous access from other * network tasks is possible. * * (3) If a network buffer's unlink function is available, it is assumed that the function * correctly unlinks the network buffer from any other network layer(s). * * (4) #### Since any single IP packet requires only a single network buffer to receive IP * options (see 'net_ip.c NetIP_RxPktValidate() Note #1bC'), then no more than ONE * network buffer should be linked as an IP options buffer from another buffer. ********************************************************************************************************* */ void NetBuf_Free (NET_BUF *pbuf) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) CPU_BOOLEAN used; #endif NET_BUF_HDR *pbuf_hdr; NET_BUF **pbuf_pool; NET_BUF *pbuf_ip_opt; NET_STAT_POOL *pbuf_pool_stat; CPU_FNCT_PTR unlink_fnct; NET_ERR stat_err; /*$PAGE*/ /* ------------------- VALIDATE PTR ------------------- */ if (pbuf == (NET_BUF *)0) { return; } pbuf_hdr = &pbuf->Hdr; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ---------------- VALIDATE BUF USED ----------------- */ used = DEF_BIT_IS_SET(pbuf_hdr->Flags, NET_BUF_FLAG_USED); if (used != DEF_YES) { /* If buf NOT used, ... */ NET_CTR_ERR_INC(NetBuf_ErrNotUsedCtr); return; /* ... rtn but do NOT free (see Note #2). */ } #endif /* ------------------- CFG BUF FREE ------------------- */ switch (pbuf_hdr->Type) { #if (NET_BUF_CFG_NBR_SMALL > 0) case NET_BUF_TYPE_SMALL: pbuf_pool = (NET_BUF **)&NetBuf_SmallPoolPtr; pbuf_pool_stat = (NET_STAT_POOL *)&NetBuf_SmallPoolStat; break; #endif #if (NET_BUF_CFG_NBR_LARGE > 0) case NET_BUF_TYPE_LARGE: pbuf_pool = (NET_BUF **)&NetBuf_LargePoolPtr; pbuf_pool_stat = (NET_STAT_POOL *)&NetBuf_LargePoolStat; break; #endif case NET_BUF_TYPE_NONE: default: NetBuf_Discard(pbuf, NET_BUF_TYPE_NONE); NET_CTR_ERR_INC(NetBuf_ErrInvalidTypeCtr); return; /* Prevent 'break NOT reachable' compiler warning. */ } pbuf_ip_opt = (NET_BUF *)pbuf_hdr->IP_OptPtr; /* -------------------- UNLINK BUF -------------------- */ unlink_fnct = pbuf_hdr->UnlinkFnctPtr; if (unlink_fnct != (CPU_FNCT_PTR)0) { /* If unlink fnct avail, .. */ unlink_fnct((void *)pbuf); /* .. unlink buf from other layer(s) [see Note #3]. */ } /* ---------------------- CLR BUF --------------------- */ DEF_BIT_CLR(pbuf_hdr->Flags, NET_BUF_FLAG_USED); /* Set buf as NOT used. */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) NetBuf_ClrHdr(pbuf_hdr); #endif /* --------------------- FREE BUF --------------------- */ pbuf_hdr->NextBufPtr = (void *)(*pbuf_pool); *pbuf_pool = (NET_BUF *) pbuf; /* -------------- UPDATE BUF POOL STATS --------------- */ NetStat_PoolEntryUsedDec(pbuf_pool_stat, &stat_err); /* ----------------- FREE IP OPT BUF ------------------ */ NetBuf_Free(pbuf_ip_opt); /* See Note #4. */ } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_FreeBuf() * * Description : Free a network buffer. * * Argument(s) : pbuf Pointer to a network buffer. * * pctr Pointer to possible error counter. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (1) #### Buffers are NOT validated for 'Type' or 'USED' before freeing. * * See also 'NetBuf_Free() Note #2'. * * (2) Buffers may be referenced by multiple layer(s). Therefore, the buffer's reference * counter MUST be checked before freeing the buffer. ********************************************************************************************************* */ void NetBuf_FreeBuf (NET_BUF *pbuf, NET_CTR *pctr) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_BUF_HDR *pbuf_hdr; if (pbuf != (NET_BUF *)0) { pbuf_hdr = &pbuf->Hdr; if (pbuf_hdr->RefCtr > 1) { /* If buf ref'd by multiple layers (see Note #2), ..*/ pbuf_hdr->RefCtr--; /* .. dec buf ref ctr. */ } else { /* Else free buf. */ NetBuf_Free(pbuf); } } if (pctr != (NET_CTR *)0) { /* If avail, ... */ NET_CTR_ERR_INC(*pctr); /* ... inc err ctr. */ } } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_FreeBufList() * * Description : Free a network buffer list. * * (1) Network buffer lists are implemented as doubly-linked lists : * * (a) 'pbuf_list' points to the head of the buffer list. * * (b) Buffer's 'PrevBufPtr' & 'NextBufPtr' doubly-link each buffer in a buffer list. * * * --- Head of ------- * ^ Buffer List ---->| | * | | | * | (see Note #1a) | | * | | | * | | | * | ------- * | | ^ * | | | * | v | * ------- * Buffer List | | * (see Note #1) | | * | | * | | | * | | | * | ------- * | | ^ * | NextBufPtr ---> | | <--- PrevBufPtr * | (see Note #1b) v | (see Note #1b) * | ------- * | | | * v | | * --- ------- * * * Argument(s) : pbuf_list Pointer to a buffer list. * * pctr Pointer to possible error counter. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (2) #### Buffers are NOT validated for 'Type' or 'USED' before freeing. * * See also 'NetBuf_Free() Note #2'. * * (3) Buffers may be referenced by multiple layer(s). Therefore, the buffer's reference * counter MUST be checked before freeing the buffer. * * (4) Buffers NOT freed are unlinked from other buffer fragment lists & compressed within * their own buffer list. Ideally, buffer fragment lists SHOULD NEVER be compressed * but should be unlinked in their entirety. ********************************************************************************************************* */ /*$PAGE*/ void NetBuf_FreeBufList (NET_BUF *pbuf_list, NET_CTR *pctr) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_BUF *pbuf; NET_BUF *pbuf_prev; NET_BUF *pbuf_next; NET_BUF_HDR *pbuf_hdr; NET_BUF_HDR *pbuf_prev_hdr; pbuf = (NET_BUF *)pbuf_list; pbuf_prev = (NET_BUF *)0; while (pbuf != (NET_BUF *)0) { /* Free ALL bufs in buf list. */ pbuf_hdr = &pbuf->Hdr; pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr; #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) pbuf_hdr->PrevPrimListPtr = (void *)0; pbuf_hdr->NextPrimListPtr = (void *)0; #endif if (pbuf_hdr->RefCtr > 1) { /* If buf ref'd by multiple layers (see Note #3), ..*/ pbuf_hdr->RefCtr--; /* .. dec buf ref ctr. */ pbuf_hdr->PrevBufPtr = (void *)pbuf_prev; pbuf_hdr->NextBufPtr = (void *)0; if (pbuf_prev != (NET_BUF *)0) { /* If prev buf non-NULL, ... */ pbuf_prev_hdr = &pbuf_prev->Hdr; pbuf_prev_hdr->NextBufPtr = (void *)pbuf; /* ... set prev buf's next ptr to cur buf. */ } pbuf_prev = (NET_BUF *)pbuf; /* Set cur buf as new prev buf (see Note #4). */ } else { /* Else free buf. */ NetBuf_Free(pbuf); } if (pctr != (NET_CTR *)0) { /* If avail, ... */ NET_CTR_ERR_INC(*pctr); /* ... inc err ctr. */ } pbuf = pbuf_next; } } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_FreeBufQ_PrimList() * * Description : Free a network buffer queue, organized by the buffers' primary buffer lists. * * (1) Network buffer queues are implemented as multiply-linked lists : * * (a) 'pbuf_q' points to the head of the buffer queue. * * (b) Buffers are multiply-linked to form a queue of buffer lists. In the diagram below, * the buffer lists in vertical columns represent buffer fragments & the head fragment * of each buffer list is linked horizontally to form the queue of buffer lists. * * (1) Buffers' 'PrevPrimListPtr' & 'NextPrimListPtr' doubly-link each buffer list's * head buffer to form the queue of buffer lists. * * (2) Buffer's 'PrevBufPtr' & 'NextBufPtr' doubly-link each buffer in a * buffer list. * * * | | * |<--------------- Buffer Queue ---------------->| * | (see Note #1) | * * NextPrimListPtr * (see Note #1b1) * | * | * --- Head of ------- ------- v ------- ------- * ^ Buffer ---->| |------>| |------>| |------>| | * | Queue | | | | | | | | * | | |<------| |<------| |<------| | * | (see Note #1a) | | | | ^ | | | | * | | | | | | | | | | * | ------- ------- | ------- ------- * | | ^ | | ^ * | | | PrevPrimListPtr | | * | v | (see Note #1b1) v | * | ------- ------- * | | | | * Fragments in the | | | | * same Buffer List | | | | * (see Note #1b) | | | | * | | | | * | ------- ------- * | | ^ | ^ * | NextBufPtr ---> | | <--- PrevBufPtr | | * | (see Note #1b2) v | (see Note #1b2) v | * | ------- ------- * | | | | | * | | | | | * | | | ------- * | | | * v | | * --- ------- * * * Argument(s) : pbuf_q Pointer to a buffer queue. * * pctr Pointer to possible error counter. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (2) #### Buffers are NOT validated for 'Type' or 'USED' before freeing. * * See also 'NetBuf_Free() Note #2'. * * (3) Buffers may be referenced by multiple layer(s). Therefore, the buffers' reference * counters MUST be checked before freeing the buffer(s). * * (4) Buffers NOT freed are unlinked from other buffer fragment lists & compressed within * their own buffer list. Ideally, buffer fragment lists SHOULD NEVER be compressed * but should be unlinked in their entirety. ********************************************************************************************************* */ /*$PAGE*/ void NetBuf_FreeBufQ_PrimList (NET_BUF *pbuf_q, NET_CTR *pctr) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_BUF *pbuf_list; NET_BUF *pbuf_list_next; NET_BUF *pbuf; NET_BUF *pbuf_prev; NET_BUF *pbuf_next; NET_BUF_HDR *pbuf_hdr; pbuf_list = pbuf_q; while (pbuf_list != (NET_BUF *)0) { /* Free ALL buf lists in buf Q. */ pbuf_hdr = &pbuf_list->Hdr; pbuf_list_next = (NET_BUF *)pbuf_hdr->NextPrimListPtr; pbuf_hdr->PrevPrimListPtr = (void *)0; pbuf_hdr->NextPrimListPtr = (void *)0; pbuf = (NET_BUF *)pbuf_list; pbuf_prev = (NET_BUF *)0; while (pbuf != (NET_BUF *)0) { /* Free ALL bufs in buf list. */ pbuf_hdr = &pbuf->Hdr; pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr; #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) pbuf_hdr->PrevPrimListPtr = (void *)0; pbuf_hdr->NextPrimListPtr = (void *)0; #endif if (pbuf_hdr->RefCtr > 1) { /* If buf ref'd by multiple layers (see Note #3), ..*/ pbuf_hdr->RefCtr--; /* .. dec buf ref ctr. */ pbuf_hdr->PrevBufPtr = (void *)pbuf_prev; pbuf_hdr->NextBufPtr = (void *)0; if (pbuf_prev != (NET_BUF *)0) { /* If prev buf non-NULL, ... */ pbuf_hdr = &pbuf_prev->Hdr; pbuf_hdr->NextBufPtr = (void *)pbuf; /* ... set prev buf's next ptr to cur buf. */ } pbuf_prev = (NET_BUF *)pbuf; /* Set cur buf as new prev buf (see Note #4). */ } else { /* Else free buf. */ NetBuf_Free(pbuf); } if (pctr != (NET_CTR *)0) { /* If avail, ... */ NET_CTR_ERR_INC(*pctr); /* ... inc err ctr. */ } pbuf = pbuf_next; } pbuf_list = pbuf_list_next; } } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_FreeBufQ_SecList() * * Description : Free a network buffer queue, organized by the buffers' secondary buffer lists. * * (1) Network buffer queues are implemented as multiply-linked lists : * * (a) 'pbuf_q' points to the head of the buffer queue. * * (b) Buffers are multiply-linked to form a queue of buffer lists. In the diagram below, * the buffer lists in vertical columns represent buffer fragments & the head fragment * of each buffer list is linked horizontally to form the queue of buffer lists. * * (1) Buffers' 'PrevSecListPtr' & 'NextSecListPtr' doubly-link each buffer list's * head buffer to form the queue of buffer lists. * * (2) Buffer's 'PrevBufPtr' & 'NextBufPtr' doubly-link each buffer in a * buffer list. * * * | | * |<--------------- Buffer Queue ---------------->| * | (see Note #1) | * * NextSecListPtr * (see Note #1b1) * | * | * --- Head of ------- ------- v ------- ------- * ^ Buffer ---->| |------>| |------>| |------>| | * | Queue | | | | | | | | * | | |<------| |<------| |<------| | * | (see Note #1a) | | | | ^ | | | | * | | | | | | | | | | * | ------- ------- | ------- ------- * | | ^ | | ^ * | | | PrevSecListPtr | | * | v | (see Note #1b1) v | * | ------- ------- * | | | | * Fragments in the | | | | * same Buffer List | | | | * (see Note #1b) | | | | * | | | | * | ------- ------- * | | ^ | ^ * | NextBufPtr ---> | | <--- PrevBufPtr | | * | (see Note #1b2) v | (see Note #1b2) v | * | ------- ------- * | | | | | * | | | | | * | | | ------- * | | | * v | | * --- ------- * * * Argument(s) : pbuf_q Pointer to a buffer queue. * * pctr Pointer to possible error counter. * * pfnct_unlink Pointer to possible unlink funcion. * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (2) #### Buffers are NOT validated for 'Type' or 'USED' before freeing. * * See also 'NetBuf_Free() Note #2'. * * (3) Buffers may be referenced by multiple layer(s). Therefore, the buffers' reference * counters MUST be checked before freeing the buffer(s). * * (4) Buffers NOT freed are unlinked from other buffer fragment lists & compressed within * their own buffer list. Ideally, buffer fragment lists SHOULD NEVER be compressed * but should be unlinked in their entirety. * * (5) Since buffers' unlink functions are intended to unlink a buffer from a secondary * buffer queue list; the secondary buffer queue list's unlink function MUST be cleared * before freeing the buffer to avoid unlinking the buffer(s) from the secondary buffer * queue list multiple times. * * See also 'NetBuf_Free() Note #3'. ********************************************************************************************************* */ /*$PAGE*/ void NetBuf_FreeBufQ_SecList (NET_BUF *pbuf_q, NET_CTR *pctr, CPU_FNCT_PTR pfnct_unlink) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_BUF *pbuf_list; NET_BUF *pbuf_list_next; NET_BUF *pbuf; NET_BUF *pbuf_prev; NET_BUF *pbuf_next; NET_BUF_HDR *pbuf_hdr; pbuf_list = pbuf_q; while (pbuf_list != (NET_BUF *)0) { /* Free ALL buf lists in buf Q. */ pbuf_hdr = &pbuf_list->Hdr; pbuf_list_next = (NET_BUF *)pbuf_hdr->NextSecListPtr; pbuf = (NET_BUF *)pbuf_list; pbuf_prev = (NET_BUF *)0; while (pbuf != (NET_BUF *)0) { /* Free ALL bufs in buf list. */ pbuf_hdr = &pbuf->Hdr; pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr; /* Clr unlink ptrs (see Note #5). */ if (pbuf_hdr->UnlinkFnctPtr == (CPU_FNCT_PTR)pfnct_unlink) { pbuf_hdr->UnlinkFnctPtr = (CPU_FNCT_PTR)0; pbuf_hdr->UnlinkObjPtr = (void *)0; } if (pbuf_hdr->RefCtr > 1) { /* If buf ref'd by multiple layers (see Note #3), ..*/ pbuf_hdr->RefCtr--; /* .. dec buf ref ctr. */ pbuf_hdr->PrevBufPtr = (void *)pbuf_prev; pbuf_hdr->NextBufPtr = (void *)0; if (pbuf_prev != (NET_BUF *)0) { /* If prev buf non-NULL, ... */ pbuf_hdr = &pbuf_prev->Hdr; pbuf_hdr->NextBufPtr = (void *)pbuf; /* ... set prev buf's next ptr to cur buf. */ } pbuf_prev = (NET_BUF *)pbuf; /* Set cur buf as new prev buf (see Note #4). */ } else { /* Else free buf. */ NetBuf_Free(pbuf); } if (pctr != (NET_CTR *)0) { /* If avail, ... */ NET_CTR_ERR_INC(*pctr); /* ... inc err ctr. */ } pbuf = pbuf_next; } pbuf_list = pbuf_list_next; } } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_DataRd() * * Description : (1) Read data from network buffer's DATA area : * * (a) Validate data read index & size * (b) Read data from buffer * * * Argument(s) : pbuf Pointer to a network buffer. * * ix Index into buffer's DATA area. * * len Number of octets to read (see Note #2). * * pdest Pointer to destination to read data into (see Note #3). * * perr Pointer to variable that will receive the return error code from this function : * * NET_BUF_ERR_NONE Read from DATA area successful. * NET_BUF_ERR_NULL_PTR Argument 'pbuf'/'pdest' passed a NULL pointer. * NET_BUF_ERR_INVALID_TYPE Argument 'pbuf's TYPE is invalid or unknown. * NET_BUF_ERR_INVALID_IX Invalid index (outside buffer's DATA area). * NET_BUF_ERR_INVALID_LEN Invalid length (outside buffer's DATA area). * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (2) Data read of 0 octets allowed. * * (3) Destination buffer size NOT validated; buffer overruns MUST be prevented by caller. * * (4) 'ix' & 'len' argument check NOT required unless 'NET_BUF_SIZE's native data type * 'CPU_INT16U' is incorrectly configured as a signed integer in 'cpu.h'. * * (5) Buffer 'Size' is NOT re-validated; validated in NetBuf_Get(). ********************************************************************************************************* */ /*$PAGE*/ void NetBuf_DataRd (NET_BUF *pbuf, NET_BUF_SIZE ix, NET_BUF_SIZE len, CPU_INT08U *pdest, NET_ERR *perr) { #if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NET_BUF_HDR *pbuf_hdr; NET_BUF_SIZE len_data; #endif CPU_INT08U *p_data; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------ VALIDATE PTR -------------------- */ if (pbuf == (NET_BUF *)0) { NET_CTR_ERR_INC(NetBuf_ErrNullPtrCtr); *perr = NET_BUF_ERR_NULL_PTR; return; } /* ------------------ VALIDATE TYPE ------------------- */ pbuf_hdr = &pbuf->Hdr; switch (pbuf_hdr->Type) { #if (NET_BUF_CFG_NBR_SMALL > 0) case NET_BUF_TYPE_SMALL: #endif #if (NET_BUF_CFG_NBR_LARGE > 0) case NET_BUF_TYPE_LARGE: #endif break; case NET_BUF_TYPE_NONE: default: NET_CTR_ERR_INC(NetBuf_ErrInvalidTypeCtr); *perr = NET_BUF_ERR_INVALID_TYPE; return; /* Prevent 'break NOT reachable' compiler warning. */ } #endif /*$PAGE*/ /* ----------------- VALIDATE IX/SIZE ----------------- */ #if 0 /* See Note #4. */ if (ix < 0) { /* If req'd ix < 0, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } if (len < 0) { /* If req'd len < 0, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrLenCtr); *perr = NET_BUF_ERR_INVALID_LEN; return; } #endif if (len == 0) { /* If req'd len = 0, rtn null rd (see Note #2). */ *perr = NET_BUF_ERR_NONE; return; } #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ----------------- VALIDATE DEST PTR ---------------- */ if (pdest == (CPU_INT08U *)0) { NET_CTR_ERR_INC(NetBuf_ErrNullPtrCtr); *perr = NET_BUF_ERR_NULL_PTR; return; } /* ----------------- VALIDATE IX/SIZE ----------------- */ if (ix >= pbuf_hdr->Size) { /* If req'd ix > size, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } len_data = ix + len; if (len_data > pbuf_hdr->Size) { /* If req'd len > size, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrLenCtr); *perr = NET_BUF_ERR_INVALID_LEN; return; } #endif /* ------------------- RD BUF DATA -------------------- */ /* Req'd ix & len within buf DATA area, ... */ p_data = &pbuf->Data[ix]; /* ... set ptr to ix into buf DATA area, ... */ Mem_Copy((void *)pdest, /* ... & copy len nbr DATA buf octets to dest. */ (void *)p_data, (CPU_SIZE_T)len); *perr = NET_BUF_ERR_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_DataWr() * * Description : (1) Write data into network buffer's DATA area : * * (a) Validate data write index & size * (b) Write data into buffer * * * Argument(s) : pbuf Pointer to a network buffer. * * ix Index into buffer's DATA area. * * len Number of octets to write (see Note #2). * * psrc Pointer to data to write. * * perr Pointer to variable that will receive the return error code from this function : * * NET_BUF_ERR_NONE Write to DATA area successful. * NET_BUF_ERR_NULL_PTR Argument 'pbuf'/'psrc' passed a NULL pointer. * NET_BUF_ERR_INVALID_TYPE Argument 'pbuf's TYPE is invalid or unknown. * NET_BUF_ERR_INVALID_IX Invalid index (outside buffer's DATA area). * NET_BUF_ERR_INVALID_LEN Invalid length (outside buffer's DATA area). * * Return(s) : none. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (2) Data write of 0 octets allowed. * * (3) 'ix' & 'len' argument check NOT required unless 'NET_BUF_SIZE's native data type * 'CPU_INT16U' is incorrectly configured as a signed integer in 'cpu.h'. * * (4) Buffer 'Size' is NOT re-validated; validated in NetBuf_Get(). ********************************************************************************************************* */ /*$PAGE*/ void NetBuf_DataWr (NET_BUF *pbuf, NET_BUF_SIZE ix, NET_BUF_SIZE len, CPU_INT08U *psrc, NET_ERR *perr) { #if ((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \ (NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) NET_BUF_HDR *pbuf_hdr; NET_BUF_SIZE len_data; #endif CPU_INT08U *p_data; #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------ VALIDATE PTR -------------------- */ if (pbuf == (NET_BUF *)0) { NET_CTR_ERR_INC(NetBuf_ErrNullPtrCtr); *perr = NET_BUF_ERR_NULL_PTR; return; } /* ------------------ VALIDATE TYPE ------------------- */ pbuf_hdr = &pbuf->Hdr; switch (pbuf_hdr->Type) { #if (NET_BUF_CFG_NBR_SMALL > 0) case NET_BUF_TYPE_SMALL: #endif #if (NET_BUF_CFG_NBR_LARGE > 0) case NET_BUF_TYPE_LARGE: #endif break; case NET_BUF_TYPE_NONE: default: NET_CTR_ERR_INC(NetBuf_ErrInvalidTypeCtr); *perr = NET_BUF_ERR_INVALID_TYPE; return; /* Prevent 'break NOT reachable' compiler warning. */ } #endif /*$PAGE*/ /* ----------------- VALIDATE IX/SIZE ----------------- */ #if 0 /* See Note #3. */ if (ix < 0) { /* If req'd ix < 0, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } if (len < 0) { /* If req'd len < 0, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrLenCtr); *perr = NET_BUF_ERR_INVALID_LEN; return; } #endif if (len == 0) { /* If req'd len = 0, rtn null wr (see Note #2). */ *perr = NET_BUF_ERR_NONE; return; } #if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ----------------- VALIDATE SRC PTR ----------------- */ if (psrc == (CPU_INT08U *)0) { NET_CTR_ERR_INC(NetBuf_ErrNullPtrCtr); *perr = NET_BUF_ERR_NULL_PTR; return; } /* ----------------- VALIDATE IX/SIZE ----------------- */ if (ix >= pbuf_hdr->Size) { /* If req'd ix > size, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrIxCtr); *perr = NET_BUF_ERR_INVALID_IX; return; } len_data = ix + len; if (len_data > pbuf_hdr->Size) { /* If req'd len > size, rtn err. */ NET_CTR_ERR_INC(NetBuf_ErrLenCtr); *perr = NET_BUF_ERR_INVALID_LEN; return; } #endif /* ------------------- WR BUF DATA -------------------- */ /* Req'd ix & len within buf DATA area, ... */ p_data = &pbuf->Data[ix]; /* ... set ptr to ix into buf DATA area, ... */ Mem_Copy((void *)p_data, /* ... & copy len nbr src octets into DATA buf. */ (void *)psrc, (CPU_SIZE_T)len); *perr = NET_BUF_ERR_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_IsUsed() * * Description : Validate buffer in use. * * Argument(s) : pbuf Pointer to object to validate as a network buffer in use. * * Return(s) : DEF_YES, buffer valid & in use. * * DEF_NO, buffer invalid or NOT in use. * * Caller(s) : various. * * This function is an INTERNAL network protocol suite function & SHOULD NOT be called by * application function(s). * * Note(s) : (1) NetBuf_IsUsed() MUST be called with the global network lock already acquired. ********************************************************************************************************* */ CPU_BOOLEAN NetBuf_IsUsed (NET_BUF *pbuf) { NET_BUF_HDR *pbuf_hdr; CPU_BOOLEAN used; /* ------------------ VALIDATE PTR -------------------- */ if (pbuf == (NET_BUF *)0) { return (DEF_NO); } /* ------------------ VALIDATE TYPE ------------------- */ pbuf_hdr = &pbuf->Hdr; switch (pbuf_hdr->Type) { #if (NET_BUF_CFG_NBR_SMALL > 0) case NET_BUF_TYPE_SMALL: #endif #if (NET_BUF_CFG_NBR_LARGE > 0) case NET_BUF_TYPE_LARGE: #endif break; case NET_BUF_TYPE_NONE: default: return (DEF_NO); /* Prevent 'break NOT reachable' compiler warning. */ } /* ---------------- VALIDATE BUF USED ----------------- */ used = DEF_BIT_IS_SET(pbuf_hdr->Flags, NET_BUF_FLAG_USED); return (used); } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_SmallPoolStatGet() * * Description : Get SMALL network buffer statistics pool. * * Argument(s) : none. * * Return(s) : SMALL network buffer statistics pool, if NO errors. * * NULL statistics pool, otherwise. * * Caller(s) : Application. * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). * * Note(s) : (1) NetBuf_SmallPoolStatGet() blocked until network initialization completes; return NULL * statistics pool. ********************************************************************************************************* */ #if (NET_BUF_CFG_NBR_SMALL > 0) NET_STAT_POOL NetBuf_SmallPoolStatGet (void) { #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) NET_ERR err; #endif NET_STAT_POOL stat_pool; #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) if (Net_InitDone != DEF_YES) { /* If init NOT complete, ... */ NetStat_PoolClr(&stat_pool, &err); return (stat_pool); /* ... rtn NULL stat pool (see Note #1). */ } #endif CPU_CRITICAL_ENTER(); stat_pool = NetBuf_SmallPoolStat; CPU_CRITICAL_EXIT(); return (stat_pool); } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_SmallPoolStatResetMaxUsed() * * Description : Reset SMALL network buffer statistics pool's maximum number of entries used. * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : Application. * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). * * Note(s) : none. ********************************************************************************************************* */ #if (NET_BUF_CFG_NBR_SMALL > 0) void NetBuf_SmallPoolStatResetMaxUsed (void) { NET_ERR err; NetStat_PoolResetUsedMax(&NetBuf_SmallPoolStat, &err); } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_LargePoolStatGet() * * Description : Get LARGE network buffer statistics pool. * * Argument(s) : none. * * Return(s) : LARGE network buffer statistics pool, if NO errors. * * NULL statistics pool, otherwise. * * Caller(s) : Application. * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). * * Note(s) : (1) NetBuf_LargePoolStatGet() blocked until network initialization completes; return NULL * statistics pool. ********************************************************************************************************* */ #if (NET_BUF_CFG_NBR_LARGE > 0) NET_STAT_POOL NetBuf_LargePoolStatGet (void) { #if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL) CPU_SR cpu_sr; #endif #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) NET_ERR err; #endif NET_STAT_POOL stat_pool; #if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) if (Net_InitDone != DEF_YES) { /* If init NOT complete, ... */ NetStat_PoolClr(&stat_pool, &err); return (stat_pool); /* ... rtn NULL stat pool (see Note #1). */ } #endif CPU_CRITICAL_ENTER(); stat_pool = NetBuf_LargePoolStat; CPU_CRITICAL_EXIT(); return (stat_pool); } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_LargePoolStatResetMaxUsed() * * Description : Reset LARGE network buffer statistics pool's maximum number of entries used. * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : Application. * * This function is a network protocol suite application interface (API) function & MAY be * called by application function(s). * * Note(s) : none. ********************************************************************************************************* */ #if (NET_BUF_CFG_NBR_LARGE > 0) void NetBuf_LargePoolStatResetMaxUsed (void) { NET_ERR err; NetStat_PoolResetUsedMax(&NetBuf_LargePoolStat, &err); } #endif /*$PAGE*/ /* ********************************************************************************************************* ********************************************************************************************************* * LOCAL FUNCTIONS ********************************************************************************************************* ********************************************************************************************************* */ /* ********************************************************************************************************* * NetBuf_InitSmall() * * Description : (1) Initialize SMALL buffers & buffer pool : * * (a) Initialize SMALL buffer pool * (b) Initialize SMALL buffer table * * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetBuf_Init(). * * Note(s) : (2) SMALL buffer pool MUST be initialized PRIOR to initializing the pool with pointers to * SMALL buffers. ********************************************************************************************************* */ #if (NET_BUF_CFG_NBR_SMALL > 0) static void NetBuf_InitSmall (void) { NET_BUF_SMALL *pbuf; NET_BUF_HDR *pbuf_hdr; NET_BUF_QTY i; NET_ERR err; /* ------------------- INIT BUF POOL ------------------ */ NetBuf_SmallPoolPtr = (NET_BUF_SMALL *)0; /* Init-clr SMALL buf pool (see Note #2). */ NetStat_PoolInit((NET_STAT_POOL *)&NetBuf_SmallPoolStat, (NET_STAT_POOL_QTY) NET_BUF_CFG_NBR_SMALL, (NET_ERR *)&err); /* ------------------- INIT BUF TBL ------------------- */ pbuf = &NetBuf_SmallTbl[0]; for (i = 0; i < NET_BUF_CFG_NBR_SMALL; i++) { pbuf_hdr = &pbuf->Hdr; pbuf_hdr->Type = NET_BUF_TYPE_SMALL; /* Init each SMALL buf type/size/id--NEVER modify. */ pbuf_hdr->Size = NET_BUF_CFG_DATA_SIZE_SMALL; pbuf_hdr->ID = (NET_BUF_QTY)i; pbuf_hdr->Flags = NET_BUF_FLAG_NONE; /* Init each buf as NOT used. */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) NetBuf_ClrHdr(pbuf_hdr); Mem_Clr((void *)&pbuf->Data[0], (CPU_SIZE_T) pbuf_hdr->Size); #endif /* Free each buf to SMALL buf pool (see Note #2). */ pbuf_hdr->NextBufPtr = (void *)NetBuf_SmallPoolPtr; NetBuf_SmallPoolPtr = (NET_BUF_SMALL *)pbuf; pbuf++; } } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_InitLarge() * * Description : (1) Initialize LARGE buffers & buffer pool : * * (a) Initialize LARGE buffer pool * (b) Initialize LARGE buffer table * * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : NetBuf_Init(). * * Note(s) : (2) LARGE buffer pool MUST be initialized PRIOR to initializing the pool with pointers to * LARGE buffers. ********************************************************************************************************* */ #if (NET_BUF_CFG_NBR_LARGE > 0) static void NetBuf_InitLarge (void) { NET_BUF_LARGE *pbuf; NET_BUF_HDR *pbuf_hdr; NET_BUF_QTY i; NET_ERR err; /* ------------------- INIT BUF POOL ------------------ */ NetBuf_LargePoolPtr = (NET_BUF_LARGE *)0; /* Init-clr LARGE buf pool (see Note #2). */ NetStat_PoolInit((NET_STAT_POOL *)&NetBuf_LargePoolStat, (NET_STAT_POOL_QTY) NET_BUF_CFG_NBR_LARGE, (NET_ERR *)&err); /* ------------------- INIT BUF TBL ------------------- */ pbuf = &NetBuf_LargeTbl[0]; for (i = 0; i < NET_BUF_CFG_NBR_LARGE; i++) { pbuf_hdr = &pbuf->Hdr; pbuf_hdr->Type = NET_BUF_TYPE_LARGE; /* Init each LARGE buf type/size/id--NEVER modify. */ pbuf_hdr->Size = NET_BUF_CFG_DATA_SIZE_LARGE; pbuf_hdr->ID = (NET_BUF_QTY)i; pbuf_hdr->Flags = NET_BUF_FLAG_NONE; /* Init each buf as NOT used. */ #if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) NetBuf_ClrHdr(pbuf_hdr); Mem_Clr((void *)&pbuf->Data[0], (CPU_SIZE_T) pbuf_hdr->Size); #endif /* Free each buf to LARGE buf pool (see Note #2). */ pbuf_hdr->NextBufPtr = (void *)NetBuf_LargePoolPtr; NetBuf_LargePoolPtr = (NET_BUF_LARGE *)pbuf; pbuf++; } } #endif /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_ClrHdr() * * Description : Clear network buffer header controls. * * Argument(s) : pbuf_hdr Pointer to network buffer header. * -------- Argument validated in NetBuf_Get(), * NetBuf_Free(), * NetBuf_InitSmall(), * NetBuf_InitLarge(). * * Return(s) : none. * * Caller(s) : NetBuf_Get(), * NetBuf_Free(), * NetBuf_InitSmall(), * NetBuf_InitLarge(). * * Note(s) : none. ********************************************************************************************************* */ /*$PAGE*/ static void NetBuf_ClrHdr (NET_BUF_HDR *pbuf_hdr) { pbuf_hdr->PrevPrimListPtr = (void *)0; pbuf_hdr->NextPrimListPtr = (void *)0; pbuf_hdr->PrevSecListPtr = (void *)0; pbuf_hdr->NextSecListPtr = (void *)0; pbuf_hdr->PrevBufPtr = (void *)0; pbuf_hdr->NextBufPtr = (void *)0; pbuf_hdr->TmrPtr = (NET_TMR *)0; pbuf_hdr->UnlinkFnctPtr = (CPU_FNCT_PTR)0; pbuf_hdr->UnlinkObjPtr = (void *)0; pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_NONE; pbuf_hdr->IF_HdrIx = NET_BUF_IX_NONE; pbuf_hdr->IF_HdrLen = 0; pbuf_hdr->IF_DataLenMin = 0; #ifdef NET_ARP_MODULE_PRESENT pbuf_hdr->ARP_MsgIx = NET_BUF_IX_NONE; pbuf_hdr->ARP_MsgLen = 0; #endif pbuf_hdr->IP_HdrIx = NET_BUF_IX_NONE; pbuf_hdr->IP_HdrLen = 0; pbuf_hdr->ICMP_MsgIx = NET_BUF_IX_NONE; pbuf_hdr->ICMP_MsgLen = 0; pbuf_hdr->ICMP_HdrLen = 0; pbuf_hdr->TCP_UDP_HdrDataIx = NET_BUF_IX_NONE; pbuf_hdr->TCP_UDP_HdrLen = 0; pbuf_hdr->DataIx = NET_BUF_IX_NONE; pbuf_hdr->DataLen = 0; pbuf_hdr->TotLen = 0; #ifdef NET_ARP_MODULE_PRESENT pbuf_hdr->ARP_AddrHW_Ptr = (CPU_INT08U *)0; pbuf_hdr->ARP_AddrProtocolPtr = (CPU_INT08U *)0; #endif pbuf_hdr->IP_TotLen = 0; pbuf_hdr->IP_DataLen = 0; pbuf_hdr->IP_DatagramLen = 0; pbuf_hdr->IP_ID = NET_IP_ID_NONE; pbuf_hdr->IP_Flags_FragOffset = NET_IP_HDR_FLAG_NONE | NET_IP_HDR_FRAG_OFFSET_NONE; pbuf_hdr->IP_FragSizeTot = NET_IP_FRAG_SIZE_NONE; pbuf_hdr->IP_FragSizeCur = 0; pbuf_hdr->IP_AddrSrc = NET_IP_ADDR_NONE; pbuf_hdr->IP_AddrDest = NET_IP_ADDR_NONE; pbuf_hdr->IP_AddrNextHop = NET_IP_ADDR_NONE; pbuf_hdr->IP_AddrNextHopNetOrder = (CPU_INT32U)NET_UTIL_HOST_TO_NET_32(NET_IP_ADDR_NONE); pbuf_hdr->IP_OptPtr = (void *)0; pbuf_hdr->TCP_UDP_TotLen = 0; pbuf_hdr->TCP_UDP_DataLen = 0; pbuf_hdr->TCP_UDP_PortSrc = NET_PORT_NBR_NONE; pbuf_hdr->TCP_UDP_PortDest = NET_PORT_NBR_NONE; #ifdef NET_TCP_MODULE_PRESENT pbuf_hdr->TCP_HdrLen_Flags = NET_TCP_HDR_LEN_NONE | NET_TCP_HDR_FLAG_NONE; pbuf_hdr->TCP_SegLenInit = 0; pbuf_hdr->TCP_SegLenLast = 0; pbuf_hdr->TCP_SegLen = 0; pbuf_hdr->TCP_SegLenData = 0; pbuf_hdr->TCP_SegReTxCtr = 0; pbuf_hdr->TCP_SegSync = DEF_NO; pbuf_hdr->TCP_SegClose = DEF_NO; pbuf_hdr->TCP_SegReset = DEF_NO; pbuf_hdr->TCP_SegAck = DEF_NO; pbuf_hdr->TCP_SegAckTxd = DEF_NO; pbuf_hdr->TCP_SegAckTxReqCode = NET_TCP_CONN_TX_ACK_NONE; pbuf_hdr->TCP_SeqNbrInit = NET_TCP_SEQ_NBR_NONE; pbuf_hdr->TCP_SeqNbrLast = NET_TCP_SEQ_NBR_NONE; pbuf_hdr->TCP_SeqNbr = NET_TCP_SEQ_NBR_NONE; pbuf_hdr->TCP_AckNbr = NET_TCP_ACK_NBR_NONE; pbuf_hdr->TCP_AckNbrLast = NET_TCP_ACK_NBR_NONE; pbuf_hdr->TCP_MaxSegSize = NET_TCP_MAX_SEG_SIZE_NONE; pbuf_hdr->TCP_WinSize = NET_TCP_WIN_SIZE_NONE; pbuf_hdr->TCP_WinSizeLast = NET_TCP_WIN_SIZE_NONE; pbuf_hdr->TCP_RTT_TS_Rxd_ms = NET_TCP_TX_RTT_TS_NONE; pbuf_hdr->TCP_RTT_TS_Txd_ms = NET_TCP_TX_RTT_TS_NONE; pbuf_hdr->TCP_Flags = NET_TCP_FLAG_NONE; #endif #ifdef NET_CONN_MODULE_PRESENT pbuf_hdr->Conn_ID = NET_CONN_ID_NONE; pbuf_hdr->Conn_ID_Transport = NET_CONN_ID_NONE; pbuf_hdr->Conn_ID_App = NET_CONN_ID_NONE; pbuf_hdr->ConnType = NET_CONN_TYPE_CONN_NONE; #endif pbuf_hdr->RefCtr = 0; pbuf_hdr->Flags = NET_BUF_FLAG_NONE; } /*$PAGE*/ /* ********************************************************************************************************* * NetBuf_Discard() * * Description : (1) Discard an invalid/corrupted network buffer from available buffer pools : * * (a) Discard timer from available timer pool * (b) Update timer pool statistics * * (2) Assumes buffer is invalid/corrupt & MUST be removed. Buffer removed simply by NOT * returning the buffer back to any buffer pool. * * * Argument(s) : pbuf Pointer to an invalid/corrupt network buffer. * ---- Argument checked in NetBuf_Get(), * NetBuf_Free(). * Argument validated in NetBuf_InitSmall(), * NetBuf_InitLarge(). * * type Buffer type : * * NET_BUF_TYPE_NONE Buffer TYPE unknown. * NET_BUF_TYPE_SMALL Buffer TYPE SMALL. * NET_BUF_TYPE_LARGE Buffer TYPE LARGE. * * Return(s) : none. * * Caller(s) : NetBuf_Get(), * NetBuf_Free(). * * Note(s) : (3) If buffer 'Type' is unknown, it cannot be determined which buffer pool, SMALL or LARGE, * lost the buffer. The unrecoverable buffer will remain unaccounted for in one of the * buffer pool's 'Used' entries. ********************************************************************************************************* */ static void NetBuf_Discard (NET_BUF *pbuf, NET_TYPE type) { #if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \ (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)) CPU_SR cpu_sr; #endif NET_ERR stat_err; /* ------------------- DISCARD BUF -------------------- */ (void)&pbuf; /* Prevent compiler warning (see Note #2). */ /* --------------- UPDATE DISCARD STATS --------------- */ switch (type) { #if (NET_BUF_CFG_NBR_SMALL > 0) case NET_BUF_TYPE_SMALL: /* Discard SMALL corrupt buf. */ NetStat_PoolEntryLostInc(&NetBuf_SmallPoolStat, &stat_err); break; #endif #if (NET_BUF_CFG_NBR_LARGE > 0) case NET_BUF_TYPE_LARGE: /* Discard LARGE corrupt buf. */ NetStat_PoolEntryLostInc(&NetBuf_LargePoolStat, &stat_err); break; #endif case NET_BUF_TYPE_NONE: /* If type unknown, NO buf pool updated (see Note #3). */ default: NET_CTR_ERR_INC(NetBuf_ErrLostCtr); break; } }