📄 skrlmt.c
字号:
* Context: * runtime, pageable? * * Returns: * SK_BOOL */RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 Active, /* Active port */SK_U32 PrefPort, /* Preferred port */SK_U32 *pSelect, /* New active port */SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */{ SK_U64 GuTimeStamp; SK_U32 i; SK_BOOL PortFound; GuTimeStamp = 0; PortFound = SK_FALSE; /* Select port that is PortGoingUp for the longest time. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; *pSelect = i; PortFound = SK_TRUE; break; } } if (!PortFound) { return (SK_FALSE); } for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp && pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; *pSelect = i; } } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)) return (SK_TRUE);} /* SkRlmtSelectGoingUp *//****************************************************************************** * * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP) * * Description: * This routine selects a port that is down. * * Context: * runtime, pageable? * * Returns: * SK_BOOL */RLMT_STATIC SK_BOOL SkRlmtSelectDown(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 Active, /* Active port */SK_U32 PrefPort, /* Preferred port */SK_U32 *pSelect, /* New active port */SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */{ SK_U32 i; SK_BOOL PortFound; PortFound = SK_FALSE; /* Select first port that is PortDown. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN && pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { *pSelect = i; if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN && pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { *pSelect = Active; } if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN && pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { *pSelect = PrefPort; } PortFound = SK_TRUE; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)) break; } } return (PortFound);} /* SkRlmtSelectDown *//****************************************************************************** * * SkRlmtCheckSwitch - select new active port and switch to it * * Description: * This routine decides which port should be the active one and queues * port switching if necessary. * * Context: * runtime, pageable? * * Returns: * Nothing. */RLMT_STATIC void SkRlmtCheckSwitch(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 NetIdx) /* Net index */{ SK_EVPARA Para; SK_U32 Active; SK_U32 PrefPort; SK_U32 i; SK_BOOL PortFound; Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */ PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */ PortFound = SK_FALSE; pAC->Rlmt.CheckSwitch = SK_FALSE;#if 0 /* RW 2001/10/18 - active port becomes always prefered one */ if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */ /* disable auto-fail back */ PrefPort = Active; }#endif if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) { /* Last link went down - shut down the net. */ pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN; Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP; Para.Para32[1] = NetIdx; SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para); Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; Para.Para32[1] = NetIdx; SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); return; } /* pAC->Rlmt.LinksUp == 0 */ else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 && pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) { /* First link came up - get the net up. */ pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP; /* * If pAC->Rlmt.ActivePort != Para.Para32[0], * the DRV switches to the port that came up. */ for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) { i = Active; } if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) { i = PrefPort; } PortFound = SK_TRUE; break; } } if (PortFound) { Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; Para.Para32[1] = NetIdx; SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); pAC->Rlmt.Net[NetIdx].ActivePort = i; Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; Para.Para32[1] = NetIdx; SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { /* * Send announce packet to RLMT multicast address to force * switches to learn the new location of the logical MAC 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; } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */ else { /* Cannot be reached in dual-net mode. */ Para.Para32[0] = Active; /* * 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 ActivePort != SelectedPort, * If old ActivePort is LinkDown, * SwitchHard * else * SwitchSoft */ /* check of ChgBcPrio flag added */ if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && (!pAC->Rlmt.Net[0].ChgBcPrio)) { if (!PortFound) { PortFound = SkRlmtSelectBcRx( pAC, IoC, Active, PrefPort, &Para.Para32[1]); } if (!PortFound) { PortFound = SkRlmtSelectNotSuspect( pAC, IoC, Active, PrefPort, &Para.Para32[1]); } } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ /* with changed priority for last broadcast received */ if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && (pAC->Rlmt.Net[0].ChgBcPrio)) { if (!PortFound) { PortFound = SkRlmtSelectNotSuspect( pAC, IoC, Active, PrefPort, &Para.Para32[1]); } if (!PortFound) { PortFound = SkRlmtSelectBcRx( pAC, IoC, Active, PrefPort, &Para.Para32[1]); } } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ if (!PortFound) { PortFound = SkRlmtSelectUp( pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); } if (!PortFound) { PortFound = SkRlmtSelectUp( pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); } if (!PortFound) { PortFound = SkRlmtSelectGoingUp( pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); } if (!PortFound) { PortFound = SkRlmtSelectGoingUp( pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); } if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) { if (!PortFound) { PortFound = SkRlmtSelectDown(pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); } if (!PortFound) { PortFound = SkRlmtSelectDown(pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); } } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ if (PortFound) { if (Para.Para32[1] != Active) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])) pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1]; Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. Port[Para.Para32[0]]->PortNumber; Para.Para32[1] = pAC->Rlmt.Net[NetIdx]. Port[Para.Para32[1]]->PortNumber; SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE); if (pAC->Rlmt.Port[Active].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); } Para.Para32[1] = NetIdx; Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber; SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { /* * Send announce packet to RLMT multicast address to force * switches to learn the new location of the logical * MAC address. */ SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */ } /* Para.Para32[1] != Active */ } /* PortFound */ else { SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG); } } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */ 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_U32 NetIdx) /* Net number */{ SK_EVPARA Para; SK_RLMT_NET *pNet; SK_U32 i, j; SK_BOOL Equal; pNet = &pAC->Rlmt.Net[NetIdx]; pNet->RootIdSet = SK_FALSE; Equal = SK_TRUE; for (i = 0; i < pNet->NumPorts; i++) { if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) { continue; } SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i, pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1], pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3], pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5], pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])) if (!pNet->RootIdSet) { pNet->Root = pNet->Port[i]->Root; pNet->RootIdSet = SK_TRUE; continue; } for (j = 0; j < 8; j ++) { Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j]; if (!Equal) { break; } } if (!Equal) { SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG); Para.Para32[0] = NetIdx; Para.Para32[1] = (SK_U32)-1; SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para); pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG; /* 2000-03-06 RA: New. */ Para.Para32[0] = NetIdx; Para.Para32[1] = (SK_U32)-1; SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); break; } } /* for (i = 0; i < pNet->NumPorts; i++) */ /* 2000-03-06 RA: Moved here. */ /* Segmentation check not running anymore. */ pNet->CheckingState &= ~SK_RLMT_RCS_SEG;} /* 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 PortNumber) /* Port number */{ SK_EVPARA Para; pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN; pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE; pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE; pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE; pAC->Rlmt.Port[PortNumbe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -