wlan_bearer/wlanldd/wlan_common/umac_common/src/UmacDot11Associated.cpp
changeset 0 c40eb8fe8501
child 3 6524e815f76f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanldd/wlan_common/umac_common/src/UmacDot11Associated.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,2725 @@
+/*
+* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:   Implementation of the WlanDot11Associated class
+*
+*/
+
+/*
+* %version: 95 %
+*/
+
+#include "config.h"
+#include "UmacDot11Associated.h"
+#include "UmacContextImpl.h"
+#include "UmacWsaWriteMib.h"
+#include "umacinternaldefinitions.h"
+
+/**
+* Mask to determine the used encryption from WHA::ReceivePacket's aFlags 
+* parameter
+*/
+const TUint32 KReceivePacketEncryptionMask = 0x00038000;
+
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::OnBeaconFrameRx( 
+    WlanContextImpl& aCtxImpl,
+    const TAny* /*aFrame*/,
+    const TUint32 /*aLength*/,
+    WHA::TRcpi /*aRcpi*/,
+    TUint8* aBuffer )
+    {
+    // release the Rx buffer
+    aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::OnProbeResponseFrameRx( 
+    WlanContextImpl& aCtxImpl,
+    const TAny* /*aFrame*/,
+    const TUint32 /*aLength*/,
+    WHA::TRcpi /*aRcpi*/,
+    TUint8* aBuffer )
+    {
+    // release the Rx buffer
+    aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::OnDeauthenticateFrameRx( 
+    WlanContextImpl& aCtxImpl,
+    TUint8* aBuffer )
+    {
+    // release the Rx buffer
+    aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::OnDisassociateFrameRx( 
+    WlanContextImpl& aCtxImpl,
+    TUint8* aBuffer )
+    {
+    // release the Rx buffer
+    aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TSnapStatus WlanDot11Associated::ValiDateSnapHeader( 
+    WlanContextImpl& aCtxImpl,
+    const TUint8* aStartOfSnap ) const
+    {
+    TSnapStatus snapStatus( ESnapUnknown );
+
+    if ( !os_memcmp( 
+            aStartOfSnap, 
+            &KEncapsulatingRfc1042SnapHeader, 
+            sizeof( KEncapsulatingRfc1042SnapHeader ) ) )
+        {
+        snapStatus = ESnapDot11Ok;
+        }
+    else if ( !os_memcmp( 
+                aStartOfSnap, 
+                &KEncapsulating802_1hSnapHeader, 
+                sizeof( KEncapsulating802_1hSnapHeader ) ) )
+        {
+        snapStatus = ESnapDot11Ok;
+        }
+    else
+        {
+        // unknown SNAP. Status already correct. No action needed
+        }
+
+    if ( snapStatus == ESnapUnknown &&
+         aCtxImpl.NetworkOperationMode() == WHA::EBSS &&
+         aCtxImpl.GetProprietarySnapHeader() != KUndefinedSnapHeader )
+        {
+        // SNAP still unknown, but we a are in a infrastructure network and
+        // a proprietary SNAP header has been defined.
+        // Check if the SNAP is this proprietary SNAP header
+        
+        if ( !os_memcmp( 
+                aStartOfSnap, 
+                &(aCtxImpl.GetProprietarySnapHeader()), 
+                sizeof( aCtxImpl.GetProprietarySnapHeader() ) ) )
+            {
+            snapStatus = ESnapProprietaryOk;
+            }        
+        }
+    
+    return snapStatus;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+inline TBool WlanDot11Associated::RxDataMpduValid(
+    const TUint32 aLength,
+    const SDataFrameHeader& aFrameHeader,
+    TBool aQosData,
+    TBool aAmsdu,
+    TUint aHtControlLen,
+    TUint aSecurityHeaderLen,
+    TUint aSecurityTrailerLen ) const
+    {
+    //========================================================================
+    // validate frame length
+    //========================================================================
+    
+    const TUint KMinAcceptableRxDataMpduLen ( 
+        MinAcceptableRxDataMpduLen( 
+            aQosData,
+            aAmsdu,
+            aHtControlLen,
+            aSecurityHeaderLen,
+            aSecurityTrailerLen ) );
+    
+    if ( aLength < KMinAcceptableRxDataMpduLen )
+        {
+        // frame shorter than min acceptable length; reject it 
+        OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+            ("UMAC: WlanDot11Associated::RxDataMpduValid: WARNING: MPDU rejected because its shorter than min acceptable length of %d"),
+            KMinAcceptableRxDataMpduLen );        
+
+        return EFalse;
+        }
+    
+    //========================================================================
+    // validate To DS & From DS bits
+    //========================================================================
+
+    if ( !DoIsValidAddressBitCombination( aFrameHeader ) )
+        {
+        OsTracePrint( KRxFrame, (TUint8*)
+            ("UMAC: WlanDot11Associated::RxDataMpduValid: MPDU rejected because of invalid To DS and/or From DS bit values") );
+
+        return EFalse;
+        }
+            
+    return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+// defines the minimum acceptable Data MPDU length as:
+// dot11 MAC header length including SNAP and possibly existing HT Control 
+// field
+// + security header length
+// + subframe header length if the QoS Data MPDU contains an A-MSDU
+// + security trailer length
+// + Ethernet type field length
+// ---------------------------------------------------------------------------
+//
+inline TUint WlanDot11Associated::MinAcceptableRxDataMpduLen(
+    TBool aQosData,
+    TBool aAmsdu,
+    TUint aHtControlLen,
+    TUint aSecurityHeaderLen,
+    TUint aSecurityTrailerLen ) const
+    {
+    return aQosData ? 
+        sizeof( SQosDataMpduHeader ) + aHtControlLen
+        + aSecurityHeaderLen
+        + ( aAmsdu ? sizeof( SAmsduSubframeHeader ) : 0 )
+        + aSecurityTrailerLen
+        + sizeof( SEthernetType )
+        :         
+        sizeof( SDataMpduHeader )
+        + aSecurityHeaderLen
+        + aSecurityTrailerLen
+        + sizeof( SEthernetType );
+    }
+
+// ---------------------------------------------------------------------------
+// Note that address 1 is the DA (Destination Address) both in infrastructure
+// and IBSS network Rx frames
+// ---------------------------------------------------------------------------
+//
+inline TDaType WlanDot11Associated::RxFrameDaType(
+    const SDataFrameHeader& aFrameHeader ) const
+    {
+    if ( IsGroupBitSet( aFrameHeader.iAddress1 ) )
+        {
+        // a multicast
+        if ( aFrameHeader.iAddress1 == KBroadcastMacAddr )
+            {
+            // also a brodcast
+            return EBroadcastAddress;
+            }
+        else
+            {
+            // a multicast but not a broadcast
+            return EMulticastAddress;
+            }
+        }
+    else
+        {
+        // a unicast
+        return EUnicastAddress;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+//  
+// ---------------------------------------------------------------------------
+//
+inline TBool WlanDot11Associated::RxMsduValid(
+    WlanContextImpl& aCtxImpl,
+    const SDataFrameHeader& aFrameHeader,
+    const SAmsduSubframeHeader* aSubFrameHeader,
+    const TUint8* aStartOfSnap,
+    TUint16 aEtherType,
+    TBool aMulticast,
+    TUint32 aFlags,
+    TSnapStatus& aSnapStatus ) const
+    {
+    //========================================================================
+    // validate SNAP header
+    //========================================================================
+    
+    aSnapStatus = ValiDateSnapHeader( aCtxImpl, aStartOfSnap );
+    
+    if ( aSnapStatus == ESnapUnknown )
+        {
+        // SNAP header is invalid
+        
+        OsTracePrint( KRxFrame, (TUint8*)
+            ("UMAC: WlanDot11Associated::RxMsduValid: MSDU rejected because of invalid snap:"),
+            aStartOfSnap, aStartOfSnap + sizeof( SSnapHeader ) );    
+
+        return EFalse;
+        }
+
+    // determine if SA is our MAC address
+    const TBool KSaIsOurMac ( 
+        DoIsRxFrameSAourAddress( aCtxImpl, aFrameHeader, aSubFrameHeader ) );           
+
+    //========================================================================
+    // if this is a proprietary test MSDU but not sent by us, its not valid 
+    // for us
+    //========================================================================
+
+    if ( aEtherType == KBounceType && !KSaIsOurMac )
+        {
+#ifndef NDEBUG
+        OsTracePrint( KRxFrame, (TUint8*)
+            ("UMAC: WlanDot11Associated::RxMsduValid: proprietary test MSDU, but not sent by us. MSDU rejected") );
+
+        if ( aSubFrameHeader )
+            {
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Subframe DA:"), aSubFrameHeader->iDa );                
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Subframe SA:"), aSubFrameHeader->iSa );                
+            }
+        else
+            {
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Address1:"), aFrameHeader.iAddress1);    
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Address2:"), aFrameHeader.iAddress2);    
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Address3:"), aFrameHeader.iAddress3);
+            }
+#endif        
+
+        return EFalse;
+        }
+
+    //========================================================================
+    // non-test multicast MSDUs sent by us are not relevant for us
+    //========================================================================
+
+    if ( // SA is our MAC address
+         KSaIsOurMac
+         // AND this is a multicast frame
+         && aMulticast
+         // AND this is not a test frame
+         && aEtherType != KBounceType )
+        {
+        // we have received a non-test multicast frame that was sent by us.
+        // Ignore it.
+        
+#ifndef NDEBUG
+        OsTracePrint( KRxFrame, (TUint8*)
+            ("UMAC: WlanDot11Associated::RxMsduValid: MSDU rejected because its a non-test multicast MSDU sent by us"));
+        
+        if ( aSubFrameHeader )
+            {
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Subframe DA:"), aSubFrameHeader->iDa );                
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Subframe SA:"), aSubFrameHeader->iSa );                
+            }
+        else
+            {
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Address1:"), aFrameHeader.iAddress1);    
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Address2:"), aFrameHeader.iAddress2);    
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: Address3:"), aFrameHeader.iAddress3);
+            }
+#endif
+
+        return EFalse;
+        }
+        
+    // determine the encryption of the frame
+    const TUint32 KEncryption ( aFlags & KReceivePacketEncryptionMask );
+
+    if ( aSnapStatus != ESnapProprietaryOk )
+        {
+        //====================================================================
+        // validate MSDU with the applicable privacy mode filter
+        //====================================================================
+        if ( !aCtxImpl.ExecuteActivePrivacyModeFilter(
+                aFrameHeader,
+                aCtxImpl.iEnableUserData,
+                aEtherType,
+                aCtxImpl.PairWiseKeyType() != WHA::EKeyNone,
+                ( KEncryption == WHA::KEncryptAes || 
+                  KEncryption == WHA::KEncryptTkip ||
+                  KEncryption == WHA::KEncryptWapi ) ) )
+            {
+            return EFalse;
+            }
+        }
+
+    // this MSDU has passed all our checks, so it is valid for us
+    return ETrue;
+    }
+
+// ---------------------------------------------------------------------------
+//  
+// ---------------------------------------------------------------------------
+//
+inline TUint WlanDot11Associated::RxMsduEthernetPayloadLength(
+    const TUint32 aMpduLength, 
+    TUint aSubframeLength, 
+    TBool aQosData,
+    TUint aHtControlLen,
+    TUint aSecurityHeaderLen,
+    TUint aSecurityTrailerLen ) const
+    {
+    TUint length ( 0 );
+    
+    if ( aSubframeLength )
+        {
+        // this ethernet payload is carried in an A-MSDU subframe
+        
+        length = aSubframeLength - sizeof( SSnapHeader );
+
+        OsTracePrint( KRxFrame, (TUint8*)
+            ("UMAC: subframe eth payload len: %d"),
+            length );                        
+        }
+    else
+        {
+        // this ethernet payload is carried in a non-A-MSDU frame
+
+        if ( aQosData )
+            {
+            length = 
+                // total length of the Rx frame
+                aMpduLength
+                // - MAC header length including SNAP
+                - ( sizeof( SQosDataMpduHeader ) + aHtControlLen )
+                // - security header length
+                - aSecurityHeaderLen
+                // - security trailer length
+                - aSecurityTrailerLen;
+                
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: qos data eth payload len: %d"),
+                length );                        
+            }
+        else
+            {
+            length =
+                // total length of the Rx frame
+                aMpduLength
+                // MAC header length including SNAP
+                - sizeof( SDataMpduHeader )
+                // - security header length
+                - aSecurityHeaderLen
+                // - security trailer length
+                - aSecurityTrailerLen;
+        
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: non-qos data eth payload len: %d"),
+                length );                        
+            }
+        }
+    
+    return length;
+    }
+
+// ---------------------------------------------------------------------------
+//   
+// ---------------------------------------------------------------------------
+//
+inline TUint8* WlanDot11Associated::NewBufForMgmtClientRxFrame(
+    WlanContextImpl& aCtxImpl,
+    TBool aProprieatarySnapFrame,
+    TBool aQosFrame,
+    TUint aHtControlLen,
+    TUint aEtherPayloadLength ) const
+    {
+    TUint requiredLength ( 0 );
+    
+    if ( aProprieatarySnapFrame )
+        {
+        // forwarded as a Data MPDU
+        
+        requiredLength = aQosFrame ? 
+            sizeof( SQosDataFrameHeader ) 
+            + aHtControlLen 
+            + aEtherPayloadLength :
+            sizeof( SDataFrameHeader ) 
+            + aEtherPayloadLength;        
+        }
+    else
+        {
+        // forwarded as Ethernet frame
+        
+        requiredLength = 2 * sizeof( TMacAddress ) + aEtherPayloadLength;
+        }
+    
+    // request for a new Rx buffer
+    return aCtxImpl.GetRxBuffer( 
+        requiredLength, 
+        // tell that this is an internally triggered buffer request
+        ETrue );
+    }
+        
+// ---------------------------------------------------------------------------
+//  
+// ---------------------------------------------------------------------------
+//
+inline TBool WlanDot11Associated::RxMsduForUser(
+    TUint16 aEtherType,
+    TSnapStatus aSnapstatus ) const
+    {
+    if ( // not an EAPOL frame AND
+         aEtherType != KEapolType &&
+         // not a WAI frame AND
+         aEtherType != KWaiType &&
+         // not a WLAN Mgmt Client test frame
+         aEtherType != KBounceType &&
+         // not a proprietary SNAP frame
+         aSnapstatus != ESnapProprietaryOk )
+        {
+        // a user data / protocol stack data frame
+
+        return ETrue;
+        }
+    else
+        {
+        return EFalse;
+        }
+    }
+
+// ---------------------------------------------------------------------------
+//  
+// ---------------------------------------------------------------------------
+//
+inline void WlanDot11Associated::UpdateDataFrameRxStatistics(
+    WlanContextImpl& aCtxImpl,
+    TUint16 aEtherType,
+    TBool aMulticast,
+    WHA::TQueueId aAccessCategory ) const
+    {
+    if ( aEtherType != KBounceType )
+        {
+        // other than WLAN Mgmt Client test data frame received
+        
+        if ( aMulticast )
+            {
+            // multicast frame
+    
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: inc rx mcast cnt for AC: %d"),
+                aAccessCategory );
+    
+            // update frame statistics
+            aCtxImpl.IncrementRxMulticastDataFrameCount( aAccessCategory );            
+            }
+        else
+            {
+            // unicast frame
+    
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: inc rx unicast cnt for AC: %d"),
+                aAccessCategory );
+    
+            // update frame statistics
+            aCtxImpl.IncrementRxUnicastDataFrameCount( aAccessCategory );
+            }
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::OnDataFrameRx(
+    WlanContextImpl& aCtxImpl,
+    const TAny* aFrame,
+    const TUint32 aLength,
+    TUint32 aFlags,
+    WHA::TRcpi aRcpi,
+    TUint8* aBuffer )
+    {
+    OsTracePrint( KRxFrame, (TUint8*)
+        ("UMAC: WlanDot11Associated::OnDataFrameRx") );    
+
+    SDataMpduHeader* hdr 
+        = reinterpret_cast<SDataMpduHeader*>(const_cast<TAny*>(aFrame));
+    SQosDataMpduHeader* qoshdr 
+        = reinterpret_cast<SQosDataMpduHeader*>(const_cast<TAny*>(aFrame));
+
+    // determine the length of the security header (e.g. IV etc.) ...
+    const TUint KSecurityHeaderLen( DecryptHdrOffset( aCtxImpl, aFlags ) );
+
+    OsTracePrint( KRxFrame, (TUint8*)("UMAC: KSecurityHeaderLen: %d"),
+        KSecurityHeaderLen );    
+
+    // ... and the security trailer (e.g. MIC etc.)
+    const TUint KSecurityTrailerLen( DecryptTrailerOffset( aCtxImpl, aFlags ) );
+
+    OsTracePrint( KRxFrame, (TUint8*)("UMAC: KSecurityTrailerLen: %d"),
+        KSecurityTrailerLen );    
+
+    // as the MAC header of a QoS data MPDU has an additional field
+    // we need to take that into account; so make a note if we indeed have 
+    // received a QoS data MPDU
+    const TBool KQosData = 
+        ( hdr->iHdr.iFrameControl.iType == E802Dot11FrameTypeQosData ) ? 
+        ETrue : EFalse;
+
+    // the MAC header of HT QoS data MPDU also has an additional field,
+    // so determine if that field is present and hence has a non-zero length
+    const TUint KHtControlLen ( 
+        KQosData && HtcFieldPresent( aCtxImpl, aFrame, aFlags ) ? 
+            KHtControlFieldLength : 0 );
+
+    // determine if the MPDU contains an A-MSDU
+    const TBool KAmsdu ( 
+        KQosData && qoshdr->iHdr.AmsduPresent() ? ETrue : EFalse );
+    
+    if ( !RxDataMpduValid(
+            aLength,
+            hdr->iHdr,
+            KQosData,
+            KAmsdu,
+            KHtControlLen,
+            KSecurityHeaderLen,
+            KSecurityTrailerLen ) )
+        {
+        // the overall MAC MPDU (disregarding the included MSDU(s) at this
+        // point) is not valid for us. Release the Rx buffer & abort
+        aCtxImpl.iUmac.MarkRxBufFree( aBuffer );                            
+        return;        
+        }
+    
+    TUint8* framePtr ( 0 );
+    WHA::TQueueId accessCategory( WHA::ELegacy );
+
+    // User Priority is regarded as Best Effort (i.e. Legacy, i.e. zero) unless
+    // the received MPDU is a QoS Data MPDU & a different priority is 
+    // specified in its MAC header
+    TUint8 userPriority( 0 );
+    
+    if ( KQosData )
+        {
+        // a QoS Data MPDU
+        
+        // move framePtr past the MAC header
+        framePtr = reinterpret_cast<TUint8 *>(
+            reinterpret_cast<SQosDataFrameHeader *>( hdr ) + 1 ) 
+            + KHtControlLen;        
+
+        // get the User Priority
+        userPriority = qoshdr->iHdr.UserPriority();
+
+        // make a note of the Access Category corresponding to the
+        // user priority of the MPDU (note that there's a one to one 
+        // mapping between Queue id and Access Category)       
+        accessCategory = Queue( userPriority );
+        }
+    else
+        {
+        // move framePtr past the MAC header
+        framePtr = reinterpret_cast<TUint8 *>(
+            reinterpret_cast<SDataFrameHeader *>( hdr ) + 1 );
+        }
+
+    // move after possibly existing security header and possibly existing
+    // A-MSDU subframe header, i.e. beginning of SNAP header
+    framePtr += KAmsdu ? 
+                KSecurityHeaderLen + sizeof( SAmsduSubframeHeader ) : 
+                KSecurityHeaderLen;
+    TUint8* snapLocation ( framePtr );
+    
+    // determine the DA type
+    const TDaType KDaType ( RxFrameDaType( hdr->iHdr ) );
+
+    TSnapStatus snapstatus( ESnapUnknown );
+    TDataBuffer* latestValidPacketForUsr ( NULL );
+    TUint nbrOfpacketsForUsr ( 0 );
+    TUint nbrOfpacketsForMgmtClient ( 0 );
+    const TUint KMaxNbrOfPacketsForUsr ( 30 );
+    const TUint KMaxNbrOfPacketsForMgmtClient ( 10 );
+    const TDataBuffer* packetsForUsr[KMaxNbrOfPacketsForUsr];
+    const TDataBuffer* packetsForMgmtClient[KMaxNbrOfPacketsForMgmtClient];
+    // one byte past the last actual payload byte (so excluding the potentially
+    // present security trailer) of the MPDU
+    const TUint8* const KMpduPayloadEnd ( 
+        reinterpret_cast<const TUint8*>(aFrame) 
+        + aLength 
+        - KSecurityTrailerLen );
+    TPowerMgmtModeChange powerMgmtModeChange ( ENoChange );
+    
+    // handle every MSDU contained in this MPDU. If this is not an A-MSDU
+    // there's only a single MSDU in it.
+    do
+        {
+        TUint8* rxBuffer ( aBuffer );
+        
+        // move after SNAP header to Ethernet type field
+        framePtr += sizeof( SSnapHeader );     
+        const SEthernetType* const KEtherTypeLocation 
+            = reinterpret_cast<const SEthernetType*>( framePtr );
+    
+        // determine Ethernet type
+        const TUint16 KEtherType = KEtherTypeLocation->Type();
+    
+        OsTracePrint( KRxFrame, (TUint8*)
+            ("UMAC: ether type: 0x%04x"), 
+            KEtherType );
+
+        // pointer to subframe heaader; or NULL if the MPDU doesn't contain
+        // an A-MSDU
+        const SAmsduSubframeHeader* KSubframeHdr ( KAmsdu ?  
+            ( reinterpret_cast<const SAmsduSubframeHeader*>(
+                    snapLocation) - 1 ) : 
+            NULL );
+        
+        // determine if this is a multicast MSDU
+        TBool KMulticastMsdu ( EFalse );
+        if ( KSubframeHdr )
+            {
+            KMulticastMsdu = IsGroupBitSet( KSubframeHdr->iDa );
+            }
+        else
+            {
+            KMulticastMsdu = ( KDaType == EUnicastAddress ? EFalse : ETrue );
+            }
+
+        // determine subframe length, which can be non-zero only if the MPDU
+        // contains an A-MSDU
+        const TUint KSubframeLen ( KSubframeHdr ?  KSubframeHdr->Length() : 0 );
+        
+        if ( !RxMsduValid(
+                aCtxImpl,
+                hdr->iHdr,
+                KSubframeHdr,
+                snapLocation,
+                KEtherType,
+                KMulticastMsdu,
+                aFlags,
+                snapstatus ) )
+            {
+            // this MSDU is not valid/relevant for us
+
+            if ( KAmsdu )
+                {
+                // move pointer to the SNAP of the possibly existing next 
+                // subframe
+                snapLocation += 
+                    Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen );
+                // update frame pointer accordingly
+                framePtr = snapLocation;
+
+                continue;
+                }
+            else
+                {
+                // this MPDU doesn't contain an A-MSDU, so there cannot be
+                // more than a single MSDU in it
+                break;
+                }
+            }
+            
+        // determine if this MSDU is for user / protocol stack
+        const TBool KMsduForUser ( RxMsduForUser( KEtherType, snapstatus) );
+        
+        if ( KMsduForUser && !aCtxImpl.iUmac.ProtocolStackSideClientReady() )
+            {
+            // this MSDU should be forwarded up the protocol stack but the 
+            // protocol stack client is not ready. So we need to skip at
+            // least this MSDU. 
+            // Move pointer to the SNAP of the possibly existing next subframe
+            snapLocation += 
+                Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen );            
+            // update frame pointer accordingly
+            framePtr = snapLocation;
+
+            OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+                ("UMAC: WARNING: protocol stack client not ready; MSDU ignored") );
+
+            continue;            
+            }
+
+        TDataBuffer* metaHdr ( aCtxImpl.GetRxFrameMetaHeader() );        
+        if ( !metaHdr )
+            {
+            // no memory available for Rx frame meta header. This means that
+            // we are not able to forward to higher layers the current MSDU or 
+            // any MSDU(s) that possibly follow it in this same MPDU
+
+            OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+                ("UMAC: WARNING: no memory for Rx frame meta hdr; MSDU ignored") );
+            break;
+            }        
+    
+        const TUint KEtherPayloadLen( RxMsduEthernetPayloadLength(
+                aLength, 
+                KSubframeLen, 
+                KQosData,
+                KHtControlLen,
+                KSecurityHeaderLen,
+                KSecurityTrailerLen ) );
+    
+        if ( !KMsduForUser && KAmsdu )
+            {
+            // an MSDU for WLAN Mgmt Client which is also a part of an 
+            // A-MSDU. In this case we need to allocate a new buffer for
+            // this packet and copy it there. This is necessary as an 
+            // A-MSDU may contain MSDUs both for the protocol stack side 
+            // and for WLAN Mgmt Client. Either one of those clients may 
+            // complete the handling of its MSDUs first at which point the
+            // Rx buffer(s) for its MSDU(s) is freed. So we need to make 
+            // sure that a buffer is not freed while a client is still 
+            // handling MSDU(s) contained in it. We do this by always 
+            // copying WLAN Mgmt client MSDU(s) part of an A-MSDU to 
+            // new buffers.
+            
+            rxBuffer = NewBufForMgmtClientRxFrame(
+                aCtxImpl,
+                snapstatus == ESnapProprietaryOk,
+                KQosData,
+                KHtControlLen,
+                snapstatus == ESnapProprietaryOk ? 
+                    KSubframeLen : KEtherPayloadLen );
+            
+            if ( !rxBuffer )
+                {
+                // allocation failed so we need to skip at least this MSDU. 
+
+                // Move pointer to the SNAP of the possibly existing next 
+                // subframe
+                snapLocation += 
+                    Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen );                // update frame pointer accordingly
+                // update frame pointer accordingly
+                framePtr = snapLocation;
+
+                // also release the meta hdr which was planned to be used for
+                // this MSDU 
+                aCtxImpl.FreeRxFrameMetaHeader( metaHdr );
+
+                OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+                    ("UMAC: WARNING: new buf alloc for mgmt client frame failed; MSDU ignored") );
+                continue;
+                }
+            }
+        
+        // set the offset to the beginning of the Rx buffer from the beginning
+        // of the meta header. Note that this may be also negative
+        metaHdr->KeSetBufferOffset(
+            rxBuffer
+            - reinterpret_cast<TUint8*>(metaHdr) );
+        
+        if ( snapstatus == ESnapProprietaryOk )
+            {
+            HandleProprietarySnapRxFrame( 
+                *metaHdr, 
+                KQosData,
+                aFrame, 
+                KSubframeHdr,
+                aLength, 
+                KSecurityHeaderLen, 
+                KSecurityTrailerLen,
+                KHtControlLen,
+                KAmsdu ? rxBuffer : NULL );
+            }
+        else
+            {
+            DoBuildEthernetFrame( 
+                *metaHdr, 
+                *hdr, 
+                // start of ethernet payload (includes ether type field)
+                reinterpret_cast<const TUint8*>(KEtherTypeLocation), 
+                // length of ethernet payload
+                KEtherPayloadLen,
+                KAmsdu,
+                !KMsduForUser && KAmsdu ? rxBuffer : NULL );
+            }
+        
+        // set the frame's User Priority to the Rx buffer being passed 
+        // to the client
+        metaHdr->SetUserPriority( userPriority );                    
+        // set the RCPI
+        metaHdr->KeSetRcpi( aRcpi );
+    
+        if ( KEtherType == KBounceType )
+            {
+            metaHdr->FrameType( 
+                TDataBuffer::KEthernetTestFrame );
+            }
+
+        if ( KMsduForUser )
+            {
+            // a user data / protocol stack data frame
+
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: data frame rx"));    
+
+            packetsForUsr[nbrOfpacketsForUsr++] = metaHdr;            
+            latestValidPacketForUsr = metaHdr;
+            if ( KAmsdu )
+                {
+                metaHdr->KeSetFlags( TDataBuffer::KDontReleaseBuffer );
+                }
+            }
+        else
+            {
+            // a WLAN Mgmt Client data frame
+            
+            OsTracePrint( KRxFrame, (TUint8*)
+                ("UMAC: mgmt client frame rx"));    
+
+            packetsForMgmtClient[nbrOfpacketsForMgmtClient++] = metaHdr;
+            }
+
+        //  move pointer to the SNAP of the possibly existing next subframe
+        snapLocation += Align4( sizeof( SAmsduSubframeHeader ) + KSubframeLen );
+        // update frame pointer accordingly
+        framePtr = snapLocation;
+
+        UpdateDataFrameRxStatistics(
+            aCtxImpl,
+            KEtherType,
+            KMulticastMsdu,
+            accessCategory );        
+
+        // inform dynamic power mode mgr about Rx data frame acceptance        
+        if ( // if this is not our test frame AND 
+             KEtherType != KBounceType &&
+             // need to change power mgmt mode hasn't already been detected
+             // based on this received (A-)MSDU
+             powerMgmtModeChange == ENoChange )
+            {
+            powerMgmtModeChange = aCtxImpl.OnFrameRx( 
+                accessCategory, 
+                KEtherType, 
+                KEtherPayloadLen, 
+                KDaType );
+            }
+        
+        // inform Null Send Controller about data frame Rx
+        aCtxImpl.OnDataRxCompleted( 
+            ( KEtherType == KEapolType || KEtherType == KWaiType ) ?
+            // as EAPOL and WAI frames or not really Voice data (they
+            // are just sometimes sent with Voice priority), handle them 
+            // here as Best Effort (Legacy)
+            WHA::ELegacy : 
+            accessCategory, 
+            KEtherPayloadLen );
+
+          // for a non-A-MSDU this loop is executed only once
+        } while ( KAmsdu && snapLocation < KMpduPayloadEnd );
+
+    if ( nbrOfpacketsForUsr )
+        {
+        latestValidPacketForUsr->KeClearFlags( 
+            TDataBuffer::KDontReleaseBuffer );
+
+        // complete user data / protocol stack data frame(s)
+        if ( !aCtxImpl.iUmac.ProtocolStackDataReceiveComplete( 
+                packetsForUsr[0], 
+                nbrOfpacketsForUsr ) )
+            {
+            // there's no protocol stack client to whom to complete Rx packets.
+            // (Actually the control should never arrive here as we have 
+            // checked the readiness of the protocol stack client already
+            // earlier)
+            nbrOfpacketsForUsr = 0;
+            }
+        }
+
+    if ( nbrOfpacketsForMgmtClient )
+        {
+        // complete WLAN Mgmt Client data frame(s)
+        aCtxImpl.iUmac.MgmtDataReceiveComplete( 
+            packetsForMgmtClient[0], 
+            nbrOfpacketsForMgmtClient );
+        }
+
+    if ( ( !nbrOfpacketsForUsr && !nbrOfpacketsForMgmtClient ) ||
+         ( KAmsdu && !nbrOfpacketsForUsr ) )
+        {
+        // the contents of the original Rx buffer are not needed any more,
+        // so deallocate it        
+        OsTracePrint( KRxFrame, (TUint8*)
+            ("UMAC: free original Rx buf"));    
+        aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+        }
+    
+    // if any change is needed regarding our power mgmt mode,
+    // proceed with it
+    PowerMgmtModeChange( aCtxImpl, powerMgmtModeChange );    
+    }
+    
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::OnManagementActionFrameRx(
+    WlanContextImpl& aCtxImpl,
+    const TAny* aFrame,
+    const TUint32 aLength,
+    WHA::TRcpi aRcpi,
+    TUint8* aBuffer ) const
+    {
+    OsTracePrint(  KRxFrame, (TUint8*)
+        ("UMAC: WlanDot11Associated::OnManagementActionFrameRx"));    
+
+    TDataBuffer* metaHdr ( aCtxImpl.GetRxFrameMetaHeader() );
+
+    if ( metaHdr )
+        {
+        // set length and type
+        metaHdr->KeSetLength( aLength );
+        metaHdr->FrameType( TDataBuffer::KDot11Frame );
+        // set RCPI
+        metaHdr->KeSetRcpi( aRcpi );
+        
+        // set the offset to the beginning of the Rx buffer from the beginning
+        // of the meta header. Note that this may be also negative
+        metaHdr->KeSetBufferOffset(
+            aBuffer
+            - reinterpret_cast<TUint8*>(metaHdr) );
+        
+        // set the offset to the beginning of the actual frame within the
+        // Rx buffer
+        metaHdr->KeSetOffsetToFrameBeginning( 
+            reinterpret_cast<const TUint8*>(aFrame)   // frame beginning
+            - aBuffer );                              // buffer beginning
+        
+        // complete
+        const TDataBuffer* KMetaHdr ( metaHdr );
+        aCtxImpl.iUmac.MgmtDataReceiveComplete( KMetaHdr, 1 );
+        }
+    else
+        {
+        // no memory available for the meta header. In this case we have no
+        // other choice than to discard the received frame. 
+        aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+        OsTracePrint( KWarningLevel | KRxFrame, (TUint8*)
+            ("UMAC: WlanDot11Associated::OnManagementActionFrameRx: WARNING: no memory for meta hdr => abort rx") );            
+        }
+    }
+        
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TAny* WlanDot11Associated::RequestForBuffer( 
+    WlanContextImpl& aCtxImpl,
+    TUint16 aLength )
+    {
+    return aCtxImpl.GetRxBuffer( aLength );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::ReceivePacket( 
+    WlanContextImpl& aCtxImpl, 
+    WHA::TStatus aStatus,
+    const void* aFrame,
+    TUint16 aLength,
+    WHA::TRate /*aRate*/,
+    WHA::TRcpi aRcpi,
+    WHA::TChannelNumber /*aChannel*/,
+    TUint8* aBuffer,
+    TUint32 aFlags )
+    {
+    SDataMpduHeader* hdr( 
+        reinterpret_cast<SDataMpduHeader*>(const_cast<TAny*>(aFrame)) );
+
+    if ( aStatus == WHA::KSuccess )
+        {
+        // packet reception success lets see what type of frame we have
+        OsTracePrint( KRxFrame, 
+            (TUint8*)
+            ("UMAC: WlanDot11Associated::ReceivePacket:frame receive success, frame type: 0x%02x"), 
+            hdr->iHdr.iFrameControl.iType );
+
+        if ( ( hdr->iHdr.iFrameControl.iType == E802Dot11FrameTypeData )
+             || ( hdr->iHdr.iFrameControl.iType == E802Dot11FrameTypeQosData ) )
+            {
+            OnDataFrameRx( aCtxImpl, aFrame, aLength, aFlags, aRcpi, aBuffer );
+            
+            if ( aCtxImpl.InsertNewRcpiIntoPredictor( os_systemTime(), aRcpi ) )
+                {
+                // indicate WLAN signal loss prediction to WLAN Mgmt Client
+                OnInDicationEvent( aCtxImpl, ESignalLossPrediction );
+                }
+            }        
+        else if ( hdr->iHdr.iFrameControl.iType 
+            == E802Dot11FrameTypeManagementAction )
+            {
+            OnManagementActionFrameRx( 
+                aCtxImpl, 
+                aFrame, 
+                aLength, 
+                aRcpi, 
+                aBuffer );
+
+            if ( aCtxImpl.InsertNewRcpiIntoPredictor( os_systemTime(), aRcpi ) )
+                {
+                // indicate WLAN signal loss prediction to WLAN Mgmt Client
+                OnInDicationEvent( aCtxImpl, ESignalLossPrediction );
+                }
+            }
+        else if ( hdr->iHdr.iFrameControl.iType 
+            == E802Dot11FrameTypeDeauthentication )
+            {
+            OnDeauthenticateFrameRx( aCtxImpl, aBuffer );
+            }
+        else if ( hdr->iHdr.iFrameControl.iType 
+            == E802Dot11FrameTypeDisassociation )
+            {
+            OnDisassociateFrameRx( aCtxImpl, aBuffer );
+            }
+        else if ( hdr->iHdr.iFrameControl.iType 
+            == E802Dot11FrameTypeBeacon )
+            {
+            OnBeaconFrameRx( aCtxImpl, aFrame, aLength, aRcpi, aBuffer );
+            }
+        else if ( hdr->iHdr.iFrameControl.iType 
+            == E802Dot11FrameTypeProbeResp )
+            {
+            OnProbeResponseFrameRx( aCtxImpl, aFrame, aLength, aRcpi, aBuffer );
+            }
+        else
+            {
+            OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+                ("UMAC: WlanDot11Associated::ReceivePacket: unsupported frame type: 0x%02x"), 
+                hdr->iHdr.iFrameControl.iType );            
+
+            // release the Rx buffer
+            aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+            }
+        }
+    else if ( aStatus == WHA::KDecryptFailure )
+        {
+        // decryption error
+        OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+            ("UMAC: WlanDot11Associated::ReceivePacket: decrypt error for frame:"), hdr->iHdr );    
+
+        OnInDicationEvent( aCtxImpl, EWepDecryptFailure );
+
+        // release the Rx buffer
+        aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+        }
+    else if ( aStatus == WHA::KMicFailure )
+        {
+        // MIC failed
+        OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+            ("UMAC: WlanDot11Associated::ReceivePacket: MIC error for frame:"), hdr->iHdr );    
+
+        // address 1 is always the DA in our case
+        OnInDicationEvent( aCtxImpl, 
+            (IsGroupBitSet( hdr->iHdr.iAddress1 )) 
+            ? EGroupKeyMicFailure : EPairwiseKeyMicFailure 
+            );
+
+        // release the Rx buffer
+        aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+        }    
+    else
+        {
+        // packet rececption failed 
+        OsTracePrint( KRxFrame | KWarningLevel, (TUint8*)
+            ("UMAC: WlanDot11Associated::ReceivePacket: frame receive failure"));
+
+        // release the Rx buffer
+        aCtxImpl.iUmac.MarkRxBufFree( aBuffer );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::EncryptTxFrames( 
+    WlanContextImpl& aCtxImpl,
+    const TDataBuffer& aDataBuffer ) const
+    {
+    TBool encrypt ( EFalse );
+
+    if ( aDataBuffer.KeFlags() & TDataBuffer::KTxFrameMustNotBeEncrypted )
+        {
+        // our client has instructed us not the encrypt this frame under
+        // any circumstances. EFalse will be returned. 
+        // No further action needed
+        }
+    else
+        {
+        const WHA::TKeyType pairwiseKey ( aCtxImpl.PairWiseKeyType() );
+        const WHA::TKeyType groupKey ( aCtxImpl.GroupKeyType() );
+    
+        if ( pairwiseKey != WHA::EKeyNone )
+            {
+            // pairwise key set => use encryption
+            encrypt = ETrue;
+            }
+        else
+            {
+            // pairwise key not set
+            
+            if ( groupKey == WHA::EWepGroupKey )
+                {
+                // wep group key set => use encryption
+                encrypt = ETrue;
+                }        
+            }
+        }
+        
+    return encrypt;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TUint WlanDot11Associated::DecryptHdrOffset( 
+    WlanContextImpl& aCtxImpl, 
+    TUint32 aFlags ) const
+    {
+    TUint offset( 0 );
+
+    const TUint32 encryption ( aFlags & KReceivePacketEncryptionMask );
+
+    if ( aCtxImpl.WHASettings().iCapability & WHA::SSettings::KNoSecHdrAndTrailer )
+        {
+        // no security header is present on this sw layer. It is removed
+        // on lower layers; when necessary.
+        // We will return zero, so no further actions
+        }
+    else
+        {
+        // IV and/or Ext IV or CCMP header is present
+        // on this sw layer; when applicable
+        
+        if ( encryption == WHA::KEncryptAes )
+            {
+            offset = KCcmpHeaderLength;
+            }
+        else if ( encryption == WHA::KEncryptTkip )
+            {
+            offset = KWepIVLength + KWepExtendedIVLength;  
+            }
+        else if ( encryption == WHA::KEncryptWep )
+            {
+            offset = KWepIVLength;
+            }
+        else if ( encryption == WHA::KEncryptWapi )
+            {
+            offset = KWapiHeaderLength;
+            }
+        else
+            {
+            // frame not encrypted; returns zero
+            }        
+        }
+
+    return offset;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TUint WlanDot11Associated::DecryptTrailerOffset( 
+    WlanContextImpl& aCtxImpl, 
+    TUint32 aFlags ) const
+    {
+    TUint offset( 0 );
+    
+    const TUint32 encryption ( aFlags & KReceivePacketEncryptionMask );
+
+    if ( aCtxImpl.WHASettings().iCapability & WHA::SSettings::KNoSecHdrAndTrailer )
+        {
+        // no security trailer is present on this sw layer. It is removed
+        // on lower layers; when necessary.
+        // We will return zero, so no further actions
+        }
+    else
+        {
+        // ICV and/or MIC field is present on this sw layer; when applicable
+    
+        if ( encryption == WHA::KEncryptAes )
+            {
+            offset = KMicLength;
+            }
+        else if ( encryption == WHA::KEncryptTkip )
+            {
+            offset = KMicLength + KWEPICVLength;
+            }
+        else if ( encryption == WHA::KEncryptWep )
+            {
+            offset = KWEPICVLength;
+            }
+        else if ( encryption == WHA::KEncryptWapi )
+            {
+            offset = KWapiMicLength;
+            }
+        else
+            {
+            // frame not encrypted; returns zero
+            }        
+        }
+
+    return offset;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TUint WlanDot11Associated::ComputeEncryptionOffsetAmount(
+    const WlanContextImpl& aCtxImpl,
+    const TDataBuffer& aDataBuffer ) const
+    {
+    TUint offset( 0 );
+
+    if ( // our client has instructed us not the encrypt this frame under
+         // any circumstances OR
+         ( aDataBuffer.KeFlags() & TDataBuffer::KTxFrameMustNotBeEncrypted ) ||
+         // no space is reserved for security header on this sw layer. It is
+         // done on lower layers; when necessary.
+         ( aCtxImpl.WHASettings().iCapability & 
+           WHA::SSettings::KNoSecHdrAndTrailer ) )
+        {
+        // We will return zero, so no further actions
+        }
+    else
+        {
+        // encryption is allowed if relevant and
+        // space is reserved for IV and/or Ext IV or CCMP header
+        // on this sw layer; when necessary
+
+        const WHA::TKeyType groupKey( aCtxImpl.GroupKeyType() );
+        const WHA::TKeyType pairwiseKey( aCtxImpl.PairWiseKeyType() );
+
+        if ( pairwiseKey == WHA::EAesPairWiseKey )
+            {
+            offset = KCcmpHeaderLength;
+            }
+        else if ( pairwiseKey == WHA::ETkipPairWiseKey )
+            {
+            offset = KWepIVLength + KWepExtendedIVLength;
+            }
+        else if ( pairwiseKey == WHA::EWepPairWiseKey )
+            {
+            offset = KWepIVLength;
+            }
+        else if ( pairwiseKey == WHA::EWapiPairWiseKey )
+            {
+            offset = KWapiHeaderLength;
+            }
+        else
+            {
+            // don't care of anything else
+            }
+
+        if ( !offset )
+            {
+            // no encryption used based on pairwise key presence
+            // check for WEP groupkey presence
+            if ( groupKey == WHA::EWepGroupKey )
+                {
+                offset = KWepIVLength;
+                }
+            else
+                {
+                // don't care of anything else as group key encyption is not 
+                // supported for the other key types. For them we always have 
+                // a pairwise key
+                }
+            }        
+        }
+
+    return offset;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TUint WlanDot11Associated::EncryptTrailerLength(
+    WlanContextImpl& aCtxImpl,
+    const TDataBuffer& aDataBuffer ) const
+    {
+    TUint length( 0 );
+
+    if ( // our client has instructed us not the encrypt this frame under
+         // any circumstances OR
+         ( aDataBuffer.KeFlags() & TDataBuffer::KTxFrameMustNotBeEncrypted ) ||
+         // no space is reserved for security header on this sw layer. It is
+         // done on lower layers; when necessary.
+         ( aCtxImpl.WHASettings().iCapability & 
+           WHA::SSettings::KNoSecHdrAndTrailer ) )
+        {
+        // We will return zero, so no further actions
+        }
+    else
+        {
+        // encryption is allowed if relevant and
+        // space is reserved for ICV and/or MIC
+        // on this sw layer; when necessary
+
+        const WHA::TKeyType groupKey( aCtxImpl.GroupKeyType() );
+        const WHA::TKeyType pairwiseKey( aCtxImpl.PairWiseKeyType() );    
+
+        if ( pairwiseKey == WHA::EAesPairWiseKey )
+            {
+            length = KMicLength;
+            }
+        else if ( pairwiseKey == WHA::ETkipPairWiseKey )    
+            {
+            length = KMicLength + KWEPICVLength;
+            }
+        else if ( pairwiseKey == WHA::EWepPairWiseKey )
+            {
+            length = KWEPICVLength;
+            }
+        else if ( pairwiseKey == WHA::EWapiPairWiseKey )
+            {
+            length = KWapiMicLength;
+            }
+        else
+            {
+            // don't care of anything else
+            }
+
+        if ( !length )
+            {
+            // no pairwise key present
+            // check for groupkey
+            if ( groupKey == WHA::EWepGroupKey )
+                {
+                length = KWEPICVLength;
+                }
+            else
+                {
+                // don't care of anything else as group key encyption is not 
+                // supported for the other key types. For them we always have 
+                // a pairwise key
+                }
+            }        
+        }
+
+    return length;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TUint WlanDot11Associated::ComputeQosOffsetAmount(
+    WlanContextImpl& aCtxImpl ) const
+    {
+    const TUint KNoQosHeader( 0 );
+    
+    if ( aCtxImpl.QosEnabled() )        
+        {
+        return sizeof( T802Dot11QosControl );
+        }
+    else
+        {
+        return KNoQosHeader;
+        }    
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::EncapsulateEthernetFrame(
+    WlanContextImpl& aCtxImpl,
+    TWlanUserTxDataCntx& aDataCntx,
+    TDataBuffer& aDataBuffer,
+    TUint16& aEtherType ) const
+    {
+    TUint8* etherFrameBeginning ( aDataBuffer.GetBuffer() );
+
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: WlanDot11Associated::EncapsulateEthernetFrame: supplied ether frame start address: 0x%08x"),
+        reinterpret_cast<TUint32>(etherFrameBeginning) );
+
+    // start of dot11 frame
+    SDataFrameHeader* dot11_dataframe_hdr ( NULL );
+
+    // start of ethernet frame
+    const SEthernetHeader* ether_hdr 
+        = reinterpret_cast<const SEthernetHeader*>(etherFrameBeginning);
+
+    // determine Ethernet type
+    aEtherType = ether_hdr->Type();
+
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: ether type: 0x%04x"),
+        aEtherType );    
+
+    // compute space required for encryption header
+    // after dot11 radio header and before data payload
+    const TUint encryption_offset = ( 
+        ComputeEncryptionOffsetAmount( aCtxImpl, aDataBuffer ) );
+
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: encryption_offset: %d"),
+        encryption_offset );    
+
+    const TUint32 ether_offset = (KMacAddressLength << 1);
+    
+    // take a backup copy of the destination and source addresses from the
+    // ethernet frame as they will get overwritten
+    
+    TMacAddress da;
+    os_memcpy( 
+        reinterpret_cast<TUint8*>(&da), 
+        etherFrameBeginning, 
+        sizeof( TMacAddress ) );
+    TMacAddress sa;
+    os_memcpy( 
+        reinterpret_cast<TUint8*>(&sa), 
+        etherFrameBeginning + sizeof( TMacAddress ), 
+        sizeof( TMacAddress ) );
+
+    // compute space possibly required at the end of the dot11 mac
+    // header for the QoS control field, which is required for QoS data frames
+    // This will be needed (i.e. the qosOffset will be > 0) if QoS is enabled
+    const TUint qosOffset = ComputeQosOffsetAmount( aCtxImpl );
+    // the mac header of HT QoS data frames also has an additional field,
+    // so determine if that field needs to be present and hence has a non-zero
+    // length
+    const TUint KHtControlOffset ( aCtxImpl.HtSupportedByNw() ? 
+            KHtControlFieldLength : 0 );
+    
+    if ( qosOffset )
+        {
+        // a QoS data frame
+        
+        OsTracePrint( KWsaTxDetails | KQos, (TUint8*)
+            ("UMAC: qos data frame"));    
+
+        SQosDataFrameHeader* dot11QosDataFrameHdr = 
+            reinterpret_cast<SQosDataFrameHeader*>(
+                etherFrameBeginning 
+                + ether_offset
+                - sizeof( KEncapsulatingRfc1042SnapHeader )
+                - encryption_offset
+                - KHtControlOffset
+                - sizeof( SQosDataFrameHeader ) );
+
+        // construct the MAC header
+        new (dot11QosDataFrameHdr) SQosDataFrameHeader;
+        
+        // set the frame type
+        dot11QosDataFrameHdr->iHdr.iFrameControl.iType = E802Dot11FrameTypeQosData;
+        
+        // reset the QoS control field
+        // => ack policy == acknowledge && priority == best effort
+        dot11QosDataFrameHdr->ResetQosControl();
+        
+        // set the user priority
+        dot11QosDataFrameHdr->SetUserPriority( aDataBuffer.UserPriority() );
+
+        dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>(
+            dot11QosDataFrameHdr);
+
+        if ( KHtControlOffset )
+            {
+            // HT control field is present => order bit needs to be set
+            dot11QosDataFrameHdr->iHdr.SetOrderBit();
+
+            // clear the HT Control field, too
+            reinterpret_cast<SHtQosDataFrameHeader*>(
+                dot11QosDataFrameHdr)->ResetHtControl();
+            }
+        else
+            {
+            // HT control field is not present => order bit needs to be cleared
+            dot11QosDataFrameHdr->iHdr.ClearOrderBit();
+            }        
+        }
+    else
+        {
+        // a non-QoS data frame
+
+        OsTracePrint( KWsaTxDetails, (TUint8*)
+            ("UMAC: non-qos data frame"));    
+
+        dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>(
+            etherFrameBeginning 
+            + ether_offset
+            - sizeof( KEncapsulatingRfc1042SnapHeader )
+            - encryption_offset
+            - sizeof( SDataFrameHeader ) );
+
+        // construct the MAC header. In this case this also sets the frame type
+        // correctly
+        new (dot11_dataframe_hdr) SDataFrameHeader;
+        }
+
+    // set the source address
+    dot11_dataframe_hdr->iAddress2 = sa;
+
+    // set the destination address
+    DoSetTxMpduDaAddress( *dot11_dataframe_hdr, da );
+    
+    // set the To DS bit
+    if ( aCtxImpl.NetworkOperationMode() == WHA::EBSS )
+        {
+        dot11_dataframe_hdr->SetToDsBit();        
+        // set the BSS ID
+        dot11_dataframe_hdr->iAddress1 = aCtxImpl.GetBssId();
+        }
+    else
+        {
+        dot11_dataframe_hdr->ClearToDsBit();
+        // set the BSS ID
+        dot11_dataframe_hdr->iAddress3 = aCtxImpl.GetBssId();
+        }
+        
+    // determine if the frame needs to be encrypted
+    if ( EncryptTxFrames( aCtxImpl, aDataBuffer ) )
+        {
+        dot11_dataframe_hdr->SetWepBit();
+        }
+    else
+        {
+        dot11_dataframe_hdr->ClearWepBit();
+        }
+        
+    // set the snap header to correct location. 
+    os_memcpy( 
+        reinterpret_cast<TUint8*>(dot11_dataframe_hdr)
+        + sizeof( SDataFrameHeader )
+        + qosOffset
+        + KHtControlOffset
+        // space occupied by encryption header(s)
+        + encryption_offset,  
+        &KEncapsulatingRfc1042SnapHeader,
+        sizeof( KEncapsulatingRfc1042SnapHeader ) );        
+
+    // clear the area reserved for IV etc, when necessary
+    if ( encryption_offset )
+        {
+        os_memset( 
+            reinterpret_cast<TUint8*>(dot11_dataframe_hdr) 
+                + sizeof( SDataFrameHeader ) 
+                + qosOffset
+                + KHtControlOffset,
+            0,
+            encryption_offset );           
+        }
+
+    // compute padding required for encryption trailer (ICV, MIC etc)
+    const TUint encryptTrailerLength = (
+        EncryptTrailerLength( aCtxImpl, aDataBuffer ) );
+    
+    // clear the area reserved for encryption trailer, when necessary
+    if ( encryptTrailerLength )
+        {
+        os_memset( 
+            reinterpret_cast<TUint8*>(dot11_dataframe_hdr) 
+            + sizeof( SDataFrameHeader )
+            + qosOffset
+            + KHtControlOffset
+            + encryption_offset
+            + sizeof( SSnapHeader )  
+            + aDataBuffer.GetLength() - ether_offset,
+            0,
+            encryptTrailerLength );                   
+        }
+    
+    // calculate frame length 
+    const TUint length_of_frame = 
+        // MAC header length
+        sizeof( SDataFrameHeader )
+        // length of possibly existing QoS control field 
+        + qosOffset
+        // length of possibly existing HT control field
+        + KHtControlOffset
+        // SNAP header length
+        + sizeof( SSnapHeader ) 
+        // length of ethernet payload (including ether type)
+        + aDataBuffer.GetLength() - ether_offset
+        // encryption header length
+        + encryption_offset
+        // encryption trailer length
+        + encryptTrailerLength;
+
+    // we now have a dot11 frame ready to be sent
+    aDataCntx.Dot11FrameReady( 
+        reinterpret_cast<TUint8*>(dot11_dataframe_hdr),
+        length_of_frame );
+
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: length_of_frame (excl. fcs): %d"),
+        length_of_frame );
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: frame start address: 0x%08x"),
+        reinterpret_cast<TUint32>(dot11_dataframe_hdr) );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::EncapsulateSnapFrame(
+    WlanContextImpl& aCtxImpl,
+    TWlanUserTxDataCntx& aDataCntx,
+    TDataBuffer& aDataBuffer,
+    TBool aEncrypt,
+    TUint aEncryptionOffset,
+    TUint aEncryptTrailerLength,
+    TUint aQosOffset,
+    TUint aHtControlOffset ) const
+    {
+    // extract start of frame. The frame starts with a SNAP header
+    TUint8* snapFrameBeginning ( aDataBuffer.GetBuffer() );
+
+    // start of dot11 frame
+    SDataFrameHeader* dot11_dataframe_hdr( NULL );
+    
+    if ( aQosOffset )
+        {
+        OsTracePrint( KWsaTxDetails | KQos, (TUint8*)
+            ("UMAC: qos data frame"));    
+
+        SQosDataFrameHeader* dot11QosDataFrameHdr( 
+            reinterpret_cast<SQosDataFrameHeader*>(
+                snapFrameBeginning 
+                - aEncryptionOffset
+                - aHtControlOffset
+                - sizeof( SQosDataFrameHeader )) );
+
+        // construct the MAC header
+        new (dot11QosDataFrameHdr) SQosDataFrameHeader;
+        
+        // set the frame type
+        dot11QosDataFrameHdr->iHdr.iFrameControl.iType = E802Dot11FrameTypeQosData;
+        
+        // reset the QoS control field
+        // => ack policy == acknowledge && priority == best effort
+        dot11QosDataFrameHdr->ResetQosControl();        
+
+        // set the user priority
+        dot11QosDataFrameHdr->SetUserPriority( aDataBuffer.UserPriority() );
+
+        dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>(
+            dot11QosDataFrameHdr);
+
+        if ( aHtControlOffset )
+            {
+            // HT control field is present => order bit needs to be set
+            dot11QosDataFrameHdr->iHdr.SetOrderBit();
+            // clear the HT Control field, too
+            reinterpret_cast<SHtQosDataFrameHeader*>(
+                dot11QosDataFrameHdr)->ResetHtControl();
+            }
+        else
+            {
+            // HT control field is not present => order bit needs to be cleared
+            dot11QosDataFrameHdr->iHdr.ClearOrderBit();
+            }        
+        }
+    else
+        {
+        OsTracePrint( KWsaTxDetails | KQos, (TUint8*)
+            ("UMAC: non-qos data frame"));    
+
+        dot11_dataframe_hdr = reinterpret_cast<SDataFrameHeader*>(
+            snapFrameBeginning 
+            - aEncryptionOffset
+            - sizeof( SDataFrameHeader ) );
+
+        // construct the MAC header. In this case this also sets the frame type
+        // correctly
+        new (dot11_dataframe_hdr) SDataFrameHeader;
+        }
+
+    // set the source address
+    dot11_dataframe_hdr->iAddress2 = aCtxImpl.iWlanMib.dot11StationId;
+
+    // set the destination address
+    DoSetTxMpduDaAddress( *dot11_dataframe_hdr, 
+        aDataBuffer.KeDestinationAddress() );
+    
+    // set the To DS bit
+    if ( aCtxImpl.NetworkOperationMode() == WHA::EBSS )
+        {
+        dot11_dataframe_hdr->SetToDsBit();        
+        // set the BSS ID
+        dot11_dataframe_hdr->iAddress1 = aCtxImpl.GetBssId();
+        }
+    else
+        {
+        dot11_dataframe_hdr->ClearToDsBit();
+        // set the BSS ID
+        dot11_dataframe_hdr->iAddress3 = aCtxImpl.GetBssId();
+        }
+        
+    // determine if the frame needs to be encrypted
+    if ( aEncrypt )
+        {
+        dot11_dataframe_hdr->SetWepBit();
+        }
+    else
+        {
+        dot11_dataframe_hdr->ClearWepBit();
+        }
+
+    // clear the area reserved for IV etc, when necessary
+    if ( aEncryptionOffset )
+        {
+        os_memset( 
+            reinterpret_cast<TUint8*>(dot11_dataframe_hdr) 
+                + sizeof( SDataFrameHeader ) 
+                + aQosOffset
+                + aHtControlOffset,
+            0,
+            aEncryptionOffset );           
+        }
+    
+    // clear the area reserved for encryption trailer, when necessary
+    if ( aEncryptTrailerLength )
+        {
+        os_memset( 
+            reinterpret_cast<TUint8*>(dot11_dataframe_hdr) 
+            + sizeof( SDataFrameHeader )
+            + aQosOffset
+            + aHtControlOffset
+            + aEncryptionOffset
+            + aDataBuffer.GetLength(),
+            0,
+            aEncryptTrailerLength );                   
+        }
+
+    // calculate frame length
+    const TUint length_of_frame = 
+        // MAC header length
+        sizeof( SDataFrameHeader ) +
+        // length of possibly existing QoS control field 
+        aQosOffset + 
+        // length of possibly existing HT control field
+        aHtControlOffset +
+        // payload (including SNAP header)
+        aDataBuffer.GetLength()
+        // encryption header length
+        + aEncryptionOffset
+        // encryption trailer length
+        + aEncryptTrailerLength;
+
+    // we now have a dot11 frame ready to be sent
+    aDataCntx.Dot11FrameReady( 
+        reinterpret_cast<TUint8*>(dot11_dataframe_hdr),
+        length_of_frame );
+
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: length_of_frame: %d"),
+        length_of_frame );
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: frame start address: 0x%08x"),
+        reinterpret_cast<TUint32>(dot11_dataframe_hdr) );
+    // trace the dot11 frame header
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: Encapsulated prorietary SNAP Tx frame:"), 
+        *(reinterpret_cast<Sdot11MacHeader*>(dot11_dataframe_hdr))); 
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::SetDot11FrameToTxBuffer(
+    const WlanContextImpl& aCtxImpl,
+    TWlanUserTxDataCntx& aDataCntx,
+    TDataBuffer& aDataBuffer ) const
+    {
+    OsTracePrint( KWsaTxDetails, (TUint8*)
+        ("UMAC: WlanDot11Associated::SetDot11FrameToTxBuffer") );    
+
+    if ( aCtxImpl.HtSupportedByNw() && aCtxImpl.QosEnabled() )
+        {
+        // in this case we need to insert the HT Control field to the
+        // otherwise ready 802.11 MAC frame
+
+        const TUint KOrigLengthOfFrame = aDataBuffer.GetLength();
+        const TUint KMgmtFrameMacHdrLen = sizeof( SManagementFrameHeader );
+        TUint8* KFrameStart = aDataBuffer.GetBuffer();
+
+        os_memcpy( 
+            KFrameStart + 
+            KMgmtFrameMacHdrLen +
+            KHtControlFieldLength,
+            KFrameStart + 
+            KMgmtFrameMacHdrLen,
+            KOrigLengthOfFrame - KMgmtFrameMacHdrLen );
+
+        // clear the added HT Control field
+        reinterpret_cast<SHtManagementFrameHeader*>( 
+            KFrameStart)->ResetHtControl();
+        // update frame length
+        aDataBuffer.KeSetLength( KOrigLengthOfFrame + KHtControlFieldLength );
+        // as the HT control field is present the order bit needs to be set
+        reinterpret_cast<SHtManagementFrameHeader*>( 
+            KFrameStart)->iMgmtFrameHdr.SetOrderBit();        
+        }
+    
+    // we now have a dot11 frame ready to be sent
+    aDataCntx.Dot11FrameReady( 
+        aDataBuffer.GetBuffer(), 
+        aDataBuffer.GetLength() );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::EncapsulateFrame(
+    WlanContextImpl& aCtxImpl,
+    TWlanUserTxDataCntx& aDataCntx,
+    TDataBuffer& aDataBuffer,
+    TUint16& aEtherType )
+    {
+    const TDataBuffer::TFrameType KFrameType( aDataBuffer.FrameType() );
+    
+    OsTracePrint( KWsaTx, (TUint8*)
+        ("UMAC: WlanDot11Associated::EncapsulateFrame: frame type: %d"),
+        KFrameType );
+    
+    if ( KFrameType == TDataBuffer::KEthernetFrame || 
+         KFrameType == TDataBuffer::KEthernetTestFrame )
+        {
+        // ethernet II frame in the buffer for tx
+
+        EncapsulateEthernetFrame( 
+            aCtxImpl, 
+            aDataCntx, 
+            aDataBuffer, 
+            aEtherType );
+        }
+    else if ( KFrameType == TDataBuffer::KSnapFrame )
+        {
+        // frame beginning with a SNAP header in the buffer for tx
+
+        EncapsulateSnapFrame( 
+            aCtxImpl, 
+            aDataCntx, 
+            aDataBuffer,
+            EncryptTxFrames( aCtxImpl, aDataBuffer ),
+            ComputeEncryptionOffsetAmount( aCtxImpl, aDataBuffer ),
+            EncryptTrailerLength( aCtxImpl, aDataBuffer ),
+            ComputeQosOffsetAmount( aCtxImpl ),
+            aCtxImpl.HtSupportedByNw() ? 
+                KHtControlFieldLength : 
+                0 );
+        }
+    else if ( KFrameType == TDataBuffer::KDot11Frame )
+        {
+        // ready made 802.11 frame in the buffer for tx
+
+        SetDot11FrameToTxBuffer( aCtxImpl, aDataCntx, aDataBuffer );
+        }
+    else
+        {
+        // not supported
+        OsTracePrint( KErrorLevel, (TUint8*)("UMAC: frame_type: %d"),
+            KFrameType );
+        OsAssert( (TUint8*)("UMAC: panic"),(TUint8*)(WLAN_FILE), __LINE__ );                
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::TxData( 
+    WlanContextImpl& aCtxImpl,
+    TDataBuffer& aDataBuffer,
+    TBool aMore )
+    {
+    TWlanUserTxDataCntx& data_cntx( aCtxImpl.GetTxDataCntx() );
+    
+    TBool stateChange( EFalse );
+
+    if ( (aCtxImpl.ProtocolStackTxDataAllowed()) )
+        {
+        // protocol stack tx data allowed
+        // now construct a dot11 frame from databuffer to storage
+
+        TUint16 etherType( 0 ); // initial value: not relevant
+        
+        // construct the frame
+        EncapsulateFrame( aCtxImpl, data_cntx, aDataBuffer, etherType );
+
+        // dot11 frame ready to be sent so push it to the packet sceduler
+
+        // start of dot11 frame to send
+        const TUint8* start_of_frame( 
+            data_cntx.StartOfFrame() );
+
+        // select correct tx queue
+        const WHA::TQueueId queue_id( 
+            QueueId( aCtxImpl, start_of_frame ) );
+
+        // push the frame to packet scheduler for transmission
+        aCtxImpl.PushPacketToPacketScheduler(
+            start_of_frame,
+            data_cntx.LengthOfFrame(),
+            queue_id,
+            E802Dot11FrameTypeData,
+            &aDataBuffer,
+            aMore,
+            OutgoingMulticastDataFrame( 
+                reinterpret_cast<const SDataFrameHeader*>( start_of_frame ) ) );
+            // now just wait for the scheduler to call completion methods
+            
+        // check if we need to change power mgmt mode because of frame Tx
+        const TPowerMgmtModeChange KPowerMgmtModeChange ( 
+            aCtxImpl.OnFrameTx( queue_id, etherType ) );
+        
+        // if any change change is needed regarding our power mgmt mode,
+        // proceed with it
+        stateChange = PowerMgmtModeChange( aCtxImpl, KPowerMgmtModeChange );        
+        }
+    else
+        {
+        // protocol stack tx data not allowed
+
+#ifndef NDEBUG
+        // programming error
+        OsTracePrint( KErrorLevel, (TUint8*)
+            ("UMAC: Tx attempted when it's not allowed") );
+        OsAssert( (TUint8*)("UMAC: panic"), (TUint8*)(WLAN_FILE), __LINE__ );
+#else
+        aCtxImpl.iUmac.OnTxProtocolStackDataComplete( 
+            KErrNone,
+            &aDataBuffer );        
+#endif        
+        }
+
+    return stateChange;        
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::OnPacketSendComplete(
+    WlanContextImpl& aCtxImpl, 
+    WHA::TStatus aStatus,
+    TUint32 aPacketId,
+    WHA::TRate aRate,
+    TUint32 /*aPacketQueueDelay*/,
+    TUint32 aMediaDelay,
+    TUint aTotalTxDelay,
+    TUint8 aAckFailures,
+    WHA::TQueueId aQueueId,
+    WHA::TRate aRequestedRate,
+    TBool aMulticastData )
+    {
+    if ( aPacketId == E802Dot11FrameTypeData ||
+         aPacketId == E802Dot11FrameTypeDataEapol )
+        {
+        // update data frame statistics
+        UpdateTxDataFrameStatistics( 
+            aCtxImpl,
+            aQueueId, 
+            aStatus, 
+            aMulticastData, 
+            aAckFailures,
+            aMediaDelay,
+            aTotalTxDelay );
+        }
+    else if ( aPacketId == E802Dot11FrameTypeQosDataNull )        
+        {
+        // inform Null Data frame sending controller of QoS Null data Tx 
+        // completion; successful or not
+        aCtxImpl.OnQosNullDataTxCompleted();
+        }        
+    else if ( aPacketId == E802Dot11FrameTypeDataNull )        
+        {
+        // inform Null Data frame sending controller of Null data Tx 
+        // completion; successful or not
+        aCtxImpl.OnNullDataTxCompleted();
+        }        
+
+    if ( aStatus == WHA::KSuccess )
+        {
+        aCtxImpl.OnTxCompleted( aRate, ETrue, aQueueId, aRequestedRate );
+    
+        aCtxImpl.ResetFailedTxPacketCount();
+        DoRegainedBSSIndication( aCtxImpl );
+
+        if ( aPacketId == E802Dot11FrameTypeData ||
+             aPacketId == E802Dot11FrameTypeDataEapol ||
+             aPacketId == E802Dot11FrameTypeTestFrame )
+            {
+            // inform Null Data frame sending controller of successful
+            // data frame Tx completion
+            aCtxImpl.OnDataTxCompleted( 
+                aPacketId == E802Dot11FrameTypeDataEapol ?
+                // as EAPOL and WAI frames or not really Voice data (we just
+                // send them with Voice priority in WMM nw), handle them
+                // here as Best Effort (Legacy)
+                WHA::ELegacy : 
+                aQueueId );
+            }
+        }
+    else if ( aStatus == WHA::KErrorLifetimeExceeded && !aAckFailures )
+        {
+        // the packet was discarded by WLAN PDD without any Tx attempts
+        // So this is not a Tx failure and we don't need to take
+        // any further actions
+        OsTracePrint( KWsaTxDetails, (TUint8*)
+            ("UMAC: WlanDot11Associated::OnPacketSendComplete: packet expired in PDD without any Tx attempts)"));
+        }
+    else
+        {
+        // an actual Tx failure has occurred
+        
+        aCtxImpl.OnTxCompleted( aRate, EFalse, aQueueId, aRequestedRate );
+    
+        aCtxImpl.IncrementFailedTxPacketCount();
+
+        // if we have failed to send more than threshold number of 
+        // consecutive packets, send Consecutive Tx Failures indication to 
+        // WLAN Mgmt Client - unless already sent
+        if ( aCtxImpl.FailedTxPacketCount() > 
+             aCtxImpl.iWlanMib.iFailedTxPacketCountThreshold )
+            {
+            DoConsecutiveTxFailuresIndication( aCtxImpl );
+            aCtxImpl.ResetFailedTxPacketCount();
+            }        
+        }
+    
+    aCtxImpl.iUmac.OnTxDataSent();
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::DoConsecutiveBeaconsLostIndication( 
+    WlanContextImpl& aCtxImpl )
+    {
+    if ( aCtxImpl.OnConsecutiveBeaconsLost() )
+        {
+        OnInDicationEvent( aCtxImpl, EConsecutiveBeaconsLost );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+//
+void WlanDot11Associated::DoConsecutiveTxFailuresIndication( 
+    WlanContextImpl& aCtxImpl )
+    {
+    if ( aCtxImpl.OnConsecutiveTxFailures() )
+        {
+        OnInDicationEvent( aCtxImpl, EConsecutiveTxFailures );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::DoRegainedBSSIndication( 
+    WlanContextImpl& aCtxImpl )
+    {
+    if ( aCtxImpl.OnBssRegained() )
+        {
+        OnInDicationEvent( aCtxImpl, EBSSRegained );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::AddMulticastAddr(
+    WlanContextImpl& aCtxImpl,
+    const TMacAddress& aMacAddr )
+    {
+    TBool stateTransitionOccurred( EFalse );
+    
+    OsTracePrint( 
+        KWlmCmdDetails, 
+        (TUint8*)
+        ("UMAC: WlanDot11Associated::AddMulticastAddr(): addr to be added:"),
+        aMacAddr);
+
+    if ( aCtxImpl.MulticastFilteringDisAllowed() )
+        {
+        OsTracePrint( 
+            KWlmCmdDetails, 
+            (TUint8*)
+            ("UMAC: WlanDot11Associated::AddMulticastAddr(): Multicast filtering disallowed"));
+            
+        OnOidComplete( aCtxImpl, KErrGeneral );        
+        }
+    else
+        {        
+        if ( aCtxImpl.WHASettings().iNumOfGroupTableEntrys > 
+             aCtxImpl.MulticastAddressCount() )
+            {
+            // wha layer is able to take in an address
+            
+            // 1st try to add the address to our own internal bookkeeping
+            WlanContextImpl::TGroupAddStatus addStatus = 
+                aCtxImpl.AddMulticastAddress( aMacAddr );
+
+            switch ( addStatus )
+                {
+                case WlanContextImpl::EOk:
+                    OsTracePrint( 
+                        KWlmCmdDetails, 
+                        (TUint8*)
+                        ("UMAC: WlanDot11Associated::AddMulticastAddr(): Address will be added to the MIB"));
+                    // the address needed to be added and adding went ok.
+                    // Now update the group addresses MIB
+                    stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl ); 
+                    break;
+                case WlanContextImpl::EAlreadyExists: 
+                    OsTracePrint( 
+                        KWlmCmdDetails, 
+                        (TUint8*)
+                        ("UMAC: WlanDot11Associated::AddMulticastAddr(): Address already exists"));
+                    // the specified address already exists so there's no need
+                    // to update the group addresses MIB
+                    // just complete the request with OK status
+                    OnOidComplete( aCtxImpl );
+                    stateTransitionOccurred = EFalse;           
+                    break;
+                case WlanContextImpl::EFull:
+                    OsTracePrint( 
+                        KWlmCmdDetails, 
+                        (TUint8*)
+                        ("UMAC: WlanDot11Associated::AddMulticastAddr(): Internal address table full; disallow multicast filtering"));
+                    // we are not able to take in any more addresses.
+                    // We will totally disable the multicast filtering
+                    // and we won't allow it to be enabled any more during 
+                    // the current nw connection
+                    //
+                    aCtxImpl.ResetMulticastAddresses();               
+                    aCtxImpl.MulticastFilteringDisAllowed( ETrue );
+                    stateTransitionOccurred = 
+                        SetGroupAddressesTableMib( aCtxImpl );
+                    break;
+                default:
+                    // programming error
+                    OsTracePrint( KErrorLevel, (TUint8*)
+                        ("UMAC: addStatus: %d"), addStatus );
+                    OsAssert( (TUint8*)("UMAC: panic"), 
+                        (TUint8*)(WLAN_FILE), __LINE__ );
+                }
+            }
+        else
+            {
+            OsTracePrint( 
+                KWlmCmdDetails, 
+                (TUint8*)
+                ("UMAC: WlanDot11Associated::AddMulticastAddr(): WHA not able to accept address; disallow multicast filtering"));
+            // wha layer is not able to take in an address. Either this is one 
+            // address too many, or it doesn't support even a single address.
+            // In either case we will totally disable the multicast filtering
+            // and we won't allow it to be enabled any more during the current 
+            // nw connection
+            aCtxImpl.ResetMulticastAddresses();               
+            aCtxImpl.MulticastFilteringDisAllowed( ETrue );
+            stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl );
+            }
+        }
+
+    // signal caller whether a state transition occurred or not
+    return stateTransitionOccurred;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::RemoveMulticastAddr(
+    WlanContextImpl& aCtxImpl,
+    TBool aRemoveAll,
+    const TMacAddress& aMacAddr )
+    {
+    TBool stateTransitionOccurred( EFalse );
+    
+    OsTracePrint( 
+        KWlmCmdDetails, 
+        (TUint8*)
+        ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): addr to be removed:"),
+        aMacAddr);
+
+    if ( aCtxImpl.MulticastFilteringDisAllowed() )
+        {
+        OsTracePrint( 
+            KWlmCmdDetails, 
+            (TUint8*)
+            ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): Multicast filtering disallowed"));
+        // filtering is not allowed currently so there can't be any addresses
+        // to remove. Just complete the request with OK status            
+        OnOidComplete( aCtxImpl );        
+        }
+    else
+        {
+        if ( aRemoveAll )        
+            {
+            OsTracePrint( 
+                KWlmCmdDetails, 
+                (TUint8*)
+                ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): remove all"));
+            // remove all addresses; naturally will also disable filtering
+            aCtxImpl.ResetMulticastAddresses();
+            stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl );            
+            }
+        else
+            {            
+            // 1st remove the specified address from our own internal 
+            // bookkeeping, if it exists
+            if ( aCtxImpl.RemoveMulticastAddress( aMacAddr ) )
+                {
+                OsTracePrint( 
+                    KWlmCmdDetails, 
+                    (TUint8*)
+                    ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): removing the specified address"));
+                // it existed, so update the group addresses MIB, too
+                stateTransitionOccurred = SetGroupAddressesTableMib( aCtxImpl );                 
+                }
+            else
+                {
+                OsTracePrint( 
+                    KWlmCmdDetails, 
+                    (TUint8*)
+                    ("UMAC: WlanDot11Associated::RemoveMulticastAddr(): specified address doesn't exist, nothing to do"));
+                // it did't exist, so there's nothing to remove
+                // Just complete the request with OK status            
+                OnOidComplete( aCtxImpl );                    
+                }
+            }
+        }
+
+    // signal caller whether a state transition occurred or not
+    return stateTransitionOccurred;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::AddBroadcastWepKey(
+    WlanContextImpl& aCtxImpl,
+    TUint32 aKeyIndex,             
+    TBool aUseAsDefaulKey,                
+    TUint32 aKeyLength,                      
+    const TUint8 aKey[KMaxWEPKeyLength],
+    const TMacAddress& aMac )
+    {
+    return OnAddBroadcastWepKey( aCtxImpl, aKeyIndex, aUseAsDefaulKey, 
+        EFalse, // do NOT set as PTK
+        aKeyLength, aKey, aMac );
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::ConfigureTxQueueIfNecessary( 
+    WlanContextImpl& aCtxImpl,
+    TQueueId aQueueId,
+    TUint16 aMediumTime,
+    TUint32 aMaxTxMSDULifetime )
+    {
+    // this cast is safe as the types are effectively the same
+    const WHA::TQueueId whaQueueId = static_cast<WHA::TQueueId>(aQueueId);
+    
+    if ( aMediumTime != aCtxImpl.iWlanMib.iMediumTime[whaQueueId] ||
+         aMaxTxMSDULifetime != 
+            aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetime[whaQueueId] )
+        {
+        // at least one of the parameters for this queue is changed => a
+        // reconfiguration is needed
+        
+        // update the queue parameters. These values will be used in the
+        // queue reconfiguration
+
+        aCtxImpl.iWlanMib.iMediumTime[aQueueId] = aMediumTime;
+        aCtxImpl.iWlanMib.dot11MaxTransmitMSDULifetime[whaQueueId] = 
+            aMaxTxMSDULifetime;
+
+        OsTracePrint( KUmacDetails, (TUint8*)
+            ("UMAC: WlanDot11Associated::ConfigureTxQueueIfNecessary: reconfiguring the queue is necessary") );
+
+        // reconfigure the queue. Also request the WLAN mgmt client request
+        // to be completed
+        return ConfigureTxQueue( aCtxImpl, whaQueueId, ETrue );
+        }
+    else
+        {
+        // the provided queue parameters have not changed, so no need to
+        // reconfigure the queue
+        
+        OsTracePrint( KUmacDetails, (TUint8*)
+            ("UMAC: WlanDot11Associated::ConfigureTxQueueIfNecessary: no queue reconfigure is necessary") );
+
+        // complete the WLAN Mgmt Client request
+        OnOidComplete( aCtxImpl, KErrNone );
+
+        // signal caller that no state transition occurred
+        return EFalse;
+        }
+    }
+ 
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::SetGroupAddressesTableMib(
+    WlanContextImpl& aCtxImpl )
+    {
+    const TMacAddress* multicastAddresses( NULL );
+    const TUint32 nbrOfAddrs( 
+        aCtxImpl.GetMulticastAddresses( multicastAddresses ) );
+
+    TUint32 mibLength(  
+        // mib header length
+        WHA::Sdot11GroupAddressesTable::KHeaderSize
+        // + mib data length
+        + ( sizeof( TMacAddress ) * nbrOfAddrs ) );
+
+    // align length of MIB to 4-byte boundary
+    mibLength = Align4( mibLength );
+    
+    OsTracePrint( 
+        KWlmCmdDetails, 
+        (TUint8*)
+        ("UMAC: WlanDot11Associated::SetGroupAddressesTableMib(): mibLength: %d"), 
+        mibLength );        
+
+    // allocate memory for the mib to write
+    WHA::Sdot11GroupAddressesTable* mib 
+        = static_cast<WHA::Sdot11GroupAddressesTable*>
+        (os_alloc( mibLength )); 
+
+    if ( !mib )
+        {
+        // allocation failed
+        // simulate macnotresponding error
+        OsTracePrint( KWarningLevel, (TUint8*)
+            ("UMAC: WlanDot11Associated::SetGroupAddressesTableMib(): memory allocating failed") );
+        return DoErrorIndication( aCtxImpl, WHA::KErrorMacNotResponding );
+        }
+    
+    if ( nbrOfAddrs )
+        {
+        // at least one address exists, so enable multicast address filtering
+        mib->iEnable = ETrue;
+        }
+    else
+        {
+        // no addresses, so disable filtering
+        mib->iEnable = EFalse;
+        OsTracePrint( KWlmCmdDetails, (TUint8*)
+            ("UMAC: WlanDot11Associated::SetGroupAddressesTableMib(): no addresses; disable filtering") );
+        }
+
+    mib->iNumOfAddrs = nbrOfAddrs;
+    
+    // copy the multicast addresses after the mib header
+    os_memcpy( mib->iAddrData,
+               reinterpret_cast<TUint8*>(const_cast<TMacAddress*>(
+                    multicastAddresses)),
+               ( sizeof( TMacAddress ) * nbrOfAddrs ) );
+        
+    WlanWsaWriteMib& wha_cmd = aCtxImpl.WsaWriteMib();
+        
+    wha_cmd.Set( 
+        aCtxImpl, 
+        WHA::KMibDot11GroupAddressesTable, 
+        mibLength, 
+        mib );
+        
+    // change global state: entry procedure triggers action
+    ChangeState( aCtxImpl, 
+        *this,              // prev state
+        wha_cmd,            // next state
+        // the ACT
+        KCompleteManagementRequest
+        );   
+
+    os_free( mib ); // release the allocated memory
+
+    // signal caller that a state transition occurred
+    return ETrue;
+    }         
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::PowerMgmtModeChange(
+    WlanContextImpl& aCtxImpl,
+    TPowerMgmtModeChange aPowerMgmtModeChange )
+    {
+    TBool stateChange ( EFalse );
+    
+    if ( aPowerMgmtModeChange != ENoChange )
+        {
+        // power mgmt mode change needed
+        
+        if ( aPowerMgmtModeChange == EToActive )
+            {
+            aCtxImpl.DesiredDot11PwrMgmtMode( WHA::KPsDisable );                
+            }
+        else if ( aPowerMgmtModeChange == EToLightPs )
+            {
+            aCtxImpl.DesiredDot11PwrMgmtMode( WHA::KPsEnable );
+            aCtxImpl.SetDesiredPsModeConfig( 
+                aCtxImpl.ClientLightPsModeConfig() );                
+            }
+        else // aPowerMgmtModeChange == EToDeepPs
+            {
+            aCtxImpl.DesiredDot11PwrMgmtMode( WHA::KPsEnable );
+            aCtxImpl.SetDesiredPsModeConfig( 
+                aCtxImpl.ClientDeepPsModeConfig() );                
+            }
+        
+        if ( !(aCtxImpl.WsaCmdActive()) )
+            {
+            // proceed with the power mgmt mode change
+            stateChange = ChangePowerMgmtMode( aCtxImpl );
+            }
+        else
+            {
+            // WHA command is in progress so we must defer this access
+            aCtxImpl.RegisterEvent( KPowerMgmtTransition );
+
+            OsTracePrint( KEventDispatcher | KPwrStateTransition, 
+                (TUint8*)("UMAC: WlanDot11Associated::PowerMgmtModeChange: power mgmt mode change event registered"));                
+            }
+        }
+    
+    return stateChange;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanDot11Associated::HandleProprietarySnapRxFrame( 
+    TDataBuffer& aBuffer,
+    TBool aQosData, 
+    const TAny* const aFrame, 
+    const SAmsduSubframeHeader* aSubFrameHeader,
+    TUint aLength,
+    TUint aDecryptHeaderLen,
+    TUint aDecryptTrailerLen,
+    TUint aHtControlLen,
+    TUint8* aCopyBuffer ) const
+    {
+    OsTracePrint( KRxFrame, (TUint8*)
+        ("UMAC: WlanDot11Associated::HandleProprietarySnapRxFrame"));
+
+    // prepare received frame with proprietary SNAP header for wlan mgmt client
+    // Remove the possibly existing security header & trailer before
+    // passing the frame up
+    
+    const TUint8* frameBeginning = reinterpret_cast<const TUint8*>(aFrame);
+    const TUint KMacHdrLen( aQosData ? 
+        sizeof( SQosDataFrameHeader ) + aHtControlLen : 
+        sizeof( SDataFrameHeader ) );
+    // subframe header length is non-zero only if the frame is part of an 
+    // A-MSDU, i.e. if aCopyBuffer is not NULL
+    const TUint KSubframeHdrLen ( 
+        aCopyBuffer ? sizeof( SAmsduSubframeHeader ) : 0 );    
+    // determine subframe length
+    const TUint KSubframeLen ( 
+        aSubFrameHeader ? aSubFrameHeader->Length() : 0 );    
+
+    if ( aCopyBuffer )
+        {
+        // the frame needs to be copied to the copy buffer, which means
+        // that it is part of an A-MSDU
+
+        // 1st copy the MAC header
+        os_memcpy( aCopyBuffer, frameBeginning, KMacHdrLen );
+                
+        // then copy the subframe body following the subframe header
+        os_memcpy( 
+            aCopyBuffer 
+            + KMacHdrLen, 
+            reinterpret_cast<const TUint8*>(aSubFrameHeader) + KSubframeHdrLen,
+            KSubframeLen );
+
+        // update to point to the new location
+        frameBeginning = aCopyBuffer;
+        }
+    else
+        {
+        // no copying to the copy buffer is required
+        
+        if ( aDecryptHeaderLen )
+            {
+            // decrypt header exists. Shift the MAC header so that it
+            // overwrites the decrypt header, thus removing it
+            
+            TUint8* dest( const_cast<TUint8*>(frameBeginning) 
+                          + aDecryptHeaderLen );
+    
+            TUint copyBlockSize( aQosData ? 
+                sizeof( SQosDataFrameHeader ) + aHtControlLen : 
+                sizeof( SDataFrameHeader ) );
+    
+            os_memcpy( dest, frameBeginning, copyBlockSize );
+
+            // update to point to the new location
+            frameBeginning = dest;            
+            }
+        }
+
+#ifndef NDEBUG
+    OsTracePrint( KRxFrame, (TUint8*)
+        ("UMAC: WlanDot11Associated::HandleProprietarySnapRxFrame: MPDU header:"), 
+        *(reinterpret_cast<const Sdot11MacHeader*>(
+            frameBeginning)));
+#endif
+
+    // set the frame length
+    if ( aCopyBuffer )
+        {
+        aBuffer.KeSetLength( KMacHdrLen + KSubframeLen );        
+        }
+    else
+        {
+        aBuffer.KeSetLength( 
+            aLength - aDecryptHeaderLen - aDecryptTrailerLen );
+        }
+    // set the frame type
+    aBuffer.FrameType( TDataBuffer::KDot11Frame );
+    // set the offset to the beginning of the actual frame within the
+    // Rx buffer
+    aBuffer.KeSetOffsetToFrameBeginning(
+        frameBeginning                  // frame beginning
+        - aBuffer.KeGetBufferStart() ); // buffer beginning
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::ConfigureTxRatePolicies( 
+    WlanContextImpl& aCtxImpl,
+    const TTxRatePolicy& aRatePolicy,
+    const TQueue2RateClass& aQueue2RateClass,
+    const TInitialMaxTxRate4RateClass& aInitialMaxTxRate4RateClass,
+    const TTxAutoRatePolicy& aAutoRatePolicy,
+    const THtMcsPolicy& aHtMcsPolicy )
+    {
+    OsTracePrint( KTxRateAdapt, (TUint8*)
+        ("UMAC: WlanDot11Associated::ConfigureTxRatePolicies"));
+
+    TBool stateChange( EFalse );
+
+    if ( aCtxImpl.ProtocolStackTxDataAllowed() )
+        {
+        // store the provided information ...
+        StoreTxRatePolicyInfo( 
+            aCtxImpl,
+            aRatePolicy,
+            aQueue2RateClass,
+            aInitialMaxTxRate4RateClass,
+            aAutoRatePolicy,
+            aHtMcsPolicy );
+
+        // ... take it into use; and specify that the mgmt client request needs
+        // to be completed when doing it
+        stateChange = WlanDot11State::ConfigureTxRatePolicies( aCtxImpl, 
+                                                               ETrue );
+        if ( !stateChange )
+            {
+            // a fatal error occurred. Simulate MAC Not Responding error
+            // Note that the Mgmt Client request will be completed when 
+            // entering the dot11error state
+            stateChange = DoErrorIndication( 
+                aCtxImpl, 
+                WHA::KErrorMacNotResponding );            
+            }
+        }
+    else
+        {
+        // as user data is not allowed currently, it means that WLAN Mgmt client
+        // will request us to connect to a new nw shortly and this policy is for
+        // that new nw. So we shouldn't take the new rate policy into use yet, 
+        // as we don't know which rates the new nw will be supporting. We just 
+        // store the provided information for later use
+        stateChange = WlanDot11State::ConfigureTxRatePolicies( 
+            aCtxImpl,
+            aRatePolicy,
+            aQueue2RateClass,
+            aInitialMaxTxRate4RateClass,
+            aAutoRatePolicy,
+            aHtMcsPolicy );
+        }
+        
+    return stateChange;
+    }
+
+// -----------------------------------------------------------------------------
+// 
+// -----------------------------------------------------------------------------
+//
+TBool WlanDot11Associated::ConfigurePwrModeMgmtTrafficOverride( 
+    WlanContextImpl& aCtxImpl,
+    TBool aStayInPsDespiteUapsdVoiceTraffic,
+    TBool aStayInPsDespiteUapsdVideoTraffic,
+    TBool aStayInPsDespiteUapsdBestEffortTraffic, 
+    TBool aStayInPsDespiteUapsdBackgroundTraffic,
+    TBool aStayInPsDespiteLegacyVoiceTraffic,
+    TBool aStayInPsDespiteLegacyVideoTraffic,
+    TBool aStayInPsDespiteLegacyBestEffortTraffic,
+    TBool aStayInPsDespiteLegacyBackgroundTraffic )
+    {
+    OsTracePrint( KUmacDetails, (TUint8*)
+        ("UMAC: WlanDot11Associated::ConfigurePwrModeMgmtTrafficOverride"));
+
+    aCtxImpl.ConfigurePwrModeMgmtTrafficOverride( 
+        aStayInPsDespiteUapsdVoiceTraffic,
+        aStayInPsDespiteUapsdVideoTraffic,
+        aStayInPsDespiteUapsdBestEffortTraffic, 
+        aStayInPsDespiteUapsdBackgroundTraffic,
+        aStayInPsDespiteLegacyVoiceTraffic,
+        aStayInPsDespiteLegacyVideoTraffic,
+        aStayInPsDespiteLegacyBestEffortTraffic,
+        aStayInPsDespiteLegacyBackgroundTraffic );
+
+    // as we are already connected and aware of the network capabilities, we 
+    // also need to freeze the dynamic power mode mgmt traffic 
+    // override/ignoration settings so that they become immediately effective
+    aCtxImpl.FreezePwrModeMgmtTrafficOverride();
+
+    OnOidComplete( aCtxImpl, KErrNone );
+
+    // signal caller that no state transition occurred
+    return EFalse;    
+    }