diff --git a/iot_sim/core/iot_sim_cmn_api_i.h b/iot_sim/core/iot_sim_cmn_api_i.h index 0ee0010d5f7b..f8fb1670fb25 100644 --- a/iot_sim/core/iot_sim_cmn_api_i.h +++ b/iot_sim/core/iot_sim_cmn_api_i.h @@ -18,35 +18,50 @@ #define _IOT_SIM_CMN_API_I_H_ #include "iot_sim_defs_i.h" +#include +#define MAX_BUFFER_SIZE 2048 /* - * wlan_iot_sim_psoc_obj_create_handler() - handler for psoc object create - * @psoc: reference to global psoc object + * IOT SIM User Buf Format + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * | FrmType/subtype | Seq | Offset | Length | content | Mac Addr | + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * | 1Byte | 2Byte | 2Bytes | 2Bytes | Length | 6 Bytes | + * + */ +#define USER_BUF_LEN (1 + 2 + 2 + 2 + MAX_BUFFER_SIZE + 6) +#define IOT_SIM_SET_OP_BIT(bitmap, oper) ((bitmap) |= 1 << (oper)) +#define IOT_SIM_CLEAR_OP_BIT(bitmap, oper) (((bitmap) &= ~(1 << (oper))) == 0) + +/** + * wlan_iot_sim_pdev_obj_create_handler() - handler for pdev object create + * @pdev: reference to global pdev object * @arg: reference to argument provided during registration of handler * - * This is a handler to indicate psoc object created. Hence iot_sim_context - * object can be created and attached to psoc component list. + * This is a handler to indicate pdev object created. Hence iot_sim_context + * object can be created and attached to pdev component list. * * Return: QDF_STATUS_SUCCESS on success - * QDF_STATUS_E_FAILURE if psoc is null + * QDF_STATUS_E_FAILURE if pdev is null * QDF_STATUS_E_NOMEM on failure of iot_sim object allocation */ -QDF_STATUS wlan_iot_sim_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, +QDF_STATUS wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg); -/* - * wlan_iot_sim_psoc_obj_destroy_handler() - handler for psoc object delete - * @psoc: reference to global psoc object +/** + * wlan_iot_sim_pdev_obj_destroy_handler() - handler for pdev object delete + * @pdev: reference to global pdev object * @arg: reference to argument provided during registration of handler * - * This is a handler to indicate psoc object going to be deleted. - * Hence iot_sim_context object can be detached from psoc component list. + * This is a handler to indicate pdev object going to be deleted. + * Hence iot_sim_context object can be detached from pdev component list. * Then iot_sim_context object can be deleted. * * Return: QDF_STATUS_SUCCESS on success * QDF_STATUS_E_FAILURE on failure */ -QDF_STATUS wlan_iot_sim_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, +QDF_STATUS wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg); /* @@ -61,16 +76,34 @@ QDF_STATUS wlan_iot_sim_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, * */ static inline struct iot_sim_context * -iot_sim_get_ctx_from_psoc(struct wlan_objmgr_psoc *psoc) +iot_sim_get_ctx_from_pdev(struct wlan_objmgr_pdev *pdev) { struct iot_sim_context *isc = NULL; - if (psoc) { - isc = wlan_objmgr_psoc_get_comp_private_obj(psoc, + if (pdev) { + isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP); } return isc; } +char* +iot_sim_print_mac(struct qdf_mac_addr *mac); + +QDF_STATUS +iot_sim_delete_rule_for_mac(struct iot_sim_context *isc, + enum iot_sim_operations oper, + unsigned short seq, + unsigned char type, + unsigned char subtype, + struct qdf_mac_addr *mac); + +QDF_STATUS +iot_sim_parse_user_input_content_change(struct iot_sim_context *isc, + char *userbuf, ssize_t count, + uint8_t *t_st, uint16_t *seq, + uint16_t *offset, uint16_t *length, + uint8_t **content, + struct qdf_mac_addr *mac); #endif /* _IOT_SIM_CMN_API_I_H_ */ diff --git a/iot_sim/core/iot_sim_common.c b/iot_sim/core/iot_sim_common.c index 06499adcd18c..2624cb60b4f1 100644 --- a/iot_sim/core/iot_sim_common.c +++ b/iot_sim/core/iot_sim_common.c @@ -15,21 +15,680 @@ */ #include "iot_sim_cmn_api_i.h" +#include "iot_sim_defs_i.h" #include #include +#include + +/* + * iot_sim_validate_content - function to validate frame content. User provided + * content must be either full frame or full frame + * body or valid TLV formatted data. + * @buf: pointer to frame content in binary format + * @total_len: length of content + * @offset: offset provided by user + * + * Return: QDF_STATUS_SUCCESS on success + * QDF_STATUS_E_FAULT on failure + */ +static QDF_STATUS +iot_sim_validate_content(uint8_t *buf, + uint16_t total_len, + uint16_t offset) +{ + char *ie = buf; + uint32_t len = 0, i = 0; + uint32_t fb = sizeof(struct ieee80211_frame); + + if (offset == 0 || offset == fb) { + /* Replace the entire content set by user */ + return QDF_STATUS_SUCCESS; + } + + /* Check for malformed IEs and proper IE + * boundaries in user content + */ + for (i = 0; i < total_len;) { + /* TLV: T(1) + L(1) + V(L)*/ + len = (1 + 1 + ie[1]); + i += len; + ie += len; + } + + if (i == total_len) + return QDF_STATUS_SUCCESS; + + iot_sim_err("iot_sim: cnt(bin) len:%u IE Parsed len:%u", + total_len, + i); + + return QDF_STATUS_E_INVAL; +} + +/* + * iot_sim_handle_frame_content - function to process frame content provided + * by user. This function will convert the ascii + * string into binary string and validate the + * content. + * @isc: iot sim context + * @pos: position to the frame content in the user buffer + * @storage: storage to store frame content after processing + * @offset: user provided offset + * @len: length of the user provided content in bytes + * + * Return: QDF_STATUS_SUCCESS on success + * QDF_STATUS_E_FAULT on hex str to binary conversion failure + * QDF_STATUS_E_NOMEM on memory allocation failure + */ +QDF_STATUS +iot_sim_handle_frame_content(struct iot_sim_context *isc, + const char *pos, + uint8_t **storage, + uint16_t offset, + uint16_t len) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + int ret; + + *storage = qdf_mem_malloc(len); + if (!*storage) { + iot_sim_err("iot_sim:storage allocation failed"); + return QDF_STATUS_E_NOMEM; + } + + ret = qdf_hex_str_to_binary(*storage, pos, len); + if (ret == -1) { + iot_sim_err("iot_sim:hex2bin conversion failed"); + status = QDF_STATUS_E_FAULT; + goto error2; + } + + status = iot_sim_validate_content(*storage, len, offset); + if (QDF_IS_STATUS_ERROR(status)) { + iot_sim_err("iot_sim:User Content Invalid"); + goto error2; + } + + return QDF_STATUS_SUCCESS; + +error2: + qdf_mem_free(*storage); + *storage = NULL; + return status; +} + +/* + * iot_sim_parse_user_input_content_change - function to parse user input into + * predefined format for content + * change operation. All arguments + * passed will be filled upon success + * @isc: iot sim context + * @userbuf: local copy of user input + * @count: length of userbuf + * @t_st: address of type variable + * @seq: address of seq variable + * @offset: address of offset variable + * @length: address of length variable + * @content: double pointer to storage to store frame content after processing + * @addr: pointer to mac address + * + * @storage: storage to store frame content after processing + * @offset: user provided offset + * @len: length of the user provided content in bytes + * + * Return: QDF_STATUS_SUCCESS on success + * QDF_STATUS_E_FAILURE otherwise + */ +QDF_STATUS +iot_sim_parse_user_input_content_change(struct iot_sim_context *isc, + char *userbuf, ssize_t count, + uint8_t *t_st, uint16_t *seq, + uint16_t *offset, uint16_t *length, + uint8_t **content, + struct qdf_mac_addr *addr) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + char *argv[6], *delim = " ", *substr; + int argc = -1, ret = 0; + + qdf_mem_zero(argv, sizeof(argv)); + userbuf = strim(userbuf); + + while ((substr = strsep(&userbuf, delim)) != NULL) { + if (!isspace(*substr) && *substr != '\0') + argv[++argc] = substr; + if (argc >= 5) + break; + } + + if (argc < 3) { + iot_sim_err("Invalid argument count %d", (argc + 1)); + return status; + } + + if (!argv[0] || !argv[1] || !argv[2] || !argv[3]) { + iot_sim_err("One or more arguments are null"); + return status; + } + + ret = kstrtou8(argv[0], 16, t_st); + if (ret) + goto err; + ret = kstrtou16(argv[1], 10, seq); + if (ret) + goto err; + ret = kstrtou16(argv[2], 10, offset); + if (ret) + goto err; + ret = kstrtou16(argv[3], 10, length); + if (ret) + goto err; + /* + * User can send content change data in following format: + * 1. Add rule for specific peer + * + * 2. Add rule for broadcast peer + * + * 3. Remove rule for specific peer + * + * 4. Remove rule for broadcast peer + * + */ + + /* + * If length is 0, this implies remove the rule + */ + if (!*length) { + /* + * 1. Ignore the frame content + * 2. argv[4] is not null, then it must be a valid mac + * If argv[4] is null, then set 'addr' as null + */ + *content = NULL; + if (argv[4]) { + status = qdf_mac_parse(argv[4], addr); + if (QDF_IS_STATUS_ERROR(status)) + iot_sim_err("iot_sim: argv4 is invalid mac for 0 len"); + } else { + qdf_mem_zero(addr, QDF_MAC_ADDR_SIZE); + status = QDF_STATUS_SUCCESS; + } + /* + * No need to parse further just return. + */ + return status; + } + + /* + * If argv[4] is valid, this implies frame content + */ + if (argv[4]) { + status = iot_sim_handle_frame_content(isc, argv[4], + content, *offset, + *length); + if (QDF_IS_STATUS_ERROR(status)) + return status; + } + + /* + * If argv[5] is valid, this must be mac address + */ + if (argv[5]) + status = qdf_mac_parse(argv[5], addr); + + return status; +err: + iot_sim_err("kstrtoXX failed: %d", ret); + return status; +} + +/* + * iot_sim_del_cnt_cng_rule_peer - function to delete content change rule + * @peer: iot sim peer + * @type: 802.11 frame type + * @subtype: 802.11 frame subtype + * @seq: authentication sequence number, mostly 0 for non-authentication frame + * @oper: iot sim operation + * + * Return: QDF_STATUS_SUCCESS + */ +QDF_STATUS +iot_sim_del_cnt_cng_rule_peer(struct iot_sim_rule_per_peer *peer, + uint8_t type, uint8_t subtype, + uint16_t seq, enum iot_sim_operations oper) +{ + /* seq entries and frame entries */ + struct iot_sim_rule_per_seq *s_e; + struct iot_sim_rule *f_e; + uint8_t bm; + + qdf_spin_lock(&peer->iot_sim_lock); + s_e = peer->rule_per_seq[seq]; + if (!s_e) { + qdf_spin_unlock(&peer->iot_sim_lock); + iot_sim_info("s_e is null"); + return QDF_STATUS_SUCCESS; + } + + f_e = s_e->rule_per_type[type][subtype]; + if (f_e && f_e->frm_content) { + qdf_mem_free(f_e->frm_content); + f_e->frm_content = NULL; + bm = f_e->rule_bitmap; + s_e->use_count--; + if (IOT_SIM_CLEAR_OP_BIT(bm, oper)) { + qdf_mem_free(f_e); + s_e->rule_per_type[type][subtype] = NULL; + } + if (s_e->use_count == 0) { + qdf_mem_free(s_e); + peer->rule_per_seq[seq] = NULL; + } + } + qdf_spin_unlock(&peer->iot_sim_lock); + + return QDF_STATUS_SUCCESS; +} + +/* + * iot_sim_delete_rule_for_mac - function to delete content change rule + * for given peer mac + * @isc: iot sim context + * @oper: iot sim operation + * @seq: authentication sequence number, mostly 0 for non-authentication frame + * @type: 802.11 frame type + * @subtype: 802.11 frame subtype + * @mac: peer mac address + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise + */ +QDF_STATUS +iot_sim_delete_rule_for_mac(struct iot_sim_context *isc, + enum iot_sim_operations oper, + uint16_t seq, uint8_t type, + uint8_t subtype, + struct qdf_mac_addr *mac) +{ + QDF_STATUS ret = QDF_STATUS_SUCCESS; + + if (qdf_is_macaddr_zero(mac)) + iot_sim_info("Rule deletion for all peers"); + else + iot_sim_info("Rule deletion for " QDF_MAC_ADDR_STR, + QDF_MAC_ADDR_ARRAY(mac->bytes)); + iot_sim_info("oper:%u type:%hu subtype:%hu seq:%hu", oper, type, + subtype, seq); + + if (!isc) { + iot_sim_err("iot_sim: isc is null"); + return QDF_STATUS_E_FAILURE; + } + + if (oper == CONTENT_CHANGE) { + if (qdf_is_macaddr_broadcast(mac)) { + /* + * Clear rules for bcast peer + */ + ret = iot_sim_del_cnt_cng_rule_peer(&isc->bcast_peer, + type, subtype, + seq, oper); + } else if (qdf_is_macaddr_zero(mac)) { + /* + * Zero mac address, rules will be deleted + * for all peer and including for bcast peer + */ + + /* + * Clear rules for bcast peer + */ + ret = iot_sim_del_cnt_cng_rule_peer(&isc->bcast_peer, + type, subtype, + seq, oper); + /* Clear rules for individual peer + * TBD + */ + } else { + /* TBD: clear the rules for peer with address 'mac'*/ + } + } else if (oper == DROP) { + /* TBD */ + } else if (oper == DELAY) { + /* TBD */ + } + return ret; +} + +/* + * iot_sim_add_cnt_cng_rule_peer - function to add content change rule on peer + * @peer: iot sim peer + * @type: 802.11 frame type + * @subtype: 802.11 frame subtype + * @seq: authentication sequence number, mostly 0 for non-authentication frame + * @frm: frame content to store + * @offset: offset value + * @len: length of frame content + * @oper: iot sim operation + * + * Return: QDF_STATUS_SUCCESS on success, failure otherwise + */ +QDF_STATUS +iot_sim_add_cnt_cng_rule_peer(struct iot_sim_rule_per_peer *peer, + uint8_t type, uint8_t subtype, + uint16_t seq, uint8_t *frm, + uint16_t offset, uint16_t len, + enum iot_sim_operations oper) +{ + struct iot_sim_rule_per_seq *s_e = NULL; + struct iot_sim_rule *f_e = NULL; + + qdf_spin_lock(&peer->iot_sim_lock); + s_e = peer->rule_per_seq[seq]; + if (s_e) { + f_e = s_e->rule_per_type[type][subtype]; + if (!f_e) { + f_e = qdf_mem_malloc(sizeof(struct iot_sim_rule)); + if (!f_e) { + iot_sim_err("can't allocate f_e"); + qdf_spin_unlock(&peer->iot_sim_lock); + return QDF_STATUS_E_NOMEM; + } + s_e->rule_per_type[type][subtype] = f_e; + } + } else { + s_e = qdf_mem_malloc(sizeof(struct iot_sim_rule_per_seq)); + if (!s_e) { + qdf_spin_unlock(&peer->iot_sim_lock); + iot_sim_err("iot_sim: s_e is null"); + return QDF_STATUS_E_NOMEM; + } + + f_e = qdf_mem_malloc(sizeof(struct iot_sim_rule)); + if (!f_e) { + qdf_mem_free(s_e); + peer->rule_per_seq[seq] = NULL; + qdf_spin_unlock(&peer->iot_sim_lock); + iot_sim_err("iot_sim: f_e is null"); + return QDF_STATUS_E_NOMEM; + } + + s_e->rule_per_type[type][subtype] = f_e; + peer->rule_per_seq[seq] = s_e; + } + + f_e->frm_content = qdf_mem_malloc(len); + qdf_mem_copy(f_e->frm_content, frm, len); + f_e->len = len; + f_e->offset = offset; + s_e->use_count++; + IOT_SIM_SET_OP_BIT(f_e->rule_bitmap, oper); + qdf_spin_unlock(&peer->iot_sim_lock); + + iot_sim_info("iot_sim:Rule added for mac: " QDF_MAC_ADDR_STR " oper:%u", + QDF_MAC_ADDR_ARRAY(peer->addr.bytes), oper); + iot_sim_info("type:%x stype:%x sq:%hu off:%hu len:%hu", + type, subtype, seq, offset, len); + + return QDF_STATUS_SUCCESS; +} + +/* + * iot_sim_add_rule_for_mac - function to add content change rule + * for given peer mac + * @isc: iot sim context + * @oper: iot sim operation + * @mac: peer mac address + * @type: 802.11 frame type + * @subtype: 802.11 frame subtype + * @seq: authentication sequence number, mostly 0 for non-authentication frame + * @offset: user provided offset + * @frm: user provided frame content + * @length: length of frm + * + * Return: QDF_STATUS_SUCCESS on success, QDF_STATUS_E_FAILURE otherwise + */ +QDF_STATUS +iot_sim_add_rule_for_mac(struct iot_sim_context *isc, + enum iot_sim_operations oper, + struct qdf_mac_addr *mac, + uint8_t type, uint8_t subtype, + uint16_t seq, uint16_t offset, + uint8_t *frm, uint16_t len) +{ + QDF_STATUS status = QDF_STATUS_E_FAILURE; + + if (!isc) { + iot_sim_err("iot_sim: isc is null"); + return status; + } + + if (oper == CONTENT_CHANGE) { + if (!frm) + return status; + + status = iot_sim_delete_rule_for_mac(isc, oper, seq, + type, subtype, mac); + if (status == QDF_STATUS_E_FAILURE) { + iot_sim_err("iot_sim: Rule removed - Fail"); + return status; + } + + if (qdf_is_macaddr_broadcast(mac)) { + iot_sim_add_cnt_cng_rule_peer(&isc->bcast_peer, type, + subtype, seq, frm, + offset, len, oper); + } else { + /* + * Add entry to peer with MAC 'mac' + */ + /* TBD */ + } + } else if (oper == DROP) { + /* TBD */ + } else if (oper == DELAY) { + /* TBD */ + } + + return QDF_STATUS_SUCCESS; +} + +/* + * IOT SIM User Command Format + * + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * | FrmType/subtype | Seq | Offset | Length | content | Mac Addr | + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * | 1Byte | 2Byte | 2Bytes | 2Bytes | Length | 6 Bytes | + * + */ + +/* + * iot_sim_debug_content_change_write - Write Handler for content change + * operation + * @file: debugfs file pointer + * @buf: buf of user input + * @count: buf count + * @ppos: offset on file + * + * Return: character read on success, failure otherwise + */ +static ssize_t +iot_sim_debug_content_change_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + QDF_STATUS status; + unsigned char t_st, type, subtype, *content = NULL; + uint16_t offset = 0, length = 0, seq = 0; + char *locbuf; + enum iot_sim_operations oper = CONTENT_CHANGE; + struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT; + struct iot_sim_context *isc = + ((struct seq_file *)file->private_data)->private; + + if ((!buf) || (count > USER_BUF_LEN) || (count < 7)) + return -EFAULT; + + locbuf = qdf_mem_malloc(USER_BUF_LEN + 1); + if (!locbuf) + return -ENOMEM; + + if (copy_from_user(locbuf, buf, count)) { + qdf_mem_free(locbuf); + return -EFAULT; + } + + status = iot_sim_parse_user_input_content_change(isc, locbuf, count, + &t_st, &seq, &offset, + &length, &content, + &mac_addr); + if (QDF_IS_STATUS_ERROR(status)) { + qdf_mem_free(locbuf); + return count; + } + + type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; + subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK); + subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + + if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ) { + qdf_mem_free(locbuf); + return -EFAULT; + } + + /* check for rule removal */ + if (!length || !content) { + status = iot_sim_delete_rule_for_mac(isc, oper, seq, + type, subtype, + &mac_addr); + if (QDF_IS_STATUS_ERROR(status)) + iot_sim_err("iot_sim: Rule removed - Fail"); + else + iot_sim_err("iot_sim: Rule removed - success"); + + qdf_mem_free(locbuf); + return count; + } + + status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr, type, subtype, + seq, offset, content, length); + + if (QDF_IS_STATUS_ERROR(status)) + iot_sim_err("iot_sim: Rule Add - Fail"); + + qdf_mem_free(content); + qdf_mem_free(locbuf); + return count; +} + +/* + * iot_sim_debug_delay_write - Write Handler for delay operation + * @file: debugfs file pointer + * @buf: buf of user input + * @count: buf count + * @ppos: offset on file + * + * Return: character read + */ +static ssize_t +iot_sim_debug_delay_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + iot_sim_err("delay iot sim ops called"); + return count; +} + +/* + * iot_sim_debug_drop_write - Write Handler for drop operation + * @file: debugfs file pointer + * @buf: buf of user input + * @count: buf count + * @ppos: offset on file + * + * Return: character read + */ +static ssize_t +iot_sim_debug_drop_write(struct file *file, + const char __user *buf, + size_t count, loff_t *ppos) +{ + iot_sim_err("drop iot sim ops called"); + return count; +} + +/* + * debug_iot_sim_##func_base##_show() - debugfs functions to display content + * dummy function + * Return: success + */ +#define GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(func_base) \ + static int iot_sim_debug_##func_base##_show(struct seq_file *m, \ + void *v) \ +{ \ + return qdf_status_to_os_return(QDF_STATUS_SUCCESS); \ +} + +GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(content_change); +GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(delay); +GENERATE_IOT_SIM_DEBUG_SHOW_FUNCS(drop); + +/* + * debug_##func_base##_open() - Open debugfs entry for respective command + * and event buffer. + * + * @inode: node for debug dir entry + * @file: file handler + * + * Return: open status + */ +#define GENERATE_DEBUG_IOT_SIM_STRUCTS(func_base) \ + static int debug_##func_base##_open(struct inode *inode, \ + struct file *file) \ +{ \ + return single_open(file, iot_sim_debug_##func_base##_show, \ + inode->i_private); \ +} \ + \ +static const struct file_operations debug_##func_base##_ops = { \ + .open = debug_##func_base##_open, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .write = iot_sim_debug_##func_base##_write, \ + .release = single_release, \ +} + +GENERATE_DEBUG_IOT_SIM_STRUCTS(content_change); +GENERATE_DEBUG_IOT_SIM_STRUCTS(drop); +GENERATE_DEBUG_IOT_SIM_STRUCTS(delay); + +/* Structure to maintain debug information */ +struct iot_sim_dbgfs_file { + const char *name; + const struct file_operations *ops; +}; + +#define DEBUG_IOT_SIM(func_base) { .name = #func_base, \ + .ops = &debug_##func_base##_ops \ +} + +struct iot_sim_dbgfs_file iot_sim_dbgfs_files[IOT_SIM_DEBUGFS_FILE_NUM] = { + DEBUG_IOT_SIM(content_change), + DEBUG_IOT_SIM(drop), + DEBUG_IOT_SIM(delay), +}; QDF_STATUS -iot_sim_control_cmn(struct wlan_objmgr_psoc *psoc, wbuf_t wbuf) +iot_sim_control_cmn(struct wlan_objmgr_pdev *pdev, wbuf_t wbuf) { QDF_STATUS status = QDF_STATUS_E_FAILURE; struct iot_sim_context *isc; - if (!psoc) { + if (!pdev) { iot_sim_err("PDEV is NULL!"); goto bad; } - isc = iot_sim_get_ctx_from_psoc(psoc); + isc = iot_sim_get_ctx_from_pdev(pdev); if (!isc) { iot_sim_err("iot_sim context is NULL!"); goto bad; @@ -53,52 +712,180 @@ iot_sim_ctx_deinit(struct iot_sim_context *isc) isc->iot_sim_operation_handler = NULL; } -QDF_STATUS -wlan_iot_sim_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg) +/** + * iot_sim_debugfs_deinit() - Deinit functions to remove debugfs directory and + * it's file enteries. + * @isc: iot_sim context + * + * Return: init status + */ +static QDF_STATUS +iot_sim_debugfs_deinit(struct iot_sim_context *isc) { - struct iot_sim_context *isc = NULL; - - if (!psoc) { - iot_sim_err("PSOC is NULL"); - return QDF_STATUS_E_NULL_VALUE; - } - - isc = (struct iot_sim_context *) - qdf_mem_malloc(sizeof(struct iot_sim_context)); - if (!isc) - return QDF_STATUS_E_NOMEM; - - isc->psoc_obj = psoc; - wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_IOT_SIM_COMP, - (void *)isc, QDF_STATUS_SUCCESS); - - iot_sim_info("iot_sim component psoc object created"); + debugfs_remove_recursive(isc->iot_sim_dbgfs_ctx.iot_sim_dir_de); return QDF_STATUS_SUCCESS; } +/* + * iot_sim_remove_all_oper_rules - Function to remove all configured rules + * for given operation + * + * @isc: iot sim context + * @oper: iot sim operation + * + * Return: void + */ +static void +iot_sim_remove_all_oper_rules(struct iot_sim_context *isc, + enum iot_sim_operations oper) +{ + uint16_t seq; + uint8_t type, subtype; + struct qdf_mac_addr zero_mac_addr = QDF_MAC_ADDR_ZERO_INIT; + + for (seq = 0; seq < MAX_SEQ; seq++) + for (type = 0; type < N_FRAME_TYPE; type++) + for (subtype = 0; subtype < N_FRAME_SUBTYPE; subtype++) + iot_sim_delete_rule_for_mac(isc, oper, seq, + type, subtype, + &zero_mac_addr); +} + +/* + * iot_sim_remove_all_rules - Function to remove all configured rules + * + * @isc: iot sim context + * + * Return: void + */ +static void +iot_sim_remove_all_rules(struct iot_sim_context *isc) +{ + enum iot_sim_operations oper; + + if (!isc) + return; + + for (oper = CONTENT_CHANGE; oper < IOT_SIM_MAX_OPERATION; oper++) + iot_sim_remove_all_oper_rules(isc, oper); +} + +/** + * iot_sim_debugfs_init() - debugfs functions to create debugfs directory and to + * create debugfs enteries. + * @isc: iot_sim context + * + * Return: init status + */ +static QDF_STATUS +iot_sim_debugfs_init(struct iot_sim_context *isc) +{ + struct dentry *dbgfs_dir = NULL; + struct dentry *de = NULL; + uint8_t i, pdev_id; + char buf[32]; + + if (!isc) + return QDF_STATUS_E_FAILURE; + + pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj); + + qdf_mem_zero(buf, sizeof(buf)); + snprintf(buf, sizeof(buf), "iot_sim_pdev%u", pdev_id); + + dbgfs_dir = debugfs_create_dir(buf, NULL); + isc->iot_sim_dbgfs_ctx.iot_sim_dir_de = dbgfs_dir; + + if (!isc->iot_sim_dbgfs_ctx.iot_sim_dir_de) { + iot_sim_err("dbgfs dir creation failed for pdev%u", pdev_id); + return QDF_STATUS_E_FAILURE; + } + + for (i = 0; i < IOT_SIM_DEBUGFS_FILE_NUM; ++i) { + de = debugfs_create_file(iot_sim_dbgfs_files[i].name, + 0644, + dbgfs_dir, isc, + iot_sim_dbgfs_files[i].ops); + + if (!de) { + iot_sim_err("dbgfs file creation failed for pdev%u", + pdev_id); + goto out; + } + isc->iot_sim_dbgfs_ctx.iot_sim_file_de[i] = de; + } + + return QDF_STATUS_SUCCESS; + +out: + debugfs_remove_recursive(dbgfs_dir); + qdf_mem_set(isc->iot_sim_dbgfs_ctx.iot_sim_file_de, + sizeof(isc->iot_sim_dbgfs_ctx.iot_sim_file_de), 0); + + return QDF_STATUS_E_FAILURE; +} + QDF_STATUS -wlan_iot_sim_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, +wlan_iot_sim_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg) +{ + struct iot_sim_context *isc = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (!pdev) { + iot_sim_err("pdev is NULL"); + return QDF_STATUS_E_NULL_VALUE; + } + + isc = qdf_mem_malloc(sizeof(struct iot_sim_context)); + if (!isc) + return QDF_STATUS_E_NOMEM; + + isc->pdev_obj = pdev; + + if (QDF_IS_STATUS_ERROR(iot_sim_debugfs_init(isc))) { + qdf_mem_free(isc); + iot_sim_info("iot_sim debugfs file creation failed"); + return QDF_STATUS_E_FAILURE; + } + + qdf_set_macaddr_broadcast(&isc->bcast_peer.addr); + qdf_spinlock_create(&isc->bcast_peer.iot_sim_lock); + qdf_list_create(&isc->bcast_peer.p_list, 0); + + wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_IOT_SIM_COMP, + (void *)isc, QDF_STATUS_SUCCESS); + + iot_sim_err("iot_sim component pdev object created"); + + return status; +} + +QDF_STATUS +wlan_iot_sim_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg) { struct iot_sim_context *isc = NULL; - if (!psoc) { - iot_sim_err("PSOC is NULL"); + if (!pdev) { + iot_sim_err("pdev is NULL"); return QDF_STATUS_E_NULL_VALUE; } - isc = wlan_objmgr_psoc_get_comp_private_obj(psoc, + isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP); if (isc) { - wlan_objmgr_psoc_component_obj_detach(psoc, + wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_IOT_SIM_COMP, (void *)isc); /* Deinitilise function pointers from iot_sim context */ iot_sim_ctx_deinit(isc); + iot_sim_debugfs_deinit(isc); + iot_sim_remove_all_rules(isc); + qdf_spinlock_destroy(&isc->bcast_peer.iot_sim_lock); qdf_mem_free(isc); } - iot_sim_info("iot_sim component psoc object destroyed"); + iot_sim_err("iot_sim component pdev object destroyed"); return QDF_STATUS_SUCCESS; } diff --git a/iot_sim/core/iot_sim_defs_i.h b/iot_sim/core/iot_sim_defs_i.h index fe1ff2b085ea..e6e3900e145b 100644 --- a/iot_sim/core/iot_sim_defs_i.h +++ b/iot_sim/core/iot_sim_defs_i.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include #include @@ -74,46 +74,95 @@ #define N_FRAME_TYPE 0x4 #define N_FRAME_SUBTYPE 0xF #define MAX_SEQ 0x4 +#define IOT_SIM_DEBUGFS_FILE_NUM 3 -/* struct iot_sim_content - represent user content +/* + * struct iot_sim_debugfs - contains dentry pointer for opened + * iot sim files and directory + * @iot_sim_dir_de - dentry pointer to pdev specific folder + * @iot_sim_file_de - dentry pointer representing operation specific files + */ +struct iot_sim_debugfs { + struct dentry *iot_sim_dir_de; + struct dentry *iot_sim_file_de[IOT_SIM_DEBUGFS_FILE_NUM]; +}; + +/* + * struct iot_sim_rule - represent user configured rules * @len - Length of the content provided by user * @offset - offset at which modification done in capture frame * @frm_content - actual user data in hex * @drop - frame marked for drop * @delay_dur - duration of delay */ -struct iot_sim_content { +struct iot_sim_rule { uint16_t len; uint16_t offset; uint8_t *frm_content; bool drop; uint16_t delay_dur; + uint8_t rule_bitmap; }; -/* Per Peer iot_sim data per frame type/subtype */ -struct iot_sim_fb_array_peer { - struct qdf_mac_addr peer_addr; - struct iot_sim_content iot_sim_fb_array[N_FRAME_TYPE][N_FRAME_SUBTYPE]; +/* + * struct iot_sim_rule_per_seq - rule structure per sequence iot sim files + * and directory + * + * @rule_per_type - 2d array of iot_sim_rule per type subtype + * @use_count - usage reference + */ +struct iot_sim_rule_per_seq { + struct iot_sim_rule *rule_per_type[N_FRAME_TYPE][N_FRAME_SUBTYPE]; + uint8_t use_count; +}; + +/* + * struct iot_sim_rule_per_peer - peer specific structure for iot sim ops + * + * @addr - address of peer + * @iot_sim_lock - spinlock + * @rule_per_seq - array of iot_sim_rule_per_seq + * @p_list - list variable + */ +struct iot_sim_rule_per_peer { + struct qdf_mac_addr addr; + qdf_spinlock_t iot_sim_lock; + struct iot_sim_rule_per_seq *rule_per_seq[MAX_SEQ]; qdf_list_t p_list; }; /** - * struct iot_sim_context - iot_sim psoc private object - * @psoc_obj:Reference to psoc global object - * @iot_sim_lock: spinlock for synchronization - * - * Call back functions - * @iot_sim_opertion_handler: iot sim operations handler + * struct iot_sim_context - iot_sim pdev private object + * @pdev_obj:Reference to pdev global object + * @iot_sim_peer_list: peer list for peer specific rules + * @bcast_peer: broadcast peer entry for storing rules for all peers + * @p_iot_sim_target_handle: handle to iot_sim target_if + * @iot_sim_operation_handler: callback for iot sim operation handler */ - struct iot_sim_context { - struct wlan_objmgr_psoc *psoc_obj; - qdf_spinlock_t iot_sim_lock; - /* IOT_SIM Peer list */ - struct iot_sim_fb_arrary_peer *iot_sim_peer_list; + struct wlan_objmgr_pdev *pdev_obj; + /* IOT_SIM Peer list & Bcast Peer */ + struct iot_sim_rule_per_peer *iot_sim_peer_list, bcast_peer; void *p_iot_sim_target_handle; - QDF_STATUS (*iot_sim_operation_handler)(struct wlan_objmgr_psoc *psoc, + struct iot_sim_debugfs iot_sim_dbgfs_ctx; + QDF_STATUS (*iot_sim_operation_handler)(struct wlan_objmgr_pdev *pdev, wbuf_t wbuf); }; +/* enum iot_sim_operations - iot sim operations + * + * @INVALID_OPERATION - invalid operation + * @CONTENT_CHANGE - Frame Content Change operation + * @DROP - Frame drop operation + * @DELAY - Frame delay operation + * @IOT_SIM_MAX_OPERATION - iot sim max operation + */ +enum iot_sim_operations { + INVALID_OPERATION, + CONTENT_CHANGE = 1, + DROP, + DELAY, + IOT_SIM_MAX_OPERATION +}; + #endif /* _IOT_SIM_DEFS_I_H_ */ diff --git a/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c b/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c index 04b721eae491..cd9036873f81 100644 --- a/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c +++ b/iot_sim/dispatcher/src/wlan_iot_sim_tgt_api.c @@ -18,18 +18,18 @@ #include void * -tgt_get_target_handle(struct wlan_objmgr_psoc *psoc) +tgt_get_target_handle(struct wlan_objmgr_pdev *pdev) { struct iot_sim_context *isc; - if (!psoc) { - iot_sim_err("psoc is NULL!"); + if (!pdev) { + iot_sim_err("pdev is NULL!"); return NULL; } - isc = wlan_objmgr_psoc_get_comp_private_obj(psoc, + isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP); if (!isc) { - iot_sim_err("psoc IOT_SIM object is NULL!"); + iot_sim_err("pdev IOT_SIM object is NULL!"); return NULL; } return isc->p_iot_sim_target_handle; diff --git a/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c b/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c index 8ee908fe1edc..3f56af22b9db 100644 --- a/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c +++ b/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c @@ -22,16 +22,16 @@ QDF_STATUS wlan_iot_sim_init(void) { - if (wlan_objmgr_register_psoc_create_handler( + if (wlan_objmgr_register_pdev_create_handler( WLAN_IOT_SIM_COMP, - wlan_iot_sim_psoc_obj_create_handler, + wlan_iot_sim_pdev_obj_create_handler, NULL) != QDF_STATUS_SUCCESS) { return QDF_STATUS_E_FAILURE; } - if (wlan_objmgr_register_psoc_destroy_handler( + if (wlan_objmgr_register_pdev_destroy_handler( WLAN_IOT_SIM_COMP, - wlan_iot_sim_psoc_obj_destroy_handler, + wlan_iot_sim_pdev_obj_destroy_handler, NULL) != QDF_STATUS_SUCCESS) { return QDF_STATUS_E_FAILURE; @@ -43,16 +43,16 @@ wlan_iot_sim_init(void) QDF_STATUS wlan_iot_sim_deinit(void) { - if (wlan_objmgr_unregister_psoc_create_handler( + if (wlan_objmgr_unregister_pdev_create_handler( WLAN_IOT_SIM_COMP, - wlan_iot_sim_psoc_obj_create_handler, + wlan_iot_sim_pdev_obj_create_handler, NULL) != QDF_STATUS_SUCCESS) { return QDF_STATUS_E_FAILURE; } - if (wlan_objmgr_unregister_psoc_destroy_handler( + if (wlan_objmgr_unregister_pdev_destroy_handler( WLAN_IOT_SIM_COMP, - wlan_iot_sim_psoc_obj_destroy_handler, + wlan_iot_sim_pdev_obj_destroy_handler, NULL) != QDF_STATUS_SUCCESS) { return QDF_STATUS_E_FAILURE;