📄 skrlmt.c
字号:
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 + -