📄 mirrorend.c
字号:
} break; case EIOCGFLAGS: if (data == NULL) { error = EINVAL; } else { *(int*)data = END_FLAGS_GET(pEndObj); } break; case EIOCPOLLSTART: error = mirrorEndPollStart(pDrvCtrl); break; case EIOCPOLLSTOP: error = mirrorEndPollStop(pDrvCtrl); break; case EIOCGMIB2: if (data == NULL) { error = EINVAL; } else { bcopy((char*)&pDrvCtrl->endObject.mib2Tbl, (char*)data, sizeof(pDrvCtrl->endObject.mib2Tbl)); } break; case EIOCGFBUF: if (data == NULL) { error = EINVAL; } else { *(int*)data = LENGTH_MIN_FBUF; } break; default: error = EINVAL; break; } return error; }/******************************************************************************** mirrorEndSend - output packet to network interface device** This routine() takes a M_BLK* and sends off the data in the M_BLK*.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer.** muxSend() calls this routine each time it wants to send a packet.** RETURNS: OK , ERROR or END_ERR_BLOCK** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndSend ( END_CTRL* pDrvCtrl, M_BLK* pMblk ) { int otherHalfOfMirror; int status = OK; LOG_MSG("mirrorEndSend: unit: %d, pollMode: %d, ", (int)pDrvCtrl->unit, (int)pDrvCtrl->polling, 4, 5, 6, 7); LOG_MSG("dst:%02X:%02X:%02X:%02X:%02X:%02X, ", *(UCHAR *)(pMblk->mBlkHdr.mData), *((UCHAR *)(pMblk->mBlkHdr.mData) + 1), *((UCHAR *)(pMblk->mBlkHdr.mData) + 2), *((UCHAR *)(pMblk->mBlkHdr.mData) + 3), *((UCHAR *)(pMblk->mBlkHdr.mData) + 4), *((UCHAR *)(pMblk->mBlkHdr.mData) + 5)); LOG_MSG("src:%02X:%02X:%02X:%02X:%02X:%02X\n", *((UCHAR *)(pMblk->mBlkHdr.mData) + 6), *((UCHAR *)(pMblk->mBlkHdr.mData) + 7), *((UCHAR *)(pMblk->mBlkHdr.mData) + 8), *((UCHAR *)(pMblk->mBlkHdr.mData) + 9), *((UCHAR *)(pMblk->mBlkHdr.mData) + 10), *((UCHAR *)(pMblk->mBlkHdr.mData) + 11)); if (pDrvCtrl->polling == TRUE) { netMblkClChainFree (pMblk); /* free the given mBlk chain */ return ERROR; } otherHalfOfMirror = pDrvCtrl->unit ^ 1; /* 0->1, 1->0 */ if (channelState[otherHalfOfMirror] == CHANNEL_UP) { /* other half of mirror is up, send packet there */ if (pDrvCtrl->unit == MIRROR_STACK_UNIT_NUM) mirrorSendStatus = OK; /* * In the previous version of the Bridge, calling mirrorEndReceive * directly caused deadlock when bridge tries to flood multicasts * outgoing from local stack. One way to avoid the deadlock is to * call mirrorEndReceive from tNetTask by using netJobAdd. But this * causes performance hit, and also overloads the netJob ring buffer. * * The better solution is to call mirrorEndReceive directly, and * avoid deadlock by not taking the bridge port list semaphore when * flooding packets to all bridge ports. Taking this semaphore was * previously thought necessary to guard against removal of a bridge * port when the bridge is flooding packets to that port. The * possibility of this occurring is very small, and can be avoided * if the user makes sure the bridge port is free of incoming and * outgoing traffic before removing the bridge port. */ mirrorEndReceive(&drvCtrl[otherHalfOfMirror], pMblk); if (pDrvCtrl->unit == MIRROR_STACK_UNIT_NUM) status = mirrorSendStatus; } else { /* other half of mirror is not up, toss the packet */ netMblkClChainFree(pMblk); } /* Bump the statistic counter. */ END_ERR_ADD(&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1); return status; }/******************************************************************************** isInMulticastList - is the address is a multicast address for this device?** This routine checks whether the given address matches a multicast address* from the current list of multicast addresses. ** RETURNS: TRUE or FALSE** ERRNO: N/A** NOMANUAL*/LOCAL BOOL isInMulticastList ( END_CTRL* pDrvCtrl, /* pointer to END_CTRL structure */ UINT16* enetAddr /* address to check */ ) { ETHER_MULTI* pCurr; pCurr = (ETHER_MULTI *)lstFirst(&pDrvCtrl->endObject.multiList); while (pCurr != (ETHER_MULTI *)NULL) { if (((UINT32)(pCurr->addr) & 0x01) == 0) { /* address is aligned on a 2 or 4 byte boundary */ if (MAC_ADDR_EQ(((UINT16 *)(pCurr->addr)), enetAddr) == TRUE) return TRUE; } else { /* address is aligned on a byte-boundary */ if (bcmp(pCurr->addr, (char *)enetAddr, 6) == 0) return TRUE; } pCurr = (ETHER_MULTI *)lstNext(&pCurr->node); } return FALSE; }/******************************************************************************** mirrorEndReceive - process an input frame** This routine processes an input frame, then passes it up to the higher * level in a form it expects. Buffer loaning, promiscuous mode are all * supported. Trailer protocols is not supported.** RETURNS: N/A** ERRNO: N/A** NOMANUAL*/LOCAL void mirrorEndReceive ( END_CTRL* pDrvCtrl, /* pointer to END_CTRL structure */ M_BLK* pMblk ) { UINT16 * pTmp; UINT16 enetAddr[3]; LOG_MSG("mirrorEndReceive: unit: %d, ", (int)pDrvCtrl->unit, 2, 3, 4, 5, 6); LOG_MSG("dst:%02X:%02X:%02X:%02X:%02X:%02X, ", *(UCHAR *)(pMblk->mBlkHdr.mData), *((UCHAR *)(pMblk->mBlkHdr.mData) + 1), *((UCHAR *)(pMblk->mBlkHdr.mData) + 2), *((UCHAR *)(pMblk->mBlkHdr.mData) + 3), *((UCHAR *)(pMblk->mBlkHdr.mData) + 4), *((UCHAR *)(pMblk->mBlkHdr.mData) + 5)); LOG_MSG("src:%02X:%02X:%02X:%02X:%02X:%02X\n", *((UCHAR *)(pMblk->mBlkHdr.mData) + 6), *((UCHAR *)(pMblk->mBlkHdr.mData) + 7), *((UCHAR *)(pMblk->mBlkHdr.mData) + 8), *((UCHAR *)(pMblk->mBlkHdr.mData) + 9), *((UCHAR *)(pMblk->mBlkHdr.mData) + 10), *((UCHAR *)(pMblk->mBlkHdr.mData) + 11)); /* don't allow the packet through if in polling mode */ if (pDrvCtrl->polling == TRUE) { netMblkClChainFree(pMblk); return; } /* if unit is not in promiscuous mode, filter packets to receive only * packets for our MAC address or broadcasts. */ if (pDrvCtrl->promiscuous == FALSE) { pTmp = (UINT16 *)(pMblk->mBlkHdr.mData); if (((UINT32)(pTmp) & 0x01) == 0) { /* address is aligned on a 2 or 4 byte boundary */ enetAddr[0] = pTmp[0]; enetAddr[1] = pTmp[1]; enetAddr[2] = pTmp[2]; } else { /* address is aligned on a byte-boundary */ bcopy((char *)pTmp, (char *)enetAddr, 6); } if ((MAC_ADDR_EQ(enetAddr, pDrvCtrl->enetAddr) == 0) && (IS_BROADCAST(enetAddr) == 0) && (isInMulticastList(pDrvCtrl, enetAddr) == FALSE)) { LOG_MSG("Dest addr not my addr/broadcast/multicast - dropping!\n", 1, 2, 3, 4, 5, 6); netMblkClChainFree(pMblk); return; } } LOG_MSG("Sending up the packet to my network stack\n", 1, 2, 3, 4, 5, 6); /* send up to protocol */ END_RCV_RTN_CALL(&pDrvCtrl->endObject, pMblk); /* bump input packet counter */ END_ERR_ADD(&pDrvCtrl->endObject, MIB2_IN_UCAST, +1); }/******************************************************************************** mirrorEndMCastAddrAdd - add a multicast address for the device** Multicast makes no sense in this driver. Keep the table for "get" calls.** RETURNS : OK or ERROR** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndMCastAddrAdd ( END_CTRL* pDrvCtrl, char* pAddr ) { STATUS error; error = etherMultiAdd(&pDrvCtrl->endObject.multiList, pAddr); if (error == ENETRESET) { pDrvCtrl->endObject.nMulti++; error = OK; } return (error == OK) ? OK : ERROR; }/******************************************************************************** mirrorEndMCastAddrDel - delete a multicast address for the device** This routine deletes a multicast address from the current list of* multicast addresses.** RETURNS : OK or ERROR** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndMCastAddrDel ( END_CTRL * pDrvCtrl, /* pointer to END_CTRL structure */ char * pAddr /* Address to delete from the table. */ ) { STATUS error; error = etherMultiDel(&pDrvCtrl->endObject.multiList, pAddr); if (error == ENETRESET) { pDrvCtrl->endObject.nMulti--; error = OK; } return (error == OK) ? OK : ERROR; }/******************************************************************************** mirrorEndMCastAddrGet - get the current multicast address list** This routine returns the current multicast address list in <pTable>** RETURNS: Multicast address list or NULL** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndMCastAddrGet ( END_CTRL* pDrvCtrl, MULTI_TABLE* pTable ) { return etherMultiGet(&pDrvCtrl->endObject.multiList, pTable); }/******************************************************************************** mirrorEndPollStart - start polling mode** Using polled mode for the mirror driver makes no sense. Do not use it.** RETURNS: OK** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndPollStart ( END_CTRL* pDrvCtrl ) { /* Set the polling flag */ pDrvCtrl->polling = TRUE; /* need to set the real device, we either put all devices associated with * this vritual mirror device into poll mode, or simply put one * currently only put one. */ (*pDrvCtrl->pPhyEnd->pFuncTable->ioctl)(pDrvCtrl->pPhyEnd,EIOCPOLLSTART,0); return OK; }/******************************************************************************** mirrorEndPollStop - stop polling mode** This routine stops the mirrorEnd from the polling mode.** RETURNS: OK always** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndPollStop ( END_CTRL* pDrvCtrl ) { /* reset the polling flag */ pDrvCtrl->polling = FALSE; (*pDrvCtrl->pPhyEnd->pFuncTable->ioctl)(pDrvCtrl->pPhyEnd,EIOCPOLLSTOP,0); return OK; }/******************************************************************************* mirrorEndPollSend - transmit a packet in polled mode** This routine is called by a user to try and send a packet on the* device. It sends a packet directly on the network from the caller without* going through the normal processes of queuing a packet on an output queue* and the waiting for the device to decide to transmit it.** If it detects a transmission error, the restart command is issued.** These routine should not call any kernel functions.** RETURNS: OK or EAGAIN** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndPollSend ( END_CTRL* pDrvCtrl, M_BLK* pMblk ) { STATUS status; /* mirror 1 should not call this function */ if (pDrvCtrl->unit != 0) return ERROR; /* call the poll routine in the real device */ status = pDrvCtrl->pPhyEnd->pFuncTable->pollSend(pDrvCtrl->pPhyEnd, pMblk); /* Bump the statistic counter. */ END_ERR_ADD(&pDrvCtrl->endObject, MIB2_OUT_UCAST, +1); return OK; }/******************************************************************************** mirrorEndPollReceive - receive a packet in polled mode** This routine receives a packet in polled mode** RETURNS: OK or ERROR** ERRNO: N/A** NOMANUAL*/LOCAL STATUS mirrorEndPollReceive ( END_CTRL* pDrvCtrl, M_BLK* pMblk ) { return pDrvCtrl->pPhyEnd->pFuncTable->pollRcv(pDrvCtrl->pPhyEnd, pMblk); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -