Procházet zdrojové kódy

qcacld-3.0: Drop mgmt frames if no.of RX mgmt packets reaches to threshold

This change includes to drop RX mgmt packets before sending to MC thread
context based on below conditions

1) Print an warn message when no.of pending RX packets reaches to
   1/4th of threshold
2) Drop probe req, probe resp and beacon frames when
   no.of pending RX packets reaches to 1/2 of threshold
3) Drop all the RX management packets when no.of pending RX packets
   equals to threshold

Add a counter to maintain no.of pending management packets in queue
and MGMT_RX_PACKETS_THRESHOLD for threshold value

Change-Id: I9428a1a054f717a285378dbe95592ba0c5c569e6
CRs-Fixed: 2011645
Sreelakshmi Konamki před 8 roky
rodič
revize
6d478cd5cf

+ 3 - 1
core/mac/src/include/sys_global.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved.
  *
  * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
  *
@@ -32,6 +32,7 @@ typedef struct sAniSirSys {
 
 	uint32_t gSysFrameCount[4][16];
 	uint32_t gSysBbtReceived;
+	uint32_t sys_bbt_pending_mgmt_count;
 	uint32_t gSysBbtPostedToLim;
 	uint32_t gSysBbtPostedToSch;
 	uint32_t gSysBbtPostedToPmm;
@@ -47,6 +48,7 @@ typedef struct sAniSirSys {
 	uint32_t gSysEnableLearnMode;
 	uint32_t gSysEnableScanMode;
 	uint32_t gSysEnableLinkMonitorMode;
+	qdf_spinlock_t bbt_mgmt_lock;
 } tAniSirSys, *tpAniSirSys;
 
 #endif

+ 57 - 0
core/mac/src/pe/lim/lim_api.c

@@ -755,6 +755,7 @@ tSirRetStatus pe_open(tpAniSirGlobal pMac, struct cds_config_info *cds_cfg)
 
 	pMac->lim.maxBssId = cds_cfg->max_bssid;
 	pMac->lim.maxStation = cds_cfg->max_station;
+	qdf_spinlock_create(&pMac->sys.bbt_mgmt_lock);
 
 	if ((pMac->lim.maxBssId == 0) || (pMac->lim.maxStation == 0)) {
 		PELOGE(lim_log(pMac, LOGE,
@@ -828,6 +829,7 @@ tSirRetStatus pe_close(tpAniSirGlobal pMac)
 	if (ANI_DRIVER_TYPE(pMac) == eDRIVER_TYPE_MFG)
 		return eSIR_SUCCESS;
 
+	qdf_spinlock_destroy(&pMac->sys.bbt_mgmt_lock);
 	for (i = 0; i < pMac->lim.maxBssId; i++) {
 		if (pMac->lim.gpSession[i].valid == true) {
 			pe_delete_session(pMac, &pMac->lim.gpSession[i]);
@@ -1010,6 +1012,52 @@ QDF_STATUS pe_mc_process_handler(struct scheduler_msg *msg)
 	return QDF_STATUS_E_FAILURE;
 }
 
+/**
+ * pe_drop_pending_rx_mgmt_frames: To drop pending RX mgmt frames
+ * @mac_ctx: Pointer to global MAC structure
+ * @hdr: Management header
+ * @cds_pkt: Packet
+ *
+ * This function is used to drop RX pending mgmt frames if pe mgmt queue
+ * reaches threshold
+ *
+ * Return: QDF_STATUS_SUCCESS on success or QDF_STATUS_E_FAILURE on failure
+ */
+static QDF_STATUS pe_drop_pending_rx_mgmt_frames(tpAniSirGlobal mac_ctx,
+				tpSirMacMgmtHdr hdr, cds_pkt_t *cds_pkt)
+{
+	qdf_spin_lock(&mac_ctx->sys.bbt_mgmt_lock);
+	if (mac_ctx->sys.sys_bbt_pending_mgmt_count >=
+	     MGMT_RX_PACKETS_THRESHOLD) {
+		qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
+		lim_log(mac_ctx, LOGE,
+			FL("No.of pending RX management frames reaches to threshold, dropping management frames"));
+		cds_pkt_return_packet(cds_pkt);
+		cds_pkt = NULL;
+		return QDF_STATUS_E_FAILURE;
+	} else if (mac_ctx->sys.sys_bbt_pending_mgmt_count >
+		   (MGMT_RX_PACKETS_THRESHOLD / 2)) {
+		/* drop all probereq, proberesp and beacons */
+		if (hdr->fc.subType == SIR_MAC_MGMT_BEACON ||
+		    hdr->fc.subType == SIR_MAC_MGMT_PROBE_REQ ||
+		    hdr->fc.subType == SIR_MAC_MGMT_PROBE_RSP) {
+			qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
+			lim_log(mac_ctx, LOGE,
+				FL("No.of pending RX management frames reaches to half of threshold, dropping probe req, probe resp or beacon frames"));
+			cds_pkt_return_packet(cds_pkt);
+			cds_pkt = NULL;
+			return QDF_STATUS_E_FAILURE;
+		}
+	}
+	mac_ctx->sys.sys_bbt_pending_mgmt_count++;
+	qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
+	if (mac_ctx->sys.sys_bbt_pending_mgmt_count ==
+	    (MGMT_RX_PACKETS_THRESHOLD / 4))
+		lim_log(mac_ctx, LOGW,
+			FL("No.of pending RX management frames reaches to 1/4th of threshold"));
+	return QDF_STATUS_SUCCESS;
+}
+
 /* --------------------------------------------------------------------------- */
 /**
  * pe_handle_mgmt_frame() - Process the Management frames from TXRX
@@ -1094,6 +1142,10 @@ static QDF_STATUS pe_handle_mgmt_frame(struct wlan_objmgr_psoc *psoc,
 				 WMA_GET_OFFLOADSCANLEARN(pRxPacketInfo));
 	}
 
+	if (QDF_STATUS_SUCCESS !=
+	    pe_drop_pending_rx_mgmt_frames(pMac, mHdr, pVosPkt))
+		return QDF_STATUS_E_FAILURE;
+
 	/* Forward to MAC via mesg = SIR_BB_XPORT_MGMT_MSG */
 	msg.type = SIR_BB_XPORT_MGMT_MSG;
 	msg.bodyptr = pVosPkt;
@@ -1105,6 +1157,11 @@ static QDF_STATUS pe_handle_mgmt_frame(struct wlan_objmgr_psoc *psoc,
 							 mHdr->fc.subType)) {
 		cds_pkt_return_packet(pVosPkt);
 		pVosPkt = NULL;
+		/*
+		 * Decrement sys_bbt_pending_mgmt_count if packet
+		 * is dropped before posting to LIM
+		 */
+		lim_decrement_pending_mgmt_count(pMac);
 		return QDF_STATUS_E_FAILURE;
 	}
 

+ 5 - 1
core/mac/src/pe/lim/lim_process_message_queue.c

@@ -1387,6 +1387,7 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx,
 			(void **) &new_msg.bodyptr, false);
 
 		if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
+			lim_decrement_pending_mgmt_count(mac_ctx);
 			cds_pkt_return_packet(body_ptr);
 			break;
 		}
@@ -1408,15 +1409,18 @@ static void lim_process_messages(tpAniSirGlobal mac_ctx,
 				QDF_TRACE(QDF_MODULE_ID_PE, LOGE,
 						FL("Unable to Defer Msg"));
 				lim_log_session_states(mac_ctx);
+				lim_decrement_pending_mgmt_count(mac_ctx);
 				cds_pkt_return_packet(body_ptr);
 			}
-		} else
+		} else {
 			/* PE is not deferring this 802.11 frame so we need to
 			 * call cds_pkt_return. Asumption here is when Rx mgmt
 			 * frame processing is done, cds packet could be
 			 * freed here.
 			 */
+			lim_decrement_pending_mgmt_count(mac_ctx);
 			cds_pkt_return_packet(body_ptr);
+		}
 		break;
 	case eWNI_SME_SCAN_REQ:
 	case eWNI_SME_REMAIN_ON_CHANNEL_REQ:

+ 14 - 0
core/mac/src/pe/lim/lim_utils.c

@@ -5776,6 +5776,7 @@ void lim_handle_defer_msg_error(tpAniSirGlobal pMac,
 				struct scheduler_msg *pLimMsg)
 {
 	if (SIR_BB_XPORT_MGMT_MSG == pLimMsg->type) {
+		lim_decrement_pending_mgmt_count(pMac);
 		cds_pkt_return_packet((cds_pkt_t *) pLimMsg->bodyptr);
 		pLimMsg->bodyptr = NULL;
 	} else if (pLimMsg->bodyptr != NULL) {
@@ -7896,3 +7897,16 @@ QDF_STATUS lim_send_he_caps_ie(tpAniSirGlobal mac_ctx, tpPESession session,
 	return QDF_STATUS_E_FAILURE;
 }
 #endif
+
+void lim_decrement_pending_mgmt_count(tpAniSirGlobal mac_ctx)
+{
+	qdf_spin_lock(&mac_ctx->sys.bbt_mgmt_lock);
+	if (!mac_ctx->sys.sys_bbt_pending_mgmt_count) {
+		qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
+		lim_log(mac_ctx, LOGW,
+			FL("sys_bbt_pending_mgmt_count value is 0"));
+		return;
+	}
+	mac_ctx->sys.sys_bbt_pending_mgmt_count--;
+	qdf_spin_unlock(&mac_ctx->sys.bbt_mgmt_lock);
+}

+ 13 - 0
core/mac/src/pe/lim/lim_utils.h

@@ -69,6 +69,8 @@ typedef enum {
 
 #define IS_VHT_NSS_1x1(__mcs_map)	((__mcs_map & 0xFFFC) == 0xFFFC)
 
+#define MGMT_RX_PACKETS_THRESHOLD 200
+
 #ifdef WLAN_FEATURE_11W
 typedef union uPmfSaQueryTimerId {
 	struct {
@@ -1002,4 +1004,15 @@ static inline QDF_STATUS lim_send_he_caps_ie(tpAniSirGlobal mac_ctx,
 }
 
 #endif
+
+/**
+ * lim_decrement_pending_mgmt_count: Decrement mgmt frame count
+ * @mac_ctx: Pointer to global MAC structure
+ *
+ * This function is used to decrement pe mgmt count once frame
+ * removed from queue
+ *
+ * Return: None
+ */
+void lim_decrement_pending_mgmt_count(tpAniSirGlobal mac_ctx);
 #endif /* __LIM_UTILS_H */