📄 ixethaccend.c
字号:
* of available mbufs * the result value will be in the following range * IP_FRAG_TTL_MIN <= ipFragTtl <= IP_FRAG_TTL_DFLT */ UINT32 rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; pDrvCtrl->ipFragTtl = IP_FRAG_TTL_MIN + ((IP_FRAG_TTL_DFLT-IP_FRAG_TTL_MIN) * rxBufsActive) / pDrvCtrl->rxBufsAlloc; { /* update the global frag ttl value with the worst-case * interface value. There is a side effect : * it affect all interfaces. */ extern int ipfragttl; END_DEVICE *pOtherDrvCtrl = ixEthAccpDrvCtrl[1 - pDrvCtrl->unit]; if (pOtherDrvCtrl && pOtherDrvCtrl->ipFragTtl <= pDrvCtrl->ipFragTtl) { ipfragttl = pOtherDrvCtrl->ipFragTtl; } else { ipfragttl = pDrvCtrl->ipFragTtl; } }}#endif/******************************************************************************** ixEthAccEndHandleRcvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** RETURNS: N/A.*/LOCAL void ixEthAccEndHandleRcvInt ( END_DEVICE *pDrvCtrl /* interrupting device */ ){ M_BLK_ID pMblk; UINT32 rxBufsActive; pDrvCtrl->netJobAddOut++; DO_EVENT(IXE_EVT_RCV_HANDLE_ENTRY); while ((1)) { DO_EVENT(IXE_EVT_RCV_RECEIVE_LOOP_TOP); if (pDrvCtrl->recRd == pDrvCtrl->recWr) { /* queue empty */ break; } DO_EVENT(IXE_EVT_RCV_HANDLE_ENTRY); /* queue not empty, get a mbuf */ pMblk = pDrvCtrl->recBufList[pDrvCtrl->recRd++ & RECBUF_MASK]; IXP_DRV_LOG (IXP_DRV_DEBUG_RX_HANDLING, "ixEthAccEndRcvInt: received mbuf 0x%08x\n", (UINT32)pMblk, 2, 3, 4, 5, 6); DO_EVENT(IXE_EVT_RCV_RECEIVE_LOOP_CACHEOPS);#ifdef IXE_CACHED_RX_BUFFERS_ENABLE /* * We need only invalidate up to the contents of the use * of this buffer. But because * - the buffers are invalidated during replenish * - the buffers are aligned on cache line boundaries if the * cache is enabled, * it is not necessary to invalidate the cache. */ /* IXP425_END_CACHE_INVALIDATE(pMblk->m_data, pMblk->m_len); */#endif#ifdef IXP_DRV_DEBUG_MBUFS elogHook(pMblk, 3, pDrvCtrl->rxBufsRecv, pDrvCtrl->rxBufsReplenish);#endif /* Now start a prefetch on the packet payload * This will bring to memory the MAC addresses * and a part of the IP header. This should be done * as early as possible before being used, since * Xscale can execute more code while preload * is not complete. */ PREFETCH(pMblk->m_data) ; /* check the NPE is not short of rxfree buffers */ rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; if (rxBufsActive < IXETHACC_REPL_FAST_THRESHOLD) { /* check the driver is up */ if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_UP) { /* replenish as much as possible */ ixEthAccEndReplenishFast(pDrvCtrl); } rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; } /* check the NPE is not short of rxfree buffers */ if (rxBufsActive < IXETHACC_REPL_SLOW_THRESHOLD) { /* check the driver is up */ if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_UP) { /* replenish as much as possible */ ixEthAccEndReplenishSlow(pDrvCtrl); } rxBufsActive = pDrvCtrl->rxBufsReplenish - pDrvCtrl->rxBufsRecv; } /* check the NPE is not extremely short of rxfree buffers */ if (rxBufsActive < 2) { /* The number of cblk/mblk pairs owned by NPE * is gone low. This mbuf will be used for replenish. * If we don't replenish, rx events will not take * place and traffic is blocked (because replenish * is done from RX) */ netMblkClChainFree (pMblk); #ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tnetDrop++;#endif#ifdef IXETHACCEND_FRAG_RECOVERY /* update the ip ttl for this interface */ ixEthAccEnd_ip_ttl_update(pDrvCtrl); /* recover ttl-expired mbufs from the stack */ ixEthAccEnd_ip_ttl_mbuf_release(pDrvCtrl->ipFragTtl, pDrvCtrl->end.pNetPool);#endif } else { /* Update Mcast and Bcast input statistics and flag */ if (pMblk->mBlkHdr.mFlags & M_MCAST) { END_INC_IN_MCAST(pMblk->mBlkHdr.mData,pMblk->mBlkPktHdr.len); } else if (pMblk->mBlkHdr.mFlags & M_BCAST) { END_INC_IN_BCAST(pMblk->mBlkHdr.mData,pMblk->mBlkPktHdr.len); } else { END_INC_IN_UCAST(pMblk->mBlkHdr.mData,pMblk->mBlkPktHdr.len); } pMblk->mBlkHdr.mFlags |= M_PKTHDR;#ifdef IXETHACCEND_FRAG_RECOVERY /* update the ip ttl for this interface */ ixEthAccEnd_ip_ttl_update(pDrvCtrl);#endif#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tnetReceived++;#endif IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "ixEthAccEndRcvInt: mbuf 0x%08x sent to stack\n", (UINT32)pMblk, 2, 3, 4, 5, 6); /* Call the upper layer's receive routine. */ END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); } } /* check the driver is up */ if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_UP) { /* replenish all buffers */ ixEthAccEndReplenishSlow(pDrvCtrl); } DO_EVENT(IXE_EVT_RCV_HANDLE_EXIT);}/******************************************************************************** ixEthAccEndSwapMblk: part of the driver send routine** This routine is used to replace a mbuf chain with mbuf appropriate * for transmission. When a buffer header is not from one of * the pools, then it is swapped with a header from the pool.* If the data payload is not correctly aligned (a flush may affect * the adjacent buffers), the payload is copied.*/LOCAL IX_OSAL_MBUF *ixEthAccEndSwapMblk ( END_DEVICE *pDrvCtrl, M_BLK *pMblk ){ IX_OSAL_MBUF *pIxpBuf, *pNextIxpBuf; M_BLK *newMblk; /* get the buffer's pool information */ NET_POOL_ID netPoolId = MBLK_TO_NET_POOL(pMblk); IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "ixEthAccEndSwapMblk mbuf 0x%08x pool 0x%08x\n", (UINT32)pMblk, (UINT32)netPoolId, 3, 4, 5, 6); /* check if the mbuf is from one of the drivers pools */ if ((netPoolId == pDrvCtrl->end.pNetPool) || (netPoolId == pDrvCtrl->pTxNetPool) || (netPoolId == ixEthAccpDrvCtrl[1 - pDrvCtrl->unit]->end.pNetPool) || (netPoolId == ixEthAccpDrvCtrl[1 - pDrvCtrl->unit]->pTxNetPool)) { IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "Buffer 0x%08x is from this END driver pool\n", (UINT32)pIxpBuf, 2, 3, 4, 5, 6); /* the mbuf is from one of the driver pools * then use the current mbuf (its header and its payload * can be used by NPE) */ pIxpBuf = (IX_OSAL_MBUF *)pMblk; /* check for unchained buffers */ if (pMblk->m_next == NULL) { /* unchained buffers (best case scenario) */ return pIxpBuf; } else { /* chained mbufs */ pNextIxpBuf = ixEthAccEndSwapMblk(pDrvCtrl, pMblk->m_next); IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(pIxpBuf) = pNextIxpBuf; /* unchain the current mblk */ pMblk->m_next = NULL; if (pNextIxpBuf != NULL) { return pIxpBuf; } else { /* cannot chain, drop the chain */ IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "ixEthAccEndSwapMblk ! Swap Buffer 0x%08x " "<-> 0x%08x failed\n", (UINT32)pMblk, (UINT32)pIxpBuf, 3, 4, 5, 6); netMblkClChainFree(pMblk); return NULL; } } } /* If we got here, the buffer is not one of the drivers pools */ IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "Buffer 0x%08x is NOT from this END driver pool\n", (UINT32)pIxpBuf, 2, 3, 4, 5, 6); /* Check if payload is aligned (flush unaligned payload may corrupt * the previous part of memory */ if (((UINT32)(pMblk->m_data) & (IX_XSCALE_CACHE_LINE_SIZE - 1)) <= 3) { /* current mbuf data is correctly aligned * so all we need is to swap the mbuf headers and not copy * the payload */ IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "Buffer 0x%08x Data is correctly aligned\n", (UINT32)pMblk, 2, 3, 4, 5, 6);#ifdef IXP_DRV_DEBUG_MBUFS pDrvCtrl->tupleTxAlloc++;#endif /* Get a new mbuf header from the tx pool */ if (pDrvCtrl->txRd != pDrvCtrl->txWr) { pIxpBuf = pDrvCtrl->txBufList[pDrvCtrl->txRd++ & RECBUF_MASK]; IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "Got Buffer 0x%08x header from fast pool\n", (UINT32)pIxpBuf, 2, 3, 4, 5, 6); } else { pIxpBuf = (IX_OSAL_MBUF *)netTupleGet(pDrvCtrl->pTxNetPool, ALIGN_MLEN, M_DONTWAIT, MT_HEADER, FALSE); IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "Got Buffer 0x%08x header from slow pool\n", (UINT32)pIxpBuf, 2, 3, 4, 5, 6); } if (pIxpBuf != NULL) { /* swap the headers */ IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "Swap Buffer 0x%08x <-> 0x%08x headers\n", (UINT32)pMblk, (UINT32)pIxpBuf, 3, 4, 5, 6); /* for TX, all the NPE needs is m_data, m_len, m_pktlen and m_next fields */ IX_OSAL_MBUF_MDATA(pIxpBuf) = pMblk->m_data; IX_OSAL_MBUF_MLEN(pIxpBuf) = pMblk->m_len; /* save the pMblk into an unused area safe from cache problems */ IXP_DRV_MBUF_PRIV(pIxpBuf) = (UINT32)pMblk; if (pMblk->m_next == NULL) { /* unchained mbufs */ IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(pIxpBuf) = NULL; return pIxpBuf; } else { /* chained mbufs, swap the next buffer */ pNextIxpBuf = ixEthAccEndSwapMblk(pDrvCtrl, pMblk->m_next); IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(pIxpBuf) = pNextIxpBuf; /* unchain the current mblk */ pMblk->m_next = NULL; if (pNextIxpBuf != NULL) { return pIxpBuf; } else { /* cannot chain, drop the chain */ IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "ixEthAccEndSwapMblk ! Swap Buffer 0x%08x " "<-> 0x%08x failed\n", (UINT32)pMblk, (UINT32)pIxpBuf, 3, 4, 5, 6); netMblkClChainFree((M_BLK_ID)IXP_DRV_MBUF_PRIV(pIxpBuf)); IXP_DRV_MBUF_PRIV(pIxpBuf) = (UINT32)NULL; netMblkClChainFree((M_BLK_ID)pIxpBuf); return NULL; } } } else { IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "No Buffer 0x%08x header available\n", (UINT32)pMblk, 2, 3, 4, 5, 6); /* no buffer header is available, so try to * do a full buffer copy (header + payload). */ } } IXP_DRV_LOG (IXP_DRV_DEBUG_TX_HANDLING, "Buffer 0x%08x payload copy in needed\n", (UINT32)pMblk, 2, 3, 4, 5, 6); /* we get here because the buffers is from an unknown pool and the * cache operations over the current mbufs * will destroy the information in adjacent mbuf. * * The solution is to get a new mbuf with correct alignment * and to copy the payload * * This case is not supposed to occur often */ newMblk = netTupleGet(pDrvCtrl->end.pNetPool, pMblk->m_len, M_DONTWAIT, MT_HEADER, FALSE ); pIxpBuf = (IX_OSAL_MBUF *)newMblk;#ifdef IXP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -