📄 skrlmt.c
字号:
#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. *//* Remaining 6 bytes will be the current port address. */#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. *//* Remaining 6 bytes will be the current port address. */#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */#define SK_RLMT_SPT_MSG_AGE0 0x00#define SK_RLMT_SPT_MSG_AGE1 0x00#define SK_RLMT_SPT_MAX_AGE0 0x00#define SK_RLMT_SPT_MAX_AGE1 0xFF#define SK_RLMT_SPT_HELLO_TIME0 0x00#define SK_RLMT_SPT_HELLO_TIME1 0xFF#define SK_RLMT_SPT_FWD_DELAY0 0x00#define SK_RLMT_SPT_FWD_DELAY1 0x40/* Size defines. */#define SK_RLMT_MIN_PACKET_SIZE 34#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE)#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \ SK_RLMT_MIN_PACKET_SIZE)/* ----- RLMT packet types ----- */#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */#define SK_PACKET_ALIVE 2 /* Alive packet to port. */#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */#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_MAC_ADDR VirtualMacAddress; SK_MAC_ADDR PhysicalAMacAddress; SK_BOOL VirtualMacAddressSet; SK_BOOL PhysicalAMacAddressSet; 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].PrefPort = SK_RLMT_DEF_PREF_PORT; pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */ /* 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 == 1) { 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); } VirtualMacAddressSet = SK_FALSE; /* Read virtual MAC address from Control Register File. */ for (j = 0; j < SK_MAC_ADDR_LEN; j++) { SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); VirtualMacAddressSet |= VirtualMacAddress.a[j]; } PhysicalAMacAddressSet = SK_FALSE; /* Read physical MAC address for MAC A from Control Register File. */ for (j = 0; j < SK_MAC_ADDR_LEN; j++) { SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; } /* check if the two mac addresses contain reasonable values */ if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { pAC->Rlmt.RlmtOff = SK_TRUE; } /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD and the RLMT_LOOKAHEAD macros */ else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { pAC->Rlmt.RlmtOff = SK_TRUE; } else { pAC->Rlmt.RlmtOff = SK_FALSE; } 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 { PrevMacUp->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", i, 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;#ifdef DEBUG SK_U8 CheckSrc = 0; SK_U8 CheckDest = 0; for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { CheckSrc |= SrcAddr->a[i]; CheckDest |= DestAddr->a[i]; } if ((CheckSrc == 0) || (CheckDest == 0)) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, ("SkRlmtBuildPacket: Invalid %s%saddr.\n", (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))) }#endif 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -