📄 mirrorend.c
字号:
/* mirrorEnd.c - mirroring END device driver *//* * 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--------------------01s,04feb06,kch Fixed apigen doc errors and warnings.01r,15apr05,svk Update API descriptions01q,07feb05,svk Remove unused/obsolete include01p,19jul04,myz removed end_err_block_flag and moved muxTxRestart to bridge.01o,07aug03,myz zero out drvCtrl at init, call mirrorEndStop and undo last fix in mirrorEndUnload01n,03jun03,myz clear the snarfCount in mirrorEndUnload01m,22may03,svk Add a missing cast, debug message changes01l,06may03,svk Remove the costly netJobAdd in mirrorEndSend()01k,02may03,svk Add multicast support, avoid a possible deadlock, address optimzation, re-format for coding convention01j,17apr03,svk Update copyright date01i,22nov02,zhu removed compiler warnings01h,22nov02,zhu added polling mode support01g,18oct02,ep removing gnu warning01f,15apr02,zhu changed arg types to call mirrorEndReceive01e,15apr02,zhu made changes to docs01d,10apr02,svk Replace another netJobAdd with mirrorEndReceive01c,09apr02,svk Replace a netJobAdd with mirrorEndReceive01b,27sep01,zhu TSR#257133 flow control01a,10oct00,jhl created*//*DESCRIPTIONThis library implements a mirroring END device driver.INCLUDE FILES: mirrorEnd.hSEE ALSO: endLib*//* includes */#include "vxWorks.h"#include "string.h"#include "iv.h"#include "taskLib.h"#include "memLib.h"#include "ioctl.h"#include "net/mbuf.h"#include "net/protosw.h"#include "socket.h"#include "errno.h"#include "errnoLib.h"#include "net/unixLib.h"#include "net/route.h"#include "net/if_subr.h"#include "cacheLib.h"#include "stdio.h"#include "intLib.h"#include "logLib.h"#include "netLib.h"#include "iosLib.h"#include "net/if.h"#include "netinet/in.h"#include "netinet/in_systm.h"#include "netinet/in_var.h"#include "netinet/ip.h"#include "netinet/if_ether.h"#include "etherLib.h"#include "etherMultiLib.h"#include "end.h"#include "semLib.h"/* Uncomment the line below to enable debug messages *//*#define END_MIRROR_DEBUG */#ifdef END_MIRROR_DEBUGint endMirrorDebug = 1;#define LOG_MSG \ if (endMirrorDebug) \ logMsg #else#define LOG_MSG(a0,a1,a2,a3,a4,a5,a6)#endif#undef END_MACROS#include "endLib.h"#include "lstLib.h"#include "netBufLib.h"#include "wrn/bridge/mirrorEnd.h"/* defines */#define LENGTH_MIN_FBUF 9 /* min. size of the first buffer in a frame */#define SPEED 10000000/* ethernet speed */#define MAX_MIRROR_CHANNELS 2#define CHANNEL_DOWN 0#define CHANNEL_UP 1/* macros *//* A shortcut for getting the hardware address from the MIB II stuff. */#define END_HADDR(pEnd) ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)#define END_HADDR_LEN(pEnd) ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)/* 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]) ) /* typedefs *//* END control structure */typedef struct end_ctrl { END_OBJ endObject; /* base class */ int unit; /* unit number */ BOOL promiscuous; /* promiscuous on or off */ BOOL polling; /* polling mode */ END_OBJ * pPhyEnd; UINT16 enetAddr[3]; /* ethernet address of this entry */ } END_CTRL;/* globals */int mirrorSendStatus = OK;/* locals */LOCAL UINT16 bcastMacAddr[3] = { 0xFFFF, 0xFFFF, 0xFFFF };LOCAL END_CTRL drvCtrl[MAX_MIRROR_CHANNELS]; /* array of driver control */LOCAL int channelState[MAX_MIRROR_CHANNELS] = {CHANNEL_DOWN, CHANNEL_DOWN };/* prototypes */END_OBJ* mirrorEndLoad(char* initString);LOCAL STATUS mirrorEndStart(END_CTRL* pDrvCtrl);LOCAL STATUS mirrorEndStop(END_CTRL* pDrvCtrl);LOCAL STATUS mirrorEndUnload(END_CTRL* pDrvCtrl);LOCAL int mirrorEndIoctl(END_CTRL* pDrvCtrl, int cmd, caddr_t data);LOCAL STATUS mirrorEndSend(END_CTRL* pDrvCtrl, M_BLK* pMblk);LOCAL void mirrorEndReceive(END_CTRL* pDrvCtrl, M_BLK* pMblk);LOCAL STATUS mirrorEndMCastAddrAdd(END_CTRL* pDrvCtrl, char* pAddress);LOCAL STATUS mirrorEndMCastAddrDel(END_CTRL* pDrvCtrl, char* pAddress);LOCAL STATUS mirrorEndMCastAddrGet(END_CTRL* pDrvCtrl, MULTI_TABLE* pTable);LOCAL STATUS mirrorEndPollStart(END_CTRL* pDrvCtrl);LOCAL STATUS mirrorEndPollStop(END_CTRL* pDrvCtrl);LOCAL STATUS mirrorEndPollSend(END_CTRL* pDrvCtrl, M_BLK* pMblk);LOCAL STATUS mirrorEndPollReceive(END_CTRL* pDrvCtrl, M_BLK* pMblk);LOCAL BOOL isInMulticastList(END_CTRL* pDrvCtrl, UINT16* enetAddr);extern STATUS bridgeNextPhyDevEndGet(char *,int *);/* * Define the device function table. This is static across all driver * instances. */LOCAL NET_FUNCS netFuncs = { (FUNCPTR)mirrorEndStart, /* start func. */ (FUNCPTR)mirrorEndStop, /* stop func. */ (FUNCPTR)mirrorEndUnload, /* unload func. */ (FUNCPTR)mirrorEndIoctl, /* ioctl func. */ (FUNCPTR)mirrorEndSend, /* send func. */ (FUNCPTR)mirrorEndMCastAddrAdd, /* multicast add func. */ (FUNCPTR)mirrorEndMCastAddrDel, /* multicast delete func. */ (FUNCPTR)mirrorEndMCastAddrGet, /* multicast get fun. */ (FUNCPTR)mirrorEndPollSend, /* polling send func. */ (FUNCPTR)mirrorEndPollReceive, /* polling receive func. */ endEtherAddressForm, /* Put address info into a packet. */ endEtherPacketDataGet, /* Get a pointer to packet data. */ endEtherPacketAddrGet /* Get packet addresses. */ };/******************************************************************************** mirrorEndLoad - initialize the driver and device** This routine initializes the driver and the device. All of the * device-specific parameters are passed in the <initString> parameter. * <initstring> is of the following format, where <unit> is the device* driver unit number:** <unit>:** Mirror driver unit number can be 'MIRROR_STACK_UNIT_NUM' (0) or* 'MIRROR_BRIDGE_UNIT_NUM' (1). These are defined in:** target/h/wrn/bridge/mirrorEnd.h** Typically, unit 0 is attached to the network stack and unit 1 is attached to* the bridge.** RETURNS: An END object pointer on success, or NULL on error** ERRNO: N/A**/END_OBJ* mirrorEndLoad ( char* initString ) { END_CTRL* pDrvCtrl; if (initString == NULL) return NULL; if (initString[0] == 0) { bcopy((char *)MIRROR_DEV_NAME, initString, MIRROR_DEV_NAME_LEN); return NULL; } /* Parse InitString */ switch (initString[0]) { case '0': pDrvCtrl = &drvCtrl[0]; bzero((char *)pDrvCtrl,sizeof(END_CTRL)); pDrvCtrl->unit = 0; SYS_ENET_ADDR_GET((char *) pDrvCtrl->enetAddr); break; case '1': pDrvCtrl = &drvCtrl[1]; bzero((char *)pDrvCtrl,sizeof(END_CTRL)); pDrvCtrl->unit = 1; /* if unit ever REALLY needs a MAC address, change this appropriately */ SYS_ENET_ADDR_GET((char *) pDrvCtrl->enetAddr); break; default: return NULL; } /* Check if we are already attached */ if (pDrvCtrl->endObject.attached == TRUE) return &pDrvCtrl->endObject; /* endObject initializations */ if (END_OBJ_INIT(&pDrvCtrl->endObject, (void*)pDrvCtrl, MIRROR_DEV_NAME, pDrvCtrl->unit, &netFuncs, MIRROR_END_OBJ_STRING) == ERROR) { return NULL; } /* Initialize MIB2 entries */ if (END_MIB_INIT(&pDrvCtrl->endObject, M2_ifType_ethernet_csmacd, (UCHAR *) pDrvCtrl->enetAddr, 6, ETHERMTU, SPEED) == ERROR) { return NULL; } /* we need to import the memory pool from a real physical driver. At least * the WDB end driver is using it */ if (pDrvCtrl->unit == 0) { char devName[END_NAME_MAX]; int unit = 0; bzero(devName,END_NAME_MAX); if (bridgeNextPhyDevEndGet(devName,&unit) == ERROR) { logMsg("mirrorEndLoad: No physical device found\n",1,2,3,4,5,6); } else { END_OBJ * pEnd; pEnd = endFindByName(devName,unit); if (pEnd != NULL) pDrvCtrl->endObject.pNetPool = pEnd->pNetPool; pDrvCtrl->pPhyEnd = pEnd; } } /* Mark the device ready */ /* IFF_SCAT is not defined by default */ END_OBJ_READY(&pDrvCtrl->endObject, IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST); /* Successful return */ return &pDrvCtrl->endObject; }/******************************************************************************** mirrorEndStart - start the device ** This routine marks the interface as up.** The complement of this routine is mirrorEndStop(). Once a unit is reset by* mirrorEndStop(), it may be re-initialized to a running state by this routine.* * RETURNS: OK if successful, otherwise ERROR** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndStart ( END_CTRL* pDrvCtrl ) { /* initialize flag(s) */ pDrvCtrl->polling = FALSE; pDrvCtrl->promiscuous = FALSE; /* mark the channel state as "UP" */ channelState[pDrvCtrl->unit] = CHANNEL_UP; /* raise the interface flags - mark the device as up */ END_FLAGS_SET (&pDrvCtrl->endObject, IFF_UP | IFF_RUNNING); return OK; }/******************************************************************************** mirrorEndStop - stop the device ** This routine marks the interface as down.** The complement of this routine is mirrorEndStart(). Once a unit is * stop in this routine, it may be re-initialized to a running state by * mirrorEndStart().** RETURNS: OK or ERROR** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndStop ( END_CTRL* pDrvCtrl ) { /* mark the channel state as "DOWN" */ channelState[pDrvCtrl->unit] = CHANNEL_DOWN; /* mark the driver as down */ END_FLAGS_CLR (&pDrvCtrl->endObject, IFF_UP | IFF_RUNNING); return OK; }/******************************************************************************* mirrorEndUnload - unload a driver from the system** This function first brings down the device, and then frees any* stuff that was allocated by the driver in the load function.** RETURNS: OK always** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndUnload ( END_CTRL* pDrvCtrl ) { mirrorEndStop(pDrvCtrl); END_OBJECT_UNLOAD(&pDrvCtrl->endObject); return OK; }/******************************************************************************** mirrorEndIoctl - network interface control routine** This routine implements the network interface control functions.* It handles EIOCSIFADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS,* EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2 and EIOCGFBUF ENDERRBLOCK commands.** RETURNS: OK if successful, otherwise EINVAL** ERRNO: N/A** NOMANUAL*/LOCAL int mirrorEndIoctl ( END_CTRL* pDrvCtrl, int cmd, caddr_t data ) { int error = 0; long value; END_OBJ* pEndObj = &pDrvCtrl->endObject; switch ((UINT)cmd) { case EIOCSADDR: if (data == NULL) { error = EINVAL; } else { bcopy((char*)data, (char*)END_HADDR(pEndObj), END_HADDR_LEN(pEndObj)); } break; case EIOCGADDR: if (data == NULL) { error = EINVAL; } else { bcopy((char*)END_HADDR(pEndObj), (char*)data, END_HADDR_LEN(pEndObj)); } break; case EIOCSFLAGS: value = (long)data; if (value < 0) { value = -value; value--; END_FLAGS_CLR(pEndObj, value); } else { END_FLAGS_SET(pEndObj, value); } if (END_FLAGS_GET(pEndObj) & IFF_PROMISC) { pDrvCtrl->promiscuous = TRUE; } else { pDrvCtrl->promiscuous = FALSE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -