Пример #1
0
NDIS_STATUS
Hvl11RegisterVNic(
    _In_  PHVL    pHvl,
    _In_  PVNIC   pVNic               
    )
{
    NDIS_STATUS ndisStatus = NDIS_STATUS_SUCCESS;
    PHVL_CONTEXT pCtx = NULL;
    
    do
    {
        HvlLock(pHvl);

        // add it to the HVL's list of VNICs
        InsertTailList(&pHvl->VNiclist, &pVNic->VNicLink);
        
        HvlAssignVNicToContext(pHvl, pVNic, &pCtx);
        
        /*
            Initially make it part of the inactive context list. It will be picked up whenever we
            next context switch to it
            */
        InsertTailList(&pHvl->InactiveContextList, &pCtx->Link);

        HvlUnlock(pHvl);

        // notify it of any existing cached notifications
        if (pHvl->CachedChannelNotification.Header.pSourceVNic)
        {
            VNic11Notify(pVNic, &pHvl->CachedChannelNotification);
        }
    } while (FALSE);

    return ndisStatus;
}
Пример #2
0
VOID
HvlNotifyAllVNics(
    PHVL pHvl,
    PVOID pvNotif
    )
{
    LIST_ENTRY *pEntryVNic = NULL;
    PVNIC pVNic = NULL;
    PNOTIFICATION_DATA_HEADER pHdr = NULL;

    ASSERT(HvlIsLocked(pHvl));

    pHdr = (PNOTIFICATION_DATA_HEADER)pvNotif;
    
    pEntryVNic = pHvl->VNiclist.Flink;
    while (pEntryVNic != &pHvl->VNiclist)
    {
        pVNic = CONTAINING_RECORD(pEntryVNic, VNIC, VNicLink);

        // do not notify if this VNIC is the source of the notification
        if (pVNic != pHdr->pSourceVNic)
        {
            _Analysis_assume_lock_held_(pHvl->Lock.SpinLock);

            HvlUnlock(pHvl);
            VNic11Notify(pVNic, pvNotif);
            HvlLock(pHvl);
        }
        
        pEntryVNic = pEntryVNic->Flink;
    }

    // Also send the notification to the helper port
    pEntryVNic = pHvl->pHelperPortCtx->VNicList.Flink;
    pVNic = CONTAINING_RECORD(pEntryVNic, VNIC, CtxLink);

    _Analysis_assume_lock_held_(pHvl->Lock.SpinLock);
    HvlUnlock(pHvl);
    VNic11Notify(pVNic, pvNotif);
    HvlLock(pHvl);
}
Пример #3
0
USHORT
HwSelectTXDataRate(
    __in  PHW_MAC_CONTEXT         HwMac,
    __in  PDOT11_RATE_SET         RemoteRateSet,
    __in  ULONG                   LinkQuality
    )
{
    PDOT11_RATE_SET             operationalRateSet;
    PDOT11_RATE_SET             activeRateSet;
    ULONG                       indexLocalRates;
    ULONG                       indexRemoteRates;
    USHORT                      maximumRate;
    OP_RATE_CHANGE_NOTIFICATION rateNotification;

    // The active rate set structure needs to be protected
    HW_ACQUIRE_HARDWARE_LOCK(HwMac->Hw, FALSE);
    
    //
    // Select the best rate supported by both AP and us. 
    //
    operationalRateSet = &(HwMac->PhyContext[HwMac->OperatingPhyId].OperationalRateSet);
    activeRateSet = &(HwMac->PhyContext[HwMac->OperatingPhyId].ActiveRateSet);

    activeRateSet->uRateSetLength = 0;
    
    //
    // We merge the rates from the AP and the client to create the 
    // currently active data rates table
    //
    for (indexLocalRates = 0; indexLocalRates < operationalRateSet->uRateSetLength; indexLocalRates++) 
    {
        for (indexRemoteRates = 0; indexRemoteRates < RemoteRateSet->uRateSetLength; indexRemoteRates++)
        {
            if (operationalRateSet->ucRateSet[indexLocalRates] == (RemoteRateSet->ucRateSet[indexRemoteRates] & 0x7f))
            {

                activeRateSet->ucRateSet[activeRateSet->uRateSetLength] = 
                    operationalRateSet->ucRateSet[indexLocalRates];
                activeRateSet->uRateSetLength++;
                break;
            }
        }
    }

    //
    // If we dont find any rates, we will stick with our management packet rate
    //
    if (activeRateSet->uRateSetLength == 0)
    {
        activeRateSet->ucRateSet[0] = (UCHAR)HalGetBeaconRate(HwMac->Hw->Hal, HwMac->OperatingPhyId);
        activeRateSet->uRateSetLength = 1;
    }
    else if (activeRateSet->uRateSetLength > 1)
    {
        // bubble sort data rates in ascending order
        INT     i, j;
        UCHAR   temp;
        for (i = activeRateSet->uRateSetLength - 1; i >= 0; i--)
        {
            for (j = 1; j <= i; j++)
            {
                if (activeRateSet->ucRateSet[j - 1] > 
                    activeRateSet->ucRateSet[j])
                {
                    temp = activeRateSet->ucRateSet[j - 1];
                    activeRateSet->ucRateSet[j - 1] = 
                        activeRateSet->ucRateSet[j];
                    activeRateSet->ucRateSet[j] = temp;
                }
            }
        }
    }

    //
    // Now that the active rate set is populated and updated, select
    // the best rate
    //
    
    //
    // Determine what the maximum TX rate should be
    //
    maximumRate = HW11_MAX_DATA_RATE;  // Start with max supported by HW
    if (LinkQuality < HW_LOW_RATE_LINK_QUALITY_THRESHOLD)
    {
        //
        // The link quality is low, we will go for the lower start rate instead of 
        // the max supported. The hardware does rate fallback, so we pick
        // something that would cause the least number of retrys
        //
        maximumRate = HW_LOW_RATE_MAX_DATA_RATE;
    }

    // 
    // Check if this is greater than max permitted value read from the registry
    //
    if (maximumRate > HwMac->Hw->RegInfo.MaximumTxRate)
    {
        maximumRate = (USHORT)HwMac->Hw->RegInfo.MaximumTxRate;
    }

    //
    // Now find the best matching rate between us and the AP
    //
    for (indexLocalRates = activeRateSet->uRateSetLength - 1; 
         indexLocalRates > 0;
         indexLocalRates--) 
    {
        //
        // Check for a rate supported by both us and the AP that is below the max we prefer to use
        //
        if (activeRateSet->ucRateSet[indexLocalRates] <= maximumRate)
        {
            //
            // Found the rate we want to use
            //
            break;
        }
    }

    HwMac->DefaultTXDataRate = activeRateSet->ucRateSet[indexLocalRates];

    // Update our rate info table. In our current implementation this is not-per peer
    HwMac->RateInfo.CurrentTXDataRate = HwMac->DefaultTXDataRate;

    MpTrace(COMP_ASSOC, DBG_LOUD, ("TX Data rate: %d\n", HwMac->DefaultTXDataRate));

    
    HW_RELEASE_HARDWARE_LOCK(HwMac->Hw, FALSE);

    //
    // Indicate NDIS_STATUS_LINK_STATE to inform the OS about the new 
    // link speed
    //
    HwIndicateLinkSpeed(HwMac, HwMac->DefaultTXDataRate);    

    // Indicate change of link speed to the port so that it 
    // can take any necessary action
    rateNotification.Header.Type = NotificationOpRateChange;
    rateNotification.Header.Size = sizeof(OP_RATE_CHANGE_NOTIFICATION);
    rateNotification.Header.pSourceVNic = NULL;
    
    rateNotification.NewRate = HwMac->DefaultTXDataRate;
    rateNotification.OldRate = 0;
    
    rateNotification.LowestRate = FALSE;
    
    VNic11Notify(HwMac->VNic, &rateNotification);

    return (UCHAR)HwMac->DefaultTXDataRate;
}
Пример #4
0
/*
    Tx rate adaptation algorithm:
    Preconditions to update tx data rate:
            1) device is in connect state; 
            2)device has sent at least 100 data packets

    retransmitPercentage = (toal retry) / (total packets sent)

    if retransmit percentage <= threshold for rate increase which default to 35%
        if not sending at the highest rate
            if previously came down from higher rate and wait count < wait required
                increase wait count and exit
            else
                if not previously came down from higher rate
                    reset wait required
                else leave wait required unchanged
                increase current tx rate to next higher rate, reset all other counters and exit

    if retransmit percentage >= threshold for roam which default to 350%
        if already send at the lowest rate
            try to roam to a better AP, reset all counters and exit
        else if there are at least fallback skip (which default to 3) lower data rates available
            reduce current tx rate to third lower data rate, reset all counters and exit
        else if current sending at second lowest rate
            set current tx rate to the lowest value, reset all counters and exit
        else fall through to following rate fallback handler

    if retransmit percentage >= threshold for rate fallback which default to 125%
    and not sending at the lowest rate
        if previously came up from lower rate
            double current wait required
        else reset wait required
        reduce current tx rate to next lower value, reset all other counters and exit
*/
VOID 
HwUpdateTxDataRate(
    __in  PHW_MAC_CONTEXT         MacContext
    )
{
    PDOT11_RATE_SET             activeRateSet;
    PHW_RATE_INFO               rateInfo = &MacContext->RateInfo;     // We are not doing per peer rate adaptation
    ULONG                       rateIndex = 0;
    USHORT                      prevTxRate = 0;
    ULONG                       totalRetry = rateInfo->TotalRetryCount;
    ULONG                       totalSend = rateInfo->PacketsSentForTxRateCheck;
    ULONG                       retransmitPercentage = 0;
    OP_RATE_CHANGE_NOTIFICATION rateNotification;

    if (HW_TEST_MAC_CONTEXT_STATUS(MacContext, HW_MAC_CONTEXT_CANNOT_SEND_FLAGS) ||
        !HW_TEST_MAC_CONTEXT_STATUS(MacContext, HW_MAC_CONTEXT_LINK_UP))
    {
        // MAC context wont be sending to a peer. There isnt anything for us to do
        return;
    }

    // Check the send threshold
    if (totalSend < MacContext->Hw->RegInfo.MinPacketsSentForTxRateUpdate)
    {
        return;
    }

    // reset counters
    InterlockedExchange(&rateInfo->TotalRetryCount, 0);
    InterlockedExchange((LONG*)&rateInfo->PacketsSentForTxRateCheck, 0);

    // The active rate set structure needs to be protected
    HW_ACQUIRE_HARDWARE_LOCK(MacContext->Hw, FALSE);

    do
    {
        activeRateSet = &(MacContext->PhyContext[MacContext->OperatingPhyId].ActiveRateSet);
        for (rateIndex = 0; rateIndex < activeRateSet->uRateSetLength; rateIndex++)
        {
            if (rateInfo->CurrentTXDataRate == activeRateSet->ucRateSet[rateIndex])
            {
                prevTxRate = rateInfo->CurrentTXDataRate;
                break;
            }
        }    

        // prevTxRate equals 0 means rateInfo->CurrentTXDataRate 
        // is not in activeRateSet->ucRateSet list
        if (prevTxRate == 0)
        {   
            MpTrace(COMP_MISC, DBG_LOUD, ("Current TX data rate is not in active rate set\n"));
            break;
        }

        retransmitPercentage = totalRetry * 100 / totalSend;

        MpTrace(COMP_TESTING, DBG_TRACE, ("%s: retransmitPercentage=%d(%d/%d), waitCount=%d, "
            "waitRequired=%d, prevRate=%d\n", 
            __FUNCTION__, 
            retransmitPercentage, totalRetry, totalSend, 
            rateInfo->TxRateIncreaseWaitCount, 
            rateInfo->TxRateIncreaseWaitRequired, 
            rateInfo->PrevTxDataRate));

        if (retransmitPercentage <= MacContext->Hw->RegInfo.TxFailureThresholdForRateIncrease)
        {
            // Consider going up
            
            if (rateIndex < activeRateSet->uRateSetLength - 1)
            {
                if ((rateInfo->PrevTxDataRate == activeRateSet->ucRateSet[rateIndex + 1]) &&
                    (rateInfo->TxRateIncreaseWaitCount + 1 < rateInfo->TxRateIncreaseWaitRequired))
                {
                    // I just came down from the rate above me, i dont want to go up yet due to WaitRequired
                    rateInfo->TxRateIncreaseWaitCount++;
                    
                    MpTrace(COMP_TESTING, DBG_TRACE, ("%s: WAIT before increasing Tx rate. retransmitPercentage=%d(%d/%d), "
                        "waitCount=%d, waitRequired=%d, prevRate=%d\n",
                        __FUNCTION__,
                        retransmitPercentage, totalRetry, totalSend, rateInfo->TxRateIncreaseWaitCount, 
                        rateInfo->TxRateIncreaseWaitRequired, rateInfo->PrevTxDataRate));
                }
                else
                {
                    // 1. I came down rate above me and WaitCount >= WaitRequired
                    // 2. I came up from rate below me, no need to wait for additional time
                    if (rateInfo->PrevTxDataRate != activeRateSet->ucRateSet[rateIndex + 1])
                    {
                        // Case 2 above
                        rateInfo->TxRateIncreaseWaitRequired = 1;
                    }
                    else
                    {
                        // Case 1 above
                        /** don't reset TxRateIncreaseWaitRequired as we need to double */
                        /** the value if fallback to the current rate again */
                    }
                    rateInfo->PrevTxDataRate = rateInfo->CurrentTXDataRate;
                    rateInfo->TxRateIncreaseWaitCount = 0;

                    MpTrace(COMP_TESTING, DBG_TRACE, ("%s: increasing Tx data rate from %d to %d. "
                        "retransmitPercentage = %d(%d/%d), waitCount=%d, waitRequired=%d, prevRate=%d\n",
                        __FUNCTION__, 
                        rateInfo->CurrentTXDataRate, activeRateSet->ucRateSet[rateIndex + 1],
                        retransmitPercentage, totalRetry, totalSend,
                        rateInfo->TxRateIncreaseWaitCount, 
                        rateInfo->TxRateIncreaseWaitRequired, 
                        rateInfo->PrevTxDataRate));

                    rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[rateIndex + 1];
                }
            }
            break;
        }

        if (retransmitPercentage >= MacContext->Hw->RegInfo.TxFailureThresholdForRoam)
        {
            ULONG   rateSkipLevel = MacContext->Hw->RegInfo.TxDataRateFallbackSkipLevel;
            
            // Really large retry count, consider roaming
            
            if (rateIndex == 0)
            {
                // I am sending at the lowest rate. Either roam or disconnect.
                MpTrace(COMP_TESTING, DBG_TRACE, ("%s: too many retransmit happened while "
                    "transmitting at the lowest data rate. Attempting to roam. "
                    "retransmitPercentage=%d(%d/%d), waitCount=%d, waitRequired=%d, prevRate=%d", 
                    __FUNCTION__,
                    retransmitPercentage, totalRetry, totalSend, 
                    rateInfo->TxRateIncreaseWaitCount,
                    rateInfo->TxRateIncreaseWaitRequired, 
                    rateInfo->PrevTxDataRate));

                // Our packets arent going through, jump up to using best data rate &
                // hopefully our packets will go through
                rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[activeRateSet->uRateSetLength - 1];

                // reset counters
                rateInfo->PrevTxDataRate = 0;
                rateInfo->TxRateIncreaseWaitRequired = 1;
                rateInfo->TxRateIncreaseWaitCount = 0;
                break;
            }
            else if (rateIndex >= rateSkipLevel)
            {
                // try to go down three rates
                MpTrace(COMP_TESTING, DBG_TRACE, ("%s: too many retransmit happened. Reducing Tx rate from %d to %d.\n",
                        __FUNCTION__, 
                        rateInfo->CurrentTXDataRate,
                        activeRateSet->ucRateSet[rateIndex - rateSkipLevel]));

                rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[rateIndex - rateSkipLevel];
                rateInfo->PrevTxDataRate = 0;
                rateInfo->TxRateIncreaseWaitRequired = 1;
                rateInfo->TxRateIncreaseWaitCount = 0;
                break;
            }
            else if (rateIndex != 1)
            {
                // set tx rate to the lowest rate
                MpTrace(COMP_TESTING, DBG_TRACE, ("%s: too many retransmit happened. Reducing Tx rate from "
                        "%d to lowest %d.\n",
                        __FUNCTION__, 
                        rateInfo->CurrentTXDataRate,
                        activeRateSet->ucRateSet[0]));

                rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[0];
                rateInfo->PrevTxDataRate = 0;
                rateInfo->TxRateIncreaseWaitRequired = 1;
                rateInfo->TxRateIncreaseWaitCount = 0;
                break;
            }
            else
            {
                // rateIndex equals to 1. this is the same as lowering tx rate by 1 level
                // which is what rate fallback handler does. fall through.
            }
        }

        if ((retransmitPercentage >= MacContext->Hw->RegInfo.TxFailureThresholdForRateFallback) && (rateIndex > 0))
        {
            // consider going down. no need to wait for additional time
            
            if (rateInfo->PrevTxDataRate == activeRateSet->ucRateSet[rateIndex - 1])
            {
                rateInfo->TxRateIncreaseWaitRequired *= 2;
            }
            else
            {
                rateInfo->TxRateIncreaseWaitRequired = 1;
            }
            rateInfo->PrevTxDataRate = rateInfo->CurrentTXDataRate;
            rateInfo->TxRateIncreaseWaitCount = 0;
            
            MpTrace(COMP_TESTING, DBG_TRACE, ("%s: reducing Tx data rate from %d to %d. "
                "retransmitPercentage=%d(%d/%d), waitCount=%d, waitRequired=%d, prevRate=%d\n",
                __FUNCTION__, 
                rateInfo->CurrentTXDataRate, 
                activeRateSet->ucRateSet[rateIndex - 1],
                retransmitPercentage, totalRetry, totalSend, 
                rateInfo->TxRateIncreaseWaitCount, 
                rateInfo->TxRateIncreaseWaitRequired,
                rateInfo->PrevTxDataRate));

            rateInfo->CurrentTXDataRate = activeRateSet->ucRateSet[rateIndex - 1];
            break;
        }
    } while (FALSE);

    HW_RELEASE_HARDWARE_LOCK(MacContext->Hw, FALSE);

    if (prevTxRate != rateInfo->CurrentTXDataRate)
    {
        // Indicate new link speed
        HwIndicateLinkSpeed(MacContext, rateInfo->CurrentTXDataRate);    

        // Indicate change of link speed to the port so that it 
        // can take any necessary action
        rateNotification.Header.Type = NotificationOpRateChange;
        rateNotification.Header.Size = sizeof(OP_RATE_CHANGE_NOTIFICATION);
        rateNotification.Header.pSourceVNic = NULL;

        rateNotification.NewRate = rateInfo->CurrentTXDataRate;
        rateNotification.OldRate = prevTxRate;

        if (rateIndex == 0)
            rateNotification.LowestRate = TRUE;
        else
            rateNotification.LowestRate = FALSE;

        VNic11Notify(MacContext->VNic, &rateNotification);
    }
}