📄 skrlmt.c
字号:
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; SK_U32 PortNumber; SK_ADDR_PORT *pAPort; SK_RLMT_PORT *pRPort; SK_RLMT_PACKET *pRPacket; SK_SPTREE_PACKET *pSPacket; SK_EVPARA Para; PortNumber = pMb->PortIdx; pAPort = &pAC->Addr.Port[PortNumber]; pRPort = &pAC->Rlmt.Port[PortNumber]; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)) pRPacket = (SK_RLMT_PACKET*)pMb->pData; pSPacket = (SK_SPTREE_PACKET*)pRPacket;#ifdef xDEBUG DumpData((char *)pRPacket, 32);#endif /* DEBUG */ if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) { SkRlmtPortReceives(pAC, IoC, PortNumber); } /* Check destination address. */ if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) && !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) && !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) { /* Not sent to current MAC or registered MC address => Trash it. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Not for me.\n")) SkDrvFreeRlmtMbuf(pAC, IoC, pMb); return; } else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) { /* * Was sent by same port (may happen during port switching * or in case of duplicate MAC addresses). */ /* * Check for duplicate address here: * If Packet.Random != My.Random => DupAddr. */ for (i = 3; i >= 0; i--) { if (pRPort->Random[i] != pRPacket->Random[i]) { break; } } /* * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply * packets (they have the LLC_COMMAND_RESPONSE_BIT set in * pRPacket->SSap). */ if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP && pRPacket->Ctrl == SK_RLMT_CTRL && pRPacket->SSap == SK_RLMT_SSAP && pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Duplicate MAC Address.\n")) /* Error Log entry. */ SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG); } else { /* Simply trash it. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Sent by me.\n")) } SkDrvFreeRlmtMbuf(pAC, IoC, pMb); return; } /* Check SuspectTx entries. */ if (pRPort->PortsSuspect > 0) { for (j = 0; j < pRPort->PortsChecked; j++) { if (pRPort->PortCheck[j].SuspectTx && SK_ADDR_EQUAL( pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) { pRPort->PortCheck[j].SuspectTx = SK_FALSE; pRPort->PortsSuspect--; break; } } } /* Determine type of packet. */ if (pRPacket->DSap == SK_RLMT_DSAP && pRPacket->Ctrl == SK_RLMT_CTRL && (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP && pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { /* It's an RLMT packet. */ PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) | pRPacket->RlmtPacketType[1]); switch (PacketType) { case SK_PACKET_ANNOUNCE: /* Not yet used. */#if 0 /* Build the check chain. */ SkRlmtBuildCheckChain(pAC);#endif /* 0 */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Announce.\n")) SkDrvFreeRlmtMbuf(pAC, IoC, pMb); break; case SK_PACKET_ALIVE: if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Alive Reply.\n")) if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) || SK_ADDR_EQUAL( pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) { /* Obviously we could send something. */ if (pRPort->CheckingState & SK_RLMT_PCS_TX) { pRPort->CheckingState &= ~SK_RLMT_PCS_TX; SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); } if ((pRPort->PortState == SK_RLMT_PS_DOWN) && !(pRPort->CheckingState & SK_RLMT_PCS_RX)) { pRPort->PortState = SK_RLMT_PS_GOING_UP; pRPort->GuTimeStamp = SkOsGetTime(pAC); SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); 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); } } /* Mark sending port as alive? */ SkDrvFreeRlmtMbuf(pAC, IoC, pMb); } else { /* Alive Request Packet. */ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Alive Request.\n")) pRPort->RxHelloCts++; /* Answer. */ for (i = 0; i < SK_MAC_ADDR_LEN; i++) { pRPacket->DstAddr[i] = pRPacket->SrcAddr[i]; pRPacket->SrcAddr[i] = pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; } pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT; Para.pParaPtr = pMb; SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -