📄 bridge.c
字号:
if (muxTkDrvCheck(pDevName) == TRUE) pPortInfo->portType = BRIDGE_PORT_TYPE_NPT; else pPortInfo->portType = BRIDGE_PORT_TYPE_END; semTake(bridgePortListSemId, WAIT_FOREVER); lstAdd(&bridgePortList, (NODE*)pPortInfo); semGive(bridgePortListSemId); return OK; }/******************************************************************************** bridgePortRemove - Remove a bridge port** Remove an existing bridge port from port list. The removed bridge port must* not be used after this routine returns successfully. To ensure this, make* sure the bridge port is free of incoming or outgoing traffic before calling* this routine.** RETURNS: OK, or ERROR if port removal fails*/STATUS bridgePortRemove ( char* pDevName, /* device name */ int unitNum /* unit number */ ) { BRIDGE_PORT_INFO* pPortInfo; /*************************************************************************** * if bridge hasn't been initialized, return ERROR ***************************************************************************/ if (bridgeInited == FALSE) return ERROR; /*************************************************************************** * find the port info and remove it from the bridge ***************************************************************************/ pPortInfo = portListEntryFind(pDevName, unitNum); if (pPortInfo != NULL) return bridgePortShutdownRtn((void*)pPortInfo); /*************************************************************************** * the port was not found in the list ***************************************************************************/ return ERROR; }/******************************************************************************** bridgeMacAdd - Add a MAC address to the bridge station cache** This routine provides the ability to add a MAC address to the bridge station* cache directly instead of waiting for the bridge to automatically learn it.* This routine is typically used to add a static entry to the station cache. ** A static entry in the station cache represents a permanent mapping between* a source MAC address and a bridge port. Static entries are useful if you* already know the MAC address to bridge port mapping for your interfaces and* want to set these at initialization time instead of waiting for the bridge* to learn it. Static entries also prevent the MAC address of an interface* from migrating from one port to another, as can happen if you have a* network loop.** RETURNS: OK, or ERROR if adding MAC address to station cache fails*/STATUS bridgeMacAdd ( char* pDevName, /* device name */ int unitNum, /* unit number */ char* pMacAddr, /* MAC address to add */ UINT32 flags /* static entry? */ ) { BRIDGE_PORT_INFO* pPortInfo; STATION_CACHE_ENTRY* pSCEntry; UINT16 bridgeMacAddr[3]; /* if bridge hasn't been initialized, return ERROR */ if (bridgeInited == FALSE) return ERROR; /* Find the bridge port matching the device name and unit number */ pPortInfo = portListEntryFind(pDevName, unitNum); if (pPortInfo == NULL) { /* Only add MAC address for known bridge ports */ return ERROR; } /* Copy in MAC address */ bcopy(pMacAddr, (char*)bridgeMacAddr, 6); /* See if there is already an entry for this MAC address */ pSCEntry = stationCacheEntryFind(bridgeMacAddr); if (pSCEntry != NULL) { /* Found an entry - override it */ pSCEntry->pPortInfo = pPortInfo; pSCEntry->tick = tickGet(); pSCEntry->flags = flags; } else { /* Didn't find the entry so add it in */ stationCacheEntryAdd(bridgeMacAddr, pPortInfo, flags); } return OK;}/******************************************************************************** bridgeMacRemove - Remove a MAC address from the bridge station cache** This routines provides the ability to remove a MAC address from the bridge* station cache directly. This routine is typically used to remove a static* entry from the station cache.** RETURNS: OK, or ERROR if the MAC address is not found*/STATUS bridgeMacRemove ( char* pMacAddr ) { UINT16 bridgeMacAddr[3]; STATION_CACHE_ENTRY* pSCEntry; /* Copy in MAC address */ bcopy(pMacAddr, (char*)bridgeMacAddr, 6); /* Find the MAC address in the station cache */ pSCEntry = stationCacheEntryFind(bridgeMacAddr); if (pSCEntry != NULL) { /* Found it - remove the entry */ stationCacheEntryDelete(pSCEntry); return OK; } /* Didn't find the MAC address in the station cache */ return ERROR; } /******************************************************************************** bridgeRcvRtn - Dispatch the received packet.** This routine performs the bridge's learning function as well as dispatching* the incoming packet to the appropriate bridge ports. This routine is only* invoked from the MUX layer function mux(Tk)Receive().** RETURNS: TRUE, or FALSE if bridge receive routine fails*/LOCAL BOOL bridgeRcvRtn ( void* pNetCallBackId, /* parameter assigned when muxTkBind called */ long type, /* not used */ M_BLK* pMblk, /* the received packet */ void* pSpareData /* not used */ ) { UINT32 macAddr[4]; /* src and dst mac addresses holder */ BRIDGE_PORT_INFO* pSrcPortInfo; /* incoming port info for the packet */ BRIDGE_PORT_INFO* pDestPortInfo; /* outgoing port info for the packet */ STATION_CACHE_ENTRY* pSCEntry; /* station cache entry */ UINT16 * pTempAddr; UINT16 * pMacDstAddr; UINT16 * pMacSrcAddr; /* If it is a EAPOL packet, don't bridge it, send it on.... */ if (GETETHERTYPE(pMblk) == 0x888E) return FALSE; pSrcPortInfo = (BRIDGE_PORT_INFO*)pNetCallBackId; pTempAddr = (UINT16 *)(pMblk->mBlkHdr.mData); /* Extract the received frame's MAC addresses, which is possibely in the * non cached memory, to the at least two byte aligned local stack variable, * which most likely is in the cached memory, to acheive the optimal * performace for this function. */ if (IS_4BYTE_ALIGNED(pTempAddr)) { /* the packet is at 4 byte boundary */ macAddr[0] = *(UINT32 *)pTempAddr; macAddr[1] = *((UINT32 *)pTempAddr + 1); macAddr[2] = *((UINT32 *)pTempAddr + 2); pMacDstAddr = (UINT16 *)macAddr; pMacSrcAddr = (UINT16 *)macAddr + 3; } else if (IS_2BYTE_ALIGNED(pTempAddr)) { /* at two byte boundary */ *((UINT16 *)macAddr + 1) = pTempAddr[0]; macAddr[1] = *(UINT32 *)(pTempAddr + 1); macAddr[2] = *(UINT32 *)(pTempAddr + 3); *(UINT16 *)(macAddr + 3) = pTempAddr[5]; pMacDstAddr = (UINT16 *)macAddr + 1; pMacSrcAddr = (UINT16 *)macAddr + 4; } else { /* at byte boundary, very unlikely */ bcopy((char *)pTempAddr, (char *)macAddr,6); bcopy((char *)pTempAddr + 6, (char *)macAddr + 6, 6); pMacDstAddr = (UINT16 *)macAddr; pMacSrcAddr = (UINT16 *)macAddr + 3; } /*************************************************************************** * source address processing, perform bridge learning function ***************************************************************************/ /* check if the source MAC address is in the station cache */ pSCEntry = stationCacheEntryFind(pMacSrcAddr); if (pSCEntry != NULL) { /* source MAC address is in the station cache */ if ((pSrcPortInfo != pSCEntry->pPortInfo) && !(pSCEntry->flags & BRIDGE_STATIC_FLAG)) { /* * the source MAC address is now connected to a different port * update the station cache */ pSCEntry->pPortInfo = pSrcPortInfo; } /* reset the station cache entry's tick count */ pSCEntry->tick = tickGet(); } else { /* * source MAC address is not in the station cache; * create new entry in the station cache */ stationCacheEntryAdd(pMacSrcAddr, pSrcPortInfo, 0); } /*************************************************************************** * destination address processing ***************************************************************************/ if (IS_BROADCAST(pMacDstAddr)) { /* destination MAC address is broadcast, flood forward packet */ if (packetFloodForward(pMblk, pSrcPortInfo) != OK) return FALSE; } else { /* destination MAC address is not broadcast */ pSCEntry = stationCacheEntryFind(pMacDstAddr); if (pSCEntry != NULL) { pDestPortInfo = pSCEntry->pPortInfo; /* destination MAC address is in station cache */ if (pSrcPortInfo == pDestPortInfo) { /* destination port is same as source port, discard packet */ netMblkClChainFree(pMblk); } else { /* * destination port is not the same as source port, * forward packet */ if (packetForward(pMblk, pDestPortInfo, pSrcPortInfo) != OK) return FALSE; } } else { /* * destination MAC address is not in station cache, * flood forward packet */ if (packetFloodForward(pMblk, pSrcPortInfo) != OK) return FALSE; } } return TRUE; }/******************************************************************************** bridgePortShutdownRtn - Shut down the bridge function on a particular port** This routine removes the bridge service from the MUX interface for this* port and frees the resources allocated. The bridge port must not be* used after this routine executes successfully.** RETURNS: OK always*/LOCAL STATUS bridgePortShutdownRtn ( void* pNetCallBackId ) { BRIDGE_PORT_INFO* pPortInfo; int index; pPortInfo = (BRIDGE_PORT_INFO*)pNetCallBackId; /*************************************************************************** * unbind the bridge from this port ***************************************************************************/ muxUnbind(pPortInfo->pMuxBindCookie, MUX_PROTO_SNARF, bridgeRcvRtn); /* give the muxUnbind some time to complete its job which is eventually done * in netTask context. The port should not be removed until it is unbinded */ taskDelay(5); /*************************************************************************** * remove this port from the bridge port list ***************************************************************************/ semTake(bridgePortListSemId, WAIT_FOREVER); lstDelete(&bridgePortList, (NODE*)pPortInfo); /*************************************************************************** * remove all entries regarding this port from the station cache ***************************************************************************/ for (index = 0; index < STATION_CACHE_SIZE; ++index) { if (pStationCache[index].inUse == TRUE) { if (pPortInfo == pStationCache[index].pPortInfo) stationCacheEntryDelete(&pStationCache[index]); } } semGive(bridgePortListSemId); free(pPortInfo); return OK; }/******************************************************************************** bridgeRestartRtn - Bridge restart routine** RETURNS: OK, or ERROR if bridge restart fails*/LOCAL STATUS bridgeRestartRtn ( void* pNetCallBackId ) { BRIDGE_PORT_INFO* pMirrorPortInfo; pMirrorPortInfo = portListEntryFind(MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM); if (pMirrorPortInfo == NULL) { DBG_PRINT(("BridgeRestartRtn: ERROR: \"%s%d\" didn't attach to the \ bridge!\n", MIRROR_DEV_NAME, MIRROR_BRIDGE_UNIT_NUM)); return ERROR; } if (muxIoctl (pMirrorPortInfo->pMuxBindCookie, ENDERRBLOCK, (caddr_t)MIRROR_END_ERR_BLOCK_CHECK) == MIRROR_END_ERR_BLOCK_TRUE) { muxIoctl (pMirrorPortInfo->pMuxBindCookie, ENDERRBLOCK, (caddr_t)MIRROR_END_ERR_UNBLOCK); } return OK; }/******************************************************************************** bridgeErrorRtn - Bridge Error routine ** NOMANUAL** RETURNS: N/A*/LOCAL void bridgeErrorRtn ( void* pNetCallBackId, END_ERR* pError ) { return; }/******************************************************************************** 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.** NOMANUAL** RETURNS: OK, or ERROR if bridge forward packets fails*/LOCAL STATUS packetForward ( M_BLK* pMblk, BRIDGE_PORT_INFO* pDestPortInfo, BRIDGE_PORT_INFO* pSrcPortInfo ) { STATUS status = OK; 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -