📄 bridge.c
字号:
/* bridge.c - Simple learning bridge without STP uses NPT *//* Copyright 2000-2003 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01q,20jun03,myz removed the code for Patch muxTkBind override. This is not needed for protocol type MUX_PROTO_SNARF01p,28may03,myz added bridgeShutdown routine01o,07may03,svk Add support for static mac addresses in bridge station cache01n,06may03,svk Assume bridge port will not be removed when in use, reformat for coding convention01m,01may03,svk Don't bridge EAPOL packet, handle tick wrap-around01l,17apr03,svk Implement version number, update copyright01k,22nov02,zhu added bridgeNextPhyDevEndGet function01j,28oct02,zhu reduce compiler warnings01i,28oct02,zhu fixed station cache aging timeout calculation01h,18oct02,zhu added protocol check01g,19sep02,zhu optimized bridge code01f,16jul02,zhu turned debug flag BRIDGE_DEBUG off01e,06may02,zhu fixing bugs in floodForwardPacket01d,15apr02,zhu made changes for docs01c,04oct01,vks MIPS alignment, station cache bugs 01b,27sep01,zhu TSR#257133 flow control01a,28sep00,jhl created*//*DESCRIPTIONThis library implements a simple learning bridge without STP uses NPT.INCLUDE FILES: bridge.h mirrorEnd.hSEE ALSO: muxLib*/#include "vxWorks.h"#include "string.h"#include "stdlib.h"#include "stdio.h"#include "memLib.h"#include "lstLib.h"#include "taskLib.h"#include "semLib.h"#include "sysLib.h"#include "tickLib.h"#include "muxLib.h"#include "muxTkLib.h"#include "end.h"#include "netLib.h"#include "net/if.h"#include "private/muxLibP.h"#include "ipProto.h"#include "wrn/bridge/bridge.h"#include "wrn/bridge/mirrorEnd.h"/* Uncomment the line below to enable debug messages *//*#define BRIDGE_DEBUG */#ifdef BRIDGE_DEBUGint bridgeDebug = 1;#define DBG_PRINT(X) \ do { \ if (bridgeDebug) \ printf X; \ }while(0)#else#define DBG_PRINT(X)#endif/**************************************************************************** constants*/#define STATION_CACHE_SIZE 1024 /* must be a power of 2 */#define AGING_CHECK_DELAY_SECONDS 15#define AGING_TIMEOUT_SECONDS (5 * 60)/**************************************************************************** typedefs*//**************************************** * bridge port information ****************************************/typedef struct { NODE node; /* must be first member in the structure */ char name[END_NAME_MAX]; int unitNum; void* pMuxBindCookie; char portType; } BRIDGE_PORT_INFO;/**************************************** * defs for BRIDGE_PORT_INFO::portType ****************************************/#define BRIDGE_PORT_TYPE_END 0#define BRIDGE_PORT_TYPE_NPT 1/**************************************** * station cache entry ****************************************/typedef struct { BOOL inUse; /* entry in use/available */ BRIDGE_PORT_INFO* pPortInfo; /* port info for port this entry is attached to */ UINT32 tick; /* sys tick this port was last heard from */ UINT16 macAddr[3]; /* MAC address of this entry */ UINT32 flags; /* static or dynamic */ } STATION_CACHE_ENTRY;/**************************************************************************** macros*/#define STR_EQ(A,B) ((strcmp((A), (B)) == 0) ? TRUE : FALSE)/* both pMac1 and pMac2 must point to a two byte boundary */#define MAC_ADDR_EQ(pMac1,pMac2) \ ((pMac1[0] == pMac2[0]) && \ (pMac1[1] == pMac2[1]) && \ (pMac1[2] == pMac2[2])) /* pMacAddr must point to a two byte boundary */#define IS_BROADCAST(pMacAddr) \ ((pMacAddr[0] == bcastMacAddr[0]) && \ (pMacAddr[1] == bcastMacAddr[1]) && \ (pMacAddr[2] == bcastMacAddr[2]))#define IS_4BYTE_ALIGNED(pAddr) \ (!((UINT32)(pAddr) & 0x3))#define IS_2BYTE_ALIGNED(pAddr) \ (!((UINT32)(pAddr) & 0x1))#if (_BYTE_ORDER == _BIG_ENDIAN)#define GETETHERTYPE(pMblk) (*(UINT16*)(pMblk->mBlkHdr.mData + 12))#else /* (_BYTE_ORDER == _BIG_ENDIAN) */#define GETETHERTYPE(pMblk) (((*(UINT8*)(pMblk->mBlkHdr.mData + 12)) << 8) | \ (*(UINT8*)(pMblk->mBlkHdr.mData + 13)))#endif /* (_BYTE_ORDER == _BIG_ENDIAN) *//**************************************** * station cache manipulation macros ****************************************/#define SC_ASSOCIATIVE_SET_SIZE 4/**************************************************************************** Global data*/char * bridgeVersion = BRIDGE_VERSION;/**************************************************************************** Local data*/LOCAL UINT16 bcastMacAddr[3] = { 0xFFFF, 0xFFFF, 0xFFFF };LOCAL BOOL bridgeInited = FALSE;LOCAL LIST bridgePortList;LOCAL STATION_CACHE_ENTRY* pStationCache;LOCAL SEM_ID bridgePortListSemId;LOCAL SEM_ID stationCacheSemId;LOCAL int agingTaskId;/**************************************************************************** prototypes*/LOCAL BOOL bridgeRcvRtn(void* pNetCallBackId, long type, M_BLK* pMblk, void* pSpareData);LOCAL STATUS bridgePortShutdownRtn(void* pNetCallBackId);LOCAL STATUS bridgeRestartRtn(void* pNetCallBackId);LOCAL void bridgeErrorRtn(void* pNetCallBackId, END_ERR* pError); LOCAL STATUS packetForward(M_BLK* pMblk, BRIDGE_PORT_INFO* pDestPortInfo, BRIDGE_PORT_INFO* pSrcPortInfo);LOCAL STATUS packetFloodForward(M_BLK* pMblk, BRIDGE_PORT_INFO* pSrcPortInfo);LOCAL void bridgeAgingTask(void);LOCAL void stationCacheEntryAdd(UINT16* pMacAddr, BRIDGE_PORT_INFO* pPortInfo, UINT32 flags);LOCAL void stationCacheEntryDelete(STATION_CACHE_ENTRY* pSCEntry);LOCAL STATION_CACHE_ENTRY* stationCacheEntryFind(UINT16* pMacAddr);LOCAL BRIDGE_PORT_INFO* portListEntryFind(char* pDevName, int unitNum);void bridgePortListShow(void);void bridgeStationCacheShow(void);/******************************************************************************** bridgeInit - Initialize bridge** Initialize bridge and station cache. Create bridge port list and * station cache access mutexes.** RETURNS: OK, or ERROR if bridge initialization fails*/STATUS bridgeInit(void) { int index; if (bridgeInited == TRUE) return OK; /*************************************************************************** * initialize the station cache ***************************************************************************/ pStationCache = (STATION_CACHE_ENTRY*)calloc(STATION_CACHE_SIZE, sizeof(STATION_CACHE_ENTRY)); if (pStationCache == NULL) { DBG_PRINT(("bridgeInit: ERROR: Failure allocating station cache.\n")); return ERROR; } for (index = 0; index < STATION_CACHE_SIZE; ++index) pStationCache[index].inUse = FALSE; /*************************************************************************** * initialize the bridge port information list ***************************************************************************/ lstInit(&bridgePortList); /*************************************************************************** * create bridge port list and station cache access mutexes ***************************************************************************/ bridgePortListSemId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); if (bridgePortListSemId == NULL) { DBG_PRINT(("bridgeInit: ERROR: Failure creating bridge list mutex.\n")); free(pStationCache); return ERROR; } stationCacheSemId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); if (stationCacheSemId == NULL) { DBG_PRINT(("bridgeInit: ERROR: Failure creating bridge list mutex.\n")); free(pStationCache); semDelete(bridgePortListSemId); return ERROR; } /*************************************************************************** * initialization complete ***************************************************************************/ agingTaskId = taskSpawn("tBridgeAger", 250, 0, 4096, (FUNCPTR)bridgeAgingTask, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (agingTaskId == ERROR) { DBG_PRINT(("bridgeInit: ERROR: Failure starting bridge aging task.\n")); free(pStationCache); semDelete(bridgePortListSemId); semDelete(stationCacheSemId); return ERROR; } /*************************************************************************** * initialization complete ***************************************************************************/ bridgeInited = TRUE; return OK; }/******************************************************************************** bridgeShutdown - Shut down the bridge component** This routine performs the shutdown procedure of the bridge component. It* deletes the bridge aging task, removes bridge protocol interface from* MUX layer, reverts back the devices to non-promiscuous mode, unloads the* mirror devices and finally frees all the allocated resources. Once this* routine is called, the bridge component can be restarted using its standard* initialization routine.** This routine should not be called concurrently with bridgePortRemove and* bridgePortAdd routines. No data packet should be sent to the bridge ports* by the local IP stack during the operation.** RETURNS: OK, or ERROR if fail to shut down*/STATUS bridgeShutdown(void) { BRIDGE_PORT_INFO* pPortInfo; BRIDGE_PORT_INFO* pNextPortInfo; END_OBJ * pEnd; /* validate the operation */ if (bridgeInited == FALSE) return ERROR; /* First set the device back to non promiscuous mode. This operation * should stop most of bridge traffic */ pPortInfo = (BRIDGE_PORT_INFO*)lstFirst(&bridgePortList); while (pPortInfo != NULL) { muxIoctl(pPortInfo->pMuxBindCookie,EIOCSFLAGS,(caddr_t)(~IFF_PROMISC)); pPortInfo = (BRIDGE_PORT_INFO *)lstNext((NODE*)pPortInfo); } /* delete tBridgeAger task */ taskDelete(agingTaskId); /* Now remove the bridge ports */ pPortInfo = (BRIDGE_PORT_INFO*)lstFirst(&bridgePortList); while (pPortInfo != NULL) { pNextPortInfo = (BRIDGE_PORT_INFO *)lstNext((NODE*)pPortInfo); if (strcmp(MIRROR_DEV_NAME, pPortInfo->name) == 0) { /* must be mirror 1 bridge port */ pEnd = endFindByName (pPortInfo->name,pPortInfo->unitNum); if (pEnd != NULL) { /* Need to set this field to some value different from pEnd * to prevent the muxDevUnload from freeing the drvCtrl * descriptor which is statically allocated in our case */ pEnd->devObject.pDevice = NULL; muxDevUnload(pPortInfo->name,pPortInfo->unitNum); } } else { bridgePortShutdownRtn((void*)pPortInfo); } pPortInfo = pNextPortInfo; } /* detach from IP stack for MIRROR_STACK_UNIT */ ipDetach(MIRROR_STACK_UNIT_NUM,MIRROR_DEV_NAME); /* unload the mirror end drivers */ pEnd = endFindByName (MIRROR_DEV_NAME,MIRROR_STACK_UNIT_NUM); if (pEnd != NULL) { pEnd->devObject.pDevice = NULL; muxDevUnload(MIRROR_DEV_NAME,MIRROR_STACK_UNIT_NUM); } /* free the station cache */ free((void *)pStationCache); /* delete bridgePortListSemId and stationCacheSemId */ semDelete(bridgePortListSemId); semDelete(stationCacheSemId); bridgeInited = FALSE; return OK; } /******************************************************************************** bridgePortAdd - Add a device as a bridge port** Add a device as a bridge port to the bridge port list.** RETURNS: OK, or ERROR if port addition fails*/STATUS bridgePortAdd ( char* pDevName, /* device name */ int unitNum /* unit number */ ) { void* pMuxBindCookie; BRIDGE_PORT_INFO* pPortInfo; END_OBJ* pEnd; /*************************************************************************** * if bridge hasn't been init'ed, initialize it ***************************************************************************/ if (bridgeInited == FALSE) bridgeInit(); /*************************************************************************** * verify that the port is already attached to the MUX ***************************************************************************/ pEnd = endFindByName(pDevName, unitNum); if (pEnd == NULL) { 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -