📄 skrlmt.c
字号:
/* 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; 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]; } 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 = PortNumber; Length -= 14; SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]); pAC->Rlmt.Port[PortNumber].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 PortNumber) /* Sending port */{ unsigned j; SK_EVPARA Para; SK_RLMT_PORT *pRPort; pRPort = &pAC->Rlmt.Port[PortNumber]; if (pAC->Rlmt.Port[PortNumber].Net->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 mc addr. */ if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].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, PortNumber, SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, &pRPort->PortCheck[j].CheckAddr)) != NULL) { SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); } } } } if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && (pAC->Rlmt.Port[PortNumber].Net->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, PortNumber)) != NULL) { pAC->Rlmt.Port[PortNumber].Net->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, SK_DBGCAT_TX, ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)) } } return;} /* SkRlmtSend *//****************************************************************************** * * SkRlmtPortReceives - check if port is (going) down and bring it up * * Description: * This routine checks if a port who received a non-BPDU packet * needs to go up or needs to be stopped going down. * * Context: * runtime, pageable? * * Returns: * Nothing. */RLMT_STATIC void SkRlmtPortReceives(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 PortNumber) /* Port to check */{ SK_RLMT_PORT *pRPort; SK_EVPARA Para; pRPort = &pAC->Rlmt.Port[PortNumber]; pRPort->PortNoRx = SK_FALSE; if ((pRPort->PortState == SK_RLMT_PS_DOWN) && !(pRPort->CheckingState & SK_RLMT_PCS_TX)) { /* * Port is marked down (rx), but received a non-BPDU packet. * Bring it up. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Received on PortDown.\n")) pRPort->PortState = SK_RLMT_PS_GOING_UP; pRPort->GuTimeStamp = SkOsGetTime(pAC); Para.Para32[0] = PortNumber; Para.Para32[1] = (SK_U32)-1; SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para); pRPort->CheckingState &= ~SK_RLMT_PCS_RX; /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); } /* PortDown && !SuspectTx */ else if (pRPort->CheckingState & SK_RLMT_PCS_RX) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Stop bringing port down.\n")) SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); pRPort->CheckingState &= ~SK_RLMT_PCS_RX; /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); } /* PortGoingDown */ return;} /* SkRlmtPortReceives *//****************************************************************************** * * SkRlmtPacketReceive - receive a packet for closer examination * * Description: * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD. * * Context: * runtime, pageable? * * Returns: * Nothing. */RLMT_STATIC void SkRlmtPacketReceive(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_MBUF *pMb) /* Received packet */{#ifdef xDEBUG extern void DumpData(char *p, int size);#endif /* DEBUG */ int i; unsigned j; SK_U16 PacketType;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -