Merge "wlan: Send WoWL wake reason to upper-layer" into wlan-driver.lnx.1.0-dev.1.0
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index 7e5de46..287b29c 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -1922,7 +1922,6 @@
    staDesc.ucIsEseSta = pRoamInfo->isESEAssoc;
 #endif //FEATURE_WLAN_ESE
 
-#ifdef VOLANS_ENABLE_SW_REPLAY_CHECK
    /* check whether replay check is valid for the station or not */
    if( (eCSR_ENCRYPT_TYPE_TKIP == connectedCipherAlgo) || (eCSR_ENCRYPT_TYPE_AES == connectedCipherAlgo))
    {
@@ -1933,7 +1932,6 @@
        VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                  "HDD register TL ucIsReplayCheckValid %d: Replay check is needed for station", staDesc.ucIsReplayCheckValid);
    }
-
    else
    {
       /* For other encryption modes replay check is
@@ -1942,7 +1940,6 @@
         VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
                  "HDD register TL ucIsReplayCheckValid %d", staDesc.ucIsReplayCheckValid);
    }
-#endif
 
 #ifdef FEATURE_WLAN_WAPI
    hddLog(LOG1, "%s: WAPI STA Registered: %d", __func__, pAdapter->wapi_info.fIsWapiSta);
@@ -3424,12 +3421,10 @@
     /* tdls Direct Link do not need bcastSig */
     staDesc.ucBcastSig  = 0 ;
 
-#ifdef VOLANS_ENABLE_SW_REPLAY_CHECK
     if(staDesc.ucProtectedFrame)
         staDesc.ucIsReplayCheckValid = VOS_TRUE;
     else
         staDesc.ucIsReplayCheckValid = VOS_FALSE;
-#endif
 
     staDesc.ucInitState = WLANTL_STA_CONNECTED ;
 
diff --git a/CORE/HDD/src/wlan_hdd_cfg.c b/CORE/HDD/src/wlan_hdd_cfg.c
index 7272ed0..5cb9d3d 100644
--- a/CORE/HDD/src/wlan_hdd_cfg.c
+++ b/CORE/HDD/src/wlan_hdd_cfg.c
@@ -5154,13 +5154,14 @@
     if ((data == NULL) || ( datalist == NULL) || (num_entries == NULL))
         return VOS_STATUS_E_INVAL;
 
-    str = vos_mem_malloc(strlen((char *)data));
+    str = vos_mem_malloc(strlen((char *)data) + 1);
     if (!str) {
        VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
                  "%s str allocation failed",__func__);
        return -ENOMEM;
     }
     vos_mem_copy(str, data, strlen((char *)data));
+    str[strlen((char *)data)] = '\0';
     temp_str = str;
     /* parse the string */
     while (str && ('\0' != *str) && (num < max_entries)) {
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index 8803c2e..6b6012c 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -12039,6 +12039,11 @@
     VOS_STATUS vos_status;
     eHalStatus halStatus;
     hdd_context_t *pHddCtx;
+    uint8_t i;
+    v_MACADDR_t *peerMacAddr;
+    u64 rsc_counter = 0;
+    uint8_t staid = HDD_MAX_STA_COUNT;
+    bool pairwise_set_key = false;
 
     ENTER();
 
@@ -12072,15 +12077,24 @@
         return -EINVAL;
     }
 
+    if (CSR_MAX_RSC_LEN < params->seq_len)
+    {
+        hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Invalid seq length %d", __func__,
+                params->seq_len);
+    }
+
     hddLog(VOS_TRACE_LEVEL_INFO,
-           "%s: called with key index = %d & key length %d",
-           __func__, key_index, params->key_len);
+           "%s: called with key index = %d & key length %d & seq length %d",
+           __func__, key_index, params->key_len, params->seq_len);
+
+    peerMacAddr = (v_MACADDR_t *)mac_addr;
 
     /*extract key idx, key len and key*/
     vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey));
     setKey.keyId = key_index;
     setKey.keyLength = params->key_len;
     vos_mem_copy(&setKey.Key[0],params->key, params->key_len);
+    vos_mem_copy(&setKey.keyRsc[0], params->seq, params->seq_len);
 
     switch (params->cipher)
     {
@@ -12186,6 +12200,7 @@
                 __func__, __LINE__);
         setKey.keyDirection = eSIR_TX_RX;
         vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN);
+        pairwise_set_key = true;
     }
     if ((WLAN_HDD_IBSS == pAdapter->device_mode) && !pairwise)
     {
@@ -12216,6 +12231,9 @@
             hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
             vos_status = wlan_hdd_check_ula_done(pAdapter);
 
+            if (peerMacAddr && (pairwise_set_key == true))
+                staid = hdd_sta_id_find_from_mac_addr(pAdapter, peerMacAddr);
+
             if ( vos_status != VOS_STATUS_SUCCESS )
             {
                 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
@@ -12277,6 +12295,9 @@
             }
         }
 
+        if (pairwise_set_key == true)
+           staid = pHddStaCtx->conn_info.staId[0];
+
         pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len;
 
         pWextState->roamProfile.Keys.defaultIndex = key_index;
@@ -12384,6 +12405,13 @@
         }
     }
 
+    if (pairwise_set_key == true) {
+       for (i = 0; i < params->seq_len; i++) {
+          rsc_counter |= (params->seq[i] << i*8);
+       }
+       WLANTL_SetKeySeqCounter(pVosContext, rsc_counter, staid);
+    }
+
 end:
     /* Need to clear any trace of key value in the memory.
      * Thus zero out the memory even though it is local
diff --git a/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
index 387e32e..5133ead 100644
--- a/CORE/MAC/src/pe/lim/limProcessActionFrame.c
+++ b/CORE/MAC/src/pe/lim/limProcessActionFrame.c
@@ -2614,6 +2614,16 @@
             {
               tpSirMacVendorSpecificPublicActionFrameHdr pPubAction = (tpSirMacVendorSpecificPublicActionFrameHdr) pActionHdr;
               tANI_U8 P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 };
+	      tANI_U32 frameLen;
+
+	      frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo);
+
+	      if (frameLen < sizeof(pActionHdr)) {
+			limLog(pMac, LOG1,
+				FL("Received action frame of invalid len %d"),
+				frameLen);
+			break;
+	      }
 
               //Check if it is a P2P public action frame.
               if (vos_mem_compare(pPubAction->Oui, P2POui, 4))
@@ -2752,6 +2762,16 @@
             case SIR_MAC_ACTION_VENDOR_SPECIFIC:
               {
                 tANI_U8 P2POui[] = { 0x50, 0x6F, 0x9A, 0x09 };
+		tANI_U32 frameLen;
+
+		frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd);
+
+		if (frameLen < sizeof(pActionHdr)) {
+			limLog(pMac, LOG1,
+				FL("Received action frame of invalid len %d"),
+				frameLen);
+			break;
+		}
 
                 //Check if it is a P2P public action frame.
                 if (vos_mem_compare(pActionHdr->Oui, P2POui, 4))
diff --git a/CORE/TL/inc/wlan_qct_tl.h b/CORE/TL/inc/wlan_qct_tl.h
index 353a28a..146d658 100644
--- a/CORE/TL/inc/wlan_qct_tl.h
+++ b/CORE/TL/inc/wlan_qct_tl.h
@@ -3437,4 +3437,14 @@
  * Return: void
  */
 void WLANTL_GetSAPStaRSSi(void * pvosGCtx, uint8_t ucSTAId, s8 *rssi);
+
+/**
+ * WLANTL_SetKeySeqCounter() - set sequence key counter
+ * @pvosGCtx: global vos context
+ * @counter: key sequence counter
+ * @staid: station index
+ *
+ * Return: void
+ */
+void WLANTL_SetKeySeqCounter(void *pvosGCtx, u64 counter, uint8_t staid);
 #endif /* #ifndef WLAN_QCT_WLANTL_H */
diff --git a/CORE/TL/src/wlan_qct_tl.c b/CORE/TL/src/wlan_qct_tl.c
old mode 100755
new mode 100644
index 475d42a..07ff758
--- a/CORE/TL/src/wlan_qct_tl.c
+++ b/CORE/TL/src/wlan_qct_tl.c
@@ -6225,6 +6225,7 @@
 #endif
   uint8_t            ucMPDUHLen;
   uint16_t           seq_no;
+  u64                pn_num;
   uint16_t           usEtherType = 0;
 
   /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
@@ -6411,6 +6412,9 @@
       uDPUSig = WDA_GET_RX_DPUSIG(pvBDHeader);
       ucMPDUHLen = (uint8_t)WDA_GET_RX_MPDU_HEADER_LEN(pvBDHeader);
       seq_no = (uint16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pvBDHeader);
+      pn_num = WDA_GET_RX_REPLAY_COUNT(pvBDHeader);
+
+      vosTempBuff->pn_num = pn_num;
 
       TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH,
                  "WLAN TL:Data packet received for STA %d", ucSTAId));
@@ -9696,7 +9700,8 @@
     WLANTL_MSDUReorder( pTLCb, &vosDataBuff, aucBDHeader, ucSTAId, ucTid );
   }
 
-if(0 == ucUnicastBroadcastType
+if(WLANTL_IS_DATA_FRAME(WDA_GET_RX_TYPE_SUBTYPE(aucBDHeader)) &&
+   (0 == ucUnicastBroadcastType)
 #ifdef FEATURE_ON_CHIP_REORDERING
    && (WLANHAL_IsOnChipReorderingEnabledForTID(pvosGCtx, ucSTAId, ucTid) != TRUE)
 #endif
@@ -9773,30 +9778,36 @@
 
            /* It is not AMSDU frame so perform 
               reaply check for each packet, as
-              each packet contains valid replay counter*/ 
-           status =  WLANTL_IsReplayPacket( ullcurrentReplayCounter, ullpreviousReplayCounter);
-           if(VOS_FALSE == status)
-           {
-                /* Not a replay paket, update previous replay counter in TL CB */    
-                pClientSTA->ullReplayCounter[ucTid] = ullcurrentReplayCounter;
-           }
-           else
-           {
-              VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
-               "WLAN TL: Non-AMSDU Drop the replay packet with PN : [0x%llX]",ullcurrentReplayCounter);
+              each packet contains valid replay counter*/
+           if (vosDataBuff != NULL) {
+              if (vos_is_pkt_chain(vosDataBuff)) {
+                 WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTid);
+              } else {
+                 status =  WLANTL_IsReplayPacket(ullcurrentReplayCounter,
+                                                 ullpreviousReplayCounter);
+                 if(VOS_FALSE == status) {
+                    /* Not a replay paket, update previous replay counter in TL CB */
+                    pClientSTA->ullReplayCounter[ucTid] = ullcurrentReplayCounter;
+                 } else {
+                    VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+                    "WLAN TL: Non AMSDU Drop replay packet with PN: [0x%llX], prevPN: [0x%llx]",
+                    ullcurrentReplayCounter, ullpreviousReplayCounter);
 
-               pClientSTA->ulTotalReplayPacketsDetected++;
-               VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
-                "WLAN TL: Non-AMSDU total dropped replay packets on STA ID %X is [0x%X]",
-                ucSTAId, pClientSTA->ulTotalReplayPacketsDetected);
+                    pClientSTA->ulTotalReplayPacketsDetected++;
+                    VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+                    "WLAN TL: Non AMSDU total dropped replay packets on STA ID %X is [0x%X]",
+                    ucSTAId,  pClientSTA->ulTotalReplayPacketsDetected);
 
-               /* Repaly packet, drop the packet */
-               vos_pkt_return_packet(vosDataBuff);
-               return VOS_STATUS_SUCCESS;
-           }
+                    /* Repaly packet, drop the packet */
+                    vos_pkt_return_packet(vosDataBuff);
+                    return VOS_STATUS_SUCCESS;
+                 }
+              }
+          }
       }
-  }
+   }
 }
+
 /*It is a broadast packet DPU has already done replay check for 
   broadcast packets no need to do replay check of these packets*/
 
@@ -14437,6 +14448,34 @@
    *rssi = pTLCb->atlSTAClients[ucSTAId]->rssi_sample_sum / count;
 }
 
+void WLANTL_SetKeySeqCounter(void *pvosGCtx, u64 counter, uint8_t staid)
+{
+   WLANTL_CbType*  pTLCb = NULL;
+   uint8_t i;
+
+   pTLCb = VOS_GET_TL_CB(pvosGCtx);
+   if (NULL == pTLCb) {
+      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+             "%s: Invalid TL pointer from pvosGCtx", __func__));
+      return;
+   }
+
+   if (WLANTL_STA_ID_INVALID(staid)) {
+      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+             "%s: Invalid Sta id passed", __func__));
+      return;
+   }
+
+   if (NULL == pTLCb->atlSTAClients[staid]) {
+      TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+             "%s: Station context is NULL", __func__));
+      return;
+   }
+
+   for(i = 0; i < WLANTL_MAX_TID; i++)
+      pTLCb->atlSTAClients[staid]->ullReplayCounter[i] = counter;
+}
+
 #ifdef WLAN_FEATURE_RMC
 VOS_STATUS WLANTL_RmcInit
 (
diff --git a/CORE/TL/src/wlan_qct_tl_ba.c b/CORE/TL/src/wlan_qct_tl_ba.c
index efca2c0..166e6d6 100644
--- a/CORE/TL/src/wlan_qct_tl_ba.c
+++ b/CORE/TL/src/wlan_qct_tl_ba.c
@@ -220,66 +220,6 @@
       fwIdx = ReorderInfo->ucCIndex - 1;
    }
 
-   /* Do replay check before giving packets to upper layer 
-      replay check code : check whether replay check is needed or not */
-   if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
-   {
-       v_U64_t    ullpreviousReplayCounter = 0;
-       v_U64_t    ullcurrentReplayCounter = 0;
-       v_U8_t     ucloopCounter = 0;
-       v_BOOL_t   status = 0;
-
-       /*Do replay check for all packets which are in Reorder buffer */
-       for(ucloopCounter = 0; ucloopCounter < WLANTL_MAX_WINSIZE; ucloopCounter++)
-       {
-         /*Get previous reply counter*/
-         ullpreviousReplayCounter = pClientSTA->ullReplayCounter[ucTID];
-
-         /*Get current replay counter of packet in reorder buffer*/
-         ullcurrentReplayCounter = ReorderInfo->reorderBuffer->ullReplayCounter[ucloopCounter];
-
-         /*Check for holes, if a hole is found in Reorder buffer then
-           no need to do replay check on it, skip the current
-           hole and do replay check on other packets*/
-         if(NULL != (ReorderInfo->reorderBuffer->arrayBuffer[ucloopCounter]))
-         {
-           status = WLANTL_IsReplayPacket(ullcurrentReplayCounter, ullpreviousReplayCounter); 
-           if(VOS_TRUE == status)
-           {
-               /*Increment the debug counter*/
-               pClientSTA->ulTotalReplayPacketsDetected++;
-
-               /*A replay packet found*/
-               VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
-                "WLANTL_ReorderingAgingTimerExpierCB: total dropped replay packets on STA ID %X is [0x%X]",
-                ucSTAID, pClientSTA->ulTotalReplayPacketsDetected);
-
-               VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
-                "WLANTL_ReorderingAgingTimerExpierCB: replay packet found with PN : [0x%llX]",
-                ullcurrentReplayCounter);
-
-               VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
-                "WLANTL_ReorderingAgingTimerExpierCB: Drop the replay packet with PN : [0x%llX]",
-                ullcurrentReplayCounter);
-
-               ReorderInfo->reorderBuffer->arrayBuffer[ucloopCounter] = NULL;
-               ReorderInfo->reorderBuffer->ullReplayCounter[ucloopCounter] = 0;
-           }
-           else
-           {
-              /*Not a replay packet update previous replay counter*/
-              pClientSTA->ullReplayCounter[ucTID] = ullcurrentReplayCounter;
-           }
-         }
-         else
-         {
-              /* A hole detected in Reorder buffer*/
-              //BAMSGERROR("WLANTL_ReorderingAgingTimerExpierCB,hole detected\n",0,0,0);
-               
-         }
-       } 
-   }
-
    cIndex = ReorderInfo->ucCIndex;
    status = WLANTL_ChainFrontPkts(fwIdx, opCode, 
                                   &vosDataBuff, ReorderInfo, NULL);
@@ -314,6 +254,12 @@
       return;
    }
 
+   /* Do replay check before giving packets to upper layer
+      replay check code : check whether replay check is needed or not */
+   if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid) {
+      WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTID);
+   }
+
    pCurrent = vosDataBuff;
 
    while (pCurrent != NULL)
@@ -755,6 +701,12 @@
              "WLAN TL: Chaining was successful sending all pkts to HDD : %x",
               vosDataBuff ));
 
+    /* Do replay check before giving packets to upper layer
+       replay check code : check whether replay check is needed or not */
+    if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid) {
+      WLANTL_ReorderReplayCheck(pClientSTA, &vosDataBuff, ucTid);
+    }
+
     if ( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType )
     {
       WLANTL_FwdPktToHDD( pvosGCtx, vosDataBuff, ucSTAId);
@@ -1129,16 +1081,12 @@
    ucFwdIdx  = (v_U8_t)WDA_GET_RX_REORDER_FWD_IDX(pvBDHeader);
    CSN       = (v_U16_t)WDA_GET_RX_REORDER_CUR_PKT_SEQ_NO(pvBDHeader);
 
-
-
-#ifdef WLANTL_HAL_VOLANS
    /* Replay check code : check whether replay check is needed or not */
    if(VOS_TRUE == pClientSTA->ucIsReplayCheckValid)
    {
            /* Getting 48-bit replay counter from the RX BD */
-           ullreplayCounter = WDA_DS_GetReplayCounter(aucBDHeader);
+           ullreplayCounter = WDA_DS_GetReplayCounter(pvBDHeader);
    }
-#endif 
 
 #ifdef WLANTL_REORDER_DEBUG_MSG_ENABLE
    TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"opCode %d SI %d, FI %d, CI %d seqNo %d", ucOpCode, ucSlotIdx, ucFwdIdx, currentReorderInfo->ucCIndex, CSN));
@@ -1927,3 +1875,44 @@
    return;
 }/*WLANTL_FillReplayCounter*/
 
