📄 ixoamcodelet.c
字号:
/* * @file IxOamCodelet.c * * @date 21-July-2002 * * @brief The module implements the loopback functionality * functions of the Oam Codelet. * * * IxOamCodelet API functions: * ixOamCodeletInit * ixOamCodeletOamF5EtePing * ixOamCodeletOamF5SegPing * ixOamCodeletOamF4EtePing * ixOamCodeletOamF4SegPing * ixOamCodeletShow * * @par * * @par * IXP400 SW Release version 2.1 * * -- 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 -- *//* * Put the user defined include files required */#if defined(__wince) && defined(IX_USE_SERCONSOLE) #include "IxSerConsole.h" #define printf ixSerPrintf #define gets ixSerGets#endif#include "IxAtmTypes.h"#include "IxOsal.h"#include "IxAtmdAcc.h"#include "IxAtmm.h"#include "IxAtmCodelet.h"#include "IxAtmCodelet_p.h"/* * #defines and macros used in this file. *//* IRQ safe logs, for use in callbacks which could be in the context of an IRQ */#define IX_OAM_CODELET_IRQ_SAFE_LOG(msg, param1, param2, param3, param4) \ (void) ixOsalLog(IX_OSAL_LOG_LVL_USER,IX_OSAL_LOG_DEV_STDOUT, msg, param1, param2, param3, param4, 0, 0);#define IX_OAM_CODELET_IRQ_SAFE_LOG_ERROR(msg) \ (void) ixOsalLog (IX_OSAL_LOG_LVL_ERROR,IX_OSAL_LOG_DEV_STDERR, msg, 0, 0, 0, 0, 0, 0);/* Normal Log */#define IX_OAM_CODELET_LOG printf#define IX_OAM_CODELET_LOG_ERROR printf#define IX_OAMCODELET_NUM_MBUFS_IN_SW_MBUF_Q 64 /* must be power of 2 */#define IX_OAM_REPLENISH_WATERMARK 2#define IX_OAM_TX_RETRY_DELAY 20#define IX_OAM_TX_RETRY_COUNT_MAX 50#define IX_OAM_RX_QUEUE_POLL_INTERVAL 100/* endianness handling */#define IX_OAM_HEADER_GET(cell, hdr) \(hdr) = (((*((UCHAR *)(&(cell)->header))) & 0xFF) << 24); \(hdr) = (hdr) | (((*(((UCHAR *)(&(cell)->header)) + 1)) & 0xFF) << 16); \(hdr) = (hdr) | (((*(((UCHAR *)(&(cell)->header)) + 2)) & 0xFF) << 8); \(hdr) = (hdr) | (((*(((UCHAR *)(&(cell)->header)) + 3)) & 0xFF) << 0); #define IX_OAM_VCI_GET(oamHdr) (((oamHdr) >> 4) & 0xFFFF)#define IX_OAM_VPI_GET(oamHdr) (((oamHdr) >> 20) & 0xFF)#define IX_OAM_PTI_GET(oamHdr) (((oamHdr) >> 1) & 0x7)#define IX_OAM_HEADER_SET(cell, hdr) do { \ register UCHAR *tmpVal; \ tmpVal = ((UCHAR *)(&(cell)->header)); \ *tmpVal++ = (((hdr) >> 24) & 0xFF); \ *tmpVal++ = (((hdr) >> 16) & 0xFF); \ *tmpVal++ = (((hdr) >> 8) & 0xFF); \ *tmpVal++ = ((hdr) & 0xFF); \ } while(0);#define IX_OAM_VCI_SET(oamHdr, vci) ( (oamHdr) = ((oamHdr) | (( (vci) & 0xFFFF ) << 4)) )#define IX_OAM_VPI_SET(oamHdr, vpi) ( (oamHdr) = ((oamHdr) | (( (vpi) & 0xFF ) << 20)) )#define IX_OAM_PTI_SET(oamHdr, pti) ( (oamHdr) = ((oamHdr) | (( (pti) & 0x7 ) << 1)) )#define IX_OAM_TYPE_AND_FUNC_GET(cell) ((cell)->payload.genericPayload.oamTypeAndFunction)#define IX_OAM_LOOPBACK_INDICATION_GET(cell) ((cell)->payload.lbPayload.loopbackIndication) #define IX_OAM_TYPE_AND_FUNC_SET(payload, type) (((payload)->oamTypeAndFunction) = (type))#define IX_OAM_LOOPBACK_INDICATION_SET(payload, loop) (((payload)->loopbackIndication) = (loop))/* * Typedefs whose scope is limited to this file. *//* * This structure defines a software queue that stores mbufs. * NOTE: The head and tail pointers are incremented each time an mbuf is added * to the head or removed from the tail. The range of values that the head and * tail pointers can assume are in the range 0....2^32. The size of this queue * _must_ be a power of 2. The mask is set to (size - 1). Whenever the head or * tail pointers are used they are masked with this mask. The following is an * example of how this works(size = 128, 26 elements in the queue): * mask = 127 (0x007f) * head = 35535 (0x8acf) * tail = 35509 (0x8ab5) * numElementsInQueue = (head & mask ) - (tail & mask ) * = (0x8acf & 0x007f) - (0x8ab5 & 0x007f) * = (0x4f) - (0x35) * = 79 - 53 * numElementsInQueue = 26 */typedef struct{ volatile UINT32 head; /* Points to the head of the queue */ volatile UINT32 tail; /* Points to the tail of the queue */ UINT32 size; /* The size of the queue */ UINT32 mask; /* Head and tail mask */ IX_OSAL_MBUF *array[IX_OAMCODELET_NUM_MBUFS_IN_SW_MBUF_Q];} IxOamCodeletSwMbufQ;/* * Global Variables */static UINT32 lbCorrelationTag = 0; /* Correlation Tag of Loopback in progress, see I-610 */static UINT32 lbVci = 0; /* VCI of Loopback in progress */static UINT32 lbVpi = 0; /* VPI of Loopback in progress */static UINT32 lbPti = 0; /* PTI of Loopback in progress */static UINT32 lbPort = 0; /* Port of Loopback in progress */static int ixOamCodeletNumPorts;/* receive software queues */static IxOamCodeletSwMbufQ ixOamSwQueue[IX_UTOPIA_MAX_PORTS];/* Cell statistics */static UINT32 parentLbCellTxCount[IX_UTOPIA_MAX_PORTS]; /* Count of parent cells sent */static UINT32 childLbCellTxCount[IX_UTOPIA_MAX_PORTS]; /* Count of LB child cells sent */static UINT32 parentLbCellRxCount[IX_UTOPIA_MAX_PORTS]; /* Count of Rx Parent Loopback cells, i.e. Loopbacks initiated at far end */static UINT32 childLbCellRxCount[IX_UTOPIA_MAX_PORTS]; /* Count of expected Rx Child Loopback cells */static UINT32 childLbCellRxErrCount[IX_UTOPIA_MAX_PORTS]; /* Count of unexpected Rx Child Loopback cells, e.g. loopback not in progress, wrong VPI, VCI etc. */static UINT32 parentLbCellRxErrCount[IX_UTOPIA_MAX_PORTS]; /* Count of unexpected Rx Parent Loopback cells, e.g. LLID didn't match this CPID */static UINT32 unsupportedOamRxCount[IX_UTOPIA_MAX_PORTS]; /* Count of OAM Rx cells that are not supported, i.e. any cells != OAM LB */static UINT32 txDoneCallbackCount[IX_UTOPIA_MAX_PORTS]; /* Count of tx done callbacks for a port */static UINT32 replenishCallbackCount; /* Count of Rx Q replenish callbacks, all ports *//* This CPID is set to all 1's, i.e. no specific coding structure I-610 */static UINT8 oamCpid[IX_OAM_ITU610_LOCATION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};/* A location Id of all 1's corresponds to end point */static UINT8 allOnesLocId[IX_OAM_ITU610_LOCATION_ID_LEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};/* A location Id of all 0's corresponds to segment end point */static UINT8 allZerosLocId[IX_OAM_ITU610_LOCATION_ID_LEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};static UINT32 ixOamCodeletNumPortsConfigured = 0;static IxAtmConnId oamRxConnId;static IxAtmConnId oamTxConnId[IX_UTOPIA_MAX_PORTS];static IxAtmdAccUserId oamRxUserId = 99; /* For debug purposes */static BOOL ixOamCodeletInitialized = FALSE;/* * Static function prototypes */PRIVATE voidixOamChildLbCellRx (IxAtmLogicalPort port, IX_OSAL_MBUF *rxMbuf);PRIVATE IX_STATUSixOamParentLbCellTx (IxAtmLogicalPort port, UINT32 vpi, UINT32 vci, UINT32 pti);PRIVATE IX_STATUSixOamChildLbCellTx (IxAtmLogicalPort port, IX_OSAL_MBUF *rxMbuf);PRIVATE voidixOamParentLbCellRx (IxAtmLogicalPort port, IX_OSAL_MBUF *rxMbuf);PRIVATE IX_STATUSixOamRxLlidCheck (IxOamITU610Cell *oamCell);PRIVATE void ixOamCellRxTask( void );PRIVATE voidixOamCellRxCallback (IxAtmLogicalPort port, IxAtmdAccUserId userId, IxAtmdAccPduStatus status, IxAtmdAccClpStatus clp, IX_OSAL_MBUF *rxMbuf);PRIVATE IX_STATUSixOamCodeletOamPing(IxAtmLogicalPort port, UINT32 vpi, UINT32 vci, UINT32 pti, UINT32 numCells);PRIVATE voidixOamTxDoneCallback (IxAtmdAccUserId userId, IX_OSAL_MBUF *mbufPtr);PRIVATE voidixOamRxFreeLowReplenishCallback (IxAtmdAccUserId userId);PRIVATE IX_STATUS ixOamTxAndRetry(IxAtmConnId connId, IX_OSAL_MBUF * mbufPtr, IxAtmdAccClpStatus clp, UINT32 numberOfCells);PRIVATE voidixOamTxFlush(IX_OSAL_MBUF * mbufPtr);PRIVATE voidixOamRxInvalidate(IX_OSAL_MBUF * mbufPtr);PRIVATE void ixOamQueueInit( int port );PRIVATE BOOL ixOamQueueEmptyQuery (IxOamCodeletSwMbufQ *s);PRIVATE IX_OSAL_MBUF * ixOamMBufQueueGet (IxOamCodeletSwMbufQ *s);PRIVATE void ixOamQueuePut (IxOamCodeletSwMbufQ *s, IX_OSAL_MBUF *buf);PRIVATE BOOLixOamMemCmp(UCHAR *destBuf, UCHAR *srcBuf, UINT32 len);PRIVATE voidixOamMemCpy(UCHAR *destBuf, UCHAR* srcBuf, UINT32 len);PRIVATE voidixOamMemSet(UCHAR *destBuf, UCHAR data, UINT32 len);/* */PUBLIC IX_STATUSixOamCodeletInit (UINT32 numPorts){ IX_STATUS retval; UINT32 txRate[IX_UTOPIA_MAX_PORTS]; UINT32 rxRate; IxAtmmVc txVc; IxAtmmVc rxVc; IxAtmLogicalPort port; IxAtmSchedulerVcId rxVcId; IxAtmSchedulerVcId txVcId; IxAtmNpeRxVcId npeRxVcId; IxOsalThread tid; IxOsalThreadAttr threadAttr; char *pThreadName = "OAM Receive"; if (ixOamCodeletInitialized) { IX_OAM_CODELET_LOG_ERROR("Already initialized"); return IX_FAIL; } /* Check parameters */ if (numPorts < 1 || numPorts > IX_UTOPIA_MAX_PORTS) { IX_OAM_CODELET_LOG_ERROR("ixOamCodeletInit(): numPorts (%u) invalid\n", numPorts); return IX_FAIL; } ixOamCodeletNumPorts = numPorts; /* Check how many ports have been configured, rxRate not used */ for (port =0; port< (IxAtmLogicalPort)numPorts; port++) { if (ixAtmmPortQuery (port, &txRate[port], &rxRate) != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("ixOamCodeletInit(): numPorts (%u) not configured, %u ports configured\n", numPorts, port); } } /* Initialize stats */ for (port = 0; port < IX_UTOPIA_MAX_PORTS; port++) { parentLbCellTxCount[port] = 0; childLbCellTxCount[port] = 0; parentLbCellRxCount[port] = 0; childLbCellRxCount[port] = 0; childLbCellRxErrCount[port] = 0; parentLbCellRxErrCount[port] = 0; unsupportedOamRxCount[port] = 0; txDoneCallbackCount[port] = 0; } replenishCallbackCount = 0; /* 1 for all ports */ /* Setup the OAM Tx Port Channels */ for (port=0; port< (IxAtmLogicalPort)numPorts; port++) { ixOsalMemSet(&txVc, 0, sizeof(txVc)); /* Setup Tx Vc descriptor */ txVc.vpi = IX_ATMDACC_OAM_TX_VPI; txVc.vci = IX_ATMDACC_OAM_TX_VCI; txVc.direction = IX_ATMM_VC_DIRECTION_TX; txVc.trafficDesc.atmService = IX_ATM_UBR; txVc.trafficDesc.pcr = txRate[port]; /* Setup tx VC, N.B. TxVcId not used in this codelet, * would typically be used for Vc Deregister */ retval = ixAtmmVcRegister (port, &txVc, &txVcId); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR("Failed to register Tx Port VC\n"); return IX_FAIL; } retval = ixAtmdAccTxVcConnect (port, IX_ATMDACC_OAM_TX_VPI, IX_ATMDACC_OAM_TX_VCI, IX_ATMDACC_OAM, port, /* set userId to port */ ixOamTxDoneCallback, &oamTxConnId[port]); if (retval != IX_SUCCESS) { IX_OAM_CODELET_LOG_ERROR ("Failed to connect Tx Port Channel\n"); return IX_FAIL; } /* setup the Rx sw queues */ ixOamQueueInit( port ); } /* * Setup OAM Rx Channel
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -