📄 bridge.c
字号:
stationCacheEntryDelete(&pStationCache[index]); } } /* remove all the queue packets if any */ while(pPortInfo->errSndq.ifq_head) { /* Dequeue a packet. */ IF_DEQUEUE (&pPortInfo->errSndq, pMblk); netMblkClChainFree(pMblk); } semGive(bridgePortListSemId); free(pPortInfo); return OK; }/******************************************************************************** bridgeRestartRtn - bridge restart routine** This is the entry point for the bridge restart routine.** RETURNS: OK, or ERROR if bridge restart fails** ERRNO: N/A** NOMANUAL*/LOCAL STATUS bridgeRestartRtn ( void* pNetCallBackId ) { BRIDGE_PORT_INFO* pPortInfo; M_BLK_ID pMblk; int status = OK; pPortInfo = (BRIDGE_PORT_INFO *)pNetCallBackId; /* check if there is packets in the ERR_BLOCK send queue */ while(pPortInfo->errSndq.ifq_head) { /* Dequeue a packet. */ IF_DEQUEUE (&pPortInfo->errSndq, pMblk); status = packetToPortSend (pMblk, pPortInfo,NULL); if (status == END_ERR_BLOCK) break; } if (status == OK) { /* only after the queue is emptied, enable mirror0 restart */ if (pMirrorStackEnd == NULL) { if ((pMirrorStackEnd = endFindByName(MIRROR_DEV_NAME, MIRROR_STACK_UNIT_NUM)) == NULL) { printf("ERROR: restart fails, can't find mirror0 device\n"); return ERROR; } } /* already in tNetTask context */ muxTxRestart(pMirrorStackEnd); } return OK; }/******************************************************************************** bridgeErrorRtn - bridge Error routine ** This is the entry point for the bridge error routine.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void bridgeErrorRtn ( void* pNetCallBackId, END_ERR* pError ) { return; }/********************************************************************************* pktToQueuePut - put the unsent packets to the queue** Only the packets originated from another physical bridge port will be put* into this queue. The packet originated from local stack will be returned* back to the IP layer. Therefore this queue is only accessed by the restart* and driver's receive routines. Both are assumed to be invoked from the* 'tNetTask' context through netJobAdd() function.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void pktToQueuePut ( BRIDGE_PORT_INFO* pPortInfo, M_BLK_ID pMblk, BOOL atHead ) { /* packets not originated from the local stack */ /* put it in the queue, and let restart routine send them out */ if (IF_QFULL(&pPortInfo->errSndq)) { IF_DROP(&pPortInfo->errSndq); netMblkClChainFree(pMblk); } else if (atHead == TRUE) { IF_PREPEND(&pPortInfo->errSndq,pMblk); } else { IF_ENQUEUE(&pPortInfo->errSndq,pMblk); } }/********************************************************************************* packetToPortSend - send a packet to the given port** This routine sends a packet to the given port** RETURNS: OK or ERROR** ERRNO: N/A** NOMANUAL*/LOCAL int packetToPortSend ( M_BLK* pMblk, BRIDGE_PORT_INFO* pDestPortInfo, BRIDGE_PORT_INFO* pSrcPortInfo ) { int status = OK; /* Attempt to send the packet */ switch (pDestPortInfo->portType) { case BRIDGE_PORT_TYPE_END: status = muxSend(pDestPortInfo->pMuxBindCookie, pMblk); break; case BRIDGE_PORT_TYPE_NPT: /* pMblk->mBlkHdr.mFlags |= M_L2HDR; */ status = muxTkSend(pDestPortInfo->pMuxBindCookie, pMblk, NULL, 0, NULL); break; default: netMblkClChainFree(pMblk); break; } if (status == END_ERR_BLOCK) { /* * The device is currently unable to transmit because of * insufficient resources. Put the packet in the error send * queue for that device. When the device has enough resources * to transmit, MUX will call the Bridge restart routine. * The restart routine will try to re-send the packet. */ DBG_PRINT(("ERROR: packetForward: packet sent to %s%d returned \ END_ERR_BLOCK\n", pDestPortInfo->name, pDestPortInfo->unitNum)); /* Did this error originate from mirror1? */ if (pMirrorPortInfo == NULL) { pMirrorPortInfo = portListEntryFind(MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM); if (pMirrorPortInfo == NULL) { printf("ERROR: packetToPortSend, can't find mirror port\n"); return ERROR; } } if (pSrcPortInfo == pMirrorPortInfo) { /* packet originated from the local stack */ DBG_PRINT(("END_ERR_BLOCK packet sent from mirror 1\n")); /* notify the mirrorSend routine */ mirrorSendStatus = END_ERR_BLOCK; } else { /* * If the source port is NULL, it means the Bridge restart * routine has unsuccessfully tried to re-send the packet. * To preserve the transmit order, put the packet at the head * of the device's error send queue. * * Otherwise, this the first attempt to send the packet. Put * the packet at the tail of the device's error send queue. */ pktToQueuePut(pDestPortInfo, pMblk, (pSrcPortInfo == NULL)); } } return status; }/******************************************************************************** packetForward - forward the packet to the destination port** This routine forwards the provided packet out the indicated destination* port. ** If the destination port is driven by a NPT device driver, the* the transmission is accomplished by simply calling muxTkSend() and setting* the M_L2HDR flag in the mBlk header. The presence of this flag indicates* to the NPT device driver that a fully formed physical layer header is* already present in the packet. Although this flag is mentioned in the NPT* docs, it is not defined in any header files.** If the destination port is driven by an END device driver, transmission* cannot be accomplished by calling muxTkSend() since muxTkSend() will* prepend a physical layer header with a source MAC address of the system* itself. However, muxSend() can be called to accomplish the transmission* to an END driver.** RETURNS: OK, or ERROR if bridge forward packets fails** ERRNO: N/A** NOMANUAL*/LOCAL STATUS packetForward ( M_BLK* pMblk, BRIDGE_PORT_INFO* pDestPortInfo, BRIDGE_PORT_INFO* pSrcPortInfo ) { if (pDestPortInfo->errSndq.ifq_head) { /* * If the error send queue is not empty, there must be one restart * called later on. If the current function is called from a task * other than tNetTask(packet from local stack), it may get switched out * here to execute the restart routine in tNetTask context. But the * muxTxRestart on mirror0 device will get blocked by splnet semaphore * in ipTxStartup from ipTxRestart until this function completed. Then * it will find this packet in the IP ifqueue. So we're OK. * If the current function is called from tNetTask context(packet from * another physical bridge port), the restart(always from tNetTask * context) can't start until we're finished here. */ if (pMirrorPortInfo == NULL) { pMirrorPortInfo = portListEntryFind(MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM); if (pMirrorPortInfo == NULL) { printf("ERROR: packetForward, can't find bridge mirror port\n"); return ERROR; } } if (pSrcPortInfo == pMirrorPortInfo) { /* notify the mirrorSend routine */ mirrorSendStatus = END_ERR_BLOCK; } else pktToQueuePut(pDestPortInfo,pMblk,FALSE); } else packetToPortSend(pMblk, pDestPortInfo, pSrcPortInfo); return OK; }/******************************************************************************** packetFloodForward - send packet to all the bridge ports except source port** This routine sends packet to all the bridge ports except source port** RETURNS: OK, or ERROR if bridge flood forward packets fails** ERRNO: N/A** NOMANUAL*/LOCAL STATUS packetFloodForward ( M_BLK* pMblk, BRIDGE_PORT_INFO* pSrcPortInfo ) { BRIDGE_PORT_INFO* pDestPortInfo; M_BLK* pMblkDup; /*************************************************************************** * forward the packet to all ports except for the source port ***************************************************************************/ for (pDestPortInfo = (BRIDGE_PORT_INFO*)lstFirst(&bridgePortList); pDestPortInfo != NULL; pDestPortInfo = (BRIDGE_PORT_INFO*)lstNext((NODE*)pDestPortInfo)) { if (pDestPortInfo != pSrcPortInfo) { if (strcmp(MIRROR_DEV_NAME,pDestPortInfo->name) == 0) { /* must be mirror 1 bridge port. */ if (bcastPktToStackSend (pMblk, pDestPortInfo, pSrcPortInfo) != OK) /* don't attempt more forwarding if error is encountered */ break; } else { /*duplicate the packet (FYI - this does not copy the payload) */ pMblkDup = netMblkChainDup(_pNetDpool, pMblk, 0, M_COPYALL, M_DONTWAIT); if (pMblkDup == NULL) /* don't attempt more forwarding if error is encountered */ break; if (packetForward(pMblkDup, pDestPortInfo, pSrcPortInfo) != OK) { /* don't attempt more forwarding if error is encountered */ netMblkClChainFree(pMblkDup); break; } if (mirrorSendStatus == END_ERR_BLOCK) { if (pSrcPortInfo == pMirrorPortInfo) { /* packet originated from local stack and END_ERR_BLOCK * code is return from the packetForward(). Then stop * all forwardings. don't free the original pMblk which * will be put in the ifq which is emptied by the * stack's restart routine */ netMblkClChainFree(pMblkDup); return OK; } } } } } /* end for loop */ /* forwarding has been with duplicates, free the original */ netMblkClChainFree(pMblk); return OK; }/********************************************************************************* bcastPktToStackSend - send the broadcast packet to the local stack** This routine sends the broadcast packet to the local stack** RETURNS: OK or ERROR** ERRNO: N/A** NOMANUAL*/LOCAL STATUS bcastPktToStackSend ( M_BLK_ID pMblk, BRIDGE_PORT_INFO* pDestPortInfo, BRIDGE_PORT_INFO* pSrcPortInfo ) { M_BLK_ID pOrgMblk; M_BLK_ID p1stMblk; M_BLK_ID pNewMblk; M_BLK_ID pPreMblk; /* * Need to make a real copy of the packet when it is delivered * to the IP stack because the IP stack may modify the IP * header before the packet is sent out to the other bridge * ports. */ pOrgMblk = pMblk; p1stMblk = NULL; pPreMblk = NULL; while (pOrgMblk) { pNewMblk = netTupleGet(_pNetDpool, pOrgMblk->pClBlk->clSize, M_DONTWAIT, MT_DATA,0); if (pNewMblk == NULL || (pNewMblk->pClBlk->clSize < pOrgMblk->mBlkHdr.mLen + 2) ) { if (p1stMblk) netMblkClChainFree(p1stMblk); if (pNewMblk) netMblkClChainFree(pNewMblk); DBG_PRINT(("ERROR: can't get a buf\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -