changer/OS/uc/tcpip/Source/net_arp.c
Dmitriy 5fe1e5d358 первый коммит
первый коммит
2021-02-08 21:10:39 +03:00

3884 lines
171 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
*********************************************************************************************************
* 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 ARP LAYER
* (ADDRESS RESOLUTION PROTOCOL)
*
* Filename : net_arp.c
* Version : V1.89
* Programmer(s) : ITJ
*********************************************************************************************************
* Note(s) : (1) Address Resolution Protocol ONLY required for network interfaces that require
* network-address-to-hardware-address bindings (see RFC #826 'Abstract').
*
* (2) Supports Address Resolution Protocol as described in RFC #826 with the following
* restrictions/constraints :
*
* (a) ONLY supports the following hardware types :
* (1) 48-bit Ethernet
*
* (b) ONLY supports the following protocol types :
* (1) 32-bit IP
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE FILES
*********************************************************************************************************
*/
#define NET_ARP_MODULE
#include <net.h>
/*
*********************************************************************************************************
* MODULE
*
* Note(s) : (1) See 'net_arp.h MODULE'.
*********************************************************************************************************
*/
#ifdef NET_ARP_MODULE_PRESENT
/*$PAGE*/
/*
*********************************************************************************************************
* LOCAL DEFINES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL CONSTANTS
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL DATA TYPES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL TABLES
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/
/*$PAGE*/
/*
*********************************************************************************************************
* LOCAL FUNCTION PROTOTYPES
*********************************************************************************************************
*/
/* --------------- RX FNCTS --------------- */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetARP_RxPktValidateBuf (NET_BUF_HDR *pbuf_hdr,
NET_ERR *perr);
#endif
static void NetARP_RxPktValidate (NET_BUF_HDR *pbuf_hdr,
NET_ARP_HDR *parp_hdr,
NET_ERR *perr);
static void NetARP_RxPktCacheUpdate (NET_ARP_HDR *parp_hdr,
NET_ERR *perr);
static void NetARP_RxPktReply (NET_ARP_HDR *parp_hdr,
NET_ERR *perr);
static void NetARP_RxPktIsTargetThisHost(NET_ARP_HDR *parp_hdr,
NET_ERR *perr);
static void NetARP_RxPktFree (NET_BUF *pbuf);
static void NetARP_RxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr);
/* --------------- TX FNCTS --------------- */
static void NetARP_Tx (CPU_INT08U *paddr_hw_sender,
CPU_INT08U *paddr_hw_target,
CPU_INT08U *paddr_protocol_sender,
CPU_INT08U *paddr_protocol_target,
CPU_INT16U op_code,
NET_ERR *perr);
static void NetARP_TxReq (NET_ARP_CACHE *pcache);
static void NetARP_TxReply (NET_ARP_HDR *parp_hdr);
static void NetARP_TxPktPrepareHdr (NET_BUF *pbuf,
CPU_INT16U msg_ix,
CPU_INT08U *paddr_hw_sender,
CPU_INT08U *paddr_hw_target,
CPU_INT08U *paddr_protocol_sender,
CPU_INT08U *paddr_protocol_target,
CPU_INT16U op_code,
NET_ERR *perr);
static void NetARP_TxPktFree (NET_BUF *pbuf);
static void NetARP_TxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr);
/*$PAGE*/
/* ----------- ARP CACHE FNCTS ------------ */
static void NetARP_CacheTxPktHandler (NET_BUF *pbuf_q,
CPU_INT08U *paddr_hw);
static NET_ARP_CACHE *NetARP_CacheSrch (CPU_INT08U *paddr_protocol);
static void NetARP_CacheAddPend (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT08U *paddr_protocol,
NET_ERR *perr);
static void NetARP_CacheAddResolved (CPU_INT08U *paddr_hw,
CPU_INT08U *paddr_protocol,
NET_ERR *perr);
static void NetARP_CacheRemove (NET_ARP_CACHE *pcache,
CPU_BOOLEAN tmr_free);
static void NetARP_CacheInsert (NET_ARP_CACHE *pcache);
static void NetARP_CacheUnlink (NET_ARP_CACHE *pcache);
static void NetARP_CacheUnlinkBuf (NET_BUF *pbuf);
static void NetARP_CacheReqTimeout (void *pcache_timeout);
static void NetARP_CacheTimeout (void *pcache_timeout);
static NET_ARP_CACHE *NetARP_CacheCfg (CPU_INT08U *paddr_hw,
CPU_INT08U *paddr_protocol,
CPU_FNCT_PTR timeout_fnct,
NET_TMR_TICK timeout_tick,
NET_ERR *perr);
static NET_ARP_CACHE *NetARP_CacheGet (NET_ERR *perr);
static void NetARP_CacheFree (NET_ARP_CACHE *pcache,
CPU_BOOLEAN tmr_free);
static void NetARP_CacheClr (NET_ARP_CACHE *pcache);
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static CPU_BOOLEAN NetARP_CacheIsUsed (NET_ARP_CACHE *pcache);
static void NetARP_CacheDiscard (NET_ARP_CACHE *pcache);
#endif
/*
*********************************************************************************************************
* LOCAL CONFIGURATION ERRORS
*********************************************************************************************************
*/
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_Init()
*
* Description : (1) Initialize Address Resolution Protocol :
*
* (a) Initialize ARP cache pool
* (b) Initialize ARP cache table
* (c) Initialize ARP cache list pointers
* (d) Initialize ARP host address pointers
* (e) Initialize ARP statistics & error counters
*
*
* Argument(s) : none.
*
* Return(s) : none.
*
* Caller(s) : NetIF_Init().
*
* This function is a network protocol suite to network interface (IF) function & SHOULD be
* called only by appropriate network interface initialization function(s).
*
* Note(s) : (2) ARP cache pool MUST be initialized PRIOR to initializing the pool with pointers to
* ARP caches.
*********************************************************************************************************
*/
void NetARP_Init (void)
{
NET_ARP_CACHE *pcache;
NET_ARP_CACHE_QTY i;
NET_ERR stat_err;
/* ------------ INIT ARP CACHE POOL/STATS ------------- */
NetARP_CachePoolPtr = (NET_ARP_CACHE *)0; /* Init-clr ARP cache pool (see Note #2). */
NetStat_PoolInit((NET_STAT_POOL *)&NetARP_CachePoolStat,
(NET_STAT_POOL_QTY) NET_ARP_CFG_NBR_CACHE,
(NET_ERR *)&stat_err);
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
NetARP_CacheSrchCtr_lo = 0;
NetARP_CacheSrchCtr_hi = 0;
NetARP_CacheFoundCtr_lo = 0;
NetARP_CacheFoundCtr_hi = 0;
NetARP_CacheFoundPct = 0;
#endif
/* ---------------- INIT ARP CACHE TBL ---------------- */
pcache = &NetARP_CacheTbl[0];
for (i = 0; i < NET_ARP_CFG_NBR_CACHE; i++) {
/* Init each ARP cache type/addr len--NEVER modify. */
pcache->Type = NET_ARP_TYPE_CACHE;
pcache->HW_Type = NET_ARP_CFG_HW_TYPE;
pcache->HW_AddrLen = NET_ARP_CFG_HW_ADDR_LEN;
pcache->ProtocolType = NET_ARP_CFG_PROTOCOL_TYPE;
pcache->ProtocolAddrLen = NET_ARP_CFG_PROTOCOL_ADDR_LEN;
pcache->State = NET_ARP_CACHE_STATE_FREE; /* Init each ARP cache as free/NOT used. */
pcache->Flags = NET_ARP_FLAG_NONE;
#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED)
NetARP_CacheClr(pcache);
#endif
/* Free each ARP cache to cache pool (see Note #2). */
pcache->NextPtr = (void *)NetARP_CachePoolPtr;
NetARP_CachePoolPtr = (NET_ARP_CACHE *)pcache;
pcache++;
}
/* ------------- INIT ARP CACHE LIST PTRS ------------- */
NetARP_CacheListHead = (NET_ARP_CACHE *)0;
NetARP_CacheListTail = (NET_ARP_CACHE *)0;
/* ------------- INIT ARP HOST ADDR PTRS ------------- */
NetARP_HostAddrPtrHW = NetARP_GetHostAddrPtrHW();
NetARP_HostAddrPtrProtocol = NetARP_GetHostAddrPtrProtocol();
/*$PAGE*/
/* ------------- INIT ARP STAT & ERR CTRS ------------- */
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
NetARP_StatRxPktCtr = 0;
NetARP_StatRxMsgProcessedCtr = 0;
NetARP_StatRxMsgReqProcessedCtr = 0;
NetARP_StatRxMsgReplyProcessedCtr = 0;
NetARP_StatTxMsgCtr = 0;
NetARP_StatTxMsgReqCtr = 0;
NetARP_StatTxMsgReplyCtr = 0;
#endif
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
NetARP_ErrNoneAvailCtr = 0;
NetARP_ErrRxHdrHW_TypeCtr = 0;
NetARP_ErrRxHdrHW_AddrLenCtr = 0;
NetARP_ErrRxHdrHW_AddrCtr = 0;
NetARP_ErrRxHdrProtocolTypeCtr = 0;
NetARP_ErrRxHdrProtocolAddrLenCtr = 0;
NetARP_ErrRxHdrProtocolAddrCtr = 0;
NetARP_ErrRxHdrOpCodeCtr = 0;
NetARP_ErrRxHdrOpAddrCtr = 0;
NetARP_ErrRxHdrMsgLenCtr = 0;
NetARP_ErrRxPktTargetReplyCtr = 0;
NetARP_ErrRxPktTargetNotThisHostCtr = 0;
NetARP_ErrRxPktDiscardedCtr = 0;
NetARP_ErrTxPktDiscardedCtr = 0;
#if ((NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) || \
(NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED))
NetARP_ErrNullPtrCtr = 0;
#endif
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
NetARP_ErrInvalidAddrLenHW_Ctr = 0;
NetARP_ErrInvalidAddrLenProtocolCtr = 0;
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
NetARP_ErrNotUsedCtr = 0;
NetARP_ErrInvalidTypeCtr = 0;
NetARP_ErrRxInvalidBufIxCtr = 0;
NetARP_ErrTxHdrOpCodeCtr = 0;
#endif
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CfgCacheTimeout()
*
* Description : Configure ARP cache timeout from ARP Cache List.
*
* Argument(s) : timeout_sec Desired value for ARP cache timeout (in seconds).
*
* Return(s) : DEF_OK, ARP cache timeout configured.
*
* Caller(s) : Net_InitDflt(),
* Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (1) RFC #1122, Section 2.3.2.1 states that "an implementation of the Address Resolution
* Protocol (ARP) ... MUST provide a mechanism to flush out-of-date cache entries. If
* this mechanism involves a timeout, it SHOULD be possible to configure the timeout
* value".
*
* (2) Timeout in seconds converted to 'NET_TMR_TICK' ticks in order to pre-compute initial
* timeout value in 'NET_TMR_TICK' ticks.
*********************************************************************************************************
*/
CPU_BOOLEAN NetARP_CfgCacheTimeout (CPU_INT16U timeout_sec)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_TMR_TICK tick;
#if (NET_ARP_CACHE_TIMEOUT_MIN_SEC > DEF_INT_16U_MIN_VAL)
if (timeout_sec < NET_ARP_CACHE_TIMEOUT_MIN_SEC) {
timeout_sec = NET_ARP_CACHE_TIMEOUT_MIN_SEC;
}
#endif
#if (NET_ARP_CACHE_TIMEOUT_MAX_SEC < DEF_INT_16U_MAX_VAL)
if (timeout_sec > NET_ARP_CACHE_TIMEOUT_MAX_SEC) {
timeout_sec = NET_ARP_CACHE_TIMEOUT_MAX_SEC;
}
#endif
tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
CPU_CRITICAL_ENTER();
NetARP_CacheTimeout_sec = timeout_sec;
NetARP_CacheTimeout_tick = tick;
CPU_CRITICAL_EXIT();
return (DEF_OK);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CfgCacheAccessedTh()
*
* Description : Configure ARP cache accessed-promotion threshold.
*
* Argument(s) : nbr_access Desired number of ARP cache accesses before ARP cache is promoted.
*
* Return(s) : DEF_OK, ARP cache promotion threshold configured.
*
* Caller(s) : Net_InitDflt(),
* Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : none.
*********************************************************************************************************
*/
CPU_BOOLEAN NetARP_CfgCacheAccessedTh (CPU_INT16U nbr_access)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
#if (NET_ARP_CACHE_ACCESSED_TH_MIN > DEF_INT_16U_MIN_VAL)
if (nbr_access < NET_ARP_CACHE_ACCESSED_TH_MIN) {
nbr_access = NET_ARP_CACHE_ACCESSED_TH_MIN;
}
#endif
#if (NET_ARP_CACHE_ACCESSED_TH_MAX < DEF_INT_16U_MAX_VAL)
if (nbr_access > NET_ARP_CACHE_ACCESSED_TH_MAX) {
nbr_access = NET_ARP_CACHE_ACCESSED_TH_MAX;
}
#endif
CPU_CRITICAL_ENTER();
NetARP_CacheAccessedTh_nbr = nbr_access;
CPU_CRITICAL_EXIT();
return (DEF_OK);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CfgReqTimeout()
*
* Description : Configure timeout between ARP Request retries.
*
* Argument(s) : timeout_sec Desired value for ARP Request pending ARP Reply timeout (in seconds).
*
* Return(s) : DEF_OK, ARP Request timeout configured.
*
* Caller(s) : Net_InitDflt(),
* Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (1) Timeout in seconds converted to 'NET_TMR_TICK' ticks in order to pre-compute initial
* timeout value in 'NET_TMR_TICK' ticks.
*********************************************************************************************************
*/
CPU_BOOLEAN NetARP_CfgReqTimeout (CPU_INT08U timeout_sec)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_TMR_TICK tick;
if (timeout_sec < NET_ARP_REQ_RETRY_TIMEOUT_MIN_SEC) {
timeout_sec = NET_ARP_REQ_RETRY_TIMEOUT_MIN_SEC;
}
if (timeout_sec > NET_ARP_REQ_RETRY_TIMEOUT_MAX_SEC) {
timeout_sec = NET_ARP_REQ_RETRY_TIMEOUT_MAX_SEC;
}
tick = (NET_TMR_TICK)timeout_sec * NET_TMR_TIME_TICK_PER_SEC;
CPU_CRITICAL_ENTER();
NetARP_ReqTimeout_sec = timeout_sec;
NetARP_ReqTimeout_tick = tick;
CPU_CRITICAL_EXIT();
return (DEF_OK);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CfgReqMaxRetries()
*
* Description : Configure ARP Request maximum number of requests.
*
* Argument(s) : max_nbr_retries Desired maximum number of ARP Request attempts.
*
* Return(s) : DEF_OK, ARP Request maximum number of attempts configured.
*
* Caller(s) : Net_InitDflt(),
* Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (1) An ARP cache monitors the number of ARP Requests transmitted before receiving an ARP
* Reply. In other words, an ARP cache monitors the number of ARP Request attempts.
*
* However, the maximum number of ARP Requests that each ARP cache is allowed to transmit
* is configured in terms of retries. Thus, the total number of attempts is equal to the
* configured number of retries plus one (1).
*********************************************************************************************************
*/
CPU_BOOLEAN NetARP_CfgReqMaxRetries (CPU_INT08U max_nbr_retries)
{
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
#if (NET_ARP_REQ_RETRY_MIN > DEF_INT_08U_MIN_VAL)
if (max_nbr_retries < NET_ARP_REQ_RETRY_MIN) {
max_nbr_retries = NET_ARP_REQ_RETRY_MIN;
}
#endif
#if (NET_ARP_REQ_RETRY_MAX < DEF_INT_08U_MAX_VAL)
if (max_nbr_retries > NET_ARP_REQ_RETRY_MAX) {
max_nbr_retries = NET_ARP_REQ_RETRY_MAX;
}
#endif
CPU_CRITICAL_ENTER();
NetARP_ReqMaxAttempts_nbr = max_nbr_retries + 1; /* Set max attempts as max retries + 1 (see Note #1). */
CPU_CRITICAL_EXIT();
return (DEF_OK);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_ProbeAddrOnNet()
*
* Description : (1) Transmit an ARP Request to probe the local network for a specific protocol address :
*
* (a) Remove ARP cache with desired protocol address from ARP Cache List, if available
* (b) Configure ARP cache :
* (1) Get default-configured ARP cache
* (2) ARP cache state
* (c) Transmit ARP Request to probe local network for desired protocol address
*
*
* (2) NetARP_ProbeAddrOnNet() SHOULD be used in conjunction with NetARP_CacheGetAddrHW()
* to determine if a specific protocol address is available on the local network :
*
* (a) After successfully transmitting an ARP Request to probe the local network & ...
* (b) After some time delay(s) [on the order of ARP Request timeouts & retries]; ...
* (c) Check ARP Cache for the hardware address of a host on the local network that
* corresponds to the desired protocol address.
*
* See also 'NetARP_CacheGetAddrHW() Note #1'.
*
*
* Argument(s) : paddr_protocol Pointer to protocol address to probe local network (see Note #3).
*
* addr_protocol_len Length of protocol address (in octets) [see Note #4].
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE ARP Request successfully transmitted to
* probe local network for the desired
* protocol address (see Note #2).
* NET_ARP_ERR_NULL_PTR Argument 'paddr_protocol' passed a NULL
* pointer.
* NET_ARP_ERR_INVALID_PROTOCOL_LEN Invalid ARP protocol address length.
*
* --- RETURNED BY NetARP_CacheCfg() : ----
* NET_ARP_ERR_CACHE_NONE_AVAIL NO available ARP caches to allocate.
* NET_ARP_ERR_CACHE_INVALID_TYPE ARP cache is NOT a valid cache type.
* NET_TMR_ERR_NULL_OBJ Argument 'obj' passed a NULL pointer.
* NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer.
* NET_TMR_ERR_NONE_AVAIL NO available timers to allocate.
* NET_TMR_ERR_INVALID_TYPE Network timer is NOT a valid timer type.
*
* 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) : (3) 'paddr_protocol' MUST point to a valid protocol address that is in network-order.
*
* See also 'NetARP_CacheHandler() Note #2e3'.
*
* (4) The length of the protocol address MUST be equal to NET_ARP_CFG_PROTOCOL_ADDR_LEN
* & is included for correctness & completeness.
*********************************************************************************************************
*/
/*$PAGE*/
void NetARP_ProbeAddrOnNet (CPU_INT08U *paddr_protocol,
NET_ARP_ADDR_LEN addr_protocol_len,
NET_ERR *perr)
{
#if ((NET_ERR_CFG_ARG_CHK_EXT_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_ARP_CACHE *pcache;
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) /* ------------ VALIDATE PROTOCOL ADDR BUF ------------ */
if (paddr_protocol == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
if (addr_protocol_len != NET_ARP_CFG_PROTOCOL_ADDR_LEN) { /* Chk protocol addr len (see Note #4). */
NET_CTR_ERR_INC(NetARP_ErrInvalidAddrLenProtocolCtr);
*perr = NET_ARP_ERR_INVALID_PROTOCOL_LEN;
return;
}
#else
(void)&addr_protocol_len; /* Prevent compiler warning. */
#endif
/* --------- REMOVE PROTOCOL ADDR'S ARP CACHE --------- */
pcache = NetARP_CacheSrch(paddr_protocol);
if (pcache != (NET_ARP_CACHE *)0) { /* If protocol addr's ARP cache avail, ... */
NetARP_CacheRemove(pcache, DEF_YES); /* ... remove from ARP Cache List (see Note #1a). */
}
/* ------------------ CFG ARP CACHE ------------------- */
pcache = NetARP_CacheCfg((CPU_INT08U *)0,
(CPU_INT08U *)paddr_protocol,
(CPU_FNCT_PTR)NetARP_CacheReqTimeout,
(NET_TMR_TICK)NetARP_ReqTimeout_tick,
(NET_ERR *)perr);
if (*perr != NET_ARP_ERR_NONE) {
return;
}
pcache->State = NET_ARP_CACHE_STATE_PEND;
/* ------- INSERT ARP CACHE INTO ARP CACHE LIST ------- */
NetARP_CacheInsert(pcache);
/* -------------------- TX ARP REQ -------------------- */
NetARP_TxReq(pcache); /* Tx ARP req to probe local net for protocol addr. */
*perr = NET_ARP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_Rx()
*
* Description : (1) Process received ARP packets & update ARP Cache List :
*
* (a) Validate ARP packet
* (b) Update ARP cache
* (c) Prepare & transmit an ARP Reply for a received ARP Request
* (d) Free ARP packet
* (e) Update receive statistics
*
*
* Argument(s) : pbuf Pointer to network buffer that received ARP packet.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE ARP packet successfully received & processed.
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
*
* ---- RETURNED BY NetARP_RxPktDiscard() : ----
* NET_ERR_RX Receive error; packet discarded.
*
* Return(s) : none.
*
* Caller(s) : NetIF_RxPktFrameDemux().
*
* This function is a network protocol suite to network interface (IF) function & SHOULD be
* called only by appropriate network interface function(s).
*
* Note(s) : (2) NetARP_Rx() blocked until network initialization completes.
*********************************************************************************************************
*/
void NetARP_Rx (NET_BUF *pbuf,
NET_ERR *perr)
{
#if ((((NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) && \
(NET_CTR_CFG_ERR_EN == DEF_ENABLED)) || \
(NET_CTR_CFG_STAT_EN == DEF_ENABLED)) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
NET_CTR *pctr;
#endif
NET_BUF_HDR *pbuf_hdr;
NET_ARP_HDR *parp_hdr;
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (Net_InitDone != DEF_YES) { /* If init NOT complete, exit rx (see Note #2). */
*perr = NET_ERR_INIT_INCOMPLETE;
return;
}
#endif
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ------------------- VALIDATE PTR ------------------- */
if (pbuf == (NET_BUF *)0) {
NetARP_RxPktDiscard(pbuf, perr);
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
return;
}
#endif
NET_CTR_STAT_INC(NetARP_StatRxPktCtr);
/* ----------------- VALIDATE ARP PKT ----------------- */
pbuf_hdr = &pbuf->Hdr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
NetARP_RxPktValidateBuf(pbuf_hdr, perr); /* Validate rx'd buf. */
switch (*perr) {
case NET_ARP_ERR_NONE:
break;
case NET_ERR_INVALID_PROTOCOL:
case NET_BUF_ERR_INVALID_IX:
default:
NetARP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
#endif
parp_hdr = (NET_ARP_HDR *)&pbuf->Data[pbuf_hdr->ARP_MsgIx];
NetARP_RxPktValidate(pbuf_hdr, parp_hdr, perr); /* Validate rx'd pkt. */
/*$PAGE*/
/* ----------------- UPDATE ARP CACHE ----------------- */
switch (*perr) { /* Chk err from NetARP_RxPktValidate(). */
case NET_ARP_ERR_NONE:
NetARP_RxPktCacheUpdate(parp_hdr, perr);
break;
case NET_ARP_ERR_INVALID_HW_TYPE:
case NET_ARP_ERR_INVALID_HW_LEN:
case NET_ARP_ERR_INVALID_HW_ADDR:
case NET_ARP_ERR_INVALID_PROTOCOL_TYPE:
case NET_ARP_ERR_INVALID_PROTOCOL_LEN:
case NET_ARP_ERR_INVALID_PROTOCOL_ADDR:
case NET_ARP_ERR_INVALID_OP_CODE:
case NET_ARP_ERR_INVALID_OP_ADDR:
case NET_ARP_ERR_INVALID_LEN_MSG:
default:
NetARP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* ------------------- TX ARP REPLY ------------------- */
switch (*perr) { /* Chk err from NetARP_RxPktCacheUpdate(). */
case NET_ARP_ERR_CACHE_RESOLVED:
NetARP_RxPktReply(parp_hdr, perr);
break;
case NET_ARP_ERR_CACHE_NONE_AVAIL:
case NET_ARP_ERR_CACHE_INVALID_TYPE:
case NET_ARP_ERR_INVALID_OP_CODE:
case NET_ARP_ERR_RX_TARGET_REPLY:
case NET_ARP_ERR_RX_TARGET_NOT_THIS_HOST:
case NET_TMR_ERR_NULL_OBJ:
case NET_TMR_ERR_NULL_FNCT:
case NET_TMR_ERR_NONE_AVAIL:
case NET_TMR_ERR_INVALID_TYPE:
default:
NetARP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* ---------- FREE ARP PKT / UPDATE RX STATS ---------- */
switch (*perr) { /* Chk err from NetARP_RxPktReply(). */
case NET_ARP_ERR_RX_REQ_TX_REPLY:
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
pctr = &NetARP_StatRxMsgReqProcessedCtr;
#endif
break;
case NET_ARP_ERR_RX_REPLY_TX_PKTS:
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
pctr = &NetARP_StatRxMsgReplyProcessedCtr;
#endif
break;
case NET_ARP_ERR_INVALID_OP_CODE:
case NET_ARP_ERR_RX_TARGET_NOT_THIS_HOST:
default:
NetARP_RxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
NetARP_RxPktFree(pbuf);
NET_CTR_STAT_INC(NetARP_StatRxMsgProcessedCtr);
NET_CTR_STAT_INC(*pctr);
*perr = NET_ARP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheHandler()
*
* Description : (1) Resolve destination hardware address for transmit data packet :
*
* (a) Search ARP Cache List for ARP cache with corresponding protocol address
* (b) If ARP cache found, handle packet based on ARP cache state :
*
* (1) PENDING -> Enqueue transmit packet buffer to ARP cache
* (2) RESOLVED -> Copy ARP cache's hardware address to data packet;
* Return to Network Interface to transmit data packet
*
* (c) If ARP cache NOT found, allocate new ARP cache in 'PENDING' state (see Note #1b1)
*
* See 'net_arp.h ARP CACHE STATES' for ARP cache state diagram.
*
* (2) This ARP cache handler function assumes the following :
*
* (a) ALL ARP caches in the ARP Cache List are valid [validated by NetARP_CacheGet()]
* (b) ANY ARP cache in the 'PENDING' state MAY have already enqueued at LEAST one
* transmit packet buffer when ARP cache allocated [see NetARP_CacheGet()]
* (c) ALL ARP caches in the 'RESOLVED' state have valid hardware addresses
* (d) ALL transmit buffers enqueued on any ARP cache are valid
* (e) Buffer's ARP address pointers pre-configured by Network Interface to point to :
*
* (1) 'ARP_AddrProtocolPtr' Pointer to the protocol address used to
* resolve the hardware address
* (2) 'ARP_AddrHW_Ptr' Pointer to memory buffer to return the
* resolved hardware address
* (3) ARP addresses which MUST be in network-order
*
*
* Argument(s) : pbuf Pointer to network buffer to transmit.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_CACHE_RESOLVED ARP cache resolved & hardware address
* successfully copied.
* NET_ARP_ERR_CACHE_PEND ARP cache in 'PENDING' state; transmit
* buffer enqueued to ARP cache.
* NET_ARP_ERR_NULL_PTR Argument 'pbuf' passed a NULL pointer;
* OR
* 'pbuf's 'ARP_AddrProtocolPtr'/'ARP_AddrHWPtr'
* are set as NULL pointers.
*
* ---- RETURNED BY NetARP_CacheAddPend() : ----
* NET_ARP_ERR_CACHE_NONE_AVAIL NO available ARP caches to allocate.
* NET_ARP_ERR_CACHE_INVALID_TYPE ARP cache is NOT a valid cache type.
* NET_TMR_ERR_NULL_OBJ Argument 'obj' passed a NULL pointer.
* NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer.
* NET_TMR_ERR_NONE_AVAIL NO available timers to allocate.
* NET_TMR_ERR_INVALID_TYPE Network timer is NOT a valid timer type.
*
* Return(s) : none.
*
* Caller(s) : NetIF_Tx().
*
* This function is a network protocol suite to network interface (IF) function & SHOULD be
* called only by appropriate network interface function(s).
*
* Note(s) : (3) (a) ARP Cache List is accessed by
*
* (1) NetARP_CacheHandler()
* (2) NetARP_CacheAddPend() via NetARP_CacheInsert()
* (3) NetARP_CacheAddResolved() via NetARP_CacheInsert()
* (4) NetARP_CacheRemove() via NetARP_CacheUnlink()
* (5) NetARP_RxPktCacheUpdate()
* (6) ARP cache's 'TMR->Obj' pointer via NetARP_CacheReqTimeout() &
* NetARP_CacheTimeout()
*
* (b) 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 the shared
* resources of the ARP Cache List since no asynchronous access from other network
* tasks is possible.
*
* (4) (a) RFC #1122, Section 2.3.2.2 states that "the link layer SHOULD" ... :
*
* (1) "Save (rather than discard) ... packets destined to the same unresolved
* IP address and" ...
* (2) "Transmit the saved packet[s] when the address has been resolved."
*
* (b) Since ARP Layer is the last layer to handle & queue the transmit network
* buffer, it is NOT necessary to increment the network buffer's reference
* counter to include the pending ARP cache buffer queue as a new reference
* to the network buffer.
*
* (5) Some buffer controls were previously initialized in NetBuf_Get() when the packet
* was received at the network interface layer. These buffer controls do NOT need
* to be re-initialized but are shown for completeness.
*********************************************************************************************************
*/
/*$PAGE*/
void NetARP_CacheHandler (NET_BUF *pbuf,
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
CPU_INT08U *paddr_hw;
CPU_INT08U *paddr_protocol;
NET_BUF_HDR *pbuf_hdr;
NET_BUF_HDR *ptail_buf_hdr;
NET_BUF *ptail_buf;
NET_ARP_CACHE *pcache;
/* ------------------- VALIDATE PTRS ------------------ */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (pbuf == (NET_BUF *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
#endif
pbuf_hdr = &pbuf->Hdr;
paddr_hw = pbuf_hdr->ARP_AddrHW_Ptr;
paddr_protocol = pbuf_hdr->ARP_AddrProtocolPtr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
if (paddr_hw == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
if (paddr_protocol == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
#endif
/* ------------------ SRCH ARP CACHE ------------------ */
pcache = NetARP_CacheSrch(paddr_protocol);
if (pcache != (NET_ARP_CACHE *)0) { /* If ARP cache found, chk state. */
switch (pcache->State) {
case NET_ARP_CACHE_STATE_PEND: /* If ARP cache pend, append buf onto Q (see Note #4a1).*/
ptail_buf = pcache->BufQ_Tail;
if (ptail_buf != (NET_BUF *)0) { /* If Q NOT empty, append buf @ Q tail. */
ptail_buf_hdr = &ptail_buf->Hdr;
ptail_buf_hdr->NextSecListPtr = (void *)pbuf;
pbuf_hdr->PrevSecListPtr = (void *)ptail_buf;
pcache->BufQ_Tail = (NET_BUF *)pbuf;
} else { /* Else add buf as first q'd buf. */
pcache->BufQ_Head = (NET_BUF *)pbuf;
pcache->BufQ_Tail = (NET_BUF *)pbuf;
#if 0 /* Init'd in NetBuf_Get() [see Note #5]. */
pbuf_hdr->PrevSecListPtr = (void *)0;
pbuf_hdr->NextSecListPtr = (void *)0;
#endif
}
/* Set ARP cache as unlink fnct/obj. */
pbuf_hdr->UnlinkFnctPtr = (CPU_FNCT_PTR)NetARP_CacheUnlinkBuf;
pbuf_hdr->UnlinkObjPtr = (void *)pcache;
*perr = NET_ARP_ERR_CACHE_PEND;
break;
case NET_ARP_CACHE_STATE_RESOLVED: /* If ARP cache resolved, copy hw addr. */
Mem_Copy((void *) paddr_hw,
(void *)&pcache->HW_Addr[0],
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
*perr = NET_ARP_ERR_CACHE_RESOLVED;
break;
case NET_ARP_CACHE_STATE_NONE:
case NET_ARP_CACHE_STATE_FREE:
default:
NetARP_CacheRemove(pcache, DEF_YES);
NetARP_CacheAddPend(pbuf, pbuf_hdr, paddr_protocol, perr);
break;
}
} else { /* Else add new ARP cache into ARP Cache List. */
NetARP_CacheAddPend(pbuf, pbuf_hdr, paddr_protocol, perr);
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheCalcStat()
*
* Description : (1) Calculate ARP statistics :
*
* (a) ARP cache found percentage
*
*
* Argument(s) : none.
*
* Return(s) : ARP cache found percentage, if NO errors,
*
* NULL cache found percentage, otherwise.
*
* Caller(s) : Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (2) NetARP_CacheCalcStat() blocked until network initialization completes; return NULL
* ARP cache found percentage.
*
* (3) These ARP statistics calculation(s) are potentially expensive operations. Recommended
* only from low-priority, background tasks.
*********************************************************************************************************
*/
CPU_INT08U NetARP_CacheCalcStat (void)
{
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
#if (CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL)
CPU_SR cpu_sr;
#endif
NET_CTR pct_numer_hi;
NET_CTR pct_numer_lo;
NET_CTR pct_denom_hi;
NET_CTR pct_denom_lo;
#endif
CPU_INT08U pct;
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (Net_InitDone != DEF_YES) { /* If init NOT complete, ... */
return (0); /* ... rtn NULL pct (see Note #2). */
}
#endif
/* ------------- CALC ARP CACHE FOUND PCT ------------- */
#if (NET_CTR_CFG_STAT_EN == DEF_ENABLED)
CPU_CRITICAL_ENTER();
pct_numer_hi = NetARP_CacheFoundCtr_hi;
pct_numer_lo = NetARP_CacheFoundCtr_lo;
pct_denom_hi = NetARP_CacheSrchCtr_hi;
pct_denom_lo = NetARP_CacheSrchCtr_lo;
CPU_CRITICAL_EXIT();
pct = NetCtr_CalcPctLarge(pct_numer_hi,
pct_numer_lo,
pct_denom_hi,
pct_denom_lo);
CPU_CRITICAL_ENTER();
NetARP_CacheFoundPct = pct;
CPU_CRITICAL_EXIT();
#else
pct = 0;
#endif
return (pct);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheGetAddrHW()
*
* Description : (1) Get hardware address that corresponds to a specific ARP cache's protocol address :
*
* (a) Search ARP Cache List for ARP cache with desired protocol address
* (b) If corresponding ARP cache found, get/return hardware address
*
*
* Argument(s) : paddr_hw Pointer to a memory buffer that will receive the hardware address :
* (see Notes #2a & 3a) :
*
* Hardware address that corresponds to the desired protocol address,
* if NO errors.
*
* Hardware address cleared to all zeros (see Note #2a3), otherwise.
*
* addr_hw_len_buf Length of hardware address memory buffer (in octets) [see Note #2a1].
*
* paddr_protocol Pointer to the specific protocol address to search for corresponding
* hardware address (see Note #3b).
*
* addr_protocol_len Length of protocol address (in octets) [see Note #2b].
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE Hardware address successfully returned.
* NET_ARP_ERR_CACHE_NOT_FOUND ARP cache with corresponding hardware/protocol
* address NOT found.
* NET_ARP_ERR_CACHE_PEND ARP cache in 'PENDING' state; hardware address
* NOT yet resolved (see Note #4).
*
* NET_ARP_ERR_NULL_PTR Argument(s) 'paddr_hw'/'paddr_protocol' passed
* a NULL pointer.
* NET_ARP_ERR_INVALID_HW_LEN Invalid ARP hardware address length.
* NET_ARP_ERR_INVALID_PROTOCOL_LEN Invalid ARP protocol address length.
*
* Return(s) : Length of returned hardware address (see Note #2a2), if available.
*
* 0, otherwise.
*
* Caller(s) : Application.
*
* This function is a network protocol suite application interface (API) function & MAY be
* called by application function(s).
*
* Note(s) : (2) (a) (1) The size of the memory buffer that will receive the returned hardware address
* MUST be greater than or equal to NET_ARP_CFG_HW_ADDR_LEN.
*
* (2) The length of any returned hardware address is equal to NET_ARP_CFG_HW_ADDR_LEN.
*
* (3) Address memory array cleared in case of any error(s).
*
* (A) Address memory array SHOULD be initialized to return a NULL address PRIOR
* to all other validation or function handling in case of any error(s).
*
* (b) The length of the protocol address MUST be equal to NET_ARP_CFG_PROTOCOL_ADDR_LEN
* & is included for correctness & completeness.
*
* (3) ARP addresses MUST be in network-order :
*
* (a) 'paddr_hw' hardware address returned in network-order
* (b) 'paddr_protocol' MUST point to a protocol address that is in network-order
*
* See also 'NetARP_CacheHandler() Note #2e3'.
*
* (4) While an ARP cache is in 'PENDING' state the hardware address is NOT yet resolved,
* but MAY be resolved in the near future by an awaited ARP Reply.
*********************************************************************************************************
*/
/*$PAGE*/
NET_ARP_ADDR_LEN NetARP_CacheGetAddrHW (CPU_INT08U *paddr_hw,
NET_ARP_ADDR_LEN addr_hw_len_buf,
CPU_INT08U *paddr_protocol,
NET_ARP_ADDR_LEN addr_protocol_len,
NET_ERR *perr)
{
#if ((NET_ERR_CFG_ARG_CHK_EXT_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_ARP_ADDR_LEN addr_hw_len;
NET_ARP_CACHE *pcache;
/* --------------- VALIDATE HW ADDR BUF --------------- */
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (paddr_hw == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return (0);
}
#endif
/* Clr hw addr (see Note #2a3). */
Mem_Clr((void *)paddr_hw,
(CPU_SIZE_T) addr_hw_len_buf);
addr_hw_len = NET_ARP_CFG_HW_ADDR_LEN; /* Cfg hw addr len (see Note #2a2). */
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (addr_hw_len_buf < addr_hw_len) { /* Chk hw addr buf len (see Note #2a1). */
NET_CTR_ERR_INC(NetARP_ErrInvalidAddrLenHW_Ctr);
*perr = NET_ARP_ERR_INVALID_HW_LEN;
return (0);
}
#endif
#if (NET_ERR_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) /* ------------ VALIDATE PROTOCOL ADDR BUF ------------ */
if (paddr_protocol == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return (0);
}
if (addr_protocol_len != NET_ARP_CFG_PROTOCOL_ADDR_LEN) { /* Chk protocol addr len (see Note #2b). */
NET_CTR_ERR_INC(NetARP_ErrInvalidAddrLenProtocolCtr);
*perr = NET_ARP_ERR_INVALID_PROTOCOL_LEN;
return (0);
}
#else
(void)&addr_protocol_len; /* Prevent compiler warning. */
#endif
/* ------------------ SRCH ARP CACHE ------------------ */
pcache = NetARP_CacheSrch(paddr_protocol);
if (pcache == (NET_ARP_CACHE *)0) {
*perr = NET_ARP_ERR_CACHE_NOT_FOUND;
return (0);
}
switch (pcache->State) {
case NET_ARP_CACHE_STATE_PEND: /* If ARP cache pend, hw addr NOT yet avail ... */
*perr = NET_ARP_ERR_CACHE_PEND; /* ... (see Note #4). */
return (0); /* Prevent 'break NOT reachable' compiler warning. */
case NET_ARP_CACHE_STATE_RESOLVED: /* If ARP cache resolved, hw addr avail. */
break;
case NET_ARP_CACHE_STATE_NONE:
case NET_ARP_CACHE_STATE_FREE:
default:
NetARP_CacheRemove(pcache, DEF_YES);
*perr = NET_ARP_ERR_CACHE_NOT_FOUND;
return (0); /* Prevent 'break NOT reachable' compiler warning. */
}
/* ------------------- GET HW ADDR -------------------- */
Mem_Copy((void *) paddr_hw,
(void *)&pcache->HW_Addr[0],
(CPU_SIZE_T) addr_hw_len);
*perr = NET_ARP_ERR_NONE;
return (addr_hw_len);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CachePoolStatGet()
*
* Description : Get ARP statistics pool.
*
* Argument(s) : none.
*
* Return(s) : ARP 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) NetARP_CachePoolStatGet() blocked until network initialization completes; return NULL
* statistics pool.
*********************************************************************************************************
*/
NET_STAT_POOL NetARP_CachePoolStatGet (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 = NetARP_CachePoolStat;
CPU_CRITICAL_EXIT();
return (stat_pool);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CachePoolStatResetMaxUsed()
*
* Description : Reset ARP 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.
*********************************************************************************************************
*/
void NetARP_CachePoolStatResetMaxUsed (void)
{
NET_ERR err;
NetStat_PoolResetUsedMax(&NetARP_CachePoolStat, &err);
}
/*$PAGE*/
/*
*********************************************************************************************************
*********************************************************************************************************
* LOCAL FUNCTIONS
*********************************************************************************************************
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* NetARP_RxPktValidateBuf()
*
* Description : Validate received buffer header as ARP protocol.
*
* Argument(s) : pbuf_hdr Pointer to network buffer header that received ARP packet.
* -------- Argument validated in NetARP_Rx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE Received buffer's ARP header validated.
* NET_ERR_INVALID_PROTOCOL Buffer's protocol type is NOT ARP.
* NET_BUF_ERR_INVALID_IX Invalid buffer index.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Rx().
*
* Note(s) : none.
*********************************************************************************************************
*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetARP_RxPktValidateBuf (NET_BUF_HDR *pbuf_hdr,
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
/* --------------- VALIDATE ARP BUF HDR --------------- */
if (pbuf_hdr->ProtocolHdrType != NET_PROTOCOL_TYPE_ARP) {
NET_CTR_ERR_INC(Net_ErrInvalidProtocolCtr);
*perr = NET_ERR_INVALID_PROTOCOL;
return;
}
if (pbuf_hdr->ARP_MsgIx == NET_BUF_IX_NONE) {
NET_CTR_ERR_INC(NetARP_ErrRxInvalidBufIxCtr);
*perr = NET_BUF_ERR_INVALID_IX;
return;
}
*perr = NET_ARP_ERR_NONE;
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_RxPktValidate()
*
* Description : (1) Validate received ARP packet :
*
* (a) Convert the following ARP header fields from network-order to host-order :
*
* (1) Hardware Type
* (2) Protocol Type
* (3) Operation Code See Note #1aB
*
* (A) These fields are NOT converted directly in the received packet buffer's
* data area but are converted in local or network buffer variables ONLY.
*
* (B) To avoid storing the ARP operation code in a network buffer variable &
* passing an additional pointer to the network buffer header that received
* ARP packet, ARP operation code is converted in the following functions :
*
* (1) NetARP_RxPktValidate()
* (2) NetARP_RxPktCacheUpdate()
* (3) NetARP_RxPktReply()
* (4) NetARP_RxPktIsTargetThisHost()
*
* (C) Hardware & Protocol Addresses are NOT converted from network-order to
* host-order & MUST be accessed as multi-octet arrays.
*
* (b) Validate the received packet's following ARP header fields :
*
* (1) Hardware Type
* (2) Hardware Address Length
* (3) Hardware Address : Sender's
* (4) Protocol Type
* (5) Protocol Address Length
* (6) Protocol Address : Sender's
* (7) Operation Code
*
* (c) Update network buffer's length controls.
*
* (d) Validate ARP message length :
*
* (1) The ARP message length is compared to the remaining packet length which should
* be identical.
*
* (2) However, some network interface frame types append 'pad' octets (octets with a
* dummy value to be ignored) if the data length for the frame does NOT meet the
* frame's required minimum size. Thus, if the ARP message length is NOT greater
* than the frame's minimum size, then pad octets were appended & the ARP message
* length CANNOT be compared.
*
*
* Argument(s) : pbuf_hdr Pointer to network buffer header that received ARP packet.
* -------- Argument validated in NetARP_Rx().
*
* parp_hdr Pointer to received packet's ARP header.
* -------- Argument validated in NetARP_Rx()/NetARP_RxPktValidateBuf().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE Received packet validated.
* NET_ARP_ERR_INVALID_HW_TYPE Invalid ARP hardware type.
* NET_ARP_ERR_INVALID_HW_LEN Invalid ARP hardware address length.
* NET_ARP_ERR_INVALID_HW_ADDR Invalid ARP hardware address.
* NET_ARP_ERR_INVALID_PROTOCOL_TYPE Invalid ARP protocol type.
* NET_ARP_ERR_INVALID_PROTOCOL_LEN Invalid ARP protocol address length.
* NET_ARP_ERR_INVALID_PROTOCOL_ADDR Invalid ARP protocol address.
* NET_ARP_ERR_INVALID_OP_CODE Invalid ARP operation code.
* NET_ARP_ERR_INVALID_OP_ADDR Invalid address for ARP operation
* (see Note #3).
* NET_ARP_ERR_INVALID_LEN_MSG Invalid ARP message length
* (see Note #1d).
*
* Return(s) : none.
*
* Caller(s) : NetARP_Rx().
*
* Note(s) : (2) See RFC #826, Section 'Packet Format' for ARP packet header format.
*
* (3) (a) An ARP Request SHOULD be transmitted onto the network by broadcast (see RFC #826,
* Section 'Packet Generation'). Therefore, any ARP Request NOT received as a broadcast
* packet SHOULD be discarded.
*
* (b) An ARP Reply SHOULD be transmitted directly to the ARP-Requesting host (see RFC #826,
* Section 'Packet Reception' algorithm) & SHOULD NOT be broadcast onto the network.
* Therefore, any ARP Reply received as a broadcast packet SHOULD be discarded.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetARP_RxPktValidate (NET_BUF_HDR *pbuf_hdr,
NET_ARP_HDR *parp_hdr,
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
CPU_INT16U hw_type;
CPU_INT16U protocol_type;
CPU_INT16U op_code;
CPU_BOOLEAN rx_broadcast;
CPU_BOOLEAN valid;
/* ------------ VALIDATE ARP HW TYPE/ADDR ------------- */
NET_UTIL_VAL_COPY_GET_NET_16(&hw_type, &parp_hdr->HW_Type);
if (hw_type != NET_ARP_CFG_HW_TYPE) {
NET_CTR_ERR_INC(NetARP_ErrRxHdrHW_TypeCtr);
*perr = NET_ARP_ERR_INVALID_HW_TYPE;
return;
}
if (parp_hdr->HW_AddrLen != NET_ARP_CFG_HW_ADDR_LEN) {
NET_CTR_ERR_INC(NetARP_ErrRxHdrHW_AddrLenCtr);
*perr = NET_ARP_ERR_INVALID_HW_LEN;
return;
}
valid = NetARP_IsValidAddrHW(&parp_hdr->HW_AddrSender[0]);
if (valid != DEF_YES) {
NET_CTR_ERR_INC(NetARP_ErrRxHdrHW_AddrCtr);
*perr = NET_ARP_ERR_INVALID_HW_ADDR;
return;
}
/* --------- VALIDATE ARP PROTOCOL TYPE/ADDR ---------- */
NET_UTIL_VAL_COPY_GET_NET_16(&protocol_type, &parp_hdr->ProtocolType);
if (protocol_type != NET_ARP_CFG_PROTOCOL_TYPE) {
NET_CTR_ERR_INC(NetARP_ErrRxHdrProtocolTypeCtr);
*perr = NET_ARP_ERR_INVALID_PROTOCOL_TYPE;
return;
}
if (parp_hdr->ProtocolAddrLen != NET_ARP_CFG_PROTOCOL_ADDR_LEN) {
NET_CTR_ERR_INC(NetARP_ErrRxHdrProtocolAddrLenCtr);
*perr = NET_ARP_ERR_INVALID_PROTOCOL_LEN;
return;
}
valid = NetARP_IsValidAddrProtocol(&parp_hdr->ProtocolAddrSender[0]);
if (valid != DEF_YES) {
NET_CTR_ERR_INC(NetARP_ErrRxHdrProtocolAddrCtr);
*perr = NET_ARP_ERR_INVALID_PROTOCOL_ADDR;
return;
}
/* --------------- VALIDATE ARP OP CODE --------------- */
NET_UTIL_VAL_COPY_GET_NET_16(&op_code, &parp_hdr->OpCode);
rx_broadcast = DEF_BIT_IS_SET(pbuf_hdr->Flags, NET_BUF_FLAG_BROADCAST_RX);
switch (op_code) {
case NET_ARP_HDR_OP_REQ:
if (rx_broadcast != DEF_YES) { /* See Note #3a. */
NET_CTR_ERR_INC(NetARP_ErrRxHdrOpAddrCtr);
*perr = NET_ARP_ERR_INVALID_OP_ADDR;
return;
}
break;
case NET_ARP_HDR_OP_REPLY:
if (rx_broadcast != DEF_NO) { /* See Note #3b. */
NET_CTR_ERR_INC(NetARP_ErrRxHdrOpAddrCtr);
*perr = NET_ARP_ERR_INVALID_OP_ADDR;
return;
}
break;
default:
NET_CTR_ERR_INC(NetARP_ErrRxHdrOpCodeCtr);
*perr = NET_ARP_ERR_INVALID_OP_CODE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/*$PAGE*/
/* ----- UPDATE BUF CTRLS / VALIDATE ARP MSG LEN ------ */
pbuf_hdr->ARP_MsgLen = NET_ARP_HDR_SIZE;
if (pbuf_hdr->ARP_MsgLen >= pbuf_hdr->IF_DataLenMin) { /* If ARP msg len >= min net IF data size & .. */
if (pbuf_hdr->ARP_MsgLen != pbuf_hdr->DataLen) { /* .. ARP msg len != rem pkt len, .. */
NET_CTR_ERR_INC(NetARP_ErrRxHdrMsgLenCtr);
*perr = NET_ARP_ERR_INVALID_LEN_MSG; /* .. rtn err (see Note #1d). */
return;
}
}
pbuf_hdr->DataLen -= (NET_BUF_SIZE)pbuf_hdr->ARP_MsgLen;
*perr = NET_ARP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_RxPktCacheUpdate()
*
* Description : (1) Update an ARP cache based on received ARP packet's sender addresses :
*
* (a) Verify ARP message's intended target address is this host
* (b) Search ARP Cache List
* (c) Update ARP cache
*
*
* Argument(s) : parp_hdr Pointer to received packet's ARP header.
* -------- Argument validated in NetARP_Rx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_CACHE_RESOLVED ARP cache resolved & hardware address
* successfully copied.
* NET_ARP_ERR_RX_TARGET_REPLY ARP Reply received but NO corresponding ARP
* cache currently pending for ARP Reply.
*
* --- RETURNED BY NetARP_CacheAddResolved() : ----
* NET_ARP_ERR_CACHE_NONE_AVAIL NO available ARP caches to allocate.
* NET_ARP_ERR_CACHE_INVALID_TYPE ARP cache is NOT a valid cache type.
* NET_TMR_ERR_NULL_OBJ Argument 'obj' passed a NULL pointer.
* NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer.
* NET_TMR_ERR_NONE_AVAIL NO available timers to allocate.
* NET_TMR_ERR_INVALID_TYPE Network timer is NOT a valid timer type.
*
* - RETURNED BY NetARP_RxPktIsTargetThisHost() : -
* NET_ARP_ERR_RX_TARGET_NOT_THIS_HOST Received ARP message NOT intended for this host.
* NET_ARP_ERR_INVALID_OP_CODE Invalid ARP operation code.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Rx().
*
* Note(s) : (2) (a) The ARP cache algorithm implies that ALL messages received at the ARP layer automatically
* update the ARP Cache List EVEN if this host is NOT the intended target host of a received
* ARP message -- but ONLY if an ARP cache for the sender's addresses is already cached (see
* RFC #826, Section 'Packet Reception'). However, if NO ARP cache exists for the sender's
* addresses, then even the ARP cache algorithm implies that a misdirected or incorrectly
* received ARP message is discarded.
*
* (b) A configurable ARP address filtering feature is provided to selectively filter & discard
* ALL misdirected or incorrectly received ARP messages (see 'net_cfg.h ADDRESS RESOLUTION
* PROTOCOL LAYER CONFIGURATION') :
*
* (1) When ENABLED, the ARP address filter discards :
*
* (A) ALL misdirected, broadcasted, or incorrectly received ARP messages.
*
* (B) Any ARP Reply received for this host for which NO corresponding ARP cache currently
* exists. (Note : Such an ARP Reply may be a legitimate, yet late, ARP Reply to a
* pending ARP Request that has timed-out & been removed from the ARP Cache List.)
*
* (2) When DISABLED, the ARP address filter discards :
*
* (A) Any misdirected or incorrectly received ARP messages if the sender's address(s)
* are NOT already cached.
*
* (3) (a) RFC # 826, Section 'Related issue' states that "perhaps receiving of a packet from a host
* should reset a timeout in the address resolution entry".
*
* (b) RFC #1122, Section 2.3.2.1 affirms "that this timeout should be restarted when the cache
* entry is 'refreshed'".
*********************************************************************************************************
*/
static void NetARP_RxPktCacheUpdate (NET_ARP_HDR *parp_hdr,
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_ARP_CFG_ADDR_FLTR_EN == DEF_ENABLED)
CPU_INT16U op_code;
#else
CPU_BOOLEAN cache_add;
#endif
CPU_INT08U *paddr_sender_hw;
CPU_INT08U *paddr_sender_protocol;
NET_ARP_CACHE *pcache;
NET_BUF *pbuf_head;
/*$PAGE*/
/* ----------------- CHK TARGET ADDR ------------------ */
NetARP_RxPktIsTargetThisHost(parp_hdr, perr);
#if (NET_ARP_CFG_ADDR_FLTR_EN == DEF_ENABLED)
if (*perr != NET_ARP_ERR_RX_TARGET_THIS_HOST) { /* Filter misdirected rx'd ARP msgs (see Note #2b1A). */
NET_CTR_ERR_INC(NetARP_ErrRxPktTargetNotThisHostCtr);
return;
}
#else
cache_add = (*perr == NET_ARP_ERR_RX_TARGET_THIS_HOST) ? DEF_YES : DEF_NO;
#endif
/* ------------------ SRCH ARP CACHE ------------------ */
paddr_sender_hw = parp_hdr->HW_AddrSender;
paddr_sender_protocol = parp_hdr->ProtocolAddrSender;
pcache = NetARP_CacheSrch(paddr_sender_protocol);
/* ----------------- UPDATE ARP CACHE ----------------- */
if (pcache != (NET_ARP_CACHE *)0) { /* If ARP cache found, chk state. */
switch (pcache->State) {
case NET_ARP_CACHE_STATE_PEND: /* If ARP cache pend, add sender's hw addr, ... */
Mem_Copy((void *)&pcache->HW_Addr[0],
(void *) paddr_sender_hw,
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
/* Reset ARP cache tmr (see Note #3). */
NetTmr_Set((NET_TMR *)pcache->TmrPtr,
(CPU_FNCT_PTR)NetARP_CacheTimeout,
(NET_TMR_TICK)NetARP_CacheTimeout_tick,
(NET_ERR *)perr);
pbuf_head = pcache->BufQ_Head;
pcache->BufQ_Head = (NET_BUF *)0;
pcache->BufQ_Tail = (NET_BUF *)0;
NetARP_CacheTxPktHandler(pbuf_head, /* ... & handle/tx cache's buf Q. */
paddr_sender_hw);
pcache->State = NET_ARP_CACHE_STATE_RESOLVED;
*perr = NET_ARP_ERR_CACHE_RESOLVED;
break;
case NET_ARP_CACHE_STATE_RESOLVED: /* If ARP cache resolved, update sender's hw addr. */
Mem_Copy((void *)&pcache->HW_Addr[0],
(void *) paddr_sender_hw,
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
/* Reset ARP cache tmr (see Note #3). */
NetTmr_Set((NET_TMR *)pcache->TmrPtr,
(CPU_FNCT_PTR)NetARP_CacheTimeout,
(NET_TMR_TICK)NetARP_CacheTimeout_tick,
(NET_ERR *)perr);
*perr = NET_ARP_ERR_CACHE_RESOLVED;
break;
case NET_ARP_CACHE_STATE_NONE:
case NET_ARP_CACHE_STATE_FREE:
default:
NetARP_CacheRemove(pcache, DEF_YES);
NetARP_CacheAddResolved(paddr_sender_hw, paddr_sender_protocol, perr);
break;
}
} else { /* Else add new ARP cache into ARP Cache List. */
#if (NET_ARP_CFG_ADDR_FLTR_EN == DEF_ENABLED) /* If ARP addr fltr en'd .. */
NET_UTIL_VAL_COPY_GET_NET_16(&op_code, &parp_hdr->OpCode);
if (op_code != NET_ARP_HDR_OP_REQ) { /* .. but ARP pkt NOT an ARP Req, .. */
/* .. do NOT add new ARP cache (see Note #2b1B). */
NET_CTR_ERR_INC(NetARP_ErrRxPktTargetReplyCtr);
*perr = NET_ARP_ERR_RX_TARGET_REPLY;
return;
}
#else /* If ARP addr fltr dis'd .. */
if (cache_add != DEF_YES) { /* .. & ARP pkt NOT for this host, .. */
/* .. do NOT add new ARP cache (see Note #2b2A). */
NET_CTR_ERR_INC(NetARP_ErrRxPktTargetNotThisHostCtr);
return; /* Err rtn'd by NetARP_RxPktIsTargetThisHost(). */
}
#endif
NetARP_CacheAddResolved(paddr_sender_hw, paddr_sender_protocol, perr);
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_RxPktReply()
*
* Description : Reply to any ARP Request received.
*
* Argument(s) : parp_hdr Pointer to received packet's ARP header.
* -------- Argument validated in NetARP_Rx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_RX_REQ_TX_REPLY ARP Request transmitted.
* NET_ARP_ERR_RX_REPLY_TX_PKTS ARP Reply received; pending ARP cache packets
* already transmitted (see Note #2).
* NET_ARP_ERR_INVALID_OP_CODE Invalid ARP operation code.
*
* - RETURNED BY NetARP_RxPktIsTargetThisHost() : -
* NET_ARP_ERR_RX_TARGET_NOT_THIS_HOST Received ARP message NOT intended for this host.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Rx().
*
* Note(s) : (1) (a) ARP Request target hardware address already verified as the network interface's broadcast
* address in NetARP_RxPktValidate() [see 'NetARP_RxPktValidate() Note #3a'].
*
* (b) (1) When ARP address filtering is DISABLED, an ARP Reply is transmitted for an ARP Request
* ONLY if this host is the intended protocol address target of the ARP Request.
*
* (2) When ARP address filtering is ENABLED, an ARP Reply is automatically transmitted for an
* ARP Request since this host's protocol address was already verified as the target protocol
* address in NetARP_RxPktCacheUpdate() [see 'NetARP_RxPktCacheUpdate() Note #2b1'].
*
* (2) ARP Reply already transmitted the ARP cache's transmit buffer queue in NetARP_RxPktCacheUpdate();
* no further action required.
*
* (3) Default case already invalidated in NetARP_RxPktValidate(). However, the default case is included
* as an extra precaution in case 'OpCode' is incorrectly modified.
*********************************************************************************************************
*/
static void NetARP_RxPktReply (NET_ARP_HDR *parp_hdr,
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
CPU_INT16U op_code;
NET_UTIL_VAL_COPY_GET_NET_16(&op_code, &parp_hdr->OpCode);
switch (op_code) {
case NET_ARP_HDR_OP_REQ: /* Use rx'd ARP Req to tx ARP Reply. */
#if (NET_ARP_CFG_ADDR_FLTR_EN != DEF_ENABLED) /* See Note #1b1. */
NetARP_RxPktIsTargetThisHost(parp_hdr, perr);
if (*perr != NET_ARP_ERR_RX_TARGET_THIS_HOST) {
NET_CTR_ERR_INC(NetARP_ErrRxPktTargetNotThisHostCtr);
return;
}
#endif
NetARP_TxReply(parp_hdr);
*perr = NET_ARP_ERR_RX_REQ_TX_REPLY;
break;
case NET_ARP_HDR_OP_REPLY: /* See Note #2. */
*perr = NET_ARP_ERR_RX_REPLY_TX_PKTS;
break;
default: /* See Note #3. */
NET_CTR_ERR_INC(NetARP_ErrRxHdrOpCodeCtr);
*perr = NET_ARP_ERR_INVALID_OP_CODE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_RxPktIsTargetThisHost()
*
* Description : (1) Determine if this host is the intended target of the received ARP message :
*
* (a) Verify target hardware address
* (b) Verify target protocol address
* (c) Return target validation
*
* (2) (a) When ARP address filtering is ENABLED, the target hardware address for the received
* ARP message is verified as either :
*
* (1) The network interface's broadcast address for a received ARP Request
* OR
* (2) This host's hardware address for a received ARP Reply
*
* (b) ARP Request target hardware address verified as the network interface's broadcast
* address in NetARP_RxPktValidate() [see 'NetARP_RxPktValidate() Note #3a'].
*
* (c) When ARP address filtering is DISABLED, target hardware address verification required
* only for the handling of an ARP Request in NetARP_RxPktReply() [see Note #2b &
* 'NetARP_RxPktReply() Note #1b1'].
*
* See also 'NetARP_RxPktCacheUpdate() Note #2'.
*
*
* Argument(s) : parp_hdr Pointer to received packet's ARP header.
* -------- Argument validated in NetARP_Rx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_RX_TARGET_THIS_HOST Received ARP message intended
* for this host.
* NET_ARP_ERR_RX_TARGET_NOT_THIS_HOST Received ARP message NOT intended
* for this host.
* NET_ARP_ERR_INVALID_OP_CODE Invalid ARP operation code.
*
* Return(s) : none.
*
* Caller(s) : NetARP_RxPktCacheUpdate(),
* NetARP_RxPktReply().
*
* Note(s) : (3) Default case already invalidated in NetARP_RxPktValidate(). However, the default case
* is included as an extra precaution in case 'OpCode' is incorrectly modified.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetARP_RxPktIsTargetThisHost (NET_ARP_HDR *parp_hdr,
NET_ERR *perr)
{
#if (NET_ARP_CFG_ADDR_FLTR_EN == DEF_ENABLED)
#if ((NET_CTR_CFG_ERR_EN == DEF_ENABLED) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
CPU_INT16U op_code;
CPU_INT08U *paddr_target_hw;
#endif
CPU_INT08U *paddr_target_protocol;
CPU_BOOLEAN target_hw;
CPU_BOOLEAN target_protocol;
/* -------------- VERIFY TARGET HW ADDR --------------- */
#if (NET_ARP_CFG_ADDR_FLTR_EN == DEF_ENABLED) /* See Note #2a. */
NET_UTIL_VAL_COPY_GET_NET_16(&op_code, &parp_hdr->OpCode);
switch (op_code) {
case NET_ARP_HDR_OP_REQ: /* See Note #2b. */
target_hw = DEF_YES;
break;
case NET_ARP_HDR_OP_REPLY:
paddr_target_hw = parp_hdr->HW_AddrTarget;
target_hw = Mem_Cmp((void *)paddr_target_hw,
(void *)NetARP_HostAddrPtrHW,
(CPU_SIZE_T)NET_ARP_CFG_HW_ADDR_LEN);
break;
default: /* See Note #3. */
NET_CTR_ERR_INC(NetARP_ErrRxHdrOpCodeCtr);
*perr = NET_ARP_ERR_INVALID_OP_CODE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
#else /* See Note #2c. */
target_hw = DEF_YES;
#endif
/* ----------- VERIFY TARGET PROTOCOL ADDR ------------ */
paddr_target_protocol = parp_hdr->ProtocolAddrTarget;
target_protocol = Mem_Cmp((void *)paddr_target_protocol,
(void *)NetARP_HostAddrPtrProtocol,
(CPU_SIZE_T)NET_ARP_CFG_PROTOCOL_ADDR_LEN);
/* -------------- RTN TARGET VALIDATION --------------- */
*perr = ((target_hw == DEF_YES) &&
(target_protocol == DEF_YES)) ? NET_ARP_ERR_RX_TARGET_THIS_HOST :
NET_ARP_ERR_RX_TARGET_NOT_THIS_HOST;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_RxPktFree()
*
* Description : Free network buffer.
*
* Argument(s) : pbuf Pointer to network buffer.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Rx().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetARP_RxPktFree (NET_BUF *pbuf)
{
NetBuf_FreeBuf((NET_BUF *)pbuf,
(NET_CTR *)0);
}
/*
*********************************************************************************************************
* NetARP_RxPktDiscard()
*
* Description : On any ARP Receive errors, discard ARP packet & buffer.
*
* Argument(s) : pbuf Pointer to network buffer.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ERR_RX Receive error; packet discarded.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Rx().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetARP_RxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr)
{
NET_CTR *pctr;
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
pctr = (NET_CTR *)&NetARP_ErrRxPktDiscardedCtr;
#else
pctr = (NET_CTR *) 0;
#endif
NetBuf_FreeBuf((NET_BUF *)pbuf,
(NET_CTR *)pctr);
*perr = NET_ERR_RX;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_Tx()
*
* Description : (1) Prepare & transmit an ARP Request or ARP Reply :
*
* (a) Get network buffer for ARP transmit packet
* (b) Prepare & transmit packet
* (c) Free transmit packet buffer(s)
* (d) Update transmit statistics
*
*
* Argument(s) : paddr_hw_sender Pointer to sender's hardware address (see Note #2).
*
* paddr_hw_target Pointer to target's hardware address (see Note #2).
*
* paddr_protocol_sender Pointer to sender's protocol address (see Note #2).
*
* paddr_protocol_target Pointer to target's protocol address (see Note #2).
*
* op_code ARP operation : Request or Reply.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE ARP packet successfully transmitted.
* NET_ARP_ERR_NULL_PTR Argument(s) passed a NULL pointer.
* NET_ARP_ERR_INVALID_OP_CODE Invalid ARP operation code.
*
* ------- RETURNED BY NetBuf_Get() : -------
* NET_BUF_ERR_NONE_AVAIL NO available buffers to allocate.
* NET_BUF_ERR_INVALID_TYPE Network buffer is NOT a valid buffer type.
* NET_BUF_ERR_INVALID_SIZE Requested size is greater then the maximum
* buffer size available.
*
* -- RETURNED BY NetARP_TxPktDiscard() : ---
* NET_ERR_TX Transmit error; packet discarded.
*
* -------- RETURNED BY NetIF_Tx() : --------
* NET_ERR_INIT_INCOMPLETE Network initialization NOT complete.
*
* Return(s) : none.
*
* Caller(s) : NetARP_TxReq(),
* NetARP_TxReply().
*
* Note(s) : (2) ARP addresses MUST be in network-order.
*
* (3) Assumes network buffer's protocol header size is large enough to accomodate ARP header
* size (see 'net_buf.h NETWORK BUFFER INDEX & SIZE DEFINES Note #1').
*
* (4) Network buffer already freed by lower layer; only increment error counter.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetARP_Tx (CPU_INT08U *paddr_hw_sender,
CPU_INT08U *paddr_hw_target,
CPU_INT08U *paddr_protocol_sender,
CPU_INT08U *paddr_protocol_target,
CPU_INT16U op_code,
NET_ERR *perr)
{
#if (((NET_CTR_CFG_STAT_EN == DEF_ENABLED) || \
(NET_CTR_CFG_ERR_EN == DEF_ENABLED)) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
CPU_INT16U msg_ix;
NET_BUF *pbuf;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
/* ------------------- VALIDATE PTRS ------------------ */
if (paddr_hw_sender == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
NET_CTR_ERR_INC(NetARP_ErrTxPktDiscardedCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
if (paddr_protocol_sender == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
NET_CTR_ERR_INC(NetARP_ErrTxPktDiscardedCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
if (paddr_protocol_target == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
NET_CTR_ERR_INC(NetARP_ErrTxPktDiscardedCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
/* -------------------- VALIDATE OP ------------------- */
switch (op_code) {
case NET_ARP_HDR_OP_REQ: /* For ARP Req, NULL hw addr ptr expected. */
break;
case NET_ARP_HDR_OP_REPLY:
if (paddr_hw_target == (CPU_INT08U *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
NET_CTR_ERR_INC(NetARP_ErrTxPktDiscardedCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
break;
default:
NET_CTR_ERR_INC(NetARP_ErrTxHdrOpCodeCtr);
NET_CTR_ERR_INC(NetARP_ErrTxPktDiscardedCtr);
*perr = NET_ARP_ERR_INVALID_OP_CODE;
return; /* Prevent 'break NOT reachable' compiler warning. */
}
#endif
/*$PAGE*/
/* --------------------- GET BUF ---------------------- */
#if (NET_BUF_DATA_TX_IX < NET_ARP_HDR_SIZE) /* See Note #3. */
NET_CTR_ERR_INC(NetARP_ErrTxInvalidBufIxCtr);
return;
#endif
msg_ix = NET_BUF_DATA_TX_IX - NET_ARP_HDR_SIZE;
pbuf = NetBuf_Get((NET_BUF_SIZE)NET_ARP_MSG_LEN_DATA,
(NET_BUF_SIZE)msg_ix,
(CPU_INT16U )NET_BUF_FLAG_NONE,
(NET_ERR *)perr);
if (*perr != NET_BUF_ERR_NONE) {
return;
}
/* ---------------- PREPARE/TX ARP PKT ---------------- */
NetARP_TxPktPrepareHdr(pbuf,
msg_ix,
paddr_hw_sender,
paddr_hw_target,
paddr_protocol_sender,
paddr_protocol_target,
op_code,
perr);
switch (*perr) {
case NET_ARP_ERR_NONE:
NetIF_Tx(pbuf, perr);
break;
case NET_ARP_ERR_NULL_PTR:
default:
NetARP_TxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
/* ---------- FREE TX PKT / UPDATE TX STATS ----------- */
switch (*perr) { /* Chk err from NetIF_Tx(). */
case NET_IF_ERR_NONE:
NetARP_TxPktFree(pbuf);
NET_CTR_STAT_INC(NetARP_StatTxMsgCtr);
*perr = NET_ARP_ERR_NONE;
break;
case NET_ERR_TX:
NET_CTR_ERR_INC(NetARP_ErrTxPktDiscardedCtr); /* See Note #4. */
return; /* Prevent 'break NOT reachable' compiler warning. */
case NET_ERR_INIT_INCOMPLETE:
default:
NetARP_TxPktDiscard(pbuf, perr);
return; /* Prevent 'break NOT reachable' compiler warning. */
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_TxReq()
*
* Description : (1) Prepare & transmit an ARP Request to resolve a pending ARP cache :
*
* (a) Configure sender's hardware address as this host's hardware address
* (b) Configure target's hardware address as NULL since unknown
* (c) Configure sender's protocol address as this host's protocol address
* (d) Configure target's protocol address as the protocol address listed in the ARP cache
* (e) Configure ARP operation as ARP Request
*
*
* Argument(s) : pcache Pointer to an ARP cache.
* ------ Argument checked in NetARP_CacheAddPend(),
* NetARP_CacheReqTimeout().
*
* Return(s) : none.
*
* Caller(s) : NetARP_CacheAddPend(),
* NetARP_CacheReqTimeout().
*
* Note(s) : (2) Do NOT need to verify success of ARP Request since failure will cause timeouts & retries.
*********************************************************************************************************
*/
static void NetARP_TxReq (NET_ARP_CACHE *pcache)
{
#if ((NET_CTR_CFG_STAT_EN == DEF_ENABLED) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
CPU_INT08U *paddr_hw_sender;
CPU_INT08U *paddr_hw_target;
CPU_INT08U *paddr_protocol_sender;
CPU_INT08U *paddr_protocol_target;
CPU_INT16U op_code;
NET_ERR err_tx;
/* Cfg ARP Req from ARP cache data (see Note #1). */
paddr_hw_sender = (CPU_INT08U *) NetARP_HostAddrPtrHW;
paddr_hw_target = (CPU_INT08U *) 0;
paddr_protocol_sender = (CPU_INT08U *) NetARP_HostAddrPtrProtocol;
paddr_protocol_target = (CPU_INT08U *)&pcache->ProtocolAddr[0];
op_code = NET_ARP_HDR_OP_REQ;
NetARP_Tx(paddr_hw_sender,
paddr_hw_target,
paddr_protocol_sender,
paddr_protocol_target,
op_code,
&err_tx);
if (err_tx == NET_ARP_ERR_NONE) {
NET_CTR_STAT_INC(NetARP_StatTxMsgReqCtr);
}
pcache->ReqAttemptsCtr++; /* Inc req attempts ctr. */
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_TxReply()
*
* Description : (1) Prepare & transmit an ARP Reply in response to an ARP Request :
*
* (a) Configure sender's hardware address as this host's hardware address
* (b) Configure target's hardware address from the ARP Request's sender hardware address
* (c) Configure sender's protocol address from the ARP Request's target protocol address
* (d) Configure target's protocol address from the ARP Request's sender protocol address
* (e) Configure ARP operation as ARP Reply
*
*
* Argument(s) : parp_hdr Pointer to a packet's ARP header.
* -------- Argument checked in NetARP_RxPktValidate().
*
* Return(s) : none.
*
* Caller(s) : NetARP_RxPktReply().
*
* Note(s) : (2) Do NOT need to verify success of ARP Reply since failure will cause timeouts & retries.
*********************************************************************************************************
*/
static void NetARP_TxReply (NET_ARP_HDR *parp_hdr)
{
#if ((NET_CTR_CFG_STAT_EN == DEF_ENABLED) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
CPU_INT08U *paddr_hw_sender;
CPU_INT08U *paddr_hw_target;
CPU_INT08U *paddr_protocol_sender;
CPU_INT08U *paddr_protocol_target;
CPU_INT16U op_code;
NET_ERR err_tx;
/* Cfg ARP Reply from ARP Req (see Note #1). */
paddr_hw_sender = (CPU_INT08U *) NetARP_HostAddrPtrHW;
paddr_hw_target = (CPU_INT08U *)&parp_hdr->HW_AddrSender[0];
paddr_protocol_sender = (CPU_INT08U *)&parp_hdr->ProtocolAddrTarget[0];
paddr_protocol_target = (CPU_INT08U *)&parp_hdr->ProtocolAddrSender[0];
op_code = NET_ARP_HDR_OP_REPLY;
NetARP_Tx(paddr_hw_sender,
paddr_hw_target,
paddr_protocol_sender,
paddr_protocol_target,
op_code,
&err_tx);
if (err_tx == NET_ARP_ERR_NONE) {
NET_CTR_STAT_INC(NetARP_StatTxMsgReplyCtr);
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_TxPktPrepareHdr()
*
* Description : (1) Prepare ARP packet header :
*
* (a) Update network buffer's index & length controls.
*
* (b) Prepare the transmit packet's following ARP header fields :
*
* (1) Hardware Type
* (2) Protocol Type
* (3) Hardware Address Length
* (4) Protocol Address Length
* (5) Operation Code
* (6) Sender's Hardware Address
* (7) Sender's Protocol Address
* (8) Target's Hardware Address
* (9) Target's Protocol Address
*
* (c) Convert the following ARP header fields from host-order to network-order :
*
* (1) Hardware Type
* (2) Protocol Type
* (3) Operation Code
*
* (d) Configure ARP protocol address pointer (see Note #2).
*
*
* Argument(s) : pbuf Pointer to network buffer to prepare ARP packet.
*
* msg_ix Buffer index to prepare ARP packet.
* ------ Argument checked in NetARP_Tx().
*
* paddr_hw_sender Pointer to sender's hardware address (see Note #2).
* --------------- Argument checked in NetARP_Tx().
*
* paddr_hw_target Pointer to target's hardware address (see Note #2).
* --------------- Argument checked in NetARP_Tx().
*
* paddr_protocol_sender Pointer to sender's protocol address (see Note #2).
* --------------------- Argument checked in NetARP_Tx().
*
* paddr_protocol_target Pointer to target's protocol address (see Note #2).
* --------------------- Argument checked in NetARP_Tx().
*
* op_code ARP operation : Request or Reply.
* ------- Argument checked in NetARP_Tx().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE ARP packet successfully prepared.
* NET_ARP_ERR_NULL_PTR Argument 'pbuf' passed a NULL pointer.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Tx().
*
* Note(s) : (2) ARP addresses MUST be in network-order.
*
* (3) Some buffer controls were previously initialized in NetBuf_Get() when the buffer was
* allocated. These buffer controls do NOT need to be re-initialized but are shown for
* completeness.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetARP_TxPktPrepareHdr (NET_BUF *pbuf,
CPU_INT16U msg_ix,
CPU_INT08U *paddr_hw_sender,
CPU_INT08U *paddr_hw_target,
CPU_INT08U *paddr_protocol_sender,
CPU_INT08U *paddr_protocol_target,
CPU_INT16U op_code,
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
NET_BUF_HDR *pbuf_hdr;
NET_ARP_HDR *parp_hdr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* --------------- VALIDATE PTR --------------- */
if (pbuf == (NET_BUF *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
*perr = NET_ARP_ERR_NULL_PTR;
return;
}
#endif
/* ------------- UPDATE BUF CTRLS ------------- */
pbuf_hdr = &pbuf->Hdr;
pbuf_hdr->ARP_MsgIx = (CPU_INT16U )msg_ix;
pbuf_hdr->ARP_MsgLen = (CPU_INT16U )NET_ARP_HDR_SIZE;
pbuf_hdr->TotLen = (NET_BUF_SIZE)pbuf_hdr->ARP_MsgLen;
pbuf_hdr->ProtocolHdrType = NET_PROTOCOL_TYPE_ARP;
#if 0 /* Init'd in NetBuf_Get() [see Note #3]. */
pbuf_hdr->DataIx = NET_BUF_IX_NONE;
pbuf_hdr->DataLen = 0;
#endif
/* ------------- PREPARE ARP HDR -------------- */
parp_hdr = (NET_ARP_HDR *)&pbuf->Data[pbuf_hdr->ARP_MsgIx];
/* ------ PREPARE ARP HW/PROTOCOL TYPES ------- */
NET_UTIL_VAL_SET_NET_16(&parp_hdr->HW_Type, NET_ARP_CFG_HW_TYPE);
NET_UTIL_VAL_SET_NET_16(&parp_hdr->ProtocolType, NET_ARP_CFG_PROTOCOL_TYPE);
/* ---- PREPARE ARP HW/PROTOCOL ADDR LENS ----- */
parp_hdr->HW_AddrLen = NET_ARP_CFG_HW_ADDR_LEN;
parp_hdr->ProtocolAddrLen = NET_ARP_CFG_PROTOCOL_ADDR_LEN;
/* ----------- PREPARE ARP OP CODE ------------ */
NET_UTIL_VAL_COPY_SET_NET_16(&parp_hdr->OpCode, &op_code);
/* --- PREPARE ARP HW/PROTOCOL SENDER ADDRS --- */
Mem_Copy((void *)&parp_hdr->HW_AddrSender[0],
(void *) paddr_hw_sender,
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
Mem_Copy((void *)&parp_hdr->ProtocolAddrSender[0],
(void *) paddr_protocol_sender,
(CPU_SIZE_T) NET_ARP_CFG_PROTOCOL_ADDR_LEN);
/* --- PREPARE ARP HW/PROTOCOL TARGET ADDRS --- */
if (paddr_hw_target == (CPU_INT08U *)0) { /* If ARP target hw addr NULL for ARP Req, ... */
Mem_Clr( (void *)&parp_hdr->HW_AddrTarget[0], /* .. clr target hw addr octets. */
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
DEF_BIT_SET(pbuf_hdr->Flags, NET_BUF_FLAG_BROADCAST_TX); /* ARP Req broadcast to ALL hosts on local net. */
} else { /* Else copy target hw addr for ARP Reply. */
Mem_Copy((void *)&parp_hdr->HW_AddrTarget[0],
(void *) paddr_hw_target,
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
/* ARP Reply tx'd directly to target host. */
}
Mem_Copy((void *)&parp_hdr->ProtocolAddrTarget[0],
(void *) paddr_protocol_target,
(CPU_SIZE_T) NET_ARP_CFG_PROTOCOL_ADDR_LEN);
/* -------- CFG ARP PROTOCOL ADDR PTR --------- */
pbuf_hdr->ARP_AddrProtocolPtr = &parp_hdr->ProtocolAddrTarget[0];
*perr = NET_ARP_ERR_NONE;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_TxPktFree()
*
* Description : Free network buffer.
*
* Argument(s) : pbuf Pointer to network buffer.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Tx().
*
* Note(s) : (1) (a) Although ARP Transmit initially requests the network buffer for transmit,
* the ARP layer does NOT maintain a reference to the buffer.
*
* (b) Also, since the network interface layer frees ALL unreferenced buffers
* after successful transmission [see 'net_if_pkt.c NetIF_Pkt_TxPktFree()'
* or 'net_if_char.c NetIF_Char_TxPktFree()'], the ARP layer MUST not
* free the transmit buffer.
*********************************************************************************************************
*/
static void NetARP_TxPktFree (NET_BUF *pbuf)
{
(void)&pbuf; /* Prevent compiler warning (see Note #1). */
}
/*
*********************************************************************************************************
* NetARP_TxPktDiscard()
*
* Description : On any transmit handler errors, discard packet & buffer.
*
* Argument(s) : pbuf Pointer to network buffer.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ERR_TX Transmit error; packet discarded.
*
* Return(s) : none.
*
* Caller(s) : NetARP_Tx().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetARP_TxPktDiscard (NET_BUF *pbuf,
NET_ERR *perr)
{
NET_CTR *pctr;
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
pctr = (NET_CTR *)&NetARP_ErrTxPktDiscardedCtr;
#else
pctr = (NET_CTR *) 0;
#endif
NetBuf_FreeBuf((NET_BUF *)pbuf,
(NET_CTR *)pctr);
*perr = NET_ERR_TX;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheTxPktHandler()
*
* Description : (1) Transmit packet buffers from ARP cache transmit buffer queue :
*
* (a) Resolve packet buffer(s)' hardware address(s)
* (b) Update packet buffer(s)' unlink/reference values
* (c) Transmit packet buffer(s)
*
*
* Argument(s) : pbuf_q Pointer to network buffer(s) to transmit.
*
* paddr_hw Pointer to sender's hardware address (see Note #2).
* -------- Argument checked in NetARP_RxPktCacheUpdate().
*
* Return(s) : none.
*
* Caller(s) : NetARP_RxPktCacheUpdate().
*
* Note(s) : (2) ARP addresses MUST be in network-order.
*
* (3) RFC #1122, Section 2.3.2.2 states that "the link layer SHOULD" ... :
*
* (a) "Save (rather than discard) ... packets destined to the same unresolved
* IP address and" ...
* (b) "Transmit the saved packet[s] when the address has been resolved."
*********************************************************************************************************
*/
static void NetARP_CacheTxPktHandler (NET_BUF *pbuf_q,
CPU_INT08U *paddr_hw)
{
NET_BUF *pbuf_list;
NET_BUF *pbuf_list_next;
NET_BUF *pbuf;
NET_BUF *pbuf_next;
NET_BUF_HDR *pbuf_hdr;
CPU_INT08U *pbuf_addr_hw;
NET_ERR err;
pbuf_list = pbuf_q;
while (pbuf_list != (NET_BUF *)0) { /* Handle ALL buf lists in Q. */
pbuf_hdr = &pbuf_list->Hdr;
pbuf_list_next = (NET_BUF *)pbuf_hdr->NextSecListPtr;
pbuf = (NET_BUF *)pbuf_list;
while (pbuf != (NET_BUF *)0) { /* Handle ALL bufs in buf list. */
pbuf_hdr = &pbuf->Hdr;
pbuf_next = (NET_BUF *)pbuf_hdr->NextBufPtr;
pbuf_addr_hw = pbuf_hdr->ARP_AddrHW_Ptr;
Mem_Copy((void *)pbuf_addr_hw, /* Copy hw addr into pkt buf. */
(void *)paddr_hw,
(CPU_SIZE_T)NET_ARP_CFG_HW_ADDR_LEN);
/* Clr buf sec list & unlink ptrs. */
pbuf_hdr->PrevSecListPtr = (void *)0;
pbuf_hdr->NextSecListPtr = (void *)0;
pbuf_hdr->UnlinkFnctPtr = (CPU_FNCT_PTR)0;
pbuf_hdr->UnlinkObjPtr = (void *)0;
NetIF_TxPkt(pbuf, &err); /* Tx pkt to IF (see Note #3b). */
pbuf = pbuf_next;
}
pbuf_list = pbuf_list_next;
}
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheSrch()
*
* Description : Search ARP Cache List for ARP cache with specific protocol address.
*
* (1) (a) ARP Cache List resolves protocol-address-to-hardware-address bindings based on the
* following ARP cache fields :
*
* - Hardware Type Configured at compile time (see Note #1a1)
* - Hardware Address Length Configured at compile time (see Note #1a1)
* - Protocol Type Configured at compile time (see Note #1a1)
* - Protocol Address Length Configured at compile time (see Note #1a1)
* - Protocol Address Generated at run time
*
* (1) These fields are configured at compile time (see 'net_arp.h ARP CACHE Note #3').
*
* (b) ARP caches are linked to form an ARP Cache List. In the diagram below, the
* top horizontal row represents the list of ARP caches.
*
* (1) 'NetARP_CacheListHead' points to the head of the ARP Cache List;
* 'NetARP_CacheListTail' points to the tail of the ARP Cache List.
*
* (2) ARP caches' 'PrevPtr' & 'NextPtr' doubly-link each ARP cache to form the
* ARP Cache List.
*
* (c) ARP caches in the 'PENDING' state are pending hardware address resolution by an
* ARP Reply. While in the 'PENDING' state, ALL transmit packet buffers are enqueued
* for later transmission when the corresponding ARP Reply is received.
*
* (1) ARP caches' 'BufQ_Head' points to the head of the pending transmit packet queue;
* ARP caches' 'BufQ_Tail' points to the tail of the pending transmit packet queue.
*
* (2) Buffer's 'PrevSecListPtr' & 'NextSecListPtr' link each buffer in a pending transmit
* packet queue.
*
* (d) For any ARP cache lookup, all ARP caches are searched in order to find the ARP cache
* with the appropriate hardware address--i.e. the ARP cache with the corresponding
* protocol address (see Note #1a).
*
* (e) New ARP caches are added at the head of the ARP Cache List. This allows faster ARP
* cache lookup for recently added ARP caches.
*
* (f) As ARP caches are added into the list, older ARP caches migrate to the tail of the
* ARP Cache List. Once an ARP cache expires or is discarded, it is removed from the
* ARP Cache List. Also if the ARP Cache List is full & a new ARP cache is needed,
* then the oldest ARP cache at the tail of the list is removed for allocation.
*
*$PAGE*
*
* | |
* |<------------ List of ARP Caches ------------->|
* | (see Note #1b) |
*
* New ARP caches Oldest ARP cache
* inserted at head in ARP Cache List
* (see Note #1e) (see Note #1f)
*
* | NextPtr |
* | (see Note #1b2) |
* v | v
* |
* Head of ------- ------- v ------- ------- (see Note #1b1)
* ARP Cache ---->| |------>| |------>| |------>| |
* List | | | | | | | | Tail of
* | |<------| |<------| |<------| |<---- ARP Cache
* (see Note #1b1) ------- ------- ^ ------- ------- List
* | | | | |
* | | | | |
* | ------ PrevPtr | ------
* BufQ_Head ---> | | (see Note #1b2) | | <--- BufQ_Tail
* (see Note #1c1) v | v | (see Note #1c1)
* --- ------- | ------- |
* ^ | | | | | |
* | | | | | | |
* | | | | | | |
* | | | | | | |
* | ------- | ------- |
* | | ^ | | ^ |
* | NextSecListPtr ---> | | | | | <----- PrevSecListPtr
* | (see Note #1c2) v | | v | | (see Note #1c2)
* | ------- | ------- |
* | | | | |<--
* Buffers pending on | | | | |
* ARP cache resolution | | | -------
* (see Note #1c) | | |
* ------- |
* | | ^ |
* | | | |
* | v | |
* | ------- |
* | | |<--
* | | |
* | | |
* v | |
* --- -------
*
*
* Argument(s) : paddr_protocol Pointer to protocol address (see Note #2).
* -------------- Argument checked in NetARP_CacheHandler().
*
* Return(s) : Pointer to ARP cache with specific protocol address, if found.
*
* Pointer to NULL, otherwise.
*
* Caller(s) : NetARP_CacheHandler().
*
* Note(s) : (2) 'paddr_protocol' MUST point to a protocol address that is in network-order.
*
* See also 'NetARP_CacheHandler() Note #2e3'.
*********************************************************************************************************
*/
/*$PAGE*/
static NET_ARP_CACHE *NetARP_CacheSrch (CPU_INT08U *paddr_protocol)
{
#if ((NET_CTR_CFG_STAT_EN == DEF_ENABLED) && \
(CPU_CFG_CRITICAL_METHOD == CPU_CRITICAL_METHOD_STATUS_LOCAL))
CPU_SR cpu_sr;
#endif
CPU_BOOLEAN found;
NET_ARP_CACHE *pcache;
NET_ARP_CACHE *pcache_next;
CPU_INT08U *pcache_addr;
NET_CTR_STAT_INC_LARGE(NetARP_CacheSrchCtr_hi, NetARP_CacheSrchCtr_lo);
pcache = NetARP_CacheListHead; /* Start @ ARP Cache List head. */
found = DEF_NO;
while ((pcache != (NET_ARP_CACHE *)0) && /* Srch ARP Cache List ... */
(found == DEF_NO)) { /* ... until cache found. */
pcache_next = (NET_ARP_CACHE *) pcache->NextPtr;
pcache_addr = (CPU_INT08U *)&pcache->ProtocolAddr[0];
/* Cmp ARP cache protocol addr. */
found = Mem_Cmp((void *)paddr_protocol,
(void *)pcache_addr,
(CPU_SIZE_T)NET_ARP_CFG_PROTOCOL_ADDR_LEN);
if (found != DEF_YES) { /* If NOT found, adv to next ARP cache. */
pcache = pcache_next;
} else { /* Else rtn found ARP cache. */
pcache->AccessedCtr++;
if (pcache->AccessedCtr > NetARP_CacheAccessedTh_nbr) { /* If ARP cache accessed > th, & ... */
pcache->AccessedCtr = 0;
if (pcache != NetARP_CacheListHead) { /* .. ARP cache NOT @ list head, ... */
NetARP_CacheUnlink(pcache);
NetARP_CacheInsert(pcache); /* .. promote ARP cache to list head. */
}
}
NET_CTR_STAT_INC_LARGE(NetARP_CacheFoundCtr_hi, NetARP_CacheFoundCtr_lo);
}
}
return (pcache);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheAddPend()
*
* Description : (1) Add a 'PENDING' ARP cache into the ARP Cache List & transmit an ARP Request :
*
* (a) Configure ARP cache :
* (1) Get default-configured ARP cache
* (2) ARP cache state
* (3) Enqueue transmit buffer to ARP cache queue
* (b) Insert ARP cache into ARP Cache List
* (c) Transmit ARP Request to resolve ARP cache
*
*
* Argument(s) : pbuf Pointer to network buffer to transmit.
* ---- Argument checked in NetARP_CacheHandler().
*
* pbuf_hdr Pointer to network buffer header.
* -------- Argument validated in NetARP_CacheHandler().
*
* paddr_protocol Pointer to protocol address (see Note #2).
* -------------- Argument checked in NetARP_CacheHandler().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_CACHE_PEND ARP cache added in 'PENDING' state.
*
* --- RETURNED BY NetARP_CacheCfg() : ----
* NET_ARP_ERR_CACHE_NONE_AVAIL NO available ARP caches to allocate.
* NET_ARP_ERR_CACHE_INVALID_TYPE ARP cache is NOT a valid cache type.
* NET_TMR_ERR_NULL_OBJ Argument 'obj' passed a NULL pointer.
* NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer.
* NET_TMR_ERR_NONE_AVAIL NO available timers to allocate.
* NET_TMR_ERR_INVALID_TYPE Network timer is NOT a valid timer type.
*
* Return(s) : none.
*
* Caller(s) : NetARP_CacheHandler().
*
* Note(s) : (2) Assumes 'paddr_protocol' points to a valid protocol address that is in network-order.
*
* See also 'NetARP_CacheHandler() Note #2e3'.
*
* (3) (a) RFC #1122, Section 2.3.2.2 states that "the link layer SHOULD" ... :
*
* (1) "Save (rather than discard) ... packets destined to the same unresolved
* IP address and" ...
* (2) "Transmit the saved packet[s] when the address has been resolved."
*
* (b) Since ARP Layer is the last layer to handle & queue the transmit network
* buffer, it is NOT necessary to increment the network buffer's reference
* counter to include the pending ARP cache buffer queue as a new reference
* to the network buffer.
*
* (4) Some buffer controls were previously initialized in NetBuf_Get() when the packet
* was received at the network interface layer. These buffer controls do NOT need
* to be re-initialized but are shown for completeness.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetARP_CacheAddPend (NET_BUF *pbuf,
NET_BUF_HDR *pbuf_hdr,
CPU_INT08U *paddr_protocol,
NET_ERR *perr)
{
NET_ARP_CACHE *pcache;
/* ------------------ CFG ARP CACHE ------------------- */
pcache = NetARP_CacheCfg((CPU_INT08U *)0,
(CPU_INT08U *)paddr_protocol,
(CPU_FNCT_PTR)NetARP_CacheReqTimeout,
(NET_TMR_TICK)NetARP_ReqTimeout_tick,
(NET_ERR *)perr);
if (*perr != NET_ARP_ERR_NONE) {
return;
}
/* Cfg buf's unlink fnct/obj to ARP cache. */
pbuf_hdr->UnlinkFnctPtr = (CPU_FNCT_PTR)NetARP_CacheUnlinkBuf;
pbuf_hdr->UnlinkObjPtr = (void *)pcache;
#if 0 /* Init'd in NetBuf_Get() [see Note #4]. */
pbuf_hdr->PrevSecListPtr = (void *)0;
pbuf_hdr->NextSecListPtr = (void *)0;
#endif
/* Q buf to ARP cache (see Note #3a1). */
pcache->BufQ_Head = (NET_BUF *)pbuf;
pcache->BufQ_Tail = (NET_BUF *)pbuf;
pcache->State = NET_ARP_CACHE_STATE_PEND;
/* ------- INSERT ARP CACHE INTO ARP CACHE LIST ------- */
NetARP_CacheInsert(pcache);
/* -------------------- TX ARP REQ -------------------- */
NetARP_TxReq(pcache); /* Tx ARP req to resolve ARP cache. */
*perr = NET_ARP_ERR_CACHE_PEND;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheAddResolved()
*
* Description : (1) Add a 'RESOLVED' ARP cache into the ARP Cache List :
*
* (a) Configure ARP cache :
* (1) Get default-configured ARP cache
* (2) ARP cache state
* (b) Insert ARP cache into ARP Cache List
*
*
* Argument(s) : paddr_hw Pointer to hardware address (see Note #2).
* -------- Argument checked in NetARP_RxPktCacheUpdate().
*
* paddr_protocol Pointer to protocol address (see Note #2).
* -------------- Argument checked in NetARP_RxPktCacheUpdate().
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_CACHE_RESOLVED ARP cache added in 'RESOLVED' state.
*
* --- RETURNED BY NetARP_CacheCfg() : ----
* NET_ARP_ERR_CACHE_NONE_AVAIL NO available ARP caches to allocate.
* NET_ARP_ERR_CACHE_INVALID_TYPE ARP cache is NOT a valid cache type.
* NET_TMR_ERR_NULL_OBJ Argument 'obj' passed a NULL pointer.
* NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer.
* NET_TMR_ERR_NONE_AVAIL NO available timers to allocate.
* NET_TMR_ERR_INVALID_TYPE Network timer is NOT a valid timer type.
*
* Return(s) : none.
*
* Caller(s) : NetARP_RxPktCacheUpdate().
*
* Note(s) : (2) Assumes 'paddr_hw' & 'paddr_protocol' point to valid hardware & protocol addresses
* that are in network-order.
*
* See also 'NetARP_CacheHandler() Note #2e3'.
*********************************************************************************************************
*/
static void NetARP_CacheAddResolved (CPU_INT08U *paddr_hw,
CPU_INT08U *paddr_protocol,
NET_ERR *perr)
{
NET_ARP_CACHE *pcache;
/* ------------------ CFG ARP CACHE ------------------- */
pcache = NetARP_CacheCfg((CPU_INT08U *)paddr_hw,
(CPU_INT08U *)paddr_protocol,
(CPU_FNCT_PTR)NetARP_CacheTimeout,
(NET_TMR_TICK)NetARP_CacheTimeout_tick,
(NET_ERR *)perr);
if (*perr != NET_ARP_ERR_NONE) {
return;
}
pcache->State = NET_ARP_CACHE_STATE_RESOLVED;
/* ------- INSERT ARP CACHE INTO ARP CACHE LIST ------- */
NetARP_CacheInsert(pcache);
*perr = NET_ARP_ERR_CACHE_RESOLVED;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheRemove()
*
* Description : (1) Remove an ARP cache from the ARP Cache List :
*
* (a) Remove ARP cache from ARP Cache List
* (b) Free ARP cache back to ARP cache pool
*
*
* Argument(s) : pcache Pointer to an ARP cache.
* ------ Argument checked in NetARP_CacheHandler(),
* NetARP_RxPktCacheUpdate(),
* NetARP_CacheGet(),
* NetARP_CacheReqTimeout(),
* NetARP_CacheTimeout().
*
* tmr_free Indicate whether to free network timer :
*
* DEF_YES Free network timer for ARP cache.
* DEF_NO Do NOT free network timer for ARP cache
* [Freed by NetTmr_TaskHandler()].
*
* Return(s) : none.
*
* Caller(s) : NetARP_CacheHandler(),
* NetARP_RxPktCacheUpdate(),
* NetARP_CacheGet(),
* NetARP_CacheReqTimeout(),
* NetARP_CacheTimeout().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetARP_CacheRemove (NET_ARP_CACHE *pcache,
CPU_BOOLEAN tmr_free)
{
/* ------- REMOVE ARP CACHE FROM ARP CACHE LIST ------- */
NetARP_CacheUnlink(pcache);
/* ------------------ FREE ARP CACHE ------------------ */
NetARP_CacheFree(pcache, tmr_free);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheInsert()
*
* Description : Insert an ARP cache into the ARP Cache List at the head of the list.
*
* Argument(s) : pcache Pointer to an ARP cache.
* ------ Argument checked in NetARP_CacheSrch(),
* NetARP_CacheAddPend(),
* NetARP_CacheAddResolved().
*
* Return(s) : none.
*
* Caller(s) : NetARP_CacheSrch(),
* NetARP_CacheAddPend(),
* NetARP_CacheAddResolved().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetARP_CacheInsert (NET_ARP_CACHE *pcache)
{
pcache->PrevPtr = (void *)0;
pcache->NextPtr = (void *)NetARP_CacheListHead;
if (NetARP_CacheListHead != (NET_ARP_CACHE *)0) { /* If list NOT empty, insert before head. */
NetARP_CacheListHead->PrevPtr = (void *)pcache;
} else { /* Else add first ARP cache to list. */
NetARP_CacheListTail = (NET_ARP_CACHE *)pcache;
}
NetARP_CacheListHead = pcache; /* Insert ARP cache @ list head. */
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheUnlink()
*
* Description : Unlink an ARP cache from the ARP Cache List.
*
* Argument(s) : pcache Pointer to an ARP cache.
* ------ Argument checked in NetARP_CacheSrch();
* NetARP_CacheRemove()
* by NetARP_CacheHandler(),
* NetARP_CacheGet(),
* NetARP_CacheReqTimeout(),
* NetARP_CacheTimeout().
*
* Return(s) : none.
*
* Caller(s) : NetARP_CacheSrch(),
* NetARP_CacheRemove().
*
* Note(s) : (1) Since NetARP_CacheUnlink() called ONLY to remove & then re-link or free ARP caches,
* it is NOT necessary to clear the entry's previous & next pointers. However, pointers
* cleared to NULL shown for correctness & completeness.
*********************************************************************************************************
*/
static void NetARP_CacheUnlink (NET_ARP_CACHE *pcache)
{
NET_ARP_CACHE *pcache_prev;
NET_ARP_CACHE *pcache_next;
/* ------- UNLINK ARP CACHE FROM ARP CACHE LIST ------- */
pcache_prev = (NET_ARP_CACHE *)pcache->PrevPtr;
pcache_next = (NET_ARP_CACHE *)pcache->NextPtr;
/* Point prev ARP cache to next ARP cache. */
if (pcache_prev != (NET_ARP_CACHE *)0) {
pcache_prev->NextPtr = (void *)pcache_next;
} else {
NetARP_CacheListHead = (NET_ARP_CACHE *)pcache_next;
}
/* Point next ARP cache to prev ARP cache. */
if (pcache_next != (NET_ARP_CACHE *)0) {
pcache_next->PrevPtr = (void *)pcache_prev;
} else {
NetARP_CacheListTail = (NET_ARP_CACHE *)pcache_prev;
}
#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED) /* Clr ARP cache's ptrs (see Note #1). */
pcache->PrevPtr = (void *)0;
pcache->NextPtr = (void *)0;
#endif
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheUnlinkBuf()
*
* Description : Unlink a network buffer from a cache's transmit queue.
*
* Argument(s) : pbuf Pointer to network buffer enqueued in an ARP cache transmit buffer queue.
*
* Return(s) : none.
*
* Caller(s) : Referenced in NetARP_CacheHandler().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetARP_CacheUnlinkBuf (NET_BUF *pbuf)
{
#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)
CPU_BOOLEAN used;
#endif
NET_BUF *pbuf_prev;
NET_BUF *pbuf_next;
NET_BUF_HDR *pbuf_hdr;
NET_BUF_HDR *pbuf_hdr_prev;
NET_BUF_HDR *pbuf_hdr_next;
NET_ARP_CACHE *pcache;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
/* ------------------- VALIDATE PTR ------------------- */
if (pbuf == (NET_BUF *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
return;
}
/* ------------------- VALIDATE BUF ------------------- */
used = NetBuf_IsUsed(pbuf);
if (used != DEF_YES) {
return;
}
#endif
pbuf_hdr = (NET_BUF_HDR *)&pbuf->Hdr;
pcache = (NET_ARP_CACHE *) pbuf_hdr->UnlinkObjPtr;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ---------------- VALIDATE ARP CACHE ---------------- */
used = NetARP_CacheIsUsed(pcache);
if (used != DEF_YES) {
return;
}
#endif
/* ---------- UNLINK BUF FROM ARP CACHE TX Q ---------- */
pbuf_prev = (NET_BUF *)pbuf_hdr->PrevSecListPtr;
pbuf_next = (NET_BUF *)pbuf_hdr->NextSecListPtr;
/* Point prev ARP cache pending tx Q buf to next buf. */
if (pbuf_prev != (NET_BUF *)0) {
pbuf_hdr_prev = (NET_BUF_HDR *)&pbuf_prev->Hdr;
pbuf_hdr_prev->NextSecListPtr = (void *) pbuf_next;
} else {
pcache->BufQ_Head = (NET_BUF *) pbuf_next;
}
/* Point next ARP cache pending tx Q buf to prev buf. */
if (pbuf_next != (NET_BUF *)0) {
pbuf_hdr_next = (NET_BUF_HDR *)&pbuf_next->Hdr;
pbuf_hdr_next->PrevSecListPtr = (void *) pbuf_prev;
} else {
pcache->BufQ_Tail = (NET_BUF *) pbuf_prev;
}
/* -------------- CLR BUF'S UNLINK CTRLS -------------- */
pbuf_hdr->PrevSecListPtr = (void *)0; /* Clr pending tx Q ptrs. */
pbuf_hdr->NextSecListPtr = (void *)0;
pbuf_hdr->UnlinkFnctPtr = (CPU_FNCT_PTR)0; /* Clr unlink ptrs. */
pbuf_hdr->UnlinkObjPtr = (void *)0;
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheTimeout()
*
* Description : Discard an ARP cache in the 'RESOLVED' state on timeout.
*
* Argument(s) : pcache_timeout Pointer to an ARP cache (see Note #2b).
*
* Return(s) : none.
*
* Caller(s) : Referenced in NetARP_CacheAddResolved().
*
* Note(s) : (1) RFC #1122, Section 2.3.2.1 states that "an implementation of the Address Resolution
* Protocol (ARP) ... MUST provide a mechanism to flush out-of-date cache entries".
*
* (2) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]'
* type functions -- even though network timer API functions cast expiration functions
* to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
* (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a
* pointer to an object ... may be converted to a pointer to a different object
* ... [but] if the resulting pointer is not correctly aligned ... the behavior
* is undefined".
*
* And since compilers may NOT correctly convert 'void' pointers to non-'void'
* pointer arguments, network timer expiration functions MUST avoid incorrect
* pointer conversion behavior between 'void' pointer parameters & non-'void'
* pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
* (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted
* to or from a pointer to any ... object ... A pointer to any ... object ...
* may be converted to a pointer to void and back again; the result shall
* compare equal to the original pointer".
*
* (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
* network object pointer objects, network timer expiration functions MUST :
*
* (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); & ...
* (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
* (A) ... in this case, a 'NET_ARP_CACHE' pointer.
*
* See also 'net_tmr.c NetTmr_Get() Note #3'.
*
* (3) This function is a network timer expiration function :
*
* (a) Clear the timer pointer; ...
* (1) Cleared in NetARP_CacheFree() via NetARP_CacheRemove().
*
* (b) but do NOT re-free the timer.
*********************************************************************************************************
*/
static void NetARP_CacheTimeout (void *pcache_timeout)
{
#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_ARP_CACHE *pcache;
pcache = (NET_ARP_CACHE *)pcache_timeout; /* See Note #2b2A. */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
/* ------------------ VALIDATE PTR -------------------- */
if (pcache == (NET_ARP_CACHE *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
return;
}
/* ------------------ VALIDATE TYPE ------------------- */
if (pcache->Type != NET_ARP_TYPE_CACHE) {
NET_CTR_ERR_INC(NetARP_ErrInvalidTypeCtr);
return;
}
#endif
/* ---------------- DISCARD ARP CACHE ----------------- */
NetARP_CacheRemove((NET_ARP_CACHE *)pcache,
(CPU_BOOLEAN )DEF_NO); /* Clr but do NOT free tmr (see Note #3). */
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheReqTimeout()
*
* Description : Retry ARP Request to resolve an ARP cache in the 'PENDING' state on ARP Request timeout.
*
* Argument(s) : pcache_timeout Pointer to an ARP cache (see Note #1b).
*
* Return(s) : none.
*
* Caller(s) : Referenced in NetARP_CacheAddPend().
*
* Note(s) : (1) Ideally, network timer expiration functions could be defined as '[(void) (OBJECT *)]'
* type functions -- even though network timer API functions cast expiration functions
* to generic 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]').
*
* (a) (1) Unfortunately, ISO-IEC 9899-1999 ANSI-C, Section 6.3.2.3.7 states that "a
* pointer to an object ... may be converted to a pointer to a different object
* ... [but] if the resulting pointer is not correctly aligned ... the behavior
* is undefined".
*
* And since compilers may NOT correctly convert 'void' pointers to non-'void'
* pointer arguments, network timer expiration functions MUST avoid incorrect
* pointer conversion behavior between 'void' pointer parameters & non-'void'
* pointer arguments & therefore CANNOT be defined as '[(void) (OBJECT *)]'.
*
* (2) However, Section 6.3.2.3.1 states that "a pointer to void may be converted
* to or from a pointer to any ... object ... A pointer to any ... object ...
* may be converted to a pointer to void and back again; the result shall
* compare equal to the original pointer".
*
* (b) Therefore, to correctly convert 'void' pointer objects back to appropriate
* network object pointer objects, network timer expiration functions MUST :
*
* (1) Be defined as 'CPU_FNCT_PTR' type (i.e. '[(void) (void *)]'); & ...
* (2) Explicitly cast 'void' pointer arguments to specific object pointers; ...
* (A) ... in this case, a 'NET_ARP_CACHE' pointer.
*
* See also 'net_tmr.c NetTmr_Get() Note #3'.
*
* (2) This function is a network timer expiration function :
*
* (a) Clear the timer pointer; ...
* (1) Cleared in NetARP_CacheFree() via NetARP_CacheRemove(); or
* (2) Reset by NetTmr_Get().
*
* (b) but do NOT re-free the timer.
*********************************************************************************************************
*/
static void NetARP_CacheReqTimeout (void *pcache_timeout)
{
#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_ARP_CACHE *pcache;
NET_ERR err;
pcache = (NET_ARP_CACHE *)pcache_timeout; /* See Note #1b2A. */
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
/* ------------------ VALIDATE PTR -------------------- */
if (pcache == (NET_ARP_CACHE *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
return;
}
/* ------------------ VALIDATE TYPE ------------------- */
if (pcache->Type != NET_ARP_TYPE_CACHE) {
NET_CTR_ERR_INC(NetARP_ErrInvalidTypeCtr);
return;
}
#endif
if (pcache->ReqAttemptsCtr >= NetARP_ReqMaxAttempts_nbr) { /* If nbr attempts >= max, free ARP cache. */
NetARP_CacheRemove((NET_ARP_CACHE *)pcache,
(CPU_BOOLEAN )DEF_NO); /* Clr but do NOT free tmr (see Note #2). */
return;
}
/* ------------------ RETRY ARP REQ ------------------- */
pcache->TmrPtr = NetTmr_Get((void *) pcache,
(CPU_FNCT_PTR) NetARP_CacheReqTimeout,
(NET_TMR_TICK) NetARP_ReqTimeout_tick,
(CPU_INT16U ) NET_TMR_FLAG_NONE,
(NET_ERR *)&err);
if (err != NET_TMR_ERR_NONE) { /* If tmr unavail, free ARP cache. */
NetARP_CacheRemove((NET_ARP_CACHE *)pcache,
(CPU_BOOLEAN )DEF_NO); /* Clr but do NOT free tmr (see Note #2). */
return;
}
NetARP_TxReq(pcache);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheCfg()
*
* Description : (1) Configure an ARP cache :
*
* (a) Get ARP cache from ARP cache pool
* (b) Get ARP cache timer
* (c) Configure ARP cache :
* (1) Configure ARP cache addresses :
* (A) Protocol address
* (B) Hardware address
* (2) Configure ARP cache controls
*
*
* Argument(s) : paddr_hw Pointer to hardware address (see Note #2a).
*
* paddr_protocol Pointer to protocol address (see Note #2b).
* -------------- Argument checked in NetARP_ProbeAddrOnNet(),
* NetARP_CacheAddPend(),
* NetARP_CacheAddResolved().
*
* timeout_fnct Pointer to timeout function.
*
* timeout_tick Timeout value (in 'NET_TMR_TICK' ticks).
*
* perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE ARP cache successfully configured.
*
* ---- RETURNED BY NetARP_CacheGet() : ---
* NET_ARP_ERR_CACHE_NONE_AVAIL NO available ARP caches to allocate.
* NET_ARP_ERR_CACHE_INVALID_TYPE ARP cache is NOT a valid cache type.
*
* ------ RETURNED BY NetTmr_Get() : ------
* NET_TMR_ERR_NULL_OBJ Argument 'obj' passed a NULL pointer.
* NET_TMR_ERR_NULL_FNCT Argument 'fnct' passed a NULL pointer.
* NET_TMR_ERR_NONE_AVAIL NO available timers to allocate.
* NET_TMR_ERR_INVALID_TYPE Network timer is NOT a valid timer type.
*
* Return(s) : none.
*
* Caller(s) : NetARP_ProbeAddrOnNet(),
* NetARP_CacheAddPend(),
* NetARP_CacheAddResolved().
*
* Note(s) : (2) (a) If 'paddr_hw' available, points to a valid hardware address that is in network-order.
*
* (b) Assumes 'paddr_protocol' points to a valid protocol address that is in network-order.
*
* See also 'NetARP_CacheHandler() Note #2e3'.
*
* (3) On ANY errors, network resources MUST be appropriately freed.
*
* (4) During ARP cache initialization, some ARP cache controls were previously initialized
* in NetARP_CacheGet() when the ARP cache was allocated from the ARP cache pool. These
* ARP cache controls do NOT need to be re-initialized but are shown for completeness.
*********************************************************************************************************
*/
/*$PAGE*/
static NET_ARP_CACHE *NetARP_CacheCfg (CPU_INT08U *paddr_hw,
CPU_INT08U *paddr_protocol,
CPU_FNCT_PTR timeout_fnct,
NET_TMR_TICK timeout_tick,
NET_ERR *perr)
{
NET_ARP_CACHE *pcache;
/* ------------------ GET ARP CACHE ------------------- */
pcache = NetARP_CacheGet(perr);
if (pcache == (NET_ARP_CACHE *)0) {
return ((NET_ARP_CACHE *)0); /* Rtn err from NetARP_CacheGet(). */
}
/* ---------------- GET ARP CACHE TMR ----------------- */
pcache->TmrPtr = NetTmr_Get((void *)pcache,
(CPU_FNCT_PTR)timeout_fnct,
(NET_TMR_TICK)timeout_tick,
(CPU_INT16U )NET_TMR_FLAG_NONE,
(NET_ERR *)perr);
if (*perr != NET_TMR_ERR_NONE) { /* If tmr unavail, ... */
NetARP_CacheFree(pcache, DEF_NO); /* ... free ARP cache (see Note #3). */
return ((NET_ARP_CACHE *)0);
}
/* ------------------ CFG ARP CACHE ------------------- */
/* Cfg ARP cache addr(s). */
if (paddr_hw != (CPU_INT08U *)0) { /* If hw addr avail, ... */
Mem_Copy((void *)&pcache->HW_Addr[0], /* ... copy hw addr into ARP cache (see Note #2a). */
(void *) paddr_hw,
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
}
Mem_Copy((void *)&pcache->ProtocolAddr[0], /* Copy protocol addr into ARP cache (see Note #2b). */
(void *) paddr_protocol,
(CPU_SIZE_T) NET_ARP_CFG_PROTOCOL_ADDR_LEN);
/* Cfg ARP cache ctrl(s). */
#if 0 /* Init'd in NetARP_CacheGet() [see Note #4]. */
pcache->AccessedCtr = 0;
pcache->ReqAttemptsCtr = 0;
pcache->BufQ_Head = (NET_BUF *)0;
pcache->BufQ_Tail = (NET_BUF *)0;
/* Cfg'd in NetARP_CacheInsert(). */
pcache->PrevPtr = (void *)0;
pcache->NextPtr = (void *)0;
#endif
*perr = NET_ARP_ERR_NONE;
return (pcache);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheGet()
*
* Description : (1) Allocate & initialize an ARP cache :
*
* (a) Get an ARP cache
* (b) Validate ARP cache
* (c) Initialize ARP cache
* (d) Update ARP cache pool statistics
* (e) Return pointer to ARP cache
* OR
* Null pointer & error code, on failure
*
* (2) The ARP cache pool is implemented as a stack :
*
* (a) 'NetARP_CachePoolPtr' points to the head of the ARP cache pool.
*
* (b) ARP caches' 'NextPtr's link each ARP cache to form the ARP cache pool stack.
*
* (c) ARP caches are inserted & removed at the head of the ARP cache pool stack.
*
*
* ARP caches are
* inserted & removed
* at the head
* (see Note #2c)
*
* | NextPtr
* | (see Note #2b)
* v |
* |
* ------- ------- v ------- -------
* ARP Pool ---->| |------>| |------>| |------>| |
* Pointer | | | | | | | |
* | | | | | | | |
* (see Note #2a) ------- ------- ------- -------
*
* | |
* |<---------- Pool of Free ARP Caches ---------->|
* | (see Note #2) |
*
*
* Argument(s) : perr Pointer to variable that will receive the return error code from this function :
*
* NET_ARP_ERR_NONE ARP cache successfully allocated &
* initialized.
* NET_ARP_ERR_CACHE_NONE_AVAIL NO available ARP caches to allocate.
* NET_ARP_ERR_CACHE_INVALID_TYPE ARP cache is NOT a valid cache type.
*
* Return(s) : Pointer to ARP cache, if NO errors.
*
* Pointer to NULL, otherwise.
*
* Caller(s) : NetARP_CacheCfg().
*
* Note(s) : (3) (a) ARP cache pool is accessed by 'NetARP_CachePoolPtr' during execution of
*
* (1) NetARP_Init()
* (2) NetARP_CacheGet()
* (3) NetARP_CacheFree()
*
* (b) 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 the shared
* resources of the ARP cache pool since no asynchronous access from other network
* tasks is possible.
*
* (4) 'No cache available' case NOT possible during correct operation of the ARP Cache.
* However, the 'else' case is included as an extra precaution in case the ARP Cache
* List is incorrectly modified &/or corrupted.
*********************************************************************************************************
*/
/*$PAGE*/
static NET_ARP_CACHE *NetARP_CacheGet (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
NET_ARP_CACHE *pcache;
NET_ERR stat_err;
/* ------------------ GET ARP CACHE ------------------- */
if (NetARP_CachePoolPtr != (NET_ARP_CACHE *)0) { /* If ARP cache pool NOT empty, get cache from pool. */
pcache = (NET_ARP_CACHE *)NetARP_CachePoolPtr;
NetARP_CachePoolPtr = (NET_ARP_CACHE *)pcache->NextPtr;
} else if (NetARP_CacheListTail != (NET_ARP_CACHE *)0) { /* If ARP Cache List NOT empty, ... */
/* ... get ARP cache from list tail. */
pcache = (NET_ARP_CACHE *)NetARP_CacheListTail;
NetARP_CacheRemove(pcache, DEF_YES);
pcache = (NET_ARP_CACHE *)NetARP_CachePoolPtr;
NetARP_CachePoolPtr = (NET_ARP_CACHE *)pcache->NextPtr;
} else { /* Else none avail, rtn err (see Note #4). */
NET_CTR_ERR_INC(NetARP_ErrNoneAvailCtr);
*perr = NET_ARP_ERR_CACHE_NONE_AVAIL;
return ((NET_ARP_CACHE *)0);
}
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED) /* ---------------- VALIDATE ARP CACHE ---------------- */
if (pcache->Type != NET_ARP_TYPE_CACHE) {
NetARP_CacheDiscard(pcache);
NET_CTR_ERR_INC(NetARP_ErrInvalidTypeCtr);
*perr = NET_ARP_ERR_CACHE_INVALID_TYPE;
return ((NET_ARP_CACHE *)0);
}
#endif
/* ------------------ INIT ARP CACHE ------------------ */
NetARP_CacheClr(pcache);
DEF_BIT_SET(pcache->Flags, NET_ARP_FLAG_USED); /* Set ARP cache as used. */
/* ----------- UPDATE ARP CACHE POOL STATS ------------ */
NetStat_PoolEntryUsedInc(&NetARP_CachePoolStat, &stat_err);
*perr = NET_ARP_ERR_NONE;
return (pcache); /* ------------------ RTN ARP CACHE ------------------- */
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheFree()
*
* Description : (1) Free an ARP cache :
*
* (a) Free ARP cache timer
* (b) Free ARP cache buffer queue
* (c) Clear ARP cache controls
* (d) Free ARP cache back to ARP cache pool
* (e) Update ARP cache pool statistics
*
*
* Argument(s) : pcache Pointer to an ARP cache.
* ------ Argument checked in NetARP_CacheCfg(),
* NetARP_CacheRemove()
* by NetARP_CacheHandler(),
* NetARP_CacheGet(),
* NetARP_CacheReqTimeout(),
* NetARP_CacheTimeout().
*
* tmr_free Indicate whether to free network timer :
*
* DEF_YES Free network timer for ARP cache.
* DEF_NO Do NOT free network timer for ARP cache
* [Freed by NetTmr_TaskHandler()
* via NetARP_CacheRemove()].
*
* Return(s) : none.
*
* Caller(s) : NetARP_CacheCfg(),
* NetARP_CacheRemove().
*
* Note(s) : (2) #### To prevent freeing an ARP cache already freed via previous ARP cache free,
* NetARP_CacheFree() checks the ARP cache's 'USED' flag BEFORE freeing the cache.
*
* This prevention is only best-effort since any invalid duplicate ARP cache frees
* MAY be asynchronous to potentially valid ARP cache gets. Thus the invalid ARP
* cache free(s) MAY corrupt the ARP cache'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 ARP
* cache resources from possible corruption since no asynchronous access from other
* network tasks is possible.
*
* (3) When an ARP cache in the 'PENDING' state is freed, it discards its transmit packet
* buffer queue. The discard is performed by the network interface layer since it is
* the last layer to initiate transmission for these packet buffers.
*********************************************************************************************************
*/
/*$PAGE*/
static void NetARP_CacheFree (NET_ARP_CACHE *pcache,
CPU_BOOLEAN tmr_free)
{
#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)
CPU_BOOLEAN used;
#endif
NET_CTR *pctr;
NET_ERR err;
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
/* ---------------- VALIDATE TYPE ----------------- */
if (pcache->Type != NET_ARP_TYPE_CACHE) {
NetARP_CacheDiscard(pcache);
NET_CTR_ERR_INC(NetARP_ErrInvalidTypeCtr);
return;
}
/* ------------ VALIDATE ARP CACHE USED ----------- */
used = DEF_BIT_IS_SET(pcache->Flags, NET_ARP_FLAG_USED);
if (used != DEF_YES) { /* If ARP cache NOT used, ... */
NET_CTR_ERR_INC(NetARP_ErrNotUsedCtr);
return; /* ... rtn but do NOT free (see Note #2). */
}
#endif
/* -------------- FREE ARP CACHE TMR -------------- */
if (tmr_free == DEF_YES) {
if (pcache->TmrPtr != (NET_TMR *)0) {
NetTmr_Free(pcache->TmrPtr);
}
}
/* ------------- FREE ARP CACHE BUF Q ------------- */
#if (NET_CTR_CFG_ERR_EN == DEF_ENABLED)
pctr = (NET_CTR *)&NetIF_ErrTxPktDiscardedCtr; /* See Note #3. */
#else
pctr = (NET_CTR *) 0;
#endif
NetBuf_FreeBufQ_SecList((NET_BUF *)pcache->BufQ_Head,
(NET_CTR *)pctr,
(CPU_FNCT_PTR)NetARP_CacheUnlinkBuf);
/* ----------------- CLR ARP CACHE ---------------- */
pcache->State = NET_ARP_CACHE_STATE_FREE; /* Set ARP cache as freed/NOT used. */
DEF_BIT_CLR(pcache->Flags, NET_ARP_FLAG_USED);
#if (NET_DBG_CFG_MEM_CLR_EN == DEF_ENABLED)
NetARP_CacheClr(pcache);
#endif
/* ---------------- FREE ARP CACHE ---------------- */
pcache->NextPtr = (void *)NetARP_CachePoolPtr;
NetARP_CachePoolPtr = (NET_ARP_CACHE *)pcache;
/* --------- UPDATE ARP CACHE POOL STATS ---------- */
NetStat_PoolEntryUsedDec(&NetARP_CachePoolStat, &err);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheClr()
*
* Description : Clear ARP cache controls.
*
* Argument(s) : pcache Pointer to an ARP cache.
* ------ Argument validated in NetARP_Init(),
* NetARP_CacheGet(),
* NetARP_CacheFree().
*
* Return(s) : none.
*
* Caller(s) : NetARP_Init(),
* NetARP_CacheGet(),
* NetARP_CacheFree().
*
* Note(s) : none.
*********************************************************************************************************
*/
static void NetARP_CacheClr (NET_ARP_CACHE *pcache)
{
pcache->PrevPtr = (void *)0;
pcache->NextPtr = (void *)0;
pcache->BufQ_Head = (NET_BUF *)0;
pcache->BufQ_Tail = (NET_BUF *)0;
pcache->TmrPtr = (NET_TMR *)0;
pcache->AccessedCtr = 0;
pcache->ReqAttemptsCtr = 0;
pcache->State = NET_ARP_CACHE_STATE_FREE;
pcache->Flags = NET_ARP_FLAG_NONE;
Mem_Clr((void *)&pcache->HW_Addr[0],
(CPU_SIZE_T) NET_ARP_CFG_HW_ADDR_LEN);
Mem_Clr((void *)&pcache->ProtocolAddr[0],
(CPU_SIZE_T) NET_ARP_CFG_PROTOCOL_ADDR_LEN);
}
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheIsUsed()
*
* Description : Validate ARP cache in use.
*
* Argument(s) : pcache Pointer to object to validate as an ARP cache in use.
*
* Return(s) : DEF_YES, ARP cache valid & in use.
*
* DEF_NO, ARP cache invalid or NOT in use.
*
* Caller(s) : various.
*
* Note(s) : (1) NetARP_CacheIsUsed() MUST be called with the global network lock already acquired.
*********************************************************************************************************
*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static CPU_BOOLEAN NetARP_CacheIsUsed (NET_ARP_CACHE *pcache)
{
CPU_BOOLEAN used;
/* ------------------ VALIDATE PTR -------------------- */
if (pcache == (NET_ARP_CACHE *)0) {
return (DEF_NO);
}
/* ------------------ VALIDATE TYPE ------------------- */
if (pcache->Type != NET_ARP_TYPE_CACHE) {
return (DEF_NO);
}
/* ------------- VALIDATE ARP CACHE USED -------------- */
used = DEF_BIT_IS_SET(pcache->Flags, NET_ARP_FLAG_USED);
return (used);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* NetARP_CacheDiscard()
*
* Description : (1) Discard an invalid/corrupted ARP cache :
*
* (a) Discard ARP cache from available cache pool See Note #2
* (b) Update ARP cache pool statistics
*
* (2) Assumes ARP cache is invalid/corrupt & MUST be removed. ARP cache removed
* simply by NOT returning the ARP cache back to the ARP cache pool.
*
*
* Argument(s) : pcache Pointer to an invalid/corrupted ARP cache.
*
* Return(s) : none.
*
* Caller(s) : NetARP_CacheGet(),
* NetARP_CacheFree().
*
* Note(s) : none.
*********************************************************************************************************
*/
#if (NET_ERR_CFG_ARG_CHK_DBG_EN == DEF_ENABLED)
static void NetARP_CacheDiscard (NET_ARP_CACHE *pcache)
{
#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 ARP CACHE ----------------- */
if (pcache == (NET_ARP_CACHE *)0) {
NET_CTR_ERR_INC(NetARP_ErrNullPtrCtr);
return;
}
/* --------------- UPDATE DISCARD STATS --------------- */
NetStat_PoolEntryLostInc(&NetARP_CachePoolStat, &stat_err);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* MODULE END
*
* Note(s) : (1) See 'MODULE Note #1' & 'net_arp.h MODULE Note #1'.
*********************************************************************************************************
*/
#endif /* End of ARP module include (see Note #1). */