📄 skrlmt.c
字号:
/* * Send packet to RLMT multicast address * to force switches to learn the new * location of the address. */ SkEventQueue( pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); } } else { SK_ERR_LOG( pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG); } return; } else { Para.Para32[0] = A; /* * Preselection: * If RLMT Mode != CheckLinkState * select port that received a broadcast frame * substantially later than all other ports * else select first port that is not SuspectRx * else select first port that is PortUp * else select port that is PortGoingUp for the longest time * else select first port that is PortDown * else stop. * * For the preselected port: * If ActivePort is equal in quality, select ActivePort. * * If PrefPort is equal in quality, select PrefPort. * * If MacActive != SelectedPort, * If old ActivePort is LinkDown, * SwitchHard * else * SwitchSoft */ if (pAC->Rlmt.RlmtMode != SK_RLMT_CHECK_LINK) { if (!PortFound) { PortFound = SkRlmtSelectBcRx(pAC, IoC, A, P, &Para.Para32[1]); } if (!PortFound) { PortFound = SkRlmtSelectNotSuspect(pAC, IoC, A, P, &Para.Para32[1]); } } if (!PortFound) { PortFound = SkRlmtSelectUp(pAC, IoC, A, P, &Para.Para32[1], AUTONEG_SUCCESS); } if (!PortFound) { PortFound = SkRlmtSelectUp(pAC, IoC, A, P, &Para.Para32[1], AUTONEG_FAILED); } if (!PortFound) { PortFound = SkRlmtSelectGoingUp(pAC, IoC, A, P, &Para.Para32[1], AUTONEG_SUCCESS); } if (!PortFound) { PortFound = SkRlmtSelectGoingUp(pAC, IoC, A, P,&Para.Para32[1], AUTONEG_FAILED); } if (pAC->Rlmt.RlmtMode != SK_RLMT_CHECK_LINK) { if (!PortFound) { PortFound = SkRlmtSelectDown(pAC, IoC, A, P,&Para.Para32[1], AUTONEG_SUCCESS); } if (!PortFound) { PortFound = SkRlmtSelectDown(pAC, IoC, A, P,&Para.Para32[1], AUTONEG_FAILED); } } if (PortFound) { if (Para.Para32[1] != A) { pAC->Rlmt.MacActive = Para.Para32[1]; SK_HWAC_LINK_LED( pAC, IoC, Para.Para32[1], SK_LED_ACTIVE); if (pAC->Rlmt.Port[A].LinkDown) { SkEventQueue( pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para); } else { SK_HWAC_LINK_LED( pAC, IoC, Para.Para32[0], SK_LED_STANDBY); SkEventQueue( pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para); } SkEventQueue( pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_SWITCH, Para); if ((Para.pParaPtr = SkRlmtBuildPacket( pAC, IoC, Para.Para32[1], SK_PACKET_ANNOUNCE, &pAC->Addr.CurrentMacAddress, &SkRlmtMcAddr) ) != NULL) { /* * Send "new" packet to RLMT multicast * address to force switches to learn * the new location of the MAC address. */ SkEventQueue( pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); } } } else { SK_ERR_LOG( pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG); } } return;} /* SkRlmtCheckSwitch *//****************************************************************************** * * SkRlmtCheckSeg - Report if segmentation is detected * * Description: * This routine checks if the ports see different root bridges and reports * segmentation in such a case. * * Context: * runtime, pageable? * * Returns: * Nothing. */RLMT_STATIC void SkRlmtCheckSeg(SK_AC *pAC, /* adapter context */SK_IOC IoC) /* I/O context */{ SK_BOOL Equal; SK_U32 i, j; pAC->Rlmt.RootIdSet = SK_FALSE; Equal = SK_TRUE; for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (pAC->Rlmt.Port[i].LinkDown || !pAC->Rlmt.Port[i].RootIdSet) { continue; } SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i, pAC->Rlmt.Port[i].Root.Id[0], pAC->Rlmt.Port[i].Root.Id[1], pAC->Rlmt.Port[i].Root.Id[2], pAC->Rlmt.Port[i].Root.Id[3], pAC->Rlmt.Port[i].Root.Id[4], pAC->Rlmt.Port[i].Root.Id[5], pAC->Rlmt.Port[i].Root.Id[6], pAC->Rlmt.Port[i].Root.Id[7])) if (!pAC->Rlmt.RootIdSet) { pAC->Rlmt.Root = pAC->Rlmt.Port[i].Root; pAC->Rlmt.RootIdSet = SK_TRUE; continue; } for (j = 0; j < 8; j ++) { Equal &= pAC->Rlmt.Port[i].Root.Id[j] == pAC->Rlmt.Root.Id[j]; if (!Equal) { break; } } if (!Equal) { SK_ERR_LOG( pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG);#ifdef SK_PNMI_EVT_SEGMENTATION SkEventQueue( pAC, SKGE_PNMI, SK_PNMI_EVT_SEGMENTATION, Para);#endif /* SK_PNMI_EVT_SEGMENTATION */ pAC->Rlmt.CheckingState &= ~SK_RLMT_RCS_REPORT_SEG; break; } }} /* SkRlmtCheckSeg *//****************************************************************************** * * SkRlmtPortStart - initialize port variables and start port * * Description: * This routine initializes a port's variables and issues a PORT_START * to the HWAC module. This handles retries if the start fails or the * link eventually goes down. * * Context: * runtime, pageable? * * Returns: * Nothing */RLMT_STATIC void SkRlmtPortStart(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */SK_U32 PortIdx) /* event code */{ SK_EVPARA Para; pAC->Rlmt.Port[PortIdx].PortState = SK_RLMT_PS_LINK_DOWN; pAC->Rlmt.Port[PortIdx].PortStarted = SK_TRUE; pAC->Rlmt.Port[PortIdx].LinkDown = SK_TRUE; pAC->Rlmt.Port[PortIdx].PortDown = SK_TRUE; pAC->Rlmt.Port[PortIdx].CheckingState = 0; pAC->Rlmt.Port[PortIdx].RootIdSet = SK_FALSE; Para.Para32[0] = PortIdx; SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);} /* SkRlmtPortStart *//****************************************************************************** * * SkRlmtEvent - a PORT- or an RLMT-specific event happened * * Description: * This routine handles PORT- and RLMT-specific events. * * Context: * runtime, pageable? * may be called after SK_INIT_IO * * Returns: * 0 */int SkRlmtEvent(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */SK_U32 Event, /* event code */SK_EVPARA Para) /* event-specific parameter */{ SK_U32 i, j; SK_RLMT_PORT *pRPort; SK_EVPARA Para2; SK_MBUF *pMb; SK_MBUF *pNextMb; SK_MAC_ADDR *pOldMacAddr; SK_MAC_ADDR *pNewMacAddr; SK_U32 Timeout; SK_U32 NewTimeout; SK_U32 PrevRlmtMode; switch (Event) { case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */ SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event (%d) BEGIN.\n", Para.Para32[0], Event)) /* * Used to start non-preferred ports if the preferred one * does not come up. * This timeout needs only be set when starting the first * (preferred) port. */ if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { /* PORT_START failed. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (!pAC->Rlmt.Port[i].PortStarted) { SkRlmtPortStart(pAC, IoC, i); } } } SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_PORTSTART_TIMEOUT Event (%d) END.\n", Event)) break; case SK_RLMT_LINK_UP: /* From SIRQ. */ SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_LINK_UP Port %d Event (%d) BEGIN.\n", Para.Para32[0], Event)) pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; if (!pRPort->PortStarted) { SK_ERR_LOG( pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG); SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_LINK_UP Event (%d) EMPTY.\n", Event)) break; } if (!pRPort->LinkDown) { /* RA;:;: Any better solution? */ SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_LINK_UP Event (%d) EMPTY.\n", Event)) break; } SkTimerStop(pAC, IoC, &pRPort->UpTimer); SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); /* Do something if timer already fired? */ pRPort->LinkDown = SK_FALSE; pRPort->PortState = SK_RLMT_PS_GOING_UP; pRPort->GuTimeStamp = SkOsGetTime(pAC); pRPort->BcTimeStamp = 0; if (pAC->Rlmt.LinksUp == 0) { SK_HWAC_LINK_LED( pAC, IoC, Para.Para32[0], SK_LED_ACTIVE); } else { SK_HWAC_LINK_LED( pAC, IoC, Para.Para32[0], SK_LED_STANDBY); } pAC->Rlmt.LinksUp++; for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (!pAC->Rlmt.Port[i].PortStarted) { SkRlmtPortStart(pAC, IoC, i); } } SkRlmtCheckSwitch(pAC, IoC); if (pAC->Rlmt.LinksUp >= 2) { if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) { /* Build the check chain. */ SkRlmtBuildCheckChain(pAC); } } /* * If the first link comes up, start the periodical * RLMT timeout. */ if (pAC->GIni.GIMacsFound > 1 && pAC->Rlmt.LinksUp == 1 && (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_OTHERS)) { SkTimerStart( pAC, IoC, &pAC->Rlmt.LocTimer, pAC->Rlmt.TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para); } SkTimerStart( pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para); /* * Later: * if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */ if ((pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LINK) && (Para2.pParaPtr = SkRlmtBuildPacket( pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) ) != NULL) { /* Send "new" packet to RLMT multicast address. */ SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); } if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_SEG) { if ((Para2.pParaPtr = SkRlmtBuildSpanningTreePacket( pAC, IoC, Para.Para32[0]) ) != NULL) { pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE; pAC->Rlmt.CheckingState |= SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; SkEventQueue( pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); SkTimerStart( pAC, IoC, &pAC->Rlmt.SegTimer, SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); } } SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_LINK_UP Event (%d) END.\n", Event)) break; case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */ SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_PORTUP_TIM Port %d Event (%d) BEGIN.\n", Para.Para32[0], Event)) pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) { SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_PORTUP_TIM Port %d Event (%d) EMPTY.\n", Para.Para32[0], Event)) break; } pRPort->PortDown = SK_FALSE; pRPort->PortState = SK_RLMT_PS_UP; pAC->Rlmt.PortsUp++; if (pAC->Rlmt.RlmtState != SK_RLMT_RS_INIT) { SkRlmtCheckSwitch(pAC, IoC); SkEventQueue( pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para); } SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("S
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -