Selaa lähdekoodia

qcacmn: iot_sim beacon content change update

Adding support for beacon content change.

Change-Id: I8f804dd7d2cbbe7d3b7dea58841d7321f28101c7
CRs-Fixed: 2694454
nakul kachhwaha 5 vuotta sitten
vanhempi
sitoutus
89a67f807e

+ 4 - 2
iot_sim/core/iot_sim_cmn_api_i.h

@@ -89,7 +89,7 @@ QDF_STATUS iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat,
  * iot_sim_frame_update() - Management frame update
  * @pdev: reference to global pdev object
  * @nbuf: frame buffer
- * @direction: direction tx or rx
+ * @tx: TRUE in case of tx
  *
  * This function updates the outgoing management frame with
  * the content stored in iot_sim_context.
@@ -98,7 +98,9 @@ QDF_STATUS iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat,
  * QDF_STATUS_E_FAILURE on failure
  */
 QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev,
-				qdf_nbuf_t nbuf, bool direction);
+				qdf_nbuf_t nbuf,
+				struct beacon_tmpl_params *param,
+				bool tx);
 
 /*
  * iot_sim_get_ctx_from_pdev() - API to get iot_sim context object

+ 32 - 6
iot_sim/core/iot_sim_common.c

@@ -22,6 +22,7 @@
 #include <qdf_util.h>
 #include <qdf_str.h>
 #include <wmi_unified_param.h>
+#include <wlan_iot_sim_utils_api.h>
 
 /*
  * iot_sim_oper_to_str - function to return iot sim operation string
@@ -580,6 +581,11 @@ iot_sim_send_rule_to_fw(struct iot_sim_context *isc,
 {
 	struct simulation_test_params param;
 
+	if (FRAME_TYPE_IS_BEACON(type, subtype) && offset) {
+		iot_sim_info("Beacon update from offset:%d", offset);
+		return QDF_STATUS_E_NOSUPPORT;
+	}
+
 	if (iot_sim_frame_supported_by_fw(type, subtype, action)) {
 		qdf_mem_zero(&param, sizeof(struct simulation_test_params));
 		param.pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj);
@@ -608,8 +614,10 @@ iot_sim_send_rule_to_fw(struct iot_sim_context *isc,
 								&param)))
 			iot_sim_err("Sending del rule to fw failed!");
 
-		if (!FRAME_TYPE_IS_BEACON(type, subtype))
-			return QDF_STATUS_SUCCESS;
+		if (FRAME_TYPE_IS_BEACON(type, subtype) && clear)
+			return QDF_STATUS_E_NOSUPPORT;
+
+		return QDF_STATUS_SUCCESS;
 	}
 
 	return QDF_STATUS_E_NOSUPPORT;
@@ -889,6 +897,7 @@ iot_sim_debug_content_change_write(struct file *file,
 			((struct seq_file *)file->private_data)->private;
 	uint8_t action = 0, category = 0;
 	bool is_action = 0, clear = false;
+	mlme_pdev_ext_t *ext = NULL;
 
 	if ((!buf) || (count > USER_BUF_LEN) || (count < 7))
 		return -EFAULT;
@@ -947,11 +956,24 @@ iot_sim_debug_content_change_write(struct file *file,
 						  content, length, 0,
 						  is_action);
 	}
-	if (QDF_IS_STATUS_SUCCESS(status))
+	if (QDF_IS_STATUS_SUCCESS(status)) {
 		iot_sim_err("iot_sim: Content Change Operation - success");
-	else
+		if (FRAME_TYPE_IS_BEACON(type, subtype)) {
+			if (isc->bcn_buf && (!length || !content)) {
+				qdf_nbuf_free(isc->bcn_buf);
+				isc->bcn_buf = NULL;
+			}
+			ext = wlan_pdev_mlme_get_ext_hdl(isc->pdev_obj);
+			if (ext) {
+				isc->iot_sim_update_beacon_trigger(ext);
+				iot_sim_info("Beacon update triggered");
+			} else {
+				iot_sim_err("mlme_pdev_ext is null");
+			}
+		}
+	} else {
 		iot_sim_err("iot_sim: Content Change Operation - Fail");
-
+	}
 free:
 	qdf_mem_free(content);
 	qdf_mem_free(locbuf);
@@ -1366,6 +1388,7 @@ wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
 	qdf_set_macaddr_broadcast(&isc->bcast_peer.addr);
 	qdf_spinlock_create(&isc->bcast_peer.iot_sim_lock);
 	qdf_list_create(&isc->bcast_peer.list, 0);
+	isc->bcn_buf = NULL;
 
 	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_IOT_SIM_COMP,
 					      (void *)isc, QDF_STATUS_SUCCESS);
@@ -1396,11 +1419,14 @@ wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev,
 		/* Deinitilise function pointers from iot_sim context */
 		iot_sim_debugfs_deinit(isc);
 		iot_sim_remove_all_rules(isc);
+		if (isc->bcn_buf)
+			qdf_nbuf_free(isc->bcn_buf);
 		qdf_spinlock_destroy(&isc->bcast_peer.iot_sim_lock);
 		qdf_mem_free(isc);
 	}
-	iot_sim_debug("iot_sim component pdev%u object created",
+	iot_sim_debug("iot_sim component pdev%u object destroyed",
 		      wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj));
 
 	return QDF_STATUS_SUCCESS;
 }
+

+ 2 - 0
iot_sim/core/iot_sim_defs_i.h

@@ -153,6 +153,8 @@ struct iot_sim_context {
 	/* IOT_SIM Peer list & Bcast Peer */
 	struct iot_sim_rule_per_peer *iot_sim_peer_list, bcast_peer;
 	struct iot_sim_debugfs iot_sim_dbgfs_ctx;
+	void (*iot_sim_update_beacon_trigger)(mlme_pdev_ext_t *);
+	qdf_nbuf_t bcn_buf;
 };
 
 /* enum iot_sim_operations - iot sim operations

+ 151 - 11
iot_sim/core/iot_sim_utils.c

@@ -21,6 +21,7 @@
 #include <wlan_objmgr_vdev_obj.h>
 
 #define IEEE80211_FRAME_BODY_OFFSET 0x18
+#define IEEE80211_TSF_LEN       (8)
 
 /*
  * iot_sim_apply_content_change_rule - function to apply content change rule
@@ -34,13 +35,125 @@
  *	   QDF_STATUS_E_NOSUPPORT, no content change rule found for this frame
  */
 QDF_STATUS
-iot_sim_apply_content_change_rule(struct iot_sim_rule *piot_sim_rule,
+iot_sim_update_beacon_template_struct(qdf_nbuf_t nbuf,
+				      struct beacon_tmpl_params *param)
+{
+	struct ie_header *ie = NULL;
+	uint16_t offset = 0, ie_len = 0;
+	struct ieee80211_ath_channelswitch_ie *csa = NULL;
+	struct ieee80211_extendedchannelswitch_ie *ecsa = NULL;
+	struct extn_ie_header *extn_ie = NULL;
+
+	if (!param)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	/**
+	 * Skip fixed field
+	 */
+	offset += IEEE80211_TSF_LEN; /* TSF field */
+	offset += 2; /* Beacon interval */
+	offset += 2; /* Capability Information */
+
+	ie_len = wbuf_get_pktlen(nbuf) -
+		 sizeof(struct ieee80211_frame) - offset;
+	ie = (struct ie_header *)((uint8_t *)qdf_nbuf_data(nbuf) +
+				  sizeof(struct ieee80211_frame) + offset);
+
+	while (ie_len >= sizeof(struct ie_header)) {
+		ie_len -= sizeof(struct ie_header);
+		if (!ie->ie_len) {
+			ie += 1;
+			continue;
+		}
+
+		if (ie_len < ie->ie_len) {
+			iot_sim_err("Incomplete corrupted IE:%x", ie->ie_id);
+			return QDF_STATUS_E_INVAL;
+		}
+
+		switch (ie->ie_id) {
+		case WLAN_ELEMID_TIM:
+			if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH) {
+				iot_sim_err("Invalid TIM IE Length");
+				goto err;
+			}
+			param->tim_ie_offset = ((uint8_t *)ie -
+						(uint8_t *)qdf_nbuf_data(nbuf));
+			break;
+		case WLAN_ELEMID_CHANSWITCHANN:
+			if (ie->ie_len != WLAN_CSA_IE_MAX_LEN) {
+				iot_sim_err("Invalid CSA IE Length");
+				goto err;
+			}
+			csa =
+			(struct ieee80211_ath_channelswitch_ie *)ie;
+			param->csa_switch_count_offset =
+				(((uint8_t *)&csa->tbttcount) -
+				 (uint8_t *)qdf_nbuf_data(nbuf));
+			break;
+		case WLAN_ELEMID_EXTCHANSWITCHANN:
+			if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN) {
+				iot_sim_err("Invalid ECSA IE Length");
+				goto err;
+			}
+			ecsa =
+			(struct ieee80211_extendedchannelswitch_ie *)ie;
+			param->ext_csa_switch_count_offset =
+				(((uint8_t *)&ecsa->tbttcount) -
+				 (uint8_t *)qdf_nbuf_data(nbuf));
+			break;
+		case WLAN_ELEMID_EXTN_ELEM:
+			extn_ie = (struct extn_ie_header *)ie;
+			switch (extn_ie->ie_extn_id) {
+			case WLAN_EXTN_ELEMID_ESP:
+				param->esp_ie_offset =
+					((uint8_t *)ie -
+					 (uint8_t *)qdf_nbuf_data(nbuf));
+				break;
+			case WLAN_EXTN_ELEMID_MUEDCA:
+				param->mu_edca_ie_offset =
+					((uint8_t *)ie -
+					 (uint8_t *)qdf_nbuf_data(nbuf));
+				break;
+			default:
+				break;
+			}
+			break;
+		case WLAN_ELEMID_MULTIPLE_BSSID:
+			offset = ((uint8_t *)ie -
+				 (uint8_t *)qdf_nbuf_data(nbuf));
+			param->mbssid_ie_offset = offset;
+			break;
+		default:
+			break;
+		}
+		/* Consume info element */
+		ie_len -= ie->ie_len;
+		/* Go to next IE */
+		ie = (struct ie_header *)((uint8_t *)ie +
+					  sizeof(struct ie_header) +
+					  ie->ie_len);
+	}
+	param->tmpl_len = wbuf_get_pktlen(nbuf);
+	param->tmpl_len_aligned = roundup(param->tmpl_len,
+					  sizeof(uint32_t));
+	param->frm = (uint8_t *)qdf_nbuf_data(nbuf);
+	return QDF_STATUS_SUCCESS;
+err:
+	return QDF_STATUS_E_INVAL;
+}
+
+QDF_STATUS
+iot_sim_apply_content_change_rule(struct wlan_objmgr_pdev *pdev,
+				  struct iot_sim_rule *piot_sim_rule,
 				  qdf_nbuf_t nbuf,
-				  int fixed_param_length)
+				  int fixed_param_length,
+				  struct beacon_tmpl_params *param)
 {
 	uint8_t *buf = NULL;
 	qdf_size_t buf_len = 0;
 	int offset = 0;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
 	if (!piot_sim_rule->frm_content || !piot_sim_rule->len)
 		return QDF_STATUS_E_NOSUPPORT;
@@ -76,6 +189,11 @@ iot_sim_apply_content_change_rule(struct iot_sim_rule *piot_sim_rule,
 		iot_sim_err("Failed to modify content");
 	}
 
+	if (IEEE80211_IS_BEACON((struct ieee80211_frame *)qdf_nbuf_data(nbuf)))
+		status = iot_sim_update_beacon_template_struct(nbuf, param);
+		if (QDF_IS_STATUS_ERROR(status))
+			iot_sim_err("Failed to update beacon param");
+
 	return QDF_STATUS_SUCCESS;
 }
 
@@ -113,18 +231,20 @@ iot_sim_apply_drop_rule(struct iot_sim_rule *piot_sim_rule,
  *
  * @pdev: pdev object
  * @nbuf: input packet
- * @direction: direction to specify from where this packet is arrived
+ * @param: beacon template cmd parameter
+ * @tx: tx or not
  *
  * Return: QDF_STATUS_SUCCESS in general
  *	   QDF_STATUS_E_NOSUPPORT, no content change rule found for this frame
  */
 QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf,
+				struct beacon_tmpl_params *param,
 				bool tx)
 {
 	uint8_t type, subtype, seq = 0;
 	struct iot_sim_context *isc;
 	uint8_t *buf = qdf_nbuf_data(nbuf), *frm = NULL;
-	int fixed_param_length = 0;
+	int fixed_param_len = 0;
 	bool is_action_frm = false;
 	uint8_t cat, cat_index;
 	int auth_seq_index = 0;
@@ -146,14 +266,15 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf,
 		auth_seq_index = IEEE80211_FRAME_BODY_OFFSET + 2;
 		seq = le16toh(*(u_int16_t *)(buf + auth_seq_index));
 	} else if (type == IEEE80211_FC0_TYPE_MGT &&
-		   subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
+		   (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP ||
+		    subtype == IEEE80211_FC0_SUBTYPE_BEACON))
 	/* Probe response frame */
-		fixed_param_length = 12;
+		fixed_param_len = 12;
 	else if (type == IEEE80211_FC0_TYPE_MGT &&
 		 (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_RESP ||
 		  subtype == IEEE80211_FC0_SUBTYPE_REASSOC_RESP))
 	/* Assoc/Reassoc response frame */
-		fixed_param_length = 6;
+		fixed_param_len = 6;
 	else if (type == IEEE80211_FC0_TYPE_MGT &&
 		 subtype == IEEE80211_FC0_SUBTYPE_ACTION) {
 	/* Action frame */
@@ -171,10 +292,12 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf,
 		      type, subtype, seq, is_action_frm,
 		      tx ? "TX" : "RX");
 
-	/* Only broadcast peer is getting handled right now.
+	/**
+	 * Only broadcast peer is getting handled right now.
 	 * Need to add support for peer based content modification
 	 */
 	qdf_spin_lock(&isc->bcast_peer.iot_sim_lock);
+
 	if (!isc->bcast_peer.rule_per_seq[seq])
 		goto norule;
 
@@ -189,9 +312,26 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf,
 		goto norule;
 
 	if (tx) {
-		status = iot_sim_apply_content_change_rule(piot_sim_rule,
-							   nbuf,
-							   fixed_param_length);
+		if (IEEE80211_IS_BEACON((struct ieee80211_frame *)
+					qdf_nbuf_data(nbuf))) {
+			if (isc->bcn_buf)
+				qdf_nbuf_free(isc->bcn_buf);
+			isc->bcn_buf = qdf_nbuf_copy(nbuf);
+			status =
+			   iot_sim_apply_content_change_rule(pdev,
+							     piot_sim_rule,
+							     isc->bcn_buf,
+							     fixed_param_len,
+							     param);
+		} else {
+			status =
+			   iot_sim_apply_content_change_rule(pdev,
+							     piot_sim_rule,
+							     nbuf,
+							     fixed_param_len,
+							     param);
+		}
+
 		if (status == QDF_STATUS_E_NOSUPPORT)
 			goto norule;
 	} else {

+ 11 - 1
iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h

@@ -20,10 +20,20 @@
 #include <wlan_objmgr_cmn.h>
 #include <wlan_lmac_if_def.h>
 #include <wmi_unified_param.h>
+#include "include/wlan_pdev_mlme.h"
+#include "wlan_pdev_mlme_api.h"
 
 /* Forward Declarations */
 struct wmi_iot_sim_cmd_ops;
 
+/**
+ * struct iot_sim_cbacks - IOT Sim callbacks
+ * @reg_beacon_trigger_handler: reg_beacon_trigger_handler
+ */
+struct iot_sim_cbacks {
+	void (*update_beacon_trigger)(mlme_pdev_ext_t *);
+};
+
 /**
  * iot_sim_cmd_handler() - IOT SIM frame handler function
  * @vdev - vdev object.
@@ -33,7 +43,7 @@ struct wmi_iot_sim_cmd_ops;
  * Return : QDF_STATUS_E_SUCCESS/QDF_STATUS_E_FAILURE.
  */
 QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t buf,
-			       bool tx);
+			       struct beacon_tmpl_params *param, bool tx);
 
 /**
  * wlan_iot_sim_init() - API to init iot_sim component

+ 18 - 2
iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c

@@ -24,11 +24,25 @@
 #define IEEE80211_FRAME_BODY_OFFSET 0x18
 
 QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t nbuf,
-			       bool tx)
+			       struct beacon_tmpl_params *param, bool tx)
 {
 	struct wlan_objmgr_pdev *pdev = vdev->vdev_objmgr.wlan_pdev;
 
-	return iot_sim_frame_update(pdev, nbuf, tx);
+	return iot_sim_frame_update(pdev, nbuf, param, tx);
+}
+
+QDF_STATUS iot_sim_register_callbacks(struct wlan_objmgr_pdev *pdev,
+				      struct iot_sim_cbacks *cb)
+{
+	struct iot_sim_context *isc = NULL;
+
+	isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP);
+	if (!isc)
+		return QDF_STATUS_E_NULL_VALUE;
+
+	isc->iot_sim_update_beacon_trigger = cb->update_beacon_trigger;
+
+	return QDF_STATUS_SUCCESS;
 }
 
 QDF_STATUS
@@ -79,4 +93,6 @@ void wlan_lmac_if_iot_sim_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
 						&rx_ops->iot_sim_rx_ops;
 
 	iot_sim_ops->iot_sim_cmd_handler = iot_sim_cmd_handler;
+	iot_sim_ops->iot_sim_register_cb = iot_sim_register_callbacks;
+
 }

+ 1 - 0
umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c

@@ -193,6 +193,7 @@ QDF_STATUS iot_sim_mgmt_tx_update(struct wlan_objmgr_psoc *psoc,
 	if (rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler) {
 		status = rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler(vdev,
 								    buf,
+								    NULL,
 								    true);
 		if (QDF_IS_STATUS_ERROR(status))
 			mgmt_txrx_err("iot_sim_cmd_handler returned failure");

+ 2 - 1
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c

@@ -945,7 +945,8 @@ static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc,
 									 dbgid);
 		if (vdev) {
 			status = rx_ops->iot_sim_rx_ops.
-					iot_sim_cmd_handler(vdev, buf, false);
+					iot_sim_cmd_handler(vdev, buf,
+							    NULL, false);
 			if (status == QDF_STATUS_E_NULL_VALUE) {
 				wlan_objmgr_vdev_release_ref(vdev, dbgid);
 				mgmt_txrx_debug("iot_sim:Pkt processed at RX");

+ 4 - 0
umac/cmn_services/obj_mgr/src/wlan_objmgr_global_obj.c

@@ -428,6 +428,7 @@ QDF_STATUS wlan_objmgr_register_vdev_create_handler(
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
+qdf_export_symbol(wlan_objmgr_register_vdev_create_handler);
 
 QDF_STATUS wlan_objmgr_unregister_vdev_create_handler(
 		enum wlan_umac_comp_id id,
@@ -454,6 +455,7 @@ QDF_STATUS wlan_objmgr_unregister_vdev_create_handler(
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
+qdf_export_symbol(wlan_objmgr_unregister_vdev_create_handler);
 
 QDF_STATUS wlan_objmgr_register_vdev_destroy_handler(
 		enum wlan_umac_comp_id id,
@@ -480,6 +482,7 @@ QDF_STATUS wlan_objmgr_register_vdev_destroy_handler(
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
+qdf_export_symbol(wlan_objmgr_register_vdev_destroy_handler);
 
 QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler(
 		enum wlan_umac_comp_id id,
@@ -506,6 +509,7 @@ QDF_STATUS wlan_objmgr_unregister_vdev_destroy_handler(
 	qdf_spin_unlock_bh(&g_umac_glb_obj->global_lock);
 	return QDF_STATUS_SUCCESS;
 }
+qdf_export_symbol(wlan_objmgr_unregister_vdev_destroy_handler);
 
 QDF_STATUS wlan_objmgr_register_vdev_status_handler(
 		enum wlan_umac_comp_id id,

+ 7 - 1
umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h

@@ -1418,13 +1418,19 @@ struct wlan_lmac_if_sptrl_rx_ops {
 #endif /* WLAN_CONV_SPECTRAL_ENABLE */
 
 #ifdef WLAN_IOT_SIM_SUPPORT
+struct iot_sim_cbacks;
 /**
  * wlan_lmac_if_iot_sim_rx_ops: iot_sim rx operations
  * iot_sim_cmd_handler: Applies iot_sim rule in outgoing and incoming frames
+ * iot_sim_register_cb: callback registration with iot_sim
  **/
 struct wlan_lmac_if_iot_sim_rx_ops {
 	QDF_STATUS (*iot_sim_cmd_handler)(struct wlan_objmgr_vdev *vdev,
-					  qdf_nbuf_t n_buf, bool tx);
+					  qdf_nbuf_t n_buf,
+					  struct beacon_tmpl_params *param,
+					  bool tx);
+	QDF_STATUS (*iot_sim_register_cb)(struct wlan_objmgr_pdev *pdev,
+					  struct iot_sim_cbacks *cb);
 };
 #endif