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 + -
显示快捷键?