📄 skrlmt.c
字号:
break; case SK_PACKET_CHECK_TX: SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Check your tx line.\n")) /* A port checking us requests us to check our tx line. */ pRPort->CheckingState |= SK_RLMT_PCS_TX; /* Start PortDownTx timer. */ Para.Para32[0] = PortNumber; Para.Para32[1] = (SK_U32)-1; SkTimerStart(pAC, IoC, &pRPort->DownTxTimer, SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTDOWN_TX_TIM, Para); SkDrvFreeRlmtMbuf(pAC, IoC, pMb); 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); } break; case SK_PACKET_ADDR_CHANGED: SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Address Change.\n")) /* Build the check chain. */ SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); SkDrvFreeRlmtMbuf(pAC, IoC, pMb); break; default: SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Unknown RLMT packet.\n")) /* RA;:;: ??? */ SkDrvFreeRlmtMbuf(pAC, IoC, pMb); } } else if (pSPacket->DSap == SK_RLMT_SPT_DSAP && pSPacket->Ctrl == SK_RLMT_SPT_CTRL && (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: BPDU Packet.\n")) /* Spanning Tree packet. */ pRPort->RxSpHelloCts++; if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt. Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) { /* * Check segmentation if a new root bridge is set and * the segmentation check is not currently running. */ if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG) == 0) { pAC->Rlmt.Port[PortNumber].Net->CheckingState |= SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; } /* Store tree view of this port. */ for (i = 0; i < 8; i++) { pRPort->Root.Id[i] = pSPacket->RootId[i]; } pRPort->RootIdSet = SK_TRUE; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", PortNumber, pRPort->Root.Id[0], pRPort->Root.Id[1], pRPort->Root.Id[2], pRPort->Root.Id[3], pRPort->Root.Id[4], pRPort->Root.Id[5], pRPort->Root.Id[6], pRPort->Root.Id[7])) } SkDrvFreeRlmtMbuf(pAC, IoC, pMb); if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_REPORT_SEG) != 0) { SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber); } } else { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, ("SkRlmtPacketReceive: Unknown Packet Type.\n")) /* Unknown packet. */ SkDrvFreeRlmtMbuf(pAC, IoC, pMb); } return;} /* SkRlmtPacketReceive *//****************************************************************************** * * SkRlmtCheckPort - check if a port works * * Description: * This routine checks if a port whose link is up received something * and if it seems to transmit successfully. * * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg * * if (Rx - RxBpdu == 0) { # No rx. * if (state == PsUp) { * PortCheckingState |= ChkRx * } * if (ModeCheckSeg && (Timeout == * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) { * RlmtCheckingState |= ChkSeg) * PortCheckingState |= ChkSeg * } * NewTimeout = TO_SHORTEN(Timeout) * if (NewTimeout < RLMT_MIN_TIMEOUT) { * NewTimeout = RLMT_MIN_TIMEOUT * PortState = PsDown * ... * } * } * else { # something was received * # Set counter to 0 at LinkDown? * # No - rx may be reported after LinkDown ??? * PortCheckingState &= ~ChkRx * NewTimeout = RLMT_DEFAULT_TIMEOUT * if (RxAck == 0) { * possible reasons: * is my tx line bad? -- * send RLMT multicast and report * back internally? (only possible * between ports on same adapter) * } * if (RxChk == 0) { * possible reasons: * - tx line of port set to check me * maybe bad * - no other port/adapter available or set * to check me * - adapter checking me has a longer * timeout * ??? anything that can be done here? * } * } * * Context: * runtime, pageable? * * Returns: * New timeout value. */RLMT_STATIC SK_U32 SkRlmtCheckPort(SK_AC *pAC, /* Adapter Context */SK_IOC IoC, /* I/O Context */SK_U32 PortNumber) /* Port to check */{ unsigned i; SK_U32 NewTimeout; SK_RLMT_PORT *pRPort; SK_EVPARA Para; pRPort = &pAC->Rlmt.Port[PortNumber]; 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", PortNumber, 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.Port[PortNumber].Net->LinksUp > 1) && (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) { pAC->Rlmt.Port[PortNumber].Net->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.Port[PortNumber].Net->TimeoutValue); if (NewTimeout < SK_RLMT_MIN_TO_VAL) { NewTimeout = SK_RLMT_MIN_TO_VAL; } if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) { Para.Para32[0] = PortNumber; 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? */ Para.Para32[1] = (SK_U32)-1; 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, PortNumber, SK_PACKET_CHECK_TX, &pAC->Addr.Port[PortNumber].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", PortNumber, pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, pRPort->PacketsPerTimeSlot)) SkRlmtPortReceives(pAC, IoC, PortNumber); if (pAC->Rlmt.CheckSwitch) { SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); } 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 Active, /* Active port */SK_U32 PrefPort, /* Preferred port */SK_U32 *pSelect) /* 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 (Down: %d, NoRx: %d): %08x %08x.\n", i, pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, *((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; *pSelect = i; PortFound = SK_TRUE; } } } if (PortFound) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("Port %d received the last broadcast.\n", *pSelect)) /* Look if another port's time stamp is similar. */ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { if (i == *pSelect) { 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 at a similar time.\n", i)) break; } } }#ifdef DEBUG if (PortFound) { SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially " "latest broadcast (%u).\n", *pSelect, BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)) }#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 Active, /* Active port */SK_U32 PrefPort, /* Preferred port */SK_U32 *pSelect) /* 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)) { *pSelect = i; if (!pAC->Rlmt.Port[Active].PortDown && !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) { *pSelect = Active; } if (!pAC->Rlmt.Port[PrefPort].PortDown && !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) { *pSelect = PrefPort; } PortFound = SK_TRUE; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n", *pSelect)) 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 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 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) { *pSelect = i; if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP && pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { *pSelect = Active; } if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP && pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { *pSelect = PrefPort; } PortFound = SK_TRUE; SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)) 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. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -