📄 mlme.c
字号:
if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Driver auto scan\n"); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_BSSID_LIST_SCAN, 0, NULL); RTUSBMlmeUp(pAd); }} VOID MlmeAutoRecoverNetwork( IN PRTMP_ADAPTER pAd){ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) { NDIS_802_11_SSID OidSsid; OidSsid.SsidLength = pAd->PortCfg.SsidLen; NdisMoveMemory(OidSsid.Ssid, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen); DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Driver auto recovering network - %s\n", pAd->PortCfg.Ssid); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID, sizeof(NDIS_802_11_SSID), &OidSsid); RTUSBMlmeUp(pAd); }}//2007/11/09:KH replace the original MlmeAutoReconnectLastSSIDVOID MlmeAutoReconnectLastSSID( IN PRTMP_ADAPTER pAd){ // check CntlMachine.CurrState to avoid collision with NDIS SetOID request MLME_SCAN_REQ_STRUCT ScanReq; ULONG Now= pAd->Mlme.Now32; if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && ((pAd->PortCfg.LastScanTime + (10*HZ)) >= Now)) // BUG (10 sec) { if (pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE && (MlmeValidateSSID(pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen) == TRUE)) { NDIS_802_11_SSID OidSsid; OidSsid.SsidLength = pAd->MlmeAux.AutoReconnectSsidLen; NdisMoveMemory(OidSsid.Ssid, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen); DBGPRINT(RT_DEBUG_TRACE, "Driver auto reconnect to last OID_802_11_SSID setting - %s\n", pAd->MlmeAux.AutoReconnectSsid); /* carella modify: if no SSID, sta should not try to connect AP in scan table */ if(OidSsid.SsidLength) { MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, OID_802_11_SSID, sizeof(NDIS_802_11_SSID), &OidSsid); RTUSBMlmeUp(pAd); } } } else if ((pAd->PortCfg.LastScanTime + (10*HZ)) < Now) { // check CntlMachine.CurrState to avoid collision with NDIS SetOID request DBGPRINT(RT_DEBUG_TRACE, "MMCHK - FastRoaming, No eligable entry, try new scan!\n"); pAd->PortCfg.ScanCnt = 2; pAd->PortCfg.LastScanTime = Now; ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); RTUSBMlmeUp(pAd); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; }}/* ========================================================================== Validate SSID for connection try and rescan purpose Valid SSID will have visible chars only. The valid length is from 0 to 32. ========================================================================== */BOOLEAN MlmeValidateSSID( IN PUCHAR pSsid, IN UCHAR SsidLen){ int index; if (SsidLen > MAX_LEN_OF_SSID) return (FALSE); // Check each character value for (index = 0; index < SsidLen; index++) { if (pSsid[index] < 0x20) return (FALSE); } // All checked return (TRUE);}/* ========================================================================== 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. Output: ========================================================================== */VOID MlmeCheckForRoaming( IN PRTMP_ADAPTER pAd, IN ULONG Now32){ USHORT i; BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; BSS_ENTRY *pBss; DBGPRINT(RT_DEBUG_TRACE, "==> MlmeCheckForRoaming::pAd->ScanTab.BssNr = %d\n", pAd->ScanTab.BssNr); // 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]; DBGPRINT(RT_DEBUG_TRACE, "MlmeCheckForRoaming::pBss->LastBeaconRxTime = %d\n", pBss->LastBeaconRxTime); if ((pBss->LastBeaconRxTime + BEACON_LOST_TIME) < Now32) { DBGPRINT(RT_DEBUG_TRACE, "1: AP disappear::Now32 = %d\n", Now32); continue; // AP disappear } if (pBss->Rssi <= RSSI_THRESHOLD_FOR_ROAMING) { DBGPRINT(RT_DEBUG_TRACE, "2: RSSI too weak::Rssi[%d] - RSSI_THRESHOLD_FOR_ROAMING[%d]\n", pBss->Rssi, RSSI_THRESHOLD_FOR_ROAMING); continue; // RSSI too weak. forget it. } if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->PortCfg.Bssid)) { DBGPRINT(RT_DEBUG_TRACE, "3: skip current AP\n"); continue; // skip current AP } if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen)) { DBGPRINT(RT_DEBUG_TRACE, "4: skip different SSID\n"); continue; // skip different SSID } if (pBss->Rssi < (pAd->PortCfg.LastRssi + RSSI_DELTA)) { DBGPRINT(RT_DEBUG_TRACE, "5: only AP with stronger RSSI is eligible for roaming\n"); continue; // only AP with stronger RSSI is eligible for roaming } // 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 #%d\n", pAd->RalinkCounters.PoorCQIRoamingCount); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); RTUSBMlmeUp(pAd); } } 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. Output: ========================================================================== */VOID MlmeCheckForFastRoaming( IN PRTMP_ADAPTER pAd, IN ULONG Now){ USHORT i; BSS_TABLE *pRoamTab = &pAd->MlmeAux.RoamTab; BSS_ENTRY *pBss; MLME_SCAN_REQ_STRUCT ScanReq; DBGPRINT(RT_DEBUG_TRACE, "==> MlmeCheckForFastRoaming\n"); // // If Scan talbe is fresh within 10 sec, then we can select the AP with the best RSSI // Otherwise refresh this scan table. // //KH modified time-unit from jiffies to HZ if ((pAd->Mlme.CntlMachine.CurrState == CNTL_IDLE) && ((pAd->PortCfg.LastScanTime + 10 * HZ) >= Now)) { BssTableInit(pRoamTab); // put all roaming candidates into RoamTab, and sort in RSSI order for (i = 0; i < pAd->ScanTab.BssNr; i++) { pBss = &pAd->ScanTab.BssEntry[i]; /*2007/11/05:KH replace the line"if ((pBss->Rssi <= 45) && (pBss->Channel == pAd->PortCfg.Channel))" to enable the roaming between different channels. */ if(pBss->Rssi<=45) continue; // RSSI too weak. forget it. if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->PortCfg.Bssid)) continue; // skip current AP //2007/12/20:correct hidden bugs if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen) &&pBss->SsidLen>0&&pBss->Ssid[0]!=0 ) continue; // skip different SSID if (pBss->Rssi < (pAd->PortCfg.LastRssi + RSSI_DELTA)) continue; // skip AP without better RSSI DBGPRINT(RT_DEBUG_TRACE, "LastRssi = %d, pBss->Rssi = %d\n", pAd->PortCfg.LastRssi, pBss->Rssi); // AP passing all above rules is put into roaming candidate table NdisMoveMemory(&pRoamTab->BssEntry[pRoamTab->BssNr], pBss, sizeof(BSS_ENTRY)); //2007/12/06:KH add to fix roaming with hidden SSID if(pBss->SsidLen==0||pBss->Ssid[0]==0) { DBGPRINT(RT_DEBUG_TRACE, "Roaming With NULL SSID and BSSID[#%d]=%s", pRoamTab->BssNr,pBss->Bssid); pRoamTab->BssEntry[pRoamTab->BssNr].SsidLen=pAd->PortCfg.SsidLen; NdisMoveMemory(pRoamTab->BssEntry[pRoamTab->BssNr].Ssid, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen); DBGPRINT(RT_DEBUG_TRACE, "Roaming With NULL SSID after modified the BSSID[#%d]=%s with SSID[%d]=%s", pRoamTab->BssNr,pBss->Bssid,pRoamTab->BssEntry[pRoamTab->BssNr].SsidLen,pRoamTab->BssEntry[pRoamTab->BssNr].Ssid); } pRoamTab->BssNr += 1; } if (pRoamTab->BssNr > 0) { pAd->RalinkCounters.PoorCQIRoamingCount ++; DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Roaming attempt #%d\n", pAd->RalinkCounters.PoorCQIRoamingCount); MlmeEnqueue(pAd, MLME_CNTL_STATE_MACHINE, MT2_MLME_ROAMING_REQ, 0, NULL); RTUSBMlmeUp(pAd); } } // Maybe site survey required else { if ((pAd->PortCfg.LastScanTime + 10*HZ) < Now) { // check CntlMachine.CurrState to avoid collision with NDIS SetOID request DBGPRINT(RT_DEBUG_TRACE, "MMCHK - Roaming, No eligable entry, try a new ACTIVE scan SSID[%s]\n", pAd->MlmeAux.AutoReconnectSsid); pAd->PortCfg.ScanCnt = 2; pAd->PortCfg.LastScanTime = Now; ScanParmFill(pAd, &ScanReq, pAd->MlmeAux.AutoReconnectSsid, pAd->MlmeAux.AutoReconnectSsidLen, BSS_ANY, SCAN_ACTIVE); MlmeEnqueue(pAd, SYNC_STATE_MACHINE, MT2_MLME_SCAN_REQ, sizeof(MLME_SCAN_REQ_STRUCT), &ScanReq); RTUSBMlmeUp(pAd); pAd->Mlme.CntlMachine.CurrState = CNTL_WAIT_OID_LIST_SCAN; } } DBGPRINT(RT_DEBUG_TRACE, "<== MlmeCheckForFastRoaming\n"); }/* ========================================================================== 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: PortCfg.ChannelQuality - 0..100 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; // // 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) && (TxOkCnt < 2) && // no heavy traffic (pAd->PortCfg.LastBeaconRxTime + BEACON_LOST_TIME < Now32)) { DBGPRINT(RT_DEBUG_TRACE, "BEACON lost > %d msec with TxOkCnt=%d -> CQI=0\n", BEACON_LOST_TIME, TxOkCnt); pAd->Mlme.ChannelQuality = 0; } else { // Normalize Rssi if (pAd->PortCfg.LastRssi > 0x50) NorRssi = 100; else if (pAd->PortCfg.LastRssi < 0x20) NorRssi = 0; else NorRssi = (pAd->PortCfg.LastRssi - 0x20) * 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= %d (Tx Fail=%d/Retry=%d/Total=%d, Rx Fail=%d/Total=%d, RSSI=%d dbm)\n", pAd->Mlme.ChannelQuality, pAd->RalinkCounters.OneSecTxFailCount, pAd->RalinkCounters.OneSecTxRetryOkCount, TxCnt, pAd->RalinkCounters.OneSecRxFcsErrCnt, RxCnt, pAd->PortCfg.LastRssi - pAd->BbpRssiToDbmDelta);}/* ========================================================================== Description: This routine calculates the acumulated TxPER of eaxh TxRate. And according to the calculation result, change PortCfg.TxRate which is the stable TX Rate we expect the Radio situation could sustained. PortCfg.TxRate will change dynamically within {RATE_1/RATE_6, MaxTxRate} Output: PortCfg.TxRate -
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -