mlme.c
来自「Ralink RT61 SoftAP Driver source code. 」· C语言 代码 · 共 1,669 行 · 第 1/5 页
C
1,669 行
if (pEntry->OneSecTxFailCount)
{
if ((pEntry->OneSecTxFailCount <= 1) &&
(pEntry->OneSecTxOkCount + pEntry->OneSecTxRetryOkCount))
{
pEntry->TxQuality[CurrRate] += 2; // degrade quality
if (pEntry->TxQuality[CurrRate] > DRS_TX_QUALITY_WORST_BOUND)
pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
else // more than 2 failure, or no TX ok cases
{
pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
}
// upgrade TX quality if -
// 1. no TX failure but do have TX ok case, and
// 2. there's more one-time-ok cases than retry-ok cases in the past second
else if (pEntry->OneSecTxOkCount > pEntry->OneSecTxRetryOkCount)
{
fUpgradeQuality = TRUE;
if (pEntry->TxQuality[CurrRate])
pEntry->TxQuality[CurrRate] --; // quality very good in CurrRate
if (pEntry->TxRateUpPenalty)
pEntry->TxRateUpPenalty --;
else if (pEntry->TxQuality[UpRate])
pEntry->TxQuality[UpRate] --; // may improve next UP rate's quality
}
}
pEntry->PER[CurrRate] = (UCHAR)TxErrorRatio;
if (pEntry->fNoisyEnvironment)
{
DBGPRINT(RT_DEBUG_TRACE,"DRS(Noisy)-[AID# %d] Qty[%d]=%d PER=%d%% %dsec,Qty[%d]=%d Pty=%d,TX/RX Aggr=%d,%d\n",
pEntry->Aid, RateIdToMbps[CurrRate], pEntry->TxQuality[CurrRate],
TxErrorRatio, pEntry->CurrTxRateStableTime,
RateIdToMbps[UpRate], pEntry->TxQuality[UpRate],
pEntry->TxRateUpPenalty,
pAd->RalinkCounters.OneSecTxAggregationCount,
pAd->RalinkCounters.OneSecRxAggregationCount);
}
else
{
if ((pAd->Mlme.PeriodicRound % 5) == 1)
{
DBGPRINT(RT_DEBUG_TRACE,"DRS:[AID#%d] Qty[%d]=%d PER=%d%% %dsec,Qty[%d]=%d Pty=%d,TX/RX Aggr=%d,%d\n",
pEntry->Aid, RateIdToMbps[CurrRate], pEntry->TxQuality[CurrRate],
TxErrorRatio, pEntry->CurrTxRateStableTime,
RateIdToMbps[UpRate], pEntry->TxQuality[UpRate],
pEntry->TxRateUpPenalty,
pAd->RalinkCounters.OneSecTxAggregationCount,
pAd->RalinkCounters.OneSecRxAggregationCount);
}
}
//
// PART 2. Perform TX rate switching
// perform rate switching
//
do
{
// special case 1: enter NOISY environment
if ((UpRate != CurrRate) &&
(pEntry->LastSecTxRateChangeAction == 2) &&
((pEntry->PER[CurrRate] > 20) || pEntry->fNoisyEnvironment) &&
(pEntry->PER[CurrRate] < 75) &&
((pEntry->PER[CurrRate]+5) > pEntry->PER[UpRate]))
{
// we believe this is a noisy environment. better stay at UpRate
pEntry->fNoisyEnvironment = TRUE;
// 2004-3-14 when claiming noisy environment, we're not only switch back
// to UpRate, but can be more aggressive to use one more rate up
UpRate++;
if (UpRate>RATE_54) UpRate=RATE_54;
if ((UpRate==RATE_6) || (UpRate==RATE_9)) UpRate=RATE_12;
pEntry->LastTxRate = pEntry->CurrTxRate;//record last tx rate
pEntry->CurrTxRate = UpRate;
break;
}
// special case 2: leave NOISY environment
if ((pEntry->fNoisyEnvironment == TRUE) &&
(TxTotalCnt > 15) &&
(pEntry->PER[CurrRate] <= 12))
{
UCHAR JumpUpRate;
pEntry->fNoisyEnvironment = FALSE;
for (JumpUpRate = RATE_54; JumpUpRate > RATE_1; JumpUpRate--)
{
if ((pAd->RfIcType == RFIC_5325) || (pAd->RfIcType == RFIC_2529))
{
if (pAd->PortCfg.AvgRssi > pAd->PortCfg.AvgRssi2)
{
if (pAd->PortCfg.AvgRssi > (RssiSafeLevelForTxRate[JumpUpRate] + pAd->BbpRssiToDbmDelta))
break;
}
else
{
if (pAd->PortCfg.AvgRssi2 > (RssiSafeLevelForTxRate[JumpUpRate] + pAd->BbpRssiToDbmDelta))
break;
}
}
else
{
if (pAd->PortCfg.AvgRssi > (RssiSafeLevelForTxRate[JumpUpRate] + pAd->BbpRssiToDbmDelta))
break;
}
}
if (JumpUpRate > pEntry->MaxSupportedRate)
JumpUpRate = pEntry->MaxSupportedRate;
if (JumpUpRate > CurrRate)
{
pEntry->LastTxRate = pEntry->CurrTxRate;//record last tx rate
pEntry->CurrTxRate = JumpUpRate;
break;
}
}
// we're going to ugrade CurrRate to UpRate at next few seconds,
// but before that, we'd better try a NULL frame @ UpRate and
// see if UpRate is stable or not. If this NULL frame fails, it will
// downgrade TxQuality[CurrRate], so that STA won't switch to
// to UpRate in the next second
if ((fUpgradeQuality == TRUE) &&
(UpRate != CurrRate) &&
(pEntry->TxQuality[CurrRate] <= 1) &&
(pEntry->TxQuality[UpRate] <= 1))
{
DBGPRINT(RT_DEBUG_TRACE,"2 test frames at UpRate = %d Mbps\n",RateIdToMbps[UpRate]);
// tag PID for later on per-client/WDS TX statistics caculation
PID = PTYPE_NULL_AT_HIGH_RATE + i;
ApEnqueueNullFrame(pAd, pEntry->Addr, UpRate, PID, pEntry->ApIdx, FALSE, FALSE, 0);
ApEnqueueNullFrame(pAd, pEntry->Addr, UpRate, PID, pEntry->ApIdx, FALSE, FALSE, 0);
}
// perform DRS - consider TxRate Down frist, then rate up
if ((pEntry->TxQuality[CurrRate] >= DRS_TX_QUALITY_WORST_BOUND) && (CurrRate != DownRate))
{
pEntry->LastTxRate = pEntry->CurrTxRate;//record last tx rate
pEntry->CurrTxRate = DownRate;
}
else if ((pEntry->TxQuality[CurrRate] <=0) && (pEntry->TxQuality[UpRate] <=0) && (CurrRate != UpRate))
{
pEntry->LastTxRate = pEntry->CurrTxRate;//record last tx rate
pEntry->CurrTxRate = UpRate;
}
}while (FALSE);
// PART 3. Post-processing if TX rate switching did happen
// if rate-up happen, clear all bad history of all TX rates
// if rate-down happen, only clear DownRate's bad history
if (pEntry->CurrTxRate > CurrRate)
{
DBGPRINT(RT_DEBUG_TRACE,"DRS: [AID#%d] ++TX rate = %d Mbps\n", pEntry->Aid, RateIdToMbps[UpRate]);
pEntry->CurrTxRateStableTime = 0;
pEntry->TxRateUpPenalty = 0;
pEntry->LastSecTxRateChangeAction = 0;
NdisZeroMemory(pEntry->TxQuality, MAX_LEN_OF_SUPPORTED_RATES);
NdisZeroMemory(pEntry->PER, MAX_LEN_OF_SUPPORTED_RATES);
if (!pAd->QuickResponeForRateUpTimerRunning)
{
if (pEntry->CurrTxRate <= RATE_12)
RTMPAddTimer(&pAd->QuickResponeForRateUpTimer, (200 * HZ)/1000);
else
RTMPAddTimer(&pAd->QuickResponeForRateUpTimer, (100 * HZ)/1000);
pAd->QuickResponeForRateUpTimerRunning = TRUE;
}
}
else if (pEntry->CurrTxRate < CurrRate)
{
DBGPRINT(RT_DEBUG_TRACE,"DRS: [AID#%d] --TX rate = %d Mbps\n", pEntry->Aid, RateIdToMbps[DownRate]);
// shorter stable time require more penalty in next rate UP criteria
// if (pEntry->CurrTxRateStableTime < 4) // less then 4 sec
// pEntry->TxRateUpPenalty = DRS_PENALTY; // add 8 sec penalty
// else if (pEntry->CurrTxRateStableTime < 8) // less then 8 sec
// pEntry->TxRateUpPenalty = 2; // add 2 sec penalty
// else
pEntry->TxRateUpPenalty = 0; // no penalty
pEntry->CurrTxRateStableTime = 0;
pEntry->LastSecTxRateChangeAction = 2; // rate down
pEntry->TxQuality[pEntry->CurrTxRate] = 0;
pEntry->PER[pEntry->CurrTxRate] = 0;
}
else
pEntry->LastSecTxRateChangeAction = 0; // rate no change
// reset all OneSecxxx counters
pEntry->OneSecTxFailCount = 0;
pEntry->OneSecTxOkCount = 0;
pEntry->OneSecTxRetryOkCount = 0;
}
#ifdef WDS_SUPPORT
// WDS tx rate tuning
if (pAd->WdsTab.Mode != WDS_DISABLE_MODE)
{
for (i=0; i<MAX_WDS_ENTRY; i++)
{
USHORT TxTotalCnt, TxErrorRatio;
BOOLEAN fUpgradeQuality = FALSE;
RT_802_11_WDS_ENTRY *pEntry = &pAd->WdsTab.WdsEntry[i];
if (pEntry->Valid == FALSE)
continue;
pEntry->CurrTxRateStableTime ++;
TxTotalCnt = pEntry->OneSecTxOkCount + pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount;
AllTxTotalCnt += TxTotalCnt;
// Lazy WDS age out time is 10 sec
if ((pAd->WdsTab.Mode >= WDS_LAZY_MODE) && (pEntry->WdsRcvBeaconTime + (10 * HZ) < jiffies) && (!pEntry->RestrictEntry))
{
DBGPRINT(RT_DEBUG_TRACE, "Delete WDS entry(%02x:%02x:%02x:%02x:%02x:%02x), due to age out\n",
pEntry->WdsAddr[0],pEntry->WdsAddr[1],pEntry->WdsAddr[2],pEntry->WdsAddr[3],pEntry->WdsAddr[4],pEntry->WdsAddr[5]);
pEntry->Valid = FALSE;
continue;
}
// skip those STA that has no traffic in the past period
if (TxTotalCnt == 0)
{
pEntry->TxRateUpPenalty = 0;
continue;
}
// decide the next upgrade rate and downgrade rate, if any
CurrRate = pEntry->CurrTxRate;
if (pAd->PortCfg.Channel > 14) // must be in 802.11A band
{
if (Phy11ANextRateUpward[CurrRate] <= pEntry->MaxSupportedRate)
UpRate = Phy11ANextRateUpward[CurrRate];
else
UpRate = CurrRate;
DownRate = Phy11ANextRateDownward[CurrRate];
}
else
{
if (pEntry->MaxSupportedRate < RATE_FIRST_OFDM_RATE)
{
if (Phy11BNextRateUpward[CurrRate] <= pEntry->MaxSupportedRate)
UpRate = Phy11BNextRateUpward[CurrRate];
else
UpRate = CurrRate;
DownRate = Phy11BNextRateDownward[CurrRate];
}
else
{
if (Phy11BGNextRateUpward[CurrRate] <= pEntry->MaxSupportedRate)
UpRate = Phy11BGNextRateUpward[CurrRate];
else
UpRate = CurrRate;
DownRate = Phy11BGNextRateDownward[CurrRate];
}
}
// calculate Tx with retry ratio when enough samples are available
if (TxTotalCnt > 15)
{
TxErrorRatio = ((pEntry->OneSecTxRetryOkCount + pEntry->OneSecTxFailCount) *100) / TxTotalCnt;
// downgrade TX quality if retry+error ratio reached
if (TxErrorRatio >= RateDownPER[CurrRate])
{
pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
// upgrade TX quality if retry+error ratio reached
else if (TxErrorRatio <= RateUpPER[CurrRate])
{
fUpgradeQuality = TRUE;
if (pEntry->TxQuality[CurrRate])
pEntry->TxQuality[CurrRate] --; // quality very good in CurrRate
if (pEntry->TxRateUpPenalty)
pEntry->TxRateUpPenalty --;
else if (pEntry->TxQuality[UpRate])
pEntry->TxQuality[UpRate] --; // may improve next UP rate's quality
}
}
else
{
TxErrorRatio = 0; // too few samples
// Downgrade TX quality upon any TX failure in the past second
if (pEntry->OneSecTxFailCount)
{
if ((pEntry->OneSecTxFailCount <= 1) && (pEntry->OneSecTxOkCount + pEntry->OneSecTxRetryOkCount))
{
pEntry->TxQuality[CurrRate] += 2; // degrade quality
if (pEntry->TxQuality[CurrRate] > DRS_TX_QUALITY_WORST_BOUND)
pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
else // more than 2 failure, or no TX ok cases
{
pEntry->TxQuality[CurrRate] = DRS_TX_QUALITY_WORST_BOUND;
}
}
// upgrade TX quality if -
// 1. no TX failure but do have TX ok case, and
// 2. there's more one-time-ok cases than retry-ok cases in the past second
else if (pEntry->OneSecTxOkCount > pEntry->OneSecTxRetryOkCount)
{
fUpgradeQuality = TRUE;
if (pEntry->TxQuality[CurrRate])
pEntry->TxQuality[CurrRate] --; // quality very good in CurrRate
if (pEntry->TxRateUpPenalty)
pEntry->TxRateUpPenalty --;
else if (pEntry->TxQuality[UpRate])
pEntry->TxQuality[UpRate] --; // may improve next UP rate's quality
}
}
DBGPRINT(RT_DEBUG_TRACE,"WDS: Qty[%d]=%d PER=%d%% %d-sec, Qty[%d]=%d Pty=%d\n",
RateIdToMbps[CurrRate], pEntry->TxQuality[CurrRate],
TxErrorRatio, pEntry->CurrTxRateStableTime,
RateIdToMbps[UpRate], pEntry->TxQuality[UpRate],
pEntry->TxRateUpPenalty);
// we're going to ugrade CurrRate to UpRate at next few seconds,
// but before that, we'd better try a NULL frame @ UpRate and
// see if UpRate is stable or not. If this NULL frame fails, it will
// downgrade TxQuality[CurrRate], so that STA won't switch to
// to UpRate in the next second
if ((fUpgradeQuality == TRUE) &&
(UpRate != CurrRate) &&
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?