📄 mlme.c
字号:
} } DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForRoaming(# of candidate= %d)\n",pRoamTab->BssNr)); }/* ========================================================================== Description: This routine checks if there're other APs out there capable for roaming. Caller should call this routine only when link up in INFRA mode and channel quality is below CQI_GOOD_THRESHOLD. IRQL = DISPATCH_LEVEL Output: ========================================================================== */VOID MlmeCheckForFastRoaming( IN PRTMP_ADAPTER pAd, IN ULONG Now){ USHORT i; BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; BSS_ENTRY *pBss; DBGPRINT(RT_DEBUG_TRACE, ("==> MlmeCheckForFastRoaming\n")); // put all roaming candidates into RoamTab, and sort in RSSI order BssTableInit(pRoamTab); for (i = 0; i < pAd->ScanTab.BssNr; i++) { pBss = &pAd->ScanTab.BssEntry[i]; if ((pBss->Rssi <= -50) && (pBss->Channel == pAd->CommonCfg.Channel)) continue; // RSSI too weak. forget it. if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->CommonCfg.Bssid)) continue; // skip current AP if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->CommonCfg.Ssid, pAd->CommonCfg.SsidLen)) continue; // skip different SSID if (pBss->Rssi < (RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2) + RSSI_DELTA)) continue; // skip AP without better RSSI DBGPRINT(RT_DEBUG_TRACE, ("LastRssi0 = %d, pBss->Rssi = %d\n", RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2), pBss->Rssi)); // AP passing all above rules is put into roaming candidate table NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); pRoamTab->BssNr += 1; } if (pRoamTab->BssNr > 0) { // check CntlMachine.CurrState to avoid collision with NDIS SetOID request if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { pAd->RalinkCounters.PoorCQIRoamingCount ++; DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming attempt #%ld\n", pAd->RalinkCounters.PoorCQIRoamingCount)); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); MlmeHandler(pAd); } } // Maybe site survey required else { if ((pAd->StaCfg.LastScanTime + 10 * 1000) < Now) { // check CntlMachine.CurrState to avoid collision with NDIS SetOID request DBGPRINT(RT_DEBUG_TRACE, ("MMCHK - Roaming, No eligable entry, try new scan!\n")); pAd->StaCfg.ScanCnt = 2; pAd->StaCfg.LastScanTime = Now; MlmeAutoScan(pAd); } } DBGPRINT(RT_DEBUG_TRACE, ("<== MlmeCheckForFastRoaming (BssNr=%d)\n", pRoamTab->BssNr));}/* ========================================================================== Description: This routine calculates TxPER, RxPER of the past N-sec period. And according to the calculation result, ChannelQuality is calculated here to decide if current AP is still doing the job. If ChannelQuality is not good, a ROAMing attempt may be tried later. Output: StaCfg.ChannelQuality - 0..100 IRQL = DISPATCH_LEVEL NOTE: This routine decide channle quality based on RX CRC error ratio. Caller should make sure a function call to NICUpdateRawCounters(pAd) is performed right before this routine, so that this routine can decide channel quality based on the most up-to-date information ========================================================================== */VOID MlmeCalculateChannelQuality( IN PRTMP_ADAPTER pAd, IN ULONG Now32){ ULONG TxOkCnt, TxCnt, TxPER, TxPRR; ULONG RxCnt, RxPER; UCHAR NorRssi; CHAR MaxRssi; MaxRssi = RTMPMaxRssi(pAd, pAd->StaCfg.RssiSample.LastRssi0, pAd->StaCfg.RssiSample.LastRssi1, pAd->StaCfg.RssiSample.LastRssi2); // // calculate TX packet error ratio and TX retry ratio - if too few TX samples, skip TX related statistics // TxOkCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount; TxCnt = TxOkCnt + pAd->RalinkCounters.OneSecTxFailCount; if (TxCnt < 5) { TxPER = 0; TxPRR = 0; } else { TxPER = (pAd->RalinkCounters.OneSecTxFailCount * 100) / TxCnt; TxPRR = ((TxCnt - pAd->RalinkCounters.OneSecTxNoRetryOkCount) * 100) / TxCnt; } // // calculate RX PER - don't take RxPER into consideration if too few sample // RxCnt = pAd->RalinkCounters.OneSecRxOkCnt + pAd->RalinkCounters.OneSecRxFcsErrCnt; if (RxCnt < 5) RxPER = 0; else RxPER = (pAd->RalinkCounters.OneSecRxFcsErrCnt * 100) / RxCnt; // // decide ChannelQuality based on: 1)last BEACON received time, 2)last RSSI, 3)TxPER, and 4)RxPER // if (INFRA_ON(pAd) && (pAd->RalinkCounters.OneSecTxNoRetryOkCount < 2) && // no heavy traffic (pAd->StaCfg.LastBeaconRxTime + BEACON_LOST_TIME < Now32)) { DBGPRINT(RT_DEBUG_TRACE, ("BEACON lost > %d msec with TxOkCnt=%ld -> CQI=0\n", BEACON_LOST_TIME, TxOkCnt)); pAd->Mlme.ChannelQuality = 0; } else { // Normalize Rssi if (MaxRssi > -40) NorRssi = 100; else if (MaxRssi < -90) NorRssi = 0; else NorRssi = (MaxRssi + 90) * 2; // ChannelQuality = W1*RSSI + W2*TxPRR + W3*RxPER (RSSI 0..100), (TxPER 100..0), (RxPER 100..0) pAd->Mlme.ChannelQuality = (RSSI_WEIGHTING * NorRssi + TX_WEIGHTING * (100 - TxPRR) + RX_WEIGHTING* (100 - RxPER)) / 100; if (pAd->Mlme.ChannelQuality >= 100) pAd->Mlme.ChannelQuality = 100; } DBGPRINT(RT_DEBUG_INFO, ("MMCHK - CQI= %ld (Tx Fail=%u/Retry=%u/Total=%lu, Rx Fail=%u/Total=%lu, RSSI=%d dbm)\n", pAd->Mlme.ChannelQuality, pAd->RalinkCounters.OneSecTxFailCount, pAd->RalinkCounters.OneSecTxRetryOkCount, TxCnt, pAd->RalinkCounters.OneSecRxFcsErrCnt, RxCnt, MaxRssi));}VOID MlmeSetTxRate( IN PRTMP_ADAPTER pAd, IN PMAC_TABLE_ENTRY pEntry, IN PRTMP_TX_RATE_SWITCH pTxRate){ if (pTxRate->STBC && (pAd->CommonCfg.MaxHTPhyMode.field.STBC) && (pAd->Antenna.field.TxPath == 2)) pAd->CommonCfg.HTPhyMode.field.STBC = STBC_USE; else pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; if (pTxRate->ShortGI && (pAd->CommonCfg.MaxHTPhyMode.field.ShortGI)) pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_400; else pAd->CommonCfg.HTPhyMode.field.ShortGI = GI_800; if (pTxRate->CurrMCS < MCS_AUTO) pAd->CommonCfg.HTPhyMode.field.MCS = pTxRate->CurrMCS; if (pAd->CommonCfg.HTPhyMode.field.MCS > 7) pAd->CommonCfg.HTPhyMode.field.STBC = STBC_NONE; if (pTxRate->Mode <= MODE_HTGREENFIELD) pAd->CommonCfg.HTPhyMode.field.MODE = pTxRate->Mode; pEntry->HTPhyMode.field.STBC = pAd->CommonCfg.HTPhyMode.field.STBC; pEntry->HTPhyMode.field.ShortGI = pAd->CommonCfg.HTPhyMode.field.ShortGI; pEntry->HTPhyMode.field.MCS = pAd->CommonCfg.HTPhyMode.field.MCS; pEntry->HTPhyMode.field.MODE = pAd->CommonCfg.HTPhyMode.field.MODE; pAd->LastTxRate = (USHORT)(pEntry->HTPhyMode.word); DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: MlmeSetTxRate - CurrTxRateIdx=%d, MCS=%d, STBC=%d, ShortGI=%d, Mode=%d, BW=%d \n", pAd->CommonCfg.TxRateIndex, pAd->CommonCfg.HTPhyMode.field.MCS, pAd->CommonCfg.HTPhyMode.field.STBC, pAd->CommonCfg.HTPhyMode.field.ShortGI, pAd->CommonCfg.HTPhyMode.field.MODE, pAd->CommonCfg.HTPhyMode.field.BW));}VOID MlmeSelectTxRateTable( IN PRTMP_ADAPTER pAd, IN PUCHAR *ppTable, IN PUCHAR pTableSize, IN PUCHAR pInitTxRateIdx){ // decide the rate table for tuning if (pAd->CommonCfg.TxRateTableSize > 0) { *ppTable = RateSwitchTable; *pTableSize = RateSwitchTable[0]; *pInitTxRateIdx = RateSwitchTable[1]; DBGPRINT_RAW(RT_DEBUG_TRACE,("DRS: rate table is from rate.bin \n")); } else if (ADHOC_ON(pAd)) { if (pAd->CommonCfg.PhyMode == PHY_11B) { *ppTable = RateSwitchTable11B; *pTableSize = RateSwitchTable11B[0]; *pInitTxRateIdx = RateSwitchTable11B[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: B only Adhoc \n")); } else if (pAd->LatchRfRegs.Channel <= 14) { *ppTable = RateSwitchTable11BG; *pTableSize = RateSwitchTable11BG[0]; *pInitTxRateIdx = RateSwitchTable11BG[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: B/G mixed Adhoc \n")); } else { *ppTable = RateSwitchTable11G; *pTableSize = RateSwitchTable11G[0]; *pInitTxRateIdx = RateSwitchTable11G[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: A/G Adhoc \n")); } } else { if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedHtPhy.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedHtPhy.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) {// 11BGN 1S AP *ppTable = RateSwitchTable11BGN1S; *pTableSize = RateSwitchTable11BGN1S[0]; *pInitTxRateIdx = RateSwitchTable11BGN1S[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: 11BGN 1S AP \n")); } else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 12) && (pAd->StaActive.SupportedHtPhy.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedHtPhy.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) {// 11BGN 2S AP *ppTable = RateSwitchTable11BGN2S; *pTableSize = RateSwitchTable11BGN2S[0]; *pInitTxRateIdx = RateSwitchTable11BGN2S[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: 11BGN 2S AP \n")); } else if ((pAd->StaActive.SupportedHtPhy.MCSSet[0] == 0xff) && ((pAd->StaActive.SupportedHtPhy.MCSSet[1] == 0x00) || (pAd->Antenna.field.TxPath == 1))) {// 11N 1S AP *ppTable = RateSwitchTable11N1S; *pTableSize = RateSwitchTable11N1S[0]; *pInitTxRateIdx = RateSwitchTable11N1S[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: 11N 1S AP \n")); } else if ((pAd->StaActive.SupportedHtPhy.MCSSet[0] == 0xff) && (pAd->StaActive.SupportedHtPhy.MCSSet[1] == 0xff) && (pAd->Antenna.field.TxPath == 2)) {// 11N 2S AP *ppTable = RateSwitchTable11N2S; *pTableSize = RateSwitchTable11N2S[0]; *pInitTxRateIdx = RateSwitchTable11N2S[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: 11N 2S AP \n")); } else if ((pAd->StaActive.SupRateLen == 4) && (pAd->StaActive.ExtRateLen == 0) && (pAd->StaActive.SupportedHtPhy.MCSSet[0] == 0) && (pAd->StaActive.SupportedHtPhy.MCSSet[1] == 0)) {// B only AP *ppTable = RateSwitchTable11B; *pTableSize = RateSwitchTable11B[0]; *pInitTxRateIdx = RateSwitchTable11B[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: B only AP \n")); } else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen > 8) && (pAd->StaActive.SupportedHtPhy.MCSSet[0] == 0) && (pAd->StaActive.SupportedHtPhy.MCSSet[1] == 0)) {// B/G mixed AP *ppTable = RateSwitchTable11BG; *pTableSize = RateSwitchTable11BG[0]; *pInitTxRateIdx = RateSwitchTable11BG[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: B/G mixed AP \n")); } else if ((pAd->StaActive.SupRateLen + pAd->StaActive.ExtRateLen == 8) && (pAd->StaActive.SupportedHtPhy.MCSSet[0] == 0) && (pAd->StaActive.SupportedHtPhy.MCSSet[1] == 0)) {// G only AP *ppTable = RateSwitchTable11G; *pTableSize = RateSwitchTable11G[0]; *pInitTxRateIdx = RateSwitchTable11G[1]; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: A/G AP \n")); } else { *ppTable = RateSwitchTable11N2S; *pTableSize = RateSwitchTable11N2S[0]; *pInitTxRateIdx = RateSwitchTable11N2S[1]; DBGPRINT_RAW(RT_DEBUG_ERROR,("DRS: unkown mode \n")); } }}/* ========================================================================== Description: This routine calculates the acumulated TxPER of eaxh TxRate. And according to the calculation result, change CommonCfg.TxRate which is the stable TX Rate we expect the Radio situation could sustained. CommonCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} Output: CommonCfg.TxRate - IRQL = DISPATCH_LEVEL NOTE: call this routine every second ========================================================================== */VOID MlmeDynamicTxRateSwitching( IN PRTMP_ADAPTER pAd){ UCHAR UpRateIdx = 0, DownRateIdx = 0, CurrRateIdx; ULONG TxTotalCnt; ULONG TxErrorRatio = 0; BOOLEAN bTxRateChanged = TRUE, bUpgradeQuality = FALSE; PRTMP_TX_RATE_SWITCH pCurrTxRate, pNextTxRate = NULL; PUCHAR pTable; UCHAR TableSize = 0; UCHAR InitTxRateIdx = 0, TrainUp, TrainDown; CHAR Rssi; CurrRateIdx = pAd->CommonCfg.TxRateIndex;// Rssi = RTMPMaxRssi(pAd, (CHAR)pAd->StaCfg.AvgRssi0, (CHAR)pAd->StaCfg.AvgRssi1, (CHAR)pAd->StaCfg.AvgRssi2); if (pAd->Antenna.field.TxPath > 1) Rssi = (pAd->StaCfg.RssiSample.AvgRssi0 + pAd->StaCfg.RssiSample.AvgRssi1) >> 1; else Rssi = pAd->StaCfg.RssiSample.AvgRssi0; MlmeSelectTxRateTable(pAd, &pTable, &TableSize, &InitTxRateIdx); // decide the next upgrade rate and downgrade rate, if any if ((CurrRateIdx > 0) && (CurrRateIdx < (TableSize - 1))) { UpRateIdx = CurrRateIdx + 1; DownRateIdx = CurrRateIdx -1; } else if (CurrRateIdx == 0) { UpRateIdx = CurrRateIdx + 1; DownRateIdx = CurrRateIdx; } else if (CurrRateIdx == (TableSize - 1)) { UpRateIdx = CurrRateIdx; DownRateIdx = CurrRateIdx - 1; } pCurrTxRate = (PRTMP_TX_RATE_SWITCH) &pTable[(CurrRateIdx+1)*5]; if ((Rssi > -65) && (pCurrTxRate->Mode >= MODE_HTMIX)) { TrainUp = (pCurrTxRate->TrainUp + (pCurrTxRate->TrainUp >> 1)); TrainDown = (pCurrTxRate->TrainDown + (pCurrTxRate->TrainDown >> 1)); } else { TrainUp = pCurrTxRate->TrainUp; TrainDown = pCurrTxRate->TrainDown; } // if no traffic in the past 1-sec period, don't change TX rate, // but clear all bad history. because the bad history may affect the next // Chariot throughput test TxTotalCnt = pAd->RalinkCounters.OneSecTxNoRetryOkCount + pAd->RalinkCounters.OneSecTxRetryOkCount + pAd->RalinkCounters.OneSecTxFailCount; if (TxTotalCnt) TxErrorRatio = ((pAd->RalinkCounters.OneSecTxRetryOkCount + pAd->RalinkCounters.OneSecTxFailCount) * 100) / TxTotalCnt; DBGPRINT_RAW(RT_DEBUG_INFO,("DRS: OneSecTxRetryOkCount=%d, OneSecTxFailCount=%d, OneSecTxNoRetryOkCount=%d \n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -