📄 bridge.c
字号:
/* bridge.c - simple learning bridge without STP *//* * Copyright (c) 2000-2006 Wind River Systems, Inc. * * The right to copy, distribute, modify or otherwise make use * of this software may be licensed only pursuant to the terms * of an applicable Wind River license agreement. *//*modification history--------------------01z,04feb06,kch Fixed apigen doc errors and warnings.01y,14jul05,myz Fixed the broadcast failure when transmit buffers exhausted. 01y,20jun05,svk Detach from IPv6 stack in bridgeShutdown()01x,15apr05,svk Update API descriptions01w,07feb05,svk Make bridge version string const01v,29oct04,svk Add NOMANUAL to bridgeNextPhyDevEndGet()01u,20oct04,myz use _pNetDpool pool instead of driver's pool.01t,19jul04,myz improved END_ERR_BLOCK handling after field input.01s,05may04,svk If END_ERR_BLOCK happens more than once, prepend the packet to driver sendq01r,29apr04,myz fixed spr92002 and spr9670201q,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 (Spanning Tree Protocol).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"#ifdef INET6#include "if6Lib.h"#endif /* INET6 */#ifdef VIRTUAL_STACK#include <netinet/vsLib.h>#include <netinet/vsData.h>#include <netinet/vsNetCore.h>#endif /* VIRTUAL_STACK */#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)#define SNDERRQ_MAX_LEN 25/* 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; struct ifqueue errSndq; } 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/* externals */#ifndef VIRTUAL_STACKIMPORT NET_POOL_ID _pNetDpool;#endif /* VIRTUAL_STACK */extern int mirrorSendStatus;/* Global data */const 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;LOCAL END_OBJ* pMirrorStackEnd = NULL;LOCAL BRIDGE_PORT_INFO* pMirrorPortInfo = NULL;/* 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);LOCAL STATUS bcastPktToStackSend (M_BLK_ID, BRIDGE_PORT_INFO*, BRIDGE_PORT_INFO*);LOCAL STATUS packetToPortSend (M_BLK*, BRIDGE_PORT_INFO*,BRIDGE_PORT_INFO*);void bridgePortListShow(void);void bridgeStationCacheShow(void);/******************************************************************************** bridgeInit - initialize the bridge** This routine initializes the bridge and station cache, and creates a bridge * port list and station cache access mutexes. This routine must be called * before you use any of the other bridge functionality.** RETURNS: OK, or ERROR if bridge initialization fails** ERRNO: N/A*/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; } pMirrorStackEnd = NULL; pMirrorPortInfo = NULL; /*************************************************************************** * initialization complete ***************************************************************************/ bridgeInited = TRUE; return OK; }/******************************************************************************** bridgeShutdown - shut down the bridge** This routine performs the shutdown procedure of the bridge. It deletes the* bridge aging task, removes the bridge protocol interface from the MUX layer,* reverts the devices to non-promiscuous mode, unloads the mirror devices and* frees all the allocated resources. Once this routine is called, the bridge* can be restarted using its standard initialization routine.** Do not call this routine concurrently with the 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** ERRNO: N/A*/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);#ifdef INET6 ip6Detach(MIRROR_STACK_UNIT_NUM,MIRROR_DEV_NAME);#endif /* INET6 */ /* 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** This routine adds a device as a bridge port to the bridge port list.* bridgePortAdd() is called for the network interfaces that are attached to* the bridge as ports, including 'mirror1'. This routine binds the port's * device driver through the MUX as a network service with type * 'MUX_PROTO_SNARF'.** RETURNS: OK, or ERROR if port addition fails** ERRNO: N/A*/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)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -