wlan: Link Layer Stats, implementation of interface Tx/Rx statistics

LLstats Implementation for Tx/Rx statistics

Change-Id: Id31c228b7e524b05a5509584b5e047c59c02303c
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
index a8e8d4f..165416c 100644
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -170,6 +170,11 @@
 /*BT-AMP packet LLC OUI value*/
 const v_U8_t WLANTL_BT_AMP_OUI[] =  {0x00, 0x19, 0x58 };
 
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+extern const v_U8_t  WLANTL_TID_2_AC[WLAN_MAX_TID];
+
+#endif
+
 #define WLANTL_MAX_SNR_DATA_SAMPLES 20
 
 #ifdef VOLANS_PERF
@@ -194,6 +199,11 @@
 #define WLANTL_IS_MGMT_FRAME(_type_sub)                                     \
                      ( WLANTL_MGMT_FRAME_TYPE == ( (_type_sub) & 0x30 ))
 
+#define WLANTL_IS_MGMT_ACTION_FRAME(_type_sub)                                \
+    (( WLANTL_MGMT_FRAME_TYPE == ( (_type_sub) & 0x30 )) &&    \
+     ( ( WLANTL_80211_MGMT_ACTION_SUBTYPE == ( (_type_sub) & 0xF )) || \
+       ( WLANTL_80211_MGMT_ACTION_NO_ACK_SUBTYPE == ( (_type_sub) & 0xF ))))
+
 #define WLANTL_IS_CTRL_FRAME(_type_sub)                                     \
                      ( WLANTL_CTRL_FRAME_TYPE == ( (_type_sub) & 0x30 ))
 
@@ -1387,6 +1397,13 @@
 #else
     pClientSTA->rssiAlpha = WLANTL_HO_DEFAULT_ALPHA;
 #endif /* FEATURE_WLAN_TDLS */
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+  pClientSTA->rssiDataAlpha = WLANTL_HO_DEFAULT_ALPHA;
+  pClientSTA->interfaceStats.accessCategoryStats[0].ac = WLANTL_AC_BK;
+  pClientSTA->interfaceStats.accessCategoryStats[1].ac = WLANTL_AC_BE;
+  pClientSTA->interfaceStats.accessCategoryStats[2].ac = WLANTL_AC_VI;
+  pClientSTA->interfaceStats.accessCategoryStats[3].ac = WLANTL_AC_VO;
+#endif
 
   /*Tx not suspended and station fully registered*/
   vos_atomic_set_U8(
@@ -5552,6 +5569,11 @@
   v_U16_t             usEtherType = 0;
 #endif
   v_BOOL_t            bForwardIAPPwithLLC = VOS_FALSE;
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+  v_S7_t              currentAvgRSSI = 0;
+  v_U8_t              ac;
+
+#endif
 
   /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
 
@@ -5716,6 +5738,18 @@
           TLLOGW(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN,
                             FL("Failed to Read SNR")));
         }
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+        pClientSTA = pTLCb->atlSTAClients[ucSTAId];
+        if ( NULL != pClientSTA)
+        {
+            pClientSTA->interfaceStats.mgmtRx++;
+            if (WLANTL_IS_MGMT_ACTION_FRAME(ucFrmType))
+            {
+                pClientSTA->interfaceStats.mgmtActionRx++;
+
+            }
+        }
+#endif
       }
 
       pTLCb->tlMgmtFrmClient.pfnTlMgmtFrmRx( pvosGCtx, vosTempBuff); 
@@ -5724,6 +5758,9 @@
     {
       ucSTAId = (v_U8_t)WDA_GET_RX_STAID( pvBDHeader );
       ucTid   = (v_U8_t)WDA_GET_RX_TID( pvBDHeader );
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+      ac = WLANTL_TID_2_AC[ucTid];
+#endif
 
       TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                  "WLAN TL:Data packet received for STA %d", ucSTAId));
@@ -5737,7 +5774,6 @@
         TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
         "WLAN TL:TL rx Bcast frame - sending to last registered station"));
         broadcast = VOS_TRUE;
-        
         /*-------------------------------------------------------------------
           If Addr1 is b/mcast, but Addr3 is our own self MAC, it is a b/mcast
           pkt we sent  looping back to us. To be dropped if we are non BTAMP  
@@ -5958,6 +5994,29 @@
            * continue;
            */
         }
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+        pClientSTA = pTLCb->atlSTAClients[ucSTAId];
+        if ( NULL != pClientSTA)
+        {
+            tpSirMacMgmtHdr pMacHeader = WDA_GET_RX_MAC_HEADER( pvBDHeader );
+            if( !WDA_IS_RX_BCAST(pvBDHeader) && ( pMacHeader->da[0] & 0x1))
+            {
+                pClientSTA->interfaceStats.accessCategoryStats[ac].rxMcast++;
+            }
+
+            WLANTL_HSGetDataRSSI(pvosGCtx, pvBDHeader, ucSTAId,
+                    &currentAvgRSSI);
+            pClientSTA->interfaceStats.rssiData = currentAvgRSSI;
+
+            pClientSTA->interfaceStats.accessCategoryStats[ac].rxMpdu++;
+            if (WDA_IS_RX_AN_AMPDU (pvBDHeader))
+            {
+                pClientSTA->interfaceStats.accessCategoryStats[ac].rxAmpdu++;
+            }
+        }
+
+
+#endif
         vosStatus = WLANTL_ReadSNR(pvosGCtx, pvBDHeader, ucSTAId);
 
         if (!VOS_IS_STATUS_SUCCESS(vosStatus))
@@ -5986,6 +6045,76 @@
   return VOS_STATUS_SUCCESS;
 }/* WLANTL_RxFrames */
 
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+/*==========================================================================
+
+  FUNCTION    WLANTL_CollectInterfaceStats
+
+  DESCRIPTION
+    Utility function used by TL to send the statitics
+
+  DEPENDENCIES
+
+
+  PARAMETERS
+
+    IN
+
+    ucSTAId:    station for which the statistics need to collected
+
+    vosDataBuff: it will contain the pointer to the corresponding
+                structure
+
+  RETURN VALUE
+    The result code associated with performing the operation
+
+    VOS_STATUS_E_INVAL:   Input parameters are invalid
+    VOS_STATUS_SUCCESS:   Everything is good :)
+
+  SIDE EFFECTS
+
+============================================================================*/
+VOS_STATUS
+WLANTL_CollectInterfaceStats
+(
+  v_PVOID_t       pvosGCtx,
+  v_U8_t          ucSTAId,
+  WLANTL_InterfaceStatsType    *vosDataBuff
+)
+{
+  WLANTL_CbType*  pTLCb = NULL;
+  /*------------------------------------------------------------------------
+    Sanity check
+   ------------------------------------------------------------------------*/
+  if ( WLANTL_STA_ID_INVALID( ucSTAId ) )
+  {
+    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+           "WLAN TL:Invalid station id requested on WLANTL_CollectStats"));
+    return VOS_STATUS_E_FAULT;
+  }
+  /*------------------------------------------------------------------------
+    Extract TL control block
+   ------------------------------------------------------------------------*/
+  pTLCb = VOS_GET_TL_CB(pvosGCtx);
+  if ( NULL == pTLCb )
+  {
+    TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+       "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_CollectStats"));
+    return VOS_STATUS_E_FAULT;
+  }
+
+  if ( NULL == pTLCb->atlSTAClients[ucSTAId] )
+  {
+      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+          "WLAN TL:Client Memory was not allocated on %s", __func__));
+      return VOS_STATUS_E_FAILURE;
+  }
+  vos_mem_copy(vosDataBuff, &pTLCb->atlSTAClients[ucSTAId]->interfaceStats,
+          sizeof(WLANTL_InterfaceStatsType));
+  return VOS_STATUS_SUCCESS;
+}
+
+#endif /* WLAN_FEATURE_LINK_LAYER_STATS */
 
 /*==========================================================================
 
diff --git a/CORE/TL/src/wlan_qct_tl_hosupport.c b/CORE/TL/src/wlan_qct_tl_hosupport.c
index 1b46d77..03f213b 100644
--- a/CORE/TL/src/wlan_qct_tl_hosupport.c
+++ b/CORE/TL/src/wlan_qct_tl_hosupport.c
@@ -882,13 +882,99 @@
    return status;
 }
 
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+
+/*==========================================================================
+
+   FUNCTION WLANTL_HSGetDataRSSI
+
+   DESCRIPTION
+
+   PARAMETERS
+
+   RETURN VALUE
+
+============================================================================*/
+VOS_STATUS WLANTL_HSGetDataRSSI
+(
+   v_PVOID_t        pAdapter,
+   v_PVOID_t        pBDHeader,
+   v_U8_t           STAid,
+   v_S7_t          *currentAvgRSSI
+)
+{
+   WLANTL_CbType   *tlCtxt = VOS_GET_TL_CB(pAdapter);
+   VOS_STATUS       status = VOS_STATUS_SUCCESS;
+   v_S7_t           currentRSSI, currentRSSI0, currentRSSI1;
+   WLANTL_CURRENT_HO_STATE_TYPE *currentHO = NULL;
+
+
+   if(NULL == tlCtxt)
+   {
+      TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+                  "Invalid TL handle"));
+      return VOS_STATUS_E_INVAL;
+   }
+
+   if ( NULL == tlCtxt->atlSTAClients[STAid] )
+   {
+       TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+           "WLAN TL:Client Memory was not allocated on %s", __func__));
+       return VOS_STATUS_E_FAILURE;
+   }
+
+   /*
+    * Compute RSSI only for the last MPDU of an AMPDU.
+    * Only last MPDU carries the Phy Stats Values
+    */
+    if (WDA_IS_RX_AN_AMPDU (pBDHeader)) {
+       if (!WDA_IS_RX_LAST_MPDU(pBDHeader)) {
+           return VOS_STATUS_E_FAILURE;
+          }
+    }
+
+   currentHO = &tlCtxt->hoSupport.currentHOState;
+
+   currentRSSI0 = WLANTL_GETRSSI0(pBDHeader);
+   currentRSSI1 = WLANTL_GETRSSI0(pBDHeader);
+   currentRSSI  = (currentRSSI0 > currentRSSI1) ? currentRSSI0 : currentRSSI1;
+
+   if (0 == currentRSSI)
+      return VOS_STATUS_E_INVAL;
+
+#ifdef WLANTL_HO_UTEST
+   TLHS_UtestHandleNewRSSI(&currentRSSI, pAdapter);
+#endif /* WLANTL_HO_UTEST */
+
+   if(0 == tlCtxt->atlSTAClients[STAid]->rssiDataAvg)
+   {
+      *currentAvgRSSI = currentRSSI;
+   }
+   else
+   {
+      *currentAvgRSSI = ((tlCtxt->atlSTAClients[STAid]->rssiDataAvg  *
+                          tlCtxt->atlSTAClients[STAid]->rssiDataAlpha) +
+                         (currentRSSI *
+                     (10 - tlCtxt->atlSTAClients[STAid]->rssiDataAlpha))) / 10;
+   }
+
+
+   tlCtxt->atlSTAClients[STAid]->rssiDataAvg = *currentAvgRSSI;
+
+   TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,
+          "Current new Data RSSI is %d, averaged Data RSSI is %d",
+          currentRSSI, *currentAvgRSSI));
+   return status;
+}
+#endif
+
 /*==========================================================================
 
    FUNCTION
 
-   DESCRIPTION 
-    
-   PARAMETERS 
+   DESCRIPTION
+
+   PARAMETERS
 
    RETURN VALUE
 
diff --git a/CORE/TL/src/wlan_qct_tl_hosupport.h b/CORE/TL/src/wlan_qct_tl_hosupport.h
index 1d27e97..fcffea7 100644
--- a/CORE/TL/src/wlan_qct_tl_hosupport.h
+++ b/CORE/TL/src/wlan_qct_tl_hosupport.h
@@ -68,6 +68,27 @@
 ===========================================================================*/
 #include "wlan_qct_tl.h" 
 
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+/*==========================================================================
+
+   FUNCTION
+
+   DESCRIPTION
+
+   PARAMETERS
+
+   RETURN VALUE
+
+============================================================================*/
+VOS_STATUS WLANTL_HSGetDataRSSI
+(
+   v_PVOID_t        pAdapter,
+   v_PVOID_t        pBDHeader,
+   v_U8_t           STAid,
+   v_S7_t          *currentAvgRSSI
+);
+#endif
+
 #if defined WLAN_FEATURE_NEIGHBOR_ROAMING
 /*----------------------------------------------------------------------------
  * Include Files
diff --git a/CORE/TL/src/wlan_qct_tli.h b/CORE/TL/src/wlan_qct_tli.h
index 7c22514..1215177 100644
--- a/CORE/TL/src/wlan_qct_tli.h
+++ b/CORE/TL/src/wlan_qct_tli.h
@@ -172,12 +172,15 @@
 #define WLANTL_80211_DATA_TYPE         0x02
 #define WLANTL_80211_DATA_QOS_SUBTYPE  0x08
 #define WLANTL_80211_NULL_QOS_SUBTYPE  0x0C
+#define WLANTL_80211_MGMT_ACTION_SUBTYPE  0x0D
+#define WLANTL_80211_MGMT_ACTION_NO_ACK_SUBTYPE  0x0E
 
 /*Defines for internal utility functions */
 #define WLANTL_FRAME_TYPE_BCAST 0xff
 #define WLANTL_FRAME_TYPE_MCAST 0x01
 #define WLANTL_FRAME_TYPE_UCAST 0x00
 
+#define WLANTL_FRAME_TYPESUBTYPE_MASK 0x3F
 
 /*-------------------------------------------------------------------------
   BT-AMP related definition - !!! should probably be moved to BT-AMP header
@@ -492,6 +495,7 @@
   v_TIME_t              cacheClearTime;
 }WLANTL_CacheInfoType;
 
+
 /*---------------------------------------------------------------------------
   STA Client type
 ---------------------------------------------------------------------------*/
@@ -673,6 +677,20 @@
   v_U8_t ptkInstalled;
 
   v_U32_t       linkCapacity;
+
+#ifdef WLAN_FEATURE_LINK_LAYER_STATS
+
+  /* Value of the averaged Data RSSI for this station */
+  v_S7_t                        rssiDataAvg;
+
+  /* Value of the averaged Data RSSI for this station in BMPS */
+  v_S7_t                        rssiDataAvgBmps;
+
+  /* Value of the Alpha to calculate Data RSSI average */
+  v_S7_t                        rssiDataAlpha;
+
+  WLANTL_InterfaceStatsType         interfaceStats;
+#endif
 }WLANTL_STAClientType;
 
 /*---------------------------------------------------------------------------