⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skrlmt.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			pAC->Rlmt.Port[i].PortNoRx = SK_FALSE;			pAC->Rlmt.Port[i].RootIdSet = SK_FALSE;		}		pAC->Rlmt.RlmtState = SK_RLMT_RS_INIT;		pAC->Rlmt.RootIdSet = SK_FALSE;		pAC->Rlmt.MacPreferred = 0xFFFFFFFF;	  /* Automatic. */		pAC->Rlmt.PrefPort = SK_RLMT_DEF_PREF_PORT;		pAC->Rlmt.MacActive = pAC->Rlmt.PrefPort; /* Just assuming. */		pAC->Rlmt.RlmtMode = SK_RLMT_DEF_MODE;		pAC->Rlmt.TimeoutValue = SK_RLMT_DEF_TO_VAL;		break;	case SK_INIT_IO:	/* GIMacsFound first available here. */		SK_DBG_MSG(			pAC,			SK_DBGMOD_RLMT,			SK_DBGCAT_INIT,			("RLMT: %d MACs were detected.\n",				pAC->GIni.GIMacsFound))		/* Initialize HW registers? */		if (pAC->GIni.GIMacsFound < 2) {			Para.Para32[0] = SK_RLMT_CHECK_LINK;			(void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para);		}		break;	case SK_INIT_RUN:		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {			Random = SkOsGetTime(pAC);			*(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random;			for (j = 0; j < 4; j++) {				pAC->Rlmt.Port[i].Random[j] ^= pAC->Addr.Port[i					].CurrentMacAddress.a[SK_MAC_ADDR_LEN -					1 - j];			}			(void)SkAddrMcClear(				pAC,				IoC,				i,				SK_ADDR_PERMANENT | SK_MC_SW_ONLY);						/* Add RLMT MC address. */			(void)SkAddrMcAdd(				pAC,				IoC,				i,				&SkRlmtMcAddr,				SK_ADDR_PERMANENT);			if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_SEG) {				/* Add BPDU MC address. */				(void)SkAddrMcAdd(					pAC,					IoC,					i,					&BridgeMcAddr,					SK_ADDR_PERMANENT);			}			(void)SkAddrMcUpdate(pAC, IoC, i);		}		break;	default:	/* error */		break;	}	return;}	/* SkRlmtInit *//****************************************************************************** * *	SkRlmtBuildCheckChain - build the check chain * * Description: *	This routine builds the local check chain: *	- Each port that is up checks the next port. *	- The last port that is up checks the first port that is up. * * Notes: *	- Currently only local ports are considered when building the chain. *	- Currently the SuspectState is just reset; *	  it would be better to save it ... * * Context: *	runtime, pageable? * * Returns: *	Nothing */RLMT_STATIC void	SkRlmtBuildCheckChain(SK_AC	*pAC)	/* adapter context */{	SK_U32	i;	SK_U32	NumMacsUp;	SK_U32	FirstMacUp=0;	SK_U32	PrevMacUp=0;	if (!(pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK)) {		for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {			pAC->Rlmt.Port[i].PortsChecked = 0;		}		return;	/* Nothing to build. */	}	SK_DBG_MSG(		pAC,		SK_DBGMOD_RLMT,		SK_DBGCAT_CTRL,		("SkRlmtBuildCheckChain.\n"))	NumMacsUp = 0;	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {		pAC->Rlmt.Port[i].PortsChecked = 0;		pAC->Rlmt.Port[i].PortsSuspect = 0;		pAC->Rlmt.Port[i].CheckingState &=			~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX);		/*		 * If more than two links are detected we should consider		 * checking at least two other ports:		 * 1. the next port that is not LinkDown and		 * 2. the next port that is not PortDown.		 */		if (!pAC->Rlmt.Port[i].LinkDown) {			if (NumMacsUp == 0) {				FirstMacUp = i;			}			else {				pAC->Rlmt.Port[PrevMacUp].PortCheck[					pAC->Rlmt.Port[					PrevMacUp].PortsChecked].CheckAddr =					pAC->Addr.Port[i].CurrentMacAddress;				pAC->Rlmt.Port[PrevMacUp].PortCheck[					pAC->Rlmt.Port[					PrevMacUp].PortsChecked].SuspectTx =					SK_FALSE;				pAC->Rlmt.Port[PrevMacUp].PortsChecked++;			}			PrevMacUp = i;			NumMacsUp++;		}	}	if (NumMacsUp > 1) {		pAC->Rlmt.Port[PrevMacUp].PortCheck[pAC->Rlmt.Port[			PrevMacUp].PortsChecked].CheckAddr =			pAC->Addr.Port[FirstMacUp].CurrentMacAddress;		pAC->Rlmt.Port[PrevMacUp].PortCheck[pAC->Rlmt.Port[			PrevMacUp].PortsChecked].SuspectTx = SK_FALSE;		pAC->Rlmt.Port[PrevMacUp].PortsChecked++;	}#ifdef DEBUG	for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {                SK_DBG_MSG(                        pAC,                        SK_DBGMOD_RLMT,                        SK_DBGCAT_CTRL,                        ("Port %d checks %d other ports: %2X.\n",				i,				pAC->Rlmt.Port[i].PortsChecked,				pAC->Rlmt.Port[i].PortCheck[0].CheckAddr.a[5]))	}#endif	/* DEBUG */	return;       }	/* SkRlmtBuildCheckChain */#ifdef SK_RLMT_SLOW_LOOKAHEAD/****************************************************************************** * *	SkRlmtLookaheadPacket - examine received packet shortly, count s-th * * Description: *	This routine examines each received packet fast and short and *	increments some counters. *	The received packet has to be stored virtually contiguous. *	This function does the following: *	- Increment some counters. *	- Ensure length is sufficient. *	- Ensure that destination address is physical port address, *	  RLMT multicast, or BPDU multicast address. * * Notes: *	This function is fully reentrant while the fast path is not blocked. * * Context: *	isr/dpr, not pageable * * Returns: *	SK_FALSE packet for upper layers *	SK_TRUE  packet for RLMT */SK_BOOL	SkRlmtLookaheadPacket(SK_AC		*pAC,		/* adapter context */SK_U32		PortIdx,	/* receiving port */SK_U8		*pLaPacket,	/* received packet's data */unsigned	PacketLength,	/* received packet's length */ /* Necessary? */unsigned	LaLength)	/* lookahead length */{	int	i;	SK_BOOL	IsBc;		/* Broadcast address? */	int	RxDest;		/* Receive destination? */	int	Offset;		/* Offset of data to present to LOOKAHEAD. */	int	NumBytes;	/* #Bytes to present to LOOKAHEAD. */	SK_RLMT_PACKET	*pRPacket;	SK_ADDR_PORT	*pAPort;#ifdef DEBUG	PacketLength = PacketLength;#endif	/* DEBUG */	pRPacket = (SK_RLMT_PACKET*)pLaPacket;	pAPort = &pAC->Addr.Port[PortIdx];#ifdef DEBUG	if (pLaPacket == NULL) {		/* Create error log entry. */		SK_ERR_LOG(			pAC,			SK_ERRCL_SW,			SKERR_RLMT_E001,			SKERR_RLMT_E001_MSG);		SK_DBG_MSG(			pAC,			SK_DBGMOD_RLMT,			SK_DBGCAT_RX,			("SkRlmtLookaheadPacket: NULL pointer.\n"))		return (SK_FALSE);	}#endif	/* DEBUG */	/* Drivers should get IsBc from the descriptor. */	IsBc = SK_TRUE;	for (i = 0; IsBc && i < SK_MAC_ADDR_LEN; i++) {		IsBc = IsBc && (pLaPacket[i] == 0xFF);	}	SK_RLMT_PRE_LOOKAHEAD(		pAC,		PortIdx,		PacketLength,		IsBc,		&Offset,		&NumBytes)	if (NumBytes == 0) {		return (SK_FALSE);	}	SK_RLMT_LOOKAHEAD(		pAC,		PortIdx,		&pLaPacket[Offset],		IsBc,		pLaPacket[0] & 1,	/* Drivers: Get info from descriptor. */		&RxDest)	if (RxDest & SK_RLMT_RX_RLMT) {		return (SK_TRUE);	}	return (SK_FALSE);}	/* SkRlmtLookaheadPacket */#endif	/* SK_RLMT_SLOW_LOOKAHEAD *//****************************************************************************** * *	SkRlmtBuildPacket - build an RLMT packet * * Description: *	This routine sets up an RLMT packet. * * Context: *	runtime, pageable? * * Returns: *	NULL or pointer to RLMT mbuf */RLMT_STATIC SK_MBUF	*SkRlmtBuildPacket(SK_AC		*pAC,		/* adapter context */SK_IOC		IoC,		/* I/O context */SK_U32		PortIdx,	/* sending port */SK_U16		PacketType,	/* RLMT packet type */SK_MAC_ADDR	*SrcAddr,	/* source address */SK_MAC_ADDR	*DestAddr)	/* destination address */{	int		i;	SK_U16		Length;	SK_MBUF		*pMb;	SK_RLMT_PACKET	*pPacket;	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=		NULL) {		pPacket = (SK_RLMT_PACKET*)pMb->pData;		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {			pPacket->DstAddr[i] = DestAddr->a[i];			pPacket->SrcAddr[i] = SrcAddr->a[i];		}		pPacket->DSap = SK_RLMT_DSAP;		pPacket->SSap = SK_RLMT_SSAP;		pPacket->Ctrl = SK_RLMT_CTRL;		pPacket->Indicator[0] = SK_RLMT_INDICATOR0;		pPacket->Indicator[1] = SK_RLMT_INDICATOR1;		pPacket->Indicator[2] = SK_RLMT_INDICATOR2;		pPacket->Indicator[3] = SK_RLMT_INDICATOR3;		pPacket->Indicator[4] = SK_RLMT_INDICATOR4;		pPacket->Indicator[5] = SK_RLMT_INDICATOR5;		pPacket->Indicator[6] = SK_RLMT_INDICATOR6;		SK_U16_TO_NETWORK_ORDER(			PacketType,			&pPacket->RlmtPacketType[0]);		for (i = 0; i < 4; i++) {			pPacket->Random[i] = pAC->Rlmt.Port[PortIdx].Random[i];		}				SK_U16_TO_NETWORK_ORDER(			SK_RLMT_PACKET_VERSION,			&pPacket->RlmtPacketVersion[0]);		for (i = 0; i < SK_PACKET_DATA_LEN; i++) {			pPacket->Data[i] = 0x00;		}		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */		pMb->Length = Length;		pMb->PortIdx = PortIdx;		Length -= 14;		SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]);		if (PacketType == SK_PACKET_ALIVE) {			pAC->Rlmt.Port[PortIdx].TxHelloCts++;		}	}	return (pMb);       }	/* SkRlmtBuildPacket *//****************************************************************************** * *	SkRlmtBuildSpanningTreePacket - build spanning tree check packet * * Description: *	This routine sets up a BPDU packet for spanning tree check. * * Context: *	runtime, pageable? * * Returns: *	NULL or pointer to RLMT mbuf */RLMT_STATIC SK_MBUF	*SkRlmtBuildSpanningTreePacket(SK_AC	*pAC,		/* adapter context */SK_IOC	IoC,		/* I/O context */SK_U32	PortIdx)	/* sending port */{	unsigned		i;	SK_U16			Length;	SK_MBUF			*pMb;	SK_SPTREE_PACKET	*pSPacket;	if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) !=		NULL) {		pSPacket = (SK_SPTREE_PACKET*)pMb->pData;		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {			pSPacket->DstAddr[i] = BridgeMcAddr.a[i];			pSPacket->SrcAddr[i] =				pAC->Addr.Port[PortIdx].CurrentMacAddress.a[i];		}		pSPacket->DSap = SK_RLMT_SPT_DSAP;		pSPacket->SSap = SK_RLMT_SPT_SSAP;		pSPacket->Ctrl = SK_RLMT_SPT_CTRL;		pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0;		pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1;		pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID;		pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE;		pSPacket->Flags = SK_RLMT_SPT_FLAGS;		pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0;		pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1;		pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0;		pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1;		pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2;		pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3;		pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0;		pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1;		/*		 * Use virtual address as bridge ID and filter these packets		 * on receive.		 */		for (i = 0; i < SK_MAC_ADDR_LEN; i++) {			pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] =				pAC->Addr.CurrentMacAddress.a[i];		}		pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0;		pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1;		pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0;		pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1;		pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0;		pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1;		pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0;		pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1;		pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0;		pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1;		Length = SK_RLMT_MAX_PACKET_SIZE;	/* Or smaller. */		pMb->Length = Length;		pMb->PortIdx = PortIdx;		Length -= 14;		SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]);		pAC->Rlmt.Port[PortIdx].TxSpHelloReqCts++;	}	return (pMb);       }	/* SkRlmtBuildSpanningTreePacket *//****************************************************************************** * *	SkRlmtSend - build and send check packets * * Description: *	Depending on the RLMT state and the checking state, several packets *	are sent through the indicated port. * * Context: *	runtime, pageable? * * Returns: *	Nothing. */RLMT_STATIC void	SkRlmtSend(SK_AC	*pAC,	/* adapter context */SK_IOC	IoC,	/* I/O context */SK_U32	PortIdx){	unsigned	j;	SK_EVPARA	Para;	SK_RLMT_PORT	*pRPort;	pRPort = &pAC->Rlmt.Port[PortIdx];	if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) {		if (pRPort->CheckingState &			(SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) {			/*			 * Port is suspicious. Send the RLMT packet to the			 * RLMT multicast address.			 */			if ((Para.pParaPtr = SkRlmtBuildPacket(				pAC,				IoC,				PortIdx,				SK_PACKET_ALIVE,				&pAC->Addr.Port[PortIdx].CurrentMacAddress,				&SkRlmtMcAddr)) != NULL) {				SkEventQueue(					pAC,					SKGE_DRV,					SK_DRV_RLMT_SEND,					Para);			}		}		else {			/*			 * Send a directed RLMT packet to all ports that are			 * checked by the indicated port.			 */			for (j = 0; j < pRPort->PortsChecked; j++) {				if ((Para.pParaPtr =					SkRlmtBuildPacket(						pAC,						IoC,						PortIdx,						SK_PACKET_ALIVE,						&pAC->Addr.Port[PortIdx].CurrentMacAddress,						&pRPort->PortCheck[j].CheckAddr)						) != NULL) {					SkEventQueue(						pAC,						SKGE_DRV,						SK_DRV_RLMT_SEND,						Para);				}			}		}	}	if ((pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_SEG) &&		(pAC->Rlmt.CheckingState & SK_RLMT_RCS_SEND_SEG)) {		/*		 * Send a BPDU packet to make a connected switch tell us		 * the correct root bridge.		 */		if ((Para.pParaPtr =			SkRlmtBuildSpanningTreePacket(				pAC,				IoC,				PortIdx)			) != NULL) {						pAC->Rlmt.CheckingState &= ~SK_RLMT_RCS_SEND_SEG;			pRPort->RootIdSet = SK_FALSE;			SkEventQueue(				pAC,				SKGE_DRV,				SK_DRV_RLMT_SEND,				Para);			SK_DBG_MSG(				pAC,				SK_DBGMOD_RLMT,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -