Parcourir la source

qcacmn: iot_sim add support for drop operation

Adding support for iot_sim drop operation.
Drop operation will be handled in Rx direction.

Change-Id: If2e1c9663a69fcd16715cdd1d28639a388ea1c0c
CRs-Fixed: 2686309
nakul kachhwaha il y a 5 ans
Parent
commit
c5cdd1eaaf

+ 12 - 1
iot_sim/core/iot_sim_cmn_api_i.h

@@ -31,6 +31,15 @@
  *
  */
 #define USER_BUF_LEN (1 + 2 + 2 + 2 + MAX_BUFFER_SIZE + 6)
+/*
+ *		IOT SIM User Buf Format for Drop
+ * ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * |FrmType/subtype| Seq |category|action| drop |MacAddr|
+ * ++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * |   2Characters |2char| 2chars |2chars| 1char|17chars|
+ *
+ */
+#define USER_BUF_LEN_DROP (2 + 2 + 2 + 2 + 1 + 17)
 
 /**
  * wlan_iot_sim_pdev_obj_create_handler() - handler for pdev object create
@@ -80,6 +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
  *
  * This function updates the outgoing management frame with
  * the content stored in iot_sim_context.
@@ -87,7 +97,8 @@ QDF_STATUS iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat,
  * Return: QDF_STATUS_SUCCESS on success
  * QDF_STATUS_E_FAILURE on failure
  */
-QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf);
+QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev,
+				qdf_nbuf_t nbuf, bool direction);
 
 /*
  * iot_sim_get_ctx_from_pdev() - API to get iot_sim context object

+ 312 - 17
iot_sim/core/iot_sim_common.c

@@ -20,6 +20,7 @@
 #include <qdf_mem.h>
 #include <qdf_types.h>
 #include <qdf_util.h>
+#include <qdf_str.h>
 #include <wmi_unified_param.h>
 
 /*
@@ -267,9 +268,9 @@ iot_sim_parse_user_input_content_change(struct iot_sim_context *isc,
 	int argc = -1, ret = 0;
 
 	qdf_mem_zero(argv, sizeof(argv));
-	userbuf = strim(userbuf);
+	userbuf = qdf_str_trim(userbuf);
 
-	while ((substr = strsep(&userbuf, delim)) != NULL) {
+	while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
 		if (!isspace(*substr) && *substr != '\0')
 			argv[++argc] = substr;
 		if (argc >= 5)
@@ -360,6 +361,17 @@ err:
 	return status;
 }
 
+/*
+ * iot_sim_get_index_for_action_frm - function to convert 802.11 action frame
+ *				      category and action code into iot sim
+ *				      specific code.
+ *
+ * @frm: buf containing 802.11 action/category codes
+ * @cat_type: buf to hold converted category code
+ * @act_type: buf to hold converted action code
+ *
+ * Return: QDF_STATUS_SUCCESS on success, failure otherwise
+ */
 QDF_STATUS
 iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type,
 				 uint8_t *act_type)
@@ -405,6 +417,30 @@ iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type,
 	return QDF_STATUS_SUCCESS;
 }
 
+/*
+ * iot_sim_action_frame_supported_by_fw - function to find if action frame is
+ *					  supported by fw or not
+ * @category: iot_sim specific category code
+ * @action: iot_sim specific action code
+ *
+ * Return: true if supported else false
+ */
+bool
+iot_sim_action_frame_supported_by_fw(uint8_t category, uint8_t action)
+{
+	switch (category) {
+	case IEEE80211_ACTION_CAT_BA:
+		switch (action) {
+		case IEEE80211_ACTION_BA_ADDBA_REQUEST:
+			return true;
+		default:
+			return false;
+		}
+	default:
+		return false;
+	}
+}
+
 /*
  * iot_sim_frame_supported_by_fw - function to find if frame is supported by fw
  * @type: 802.11 frame type
@@ -413,8 +449,11 @@ iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type,
  * Return: true if supported else false
  */
 bool
-iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype)
+iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype, bool action)
 {
+	if (action)
+		return iot_sim_action_frame_supported_by_fw(type, subtype);
+
 	switch (type << IEEE80211_FC0_TYPE_SHIFT) {
 	case IEEE80211_FC0_TYPE_MGT:
 		switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
@@ -444,6 +483,74 @@ iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype)
 	}
 }
 
+/*
+ * iot_sim_remap_type_subtype - function to convert rules for response
+ *				type frame into request type. This is
+ *				used for drop/delay operation. This function
+ *				will update the passed type and subtype value.
+ *
+ * @type: 802.11 frame type
+ * @subtype: 802.11 frame subtype
+ * @seq: authentication sequence number, mostly 0 for non-authentication frame
+ * @action: flag to indicate action frame
+ *
+ * Return: QDF_STATUS_SUCCESS
+ */
+QDF_STATUS
+iot_sim_remap_type_subtype(uint8_t *type, uint8_t *subtype,
+			   uint16_t *seq, bool action)
+{
+	if (action) {
+		switch (*type) {
+		case CAT_BA:
+			switch (*subtype) {
+			case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
+				*subtype = IEEE80211_ACTION_BA_ADDBA_REQUEST;
+				break;
+			default:
+				break;
+			}
+			break;
+		default:
+			break;
+		}
+		return QDF_STATUS_SUCCESS;
+	}
+
+	switch (*type << IEEE80211_FC0_TYPE_SHIFT) {
+	case IEEE80211_FC0_TYPE_MGT:
+		switch (*subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
+		case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
+			*subtype = IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
+			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
+			break;
+		case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
+			*subtype = IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
+			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
+			break;
+		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
+			*subtype = IEEE80211_FC0_SUBTYPE_PROBE_REQ;
+			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
+			break;
+		case IEEE80211_FC0_SUBTYPE_AUTH:
+			*subtype = IEEE80211_FC0_SUBTYPE_AUTH;
+			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
+			/* If auth response (auth seq num 2) is marked as
+			 * drop, then drop the auth request (auth seq num 1)
+			 */
+			if (*seq == IEEE80211_AUTH_OPEN_RESPONSE)
+				*seq = IEEE80211_AUTH_OPEN_REQUEST;
+			break;
+		default:
+			break;
+		}
+	default:
+		break;
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
 /*
  * iot_sim_send_rule_to_fw - function to send iot_sim rule to fw
  *
@@ -456,6 +563,8 @@ iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype)
  * @offset: user provided offset
  * @frm: user provided frame content
  * @length: length of frm
+ * @action: flag to indicate action frame
+ * @drop: flag to indicate set drop rule
  * @clear: flag to indicate set rule or clear
  *
  * Return: QDF_STATUS_SUCCESS
@@ -466,20 +575,30 @@ iot_sim_send_rule_to_fw(struct iot_sim_context *isc,
 			struct qdf_mac_addr *mac,
 			uint8_t type, uint8_t subtype,
 			uint16_t seq, uint16_t offset,
-			uint8_t *frm, uint16_t len, bool clear)
+			uint8_t *frm, uint16_t len,
+			bool action, bool clear)
 {
 	struct simulation_test_params param;
 
-	if (iot_sim_frame_supported_by_fw(type, subtype)) {
+	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);
 		qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE);
 		param.test_cmd_type = oper;
-		/* subtype_cmd: Rule:- set:0 clear:1 */
-		param.test_subcmd_type = clear;
+		/* subtype_cmd: Set subcmd based on action and clear flag */
+		if (action) {
+			if (clear)
+				param.test_subcmd_type = DEL_RULE_ACTION;
+			else
+				param.test_subcmd_type = ADD_RULE_ACTION;
+		} else {
+			if (clear)
+				param.test_subcmd_type = DEL_RULE;
+			else
+				param.test_subcmd_type = ADD_RULE;
+		}
 		param.frame_type = type;
 		param.frame_subtype = subtype;
-
 		param.seq = seq;
 		param.offset = offset;
 		param.frame_length = len;
@@ -514,14 +633,18 @@ iot_sim_del_rule(struct iot_sim_rule_per_seq **s_e,
 		qdf_mem_free((*f_e)->frm_content);
 		(*f_e)->frm_content = NULL;
 	} else if (oper == DROP) {
-		/* TBD */
+		(*f_e)->drop = false;
 	} else if (oper == DELAY) {
 		/* TBD */
 	}
 
-	(*s_e)->use_count--;
-	qdf_clear_bit(oper, (unsigned long *)
-			    &(*f_e)->rule_bitmap);
+	if (qdf_test_bit(oper, (unsigned long *)
+			       &(*f_e)->rule_bitmap)) {
+		(*s_e)->use_count--;
+		qdf_clear_bit(oper, (unsigned long *)
+				    &(*f_e)->rule_bitmap);
+	}
+
 	if (!(*f_e)->rule_bitmap) {
 		qdf_mem_free(*f_e);
 		*f_e = NULL;
@@ -575,6 +698,9 @@ iot_sim_delete_rule_for_mac(struct iot_sim_context *isc,
 		return QDF_STATUS_E_FAILURE;
 	}
 
+	if (oper == DROP || oper == DELAY)
+		iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
+
 	peer = iot_sim_find_peer_from_mac(isc, mac);
 	if (peer) {
 		qdf_spin_lock(&peer->iot_sim_lock);
@@ -631,7 +757,7 @@ iot_sim_add_rule(struct iot_sim_rule_per_seq **s_e,
 		(*f_e)->len = len;
 		(*f_e)->offset = offset;
 	} else if (oper == DROP) {
-		/* TBD */
+		(*f_e)->drop = true;
 	} else if (oper == DELAY) {
 		/* TBD */
 	}
@@ -666,7 +792,7 @@ iot_sim_add_rule_for_mac(struct iot_sim_context *isc,
 			 uint8_t type, uint8_t subtype,
 			 uint16_t seq, uint16_t offset,
 			 uint8_t *frm, uint16_t len,
-			 bool action)
+			 uint8_t drop, bool action)
 {
 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
 	struct iot_sim_rule_per_peer *peer;
@@ -686,6 +812,9 @@ iot_sim_add_rule_for_mac(struct iot_sim_context *isc,
 		return status;
 	}
 
+	if (oper == DROP || oper == DELAY)
+		iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
+
 	peer = iot_sim_find_peer_from_mac(isc, mac);
 	if (peer) {
 		qdf_spin_lock(&peer->iot_sim_lock);
@@ -800,7 +929,8 @@ iot_sim_debug_content_change_write(struct file *file,
 
 	clear = length ? false : true;
 	status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
-					 seq, offset, content, length, clear);
+					 seq, offset, content, length,
+					 is_action, clear);
 	if (QDF_IS_STATUS_SUCCESS(status))
 		goto free;
 
@@ -814,7 +944,8 @@ iot_sim_debug_content_change_write(struct file *file,
 	} else {
 		status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
 						  type, subtype, seq, offset,
-						  content, length, is_action);
+						  content, length, 0,
+						  is_action);
 	}
 	if (QDF_IS_STATUS_SUCCESS(status))
 		iot_sim_err("iot_sim: Content Change Operation - success");
@@ -845,6 +976,96 @@ iot_sim_debug_delay_write(struct file *file,
 	return count;
 }
 
+/*
+ * iot_sim_parse_user_input_drop - function to parse user input into
+ *				   predefined format for drop operation.
+ *				   All arguments passed will be filled
+ *				   upon success
+ * @isc: iot sim context
+ * @userbuf: local copy of user input
+ * @count: length of userbuf
+ * @t_st: address of type variable
+ * @seq: address of seq variable
+ * @cat_type: 802.11 action frame category code
+ * @act_type: 802.11 action frame action code
+ * @drop: address of drop variable to specify drop the frame or not
+ * @addr: pointer to mac address
+ *
+ * Return: QDF_STATUS_SUCCESS on success
+ *	   QDF_STATUS_E_FAILURE otherwise
+ */
+QDF_STATUS
+iot_sim_parse_user_input_drop(struct iot_sim_context *isc,
+			      char *userbuf, ssize_t count,
+			      uint8_t *t_st, uint16_t *seq,
+			      uint8_t *cat_type, uint8_t *act_type,
+			      uint8_t *drop, struct qdf_mac_addr *addr)
+{
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	char *argv[6], *delim = " ", *substr;
+	int argc = -1, ret = 0;
+
+	qdf_mem_zero(argv, sizeof(argv));
+	userbuf = qdf_str_trim(userbuf);
+
+	while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
+		if (!isspace(*substr) && *substr != '\0')
+			argv[++argc] = substr;
+		if (argc >= 5)
+			break;
+	}
+
+	if (argc < 3) {
+		iot_sim_err("Invalid argument count %d", (argc + 1));
+		return status;
+	}
+
+	if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) {
+		iot_sim_err("One or more arguments are null");
+		return status;
+	}
+	/*
+	 * User can send drop data in following format:
+	 * 1. Add drop rule for specific peer
+	 *	<t_st> <seq> <category_type> <action_type> <drop> <MAC>
+	 * 2. Add drop rule for broadcast peer
+	 *	<t_st> <seq> <category_type> <action_type> <drop>
+	 * 3. Remove drop rule for specific peer
+	 *	<t_st> <seq> <category_type> <action_type> <drop> <MAC>
+	 * 4. Remove drop rule for broadcast peer
+	 *	<t_st> <seq> <category_type> <action_type> <drop> <BCAST_MAC>
+	 * 5. Remove drop rule for all peer
+	 *	<t_st> <seq> <category_type> <action_type> <drop>
+	 */
+
+	ret = kstrtou8(argv[0], 16, t_st);
+	if (ret)
+		goto err;
+	ret = kstrtou16(argv[1], 10, seq);
+	if (ret)
+		goto err;
+	ret = kstrtou8(argv[2], 10, cat_type);
+	if (ret)
+		goto err;
+	ret = kstrtou8(argv[3], 10, act_type);
+	if (ret)
+		goto err;
+	ret = kstrtou8(argv[4], 10, drop);
+	if (ret)
+		goto err;
+
+	/*
+	 * If argv[5] is valid, this must be mac address
+	 */
+	if (argv[5])
+		status = qdf_mac_parse(argv[5], addr);
+
+	return status;
+err:
+	iot_sim_err("kstrtoXX failed: %d", ret);
+	return QDF_STATUS_E_FAILURE;
+}
+
 /*
  * iot_sim_debug_drop_write - Write Handler for drop operation
  * @file: debugfs file pointer
@@ -859,7 +1080,81 @@ iot_sim_debug_drop_write(struct file *file,
 			 const char __user *buf,
 			 size_t count, loff_t *ppos)
 {
-	iot_sim_err("drop iot sim ops called");
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+	unsigned char t_st, type, subtype;
+	uint16_t seq = 0;
+	char *locbuf = NULL;
+	enum iot_sim_operations oper = DROP;
+	struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
+	struct iot_sim_context *isc =
+			((struct seq_file *)file->private_data)->private;
+	uint8_t action = 0, category = 0, tmp[2], drop = 0;
+	bool is_action = false, clear = false;
+
+	if ((!buf) || (count > USER_BUF_LEN_DROP) || (count < 6))
+		return -EFAULT;
+
+	locbuf = qdf_mem_malloc(USER_BUF_LEN_DROP + 1);
+	if (!locbuf)
+		return -ENOMEM;
+
+	if (copy_from_user(locbuf, buf, count)) {
+		qdf_mem_free(locbuf);
+		return -EFAULT;
+	}
+
+	status = iot_sim_parse_user_input_drop(isc, locbuf, count,
+					       &t_st, &seq, &category,
+					       &action, &drop, &mac_addr);
+	if (QDF_IS_STATUS_ERROR(status))
+		goto free;
+
+	type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
+	subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
+	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
+
+	if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
+		goto free;
+
+	if (FRAME_TYPE_IS_ACTION(type, subtype)) {
+		tmp[0] = category;
+		tmp[1] = action;
+		/*
+		 * convert 802.11 category and action code to iot sim codes
+		 */
+		status = iot_sim_get_index_for_action_frm(tmp, &category,
+							  &action);
+		if (QDF_IS_STATUS_ERROR(status))
+			goto free;
+
+		is_action = 1;
+		type = category;
+		subtype = action;
+	}
+
+	clear = drop ? false : true;
+	status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
+					 seq, 0, NULL, 0, is_action, clear);
+	if (QDF_IS_STATUS_SUCCESS(status))
+		goto free;
+
+	/* check for rule removal */
+	if (!drop) {
+		status = iot_sim_delete_rule_for_mac(isc, oper, seq,
+						     type, subtype,
+						     &mac_addr,
+						     is_action);
+	} else {
+		status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
+						  type, subtype, seq, 0,
+						  NULL, 0, drop, is_action);
+	}
+	if (QDF_IS_STATUS_SUCCESS(status))
+		iot_sim_debug("iot_sim: Rule update Drop Operation - Success");
+	else
+		iot_sim_err("iot_sim: Rule update Drop Operation - Fail");
+free:
+	qdf_mem_free(locbuf);
 	return count;
 }
 

+ 17 - 2
iot_sim/core/iot_sim_defs_i.h

@@ -164,11 +164,26 @@ struct iot_sim_context {
  * @IOT_SIM_MAX_OPERATION - iot sim max operation
  */
 enum iot_sim_operations {
-	INVALID_OPERATION,
-	CONTENT_CHANGE = 1,
+	CONTENT_CHANGE,
 	DROP,
 	DELAY,
 	IOT_SIM_MAX_OPERATION
 };
 
+/* enum iot_sim_subcmd - iot sim FW related subcommands
+ *
+ * @ADD_RULE - Add Rule
+ * @DEL_RULE - Delete Rule
+ * @ADD_RULE_ACTION - Add rule for action frame
+ * @DEL_RULE_ACTION - Del rule for action frame
+ * @IOT_SIM_MAX_SUBCMD - iot sim max subcmd
+ */
+enum iot_sim_subcmd {
+	ADD_RULE = 0,
+	DEL_RULE,
+	ADD_RULE_ACTION,
+	DEL_RULE_ACTION,
+	IOT_SIM_MAX_SUBCMD,
+};
+
 #endif /* _IOT_SIM_DEFS_I_H_ */

+ 117 - 39
iot_sim/core/iot_sim_utils.c

@@ -22,7 +22,104 @@
 
 #define IEEE80211_FRAME_BODY_OFFSET 0x18
 
-QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf)
+/*
+ * iot_sim_apply_content_change_rule - function to apply content change rule
+ *				       packet from upper stack will be modified
+ *				       as per the user content.
+ * @piot_sim_rule: iot_sim rule structure
+ * @nbuf: skb coming from upper stack
+ * @fixed_param_length: length of fixed parameters in frame body
+ *
+ * Return: QDF_STATUS_SUCCESS on successful content update or otherwise
+ *	   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,
+				  qdf_nbuf_t nbuf,
+				  int fixed_param_length)
+{
+	uint8_t *buf = NULL;
+	qdf_size_t buf_len = 0;
+	int offset = 0;
+
+	if (!piot_sim_rule->frm_content || !piot_sim_rule->len)
+		return QDF_STATUS_E_NOSUPPORT;
+
+	buf_len = qdf_nbuf_len(nbuf);
+	buf = qdf_nbuf_data(nbuf);
+
+	if (piot_sim_rule->offset ==
+			IEEE80211_FRAME_BODY_OFFSET) {
+		offset = IEEE80211_FRAME_BODY_OFFSET;
+	} else if (piot_sim_rule->offset == 0) {
+		offset = 0;
+	} else if (buf[piot_sim_rule->offset] ==
+			piot_sim_rule->frm_content[0]) {
+		offset = piot_sim_rule->offset;
+	}  else {
+		offset = IEEE80211_FRAME_BODY_OFFSET +
+			fixed_param_length;
+		while (((offset + 1) < buf_len) &&
+		       (buf[offset] < piot_sim_rule->frm_content[0])) {
+			offset += buf[offset + 1] + 2;
+		}
+	}
+
+	if (offset <= buf_len) {
+		buf += offset;
+		qdf_mem_copy(buf, piot_sim_rule->frm_content,
+			     piot_sim_rule->len);
+		qdf_nbuf_set_pktlen(nbuf, offset +
+				piot_sim_rule->len);
+		iot_sim_debug("iot_sim: Content updated");
+	} else {
+		iot_sim_err("Failed to modify content");
+	}
+
+	return QDF_STATUS_SUCCESS;
+}
+
+/*
+ * iot_sim_apply_drop_rule - function to apply drop rule. If set buffer will be
+ *			     freed here and proper return value will be sent to
+ *			     tgt layer.
+ *
+ * @piot_sim_rule: iot_sim rule structure
+ * @nbuf: skb coming from upper stack
+ *
+ * Return: QDF_STATUS_SUCCESS on successful drop
+ *	   QDF_STATUS_E_NULL_VALUE, when drop rule is applied
+ */
+QDF_STATUS
+iot_sim_apply_drop_rule(struct iot_sim_rule *piot_sim_rule,
+			qdf_nbuf_t nbuf)
+{
+	if (!piot_sim_rule->drop)
+		return QDF_STATUS_E_NOSUPPORT;
+
+	if (nbuf)
+		qdf_nbuf_free(nbuf);
+
+	iot_sim_debug("iot_sim: Drop rule applied");
+	return QDF_STATUS_SUCCESS;
+}
+
+/*
+ * iot_sim_frame_update - Function to parse input packet coming from upper
+ *			  stack in Tx direction and to tgt layer in Rx
+ *			  direction. This function will also check if rule
+ *			  for that frame type/subtype is set or not and call
+ *			  specific operation functions.
+ *
+ * @pdev: pdev object
+ * @nbuf: input packet
+ * @direction: direction to specify from where this packet is arrived
+ *
+ * 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,
+				bool tx)
 {
 	uint8_t type, subtype, seq = 0;
 	struct iot_sim_context *isc;
@@ -30,18 +127,19 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf)
 	int fixed_param_length = 0;
 	bool is_action_frm = false;
 	uint8_t cat, cat_index;
-	int auth_seq_index = 0, offset = 0;
+	int auth_seq_index = 0;
 	struct iot_sim_rule *piot_sim_rule = NULL;
-	qdf_size_t buf_len = 0;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
 
-	type = (buf[0] & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
-	subtype = (buf[0] & IEEE80211_FC0_SUBTYPE_MASK);
 	isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP);
 	if (!isc) {
 		iot_sim_err("pdev IOT_SIM object is NULL!");
 		return QDF_STATUS_SUCCESS;
 	}
 
+	type = (buf[0] & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
+	subtype = (buf[0] & IEEE80211_FC0_SUBTYPE_MASK);
+
 	if (type == IEEE80211_FC0_TYPE_MGT &&
 	    subtype == IEEE80211_FC0_SUBTYPE_AUTH) {
 	/* Authentication frame */
@@ -69,9 +167,9 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf)
 	}
 
 	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
-	iot_sim_debug("iot_sim: Change content operation for frame");
-	iot_sim_debug("type:%d subtype:%d seq:%d, is_action_frm: %u",
-		      type, subtype, seq, is_action_frm);
+	iot_sim_debug("iot_sim: type:%d subtype:%d seq:%d, action:%u dir:%s",
+		      type, subtype, seq, is_action_frm,
+		      tx ? "TX" : "RX");
 
 	/* Only broadcast peer is getting handled right now.
 	 * Need to add support for peer based content modification
@@ -80,8 +178,6 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf)
 	if (!isc->bcast_peer.rule_per_seq[seq])
 		goto norule;
 
-	buf_len = qdf_nbuf_len(nbuf);
-
 	if (is_action_frm)
 		piot_sim_rule = isc->bcast_peer.rule_per_seq[seq]->
 			rule_per_action_frm[cat][cat_index];
@@ -92,38 +188,20 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf)
 	if (!piot_sim_rule)
 		goto norule;
 
-	if (!piot_sim_rule->frm_content || !piot_sim_rule->len)
-		goto norule;
-
-	if (piot_sim_rule->offset ==
-			IEEE80211_FRAME_BODY_OFFSET) {
-		offset = IEEE80211_FRAME_BODY_OFFSET;
-	} else if (piot_sim_rule->offset == 0) {
-		offset = 0;
-	} else if (buf[piot_sim_rule->offset] ==
-			piot_sim_rule->frm_content[0]) {
-		offset = piot_sim_rule->offset;
-	}  else {
-		offset = IEEE80211_FRAME_BODY_OFFSET +
-			fixed_param_length;
-		while (((offset + 1) < buf_len) &&
-		       (buf[offset] < piot_sim_rule->frm_content[0])) {
-			offset += buf[offset + 1] + 2;
-		}
-	}
-
-	if (offset <= buf_len) {
-		buf += offset;
-		qdf_mem_copy(buf, piot_sim_rule->frm_content,
-			     piot_sim_rule->len);
-		qdf_nbuf_set_pktlen(nbuf, offset +
-				piot_sim_rule->len);
-		iot_sim_debug("iot_sim: Content updated");
+	if (tx) {
+		status = iot_sim_apply_content_change_rule(piot_sim_rule,
+							   nbuf,
+							   fixed_param_length);
+		if (status == QDF_STATUS_E_NOSUPPORT)
+			goto norule;
 	} else {
-		iot_sim_err("Failed to modify content");
+		status = iot_sim_apply_drop_rule(piot_sim_rule, nbuf);
+		if (QDF_IS_STATUS_SUCCESS(status))
+			status = QDF_STATUS_E_NULL_VALUE;
 	}
+
 	qdf_spin_unlock(&isc->bcast_peer.iot_sim_lock);
-	return QDF_STATUS_SUCCESS;
+	return status;
 
 norule:
 	iot_sim_debug("Rule not set for this frame");

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

@@ -28,10 +28,12 @@ struct wmi_iot_sim_cmd_ops;
  * iot_sim_cmd_handler() - IOT SIM frame handler function
  * @vdev - vdev object.
  * @buf - skb
+ * @tx - TRUE in case of Tx
  *
  * Return : QDF_STATUS_E_SUCCESS/QDF_STATUS_E_FAILURE.
  */
-QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t buf);
+QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t buf,
+			       bool tx);
 
 /**
  * wlan_iot_sim_init() - API to init iot_sim component

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

@@ -23,11 +23,12 @@
 
 #define IEEE80211_FRAME_BODY_OFFSET 0x18
 
-QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t nbuf)
+QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t nbuf,
+			       bool tx)
 {
 	struct wlan_objmgr_pdev *pdev = vdev->vdev_objmgr.wlan_pdev;
 
-	return iot_sim_frame_update(pdev, nbuf);
+	return iot_sim_frame_update(pdev, nbuf, tx);
 }
 
 QDF_STATUS

+ 13 - 1
qdf/inc/qdf_str.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -170,4 +170,16 @@ qdf_str_ncmp(const char *str1, const char *str2, qdf_size_t limit)
 	return __qdf_str_ncmp(str1, str2, limit);
 }
 
+/**
+ * qdf_str_sep - extract token from string
+ * @str: String buffer
+ * @delim: Delimitter
+ * Return: Pointer to the first token
+ *
+ */
+static inline char *qdf_str_sep(char **str, char *delim)
+{
+	return __qdf_str_sep(str, delim);
+}
+
 #endif /* __QDF_STR_H */

+ 2 - 1
qdf/linux/src/i_qdf_str.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -34,5 +34,6 @@
 #define __qdf_str_trim(str) strim(str)
 #define __qdf_str_nlen(str, limit) strnlen(str, limit)
 #define __qdf_str_ncmp(left, right, limit) strncmp(left, right, limit)
+#define __qdf_str_sep(buf, delim) strsep(buf, delim)
 
 #endif /* __I_QDF_STR_H */

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

@@ -191,7 +191,9 @@ QDF_STATUS iot_sim_mgmt_tx_update(struct wlan_objmgr_psoc *psoc,
 		return QDF_STATUS_E_NULL_VALUE;
 	}
 	if (rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler) {
-		status = rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler(vdev, buf);
+		status = rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler(vdev,
+								    buf,
+								    true);
 		if (QDF_IS_STATUS_ERROR(status))
 			mgmt_txrx_err("iot_sim_cmd_handler returned failure");
 	}

+ 60 - 0
umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c

@@ -908,6 +908,63 @@ mgmt_txrx_get_frm_type(uint8_t mgmt_subtype, uint8_t *mpdu_data_ptr)
 	return frm_type;
 }
 
+#ifdef WLAN_IOT_SIM_SUPPORT
+static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc,
+					  qdf_nbuf_t buf,
+					  struct mgmt_rx_event_params *rx_param)
+{
+	uint8_t *addr = NULL;
+	struct wlan_objmgr_vdev *vdev = NULL;
+	uint8_t pdevid = 0;
+	wlan_objmgr_ref_dbgid dbgid;
+	struct wlan_lmac_if_rx_ops *rx_ops = NULL;
+	struct wlan_objmgr_pdev *pdev;
+	struct ieee80211_frame *wh;
+	u_int8_t *data;
+	QDF_STATUS status = QDF_STATUS_SUCCESS;
+
+	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
+	if (rx_ops && rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler) {
+		data = (uint8_t *)qdf_nbuf_data(buf);
+		wh = (struct ieee80211_frame *)data;
+		addr = (uint8_t *)wh->i_addr3;
+		pdevid = rx_param->pdev_id;
+		dbgid = WLAN_IOT_SIM_ID;
+		if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)addr)) {
+			pdev = wlan_objmgr_get_pdev_by_id(psoc, pdevid,
+							  dbgid);
+			if (pdev) {
+				vdev = wlan_objmgr_pdev_get_first_vdev(pdev,
+								       dbgid);
+				wlan_objmgr_pdev_release_ref(pdev, dbgid);
+			}
+		} else
+			vdev = wlan_objmgr_get_vdev_by_macaddr_from_psoc(psoc,
+									 pdevid,
+									 addr,
+									 dbgid);
+		if (vdev) {
+			status = rx_ops->iot_sim_rx_ops.
+					iot_sim_cmd_handler(vdev, buf, false);
+			if (status == QDF_STATUS_E_NULL_VALUE) {
+				wlan_objmgr_vdev_release_ref(vdev, dbgid);
+				mgmt_txrx_debug("iot_sim:Pkt processed at RX");
+				return status;
+			}
+			wlan_objmgr_vdev_release_ref(vdev, dbgid);
+		}
+	}
+	return status;
+}
+#else
+static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc,
+					  qdf_nbuf_t buf,
+					  struct mgmt_rx_event_params *rx_param)
+{
+	return QDF_STATUS_SUCCESS;
+}
+#endif
+
 /**
  * wlan_mgmt_txrx_rx_handler_list_copy() - copies rx handler list
  * @rx_handler: pointer to rx handler list
@@ -1084,6 +1141,9 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler(
 				WLAN_SEQ_SEQ_SHIFT), mgmt_rx_params->rssi,
 				mgmt_rx_params->tsf_delta);
 
+	if (simulation_frame_update(psoc, buf, mgmt_rx_params))
+		return QDF_STATUS_E_FAILURE;
+
 	mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *)
 			wlan_objmgr_psoc_get_comp_private_obj(psoc,
 				WLAN_UMAC_COMP_MGMT_TXRX);

+ 4 - 1
umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h

@@ -267,6 +267,7 @@ typedef void (*wlan_objmgr_peer_status_handler)(
  * @FTM_TIME_SYNC_ID:           ftm time sync operations
  * @WLAN_PKT_CAPTURE_ID         Packet capture operations
  * @WLAN_DCS_ID:                DCS operations
+ * @WLAN_IOT_SIM_ID:            IOT Simulation feature
  * @WLAN_REF_ID_MAX:            Max id used to generate ref count tracking array
  */
  /* New value added to the enum must also be reflected in function
@@ -349,6 +350,7 @@ typedef enum {
 	FTM_TIME_SYNC_ID       = 73,
 	WLAN_PKT_CAPTURE_ID   = 74,
 	WLAN_DCS_ID           = 75,
+	WLAN_IOT_SIM_ID       = 76,
 	WLAN_REF_ID_MAX,
 } wlan_objmgr_ref_dbgid;
 
@@ -437,7 +439,8 @@ static inline const char *string_from_dbgid(wlan_objmgr_ref_dbgid id)
 					"WLAN_PSOC_TARGET_IF_ID",
 					"FTM_TIME_SYNC_ID",
 					"WLAN_PKT_CAPTURE_ID",
-					"WLAN_DCS_ID"};
+					"WLAN_DCS_ID",
+					"WLAN_IOT_SIM_ID"};
 
 	if (id >= WLAN_REF_ID_MAX)
 		return "Unknown";

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

@@ -1424,7 +1424,7 @@ struct wlan_lmac_if_sptrl_rx_ops {
  **/
 struct wlan_lmac_if_iot_sim_rx_ops {
 	QDF_STATUS (*iot_sim_cmd_handler)(struct wlan_objmgr_vdev *vdev,
-					  qdf_nbuf_t n_buf);
+					  qdf_nbuf_t n_buf, bool tx);
 };
 #endif