+void WLANTL_ReorderReplayCheck(WLANTL_STAClientType *pClientSTA,
+                               vos_pkt_t **vosDataBuff, v_U8_t ucTid)
+{
+   vos_pkt_t *pVosCurPkt;
+   vos_pkt_t *pNextVosPkt;
+   vos_pkt_t *pVosHeadPkt = NULL;
+   vos_pkt_t *pfreeVosPkt = NULL;
+   v_U64_t   prevReplayCounter = 0;
+   v_BOOL_t status;
+
+   pVosCurPkt = *vosDataBuff;
+
+   do {
+      vos_pkt_walk_packet_chain(pVosCurPkt, &pNextVosPkt, VOS_FALSE);
+      prevReplayCounter = pClientSTA->ullReplayCounter[ucTid];
+      status =  WLANTL_IsReplayPacket(pVosCurPkt->pn_num,
+                                      prevReplayCounter);
+      if(VOS_FALSE == status) {
+         pClientSTA->ullReplayCounter[ucTid] = pVosCurPkt->pn_num;
+         pVosHeadPkt = pVosCurPkt;
+      } else {
+         VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,
+                   "%s: Non-AMSDU Drop the replay packet PN: [0x%llX]",
+                   __func__, pVosCurPkt->pn_num);
+         pClientSTA->ulTotalReplayPacketsDetected++;
+
+         pfreeVosPkt = pVosCurPkt;
+         pfreeVosPkt->pNext = NULL;
+         vos_pkt_return_packet(pfreeVosPkt);
+
+         if (pVosHeadPkt != NULL) {
+            pVosHeadPkt->pNext = pNextVosPkt;
+         }
+         else {
+            *vosDataBuff = pNextVosPkt;
+         }
+      }
+
+      pVosCurPkt = pNextVosPkt;
+   } while (pVosCurPkt);
+}
diff --git a/CORE/TL/src/wlan_qct_tli_ba.h b/CORE/TL/src/wlan_qct_tli_ba.h
index 6265e89..e1d68e6 100644
--- a/CORE/TL/src/wlan_qct_tli_ba.h
+++ b/CORE/TL/src/wlan_qct_tli_ba.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013,2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -394,4 +394,14 @@
    v_U8_t                 ucSlotIndex
 );
 
+/**
+ * WLANTL_ReorderReplayCheck - Do reorder PN replay check
+ * @pClientSTA: pointer to sta context
+ * @vosDataBuff: pointer to address of data buffer
+ * @ucTid: Tid value
+ *
+ * Return: None
+ */
+void WLANTL_ReorderReplayCheck(WLANTL_STAClientType *pClientSTA,
+                               vos_pkt_t **vosDataBuff, v_U8_t ucTid);
 #endif /* #ifndef WLAN_QCT_TLI_H */
diff --git a/CORE/VOSS/inc/i_vos_packet.h b/CORE/VOSS/inc/i_vos_packet.h
index f0bc8ab..173d792 100644
--- a/CORE/VOSS/inc/i_vos_packet.h
+++ b/CORE/VOSS/inc/i_vos_packet.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2013,2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -127,6 +127,8 @@
    // user data pointers
    v_VOID_t *pvUserData[ VOS_PKT_USER_DATA_ID_MAX ];
 
+   v_U64_t pn_num;
+
    // magic number for verifying this is really a struct vos_pkt_t
    v_U32_t magic;
 };
diff --git a/CORE/VOSS/inc/vos_packet.h b/CORE/VOSS/inc/vos_packet.h
index ad838d7..ab949c8 100644
--- a/CORE/VOSS/inc/vos_packet.h
+++ b/CORE/VOSS/inc/vos_packet.h
@@ -565,6 +565,14 @@
                                       v_BOOL_t unchainPacket );
 
 
+/**
+ * vos_is_pkt_chain() - Check for chain of packets
+ * @pPacket: pointer to chain of packet list
+ *
+ * Return: true if chain of packets or false otherwise
+ */
+bool vos_is_pkt_chain(vos_pkt_t *pPacket);
+
 /**--------------------------------------------------------------------------
   
   \brief vos_pkt_get_data_vector() - Get data vectors from a voss Packet
diff --git a/CORE/VOSS/src/vos_packet.c b/CORE/VOSS/src/vos_packet.c
index 0135682..1765c80 100644
--- a/CORE/VOSS/src/vos_packet.c
+++ b/CORE/VOSS/src/vos_packet.c
@@ -1597,6 +1597,15 @@
    }
 }
 
+
+bool vos_is_pkt_chain(vos_pkt_t *pPacket)
+{
+   if (pPacket->pNext != NULL)
+      return true;
+   else
+      return false;
+}
+
 /**--------------------------------------------------------------------------
 
   \brief vos_pkt_get_data_vector() - Get data vectors from a voss Packet