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