xref: /wlan-dirver/qca-wifi-host-cmn/iot_sim/core/iot_sim_common.c (revision 6d768494e5ce14eb1603a695c86739d12ecc6ec2)
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 <wmi_unified_param.h>
25 #include <wlan_iot_sim_utils_api.h>
26 
27 /*
28  * iot_sim_oper_to_str - function to return iot sim operation string
29  * @oper: iot sim operation
30  *
31  * Return: string pointer
32  */
33 uint8_t *
34 iot_sim_oper_to_str(enum iot_sim_operations oper)
35 {
36 	switch (oper) {
37 	case CONTENT_CHANGE:
38 		return "content change";
39 	case DELAY:
40 		return "delay";
41 	case DROP:
42 		return "drop";
43 	default:
44 		return "invalid";
45 	}
46 }
47 
48 /*
49  * iot_sim_convert_offset_to_hex_str - function to convert offset into binary
50  * @offset: user provided offset value while action frame rule deletion
51  * @hex: buffer to store converted value
52  * @count: size of hex buffer
53  *
54  * Return: string pointer
55  */
56 QDF_STATUS
57 iot_sim_convert_offset_to_hex_str(uint16_t offset, uint8_t *hex, int8_t count)
58 {
59 	uint8_t temp[5];
60 	int ret;
61 
62 	snprintf(temp, sizeof(temp), "%04u", offset);
63 
64 	ret = qdf_hex_str_to_binary(hex, temp, count);
65 	if (ret == -1) {
66 		iot_sim_err("offset to hex conversion failed");
67 		return QDF_STATUS_E_FAILURE;
68 	}
69 
70 	return QDF_STATUS_SUCCESS;
71 }
72 
73 /*
74  * iot_sim_parse_action_frame - function to parse action frame to decode
75  *                              category and action code
76  *
77  * @length: length for content provided by user
78  * @offset: offset provided by user
79  * @content: user provided content
80  * @category: buffer to store iot specific category code
81  * @action: buffer to store iot specific action code
82  *
83  * Return: QDF_STATUS_SUCCESS on success otherwise failure
84  */
85 QDF_STATUS
86 iot_sim_parse_action_frame(uint16_t length, uint16_t offset, uint8_t *content,
87 			   uint8_t *category, uint8_t *action)
88 {
89 	QDF_STATUS status = QDF_STATUS_SUCCESS;
90 	uint8_t hex[2], *ptr = NULL;
91 
92 	if (!length) {
93 		status = iot_sim_convert_offset_to_hex_str(offset, hex,
94 							   sizeof(hex));
95 		if (QDF_IS_STATUS_ERROR(status))
96 			return status;
97 
98 		/* Offset represet category type and action type */
99 		status = iot_sim_get_index_for_action_frm(hex, category,
100 							  action);
101 		if (status == QDF_STATUS_E_FAULT) {
102 			iot_sim_err("Get indices for action failed");
103 			return status;
104 		}
105 	} else if (length && content) {
106 		/* if offset is zero, move ptr post header */
107 		if (offset == 0) {
108 			ptr = content + sizeof(struct ieee80211_frame);
109 		} else if (offset == sizeof(struct ieee80211_frame)) {
110 			ptr = content;
111 		} else {
112 			iot_sim_err("wrong offset for action frame content");
113 			return QDF_STATUS_E_FAILURE;
114 		}
115 		status = iot_sim_get_index_for_action_frm(ptr, category,
116 							  action);
117 	}
118 	return status;
119 }
120 
121 /*
122  * iot_sim_find_peer_from_mac - function to find the iot sim peer data
123  *                                    based on the mac address provided
124  *
125  * @isc: iot_sim pdev private object
126  * @mac: mac address of the peer
127  *
128  * Return: iot_sim_rule_per_peer reference if exists else NULL
129  */
130 struct iot_sim_rule_per_peer *
131 iot_sim_find_peer_from_mac(struct iot_sim_context *isc,
132 			   struct qdf_mac_addr *mac)
133 {
134 	if (qdf_is_macaddr_zero(mac) || qdf_is_macaddr_broadcast(mac))
135 		return &isc->bcast_peer;
136 	else
137 		return NULL;
138 }
139 
140 /*
141  * iot_sim_validate_content - function to validate frame content. User provided
142  *			      content must be either full frame or full frame
143  *			      body or valid TLV formatted data.
144  * @buf: pointer to frame content in binary format
145  * @total_len: length of content
146  * @offset: offset provided by user
147  *
148  * Return: QDF_STATUS_SUCCESS on success
149  *	   QDF_STATUS_E_FAULT on failure
150  */
151 static QDF_STATUS
152 iot_sim_validate_content(uint8_t *buf,
153 			 uint16_t total_len,
154 			 uint16_t offset)
155 {
156 	char *ie = buf;
157 	uint32_t len = 0, i = 0;
158 	uint32_t fb = sizeof(struct ieee80211_frame);
159 
160 	if (offset == 0 || offset == fb) {
161 		/* Replace the entire content set by user */
162 		return QDF_STATUS_SUCCESS;
163 	}
164 
165 	/* Check for malformed IEs and proper IE
166 	 * boundaries in user content
167 	 */
168 	for (i = 0; i < total_len;) {
169 		/* TLV: T(1) + L(1) + V(L)*/
170 		len = (1 + 1 + ie[1]);
171 		i += len;
172 		ie += len;
173 	}
174 
175 	if (i == total_len)
176 		return QDF_STATUS_SUCCESS;
177 
178 	iot_sim_err("iot_sim: cnt(bin) len:%u IE Parsed len:%u",
179 		    total_len,
180 		    i);
181 
182 	return QDF_STATUS_E_INVAL;
183 }
184 
185 /*
186  * iot_sim_handle_frame_content - function to process frame content provided
187  *				  by user. This function will convert the ascii
188  *				  string into binary string and validate the
189  *				  content.
190  * @isc: iot sim context
191  * @pos: position to the frame content in the user buffer
192  * @storage: storage to store frame content after processing
193  * @offset: user provided offset
194  * @len: length of the user provided content in bytes
195  *
196  * Return: QDF_STATUS_SUCCESS on success
197  *	   QDF_STATUS_E_FAULT on hex str to binary conversion failure
198  *	   QDF_STATUS_E_NOMEM on memory allocation failure
199  */
200 QDF_STATUS
201 iot_sim_handle_frame_content(struct iot_sim_context *isc,
202 			     const char *pos,
203 			     uint8_t **storage,
204 			     uint16_t offset,
205 			     uint16_t len)
206 {
207 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
208 	int ret;
209 
210 	*storage = qdf_mem_malloc(len);
211 	if (!*storage) {
212 		iot_sim_err("iot_sim:storage allocation failed");
213 		return QDF_STATUS_E_NOMEM;
214 	}
215 
216 	ret = qdf_hex_str_to_binary(*storage, pos, len);
217 	if (ret == -1) {
218 		iot_sim_err("iot_sim:hex2bin conversion failed");
219 		status = QDF_STATUS_E_FAULT;
220 		goto error;
221 	}
222 
223 	status = iot_sim_validate_content(*storage, len, offset);
224 	if (QDF_IS_STATUS_ERROR(status)) {
225 		iot_sim_err("iot_sim:User Content Invalid");
226 		goto error;
227 	}
228 
229 	return QDF_STATUS_SUCCESS;
230 
231 error:
232 	qdf_mem_free(*storage);
233 	*storage = NULL;
234 	return status;
235 }
236 
237 /*
238  * iot_sim_parse_user_input_content_change - function to parse user input into
239  *					     predefined format for content
240  *					     change operation. All arguments
241  *					     passed will be filled upon success
242  * @isc: iot sim context
243  * @userbuf: local copy of user input
244  * @count: length of userbuf
245  * @t_st: address of type variable
246  * @seq: address of seq variable
247  * @offset: address of offset variable
248  * @length: address of length variable
249  * @content: double pointer to storage to store frame content after processing
250  * @addr: pointer to mac address
251  *
252  * @storage: storage to store frame content after processing
253  * @offset: user provided offset
254  * @len: length of the user provided content in bytes
255  *
256  * Return: QDF_STATUS_SUCCESS on success
257  *	   QDF_STATUS_E_FAILURE otherwise
258  */
259 QDF_STATUS
260 iot_sim_parse_user_input_content_change(struct iot_sim_context *isc,
261 					char *userbuf, ssize_t count,
262 					uint8_t *t_st, uint16_t *seq,
263 					uint16_t *offset, uint16_t *length,
264 					uint8_t **content,
265 					struct qdf_mac_addr *addr)
266 {
267 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
268 	char *argv[6], *delim = " ", *substr;
269 	int argc = -1, ret = 0;
270 
271 	qdf_mem_zero(argv, sizeof(argv));
272 	userbuf = qdf_str_trim(userbuf);
273 
274 	while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
275 		if (!isspace(*substr) && *substr != '\0')
276 			argv[++argc] = substr;
277 		if (argc >= 5)
278 			break;
279 	}
280 
281 	if (argc < 3) {
282 		iot_sim_err("Invalid argument count %d", (argc + 1));
283 		return status;
284 	}
285 
286 	if (!argv[0] || !argv[1] || !argv[2] || !argv[3]) {
287 		iot_sim_err("One or more arguments are null");
288 		return status;
289 	}
290 
291 	ret = kstrtou8(argv[0], 16, t_st);
292 	if (ret)
293 		goto err;
294 	ret = kstrtou16(argv[1], 10, seq);
295 	if (ret)
296 		goto err;
297 	ret = kstrtou16(argv[2], 10, offset);
298 	if (ret)
299 		goto err;
300 	ret = kstrtou16(argv[3], 10, length);
301 	if (ret)
302 		goto err;
303 	/*
304 	 * User can send content change data in following format:
305 	 * 1. Add rule for specific peer
306 	 *	<t_st> <seq> <offset> <length> <content> <MAC>
307 	 * 2. Add rule for broadcast peer
308 	 *	<t_st> <seq> <offset> <length> <content>
309 	 * 3. Remove rule for specific peer
310 	 *	<t_st> <seq> <offset> <length> <MAC>
311 	 * 4. Remove rule for broadcast peer
312 	 *	<t_st> <seq> <offset> <length>
313 	 */
314 
315 	/*
316 	 * If length is 0, this implies remove the rule
317 	 */
318 	if (!*length) {
319 		/*
320 		 * 1. Ignore the frame content
321 		 * 2. argv[4] is not null, then it must be a valid mac
322 		 *    If argv[4] is null, then set 'addr' as null
323 		 */
324 		*content = NULL;
325 		if (argv[4]) {
326 			status = qdf_mac_parse(argv[4], addr);
327 			if (QDF_IS_STATUS_ERROR(status))
328 				iot_sim_err("iot_sim: argv4 is invalid mac for 0 len");
329 		} else {
330 			qdf_mem_zero(addr, QDF_MAC_ADDR_SIZE);
331 			status = QDF_STATUS_SUCCESS;
332 		}
333 		/*
334 		 * No need to parse further just return.
335 		 */
336 		return status;
337 	}
338 
339 	/*
340 	 * If argv[4] is valid, this implies frame content
341 	 */
342 	if (argv[4]) {
343 		status = iot_sim_handle_frame_content(isc, argv[4],
344 						      content, *offset,
345 						      *length);
346 		if (QDF_IS_STATUS_ERROR(status))
347 			return status;
348 	}
349 
350 	/*
351 	 * If argv[5] is valid, this must be mac address
352 	 */
353 	if (argv[5]) {
354 		status = qdf_mac_parse(argv[5], addr);
355 		if (QDF_IS_STATUS_ERROR(status))
356 			qdf_mem_free(content);
357 	}
358 
359 	return status;
360 err:
361 	iot_sim_err("kstrtoXX failed: %d", ret);
362 	return status;
363 }
364 
365 /*
366  * iot_sim_get_index_for_action_frm - function to convert 802.11 action frame
367  *				      category and action code into iot sim
368  *				      specific code.
369  *
370  * @frm: buf containing 802.11 action/category codes
371  * @cat_type: buf to hold converted category code
372  * @act_type: buf to hold converted action code
373  *
374  * Return: QDF_STATUS_SUCCESS on success, failure otherwise
375  */
376 QDF_STATUS
377 iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type,
378 				 uint8_t *act_type)
379 {
380 	uint8_t category, action;
381 
382 	category = ((struct ieee80211_action *)(frm))->ia_category;
383 	action = ((struct ieee80211_action *)(frm))->ia_action;
384 
385 	iot_sim_info("category %x action %x", category, action);
386 
387 	switch (category) {
388 	case IEEE80211_ACTION_CAT_BA:
389 		switch (action) {
390 		case IEEE80211_ACTION_BA_ADDBA_REQUEST:
391 			*cat_type = category;
392 			*act_type = action;
393 			break;
394 		case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
395 		case IEEE80211_ACTION_BA_DELBA:
396 			*cat_type = CAT_BA;
397 			*act_type = action;
398 			break;
399 		default:
400 			return QDF_STATUS_E_FAULT;
401 		}
402 		break;
403 	case IEEE80211_ACTION_CAT_SA_QUERY:
404 		switch (action) {
405 		case IEEE80211_ACTION_SA_QUERY_REQUEST:
406 		case IEEE80211_ACTION_SA_QUERY_RESPONSE:
407 			*cat_type = CAT_SA_QUERY;
408 			*act_type = action;
409 			break;
410 		default:
411 			return QDF_STATUS_E_FAULT;
412 		}
413 		break;
414 	default:
415 		return QDF_STATUS_E_FAULT;
416 	}
417 
418 	return QDF_STATUS_SUCCESS;
419 }
420 
421 /*
422  * iot_sim_action_frame_supported_by_fw - function to find if action frame is
423  *					  supported by fw or not
424  * @category: iot_sim specific category code
425  * @action: iot_sim specific action code
426  *
427  * Return: true if supported else false
428  */
429 bool
430 iot_sim_action_frame_supported_by_fw(uint8_t category, uint8_t action)
431 {
432 	switch (category) {
433 	case IEEE80211_ACTION_CAT_BA:
434 		switch (action) {
435 		case IEEE80211_ACTION_BA_ADDBA_REQUEST:
436 			return true;
437 		default:
438 			return false;
439 		}
440 	default:
441 		return false;
442 	}
443 }
444 
445 /*
446  * iot_sim_frame_supported_by_fw - function to find if frame is supported by fw
447  * @type: 802.11 frame type
448  * @subtype: 802.11 frame subtype
449  *
450  * Return: true if supported else false
451  */
452 bool
453 iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype, bool action)
454 {
455 	if (action)
456 		return iot_sim_action_frame_supported_by_fw(type, subtype);
457 
458 	switch (type << IEEE80211_FC0_TYPE_SHIFT) {
459 	case IEEE80211_FC0_TYPE_MGT:
460 		switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
461 		case IEEE80211_FC0_SUBTYPE_BEACON:
462 				return true;
463 		default:
464 				return false;
465 		}
466 	case IEEE80211_FC0_TYPE_CTL:
467 		switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
468 		case IEEE80211_FC0_SUBTYPE_TRIGGER:
469 		case IEEE80211_FC0_SUBTYPE_BAR:
470 		case IEEE80211_FC0_SUBTYPE_CTS:
471 		case IEEE80211_FC0_SUBTYPE_ACK:
472 		case IEEE80211_FC0_SUBTYPE_NDPA:
473 			return true;
474 		default:
475 			return false;
476 		}
477 	case IEEE80211_FC0_TYPE_DATA:
478 		switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
479 		default:
480 			return true;
481 		}
482 	default:
483 		return false;
484 	}
485 }
486 
487 /*
488  * iot_sim_remap_type_subtype - function to convert rules for response
489  *				type frame into request type. This is
490  *				used for drop/delay operation. This function
491  *				will update the passed type and subtype value.
492  *
493  * @type: 802.11 frame type
494  * @subtype: 802.11 frame subtype
495  * @seq: authentication sequence number, mostly 0 for non-authentication frame
496  * @action: flag to indicate action frame
497  *
498  * Return: QDF_STATUS_SUCCESS
499  */
500 QDF_STATUS
501 iot_sim_remap_type_subtype(uint8_t *type, uint8_t *subtype,
502 			   uint16_t *seq, bool action)
503 {
504 	if (action) {
505 		switch (*type) {
506 		case CAT_BA:
507 			switch (*subtype) {
508 			case IEEE80211_ACTION_BA_ADDBA_RESPONSE:
509 				*subtype = IEEE80211_ACTION_BA_ADDBA_REQUEST;
510 				break;
511 			default:
512 				break;
513 			}
514 			break;
515 		default:
516 			break;
517 		}
518 		return QDF_STATUS_SUCCESS;
519 	}
520 
521 	switch (*type << IEEE80211_FC0_TYPE_SHIFT) {
522 	case IEEE80211_FC0_TYPE_MGT:
523 		switch (*subtype << IEEE80211_FC0_SUBTYPE_SHIFT) {
524 		case IEEE80211_FC0_SUBTYPE_ASSOC_RESP:
525 			*subtype = IEEE80211_FC0_SUBTYPE_ASSOC_REQ;
526 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
527 			break;
528 		case IEEE80211_FC0_SUBTYPE_REASSOC_RESP:
529 			*subtype = IEEE80211_FC0_SUBTYPE_REASSOC_REQ;
530 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
531 			break;
532 		case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
533 			*subtype = IEEE80211_FC0_SUBTYPE_PROBE_REQ;
534 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
535 			break;
536 		case IEEE80211_FC0_SUBTYPE_AUTH:
537 			*subtype = IEEE80211_FC0_SUBTYPE_AUTH;
538 			*subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
539 			/* If auth response (auth seq num 2) is marked as
540 			 * drop, then drop the auth request (auth seq num 1)
541 			 */
542 			if (*seq == IEEE80211_AUTH_OPEN_RESPONSE)
543 				*seq = IEEE80211_AUTH_OPEN_REQUEST;
544 			break;
545 		default:
546 			break;
547 		}
548 	default:
549 		break;
550 	}
551 
552 	return QDF_STATUS_SUCCESS;
553 }
554 
555 /*
556  * iot_sim_send_rule_to_fw - function to send iot_sim rule to fw
557  *
558  * @isc: iot sim context
559  * @oper: iot sim operation
560  * @mac: peer mac address
561  * @type: 802.11 frame type
562  * @subtype: 802.11 frame subtype
563  * @seq: authentication sequence number, mostly 0 for non-authentication frame
564  * @offset: user provided offset
565  * @frm: user provided frame content
566  * @length: length of frm
567  * @action: flag to indicate action frame
568  * @drop: flag to indicate set drop rule
569  * @clear: flag to indicate set rule or clear
570  *
571  * Return: QDF_STATUS_SUCCESS
572  */
573 QDF_STATUS
574 iot_sim_send_rule_to_fw(struct iot_sim_context *isc,
575 			enum iot_sim_operations oper,
576 			struct qdf_mac_addr *mac,
577 			uint8_t type, uint8_t subtype,
578 			uint16_t seq, uint16_t offset,
579 			uint8_t *frm, uint16_t len,
580 			bool action, bool clear)
581 {
582 	struct simulation_test_params param;
583 
584 	if (FRAME_TYPE_IS_BEACON(type, subtype) && offset) {
585 		iot_sim_info("Beacon update from offset:%d", offset);
586 		return QDF_STATUS_E_NOSUPPORT;
587 	}
588 
589 	if (iot_sim_frame_supported_by_fw(type, subtype, action)) {
590 		qdf_mem_zero(&param, sizeof(struct simulation_test_params));
591 		param.pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj);
592 		qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE);
593 		param.test_cmd_type = oper;
594 		/* subtype_cmd: Set subcmd based on action and clear flag */
595 		if (action) {
596 			if (clear)
597 				param.test_subcmd_type = DEL_RULE_ACTION;
598 			else
599 				param.test_subcmd_type = ADD_RULE_ACTION;
600 		} else {
601 			if (clear)
602 				param.test_subcmd_type = DEL_RULE;
603 			else
604 				param.test_subcmd_type = ADD_RULE;
605 		}
606 		param.frame_type = type;
607 		param.frame_subtype = subtype;
608 		param.seq = seq;
609 		param.offset = offset;
610 		param.frame_length = len;
611 		param.buf_len = len;
612 		param.bufp = frm;
613 		if (QDF_IS_STATUS_ERROR(tgt_send_simulation_cmd(isc->pdev_obj,
614 								&param)))
615 			iot_sim_err("Sending del rule to fw failed!");
616 
617 		if (FRAME_TYPE_IS_BEACON(type, subtype) && clear)
618 			return QDF_STATUS_E_NOSUPPORT;
619 
620 		return QDF_STATUS_SUCCESS;
621 	}
622 
623 	return QDF_STATUS_E_NOSUPPORT;
624 }
625 
626 /*
627  * iot_sim_del_rule - function to delete iot_sim rule
628  *
629  * @s_e: address of seq for which rule to be removed
630  * @f_e: address of the rule present in s_e to be removed
631  * @oper: iot sim operation
632  *
633  * Return: QDF_STATUS_SUCCESS
634  */
635 QDF_STATUS
636 iot_sim_del_rule(struct iot_sim_rule_per_seq **s_e,
637 		 struct iot_sim_rule **f_e,
638 		 enum iot_sim_operations oper)
639 {
640 	if (oper == CONTENT_CHANGE) {
641 		qdf_mem_free((*f_e)->frm_content);
642 		(*f_e)->frm_content = NULL;
643 	} else if (oper == DROP) {
644 		(*f_e)->drop = false;
645 	} else if (oper == DELAY) {
646 		/* TBD */
647 	}
648 
649 	if (qdf_test_bit(oper, (unsigned long *)
650 			       &(*f_e)->rule_bitmap)) {
651 		(*s_e)->use_count--;
652 		qdf_clear_bit(oper, (unsigned long *)
653 				    &(*f_e)->rule_bitmap);
654 	}
655 
656 	if (!(*f_e)->rule_bitmap) {
657 		qdf_mem_free(*f_e);
658 		*f_e = NULL;
659 	}
660 	if ((*s_e)->use_count == 0) {
661 		qdf_mem_free(*s_e);
662 		*s_e = NULL;
663 	}
664 	return QDF_STATUS_SUCCESS;
665 }
666 
667 /*
668  * iot_sim_delete_rule_for_mac - function to delete content change rule
669  *                               for given peer mac
670  * @isc: iot sim context
671  * @oper: iot sim operation
672  * @seq: authentication sequence number, mostly 0 for non-authentication frame
673  * @type: 802.11 frame type
674  * @subtype: 802.11 frame subtype
675  * @mac: peer mac address
676  * @action: action frame or not
677  *
678  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise
679  */
680 QDF_STATUS
681 iot_sim_delete_rule_for_mac(struct iot_sim_context *isc,
682 			    enum iot_sim_operations oper,
683 			    uint16_t seq, uint8_t type,
684 			    uint8_t subtype,
685 			    struct qdf_mac_addr *mac,
686 			    bool action)
687 {
688 	QDF_STATUS status = QDF_STATUS_SUCCESS;
689 	struct iot_sim_rule_per_seq **s_e;
690 	struct iot_sim_rule **f_e;
691 	struct iot_sim_rule_per_peer *peer;
692 
693 	if (qdf_is_macaddr_zero(mac))
694 		iot_sim_info("Rule deletion for all peers");
695 	else
696 		iot_sim_info("Rule deletion for " QDF_MAC_ADDR_STR,
697 			     QDF_MAC_ADDR_ARRAY(mac->bytes));
698 
699 	iot_sim_debug("oper:%s seq: %hu %s:%hu/%hu",
700 		      iot_sim_oper_to_str(oper), seq,
701 		      action ? "category/action code" : "type/subtype",
702 		      type, subtype);
703 
704 	if (!isc) {
705 		iot_sim_err("iot_sim: isc is null");
706 		return QDF_STATUS_E_FAILURE;
707 	}
708 
709 	if (oper == DROP || oper == DELAY)
710 		iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
711 
712 	peer = iot_sim_find_peer_from_mac(isc, mac);
713 	if (peer) {
714 		qdf_spin_lock(&peer->iot_sim_lock);
715 		s_e = &peer->rule_per_seq[seq];
716 		if (!*s_e) {
717 			qdf_spin_unlock(&peer->iot_sim_lock);
718 			return QDF_STATUS_SUCCESS;
719 		}
720 
721 		if (action)
722 			f_e = &((*s_e)->rule_per_action_frm[type][subtype]);
723 		else
724 			f_e = &((*s_e)->rule_per_type[type][subtype]);
725 
726 		if (*f_e)
727 			status = iot_sim_del_rule(s_e, f_e, oper);
728 		qdf_spin_unlock(&peer->iot_sim_lock);
729 	}
730 
731 	return status;
732 }
733 
734 /*
735  * iot_sim_add_rule - function to add iot_sim rule
736  *
737  * @s_e: address of seq for which rule to be added
738  * @f_e: address of the rule present in s_e to be added
739  * @oper: iot sim operation
740  * @frm: user provided frame content
741  * @offset: user provided offset
742  * @len: length of the user provided frame content
743  *
744  * Return: QDF_STATUS_SUCCESS
745  */
746 QDF_STATUS
747 iot_sim_add_rule(struct iot_sim_rule_per_seq **s_e,
748 		 struct iot_sim_rule **f_e,
749 		 enum iot_sim_operations oper,
750 		 uint8_t *frm, uint16_t offset, uint16_t len)
751 {
752 	if (!*f_e) {
753 		*f_e = qdf_mem_malloc(sizeof(struct iot_sim_rule));
754 		if (!*f_e) {
755 			iot_sim_err("can't allocate f_e");
756 			return QDF_STATUS_E_NOMEM;
757 		}
758 	}
759 
760 	if (oper == CONTENT_CHANGE) {
761 		(*f_e)->frm_content = qdf_mem_malloc(len);
762 		if (!((*f_e)->frm_content))
763 			return QDF_STATUS_E_NOMEM;
764 		qdf_mem_copy((*f_e)->frm_content, frm, len);
765 		(*f_e)->len = len;
766 		(*f_e)->offset = offset;
767 	} else if (oper == DROP) {
768 		(*f_e)->drop = true;
769 	} else if (oper == DELAY) {
770 		/* TBD */
771 	}
772 
773 	(*s_e)->use_count++;
774 	qdf_set_bit(oper, (unsigned long *)
775 			  &(*f_e)->rule_bitmap);
776 
777 	return QDF_STATUS_SUCCESS;
778 }
779 
780 /*
781  * iot_sim_add_rule_for_mac - function to add content change rule
782  *			      for given peer mac
783  * @isc: iot sim context
784  * @oper: iot sim operation
785  * @mac: peer mac address
786  * @type: 802.11 frame type
787  * @subtype: 802.11 frame subtype
788  * @seq: authentication sequence number, mostly 0 for non-authentication frame
789  * @offset: user provided offset
790  * @frm: user provided frame content
791  * @len: length of frm
792  * @action: boolean to indicate action frame
793  *
794  * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise
795  */
796 QDF_STATUS
797 iot_sim_add_rule_for_mac(struct iot_sim_context *isc,
798 			 enum iot_sim_operations oper,
799 			 struct qdf_mac_addr *mac,
800 			 uint8_t type, uint8_t subtype,
801 			 uint16_t seq, uint16_t offset,
802 			 uint8_t *frm, uint16_t len,
803 			 uint8_t drop, bool action)
804 {
805 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
806 	struct iot_sim_rule_per_peer *peer;
807 	struct iot_sim_rule_per_seq **s_e = NULL;
808 	struct iot_sim_rule **f_e = NULL;
809 
810 	if (!isc) {
811 		iot_sim_err("iot_sim: isc is null");
812 		return status;
813 	}
814 
815 	status = iot_sim_delete_rule_for_mac(isc, oper, seq,
816 					     type, subtype, mac,
817 					     action);
818 	if (status == QDF_STATUS_E_FAILURE) {
819 		iot_sim_err("iot_sim: Rule removed - Fail");
820 		return status;
821 	}
822 
823 	if (oper == DROP || oper == DELAY)
824 		iot_sim_remap_type_subtype(&type, &subtype, &seq, action);
825 
826 	peer = iot_sim_find_peer_from_mac(isc, mac);
827 	if (peer) {
828 		qdf_spin_lock(&peer->iot_sim_lock);
829 		s_e = &peer->rule_per_seq[seq];
830 		if (!*s_e) {
831 			*s_e = qdf_mem_malloc(sizeof(struct
832 					      iot_sim_rule_per_seq));
833 			if (!*s_e) {
834 				iot_sim_err("can't allocate s_e");
835 				qdf_spin_unlock(&peer->iot_sim_lock);
836 				return QDF_STATUS_E_NOMEM;
837 			}
838 		}
839 
840 		if (action)
841 			f_e = &((*s_e)->rule_per_action_frm[type][subtype]);
842 		else
843 			f_e = &((*s_e)->rule_per_type[type][subtype]);
844 
845 		if (qdf_is_macaddr_zero(mac))
846 			iot_sim_info("Rule addition for all peers");
847 		else
848 			iot_sim_info("Rule addition for " QDF_MAC_ADDR_STR,
849 				     QDF_MAC_ADDR_ARRAY(mac->bytes));
850 
851 		iot_sim_info("oper:%s seq: %hu %s:%hu/%hu",
852 			     iot_sim_oper_to_str(oper), seq,
853 			     action ? "category/action code" : "type/subtype",
854 			     type, subtype);
855 
856 		status = iot_sim_add_rule(s_e, f_e, oper, frm, offset, len);
857 		qdf_spin_unlock(&peer->iot_sim_lock);
858 	} else {
859 		/* TBD: clear the rules for peer with address 'mac'*/
860 	}
861 
862 	return status;
863 }
864 
865 /*
866  *                   IOT SIM User Command Format
867  *
868  * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
869  * | FrmType/subtype |  Seq  | Offset | Length | content | Mac Addr |
870  * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
871  * |     1Byte       | 2Byte | 2Bytes | 2Bytes | Length  | 6 Bytes  |
872  *
873  */
874 
875 /*
876  * iot_sim_debug_content_change_write - Write Handler for content change
877  *					operation
878  * @file: debugfs file pointer
879  * @buf: buf of user input
880  * @count: buf count
881  * @ppos: offset on file
882  *
883  * Return: character read on success, failure otherwise
884  */
885 static ssize_t
886 iot_sim_debug_content_change_write(struct file *file,
887 				   const char __user *buf,
888 				   size_t count, loff_t *ppos)
889 {
890 	QDF_STATUS status = QDF_STATUS_SUCCESS;
891 	unsigned char t_st, type, subtype, *content = NULL;
892 	uint16_t offset = 0, length = 0, seq = 0;
893 	char *locbuf = NULL;
894 	enum iot_sim_operations oper = CONTENT_CHANGE;
895 	struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
896 	struct iot_sim_context *isc =
897 			((struct seq_file *)file->private_data)->private;
898 	uint8_t action = 0, category = 0;
899 	bool is_action = 0, clear = false;
900 	mlme_pdev_ext_t *ext = NULL;
901 
902 	if ((!buf) || (count > USER_BUF_LEN) || (count < 7))
903 		return -EFAULT;
904 
905 	locbuf = qdf_mem_malloc(USER_BUF_LEN + 1);
906 	if (!locbuf)
907 		return -ENOMEM;
908 
909 	if (copy_from_user(locbuf, buf, count)) {
910 		qdf_mem_free(locbuf);
911 		return -EFAULT;
912 	}
913 
914 	status = iot_sim_parse_user_input_content_change(isc, locbuf, count,
915 							 &t_st, &seq, &offset,
916 							 &length, &content,
917 							 &mac_addr);
918 	if (QDF_IS_STATUS_ERROR(status))
919 		goto free;
920 
921 	type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
922 	subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
923 	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
924 
925 	if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
926 		goto free;
927 
928 	if (FRAME_TYPE_IS_ACTION(type, subtype)) {
929 		status = iot_sim_parse_action_frame(length, offset, content,
930 						    &category, &action);
931 		if (QDF_IS_STATUS_ERROR(status))
932 			goto free;
933 
934 		is_action = 1;
935 		type = category;
936 		subtype = action;
937 	}
938 
939 	clear = length ? false : true;
940 	status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
941 					 seq, offset, content, length,
942 					 is_action, clear);
943 	if (QDF_IS_STATUS_SUCCESS(status))
944 		goto free;
945 
946 	/* check for rule removal */
947 	if (!length || !content) {
948 		status = iot_sim_delete_rule_for_mac(isc, oper, seq,
949 						     type, subtype,
950 						     &mac_addr,
951 						     is_action);
952 
953 	} else {
954 		status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
955 						  type, subtype, seq, offset,
956 						  content, length, 0,
957 						  is_action);
958 	}
959 	if (QDF_IS_STATUS_SUCCESS(status)) {
960 		iot_sim_err("iot_sim: Content Change Operation - success");
961 		if (FRAME_TYPE_IS_BEACON(type, subtype)) {
962 			if (isc->bcn_buf && (!length || !content)) {
963 				qdf_nbuf_free(isc->bcn_buf);
964 				isc->bcn_buf = NULL;
965 			}
966 			ext = wlan_pdev_mlme_get_ext_hdl(isc->pdev_obj);
967 			if (ext) {
968 				isc->iot_sim_update_beacon_trigger(ext);
969 				iot_sim_info("Beacon update triggered");
970 			} else {
971 				iot_sim_err("mlme_pdev_ext is null");
972 			}
973 		}
974 	} else {
975 		iot_sim_err("iot_sim: Content Change Operation - Fail");
976 	}
977 free:
978 	qdf_mem_free(content);
979 	qdf_mem_free(locbuf);
980 	return count;
981 }
982 
983 /*
984  * iot_sim_debug_delay_write - Write Handler for delay operation
985  * @file: debugfs file pointer
986  * @buf: buf of user input
987  * @count: buf count
988  * @ppos: offset on file
989  *
990  * Return: character read
991  */
992 static ssize_t
993 iot_sim_debug_delay_write(struct file *file,
994 			  const char __user *buf,
995 			  size_t count, loff_t *ppos)
996 {
997 	iot_sim_err("delay iot sim ops called");
998 	return count;
999 }
1000 
1001 /*
1002  * iot_sim_parse_user_input_drop - function to parse user input into
1003  *				   predefined format for drop operation.
1004  *				   All arguments passed will be filled
1005  *				   upon success
1006  * @isc: iot sim context
1007  * @userbuf: local copy of user input
1008  * @count: length of userbuf
1009  * @t_st: address of type variable
1010  * @seq: address of seq variable
1011  * @cat_type: 802.11 action frame category code
1012  * @act_type: 802.11 action frame action code
1013  * @drop: address of drop variable to specify drop the frame or not
1014  * @addr: pointer to mac address
1015  *
1016  * Return: QDF_STATUS_SUCCESS on success
1017  *	   QDF_STATUS_E_FAILURE otherwise
1018  */
1019 QDF_STATUS
1020 iot_sim_parse_user_input_drop(struct iot_sim_context *isc,
1021 			      char *userbuf, ssize_t count,
1022 			      uint8_t *t_st, uint16_t *seq,
1023 			      uint8_t *cat_type, uint8_t *act_type,
1024 			      uint8_t *drop, struct qdf_mac_addr *addr)
1025 {
1026 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1027 	char *argv[6], *delim = " ", *substr;
1028 	int argc = -1, ret = 0;
1029 
1030 	qdf_mem_zero(argv, sizeof(argv));
1031 	userbuf = qdf_str_trim(userbuf);
1032 
1033 	while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) {
1034 		if (!isspace(*substr) && *substr != '\0')
1035 			argv[++argc] = substr;
1036 		if (argc >= 5)
1037 			break;
1038 	}
1039 
1040 	if (argc < 3) {
1041 		iot_sim_err("Invalid argument count %d", (argc + 1));
1042 		return status;
1043 	}
1044 
1045 	if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) {
1046 		iot_sim_err("One or more arguments are null");
1047 		return status;
1048 	}
1049 	/*
1050 	 * User can send drop data in following format:
1051 	 * 1. Add drop rule for specific peer
1052 	 *	<t_st> <seq> <category_type> <action_type> <drop> <MAC>
1053 	 * 2. Add drop rule for broadcast peer
1054 	 *	<t_st> <seq> <category_type> <action_type> <drop>
1055 	 * 3. Remove drop rule for specific peer
1056 	 *	<t_st> <seq> <category_type> <action_type> <drop> <MAC>
1057 	 * 4. Remove drop rule for broadcast peer
1058 	 *	<t_st> <seq> <category_type> <action_type> <drop> <BCAST_MAC>
1059 	 * 5. Remove drop rule for all peer
1060 	 *	<t_st> <seq> <category_type> <action_type> <drop>
1061 	 */
1062 
1063 	ret = kstrtou8(argv[0], 16, t_st);
1064 	if (ret)
1065 		goto err;
1066 	ret = kstrtou16(argv[1], 10, seq);
1067 	if (ret)
1068 		goto err;
1069 	ret = kstrtou8(argv[2], 10, cat_type);
1070 	if (ret)
1071 		goto err;
1072 	ret = kstrtou8(argv[3], 10, act_type);
1073 	if (ret)
1074 		goto err;
1075 	ret = kstrtou8(argv[4], 10, drop);
1076 	if (ret)
1077 		goto err;
1078 
1079 	/*
1080 	 * If argv[5] is valid, this must be mac address
1081 	 */
1082 	if (argv[5])
1083 		status = qdf_mac_parse(argv[5], addr);
1084 
1085 	return status;
1086 err:
1087 	iot_sim_err("kstrtoXX failed: %d", ret);
1088 	return QDF_STATUS_E_FAILURE;
1089 }
1090 
1091 /*
1092  * iot_sim_debug_drop_write - Write Handler for drop operation
1093  * @file: debugfs file pointer
1094  * @buf: buf of user input
1095  * @count: buf count
1096  * @ppos: offset on file
1097  *
1098  * Return: character read
1099  */
1100 static ssize_t
1101 iot_sim_debug_drop_write(struct file *file,
1102 			 const char __user *buf,
1103 			 size_t count, loff_t *ppos)
1104 {
1105 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1106 	unsigned char t_st, type, subtype;
1107 	uint16_t seq = 0;
1108 	char *locbuf = NULL;
1109 	enum iot_sim_operations oper = DROP;
1110 	struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT;
1111 	struct iot_sim_context *isc =
1112 			((struct seq_file *)file->private_data)->private;
1113 	uint8_t action = 0, category = 0, tmp[2], drop = 0;
1114 	bool is_action = false, clear = false;
1115 
1116 	if ((!buf) || (count > USER_BUF_LEN_DROP) || (count < 6))
1117 		return -EFAULT;
1118 
1119 	locbuf = qdf_mem_malloc(USER_BUF_LEN_DROP + 1);
1120 	if (!locbuf)
1121 		return -ENOMEM;
1122 
1123 	if (copy_from_user(locbuf, buf, count)) {
1124 		qdf_mem_free(locbuf);
1125 		return -EFAULT;
1126 	}
1127 
1128 	status = iot_sim_parse_user_input_drop(isc, locbuf, count,
1129 					       &t_st, &seq, &category,
1130 					       &action, &drop, &mac_addr);
1131 	if (QDF_IS_STATUS_ERROR(status))
1132 		goto free;
1133 
1134 	type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT;
1135 	subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK);
1136 	subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT;
1137 
1138 	if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ)
1139 		goto free;
1140 
1141 	if (FRAME_TYPE_IS_ACTION(type, subtype)) {
1142 		tmp[0] = category;
1143 		tmp[1] = action;
1144 		/*
1145 		 * convert 802.11 category and action code to iot sim codes
1146 		 */
1147 		status = iot_sim_get_index_for_action_frm(tmp, &category,
1148 							  &action);
1149 		if (QDF_IS_STATUS_ERROR(status))
1150 			goto free;
1151 
1152 		is_action = 1;
1153 		type = category;
1154 		subtype = action;
1155 	}
1156 
1157 	clear = drop ? false : true;
1158 	status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype,
1159 					 seq, 0, NULL, 0, is_action, clear);
1160 	if (QDF_IS_STATUS_SUCCESS(status))
1161 		goto free;
1162 
1163 	/* check for rule removal */
1164 	if (!drop) {
1165 		status = iot_sim_delete_rule_for_mac(isc, oper, seq,
1166 						     type, subtype,
1167 						     &mac_addr,
1168 						     is_action);
1169 	} else {
1170 		status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr,
1171 						  type, subtype, seq, 0,
1172 						  NULL, 0, drop, is_action);
1173 	}
1174 	if (QDF_IS_STATUS_SUCCESS(status))
1175 		iot_sim_debug("iot_sim: Rule update Drop Operation - Success");
1176 	else
1177 		iot_sim_err("iot_sim: Rule update Drop Operation - Fail");
1178 free:
1179 	qdf_mem_free(locbuf);
1180 	return count;
1181 }
1182 
1183 /*
1184  * debug_iot_sim_##func_base##_show() - debugfs functions to display content
1185  *                                      dummy function
1186  * Return: success
1187  */
1188 #define GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(func_base)			\
1189 	static int iot_sim_debug_##func_base##_show(struct seq_file *m,	\
1190 						    void *v)		\
1191 {									\
1192 	return qdf_status_to_os_return(QDF_STATUS_SUCCESS);		\
1193 }
1194 
1195 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(content_change);
1196 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(delay);
1197 GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(drop);
1198 
1199 /*
1200  * debug_##func_base##_open() - Open debugfs entry for respective command
1201  * and event buffer.
1202  *
1203  * @inode: node for debug dir entry
1204  * @file: file handler
1205  *
1206  * Return: open status
1207  */
1208 #define GENERATE_DEBUG_IOT_SIM_STRUCTS(func_base)			\
1209 	static int debug_##func_base##_open(struct inode *inode,	\
1210 					    struct file *file)		\
1211 {									\
1212 	return single_open(file, iot_sim_debug_##func_base##_show,	\
1213 			   inode->i_private);				\
1214 }									\
1215 									\
1216 static const struct file_operations debug_##func_base##_ops = {		\
1217 	.open           = debug_##func_base##_open,			\
1218 	.read           = seq_read,					\
1219 	.llseek         = seq_lseek,					\
1220 	.write          = iot_sim_debug_##func_base##_write,		\
1221 	.release        = single_release,				\
1222 }
1223 
1224 GENERATE_DEBUG_IOT_SIM_STRUCTS(content_change);
1225 GENERATE_DEBUG_IOT_SIM_STRUCTS(drop);
1226 GENERATE_DEBUG_IOT_SIM_STRUCTS(delay);
1227 
1228 /* Structure to maintain debug information */
1229 struct iot_sim_dbgfs_file {
1230 	const char *name;
1231 	const struct file_operations *ops;
1232 };
1233 
1234 #define DEBUG_IOT_SIM(func_base) {	.name = #func_base,		\
1235 					.ops = &debug_##func_base##_ops	\
1236 }
1237 
1238 struct iot_sim_dbgfs_file iot_sim_dbgfs_files[IOT_SIM_DEBUGFS_FILE_NUM] = {
1239 	DEBUG_IOT_SIM(content_change),
1240 	DEBUG_IOT_SIM(drop),
1241 	DEBUG_IOT_SIM(delay),
1242 };
1243 
1244 /**
1245  * iot_sim_debugfs_deinit() - Deinit functions to remove debugfs directory and
1246  *			      it's file enteries.
1247  * @isc: iot_sim context
1248  *
1249  * Return: init status
1250  */
1251 static QDF_STATUS
1252 iot_sim_debugfs_deinit(struct iot_sim_context *isc)
1253 {
1254 	debugfs_remove_recursive(isc->iot_sim_dbgfs_ctx.iot_sim_dir_de);
1255 
1256 	return QDF_STATUS_SUCCESS;
1257 }
1258 
1259 /*
1260  * iot_sim_remove_all_oper_rules - Function to remove all configured rules
1261  *				   for given operation
1262  *
1263  * @isc: iot sim context
1264  * @oper: iot sim operation
1265  *
1266  * Return: void
1267  */
1268 static void
1269 iot_sim_remove_all_oper_rules(struct iot_sim_context *isc,
1270 			      enum iot_sim_operations oper)
1271 {
1272 	uint16_t seq;
1273 	uint8_t type, subtype, category = 0, action = 0;
1274 	struct qdf_mac_addr zero_mac_addr = QDF_MAC_ADDR_ZERO_INIT;
1275 
1276 	for (seq = 0; seq < MAX_SEQ; seq++) {
1277 		/* Remove rules for non-action type frames */
1278 		for (type = 0; type < N_FRAME_TYPE; type++)
1279 			for (subtype = 0; subtype < N_FRAME_SUBTYPE; subtype++)
1280 				iot_sim_delete_rule_for_mac(isc, oper, seq,
1281 							    type, subtype,
1282 							    &zero_mac_addr, 0);
1283 		/* Remove rules for action frames */
1284 		for (category = 0; category < IOT_SIM_MAX_CAT; category++)
1285 			for (action = 0; action < MAX_ACTION; action++)
1286 				iot_sim_delete_rule_for_mac(isc, oper, seq,
1287 							    category, action,
1288 							    &zero_mac_addr, 1);
1289 	}
1290 }
1291 
1292 /*
1293  * iot_sim_remove_all_rules - Function to remove all configured rules
1294  *
1295  * @isc: iot sim context
1296  *
1297  * Return: void
1298  */
1299 static void
1300 iot_sim_remove_all_rules(struct iot_sim_context *isc)
1301 {
1302 	enum iot_sim_operations oper;
1303 
1304 	if (!isc)
1305 		return;
1306 
1307 	for (oper = CONTENT_CHANGE; oper < IOT_SIM_MAX_OPERATION; oper++)
1308 		iot_sim_remove_all_oper_rules(isc, oper);
1309 }
1310 
1311 /**
1312  * iot_sim_debugfs_init() - debugfs functions to create debugfs directory and to
1313  *			    create debugfs enteries.
1314  * @isc: iot_sim context
1315  *
1316  * Return: init status
1317  */
1318 static QDF_STATUS
1319 iot_sim_debugfs_init(struct iot_sim_context *isc)
1320 {
1321 	struct dentry *dbgfs_dir = NULL;
1322 	struct dentry *de = NULL;
1323 	uint8_t i, pdev_id;
1324 	char buf[32];
1325 
1326 	if (!isc)
1327 		return QDF_STATUS_E_FAILURE;
1328 
1329 	pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj);
1330 
1331 	qdf_mem_zero(buf, sizeof(buf));
1332 	snprintf(buf, sizeof(buf), "iot_sim_pdev%u", pdev_id);
1333 
1334 	dbgfs_dir = debugfs_create_dir(buf, NULL);
1335 	isc->iot_sim_dbgfs_ctx.iot_sim_dir_de = dbgfs_dir;
1336 
1337 	if (!isc->iot_sim_dbgfs_ctx.iot_sim_dir_de) {
1338 		iot_sim_err("dbgfs dir creation failed for pdev%u", pdev_id);
1339 		return QDF_STATUS_E_FAILURE;
1340 	}
1341 
1342 	for (i = 0; i < IOT_SIM_DEBUGFS_FILE_NUM; ++i) {
1343 		de = debugfs_create_file(iot_sim_dbgfs_files[i].name,
1344 					 0644,
1345 					 dbgfs_dir, isc,
1346 					 iot_sim_dbgfs_files[i].ops);
1347 
1348 		if (!de) {
1349 			iot_sim_err("dbgfs file creation failed for pdev%u",
1350 				    pdev_id);
1351 			goto out;
1352 		}
1353 		isc->iot_sim_dbgfs_ctx.iot_sim_file_de[i] = de;
1354 	}
1355 
1356 	return QDF_STATUS_SUCCESS;
1357 
1358 out:
1359 	debugfs_remove_recursive(dbgfs_dir);
1360 	qdf_mem_set(isc->iot_sim_dbgfs_ctx.iot_sim_file_de,
1361 		    sizeof(isc->iot_sim_dbgfs_ctx.iot_sim_file_de), 0);
1362 
1363 	return QDF_STATUS_E_FAILURE;
1364 }
1365 
1366 QDF_STATUS
1367 wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
1368 {
1369 	struct iot_sim_context *isc = NULL;
1370 
1371 	if (!pdev) {
1372 		iot_sim_err("pdev is NULL");
1373 		return QDF_STATUS_E_NULL_VALUE;
1374 	}
1375 
1376 	isc = qdf_mem_malloc(sizeof(struct iot_sim_context));
1377 	if (!isc)
1378 		return QDF_STATUS_E_NOMEM;
1379 
1380 	isc->pdev_obj = pdev;
1381 
1382 	if (QDF_IS_STATUS_ERROR(iot_sim_debugfs_init(isc))) {
1383 		qdf_mem_free(isc);
1384 		iot_sim_info("iot_sim debugfs file creation failed");
1385 		return QDF_STATUS_E_FAILURE;
1386 	}
1387 
1388 	qdf_set_macaddr_broadcast(&isc->bcast_peer.addr);
1389 	qdf_spinlock_create(&isc->bcast_peer.iot_sim_lock);
1390 	qdf_list_create(&isc->bcast_peer.list, 0);
1391 	isc->bcn_buf = NULL;
1392 
1393 	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_IOT_SIM_COMP,
1394 					      (void *)isc, QDF_STATUS_SUCCESS);
1395 
1396 	iot_sim_debug("iot_sim component pdev%u object created",
1397 		      wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj));
1398 
1399 	return QDF_STATUS_SUCCESS;
1400 }
1401 
1402 QDF_STATUS
1403 wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev,
1404 				      void *arg)
1405 {
1406 	struct iot_sim_context *isc = NULL;
1407 
1408 	if (!pdev) {
1409 		iot_sim_err("pdev is NULL");
1410 		return QDF_STATUS_E_NULL_VALUE;
1411 	}
1412 
1413 	isc = wlan_objmgr_pdev_get_comp_private_obj(pdev,
1414 						    WLAN_IOT_SIM_COMP);
1415 	if (isc) {
1416 		wlan_objmgr_pdev_component_obj_detach(pdev,
1417 						      WLAN_IOT_SIM_COMP,
1418 						      (void *)isc);
1419 		/* Deinitilise function pointers from iot_sim context */
1420 		iot_sim_debugfs_deinit(isc);
1421 		iot_sim_remove_all_rules(isc);
1422 		if (isc->bcn_buf)
1423 			qdf_nbuf_free(isc->bcn_buf);
1424 		qdf_spinlock_destroy(&isc->bcast_peer.iot_sim_lock);
1425 		qdf_mem_free(isc);
1426 	}
1427 	iot_sim_debug("iot_sim component pdev%u object destroyed",
1428 		      wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj));
1429 
1430 	return QDF_STATUS_SUCCESS;
1431 }
1432 
1433