diff --git a/core/mac/src/pe/lim/lim_process_action_frame.c b/core/mac/src/pe/lim/lim_process_action_frame.c index d2889095b1..d25e61e2c4 100644 --- a/core/mac/src/pe/lim/lim_process_action_frame.c +++ b/core/mac/src/pe/lim/lim_process_action_frame.c @@ -60,6 +60,8 @@ #define BA_DEFAULT_TX_BUFFER_SIZE 64 +static last_processed_msg rrm_link_action_frm; + /* Note: The test passes if the STAUT stops sending any frames, and no further frames are transmitted on this channel by the station when the AP has sent the last 6 beacons, with the channel switch information elements as seen @@ -1406,7 +1408,7 @@ err: qdf_mem_free(frm); } -static void +static tSirRetStatus __lim_process_link_measurement_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, tpPESession psessionEntry) { @@ -1420,7 +1422,7 @@ __lim_process_link_measurement_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, frameLen = WMA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); if (psessionEntry == NULL) { - return; + return eSIR_FAILURE; } /**Unpack the received frame */ @@ -1435,7 +1437,7 @@ __lim_process_link_measurement_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, PELOG2(sir_dump_buf (pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen); ) - return; + return eSIR_FAILURE; } else if (DOT11F_WARNED(nStatus)) { lim_log(pMac, LOGW, FL @@ -1447,7 +1449,7 @@ __lim_process_link_measurement_req(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo, } /* Call rrm function to handle the request. */ - rrm_process_link_measurement_request(pMac, pRxPacketInfo, &frm, + return rrm_process_link_measurement_request(pMac, pRxPacketInfo, &frm, psessionEntry); } @@ -1912,9 +1914,19 @@ void lim_process_action_frame(tpAniSirGlobal mac_ctx, session); break; case SIR_MAC_RRM_LINK_MEASUREMENT_REQ: - __lim_process_link_measurement_req(mac_ctx, + if (!lim_is_valid_frame( + &rrm_link_action_frm, + rx_pkt_info)) + break; + + if (__lim_process_link_measurement_req( + mac_ctx, (uint8_t *)rx_pkt_info, - session); + session) == eSIR_SUCCESS) + lim_update_last_processed_frame( + &rrm_link_action_frm, + rx_pkt_info); + break; case SIR_MAC_RRM_NEIGHBOR_RPT: __lim_process_neighbor_report(mac_ctx, diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 0518ae8fe9..ba731b8ff2 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -7218,3 +7218,76 @@ void lim_send_set_dtim_period(tpAniSirGlobal mac_ctx, uint8_t dtim_period, qdf_mem_free(dtim_params); } } + +/** + * lim_is_valid_frame(): validate RX frame using last processed frame details + * to find if it is duplicate frame. + * + * @last_processed_frm: last processed frame pointer. + * @pRxPacketInfo: RX packet. + * + * Frame treat as duplicate: + * if retry bit is set and + * if source address and seq number matches with the last processed frame + * + * Return: false if duplicate frame, else true. + */ +bool lim_is_valid_frame(last_processed_msg *last_processed_frm, + uint8_t *pRxPacketInfo) +{ + uint16_t seq_num; + tpSirMacMgmtHdr pHdr; + + if (!pRxPacketInfo) { + QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR, + FL("Invalid RX frame")); + return false; + } + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + + if (pHdr->fc.retry == 0) + return true; + + seq_num = (((pHdr->seqControl.seqNumHi << + HIGH_SEQ_NUM_OFFSET) | + pHdr->seqControl.seqNumLo)); + + if (last_processed_frm->seq_num == seq_num && + qdf_mem_cmp(last_processed_frm->sa, pHdr->sa, ETH_ALEN) == 0) { + QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR, + FL("Duplicate frame from "MAC_ADDRESS_STR " Seq Number %d"), + MAC_ADDR_ARRAY(pHdr->sa), seq_num); + return false; + } + return true; +} + +/** + * lim_update_last_processed_frame(): update new processed frame info to cache. + * + * @last_processed_frm: last processed frame pointer. + * @pRxPacketInfo: Successfully processed RX packet. + * + * Return: None. + */ +void lim_update_last_processed_frame(last_processed_msg *last_processed_frm, + uint8_t *pRxPacketInfo) +{ + uint16_t seq_num; + tpSirMacMgmtHdr pHdr; + + if (!pRxPacketInfo) { + QDF_TRACE(QDF_MODULE_ID_PE, QDF_TRACE_LEVEL_ERROR, + FL("Invalid RX frame")); + return; + } + + pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); + seq_num = (((pHdr->seqControl.seqNumHi << + HIGH_SEQ_NUM_OFFSET) | + pHdr->seqControl.seqNumLo)); + + qdf_mem_copy(last_processed_frm->sa, pHdr->sa, ETH_ALEN); + last_processed_frm->seq_num = seq_num; +} diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index 5ad6bd0921..5c6d26b57f 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -79,7 +79,16 @@ typedef union uPmfSaQueryTimerId { } tPmfSaQueryTimerId, *tpPmfSaQueryTimerId; #endif +typedef struct last_processed_frame { + tSirMacAddr sa; + uint16_t seq_num; +} last_processed_msg; + /* LIM utility functions */ +bool lim_is_valid_frame(last_processed_msg *last_processed_frm, + uint8_t *pRxPacketInfo); +void lim_update_last_processed_frame(last_processed_msg *last_processed_frm, + uint8_t *pRxPacketInfo); void limGetBssidFromPkt(tpAniSirGlobal, uint8_t *, uint8_t *, uint32_t *); char *lim_dot11_reason_str(uint16_t reasonCode); char *lim_mlm_state_str(tLimMlmStates state);