📄 mlme.c
字号:
}
else
{
//
// for long distance case, turn on RTS to protect data frame.
//
if ((dbm <= -60) && (pAd->RalinkCounters.OneSecTxNoRetryOkCount <= 15))
{
OPSTATUS_SET_FLAG(pAd, fOP_STATUS_RTS_PROTECTION_ENABLE);
}
}
}
//
// Clear Tx/Rx Traffic one second count.
//
pAd->BulkLastOneSecCount = pAd->BulkOutDataOneSecCount + pAd->BulkInDataOneSecCount;
pAd->BulkOutDataOneSecCount = 0;
pAd->BulkInDataOneSecCount = 0;
// clear all OneSecxxx counters.
pAd->RalinkCounters.OneSecBeaconSentCnt = 0;
pAd->RalinkCounters.OneSecFalseCCACnt = 0;
pAd->RalinkCounters.OneSecRxFcsErrCnt = 0;
pAd->RalinkCounters.OneSecRxOkCnt = 0;
pAd->RalinkCounters.OneSecTxFailCount = 0;
pAd->RalinkCounters.OneSecTxNoRetryOkCount = 0;
pAd->RalinkCounters.OneSecTxRetryOkCount = 0;
// TODO: for debug only. to be removed
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BE] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_BK] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VI] = 0;
pAd->RalinkCounters.OneSecOsTxCount[QID_AC_VO] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BE] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_BK] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VI] = 0;
pAd->RalinkCounters.OneSecDmaDoneCount[QID_AC_VO] = 0;
pAd->RalinkCounters.OneSecTxDoneCount = 0;
pAd->RalinkCounters.OneSecTxAggregationCount = 0;
pAd->RalinkCounters.OneSecRxAggregationCount = 0;
pAd->Mlme.PeriodicRound ++;
}
VOID LinkDownExec(
IN unsigned long data)
{
//RTMP_ADAPTER *pAd = (RTMP_ADAPTER *)data;
}
VOID MlmeAutoScan(
IN PRTMP_ADAPTER pAd)
{
// check CntlMachine.CurrState to avoid collision with NDIS SetOID request
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);
}
}
VOID MlmeAutoReconnectLastSSID(
IN PRTMP_ADAPTER pAd)
{
// check CntlMachine.CurrState to avoid collision with NDIS SetOID request
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);
MlmeEnqueue(pAd,
MLME_CNTL_STATE_MACHINE,
OID_802_11_SSID,
sizeof(NDIS_802_11_SSID),
&OidSsid);
RTUSBMlmeUp(pAd);
}
}
/*
==========================================================================
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;
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 <= 45) && (pBss->Channel == pAd->PortCfg.Channel))
continue; // RSSI too weak. forget it.
if (MAC_ADDR_EQUAL(pBss->Bssid, pAd->PortCfg.Bssid))
continue; // skip current AP
if (!SSID_EQUAL(pBss->Ssid, pBss->SsidLen, pAd->PortCfg.Ssid, pAd->PortCfg.SsidLen))
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));
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);
}
}
// Maybe site survey required
else
{
if ((pAd->PortCfg.LastScanTime + 10 * 1000) < Now)
{
MLME_SCAN_REQ_STRUCT ScanReq;
// 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);
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",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -