Browse Source

qcacld-3.0: Do not process duplicate rrm link measurement request

Add a logic to avoid processing duplicate rrm link measurement request.

Cache last processed frame with timestamp to validate new frame.
If retry bit set, compare sequence number and source address of
last processed frame. If both are matches and is within retry time
than ignore that frame, else process. Update last processed frame cache
every time new frame processed successfully

Change-Id: Ic2bff028c7bcd79d6b3dca186edb35464b1fd059
CRs-Fixed: 1088735
Arif Hussain 8 years ago
parent
commit
776ee7a0f2

+ 18 - 6
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,

+ 73 - 0
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;
+}

+ 9 - 0
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);