📄 ixethaal5app.c
字号:
{#ifdef IXEAA_DEBUG printf("AtmdAcc - cell was not sent\n");#endif /* Recycle buffer if Ethernet port didn't accept it */ ixEAAAtmBufferRecycle( atmVcRxId[ userId ], mbufPtr ); } else { ixEAANumAtmRxEthFramesForwarded++; }}/* ATM Tx done callback - called by AtmdAcc when new tx buffer was sent and is no longer used by atmdAcc */void ixEAAAtmTxDoneCallback(IxAtmdAccUserId userId, IX_OSAL_MBUF * mbufPtr){ UINT32 bufDestination; /* Obtain interface and port id from the start of the buffer data */ IX_OSAL_MBUF_POOL_MDATA_RESET(mbufPtr); bufDestination = IX_OSAL_READ_BE_SHARED_LONG( (UINT32*) IX_OSAL_MBUF_MDATA(mbufPtr) ); /* Verify it belongs to Ethernet */ if( (bufDestination & IX_EAA_MARK_MASK) != IX_EAA_ETH_MARK ) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "!!!Wrong buffer mark - expected to belong" "to Ethernet interface (buffer is lost)\n", 0, 0, 0, 0, 0, 0); IX_ETHAAL5APP_CODELET_DEBUG_DO(ixEAANumAtmRxDropBuffers++;); return; } /* Extract port id from the least significant byte of first word of mbuf data */ bufDestination &= IX_EAA_ETH_PORT_MASK; /* Verify port is in valid range */ if( bufDestination >= IX_EAA_NUM_ETH_PORTS ) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "!!!Buffer belongs to invalid Ethernet port (buffer is lost)\n", 0, 0, 0, 0, 0, 0); IX_ETHAAL5APP_CODELET_DEBUG_DO(ixEAANumAtmRxDropBuffers++;); return; } ixEAAEthBufferRecycle( bufDestination, mbufPtr );}/* We provide free buffers only, from 'ixEAAEthTxDoneCallback' or from ixEAAAtmRxCallback (as a result of error condition). Basically only buffers that were previously returned to rx handler are given to AtmdAcc component after processing. We don't have additional pool of buffers */void ixEAAAtmRxVcFreeLowCallback(IxAtmdAccUserId userId){}/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*//*>>>>>>>>>>>>>> ETH CALLBACK AND BUFFER PROCESSING FUNCTIONS <<<<<<<<<<<<<<<<*//* * ixEAAEthBufferRecycle function returns mbuf pointed by mbufPtr back to ixEthAcc * component free rx buffer queue. Buffer is unchained (and any following * buffers in the chain). Length fields and data pointers are reset to the * original state. Then buffer is replenished to the ethernet port associated * with portId. Normally this function is called from ixEAAAtmTxDoneCallback * to replenish ethernet buffer after forwarding it to ATM port. It can be * called from ixEAAEthRxCallback as a result of error condition (if for * example bufer contains chain of buffers, which application doesn't support. */void ixEAAEthBufferRecycle( IxEthAccPortId portId, IX_OSAL_MBUF * mbufPtr ){ if( IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr) == NULL ) { IX_STATUS status; IX_OSAL_MBUF_POOL_MDATA_RESET(mbufPtr); /* invalidate only the possibly modified part (including aal5 trailer) */ IX_OSAL_CACHE_INVALIDATE( (UINT32) IX_OSAL_MBUF_MDATA(mbufPtr), IX_OSAL_MBUF_MLEN(mbufPtr) + IX_EAA_MBUF_USER_SPACE + 48); IX_OSAL_MBUF_MDATA(mbufPtr) += IX_EAA_MBUF_USER_SPACE; IX_OSAL_MBUF_MLEN(mbufPtr) = IX_EAA_DEFAULT_MBUF_DATA_SIZE; /* Return buffer to ixEthAcc Rx component */ status = ixEthAccPortRxFreeReplenish( portId, mbufPtr); if (status != IX_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "Failed to pass Rx free buffer to ixEthAcc\n", 0, 0, 0, 0, 0, 0); /* If buffer replenishing fails, it means ixEthAcc component can not accept more free buffers (internal free receive queue is full). This should never happened, because this application replenish only buffers that were passed to Rx callback. Therefore we assert in such situation */ if (IX_ETH_ACC_PORT_UNINITIALIZED==status) { /* This happens when attempts to replenish to queue that its associated Eth NPE is not enabled. If this happens, we return mbuf back to pool */ IX_OSAL_MBUF_POOL_PUT(mbufPtr); } } } else { IX_OSAL_MBUF* mbufNextPtr; IX_STATUS status; /* if buffer is chained, then update statistics, unchain it and replenish */ if( IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr) != NULL ) { IX_ETHAAL5APP_CODELET_DEBUG_DO(ixEAANumEthRxChainedBuffers++;); } /* Unchain, reset and replenish buffers */ while( mbufPtr ) { /* Obtain next buffer from the chain */ mbufNextPtr = IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr); /* Reset current buffer - data is changed by Atm rx callback function to remove RFC1483 header and now it must be set to original value */ IX_OSAL_MBUF_POOL_MDATA_RESET(mbufPtr); IX_OSAL_MBUF_MDATA(mbufPtr) += IX_EAA_MBUF_USER_SPACE; IX_OSAL_MBUF_MLEN(mbufPtr) = IX_EAA_DEFAULT_MBUF_DATA_SIZE; IX_OSAL_MBUF_PKT_LEN(mbufPtr) = IX_EAA_DEFAULT_MBUF_DATA_SIZE; /* unchain current buffer */ IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr) = NULL; IX_OSAL_MBUF_NEXT_PKT_IN_CHAIN_PTR(mbufPtr) = NULL; /* Return buffer to ixEthAcc Rx component */ IX_OSAL_CACHE_INVALIDATE((UINT32) IX_OSAL_MBUF_MDATA(mbufPtr), IX_OSAL_MBUF_MLEN(mbufPtr)); status = ixEthAccPortRxFreeReplenish( portId, mbufPtr); if (status != IX_SUCCESS) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "Failed to pass Rx free buffer to ixEthAcc\n", 0, 0, 0, 0, 0, 0); /* If buffer replenishing fails, it means ixEthAcc component can not accept more free buffers (internal free receive queue is full). This should never happened, because this application replenish only buffers that were passed to Rx callback. Therefore we assert in such situation */ if (IX_ETH_ACC_PORT_UNINITIALIZED==status) { /* This happens when attempts to replenish to queue that its associated Eth NPE is not enabled. If this happens, we return mbuf back to pool */ IX_OSAL_MBUF_POOL_PUT(mbufPtr); } } /* take the next buffer from the chain and repeat all steps as for current one */ mbufPtr = mbufNextPtr; } }}/* Eth Rx callback - called by ixEthAcc when new rx buffers are available for particular port (callbackTag is different for each Eth port) */void ixEAAEthRxCallback(UINT32 callbackTag, IX_OSAL_MBUF *mbufPtr, IxEthAccPortId portId){ UINT8* pdu; int ethLength; int numCells; int atmPortCnt; int atmVcCnt = 0; IxAtmdAccUserId connVcId; UINT16 *pduLengthField; /* There is no need to invalidate the mbuf payload : invalidate * is already done before replenish and there is no cache line * in MMU for this mbuf * IX_OSAL_CACHE_INVALIDATE((UINT32) IX_OSAL_MBUF_MDATA(mbufPtr), * IX_OSAL_MBUF_MLEN(mbufPtr)); */#ifdef IXEAA_DEBUG mbufDump("Eth RX", mbufPtr);#endif ixEAANumEthRxFrames++; pdu = IX_OSAL_MBUF_MDATA(mbufPtr); /* Verify that pdu length is valid, which has to be greater than minimum Ethernet frame size. Verify also that buffer is not chained */ if( IX_OSAL_MBUF_PKT_LEN(mbufPtr) < IX_EAA_MIN_ETH_FRAME_SIZE || IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr) != NULL ) { if( IX_OSAL_MBUF_NEXT_BUFFER_IN_PKT_PTR(mbufPtr) != NULL ) ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "WARNING: Received Ethernet frame" "stored in chained buffers\n", 0, 0, 0, 0, 0, 0); else ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "WARNING: Received Ethernet frame" "has length less than 64 bytes\n", 0, 0, 0, 0, 0, 0); /* Frames less than 64 bytes in size and chained ones are not supported */ ixEAAEthBufferRecycle( callbackTag, mbufPtr ); return; } /* The packet will be sent to the atm port 0 */ if (routedProtocol) { atmPortCnt = 0; } else { /* Check if destination MAC address is present in the 'Atm' Mac database (if one of VC connections received recently packet from that address). The array with source Mac addresses received from Utopia needs to be searched for the occurrence. 'pdu' points to the start of buffer, which contains dest. mac address. Start from port 0 and increment port until Mac is found or all ports scanned */ atmVcCnt = 0; while (atmVcCnt < IX_EAA_NUM_ATM_VCS && memcmp( pdu, &atmSrcMacAddrDBase[ atmVcCnt ], IX_IEEE803_MAC_ADDRESS_SIZE )) { atmVcCnt++; } } /* if atmPortCnt is less than number of enable ports, then we found right port, otherwise Mac address is unknown and packet will be discarded */ if( atmVcCnt == IX_EAA_NUM_ATM_VCS ) { /* IMPORTANT!!! Flooding is not normally supported, what means that back to back configuration (IX4XX <-ADSL-> IXP4XX) will not transfer any data. However simplified flooding can be easily implemented. Code below is executed only if dest. MAC address on the ATM side was not found. In such a case packet is dropped and mbuffer recycled: ixEAAEthBufferRecycle( callbackTag, mbufPtr ); Instead of dropping packet it could be forwarded to Phy 1 of Utopia interface, thus flooding would be supported on Phy 1. To implement that solution code below should be commented (together with 'return;' instruction 9 lines below) and one line should be added: atmPortCnt = 1;. So to be precise this if(){...} statement will look like: if( atmPortCnt == atmNumPortsEnabled ) { atmPortCnt = 1; } This will enable flooding on Phy 1 of Utopia port only. To enable it on another Phy, atmPortCnt must be assigned corresponding value. */#ifdef IXEAA_DEBUG printf("Unknown Mac...");#endif IX_ETHAAL5APP_CODELET_DEBUG_DO(ixEAANumEthRxMACDroppedBuffers++;); /* if destination MAC address is not recognized by eth. driver, then packet will be discarded and buffer recycled */ ixEAAEthBufferRecycle( callbackTag, mbufPtr ); return; } /* Obtain VC id using port returned from MAC data base. */ connVcId = atmVcTxId[ atmVcCnt ]; if (routedProtocol) { /* store the last source mac address */ memcpy(ðSrcMacAddrDBase[callbackTag], pdu + IX_IEEE803_MAC_ADDRESS_SIZE, IX_IEEE803_MAC_ADDRESS_SIZE); ethLength = IX_OSAL_MBUF_MLEN(mbufPtr); /* obtain eth data length */ /* Calculate length of Ethernet frame with VcMux header. FCS will not be included in encapsulated frame, therefore length of frame must be decremented by 4. header is removed. */ ethLength -= IX_EAA_ETH_FCS_SIZE; IX_OSAL_MBUF_MDATA(mbufPtr) += IX_EAA_RFC1483_VCMUX_ROUTED_HEADER_SIZE; ethLength -= IX_EAA_RFC1483_VCMUX_ROUTED_HEADER_SIZE; } else { /* Append trailer and padding so the total length of pdu fits exactly into ATM cells and trailer is right justified in the last cell by adding pad field (0-47 bytes). */ ethLength = IX_OSAL_MBUF_MLEN(mbufPtr); /* obtain eth data length */ /* Calculate length of Ethernet frame with VcMux header. FCS will not be included in encapsulated frame, therefore length of frame must be decremented by 4. RFC1483 header is added (2 bytes). */ ethLength -= IX_EAA_ETH_FCS_SIZE; ethLength += IX_EAA_RFC1483_VCMUX_BRIDGED_HEADER_SIZE; /* Because this packet will be sent through ATM, therefore RFC1483 header must be appended at the start of pdu. This will be done by decrementing mData pointer by 2 - header is already placed before start of buffer */ IX_OSAL_MBUF_MDATA(mbufPtr) -= IX_EAA_RFC1483_VCMUX_BRIDGED_HEADER_SIZE; } /* Calculate total number of cells in packet (in two steps) */ /* Atm packet will also contain Aal5 CPCS-PDU trailer (8 bytes in total) */ pdu = IX_OSAL_MBUF_MDATA(mbufPtr); numCells = (ethLength + 47) / 48 + extraAtmCellNeeded[ethLength % 48]; /* Since Aal5 CPCS-PDU trailer must be justified at the end of the cell, the total length of the packet must be modulus of 48. Calculate number of cells */ IX_OSAL_MBUF_MLEN(mbufPtr) = numCells * 48; IX_OSAL_MBUF_PKT_LEN(mbufPtr) = IX_OSAL_MBUF_MLEN(mbufPtr); /* fill length field in AAL5 CPCS-PDU trailer and leave CRC field untouched (will be filled by NPE). This code assumes processor is working in big endian mode */ pduLengthField = (UINT16*) (pdu + IX_OSAL_MBUF_MLEN(mbufPtr) - IX_EAA_AAL5_LENGTH_POS_FROM_END_OF_TRAILER); IX_OSAL_WRITE_BE_SHARED_SHORT(pduLengthField,(UINT16) ethLength); /* fill trailer padding */ ixOsalMemSet(pdu + ethLength, 0x0, ((UINT8 *)pduLengthField - pdu) - ethLength);#ifdef IXEAA_DEBUG mbufDump("Tx Atm", mbufPtr);#endif /* submit buffer to VC */ IX_OSAL_CACHE_FLUSH((UINT32)IX_OSAL_MBUF_MDATA(mbufPtr), IX_OSAL_MBUF_MLEN(mbufPtr)); if( ixAtmdAccTxVcPduSubmit( connVcId, mbufPtr, 0, numCells ) != IX_SUCCESS ) {#ifdef IXEAA_DEBUG printf("AtmdAcc - cell was not sent\n");#endif /* Recycle buffer if Atm port didn't accept it */ ixEAAEthBufferRecycle( callbackTag, mbufPtr ); } else { ixEAANumEthRxEthFramesForwarded++; }}/* Eth Tx done callback - called by ixEthAcc when new tx buffer was sent and is no longer used by ixEthAcc */void ixEAAEthTxDoneCallback(UINT32 callbackTag, IX_OSAL_MBUF *mbufPtr){ UINT32 bufDestination; if (IX_OSAL_MBUF_NET_POOL(mbufPtr) == mBufAtmPool[0]) { /* prioritize traffic on port 0 , recognize the pool id */ bufDestination = 0; } else { /* Obtain interface and port id from the start of the buffer data */ IX_OSAL_MBUF_POOL_MDATA_RESET(mbufPtr); bufDestination = IX_OSAL_READ_BE_SHARED_LONG( (UINT32*) IX_OSAL_MBUF_MDATA(mbufPtr)); /* Verify it belongs to Ethernet */ if( (bufDestination & IX_EAA_MARK_MASK) != IX_EAA_ATM_MARK ) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "!!!Wrong buffer mark - expected to belong to" "Atm interface (buffer is lost)\n", 0, 0, 0, 0, 0, 0); IX_ETHAAL5APP_CODELET_DEBUG_DO(ixEAANumEthRxDropBuffers++;); return; } /* Extract port id from the least significant byte of first word of mbuf data */ bufDestination &= IX_EAA_ATM_VC_MASK; /* Verify port is in valid range */ if( bufDestination >= IX_EAA_NUM_ATM_VCS ) { ixOsalLog(IX_OSAL_LOG_LVL_ERROR, IX_OSAL_LOG_DEV_STDERR, "!!!Buffer belongs to invalid Atm port" "(buffer is lost)\n", 0, 0, 0, 0, 0, 0); IX_ETHAAL5APP_CODELET_DEBUG_DO(ixEAANumEthRxDropBuffers++;); return; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -