📄 skrlmt.c
字号:
* Returns: * New timeout value. */RLMT_STATIC SK_U32 SkRlmtCheckPort(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */SK_U32 PortIdx) /* port to check */{ unsigned i; SK_U32 NewTimeout; SK_RLMT_PORT *pRPort; SK_EVPARA Para; pRPort = &pAC->Rlmt.Port[PortIdx]; if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) { SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n", PortIdx, pRPort->PacketsPerTimeSlot)) /* * Check segmentation if there was no receive at least twice * in a row (PortNoRx is already set) and the segmentation * check is not currently running. */ if (pRPort->PortNoRx && (pAC->Rlmt.LinksUp > 1) && (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_SEG) && !(pAC->Rlmt.CheckingState & SK_RLMT_RCS_SEG)) { pAC->Rlmt.CheckingState |= SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; } SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n", pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)) if (pRPort->PortState != SK_RLMT_PS_DOWN) { NewTimeout = TO_SHORTEN(pAC->Rlmt.TimeoutValue); if (NewTimeout < SK_RLMT_MIN_TO_VAL) { NewTimeout = SK_RLMT_MIN_TO_VAL; } if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) { Para.Para32[0] = PortIdx; pRPort->CheckingState |= SK_RLMT_PCS_RX; /* * What shall we do if the port checked * by this one receives our request * frames? What's bad - our rx line * or his tx line? */ SkTimerStart( pAC, IoC, &pRPort->DownRxTimer, SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTDOWN_RX_TIM, Para); for (i = 0; i < pRPort->PortsChecked; i++) { if (pRPort->PortCheck[i].SuspectTx) { continue; } pRPort->PortCheck[i].SuspectTx = SK_TRUE; pRPort->PortsSuspect++; if ((Para.pParaPtr = SkRlmtBuildPacket( pAC, IoC, PortIdx, SK_PACKET_CHECK_TX, &pAC->Addr.Port[PortIdx].CurrentMacAddress, &pRPort->PortCheck[i].CheckAddr) ) != NULL) { SkEventQueue( pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); } } } } else { /* PortDown -- or all partners suspect. */ NewTimeout = SK_RLMT_DEF_TO_VAL; } pRPort->PortNoRx = SK_TRUE; } else { /* A non-BPDU packet was received. */ SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n", PortIdx, pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, pRPort->PacketsPerTimeSlot)) SkRlmtPortReceives(pAC, IoC, PortIdx); NewTimeout = SK_RLMT_DEF_TO_VAL; } return (NewTimeout); } /* SkRlmtCheckPort *//****************************************************************************** * * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP) * * Description: * This routine selects the port that received a broadcast frame * substantially later than all other ports. * * Context: * runtime, pageable? * * Returns: * SK_BOOL */RLMT_STATIC SK_BOOL SkRlmtSelectBcRx(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */SK_U32 A, /* active port */SK_U32 P, /* preferred port */SK_U32 *N) /* new active port */{ SK_U64 BcTimeStamp; SK_U32 i; SK_BOOL PortFound; BcTimeStamp = 0; /* Not totally necessary, but feeling better. */ PortFound = SK_FALSE; /* Select port with the latest TimeStamp. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("TimeStamp Port %d: %.08x%.08x.\n", i, *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32), *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))) if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) { if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) { BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp; *N = i; PortFound = SK_TRUE; } } } if (PortFound) { SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("Port %d received the last broadcast.\n", *N)) /* Look if another port's time stamp is similar. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (i == *N) { continue; } if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx && (pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp - SK_RLMT_BC_DELTA || pAC->Rlmt.Port[i].BcTimeStamp + SK_RLMT_BC_DELTA > BcTimeStamp)) { PortFound = SK_FALSE; SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("Port %d received a broadcast %s.\n", i, "at a similar time")) break; } } }#ifdef DEBUG if (PortFound) { SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_CHECK_SWITCH found Port %d receiving %s.\n", *N, "the substantially latest broadcast")) }#endif /* DEBUG */ return (PortFound);} /* SkRlmtSelectBcRx *//****************************************************************************** * * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP) * * Description: * This routine selects a good port (it is PortUp && !SuspectRx). * * Context: * runtime, pageable? * * Returns: * SK_BOOL */RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */SK_U32 A, /* active port */SK_U32 P, /* preferred port */SK_U32 *N) /* new active port */{ SK_U32 i; SK_BOOL PortFound; PortFound = SK_FALSE; /* Select first port that is PortUp && !SuspectRx. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (!pAC->Rlmt.Port[i].PortDown && !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) { *N = i; if (!pAC->Rlmt.Port[A].PortDown && !(pAC->Rlmt.Port[A].CheckingState & SK_RLMT_PCS_RX)) { *N = A; } if (!pAC->Rlmt.Port[P].PortDown && !(pAC->Rlmt.Port[P].CheckingState & SK_RLMT_PCS_RX)) { *N = P; } PortFound = SK_TRUE; SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_CHECK_SWITCH found Port %d up and not check RX.\n", *N)) break; } } return (PortFound);} /* SkRlmtSelectNotSuspect *//****************************************************************************** * * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP) * * Description: * This routine selects a port that is up. * * Context: * runtime, pageable? * * Returns: * SK_BOOL */RLMT_STATIC SK_BOOL SkRlmtSelectUp(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */SK_U32 A, /* active port */SK_U32 P, /* preferred port */SK_U32 *N, /* new active port */SK_BOOL AutoNegDone) /* successfully auto-negotiated? */{ SK_U32 i; SK_BOOL PortFound; PortFound = SK_FALSE; /* Select first port that is PortUp. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP && pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { *N = i; if (pAC->Rlmt.Port[A].PortState == SK_RLMT_PS_UP && pAC->GIni.GP[A].PAutoNegFail != AutoNegDone) { *N = A; } if (pAC->Rlmt.Port[P].PortState == SK_RLMT_PS_UP && pAC->GIni.GP[P].PAutoNegFail != AutoNegDone) { *N = P; } PortFound = SK_TRUE; SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_CHECK_SWITCH found Port %d up.\n", *N)) break; } } return (PortFound);} /* SkRlmtSelectUp *//****************************************************************************** * * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP) * * Description: * This routine selects the port that is going up for the longest time. * * Context: * runtime, pageable? * * Returns: * SK_BOOL */RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp(SK_AC *pAC, /* adapter context */SK_IOC IoC, /* I/O context */SK_U32 A, /* active port */SK_U32 P, /* preferred port */SK_U32 *N, /* new active port */SK_BOOL AutoNegDone) /* successfully auto-negotiated? */{ SK_U64 GuTimeStamp=0; SK_U32 i; SK_BOOL PortFound; 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; *N = i; PortFound = SK_TRUE; break; } } if (!PortFound) { return (SK_FALSE); } for (i = *N + 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; *N = i; } } SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_CHECK_SWITCH found Port %d going up.\n", *N)) 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 A, /* active port */SK_U32 P, /* preferred port */SK_U32 *N, /* 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) { *N = i; if (pAC->Rlmt.Port[A].PortState == SK_RLMT_PS_DOWN && pAC->GIni.GP[A].PAutoNegFail != AutoNegDone) { *N = A; } if (pAC->Rlmt.Port[P].PortState == SK_RLMT_PS_DOWN && pAC->GIni.GP[P].PAutoNegFail != AutoNegDone) { *N = P; } PortFound = SK_TRUE; SK_DBG_MSG( pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_CHECK_SWITCH found Port %d down.\n", *N)) 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_EVPARA Para; SK_U32 A; SK_U32 P; SK_U32 i; SK_BOOL PortFound; if (pAC->Rlmt.RlmtState == SK_RLMT_RS_INIT) { return; } A = pAC->Rlmt.MacActive; /* Index of active port. */ P = pAC->Rlmt.PrefPort; /* Index of preferred port. */ PortFound = SK_FALSE; if (pAC->Rlmt.LinksUp == 0) { /* * Last link went down - shut down the net. */ pAC->Rlmt.RlmtState = SK_RLMT_RS_NET_DOWN; Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP; SkEventQueue( pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para); return; } else if (pAC->Rlmt.LinksUp == 1 && pAC->Rlmt.RlmtState == SK_RLMT_RS_NET_DOWN) { /* First link came up - get the net up. */ pAC->Rlmt.RlmtState = SK_RLMT_RS_NET_UP; /* * If pAC->Rlmt.MacActive != Para.Para32[0], * the DRV switches to the port that came up. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (!pAC->Rlmt.Port[i].LinkDown) { if (!pAC->Rlmt.Port[A].LinkDown) { i = A; } if (!pAC->Rlmt.Port[P].LinkDown) { i = P; } PortFound = SK_TRUE; break; } } if (PortFound) { Para.Para32[0] = pAC->Rlmt.MacActive; Para.Para32[1] = i; SkEventQueue( pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_SWITCH, Para); pAC->Rlmt.MacActive = i; Para.Para32[0] = i; SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); if ((Para.pParaPtr = SkRlmtBuildPacket( pAC, IoC, i, SK_PACKET_ANNOUNCE, &pAC->Addr.CurrentMacAddress, &SkRlmtMcAddr) ) != NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -