📄 bridge.c
字号:
{ DBG_PRINT(("bridgePortAdd: ERROR: \"%s%d\" is not attached to MUX.\n", pDevName, unitNum)); return ERROR; } /*************************************************************************** * verify that this port is not already attached to the bridge ***************************************************************************/ if (portListEntryFind(pDevName, unitNum) != NULL) { /* port is already in bridge port table */ DBG_PRINT(("bridgePortAdd: ERROR: \"%s%d\" is already attached\n", pDevName, unitNum)); return ERROR; } /*************************************************************************** * allocate space for bookkeeping info for the port ***************************************************************************/ pPortInfo = (BRIDGE_PORT_INFO*)malloc(sizeof(BRIDGE_PORT_INFO)); if (pPortInfo == NULL) { DBG_PRINT(("bridgePortAdd: ERROR: out of memory, malloc failure.\n")); return ERROR; } /*************************************************************************** * bind bridge to the port as a SNARFer ***************************************************************************/ pMuxBindCookie = muxTkBind(pDevName, unitNum, bridgeRcvRtn, bridgePortShutdownRtn, bridgeRestartRtn, bridgeErrorRtn, MUX_PROTO_SNARF, "bridge", pPortInfo, /* pNetCallBackId */ NULL, /* pNetSvcInfo */ NULL); /* pNetDrvInfo */ if (pMuxBindCookie == NULL) { DBG_PRINT(("bridgePortAdd: ERROR: muxTkBind() failed for \"%s%d\".\n", pDevName, unitNum)); free(pPortInfo); return ERROR; } /*************************************************************************** * save bookkeeping info for the port ***************************************************************************/ bzero((char*)pPortInfo, sizeof(BRIDGE_PORT_INFO)); bcopy(pDevName, pPortInfo->name, END_NAME_MAX - 1); pPortInfo->name[END_NAME_MAX - 1] = EOS; pPortInfo->unitNum = unitNum; pPortInfo->pMuxBindCookie = pMuxBindCookie; pPortInfo->errSndq.ifq_head = 0; pPortInfo->errSndq.ifq_tail = 0; pPortInfo->errSndq.ifq_len = 0; pPortInfo->errSndq.ifq_maxlen = SNDERRQ_MAX_LEN; pPortInfo->errSndq.ifq_drops = 0; 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** This routine removes an existing port from the bridge port list and unbinds* the bridge service from the MUX layer for that port.** RETURNS: OK, or ERROR if port removal fails** ERRNO: N/A*/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. If the migration happens, the bridge may stop receiving* packets.** RETURNS: OK, or ERROR if adding MAC address to station cache fails** ERRNO: N/A*/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** ERRNO: N/A*/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** ERRNO: N/A** NOMANUAL*/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** ERRNO: N/A** NOMANUAL*/LOCAL STATUS bridgePortShutdownRtn ( void* pNetCallBackId ) { BRIDGE_PORT_INFO* pPortInfo; int index; M_BLK_ID pMblk; 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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -