📄 ixhssacccodeletpkt.c
字号:
/** * @file IxHssAccCodeletPkt.c * * @date 21 May 2002 * * @brief This file contains the packetised implementation of the HSS * Access Codelet. * * * @par * IXP400 SW Release version 2.3 * * -- Copyright Notice -- * * @par * Copyright (c) 2001-2005, Intel Corporation. * All rights reserved. * * @par * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * * @par * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * @par * -- End of Copyright Notice -- * @sa IxHssAccCodelet.h * @sa IxHssAccCodeletPkt.h *//* * Put the system defined include files required. *//* * Put the user defined include files required. */#include "IxHssAcc.h"#include "IxOsal.h"#include "IxHssAccCodelet_p.h"#include "IxHssAccCodeletCom.h"#include "IxHssAccCodeletPkt.h"#include "IxHssAccCodeletMbuf.h"/* * #defines and macros used in this file. */#define MESSAGE_Q_SIZE (IX_HSSACC_CODELET_PKT_NUM_RX_BUFS)#define IX_HSSACC_CODELET_PKT_56K_HDLC_CLIENT IX_HSSACC_HDLC_PORT_2/* * Typedefs whose scope is limited to this file. */typedef struct{ IX_OSAL_MBUF *buffer; unsigned numHssErrs; IxHssAccPktStatus pktStatus;} CallbackParams;typedef enum{ RxCallback, RxFreeLowCallback, TxDoneCallback} MessageType;typedef struct{ MessageType type; CallbackParams params;} Message;typedef struct{ IxHssAccHssPort hssPortId; IxHssAccHdlcPort hdlcPortId; IxOsalThread threadId; IxOsalSemaphore messageSem; Message messageQ[MESSAGE_Q_SIZE]; unsigned qHead; unsigned qTail; /** packetised TX sample data - source of data for TX */ UINT8 pktTxSampleData; /** packetised RX sample data - to verify against TX data */ UINT8 pktRxSampleData; /** packetised mbuf pools */ IxHssAccCodeletMbufPool *mbufPoolPtr; BOOL mbufPoolInitialised; unsigned staleRawBytesRecieved;} ClientInfo;/* * Variable declarations global to this file only. Externs are followed by * static variables. */static ClientInfo clientInfo [IX_HSSACC_HSS_PORT_MAX] [IX_HSSACC_HDLC_PORT_MAX];static BOOL verify = TRUE;/* * Extern function prototypes. *//* * Static function prototypes. */PRIVATE unsignedmbufsCount (IX_OSAL_MBUF *buffer);PRIVATE voidixHssAccCodeletPktRxCallback ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, IxHssAccPktUserId rxUserId);PRIVATE voidixHssAccCodeletPktRxCallbackProcess ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, ClientInfo *pClientInfo);PRIVATE void ixHssAccCodeletPktRxFreeLowCallback (IxHssAccPktUserId rxFreeLowUserId);PRIVATE voidixHssAccCodeletPktRxFreeLowCallbackProcess (ClientInfo *pClientInfo);PRIVATE voidixHssAccCodeletPktTxDoneCallback ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, IxHssAccPktUserId txDoneUserId);PRIVATE voidixHssAccCodeletPktTxDoneCallbackProcess ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, ClientInfo *pClientInfo);PRIVATE IX_STATUSixHssAccCodeletPktThreadMain ( void* arg, void** ptrRetObj);/* * Function definition: mbufsCount */PRIVATEunsignedmbufsCount ( IX_OSAL_MBUF *buffer){ unsigned count; for (count = 0; buffer != NULL; buffer = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(buffer), count++) ; return count;}/** * @fn void ixHssAccCodeletPktRxCallback ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, IxHssAccPktUserId rxUserId) * * @param IX_OSAL_MBUF *buffer (in) - the mbuf containing the received packet. * @param unsigned numHssErrs (in) - the total number of HSS port errors * since initial port configuration. * @param IxHssAccPktStatus pktStatus (in) - indicates the status of * the received packet. * @param IxHssAccPktUserId rxUserId (in) - the value supplied during * ixHssAccPktPortConnect(), a pointer to the client's ClientInfo * structure. * * This function is of type IxHssAccPktRxCallback, the prototype of the * clients function to accept notification of packetised rx. * * This function is registered through ixHssAccPktPortConnect(). Received * packets are passed back to the client in the form of mbufs via this * callback. The mbuf passed back to the client could contain a chain of * mbufs, depending on the packet size received. * <P> * The callback updates RX statistics and returns the mbuf(s) to the RX * pool. If the HSS is as loopback then any received data is verified. */PRIVATEvoidixHssAccCodeletPktRxCallback ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, IxHssAccPktUserId rxUserId){ ClientInfo *pClientInfo = (ClientInfo *)rxUserId; Message *pMessage; /* add message to the head of the message queue */ pMessage = &pClientInfo->messageQ[pClientInfo->qHead++]; pClientInfo->qHead %= NUMELEMS(pClientInfo->messageQ); /* fill in the message */ pMessage->type = RxCallback; pMessage->params.buffer = buffer; pMessage->params.numHssErrs = numHssErrs; pMessage->params.pktStatus = pktStatus; /* wake up the message processing thread */ (void) ixOsalSemaphorePost (&pClientInfo->messageSem);}/* * Function definition: ixHssAccCodeletPktRxCallbackProcess */PRIVATEvoidixHssAccCodeletPktRxCallbackProcess ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, ClientInfo *pClientInfo){ IX_STATUS status ; IX_OSAL_MBUF *rxBuffer; IxHssAccHssPort hssPortId = pClientInfo->hssPortId; IxHssAccHdlcPort hdlcPortId = pClientInfo->hdlcPortId; unsigned wordIndex; unsigned byteIndex; UINT32 value; UINT8 expectedValue; /* for each buffer in the RX buffer chain */ for (rxBuffer = buffer; (rxBuffer != NULL) && (pktStatus == IX_HSSACC_PKT_OK); rxBuffer = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(rxBuffer)) { /* to allow for caching, we request a cache invalidate after rx */ IX_OSAL_CACHE_INVALIDATE (IX_OSAL_MBUF_MDATA(rxBuffer), IX_OSAL_MBUF_MLEN(rxBuffer)); /* if hardware is performing a loopback then verify the RX data */ if (ixHssAccCodeletHssLoopbackGet () && verify) { /* verify buffer contents */ for (wordIndex = 0; wordIndex < (UINT32)(IX_OSAL_MBUF_MLEN(rxBuffer) / 4); wordIndex++) { value = ((UINT32 *)IX_OSAL_MBUF_MDATA(rxBuffer))[wordIndex]; /* if this word is an idle pattern update idle stats */ if ((value == IX_HSSACC_CODELET_PKT_IDLE_PATTERN) || (value == IX_HSSACC_CODELET_PKT_RAW_IDLE_PATTERN)) { stats[hssPortId].pkt[hdlcPortId].rxIdles += 4; continue; } /* verify each byte of the word */ for (byteIndex = 0; byteIndex < 4; byteIndex++) { /* get/update the value we are expecting to receive */ expectedValue = pClientInfo->pktRxSampleData++; if (((UINT8 *)&value)[byteIndex] != expectedValue) { if (pClientInfo->staleRawBytesRecieved < IX_HSSACC_CODELET_PKT_RAW_STALE_BYTES_MAX) { /* In the first raw-mode packet recieved after the * HDLC port is enabled, it is normal to see a * few strange bytes at the start of the packet. * This is stale data from NPE buffers. We can * safely ignore these bytes */ pClientInfo->staleRawBytesRecieved++; pClientInfo->pktRxSampleData--; } else { stats[hssPortId].pkt[hdlcPortId].rxVerifyFails++; } } } } /* for (wordIndex ... */ } /* if (ixHssAccCodeletHssLoopbackGet ()) */ /* let higher priority tasks run (i.e. channelised service) */ ixOsalYield(); } /* for (rxBuffer ... */ stats[hssPortId].pkt[hdlcPortId].rxBufsInUse -= mbufsCount (buffer); /* if codelet is performing a loopback then re-transmit buffer */ if (ixHssAccCodeletCodeletLoopbackGet () && (pktStatus == IX_HSSACC_PKT_OK)) { stats[hssPortId].pkt[hdlcPortId].txBufsInUse += mbufsCount (buffer); /* transmit the received buffer */ status = ixHssAccPktPortTx (hssPortId, hdlcPortId, buffer); /* if there was any problem then free buffer and update stats */ if (status != IX_SUCCESS) { stats[hssPortId].pkt[hdlcPortId].txBufsInUse -= mbufsCount (buffer); ixHssAccCodeletMbufChainFree (buffer); stats[hssPortId].pkt[hdlcPortId].txFails++; } } else { /* free the buffer */ ixHssAccCodeletMbufChainFree (buffer); } if (pktStatus == IX_HSSACC_PKT_OK) { /* update RX stats */ stats[hssPortId].pkt[hdlcPortId].rxPackets++; stats[hssPortId].pkt[hdlcPortId].rxBytes += IX_OSAL_MBUF_PKT_LEN(buffer); } /* update error stats */ ixHssAccCodeletNumHssErrorsUpdate (hssPortId, numHssErrs); ixHssAccCodeletPktErrorsUpdate (hssPortId, hdlcPortId, pktStatus); /* if we're not stopping or disconnecting replenish the rxfree q */ if ((pktStatus != IX_HSSACC_STOP_SHUTDOWN_ERROR) && (pktStatus != IX_HSSACC_DISCONNECT_IN_PROGRESS)) { ixHssAccCodeletPktRxFreeLowCallbackProcess (pClientInfo); }}/** * @fn void ixHssAccCodeletPktRxFreeLowCallback ( IxHssAccPktUserId rxFreeLowUserId) * * @param IxHssAccPktUserId rxFreeLowUserId (in) - the value supplied * during ixHssAccPktPortConnect(), a pointer to the client's ClientInfo * structure. * * This function is of type IxHssAccPktRxFreeLowCallback, the prototype of * the clients function to accept notification of requirement of more Rx * Free buffers. * * This function is registered through ixHssAccPktPortConnect(). The * callback is invoked when more mbufs are required to receive packets * into. * <P> * The callback will provide additional mbufs by calling * ixHssAccPktPortRxFreeReplenish(). */PRIVATEvoidixHssAccCodeletPktRxFreeLowCallback ( IxHssAccPktUserId rxFreeLowUserId){ ClientInfo *pClientInfo = (ClientInfo *)rxFreeLowUserId; Message *pMessage; /* add message to the head of the message queue */ pMessage = &pClientInfo->messageQ[pClientInfo->qHead++]; pClientInfo->qHead %= NUMELEMS(pClientInfo->messageQ); /* fill in the message */ pMessage->type = RxFreeLowCallback; /* wake up the message processing thread */ (void) ixOsalSemaphorePost (&pClientInfo->messageSem);}/* * Function definition: ixHssAccCodeletPktRxFreeLowCallbackProcess */PRIVATEvoidixHssAccCodeletPktRxFreeLowCallbackProcess ( ClientInfo *pClientInfo){ IX_STATUS status = IX_SUCCESS; IX_OSAL_MBUF *rxBuffer; IxHssAccHssPort hssPortId = pClientInfo->hssPortId; IxHssAccHdlcPort hdlcPortId = pClientInfo->hdlcPortId; /* provide as many Rx buffers as we can, i.e. until we receive: */ /* a resource error - means IxHssAcc is out of resources */ /* a queue write overflow - means the RxFree queue is full */ do { /* get an RX buffer */ rxBuffer = ixHssAccCodeletMbufGet ( pClientInfo->mbufPoolPtr); /* if we got a buffer ok */ if (rxBuffer != NULL) { /* IMPORTANT: IxHssAcc component needs to know the capacity */ /* of the mbuf - we tell it via the mbuf's m_len field */ IX_OSAL_MBUF_MLEN(rxBuffer) = IX_HSSACC_CODELET_PKT_BUFSIZE; /* give the Rx buffer to the HssAcc component */ status = ixHssAccPktPortRxFreeReplenish ( hssPortId, hdlcPortId, rxBuffer); /* if the HssAcc component couldn't accept the Rx buffer */ if (status != IX_SUCCESS) { /* free the buffer */ (void) ixHssAccCodeletMbufChainFree (rxBuffer); /* if the error was other than expected */ if ((status != IX_HSSACC_RESOURCE_ERR) && (status != IX_HSSACC_Q_WRITE_OVERFLOW)) { stats[hssPortId].pkt[hdlcPortId].replenishFails++; } } else { stats[hssPortId].pkt[hdlcPortId].rxBufsInUse++; } } else /* no rx buffers available */ { stats[hssPortId].pkt[hdlcPortId].rxNoBuffers++; } } while ((rxBuffer != NULL) && (status == IX_SUCCESS));}/** * @fn void ixHssAccCodeletPktTxDoneCallback ( IX_OSAL_MBUF *buffer, unsigned numHssErrs, IxHssAccPktStatus pktStatus, IxHssAccPktUserId txDoneUserId) * * @param IX_OSAL_MBUF *buffer (in) - the mbuf containing the transmitted * packet. * @param unsigned numHssErrs (in) - the total number of HSS port errors * since initial port configuration. * @param IxHssAccPktStatus pktStatus (in) - indicates the status of * the transmitted packet. * @param IxHssAccPktUserId txDoneUserId (in) - the value supplied during * ixHssAccPktPortConnect(), a pointer to the client's ClientInfo * structure. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -