📄 skrlmt.c
字号:
#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */#ifdef SK_LITTLE_ENDIAN#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \ SK_U8 *_Addr = (SK_U8*)(Addr); \ SK_U16 _Val = (SK_U16)(Val); \ *_Addr++ = (SK_U8)(_Val >> 8); \ *_Addr = (SK_U8)(_Val & 0xFF); \}#endif /* SK_LITTLE_ENDIAN */#ifdef SK_BIG_ENDIAN#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val))#endif /* SK_BIG_ENDIAN */#define AUTONEG_FAILED SK_FALSE#define AUTONEG_SUCCESS SK_TRUE/* typedefs *******************************************************************//* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */typedef struct s_RlmtPacket { SK_U8 DstAddr[SK_MAC_ADDR_LEN]; SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; SK_U8 TypeLen[2]; SK_U8 DSap; SK_U8 SSap; SK_U8 Ctrl; SK_U8 Indicator[7]; SK_U8 RlmtPacketType[2]; SK_U8 Align1[2]; SK_U8 Random[4]; /* Random value of requesting(!) station. */ SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */ SK_U8 Data[SK_PACKET_DATA_LEN];} SK_RLMT_PACKET;typedef struct s_SpTreeRlmtPacket { SK_U8 DstAddr[SK_MAC_ADDR_LEN]; SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; SK_U8 TypeLen[2]; SK_U8 DSap; SK_U8 SSap; SK_U8 Ctrl; SK_U8 ProtocolId[2]; SK_U8 ProtocolVersionId; SK_U8 BpduType; SK_U8 Flags; SK_U8 RootId[8]; SK_U8 RootPathCost[4]; SK_U8 BridgeId[8]; SK_U8 PortId[2]; SK_U8 MessageAge[2]; SK_U8 MaxAge[2]; SK_U8 HelloTime[2]; SK_U8 ForwardDelay[2];} SK_SPTREE_PACKET;/* global variables ***********************************************************/SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}};SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}};SK_MAC_ADDR BcAddr = {{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};/* local variables ************************************************************//* None. *//* functions ******************************************************************/RLMT_STATIC void SkRlmtCheckSwitch( SK_AC *pAC, SK_IOC IoC, SK_U32 NetIdx);RLMT_STATIC void SkRlmtCheckSeg( SK_AC *pAC, SK_IOC IoC, SK_U32 NetIdx);RLMT_STATIC void SkRlmtEvtSetNets( SK_AC *pAC, SK_IOC IoC, SK_EVPARA Para);/****************************************************************************** * * SkRlmtInit - initialize data, set state to init * * Description: * * SK_INIT_DATA * ============ * * This routine initializes all RLMT-related variables to a known state. * The initial state is SK_RLMT_RS_INIT. * All ports are initialized to SK_RLMT_PS_INIT. * * * SK_INIT_IO * ========== * * Nothing. * * * SK_INIT_RUN * =========== * * Determine the adapter's random value. * Set the hw registers, the "logical MAC address", the * RLMT multicast address, and eventually the BPDU multicast address. * * Context: * init, pageable * * Returns: * Nothing. */void SkRlmtInit(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */int Level) /* Initialization Level */{ SK_U32 i, j; SK_U64 Random; SK_EVPARA Para; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, ("RLMT Init level %d.\n", Level)) switch (Level) { case SK_INIT_DATA: /* Initialize data structures. */ SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT)); for (i = 0; i < SK_MAX_MACS; i++) { pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT; pAC->Rlmt.Port[i].LinkDown = SK_TRUE; pAC->Rlmt.Port[i].PortDown = SK_TRUE; pAC->Rlmt.Port[i].PortStarted = SK_FALSE; pAC->Rlmt.Port[i].PortNoRx = SK_FALSE; pAC->Rlmt.Port[i].RootIdSet = SK_FALSE; pAC->Rlmt.Port[i].PortNumber = i; pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0]; pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i]; } pAC->Rlmt.NumNets = 1; for (i = 0; i < SK_MAX_NETS; i++) { pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */ pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; /* Just assuming. */ pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; pAC->Rlmt.Net[i].NetNumber = i; } pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0]; pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1];#if SK_MAX_NETS > 1 pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1];#endif /* SK_MAX_NETS > 1 */ 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)) pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; /* Initialize HW registers? */ if (pAC->GIni.GIMacsFound < 2) { Para.Para32[0] = SK_RLMT_MODE_CLS; Para.Para32[1] = 0; (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para); } break; case SK_INIT_RUN: /* Ensure RLMT is set to one net. */ if (pAC->Rlmt.NumNets > 1) { Para.Para32[0] = 1; Para.Para32[1] = -1; SkRlmtEvtSetNets(pAC, IoC, Para); } 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->Rlmt.Port[i].AddrPort-> 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.Net[0].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 NetIdx) /* Net Number */{ SK_U32 i; SK_U32 NumMacsUp; SK_RLMT_PORT * FirstMacUp; SK_RLMT_PORT * PrevMacUp; FirstMacUp = NULL; PrevMacUp = NULL; if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) { pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; } return; /* Done. */ } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SkRlmtBuildCheckChain.\n")) NumMacsUp = 0; for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0; pAC->Rlmt.Net[NetIdx].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.Net[NetIdx].Port[i]->LinkDown) { if (NumMacsUp == 0) { FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; } else { pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[ pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr = pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress; PrevMacUp->PortCheck[ PrevMacUp->PortsChecked].SuspectTx = SK_FALSE; PrevMacUp->PortsChecked++; } PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; NumMacsUp++; } } if (NumMacsUp > 1) { PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr = FirstMacUp->AddrPort->CurrentMacAddress; PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx = SK_FALSE; PrevMacUp->PortsChecked++; }#ifdef DEBUG for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("Port %d checks %d other ports: %2X.\n", NetIdx, pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked, pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])) }#endif /* DEBUG */ return; } /* SkRlmtBuildCheckChain *//****************************************************************************** * * 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 PortNumber, /* 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[PortNumber].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 = PortNumber; Length -= 14; SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]); if (PacketType == SK_PACKET_ALIVE) { pAC->Rlmt.Port[PortNumber].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 PortNumber) /* 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[PortNumber].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 logical MAC 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.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber]. CurrentMacAddress.a[i]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -