xref: /wlan-dirver/qca-wifi-host-cmn/iot_sim/core/iot_sim_common.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2020, The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 #include "iot_sim_cmn_api_i.h"
18 #include "iot_sim_defs_i.h"
19 #include "wlan_iot_sim_tgt_api.h"
20 #include <qdf_mem.h>
21 #include <qdf_types.h>
22 #include <qdf_util.h>
23 #include <qdf_str.h>
24 #include <qdf_delayed_work.h>
25 #include <wmi_unified_param.h>
26 #include <wlan_iot_sim_utils_api.h>
27 #include <wlan_lmac_if_api.h>
28 
29 /*
30  * iot_sim_oper_to_str - function to return iot sim operation string
31  * @oper: iot sim operation
32  *
33  * Return: string pointer
34  */
35 uint8_t *
36 iot_sim_oper_to_str(enum iot_sim_operations oper)
37 {
38 	switch (oper) {
39 	case CONTENT_CHANGE:
40 		return "content change";
41 	case DELAY:
42 		return "delay";
43 	case DROP:
44 		return "drop";
45 	default:
46 		return "invalid";
47 	}
48 }
49 
50 /*
51  * iot_sim_convert_offset_to_hex_str - function to convert offset into binary
52  * @offset: user provided offset value while action frame rule deletion
53  * @hex: buffer to store converted value
54  * @count: size of hex buffer
55  *
56  * Return: string pointer
57  */
58 QDF_STATUS
59 iot_sim_convert_offset_to_hex_str(uint16_t offset, uint8_t *hex, int8_t count)
60 {
61 	uint8_t temp[5];
62 	int ret;
63 
64 	snprintf(temp, sizeof(temp), "%04u", offset);
65 
66 	ret = qdf_hex_str_to_binary(hex, temp, count);
67 	if (ret == -1) {
68 		iot_sim_err("offset to hex conversion failed");
69 		return QDF_STATUS_E_FAILURE;
70 	}
71 
72 	return QDF_STATUS_SUCCESS;
73 }
74 
75 /*
76  * iot_sim_parse_action_frame - function to parse action frame to decode
77  *                              category and action code
78  *
79  * @length: length for content provided by user
80  * @offset: offset provided by user
81  * @content: user provided content
82  * @category: buffer to store iot specific category code
83  * @action: buffer to store iot specific action code
84  *
85  * Return: QDF_STATUS_SUCCESS on success otherwise failure
86  */
87 QDF_STATUS
88 iot_sim_parse_action_frame(uint16_t length, uint16_t offset, uint8_t *content,
89 			   uint8_t *category, uint8_t *action)
90 {
91 	QDF_STATUS status = QDF_STATUS_SUCCESS;
92 	uint8_t hex[2], *ptr = NULL;
93 
94 	if (!length) {
95 		status = iot_sim_convert_offset_to_hex_str(offset, hex,
96 							   sizeof(hex));
97 		if (QDF_IS_STATUS_ERROR(status))
98 			return status;
99 
100 		/* Offset represet category type and action type */
101 		status = iot_sim_get_index_for_action_frm(hex, category,
102 							  action, false);
103 		if (status == QDF_STATUS_E_FAULT) {
104 			iot_sim_err("Get indices for action failed");
105 			return status;
106 		}
107 	} else if (length && content) {
108 		/* if offset is zero, move ptr post header */
109 		if (offset == 0) {
110 			ptr = content + sizeof(struct ieee80211_frame);
111 		} else if (offset == sizeof(struct ieee80211_frame)) {
112 			ptr = content;
113 		} else {
114 			iot_sim_err("wrong offset for action frame content");
115 			return QDF_STATUS_E_FAILURE;
116 		}
117 		status = iot_sim_get_index_for_action_frm(ptr, category,
118 							  action, false);
119 	}
120 	return status;
121 }
122 
123 /*
124  * iot_sim_find_peer_from_mac - function to find the iot sim peer data
125  *                                    based on the mac address provided
126  *
127  * @isc: iot_sim pdev private object
128  * @mac: mac address of the peer
129  *
130  * Return: iot_sim_rule_per_peer reference if exists else NULL
131  */
132 struct iot_sim_rule_per_peer *
133 iot_sim_find_peer_from_mac(struct iot_sim_context *isc,
134 			   struct qdf_mac_addr *mac)
135 {
136 	struct iot_sim_rule_per_peer *peer_rule = NULL;
137 	qdf_list_node_t *node = NULL, *next_node = NULL;
138 
139 	if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac))
140 		return &isc->bcast_peer;
141 	else {
142 		if (qdf_list_empty(&isc->peer_list)) {
143 			iot_sim_debug("peer_list empty");
144 			return NULL;
145 		}
146 
147 		qdf_spin_lock_bh(&isc->iot_sim_lock);
148 		if (QDF_STATUS_SUCCESS !=
149 		    qdf_list_peek_front(&isc->peer_list, &next_node)) {
150 			qdf_spin_unlock_bh(&isc->iot_sim_lock);
151 			iot_sim_err("Failed to get peer rule from peer_list");
152 			return NULL;
153 		}
154 
155 		do {
156 			node = next_node;
157 			peer_rule =
158 				qdf_container_of(node,
159 						 struct iot_sim_rule_per_peer,
160 						 node);
161 			if (qdf_is_macaddr_equal(&peer_rule->addr, mac)) {
162 				qdf_spin_unlock_bh(&isc->iot_sim_lock);
163 				return peer_rule;
164 			}
165 		} while (QDF_STATUS_SUCCESS ==
166 			 qdf_list_peek_next(&isc->peer_list, node, &next_node));
167 
168 		qdf_spin_unlock_bh(&isc->iot_sim_lock);
169 		iot_sim_debug("Failed to find peer");
170 	}
171 
172 	return NULL;
173 }
174 
175 /*
176  * iot_sim_add_peer - function to add the iot sim peer data
177  *
178  * @isc: iot_sim pdev private object
179  * @mac: mac address of the peer
180  *
181  * Return: iot_sim_rule_per_peer reference
182  */
183 struct iot_sim_rule_per_peer *
184 iot_sim_add_peer(struct iot_sim_context *isc, struct qdf_mac_addr *mac)
185 {
186 	struct iot_sim_rule_per_peer *peer_rule = NULL;
187 	QDF_STATUS status;
188 
189 	if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac)) {
190 		iot_sim_err("called iot_sim_add_peer for broadcast address");
191 		return &isc->bcast_peer;
192 	}
193 
194 	qdf_spin_lock_bh(&isc->iot_sim_lock);
195 	if (qdf_list_size(&isc->peer_list) < MAX_PEER_COUNT) {
196 		peer_rule = qdf_mem_malloc(sizeof
197 					   (struct iot_sim_rule_per_peer));
198 		if (!peer_rule) {
199 			iot_sim_err("Memory alloc failed for peer: "
200 				    QDF_MAC_ADDR_STR,
201 				    QDF_MAC_ADDR_ARRAY(mac->bytes));
202 			goto rel_lock;
203 		}
204 
205 		qdf_copy_macaddr(&peer_rule->addr, mac);
206 		status = qdf_list_insert_back(&isc->peer_list,
207 					      &peer_rule->node);
208 		if (QDF_IS_STATUS_ERROR(status)) {
209 			iot_sim_err("peer_list enqueue failed for peer "
210 				    QDF_MAC_ADDR_STR,
211 				    QDF_MAC_ADDR_ARRAY(mac->bytes));
212 			qdf_mem_free(peer_rule);
213 			peer_rule = NULL;
214 		}
215 	} else {
216 		iot_sim_err("peer_list  already reached max limit");
217 	}
218 
219 rel_lock:
220 	qdf_spin_unlock_bh(&isc->iot_sim_lock);
221 	return peer_rule;
222 }
223 
224 /*
225  * iot_sim_remove_peer - function to remove the iot sim peer data
226  *
227  * @isc: iot_sim pdev private object
228  * @mac: mac address of the peer
229  *
230  * Return: void
231  */
232 void iot_sim_remove_peer(struct iot_sim_context *isc,
233 			 struct iot_sim_rule_per_peer *peer_rule)
234 {
235 	qdf_spin_lock_bh(&isc->iot_sim_lock);
236 	qdf_list_remove_node(&isc->peer_list, &peer_rule->node);
237 	qdf_spin_unlock_bh(&isc->iot_sim_lock);
238 }
239 
240 /*
241  * iot_sim_validate_content - function to validate frame content. User provided
242  *			      content must be either full frame or full frame
243  *			      body or valid TLV formatted data.
244  * @buf: pointer to frame content in binary format
245  * @total_len: length of content
246  * @offset: offset provided by user
247  *
248  * Return: QDF_STATUS_SUCCESS on success
249  *	   QDF_STATUS_E_FAULT on failure
250  */
251 static QDF_STATUS
252 iot_sim_validate_content(uint8_t *buf,
253 			 uint16_t total_len,
254 			 uint16_t offset)
255 {
256 	char *ie = buf;
257 	uint32_t len = 0, i = 0;
258 	uint32_t fb = sizeof(struct ieee80211_frame);
259 
260 	if (offset == 0 || offset == fb) {
261 		/* Replace the entire content set by user */
262 		return QDF_STATUS_SUCCESS;
263 	}
264 
265 	/* Check for malformed IEs and proper IE
266 	 * boundaries in user content
267 	 */
268 	for (i = 0; i < total_len;) {
269 		/* TLV: T(1) + L(1) + V(L)*/
270 		len = (1 + 1 + ie[1]);
271 		i += len;
272 		ie += len;
273 	}
274 
275 	if (i == total_len)
276 		return QDF_STATUS_SUCCESS;
277 
278 	iot_sim_err("iot_sim: cnt(bin) len:%u IE Parsed len:%u",
279 		    total_len,
280 		    i);
281 
282 	return QDF_STATUS_E_INVAL;
283 }
284 
285 /*
286  * iot_sim_handle_frame_content - function to process frame content provided
287  *				  by user. This function will convert the ascii
288  *				  string into binary string and validate the
289  *				  content.
290  * @isc: iot sim context
291  * @pos: position to the frame content in the user buffer
292  * @storage: storage to store frame content after processing
293  * @offset: user provided offset
294  * @len: length of the user provided content in bytes
295  *
296  * Return: QDF_STATUS_SUCCESS on success
297  *	   QDF_STATUS_E_FAULT on hex str to binary conversion failure
298  *	   QDF_STATUS_E_NOMEM on memory allocation failure
299  */
300 QDF_STATUS
301 iot_sim_handle_frame_content(struct iot_sim_context *isc,
302 			     const char *pos,
303 			     uint8_t **storage,
304 			     uint16_t offset,
305 			     uint16_t len)
306 {
307 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
308 	int ret;
309 
310 	*storage = qdf_mem_malloc(len);
311 	if (!*storage) {
312 		iot_sim_err("iot_sim:storage allocation failed");
313 		return QDF_STATUS_E_NOMEM;
314 	}
315 
316 	ret = qdf_hex_str_to_binary(*storage, pos, len);
317 	if (ret == -1) {
318 		iot_sim_err("iot_sim:hex2bin conversion failed");
319 		status = QDF_STATUS_E_FAULT;
320 		goto error;
321 	}
322 
323 	status = iot_sim_validate_content(*storage, len, offset);
324 	if (QDF_IS_STATUS_ERROR(status)) {
325 		iot_sim_err("iot_sim:User Content Invalid");
326 		goto error;
327 	}
328 
329 	return QDF_STATUS_SUCCESS;
330 
331 error:
332 	qdf_mem_free(*storage);
333 	*storage = NULL;
334 	return status;
335 }
336 
337 /*
338  * iot_sim_parse_user_input_content_change - function to parse user input into
339  *					     predefined format for content
340  *					     change operation. All arguments
341  *					     passed will be filled upon success
342  * @isc: iot sim context
343  * @userbuf: local copy of user input
344  * @count: length of userbuf
345  * @t_st: address of type variable
346  * @seq: address of seq variable
347  * @offset: address of offset variable
348  * @length: address of length variable
349  * @content: double pointer to storage to store frame content after processing
350  * @addr: pointer to mac address
351  *
352  * @storage: storage to store frame content after processing
353  * @offset: user provided offset
354  * @len: length of the user provided content in bytes
355  *
356  * Return: QDF_STATUS_SUCCESS on success
357  *	   QDF_STATUS_E_FAILURE otherwise
358  */
359 QDF_STATUS
360 iot_sim_parse_user_input_content_change(struct iot_sim_context *isc,
361 					char *userbuf, ssize_t count,
362 					uint8_t *t_st, uint16_t *seq,
363 					uint16_t *offset, uint16_t *length,
364 					uint8_t **content,
365 					struct qdf_mac_addr *addr)
366 {
367 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
368 	char *argv[6], *delim = " ", *substr;
369 	int argc = -1, ret = 0;
370 
371 	qdf_mem_zero(argv, sizeof(argv));
372 	userbuf = qdf_str_trim(userbuf);
373 
374 	while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
375 		if (!isspace(*substr) && *substr != '\0')
376 			argv[++argc] = substr;
377 		if (argc >= 5)
378 			break;
379 	}
380 
381 	if (argc < 3) {
382 		iot_sim_err("Invalid argument count %d", (argc + 1));
383 		return status;
384 	}
385 
386 	if (!argv[0] || !argv[1] || !argv[2] || !argv[3]) {
387 		iot_sim_err("One or more arguments are null");
388 		return status;
389 	}
390 
391 	ret = kstrtou8(argv[0], 16, t_st);
392 	if (ret)
393 		goto err;
394 	ret = kstrtou16(argv[1], 10, seq);
395 	if (ret)
396 		goto err;
397 	ret = kstrtou16(argv[2], 10, offset);
398 	if (ret)
399 		goto err;
400 	ret = kstrtou16(argv[3], 10, length);
401 	if (ret)
402 		goto err;
403 	/*
404 	 * User can send content change data in following format:
405 	 * 1. Add rule for specific peer
406 	 *	<t_st> <seq> <offset> <length> <content> <MAC>
407 	 * 2. Add rule for broadcast peer
408 	 *	<t_st> <seq> <offset> <length> <content>
409 	 * 3. Remove rule for specific peer
410 	 *	<t_st> <seq> <offset> <length> <MAC>
411 	 * 4. Remove rule for broadcast peer
412 	 *	<t_st> <seq> <offset> <length>
413 	 */
414 
415 	/*
416 	 * If length is 0, this implies remove the rule
417 	 */
418 	if (!*length) {
419 		/*
420 		 * 1. Ignore the frame content
421 		 * 2. argv[4] is not null, then it must be a valid mac
422 		 *    If argv[4] is null, then set 'addr' as null
423 		 */
424 		*content = NULL;
425 		if (argv[4]) {
426 			status = qdf_mac_parse(argv[4], addr);
427 			if (QDF_IS_STATUS_ERROR(status))
428 				iot_sim_err("iot_sim: argv4 is invalid mac for 0 len");
429 		} else {
430 			qdf_mem_zero(addr, QDF_MAC_ADDR_SIZE);
431 			status = QDF_STATUS_SUCCESS;
432 		}
433 		/*
434 		 * No need to parse further just return.
435 		 */
436 		return status;
437 	}
438 
439 	/*
440 	 * If argv[4] is valid, this implies frame content
441 	 */
442 	if (argv[4]) {
443 		status = iot_sim_handle_frame_content(isc, argv[4],
444 						      content, *offset,
445 						      *length);
446 		if (QDF_IS_STATUS_ERROR(status))
447 			return status;
448 	}
449 
450 	/*
451 	 * If argv[5] is valid, this must be mac address
452 	 */
453 	if (argv[5]) {
454 		status = qdf_mac_parse(argv[5], addr);
455 		if (QDF_IS_STATUS_ERROR(status))
456 			qdf_mem_free(content);
457 	}
458 
459 	return status;
460 err:
461 	iot_sim_err("kstrtoXX failed: %d", ret);
462 	return status;
463 }
464 
465 /*
466  * iot_sim_get_index_for_action_frm - function to convert 802.11 action frame
467  *				      category and action code into iot sim
468  *				      specific code.
469  *
470  * @frm: buf containing 802.11 action/category codes
471  * @cat_type: buf to hold converted category code
472  * @act_type: buf to hold converted action code
473  * @rx: TRUE if its getting called in the rx path
474  *
475  * Return: QDF_STATUS_SUCCESS on success, failure otherwise
476  */
477 QDF_STATUS
478 iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type,
479 				 uint8_t *act_type, bool rx)
480 {
481 	uint8_t category, action;
482 
483 	category = ((struct ieee80211_action *)(frm))->ia_category;
484 	action = ((struct ieee80211_action *)(frm))->ia_action;
485 
486 	iot_sim_info("category %x action %x", category, action);
487 
488 	switch (category) {
489 	case IEEE80211_ACTION_CAT_BA:
490 		switch (action) {
491 		case IEEE80211_ACTION_BA_ADDBA_REQUEST:
492 			if (rx) {
493 				*cat_type = CAT_BA;
494 				*act_type = action;
495 
496 			} else {
497 				*cat_type = category;
498 				*act_type = action;
499 			}
500 			break;
501 		case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
502 		case IEEE80211_ACTION_BA_DELBA:
503 			*cat_type = CAT_BA;
504 			*act_type = action;
505 			break;
506 		default:
507 			return QDF_STATUS_E_FAULT;
508 		}
509 		break;
510 	case IEEE80211_ACTION_CAT_SA_QUERY:
511 		switch (action) {
512 		case IEEE80211_ACTION_SA_QUERY_REQUEST:
513 		case IEEE80211_ACTION_SA_QUERY_RESPONSE:
514 			*cat_type = CAT_SA_QUERY;
515 			*act_type = action;
516 			break;
517 		default:
518 			return QDF_STATUS_E_FAULT;
519 		}
520 		break;
521 	default:
522 		return QDF_STATUS_E_FAULT;
523 	}
524 
525 	return QDF_STATUS_SUCCESS;
526 }
527 
528 /*
529  * iot_sim_action_frame_supported_by_fw - function to find if action frame is
530  *					  supported by fw or not
531  * @category: iot_sim specific category code
532  * @action: iot_sim specific action code
533  *
534  * Return: true if supported else false
535  */
536 bool
537 iot_sim_action_frame_supported_by_fw(uint8_t category, uint8_t action)
538 {
539 	switch (category) {
540 	case IEEE80211_ACTION_CAT_BA:
541 		switch (action) {
542 		case IEEE80211_ACTION_BA_ADDBA_REQUEST:
543 			return true;
544 		default:
545 			return false;
546 		}
547 	default:
548 		return false;
549 	}
550 }
551 
552 /*
553  * iot_sim_frame_supported_by_fw - function to find if frame is supported by fw
554  * @type: 802.11 frame type
555  * @subtype: 802.11 frame subtype
556  *
557  * Return: true if supported else false
558  */
559 bool
560 iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype, bool action)
561 {
562 	if (action)
563 		return iot_sim_action_frame_supported_by_fw(type, subtype);
564 
565 	switch (type << IEEE80211_FC0_TYPE_SHIFT) {
566 	case IEEE80211_FC0_TYPE_MGT:
567 		switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
568 		case IEEE80211_FC0_SUBTYPE_BEACON:
569 				return true;
570 		default:
571 				return false;
572 		}
573 	case IEEE80211_FC0_TYPE_CTL:
574 		switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
575 		case IEEE80211_FC0_SUBTYPE_TRIGGER:
576 		case IEEE80211_FC0_SUBTYPE_BAR:
577 		case IEEE80211_FC0_SUBTYPE_CTS:
578 		case IEEE80211_FC0_SUBTYPE_ACK:
579 		case IEEE80211_FC0_SUBTYPE_NDPA:
580 			return true;
581 		default:
582 			return false;
583 		}
584 	case IEEE80211_FC0_TYPE_DATA:
585 		switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
586 		default:
587 			return true;
588 		}
589 	default:
590 		return false;
591 	}
592 }
593 
594 /*
595  * iot_sim_remap_type_subtype - function to convert rules for response
596  *				type frame into request type. This is
597  *				used for drop/delay operation. This function
598  *				will update the passed type and subtype value.
599  *
600  * @type: 802.11 frame type
601  * @subtype: 802.11 frame subtype
602  * @seq: authentication sequence number, mostly 0 for non-authentication frame
603  * @action: flag to indicate action frame
604  *
605  * Return: QDF_STATUS_SUCCESS
606  */
607 QDF_STATUS
608 iot_sim_remap_type_subtype(uint8_t *type, uint8_t *subtype,
609 			   uint16_t *seq, bool action)
610 {
611 	if (action) {
612 		switch (*type) {
613 		case CAT_BA:
614 			switch (*subtype) {
615 			case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
616 				*subtype = IEEE80211_ACTION_BA_ADDBA_REQUEST;
617 				break;
618 			default:
619 				break;
620 			}
621 			break;
622 		default:
623 			break;
624 		}
625 		return QDF_STATUS_SUCCESS;
626 	}
627 
628 	switch (*type << IEEE80211_FC0_TYPE_SHIFT) {
629 	case IEEE80211_FC0_TYPE_MGT:
630 		switch (*subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
631 		case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
632 			*subtype = IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
633 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
634 			break;
635 		case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
636 			*subtype = IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
637 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
638 			break;
639 		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
640 			*subtype = IEEE80211_FC0_SUBTYPE_PROBE_REQ;
641 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
642 			break;
643 		case IEEE80211_FC0_SUBTYPE_AUTH:
644 			*subtype = IEEE80211_FC0_SUBTYPE_AUTH;
645 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
646 			/* If auth response (auth seq num 2) is marked as
647 			 * drop, then drop the auth request (auth seq num 1)
648 			 */
649 			if (*seq == IEEE80211_AUTH_OPEN_RESPONSE)
650 				*seq = IEEE80211_AUTH_OPEN_REQUEST;
651 			break;
652 		default:
653 			break;
654 		}
655 	default:
656 		break;
657 	}
658 
659 	return QDF_STATUS_SUCCESS;
660 }
661 
662 /*
663  * iot_sim_send_rule_to_fw - function to send iot_sim rule to fw
664  *
665  * @isc: iot sim context
666  * @oper: iot sim operation
667  * @mac: peer mac address
668  * @type: 802.11 frame type
669  * @subtype: 802.11 frame subtype
670  * @seq: authentication sequence number, mostly 0 for non-authentication frame
671  * @offset: user provided offset
672  * @frm: user provided frame content
673  * @length: length of frm
674  * @action: flag to indicate action frame
675  * @drop: flag to indicate set drop rule
676  * @clear: flag to indicate set rule or clear
677  *
678  * Return: QDF_STATUS_SUCCESS
679  */
680 QDF_STATUS
681 iot_sim_send_rule_to_fw(struct iot_sim_context *isc,
682 			enum iot_sim_operations oper,
683 			struct qdf_mac_addr *mac,
684 			uint8_t type, uint8_t subtype,
685 			uint16_t seq, uint16_t offset,
686 			uint8_t *frm, uint16_t len,
687 			bool action, bool clear)
688 {
689 	struct simulation_test_params param;
690 
691 	if (oper != DELAY && FRAME_TYPE_IS_BEACON(type, subtype) && offset) {
692 		iot_sim_info("Beacon update from offset:%d", offset);
693 		return QDF_STATUS_E_NOSUPPORT;
694 	}
695 
696 	if (iot_sim_frame_supported_by_fw(type, subtype, action)) {
697 		qdf_mem_zero(&param, sizeof(struct simulation_test_params));
698 		param.pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj);
699 		qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE);
700 		param.test_cmd_type = oper;
701 		/* subtype_cmd: Set subcmd based on action and clear flag */
702 		if (action) {
703 			if (clear)
704 				param.test_subcmd_type = DEL_RULE_ACTION;
705 			else
706 				param.test_subcmd_type = ADD_RULE_ACTION;
707 		} else {
708 			if (clear)
709 				param.test_subcmd_type = DEL_RULE;
710 			else
711 				param.test_subcmd_type = ADD_RULE;
712 		}
713 		param.frame_type = type;
714 		param.frame_subtype = subtype;
715 		param.seq = seq;
716 		param.offset = offset;
717 		param.frame_length = len;
718 		param.buf_len = len;
719 		param.bufp = frm;
720 		if (QDF_IS_STATUS_ERROR(tgt_send_simulation_cmd(isc->pdev_obj,
721 								&param)))
722 			iot_sim_err("Sending del rule to fw failed!");
723 
724 		if (FRAME_TYPE_IS_BEACON(type, subtype) && clear)
725 			return QDF_STATUS_E_NOSUPPORT;
726 
727 		return QDF_STATUS_SUCCESS;
728 	}
729 
730 	return QDF_STATUS_E_NOSUPPORT;
731 }
732 
733 /*
734  * iot_sim_del_rule - function to delete iot_sim rule
735  *
736  * @s_e: address of seq for which rule to be removed
737  * @f_e: address of the rule present in s_e to be removed
738  * @oper: iot sim operation
739  *
740  * Return: QDF_STATUS_SUCCESS
741  */
742 QDF_STATUS
743 iot_sim_del_rule(struct iot_sim_rule_per_seq **s_e,
744 		 struct iot_sim_rule **f_e,
745 		 enum iot_sim_operations oper,
746 		 struct iot_sim_context *isc)
747 {
748 	if (oper == CONTENT_CHANGE) {
749 		qdf_mem_free((*f_e)->frm_content);
750 		(*f_e)->frm_content = NULL;
751 	} else if (oper == DROP) {
752 		(*f_e)->drop = false;
753 	} else if (oper == DELAY) {
754 		if (!qdf_delayed_work_stop((*f_e)->dwork)) {
755 			iot_sim_err("delayed work is in running state");
756 			/* iot_sim_lock need to be released for the delay */
757 			/* work callback to complete execution */
758 			/* Hence releasing the lock */
759 			qdf_spin_unlock_bh(&isc->iot_sim_lock);
760 			/* iot_sim_delay_lock will be freed only after delay */
761 			/* work callback execution completion */
762 			qdf_spin_lock_bh(&(*f_e)->iot_sim_delay_lock);
763 			qdf_spin_lock_bh(&isc->iot_sim_lock);
764 			qdf_delayed_work_stop_sync((*f_e)->dwork);
765 			qdf_spin_unlock_bh(&(*f_e)->iot_sim_delay_lock);
766 		}
767 
768 		qdf_delayed_work_destroy((*f_e)->dwork);
769 		qdf_spinlock_destroy(&(*f_e)->iot_sim_delay_lock);
770 		qdf_mem_free((*f_e)->dwork->context);
771 		qdf_mem_free((*f_e)->dwork);
772 		qdf_nbuf_free((*f_e)->nbuf_list[0]);
773 		(*f_e)->nbuf_list[0] = NULL;
774 		qdf_nbuf_free((*f_e)->nbuf_list[1]);
775 		(*f_e)->nbuf_list[1] = NULL;
776 		(*f_e)->sec_buf = NULL;
777 		qdf_mem_free((*f_e)->rx_param);
778 		(*f_e)->rx_param = NULL;
779 	}
780 
781 	if (qdf_test_bit(oper, (unsigned long *)
782 			       &(*f_e)->rule_bitmap)) {
783 		(*s_e)->use_count--;
784 		qdf_clear_bit(oper, (unsigned long *)
785 				    &(*f_e)->rule_bitmap);
786 	}
787 
788 	if (!(*f_e)->rule_bitmap) {
789 		qdf_mem_free(*f_e);
790 		*f_e = NULL;
791 	}
792 	if ((*s_e)->use_count == 0) {
793 		qdf_mem_free(*s_e);
794 		*s_e = NULL;
795 	}
796 	return QDF_STATUS_SUCCESS;
797 }
798 
799 /*
800  * iot_sim_delete_rule_for_mac - function to delete content change rule
801  *                               for given peer mac
802  * @isc: iot sim context
803  * @oper: iot sim operation
804  * @seq: authentication sequence number, mostly 0 for non-authentication frame
805  * @type: 802.11 frame type
806  * @subtype: 802.11 frame subtype
807  * @mac: peer mac address
808  * @action: action frame or not
809  *
810  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise
811  */
812 QDF_STATUS
813 iot_sim_delete_rule_for_mac(struct iot_sim_context *isc,
814 			    enum iot_sim_operations oper,
815 			    uint16_t seq, uint8_t type,
816 			    uint8_t subtype,
817 			    struct qdf_mac_addr *mac,
818 			    bool action)
819 {
820 	QDF_STATUS status = QDF_STATUS_SUCCESS;
821 	struct iot_sim_rule_per_seq **s_e;
822 	struct iot_sim_rule **f_e;
823 	struct iot_sim_rule_per_peer *peer;
824 	bool peer_remove = 1, broadcast_peer = 0;
825 	uint8_t i;
826 
827 	if (qdf_is_macaddr_zero(mac))
828 		iot_sim_info("Rule deletion for all peers");
829 	else
830 		iot_sim_info("Rule deletion for " QDF_MAC_ADDR_STR,
831 			     QDF_MAC_ADDR_ARRAY(mac->bytes));
832 
833 	iot_sim_debug("oper:%s seq: %hu %s:%hu/%hu",
834 		      iot_sim_oper_to_str(oper), seq,
835 		      action ? "category/action code" : "type/subtype",
836 		      type, subtype);
837 
838 	if (!isc) {
839 		iot_sim_err("iot_sim: isc is null");
840 		return QDF_STATUS_E_FAILURE;
841 	}
842 
843 	if (oper == DROP || oper == DELAY)
844 		iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
845 
846 	if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac)) {
847 		peer = &isc->bcast_peer;
848 		broadcast_peer = 1;
849 	} else
850 		peer = iot_sim_find_peer_from_mac(isc, mac);
851 	if (peer) {
852 		qdf_spin_lock_bh(&isc->iot_sim_lock);
853 		s_e = &peer->rule_per_seq[seq];
854 		if (!*s_e) {
855 			qdf_spin_unlock_bh(&isc->iot_sim_lock);
856 			return QDF_STATUS_SUCCESS;
857 		}
858 
859 		if (action)
860 			f_e = &((*s_e)->rule_per_action_frm[type][subtype]);
861 		else
862 			f_e = &((*s_e)->rule_per_type[type][subtype]);
863 
864 		if (*f_e)
865 			status = iot_sim_del_rule(s_e, f_e, oper, isc);
866 
867 		for (i = 0; i < MAX_SEQ; i++)
868 			if (peer->rule_per_seq[i])
869 				peer_remove = 0;
870 		qdf_spin_unlock_bh(&isc->iot_sim_lock);
871 		if (!broadcast_peer && peer_remove) {
872 			iot_sim_remove_peer(isc, peer);
873 			qdf_mem_free(peer);
874 		}
875 	}
876 
877 	return status;
878 }
879 
880 /*
881  * iot_sim_delay_cb - Delayed work callback function
882  *                    to process delayed frames
883  *
884  * @context: Delayed work callback context
885  *
886  * Return: void
887  */
888 static void iot_sim_delay_cb(void *ctxt)
889 {
890 	struct wlan_objmgr_psoc *psoc = NULL;
891 	struct iot_sim_cb_context *context = ctxt;
892 
893 	qdf_spin_lock_bh(&context->piot_sim_rule->iot_sim_delay_lock);
894 	qdf_spin_lock_bh(&context->isc->iot_sim_lock);
895 	psoc = wlan_pdev_get_psoc(context->isc->pdev_obj);
896 	context->piot_sim_rule->sec_buf = context->piot_sim_rule->nbuf_list[0];
897 	qdf_spin_unlock_bh(&context->isc->iot_sim_lock);
898 	mgmt_txrx_rx_handler(psoc, context->piot_sim_rule->sec_buf,
899 			     context->piot_sim_rule->rx_param);
900 	qdf_spin_lock_bh(&context->isc->iot_sim_lock);
901 	if (context->piot_sim_rule->nbuf_list[1]) {
902 		context->piot_sim_rule->nbuf_list[0] =
903 					context->piot_sim_rule->nbuf_list[1];
904 		if (!qdf_delayed_work_start(context->piot_sim_rule->dwork,
905 					    context->
906 					    piot_sim_rule->delay_dur)) {
907 			iot_sim_err("delayed_work_start failed");
908 			qdf_nbuf_free(context->piot_sim_rule->nbuf_list[0]);
909 			qdf_mem_free(context->piot_sim_rule->
910 				     rx_param->rx_params);
911 			qdf_mem_free(context->piot_sim_rule->rx_param);
912 			context->piot_sim_rule->nbuf_list[0] = NULL;
913 			context->piot_sim_rule->rx_param = NULL;
914 		}
915 		context->piot_sim_rule->nbuf_list[1] = NULL;
916 	} else {
917 		context->piot_sim_rule->nbuf_list[0] = NULL;
918 		qdf_mem_free(context->piot_sim_rule->rx_param->rx_params);
919 		qdf_mem_free(context->piot_sim_rule->rx_param);
920 		context->piot_sim_rule->rx_param = NULL;
921 	}
922 
923 	qdf_spin_unlock_bh(&context->isc->iot_sim_lock);
924 	qdf_spin_unlock_bh(&context->piot_sim_rule->iot_sim_delay_lock);
925 }
926 
927 /*
928  * iot_sim_add_rule - function to add iot_sim rule
929  *
930  * @s_e: address of seq for which rule to be added
931  * @f_e: address of the rule present in s_e to be added
932  * @oper: iot sim operation
933  * @frm: user provided frame content
934  * @offset: user provided offset
935  * @len: length of the user provided frame content
936  * @isc: iot sim context
937  *
938  * Return: QDF_STATUS_SUCCESS
939  */
940 QDF_STATUS
941 iot_sim_add_rule(struct iot_sim_rule_per_seq **s_e,
942 		 struct iot_sim_rule **f_e,
943 		 enum iot_sim_operations oper,
944 		 uint8_t *frm, uint16_t offset, uint16_t len,
945 		 struct iot_sim_context *isc)
946 {
947 	struct iot_sim_cb_context *cb_context;
948 
949 	if (!*f_e) {
950 		*f_e = qdf_mem_malloc(sizeof(struct iot_sim_rule));
951 		if (!*f_e) {
952 			iot_sim_err("can't allocate f_e");
953 			return QDF_STATUS_E_NOMEM;
954 		}
955 	}
956 
957 	if (oper == CONTENT_CHANGE) {
958 		(*f_e)->frm_content = qdf_mem_malloc(len);
959 		if (!((*f_e)->frm_content))
960 			return QDF_STATUS_E_NOMEM;
961 		qdf_mem_copy((*f_e)->frm_content, frm, len);
962 		(*f_e)->len = len;
963 		(*f_e)->offset = offset;
964 	} else if (oper == DROP) {
965 		(*f_e)->drop = true;
966 	} else if (oper == DELAY) {
967 		(*f_e)->delay_dur = offset;
968 		(*f_e)->dwork = qdf_mem_malloc(sizeof(struct qdf_delayed_work));
969 		if (!(*f_e)->dwork) {
970 			iot_sim_err("can't allocate dwork");
971 			return QDF_STATUS_E_NOMEM;
972 		}
973 
974 		cb_context = qdf_mem_malloc(sizeof(struct iot_sim_cb_context));
975 		if (!cb_context) {
976 			iot_sim_err("can't allocate cb_context");
977 			qdf_mem_free((*f_e)->dwork);
978 			return QDF_STATUS_E_NOMEM;
979 		}
980 
981 		cb_context->isc = isc;
982 		cb_context->piot_sim_rule = *f_e;
983 		if (QDF_STATUS_SUCCESS !=
984 		    qdf_delayed_work_create((*f_e)->dwork, iot_sim_delay_cb,
985 					    cb_context)) {
986 			iot_sim_err("delayed_work_create failed");
987 			qdf_mem_free(cb_context);
988 			qdf_mem_free((*f_e)->dwork);
989 			return QDF_STATUS_E_NOMEM;
990 		}
991 
992 		(*f_e)->nbuf_list[0] = NULL;
993 		(*f_e)->nbuf_list[1] = NULL;
994 		iot_sim_err("delayed_work_created");
995 		qdf_spinlock_create(&((*f_e)->iot_sim_delay_lock));
996 	}
997 
998 	(*s_e)->use_count++;
999 	qdf_set_bit(oper, (unsigned long *)
1000 			  &(*f_e)->rule_bitmap);
1001 
1002 	return QDF_STATUS_SUCCESS;
1003 }
1004 
1005 /*
1006  * iot_sim_add_rule_for_mac - function to add content change rule
1007  *			      for given peer mac
1008  * @isc: iot sim context
1009  * @oper: iot sim operation
1010  * @mac: peer mac address
1011  * @type: 802.11 frame type
1012  * @subtype: 802.11 frame subtype
1013  * @seq: authentication sequence number, mostly 0 for non-authentication frame
1014  * @offset: user provided offset
1015  * @frm: user provided frame content
1016  * @len: length of frm
1017  * @action: boolean to indicate action frame
1018  *
1019  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise
1020  */
1021 QDF_STATUS
1022 iot_sim_add_rule_for_mac(struct iot_sim_context *isc,
1023 			 enum iot_sim_operations oper,
1024 			 struct qdf_mac_addr *mac,
1025 			 uint8_t type, uint8_t subtype,
1026 			 uint16_t seq, uint16_t offset,
1027 			 uint8_t *frm, uint16_t len,
1028 			 uint16_t drop, bool action)
1029 {
1030 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
1031 	struct iot_sim_rule_per_peer *peer;
1032 	struct iot_sim_rule_per_seq **s_e = NULL;
1033 	struct iot_sim_rule **f_e = NULL;
1034 
1035 	if (!isc) {
1036 		iot_sim_err("iot_sim: isc is null");
1037 		return status;
1038 	}
1039 
1040 	status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1041 					     type, subtype, mac,
1042 					     action);
1043 	if (status == QDF_STATUS_E_FAILURE) {
1044 		iot_sim_err("iot_sim: Rule removed - Fail");
1045 		return status;
1046 	}
1047 
1048 	if (oper == DROP || oper == DELAY)
1049 		iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
1050 
1051 	peer = iot_sim_find_peer_from_mac(isc, mac);
1052 	if (!peer)
1053 		peer = iot_sim_add_peer(isc, mac);
1054 	if (peer) {
1055 		qdf_spin_lock_bh(&isc->iot_sim_lock);
1056 		s_e = &peer->rule_per_seq[seq];
1057 		if (!*s_e) {
1058 			*s_e = qdf_mem_malloc(sizeof(struct
1059 					      iot_sim_rule_per_seq));
1060 			if (!*s_e) {
1061 				iot_sim_err("can't allocate s_e");
1062 				qdf_spin_unlock_bh(&isc->iot_sim_lock);
1063 				return QDF_STATUS_E_NOMEM;
1064 			}
1065 		}
1066 
1067 		if (action)
1068 			f_e = &((*s_e)->rule_per_action_frm[type][subtype]);
1069 		else
1070 			f_e = &((*s_e)->rule_per_type[type][subtype]);
1071 
1072 		if (qdf_is_macaddr_zero(mac))
1073 			iot_sim_info("Rule addition for all peers");
1074 		else
1075 			iot_sim_info("Rule addition for " QDF_MAC_ADDR_STR,
1076 				     QDF_MAC_ADDR_ARRAY(mac->bytes));
1077 
1078 		iot_sim_info("oper:%s seq: %hu %s:%hu/%hu delay:%hu",
1079 			     iot_sim_oper_to_str(oper), seq,
1080 			     action ? "category/action code" : "type/subtype",
1081 			     type, subtype, drop);
1082 
1083 		if (oper == DELAY)
1084 			offset = drop;
1085 
1086 		status = iot_sim_add_rule(s_e, f_e, oper, frm,
1087 					  offset, len, isc);
1088 		qdf_spin_unlock_bh(&isc->iot_sim_lock);
1089 	} else {
1090 		/* TBD: clear the rules for peer with address 'mac'*/
1091 	}
1092 
1093 	return status;
1094 }
1095 
1096 /*
1097  *                   IOT SIM User Command Format
1098  *
1099  * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1100  * | FrmType/subtype |  Seq  | Offset | Length | content | Mac Addr |
1101  * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1102  * |     1Byte       | 2Byte | 2Bytes | 2Bytes | Length  | 6 Bytes  |
1103  *
1104  */
1105 
1106 /*
1107  * iot_sim_debug_content_change_write - Write Handler for content change
1108  *					operation
1109  * @file: debugfs file pointer
1110  * @buf: buf of user input
1111  * @count: buf count
1112  * @ppos: offset on file
1113  *
1114  * Return: character read on success, failure otherwise
1115  */
1116 static ssize_t
1117 iot_sim_debug_content_change_write(struct file *file,
1118 				   const char __user *buf,
1119 				   size_t count, loff_t *ppos)
1120 {
1121 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1122 	unsigned char t_st, type, subtype, *content = NULL;
1123 	uint16_t offset = 0, length = 0, seq = 0;
1124 	char *locbuf = NULL;
1125 	enum iot_sim_operations oper = CONTENT_CHANGE;
1126 	struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
1127 	struct iot_sim_context *isc =
1128 			((struct seq_file *)file->private_data)->private;
1129 	uint8_t action = 0, category = 0;
1130 	bool is_action = 0, clear = false;
1131 	mlme_pdev_ext_t *ext = NULL;
1132 
1133 	if ((!buf) || (count > USER_BUF_LEN) || (count < 7))
1134 		return -EFAULT;
1135 
1136 	locbuf = qdf_mem_malloc(USER_BUF_LEN + 1);
1137 	if (!locbuf)
1138 		return -ENOMEM;
1139 
1140 	if (copy_from_user(locbuf, buf, count)) {
1141 		qdf_mem_free(locbuf);
1142 		return -EFAULT;
1143 	}
1144 
1145 	status = iot_sim_parse_user_input_content_change(isc, locbuf, count,
1146 							 &t_st, &seq, &offset,
1147 							 &length, &content,
1148 							 &mac_addr);
1149 	if (QDF_IS_STATUS_ERROR(status))
1150 		goto free;
1151 
1152 	type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
1153 	subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
1154 	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
1155 
1156 	if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
1157 		goto free;
1158 
1159 	if (FRAME_TYPE_IS_ACTION(type, subtype)) {
1160 		status = iot_sim_parse_action_frame(length, offset, content,
1161 						    &category, &action);
1162 		if (QDF_IS_STATUS_ERROR(status))
1163 			goto free;
1164 
1165 		is_action = 1;
1166 		type = category;
1167 		subtype = action;
1168 	}
1169 
1170 	clear = length ? false : true;
1171 	status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
1172 					 seq, offset, content, length,
1173 					 is_action, clear);
1174 	if (QDF_IS_STATUS_SUCCESS(status))
1175 		goto free;
1176 
1177 	/* check for rule removal */
1178 	if (!length || !content) {
1179 		status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1180 						     type, subtype,
1181 						     &mac_addr,
1182 						     is_action);
1183 
1184 	} else {
1185 		status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
1186 						  type, subtype, seq, offset,
1187 						  content, length, 0,
1188 						  is_action);
1189 	}
1190 	if (QDF_IS_STATUS_SUCCESS(status)) {
1191 		iot_sim_err("iot_sim: Content Change Operation - success");
1192 		if (FRAME_TYPE_IS_BEACON(type, subtype)) {
1193 			if (isc->bcn_buf && (!length || !content)) {
1194 				qdf_nbuf_free(isc->bcn_buf);
1195 				isc->bcn_buf = NULL;
1196 			}
1197 			ext = wlan_pdev_mlme_get_ext_hdl(isc->pdev_obj);
1198 			if (ext) {
1199 				isc->iot_sim_update_beacon_trigger(ext);
1200 				iot_sim_info("Beacon update triggered");
1201 			} else {
1202 				iot_sim_err("mlme_pdev_ext is null");
1203 			}
1204 		}
1205 	} else {
1206 		iot_sim_err("iot_sim: Content Change Operation - Fail");
1207 	}
1208 free:
1209 	qdf_mem_free(content);
1210 	qdf_mem_free(locbuf);
1211 	return count;
1212 }
1213 
1214 /*
1215  * iot_sim_parse_user_input_delay - function to parse user input into
1216  *				   predefined format for delay operation.
1217  *				   All arguments passed will be filled
1218  *				   upon success
1219  * @isc: iot sim context
1220  * @userbuf: local copy of user input
1221  * @count: length of userbuf
1222  * @t_st: address of type variable
1223  * @seq: address of seq variable
1224  * @cat_type: 802.11 action frame category code
1225  * @act_type: 802.11 action frame action code
1226  * @delay: address of delay variable
1227  * @addr: pointer to mac address
1228  *
1229  * Return: QDF_STATUS_SUCCESS on success
1230  *	   QDF_STATUS_E_FAILURE otherwise
1231  */
1232 QDF_STATUS
1233 iot_sim_parse_user_input_delay(struct iot_sim_context *isc,
1234 			       char *userbuf, ssize_t count,
1235 			       uint8_t *t_st, uint16_t *seq,
1236 			       uint8_t *cat_type, uint8_t *act_type,
1237 			       uint16_t *delay, struct qdf_mac_addr *addr)
1238 {
1239 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1240 	char *argv[6], *delim = " ", *substr;
1241 	int argc = -1, ret = 0;
1242 
1243 	qdf_mem_zero(argv, sizeof(argv));
1244 	userbuf = qdf_str_trim(userbuf);
1245 
1246 	while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
1247 		if (!isspace(*substr) && *substr != '\0')
1248 			argv[++argc] = substr;
1249 		if (argc >= 5)
1250 			break;
1251 	}
1252 
1253 	if (argc < 3) {
1254 		iot_sim_err("Invalid argument count %d", (argc + 1));
1255 		return status;
1256 	}
1257 
1258 	if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) {
1259 		iot_sim_err("One or more arguments are null");
1260 		return status;
1261 	}
1262 	/*
1263 	 * User can send delay data in following format:
1264 	 * 1. Add delay rule for specific peer
1265 	 *	<t_st> <seq> <category_type> <action_type> <delay> <MAC>
1266 	 * 2. Remove delay rule for specific peer
1267 	 *	<t_st> <seq> <category_type> <action_type> <delay> <MAC>
1268 	 */
1269 
1270 	ret = kstrtou8(argv[0], 16, t_st);
1271 	if (ret)
1272 		goto err;
1273 	ret = kstrtou16(argv[1], 10, seq);
1274 	if (ret)
1275 		goto err;
1276 	ret = kstrtou8(argv[2], 10, cat_type);
1277 	if (ret)
1278 		goto err;
1279 	ret = kstrtou8(argv[3], 10, act_type);
1280 	if (ret)
1281 		goto err;
1282 	ret = kstrtou16(argv[4], 10, delay);
1283 	if (ret)
1284 		goto err;
1285 
1286 	/*
1287 	 * If argv[5] is valid, this must be mac address
1288 	 */
1289 	if (argv[5])
1290 		status = qdf_mac_parse(argv[5], addr);
1291 
1292 	iot_sim_err("delay rule mac address " QDF_MAC_ADDR_STR,
1293 		    QDF_MAC_ADDR_ARRAY(addr->bytes));
1294 
1295 	return status;
1296 err:
1297 	iot_sim_err("kstrtoXX failed: %d", ret);
1298 	return QDF_STATUS_E_FAILURE;
1299 }
1300 
1301 /*
1302  * iot_sim_debug_delay_write - Write Handler for delay operation
1303  * @file: debugfs file pointer
1304  * @buf: buf of user input
1305  * @count: buf count
1306  * @ppos: offset on file
1307  *
1308  * Return: character read
1309  */
1310 static ssize_t
1311 iot_sim_debug_delay_write(struct file *file,
1312 			  const char __user *buf,
1313 			  size_t count, loff_t *ppos)
1314 {
1315 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1316 	unsigned char t_st, type, subtype;
1317 	uint16_t seq = 0;
1318 	char *locbuf = NULL;
1319 	enum iot_sim_operations oper = DELAY;
1320 	struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
1321 	struct iot_sim_context *isc =
1322 			((struct seq_file *)file->private_data)->private;
1323 	uint8_t action = 0, category = 0, tmp[2];
1324 	bool is_action = false, clear = false;
1325 	uint16_t delay = 0;
1326 
1327 	if ((!buf) || (count > USER_BUF_LEN_DELAY) || (count < 6))
1328 		return -EFAULT;
1329 
1330 	locbuf = qdf_mem_malloc(USER_BUF_LEN_DELAY + 1);
1331 	if (!locbuf)
1332 		return -ENOMEM;
1333 
1334 	if (copy_from_user(locbuf, buf, count)) {
1335 		qdf_mem_free(locbuf);
1336 		return -EFAULT;
1337 	}
1338 
1339 	status = iot_sim_parse_user_input_delay(isc, locbuf, count,
1340 						&t_st, &seq, &category,
1341 						&action, &delay, &mac_addr);
1342 	if (QDF_IS_STATUS_ERROR(status)) {
1343 		iot_sim_err("iot_sim_parse_user_input_delay failed");
1344 		goto free;
1345 	}
1346 	iot_sim_err("Delay rule t_st:%d, seq:%hu cat_type:%d, act_type:%d, delay:%hu",
1347 		    t_st, seq, category, action, delay);
1348 
1349 	type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
1350 	subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
1351 	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
1352 
1353 	if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
1354 		goto free;
1355 
1356 	if (FRAME_TYPE_IS_ACTION(type, subtype)) {
1357 		tmp[0] = category;
1358 		tmp[1] = action;
1359 		/*
1360 		 * convert 802.11 category and action code to iot sim codes
1361 		 */
1362 		status = iot_sim_get_index_for_action_frm(tmp, &category,
1363 							  &action, false);
1364 		if (QDF_IS_STATUS_ERROR(status))
1365 			goto free;
1366 
1367 		is_action = 1;
1368 		type = category;
1369 		subtype = action;
1370 	}
1371 
1372 	clear = delay ? false : true;
1373 	status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
1374 					 seq, delay, NULL, 0, is_action, clear);
1375 	if (QDF_IS_STATUS_SUCCESS(status))
1376 		goto free;
1377 
1378 	/* check for rule removal */
1379 	if (!delay) {
1380 		status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1381 						     type, subtype,
1382 						     &mac_addr,
1383 						     is_action);
1384 	} else {
1385 		status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
1386 						  type, subtype, seq, 0,
1387 						  NULL, 0, delay, is_action);
1388 	}
1389 	if (QDF_IS_STATUS_SUCCESS(status))
1390 		iot_sim_debug("iot_sim: Rule update Delay Operation - Success");
1391 	else
1392 		iot_sim_err("iot_sim: Rule update Delay Operation - Fail");
1393 free:
1394 	qdf_mem_free(locbuf);
1395 	return count;
1396 }
1397 
1398 /*
1399  * iot_sim_parse_user_input_drop - function to parse user input into
1400  *				   predefined format for drop operation.
1401  *				   All arguments passed will be filled
1402  *				   upon success
1403  * @isc: iot sim context
1404  * @userbuf: local copy of user input
1405  * @count: length of userbuf
1406  * @t_st: address of type variable
1407  * @seq: address of seq variable
1408  * @cat_type: 802.11 action frame category code
1409  * @act_type: 802.11 action frame action code
1410  * @drop: address of drop variable to specify drop the frame or not
1411  * @addr: pointer to mac address
1412  *
1413  * Return: QDF_STATUS_SUCCESS on success
1414  *	   QDF_STATUS_E_FAILURE otherwise
1415  */
1416 QDF_STATUS
1417 iot_sim_parse_user_input_drop(struct iot_sim_context *isc,
1418 			      char *userbuf, ssize_t count,
1419 			      uint8_t *t_st, uint16_t *seq,
1420 			      uint8_t *cat_type, uint8_t *act_type,
1421 			      uint8_t *drop, struct qdf_mac_addr *addr)
1422 {
1423 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1424 	char *argv[6], *delim = " ", *substr;
1425 	int argc = -1, ret = 0;
1426 
1427 	qdf_mem_zero(argv, sizeof(argv));
1428 	userbuf = qdf_str_trim(userbuf);
1429 
1430 	while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
1431 		if (!isspace(*substr) && *substr != '\0')
1432 			argv[++argc] = substr;
1433 		if (argc >= 5)
1434 			break;
1435 	}
1436 
1437 	if (argc < 3) {
1438 		iot_sim_err("Invalid argument count %d", (argc + 1));
1439 		return status;
1440 	}
1441 
1442 	if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) {
1443 		iot_sim_err("One or more arguments are null");
1444 		return status;
1445 	}
1446 	/*
1447 	 * User can send drop data in following format:
1448 	 * 1. Add drop rule for specific peer
1449 	 *	<t_st> <seq> <category_type> <action_type> <drop> <MAC>
1450 	 * 2. Add drop rule for broadcast peer
1451 	 *	<t_st> <seq> <category_type> <action_type> <drop>
1452 	 * 3. Remove drop rule for specific peer
1453 	 *	<t_st> <seq> <category_type> <action_type> <drop> <MAC>
1454 	 * 4. Remove drop rule for broadcast peer
1455 	 *	<t_st> <seq> <category_type> <action_type> <drop> <BCAST_MAC>
1456 	 * 5. Remove drop rule for all peer
1457 	 *	<t_st> <seq> <category_type> <action_type> <drop>
1458 	 */
1459 
1460 	ret = kstrtou8(argv[0], 16, t_st);
1461 	if (ret)
1462 		goto err;
1463 	ret = kstrtou16(argv[1], 10, seq);
1464 	if (ret)
1465 		goto err;
1466 	ret = kstrtou8(argv[2], 10, cat_type);
1467 	if (ret)
1468 		goto err;
1469 	ret = kstrtou8(argv[3], 10, act_type);
1470 	if (ret)
1471 		goto err;
1472 	ret = kstrtou8(argv[4], 10, drop);
1473 	if (ret)
1474 		goto err;
1475 
1476 	/*
1477 	 * If argv[5] is valid, this must be mac address
1478 	 */
1479 	if (argv[5])
1480 		status = qdf_mac_parse(argv[5], addr);
1481 
1482 	iot_sim_err("drop rule mac address " QDF_MAC_ADDR_STR,
1483 		    QDF_MAC_ADDR_ARRAY(addr->bytes));
1484 
1485 	return status;
1486 err:
1487 	iot_sim_err("kstrtoXX failed: %d", ret);
1488 	return QDF_STATUS_E_FAILURE;
1489 }
1490 
1491 /*
1492  * iot_sim_debug_drop_write - Write Handler for drop operation
1493  * @file: debugfs file pointer
1494  * @buf: buf of user input
1495  * @count: buf count
1496  * @ppos: offset on file
1497  *
1498  * Return: character read
1499  */
1500 static ssize_t
1501 iot_sim_debug_drop_write(struct file *file,
1502 			 const char __user *buf,
1503 			 size_t count, loff_t *ppos)
1504 {
1505 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1506 	unsigned char t_st, type, subtype;
1507 	uint16_t seq = 0;
1508 	char *locbuf = NULL;
1509 	enum iot_sim_operations oper = DROP;
1510 	struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
1511 	struct iot_sim_context *isc =
1512 			((struct seq_file *)file->private_data)->private;
1513 	uint8_t action = 0, category = 0, tmp[2], drop = 0;
1514 	bool is_action = false, clear = false;
1515 
1516 	if ((!buf) || (count > USER_BUF_LEN_DROP) || (count < 6))
1517 		return -EFAULT;
1518 
1519 	locbuf = qdf_mem_malloc(USER_BUF_LEN_DROP + 1);
1520 	if (!locbuf)
1521 		return -ENOMEM;
1522 
1523 	if (copy_from_user(locbuf, buf, count)) {
1524 		qdf_mem_free(locbuf);
1525 		return -EFAULT;
1526 	}
1527 
1528 	status = iot_sim_parse_user_input_drop(isc, locbuf, count,
1529 					       &t_st, &seq, &category,
1530 					       &action, &drop, &mac_addr);
1531 	if (QDF_IS_STATUS_ERROR(status))
1532 		goto free;
1533 
1534 	type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
1535 	subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
1536 	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
1537 
1538 	if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
1539 		goto free;
1540 
1541 	if (FRAME_TYPE_IS_ACTION(type, subtype)) {
1542 		tmp[0] = category;
1543 		tmp[1] = action;
1544 		/*
1545 		 * convert 802.11 category and action code to iot sim codes
1546 		 */
1547 		status = iot_sim_get_index_for_action_frm(tmp, &category,
1548 							  &action, false);
1549 		if (QDF_IS_STATUS_ERROR(status))
1550 			goto free;
1551 
1552 		is_action = 1;
1553 		type = category;
1554 		subtype = action;
1555 	}
1556 
1557 	clear = drop ? false : true;
1558 	status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
1559 					 seq, 0, NULL, 0, is_action, clear);
1560 	if (QDF_IS_STATUS_SUCCESS(status))
1561 		goto free;
1562 
1563 	/* check for rule removal */
1564 	if (!drop) {
1565 		status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1566 						     type, subtype,
1567 						     &mac_addr,
1568 						     is_action);
1569 	} else {
1570 		status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
1571 						  type, subtype, seq, 0,
1572 						  NULL, 0, drop, is_action);
1573 	}
1574 	if (QDF_IS_STATUS_SUCCESS(status))
1575 		iot_sim_debug("iot_sim: Rule update Drop Operation - Success");
1576 	else
1577 		iot_sim_err("iot_sim: Rule update Drop Operation - Fail");
1578 free:
1579 	qdf_mem_free(locbuf);
1580 	return count;
1581 }
1582 
1583 /*
1584  * debug_iot_sim_##func_base##_show() - debugfs functions to display content
1585  *                                      dummy function
1586  * Return: success
1587  */
1588 #define GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(func_base)			\
1589 	static int iot_sim_debug_##func_base##_show(struct seq_file *m,	\
1590 						    void *v)		\
1591 {									\
1592 	return qdf_status_to_os_return(QDF_STATUS_SUCCESS);		\
1593 }
1594 
1595 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(content_change);
1596 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(delay);
1597 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(drop);
1598 
1599 /*
1600  * debug_##func_base##_open() - Open debugfs entry for respective command
1601  * and event buffer.
1602  *
1603  * @inode: node for debug dir entry
1604  * @file: file handler
1605  *
1606  * Return: open status
1607  */
1608 #define GENERATE_DEBUG_IOT_SIM_STRUCTS(func_base)			\
1609 	static int debug_##func_base##_open(struct inode *inode,	\
1610 					    struct file *file)		\
1611 {									\
1612 	return single_open(file, iot_sim_debug_##func_base##_show,	\
1613 			   inode->i_private);				\
1614 }									\
1615 									\
1616 static const struct file_operations debug_##func_base##_ops = {		\
1617 	.open           = debug_##func_base##_open,			\
1618 	.read           = seq_read,					\
1619 	.llseek         = seq_lseek,					\
1620 	.write          = iot_sim_debug_##func_base##_write,		\
1621 	.release        = single_release,				\
1622 }
1623 
1624 GENERATE_DEBUG_IOT_SIM_STRUCTS(content_change);
1625 GENERATE_DEBUG_IOT_SIM_STRUCTS(drop);
1626 GENERATE_DEBUG_IOT_SIM_STRUCTS(delay);
1627 
1628 /* Structure to maintain debug information */
1629 struct iot_sim_dbgfs_file {
1630 	const char *name;
1631 	const struct file_operations *ops;
1632 };
1633 
1634 #define DEBUG_IOT_SIM(func_base) {	.name = #func_base,		\
1635 					.ops = &debug_##func_base##_ops	\
1636 }
1637 
1638 struct iot_sim_dbgfs_file iot_sim_dbgfs_files[IOT_SIM_DEBUGFS_FILE_NUM] = {
1639 	DEBUG_IOT_SIM(content_change),
1640 	DEBUG_IOT_SIM(drop),
1641 	DEBUG_IOT_SIM(delay),
1642 };
1643 
1644 /**
1645  * iot_sim_debugfs_deinit() - Deinit functions to remove debugfs directory and
1646  *			      it's file enteries.
1647  * @isc: iot_sim context
1648  *
1649  * Return: init status
1650  */
1651 static QDF_STATUS
1652 iot_sim_debugfs_deinit(struct iot_sim_context *isc)
1653 {
1654 	debugfs_remove_recursive(isc->iot_sim_dbgfs_ctx.iot_sim_dir_de);
1655 
1656 	return QDF_STATUS_SUCCESS;
1657 }
1658 
1659 /*
1660  * iot_sim_remove_all_oper_rules - Function to remove all configured rules
1661  *				   for given operation
1662  *
1663  * @isc: iot sim context
1664  * @oper: iot sim operation
1665  *
1666  * Return: void
1667  */
1668 static void
1669 iot_sim_remove_all_oper_rules(struct iot_sim_context *isc,
1670 			      enum iot_sim_operations oper)
1671 {
1672 	uint16_t seq;
1673 	uint8_t type, subtype, category = 0, action = 0;
1674 	struct qdf_mac_addr zero_mac_addr = QDF_MAC_ADDR_ZERO_INIT;
1675 
1676 	for (seq = 0; seq < MAX_SEQ; seq++) {
1677 		/* Remove rules for non-action type frames */
1678 		for (type = 0; type < N_FRAME_TYPE; type++)
1679 			for (subtype = 0; subtype < N_FRAME_SUBTYPE; subtype++)
1680 				iot_sim_delete_rule_for_mac(isc, oper, seq,
1681 							    type, subtype,
1682 							    &zero_mac_addr, 0);
1683 		/* Remove rules for action frames */
1684 		for (category = 0; category < IOT_SIM_MAX_CAT; category++)
1685 			for (action = 0; action < MAX_ACTION; action++)
1686 				iot_sim_delete_rule_for_mac(isc, oper, seq,
1687 							    category, action,
1688 							    &zero_mac_addr, 1);
1689 	}
1690 }
1691 
1692 /*
1693  * iot_sim_remove_all_rules - Function to remove all configured rules
1694  *
1695  * @isc: iot sim context
1696  *
1697  * Return: void
1698  */
1699 static void
1700 iot_sim_remove_all_rules(struct iot_sim_context *isc)
1701 {
1702 	enum iot_sim_operations oper;
1703 
1704 	if (!isc)
1705 		return;
1706 
1707 	for (oper = CONTENT_CHANGE; oper < IOT_SIM_MAX_OPERATION; oper++)
1708 		iot_sim_remove_all_oper_rules(isc, oper);
1709 }
1710 
1711 /**
1712  * iot_sim_debugfs_init() - debugfs functions to create debugfs directory and to
1713  *			    create debugfs enteries.
1714  * @isc: iot_sim context
1715  *
1716  * Return: init status
1717  */
1718 static QDF_STATUS
1719 iot_sim_debugfs_init(struct iot_sim_context *isc)
1720 {
1721 	struct dentry *dbgfs_dir = NULL;
1722 	struct dentry *de = NULL;
1723 	uint8_t i, pdev_id;
1724 	char buf[32];
1725 
1726 	if (!isc)
1727 		return QDF_STATUS_E_FAILURE;
1728 
1729 	pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj);
1730 
1731 	qdf_mem_zero(buf, sizeof(buf));
1732 	snprintf(buf, sizeof(buf), "iot_sim_pdev%u", pdev_id);
1733 
1734 	dbgfs_dir = debugfs_create_dir(buf, NULL);
1735 	isc->iot_sim_dbgfs_ctx.iot_sim_dir_de = dbgfs_dir;
1736 
1737 	if (!isc->iot_sim_dbgfs_ctx.iot_sim_dir_de) {
1738 		iot_sim_err("dbgfs dir creation failed for pdev%u", pdev_id);
1739 		return QDF_STATUS_E_FAILURE;
1740 	}
1741 
1742 	for (i = 0; i < IOT_SIM_DEBUGFS_FILE_NUM; ++i) {
1743 		de = debugfs_create_file(iot_sim_dbgfs_files[i].name,
1744 					 0644,
1745 					 dbgfs_dir, isc,
1746 					 iot_sim_dbgfs_files[i].ops);
1747 
1748 		if (!de) {
1749 			iot_sim_err("dbgfs file creation failed for pdev%u",
1750 				    pdev_id);
1751 			goto out;
1752 		}
1753 		isc->iot_sim_dbgfs_ctx.iot_sim_file_de[i] = de;
1754 	}
1755 
1756 	return QDF_STATUS_SUCCESS;
1757 
1758 out:
1759 	debugfs_remove_recursive(dbgfs_dir);
1760 	qdf_mem_set(isc->iot_sim_dbgfs_ctx.iot_sim_file_de,
1761 		    sizeof(isc->iot_sim_dbgfs_ctx.iot_sim_file_de), 0);
1762 
1763 	return QDF_STATUS_E_FAILURE;
1764 }
1765 
1766 QDF_STATUS
1767 wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
1768 {
1769 	struct iot_sim_context *isc = NULL;
1770 
1771 	if (!pdev) {
1772 		iot_sim_err("pdev is NULL");
1773 		return QDF_STATUS_E_NULL_VALUE;
1774 	}
1775 
1776 	isc = qdf_mem_malloc(sizeof(struct iot_sim_context));
1777 	if (!isc)
1778 		return QDF_STATUS_E_NOMEM;
1779 
1780 	isc->pdev_obj = pdev;
1781 
1782 	if (QDF_IS_STATUS_ERROR(iot_sim_debugfs_init(isc))) {
1783 		qdf_mem_free(isc);
1784 		iot_sim_info("iot_sim debugfs file creation failed");
1785 		return QDF_STATUS_E_FAILURE;
1786 	}
1787 
1788 	qdf_set_macaddr_broadcast(&isc->bcast_peer.addr);
1789 	qdf_spinlock_create(&isc->iot_sim_lock);
1790 	qdf_list_create(&isc->peer_list, 2);
1791 	isc->bcn_buf = NULL;
1792 
1793 	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_IOT_SIM_COMP,
1794 					      (void *)isc, QDF_STATUS_SUCCESS);
1795 
1796 	iot_sim_debug("iot_sim component pdev%u object created",
1797 		      wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj));
1798 
1799 	return QDF_STATUS_SUCCESS;
1800 }
1801 
1802 QDF_STATUS
1803 wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev,
1804 				      void *arg)
1805 {
1806 	struct iot_sim_context *isc = NULL;
1807 
1808 	if (!pdev) {
1809 		iot_sim_err("pdev is NULL");
1810 		return QDF_STATUS_E_NULL_VALUE;
1811 	}
1812 
1813 	isc = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1814 						    WLAN_IOT_SIM_COMP);
1815 	if (isc) {
1816 		wlan_objmgr_pdev_component_obj_detach(pdev,
1817 						      WLAN_IOT_SIM_COMP,
1818 						      (void *)isc);
1819 		/* Deinitilise function pointers from iot_sim context */
1820 		iot_sim_debugfs_deinit(isc);
1821 		iot_sim_remove_all_rules(isc);
1822 		qdf_list_destroy(&isc->peer_list);
1823 		if (isc->bcn_buf)
1824 			qdf_nbuf_free(isc->bcn_buf);
1825 		qdf_spinlock_destroy(&isc->iot_sim_lock);
1826 		qdf_mem_free(isc);
1827 	}
1828 	iot_sim_debug("iot_sim component pdev%u object destroyed",
1829 		      wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj));
1830 
1831 	return QDF_STATUS_SUCCESS;
1832 }
1833 
1834