summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/mac/src/pe/lim/lim_process_action_frame.c24
-rw-r--r--core/mac/src/pe/lim/lim_utils.c73
-rw-r--r--core/mac/src/pe/lim/lim_utils.h9
3 files changed, 100 insertions, 6 deletions
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 d2889095b1b9..d25e61e2c4f1 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 0518ae8fe92d..ba731b8ff299 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 5ad6bd0921e4..5c6d26b57fa7 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);