📄 ixatmcodeletswloopback.c
字号:
{ /* Balance is 16 UBR VCs */ atmServiceCat = IX_ATM_UBR; IX_ATMCODELET_LOG("Setting up UBR: "); } } else { IX_ATMCODELET_LOG("Setting up UBR: "); } /* Use a different port per channel, depending on the maximum * number of ports configured */ retval = ixAtmUtilsAtmVcRegisterConnect(ixAtmSwLb_port, ixAtmSwLb_vpi, ixAtmSwLb_vci, aalType, atmServiceCat, IX_ATM_RX_A, ixAtmSwLbRxCallback, IX_ATMCODELET_RX_FREE_Q_LOW_THRESHOLD, ixAtmSwLbTxDoneCallback, ixAtmSwLbRxFreeLowReplenish, ixAtmSwLb_channelIdx, &ixAtmSwLbRxVcInfoTable[ixAtmSwLb_channelIdx].connId, &ixAtmSwLbTxVcInfoTable[ixAtmSwLb_channelIdx].connId); if (retval != IX_SUCCESS) { IX_ATMCODELET_LOG("Sw loopback VC setup failed for port %2u vpi %3u vci %5u\n", ixAtmSwLb_port, ixAtmSwLb_vpi, ixAtmSwLb_vci); return IX_FAIL; } else { IX_ATMCODELET_LOG("Sw loopback VC configured for port %2u vpi %3u vci %5u\n", ixAtmSwLb_port, ixAtmSwLb_vpi, ixAtmSwLb_vci); } /* Wrap the port back to 0 when numPortss used already */ ixAtmSwLb_port++; if (ixAtmSwLb_port >= (IxAtmLogicalPort)numPorts) { ixAtmSwLb_port = 0; } /* use the next vci */ ixAtmSwLb_vci++; } return IX_SUCCESS;}/* * Replenish buffers to the RxFree queue. Buffers are taken from * the software queue. */voidixAtmSwLbRxFreeLowReplenish (IxAtmdAccUserId userId){ IX_OSAL_MBUF *mBuf; IX_STATUS retval; IxAtmConnId connId; UINT32 numFreeEntries; UINT32 cnt; connId = ixAtmSwLbRxVcInfoTable[userId].connId; /* Get the number of free entries in the RX Free queue */ retval = ixAtmdAccRxVcFreeEntriesQuery (connId, &numFreeEntries); if (retval != IX_SUCCESS) { IX_ATMCODELET_LOG("Failed to query depth of Rx Free Q for connection %u\n", connId); return; } /* Replenish Rx buffers */ for (cnt=0; cnt<numFreeEntries; cnt++) { if (ixAtmQueueEmptyQuery (&loopbackSwq)) { ixAtmSwLbChannelRxSwqUndl++; ixAtmUtilsMbufGet(IX_ATMCODELET_MBUF_SIZE, &mBuf); if (mBuf == NULL) { IX_ATMCODELET_LOG("Failed to get rx free mbuffers\n"); return; } } else { mBuf = ixAtmMBufQueueGet (&loopbackSwq); } /* * Set the number of bytes of data in this MBUF to the number of * payloads that will fit evenly into IX_ATMCODELET_MBUF_SIZE. */ IX_OSAL_MBUF_MLEN(mBuf) = (IX_ATMCODELET_MBUF_SIZE / ixAtmSwLbRxVcInfoTable[userId].bytesPerCell) * ixAtmSwLbRxVcInfoTable[userId].bytesPerCell; ixAtmSwLbRxInvalidate(mBuf); /* Send free buffers to NPE */ retval = ixAtmdAccRxVcFreeReplenish (connId, mBuf); if (retval != IX_SUCCESS) { /* Free the allocated buffer */ ixAtmUtilsMbufFree(mBuf); IX_ATMCODELET_LOG("Failed to pass Rx free buffers to Atmd \n"); return; } /* Update stats */ ixAtmSwLbStats->rxFreeBuffers++; }}/* -------------------------------------------------------------- Return the stats. -------------------------------------------------------------- */voidixAtmSwLbStatsGet (IxAtmCodeletStats *stats){ *stats = *ixAtmSwLbStats;}/* -------------------------------------------------------------- Reset counters. -------------------------------------------------------------- */PRIVATE voidixAtmSwLbStatsReset (void){ if (NULL != ixAtmSwLbStats) { ixAtmSwLbStats->txPdus = 0; ixAtmSwLbStats->txBytes = 0; ixAtmSwLbStats->rxPdus = 0; ixAtmSwLbStats->rxBytes = 0; ixAtmSwLbStats->txDonePdus = 0; ixAtmSwLbStats->rxFreeBuffers = 0; ixAtmSwLbStats->txPdusSubmitFail = 0; ixAtmSwLbStats->txPdusSubmitBusy = 0; ixAtmSwLbStats->rxPdusInvalid = 0; }}/* -------------------------------------------------------------- The calback is called when the TxDone queue reaches a specified level. The mubf passed to this function is recycled by placing it on the the softwre queue. -------------------------------------------------------------- */PRIVATE voidixAtmSwLbTxDoneCallback (IxAtmdAccUserId userId, IX_OSAL_MBUF *mbufPtr){ ixAtmSwLbStats->txDonePdus++; if (ixAtmQueueFullQuery (&loopbackSwq)) { ixAtmSwLbChannelRxSwqOvfl++; ixAtmUtilsMbufFree(mbufPtr); } else { ixAtmChainQueuePut (&loopbackSwq, mbufPtr); }}/* -------------------------------------------------------------- The callback is called when an Atm Packet has been recieved. If the PDU is invalid or it is a buffer returned during a dissconnect by IxAtmdAcc then return the buffer to the vxWorks pool. Otherwise transmit the PDU; this is where the loopback occurs. 1 PDU is transmitted for every rxToTxRatio PDUs received. -------------------------------------------------------------- */PRIVATE voidixAtmSwLbRxCallback (IxAtmLogicalPort port, IxAtmdAccUserId userId, IxAtmdAccPduStatus pduStatus, IxAtmdAccClpStatus clp, IX_OSAL_MBUF *mbufPtr){ IX_STATUS retval = IX_FAIL; static UINT32 rxCount = 0; UINT32 sizeInCells; UINT32 rxBytes = 0; if (mbufPtr == NULL) { IX_ATMCODELET_LOG ("rxCallback called with NULL mbufPtr\n"); return; } rxBytes = IX_OSAL_MBUF_PKT_LEN(mbufPtr); /* Size of the data transmitted in CELLS */ sizeInCells = rxBytes/ixAtmSwLbRxVcInfoTable[userId].bytesPerCell; if (pduStatus == IX_ATMDACC_MBUF_RETURN) { /* Return this buffer to the pool */ ixAtmUtilsMbufFree (mbufPtr); return; } if ((pduStatus != IX_ATMDACC_AAL0_VALID) && (pduStatus != IX_ATMDACC_AAL5_VALID)) { ixAtmSwLbStats->rxPdusInvalid++; /* Return buffer to the pool */ ixAtmUtilsMbufFree(mbufPtr); return; } /* Update stats */ ixAtmSwLbStats->rxPdus++; ixAtmSwLbStats->rxBytes += rxBytes; /* Only send 1 PDU for every rxToTxRatio PDUs received */ if (rxCount++ == 0) { /* Tx the Rx data, including the trailer */ retval = ixAtmdAccTxVcPduSubmit (ixAtmSwLbTxVcInfoTable[userId].connId, mbufPtr, IX_ATMCODELET_DEFAULT_CLP, sizeInCells ); if (retval != IX_SUCCESS) { ixAtmSwLbStats->txPdusSubmitFail++; ixAtmUtilsMbufFree (mbufPtr); } } else { /* Do not process this Pdu. Free the buffer */ ixAtmUtilsMbufFree (mbufPtr); } if (rxCount == swLbRxToTxRatio) { rxCount = 0; } if (retval == IX_SUCCESS) { /* Update status */ ixAtmSwLbStats->txPdus++; ixAtmSwLbStats->txBytes += rxBytes; } return;}/* ---------------------------------------------------*/PRIVATE voidixAtmSwLbRxInvalidate(IX_OSAL_MBUF * mbufPtr){ while (mbufPtr != NULL) { IX_OSAL_CACHE_INVALIDATE(IX_OSAL_MBUF_MDATA(mbufPtr), IX_OSAL_MBUF_MLEN(mbufPtr)); mbufPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr); } return;}/* -------------------------------------------------------------- Software queue manipulation functions. -------------------------------------------------------------- */PRIVATE BOOL ixAtmQueueFullQuery (IxAtmCodeletSwLbSwMbufQ *s){ return (s->head - s->tail == s->size);}PRIVATE BOOL ixAtmQueueEmptyQuery (IxAtmCodeletSwLbSwMbufQ *s){ return (s->head == s->tail);}PRIVATE IX_OSAL_MBUF * ixAtmMBufQueueGet (IxAtmCodeletSwLbSwMbufQ *s){ IX_OSAL_ASSERT (s->head != s->tail); return (s->array[s->tail++ & s->mask]);}PRIVATE void ixAtmSwLbMBufQueuePut (IxAtmCodeletSwLbSwMbufQ *s, IX_OSAL_MBUF *buf){ IX_OSAL_ASSERT (s->head - s->tail != s->size); s->array[s->head++ & s->mask] = buf;}PRIVATE void ixAtmChainQueuePut (IxAtmCodeletSwLbSwMbufQ *s, IX_OSAL_MBUF *mbufPtr){ IX_OSAL_MBUF *buf; do { if (ixAtmQueueFullQuery(s)) { ixAtmUtilsMbufFree(mbufPtr); break; } else { buf = mbufPtr; mbufPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr); IX_OSAL_ASSERT(IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(buf) == 0); ixAtmSwLbMBufQueuePut (s, buf); } } while (mbufPtr);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -