diff --git a/iot_sim/core/iot_sim_cmn_api_i.h b/iot_sim/core/iot_sim_cmn_api_i.h index a8cd37b61e..71b6141059 100644 --- a/iot_sim/core/iot_sim_cmn_api_i.h +++ b/iot_sim/core/iot_sim_cmn_api_i.h @@ -31,6 +31,15 @@ * */ #define USER_BUF_LEN (1 + 2 + 2 + 2 + MAX_BUFFER_SIZE + 6) +/* + * IOT SIM User Buf Format for Drop + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * |FrmType/subtype| Seq |category|action| drop |MacAddr| + * ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + * | 2Characters |2char| 2chars |2chars| 1char|17chars| + * + */ +#define USER_BUF_LEN_DROP (2 + 2 + 2 + 2 + 1 + 17) /** * wlan_iot_sim_pdev_obj_create_handler() - handler for pdev object create @@ -80,6 +89,7 @@ QDF_STATUS iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat, * iot_sim_frame_update() - Management frame update * @pdev: reference to global pdev object * @nbuf: frame buffer + * @direction: direction tx or rx * * This function updates the outgoing management frame with * the content stored in iot_sim_context. @@ -87,7 +97,8 @@ QDF_STATUS iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat, * Return: QDF_STATUS_SUCCESS on success * QDF_STATUS_E_FAILURE on failure */ -QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf); +QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, + qdf_nbuf_t nbuf, bool direction); /* * iot_sim_get_ctx_from_pdev() - API to get iot_sim context object diff --git a/iot_sim/core/iot_sim_common.c b/iot_sim/core/iot_sim_common.c index debc8fd947..0ece3dfa9a 100644 --- a/iot_sim/core/iot_sim_common.c +++ b/iot_sim/core/iot_sim_common.c @@ -20,6 +20,7 @@ #include #include #include +#include #include /* @@ -267,9 +268,9 @@ iot_sim_parse_user_input_content_change(struct iot_sim_context *isc, int argc = -1, ret = 0; qdf_mem_zero(argv, sizeof(argv)); - userbuf = strim(userbuf); + userbuf = qdf_str_trim(userbuf); - while ((substr = strsep(&userbuf, delim)) != NULL) { + while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) { if (!isspace(*substr) && *substr != '\0') argv[++argc] = substr; if (argc >= 5) @@ -360,6 +361,17 @@ err: return status; } +/* + * iot_sim_get_index_for_action_frm - function to convert 802.11 action frame + * category and action code into iot sim + * specific code. + * + * @frm: buf containing 802.11 action/category codes + * @cat_type: buf to hold converted category code + * @act_type: buf to hold converted action code + * + * Return: QDF_STATUS_SUCCESS on success, failure otherwise + */ QDF_STATUS iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type, uint8_t *act_type) @@ -405,6 +417,30 @@ iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type, return QDF_STATUS_SUCCESS; } +/* + * iot_sim_action_frame_supported_by_fw - function to find if action frame is + * supported by fw or not + * @category: iot_sim specific category code + * @action: iot_sim specific action code + * + * Return: true if supported else false + */ +bool +iot_sim_action_frame_supported_by_fw(uint8_t category, uint8_t action) +{ + switch (category) { + case IEEE80211_ACTION_CAT_BA: + switch (action) { + case IEEE80211_ACTION_BA_ADDBA_REQUEST: + return true; + default: + return false; + } + default: + return false; + } +} + /* * iot_sim_frame_supported_by_fw - function to find if frame is supported by fw * @type: 802.11 frame type @@ -413,8 +449,11 @@ iot_sim_get_index_for_action_frm(uint8_t *frm, uint8_t *cat_type, * Return: true if supported else false */ bool -iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype) +iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype, bool action) { + if (action) + return iot_sim_action_frame_supported_by_fw(type, subtype); + switch (type << IEEE80211_FC0_TYPE_SHIFT) { case IEEE80211_FC0_TYPE_MGT: switch (subtype << IEEE80211_FC0_SUBTYPE_SHIFT) { @@ -444,6 +483,74 @@ iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype) } } +/* + * iot_sim_remap_type_subtype - function to convert rules for response + * type frame into request type. This is + * used for drop/delay operation. This function + * will update the passed type and subtype value. + * + * @type: 802.11 frame type + * @subtype: 802.11 frame subtype + * @seq: authentication sequence number, mostly 0 for non-authentication frame + * @action: flag to indicate action frame + * + * Return: QDF_STATUS_SUCCESS + */ +QDF_STATUS +iot_sim_remap_type_subtype(uint8_t *type, uint8_t *subtype, + uint16_t *seq, bool action) +{ + if (action) { + switch (*type) { + case CAT_BA: + switch (*subtype) { + case IEEE80211_ACTION_BA_ADDBA_RESPONSE: + *subtype = IEEE80211_ACTION_BA_ADDBA_REQUEST; + break; + default: + break; + } + break; + default: + break; + } + return QDF_STATUS_SUCCESS; + } + + switch (*type << IEEE80211_FC0_TYPE_SHIFT) { + case IEEE80211_FC0_TYPE_MGT: + switch (*subtype << IEEE80211_FC0_SUBTYPE_SHIFT) { + case IEEE80211_FC0_SUBTYPE_ASSOC_RESP: + *subtype = IEEE80211_FC0_SUBTYPE_ASSOC_REQ; + *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + break; + case IEEE80211_FC0_SUBTYPE_REASSOC_RESP: + *subtype = IEEE80211_FC0_SUBTYPE_REASSOC_REQ; + *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + break; + case IEEE80211_FC0_SUBTYPE_PROBE_RESP: + *subtype = IEEE80211_FC0_SUBTYPE_PROBE_REQ; + *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + break; + case IEEE80211_FC0_SUBTYPE_AUTH: + *subtype = IEEE80211_FC0_SUBTYPE_AUTH; + *subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + /* If auth response (auth seq num 2) is marked as + * drop, then drop the auth request (auth seq num 1) + */ + if (*seq == IEEE80211_AUTH_OPEN_RESPONSE) + *seq = IEEE80211_AUTH_OPEN_REQUEST; + break; + default: + break; + } + default: + break; + } + + return QDF_STATUS_SUCCESS; +} + /* * iot_sim_send_rule_to_fw - function to send iot_sim rule to fw * @@ -456,6 +563,8 @@ iot_sim_frame_supported_by_fw(uint8_t type, uint8_t subtype) * @offset: user provided offset * @frm: user provided frame content * @length: length of frm + * @action: flag to indicate action frame + * @drop: flag to indicate set drop rule * @clear: flag to indicate set rule or clear * * Return: QDF_STATUS_SUCCESS @@ -466,20 +575,30 @@ iot_sim_send_rule_to_fw(struct iot_sim_context *isc, struct qdf_mac_addr *mac, uint8_t type, uint8_t subtype, uint16_t seq, uint16_t offset, - uint8_t *frm, uint16_t len, bool clear) + uint8_t *frm, uint16_t len, + bool action, bool clear) { struct simulation_test_params param; - if (iot_sim_frame_supported_by_fw(type, subtype)) { + if (iot_sim_frame_supported_by_fw(type, subtype, action)) { qdf_mem_zero(¶m, sizeof(struct simulation_test_params)); param.pdev_id = wlan_objmgr_pdev_get_pdev_id(isc->pdev_obj); qdf_mem_copy(param.peer_mac, mac, QDF_MAC_ADDR_SIZE); param.test_cmd_type = oper; - /* subtype_cmd: Rule:- set:0 clear:1 */ - param.test_subcmd_type = clear; + /* subtype_cmd: Set subcmd based on action and clear flag */ + if (action) { + if (clear) + param.test_subcmd_type = DEL_RULE_ACTION; + else + param.test_subcmd_type = ADD_RULE_ACTION; + } else { + if (clear) + param.test_subcmd_type = DEL_RULE; + else + param.test_subcmd_type = ADD_RULE; + } param.frame_type = type; param.frame_subtype = subtype; - param.seq = seq; param.offset = offset; param.frame_length = len; @@ -514,14 +633,18 @@ iot_sim_del_rule(struct iot_sim_rule_per_seq **s_e, qdf_mem_free((*f_e)->frm_content); (*f_e)->frm_content = NULL; } else if (oper == DROP) { - /* TBD */ + (*f_e)->drop = false; } else if (oper == DELAY) { /* TBD */ } - (*s_e)->use_count--; - qdf_clear_bit(oper, (unsigned long *) - &(*f_e)->rule_bitmap); + if (qdf_test_bit(oper, (unsigned long *) + &(*f_e)->rule_bitmap)) { + (*s_e)->use_count--; + qdf_clear_bit(oper, (unsigned long *) + &(*f_e)->rule_bitmap); + } + if (!(*f_e)->rule_bitmap) { qdf_mem_free(*f_e); *f_e = NULL; @@ -575,6 +698,9 @@ iot_sim_delete_rule_for_mac(struct iot_sim_context *isc, return QDF_STATUS_E_FAILURE; } + if (oper == DROP || oper == DELAY) + iot_sim_remap_type_subtype(&type, &subtype, &seq, action); + peer = iot_sim_find_peer_from_mac(isc, mac); if (peer) { qdf_spin_lock(&peer->iot_sim_lock); @@ -631,7 +757,7 @@ iot_sim_add_rule(struct iot_sim_rule_per_seq **s_e, (*f_e)->len = len; (*f_e)->offset = offset; } else if (oper == DROP) { - /* TBD */ + (*f_e)->drop = true; } else if (oper == DELAY) { /* TBD */ } @@ -666,7 +792,7 @@ iot_sim_add_rule_for_mac(struct iot_sim_context *isc, uint8_t type, uint8_t subtype, uint16_t seq, uint16_t offset, uint8_t *frm, uint16_t len, - bool action) + uint8_t drop, bool action) { QDF_STATUS status = QDF_STATUS_E_FAILURE; struct iot_sim_rule_per_peer *peer; @@ -686,6 +812,9 @@ iot_sim_add_rule_for_mac(struct iot_sim_context *isc, return status; } + if (oper == DROP || oper == DELAY) + iot_sim_remap_type_subtype(&type, &subtype, &seq, action); + peer = iot_sim_find_peer_from_mac(isc, mac); if (peer) { qdf_spin_lock(&peer->iot_sim_lock); @@ -800,7 +929,8 @@ iot_sim_debug_content_change_write(struct file *file, clear = length ? false : true; status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype, - seq, offset, content, length, clear); + seq, offset, content, length, + is_action, clear); if (QDF_IS_STATUS_SUCCESS(status)) goto free; @@ -814,7 +944,8 @@ iot_sim_debug_content_change_write(struct file *file, } else { status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr, type, subtype, seq, offset, - content, length, is_action); + content, length, 0, + is_action); } if (QDF_IS_STATUS_SUCCESS(status)) iot_sim_err("iot_sim: Content Change Operation - success"); @@ -845,6 +976,96 @@ iot_sim_debug_delay_write(struct file *file, return count; } +/* + * iot_sim_parse_user_input_drop - function to parse user input into + * predefined format for drop operation. + * All arguments passed will be filled + * upon success + * @isc: iot sim context + * @userbuf: local copy of user input + * @count: length of userbuf + * @t_st: address of type variable + * @seq: address of seq variable + * @cat_type: 802.11 action frame category code + * @act_type: 802.11 action frame action code + * @drop: address of drop variable to specify drop the frame or not + * @addr: pointer to mac address + * + * Return: QDF_STATUS_SUCCESS on success + * QDF_STATUS_E_FAILURE otherwise + */ +QDF_STATUS +iot_sim_parse_user_input_drop(struct iot_sim_context *isc, + char *userbuf, ssize_t count, + uint8_t *t_st, uint16_t *seq, + uint8_t *cat_type, uint8_t *act_type, + uint8_t *drop, struct qdf_mac_addr *addr) +{ + QDF_STATUS status = QDF_STATUS_SUCCESS; + char *argv[6], *delim = " ", *substr; + int argc = -1, ret = 0; + + qdf_mem_zero(argv, sizeof(argv)); + userbuf = qdf_str_trim(userbuf); + + while ((substr = qdf_str_sep(&userbuf, delim)) != NULL) { + if (!isspace(*substr) && *substr != '\0') + argv[++argc] = substr; + if (argc >= 5) + break; + } + + if (argc < 3) { + iot_sim_err("Invalid argument count %d", (argc + 1)); + return status; + } + + if (!argv[0] || !argv[1] || !argv[2] || !argv[3] || !argv[4]) { + iot_sim_err("One or more arguments are null"); + return status; + } + /* + * User can send drop data in following format: + * 1. Add drop rule for specific peer + * + * 2. Add drop rule for broadcast peer + * + * 3. Remove drop rule for specific peer + * + * 4. Remove drop rule for broadcast peer + * + * 5. Remove drop rule for all peer + * + */ + + ret = kstrtou8(argv[0], 16, t_st); + if (ret) + goto err; + ret = kstrtou16(argv[1], 10, seq); + if (ret) + goto err; + ret = kstrtou8(argv[2], 10, cat_type); + if (ret) + goto err; + ret = kstrtou8(argv[3], 10, act_type); + if (ret) + goto err; + ret = kstrtou8(argv[4], 10, drop); + if (ret) + goto err; + + /* + * If argv[5] is valid, this must be mac address + */ + if (argv[5]) + status = qdf_mac_parse(argv[5], addr); + + return status; +err: + iot_sim_err("kstrtoXX failed: %d", ret); + return QDF_STATUS_E_FAILURE; +} + /* * iot_sim_debug_drop_write - Write Handler for drop operation * @file: debugfs file pointer @@ -859,7 +1080,81 @@ iot_sim_debug_drop_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - iot_sim_err("drop iot sim ops called"); + QDF_STATUS status = QDF_STATUS_SUCCESS; + unsigned char t_st, type, subtype; + uint16_t seq = 0; + char *locbuf = NULL; + enum iot_sim_operations oper = DROP; + struct qdf_mac_addr mac_addr = QDF_MAC_ADDR_BCAST_INIT; + struct iot_sim_context *isc = + ((struct seq_file *)file->private_data)->private; + uint8_t action = 0, category = 0, tmp[2], drop = 0; + bool is_action = false, clear = false; + + if ((!buf) || (count > USER_BUF_LEN_DROP) || (count < 6)) + return -EFAULT; + + locbuf = qdf_mem_malloc(USER_BUF_LEN_DROP + 1); + if (!locbuf) + return -ENOMEM; + + if (copy_from_user(locbuf, buf, count)) { + qdf_mem_free(locbuf); + return -EFAULT; + } + + status = iot_sim_parse_user_input_drop(isc, locbuf, count, + &t_st, &seq, &category, + &action, &drop, &mac_addr); + if (QDF_IS_STATUS_ERROR(status)) + goto free; + + type = (t_st & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; + subtype = (t_st & IEEE80211_FC0_SUBTYPE_MASK); + subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + + if (type > N_FRAME_TYPE || subtype > N_FRAME_SUBTYPE || seq > MAX_SEQ) + goto free; + + if (FRAME_TYPE_IS_ACTION(type, subtype)) { + tmp[0] = category; + tmp[1] = action; + /* + * convert 802.11 category and action code to iot sim codes + */ + status = iot_sim_get_index_for_action_frm(tmp, &category, + &action); + if (QDF_IS_STATUS_ERROR(status)) + goto free; + + is_action = 1; + type = category; + subtype = action; + } + + clear = drop ? false : true; + status = iot_sim_send_rule_to_fw(isc, oper, &mac_addr, type, subtype, + seq, 0, NULL, 0, is_action, clear); + if (QDF_IS_STATUS_SUCCESS(status)) + goto free; + + /* check for rule removal */ + if (!drop) { + status = iot_sim_delete_rule_for_mac(isc, oper, seq, + type, subtype, + &mac_addr, + is_action); + } else { + status = iot_sim_add_rule_for_mac(isc, oper, &mac_addr, + type, subtype, seq, 0, + NULL, 0, drop, is_action); + } + if (QDF_IS_STATUS_SUCCESS(status)) + iot_sim_debug("iot_sim: Rule update Drop Operation - Success"); + else + iot_sim_err("iot_sim: Rule update Drop Operation - Fail"); +free: + qdf_mem_free(locbuf); return count; } diff --git a/iot_sim/core/iot_sim_defs_i.h b/iot_sim/core/iot_sim_defs_i.h index 291880acc0..1adcfe1148 100644 --- a/iot_sim/core/iot_sim_defs_i.h +++ b/iot_sim/core/iot_sim_defs_i.h @@ -164,11 +164,26 @@ struct iot_sim_context { * @IOT_SIM_MAX_OPERATION - iot sim max operation */ enum iot_sim_operations { - INVALID_OPERATION, - CONTENT_CHANGE = 1, + CONTENT_CHANGE, DROP, DELAY, IOT_SIM_MAX_OPERATION }; +/* enum iot_sim_subcmd - iot sim FW related subcommands + * + * @ADD_RULE - Add Rule + * @DEL_RULE - Delete Rule + * @ADD_RULE_ACTION - Add rule for action frame + * @DEL_RULE_ACTION - Del rule for action frame + * @IOT_SIM_MAX_SUBCMD - iot sim max subcmd + */ +enum iot_sim_subcmd { + ADD_RULE = 0, + DEL_RULE, + ADD_RULE_ACTION, + DEL_RULE_ACTION, + IOT_SIM_MAX_SUBCMD, +}; + #endif /* _IOT_SIM_DEFS_I_H_ */ diff --git a/iot_sim/core/iot_sim_utils.c b/iot_sim/core/iot_sim_utils.c index ac1e62477c..b20dc0cf3e 100644 --- a/iot_sim/core/iot_sim_utils.c +++ b/iot_sim/core/iot_sim_utils.c @@ -22,78 +22,31 @@ #define IEEE80211_FRAME_BODY_OFFSET 0x18 -QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf) +/* + * iot_sim_apply_content_change_rule - function to apply content change rule + * packet from upper stack will be modified + * as per the user content. + * @piot_sim_rule: iot_sim rule structure + * @nbuf: skb coming from upper stack + * @fixed_param_length: length of fixed parameters in frame body + * + * Return: QDF_STATUS_SUCCESS on successful content update or otherwise + * QDF_STATUS_E_NOSUPPORT, no content change rule found for this frame + */ +QDF_STATUS +iot_sim_apply_content_change_rule(struct iot_sim_rule *piot_sim_rule, + qdf_nbuf_t nbuf, + int fixed_param_length) { - uint8_t type, subtype, seq = 0; - struct iot_sim_context *isc; - uint8_t *buf = qdf_nbuf_data(nbuf), *frm = NULL; - int fixed_param_length = 0; - bool is_action_frm = false; - uint8_t cat, cat_index; - int auth_seq_index = 0, offset = 0; - struct iot_sim_rule *piot_sim_rule = NULL; + uint8_t *buf = NULL; qdf_size_t buf_len = 0; - - type = (buf[0] & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; - subtype = (buf[0] & IEEE80211_FC0_SUBTYPE_MASK); - isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP); - if (!isc) { - iot_sim_err("pdev IOT_SIM object is NULL!"); - return QDF_STATUS_SUCCESS; - } - - if (type == IEEE80211_FC0_TYPE_MGT && - subtype == IEEE80211_FC0_SUBTYPE_AUTH) { - /* Authentication frame */ - auth_seq_index = IEEE80211_FRAME_BODY_OFFSET + 2; - seq = le16toh(*(u_int16_t *)(buf + auth_seq_index)); - } else if (type == IEEE80211_FC0_TYPE_MGT && - subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) - /* Probe response frame */ - fixed_param_length = 12; - else if (type == IEEE80211_FC0_TYPE_MGT && - (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_RESP || - subtype == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)) - /* Assoc/Reassoc response frame */ - fixed_param_length = 6; - else if (type == IEEE80211_FC0_TYPE_MGT && - subtype == IEEE80211_FC0_SUBTYPE_ACTION) { - /* Action frame */ - frm = buf + IEEE80211_FRAME_BODY_OFFSET; - - is_action_frm = true; - if (iot_sim_get_index_for_action_frm(frm, &cat, &cat_index)) { - iot_sim_err("get_index_for_action_frm failed"); - return QDF_STATUS_SUCCESS; - } - } - - subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; - iot_sim_debug("iot_sim: Change content operation for frame"); - iot_sim_debug("type:%d subtype:%d seq:%d, is_action_frm: %u", - type, subtype, seq, is_action_frm); - - /* Only broadcast peer is getting handled right now. - * Need to add support for peer based content modification - */ - qdf_spin_lock(&isc->bcast_peer.iot_sim_lock); - if (!isc->bcast_peer.rule_per_seq[seq]) - goto norule; - - buf_len = qdf_nbuf_len(nbuf); - - if (is_action_frm) - piot_sim_rule = isc->bcast_peer.rule_per_seq[seq]-> - rule_per_action_frm[cat][cat_index]; - else - piot_sim_rule = isc->bcast_peer.rule_per_seq[seq]-> - rule_per_type[type][subtype]; - - if (!piot_sim_rule) - goto norule; + int offset = 0; if (!piot_sim_rule->frm_content || !piot_sim_rule->len) - goto norule; + return QDF_STATUS_E_NOSUPPORT; + + buf_len = qdf_nbuf_len(nbuf); + buf = qdf_nbuf_data(nbuf); if (piot_sim_rule->offset == IEEE80211_FRAME_BODY_OFFSET) { @@ -122,8 +75,133 @@ QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf) } else { iot_sim_err("Failed to modify content"); } - qdf_spin_unlock(&isc->bcast_peer.iot_sim_lock); + return QDF_STATUS_SUCCESS; +} + +/* + * iot_sim_apply_drop_rule - function to apply drop rule. If set buffer will be + * freed here and proper return value will be sent to + * tgt layer. + * + * @piot_sim_rule: iot_sim rule structure + * @nbuf: skb coming from upper stack + * + * Return: QDF_STATUS_SUCCESS on successful drop + * QDF_STATUS_E_NULL_VALUE, when drop rule is applied + */ +QDF_STATUS +iot_sim_apply_drop_rule(struct iot_sim_rule *piot_sim_rule, + qdf_nbuf_t nbuf) +{ + if (!piot_sim_rule->drop) + return QDF_STATUS_E_NOSUPPORT; + + if (nbuf) + qdf_nbuf_free(nbuf); + + iot_sim_debug("iot_sim: Drop rule applied"); + return QDF_STATUS_SUCCESS; +} + +/* + * iot_sim_frame_update - Function to parse input packet coming from upper + * stack in Tx direction and to tgt layer in Rx + * direction. This function will also check if rule + * for that frame type/subtype is set or not and call + * specific operation functions. + * + * @pdev: pdev object + * @nbuf: input packet + * @direction: direction to specify from where this packet is arrived + * + * Return: QDF_STATUS_SUCCESS in general + * QDF_STATUS_E_NOSUPPORT, no content change rule found for this frame + */ +QDF_STATUS iot_sim_frame_update(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t nbuf, + bool tx) +{ + uint8_t type, subtype, seq = 0; + struct iot_sim_context *isc; + uint8_t *buf = qdf_nbuf_data(nbuf), *frm = NULL; + int fixed_param_length = 0; + bool is_action_frm = false; + uint8_t cat, cat_index; + int auth_seq_index = 0; + struct iot_sim_rule *piot_sim_rule = NULL; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + isc = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_IOT_SIM_COMP); + if (!isc) { + iot_sim_err("pdev IOT_SIM object is NULL!"); + return QDF_STATUS_SUCCESS; + } + + type = (buf[0] & IEEE80211_FC0_TYPE_MASK) >> IEEE80211_FC0_TYPE_SHIFT; + subtype = (buf[0] & IEEE80211_FC0_SUBTYPE_MASK); + + if (type == IEEE80211_FC0_TYPE_MGT && + subtype == IEEE80211_FC0_SUBTYPE_AUTH) { + /* Authentication frame */ + auth_seq_index = IEEE80211_FRAME_BODY_OFFSET + 2; + seq = le16toh(*(u_int16_t *)(buf + auth_seq_index)); + } else if (type == IEEE80211_FC0_TYPE_MGT && + subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP) + /* Probe response frame */ + fixed_param_length = 12; + else if (type == IEEE80211_FC0_TYPE_MGT && + (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_RESP || + subtype == IEEE80211_FC0_SUBTYPE_REASSOC_RESP)) + /* Assoc/Reassoc response frame */ + fixed_param_length = 6; + else if (type == IEEE80211_FC0_TYPE_MGT && + subtype == IEEE80211_FC0_SUBTYPE_ACTION) { + /* Action frame */ + frm = buf + IEEE80211_FRAME_BODY_OFFSET; + + is_action_frm = true; + if (iot_sim_get_index_for_action_frm(frm, &cat, &cat_index)) { + iot_sim_err("get_index_for_action_frm failed"); + return QDF_STATUS_SUCCESS; + } + } + + subtype >>= IEEE80211_FC0_SUBTYPE_SHIFT; + iot_sim_debug("iot_sim: type:%d subtype:%d seq:%d, action:%u dir:%s", + type, subtype, seq, is_action_frm, + tx ? "TX" : "RX"); + + /* Only broadcast peer is getting handled right now. + * Need to add support for peer based content modification + */ + qdf_spin_lock(&isc->bcast_peer.iot_sim_lock); + if (!isc->bcast_peer.rule_per_seq[seq]) + goto norule; + + if (is_action_frm) + piot_sim_rule = isc->bcast_peer.rule_per_seq[seq]-> + rule_per_action_frm[cat][cat_index]; + else + piot_sim_rule = isc->bcast_peer.rule_per_seq[seq]-> + rule_per_type[type][subtype]; + + if (!piot_sim_rule) + goto norule; + + if (tx) { + status = iot_sim_apply_content_change_rule(piot_sim_rule, + nbuf, + fixed_param_length); + if (status == QDF_STATUS_E_NOSUPPORT) + goto norule; + } else { + status = iot_sim_apply_drop_rule(piot_sim_rule, nbuf); + if (QDF_IS_STATUS_SUCCESS(status)) + status = QDF_STATUS_E_NULL_VALUE; + } + + qdf_spin_unlock(&isc->bcast_peer.iot_sim_lock); + return status; norule: iot_sim_debug("Rule not set for this frame"); diff --git a/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h b/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h index 308ad5db90..8d90cea52c 100644 --- a/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h +++ b/iot_sim/dispatcher/inc/wlan_iot_sim_utils_api.h @@ -28,10 +28,12 @@ struct wmi_iot_sim_cmd_ops; * iot_sim_cmd_handler() - IOT SIM frame handler function * @vdev - vdev object. * @buf - skb + * @tx - TRUE in case of Tx * * Return : QDF_STATUS_E_SUCCESS/QDF_STATUS_E_FAILURE. */ -QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t buf); +QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t buf, + bool tx); /** * wlan_iot_sim_init() - API to init iot_sim component 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 d846638811..7de5d8b71a 100644 --- a/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c +++ b/iot_sim/dispatcher/src/wlan_iot_sim_utils_api.c @@ -23,11 +23,12 @@ #define IEEE80211_FRAME_BODY_OFFSET 0x18 -QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t nbuf) +QDF_STATUS iot_sim_cmd_handler(struct wlan_objmgr_vdev *vdev, qdf_nbuf_t nbuf, + bool tx) { struct wlan_objmgr_pdev *pdev = vdev->vdev_objmgr.wlan_pdev; - return iot_sim_frame_update(pdev, nbuf); + return iot_sim_frame_update(pdev, nbuf, tx); } QDF_STATUS diff --git a/qdf/inc/qdf_str.h b/qdf/inc/qdf_str.h index 5c04baa5bd..f778cf19b9 100644 --- a/qdf/inc/qdf_str.h +++ b/qdf/inc/qdf_str.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -170,4 +170,16 @@ qdf_str_ncmp(const char *str1, const char *str2, qdf_size_t limit) return __qdf_str_ncmp(str1, str2, limit); } +/** + * qdf_str_sep - extract token from string + * @str: String buffer + * @delim: Delimitter + * Return: Pointer to the first token + * + */ +static inline char *qdf_str_sep(char **str, char *delim) +{ + return __qdf_str_sep(str, delim); +} + #endif /* __QDF_STR_H */ diff --git a/qdf/linux/src/i_qdf_str.h b/qdf/linux/src/i_qdf_str.h index 53378e12ba..5dc2469651 100644 --- a/qdf/linux/src/i_qdf_str.h +++ b/qdf/linux/src/i_qdf_str.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -34,5 +34,6 @@ #define __qdf_str_trim(str) strim(str) #define __qdf_str_nlen(str, limit) strnlen(str, limit) #define __qdf_str_ncmp(left, right, limit) strncmp(left, right, limit) +#define __qdf_str_sep(buf, delim) strsep(buf, delim) #endif /* __I_QDF_STR_H */ diff --git a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c index ff4cd9b5ca..f035fa4f07 100644 --- a/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c +++ b/umac/cmn_services/mgmt_txrx/core/src/wlan_mgmt_txrx_main.c @@ -191,7 +191,9 @@ QDF_STATUS iot_sim_mgmt_tx_update(struct wlan_objmgr_psoc *psoc, return QDF_STATUS_E_NULL_VALUE; } if (rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler) { - status = rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler(vdev, buf); + status = rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler(vdev, + buf, + true); if (QDF_IS_STATUS_ERROR(status)) mgmt_txrx_err("iot_sim_cmd_handler returned failure"); } diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c index 83b664b261..482de6888b 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c @@ -908,6 +908,63 @@ mgmt_txrx_get_frm_type(uint8_t mgmt_subtype, uint8_t *mpdu_data_ptr) return frm_type; } +#ifdef WLAN_IOT_SIM_SUPPORT +static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc, + qdf_nbuf_t buf, + struct mgmt_rx_event_params *rx_param) +{ + uint8_t *addr = NULL; + struct wlan_objmgr_vdev *vdev = NULL; + uint8_t pdevid = 0; + wlan_objmgr_ref_dbgid dbgid; + struct wlan_lmac_if_rx_ops *rx_ops = NULL; + struct wlan_objmgr_pdev *pdev; + struct ieee80211_frame *wh; + u_int8_t *data; + QDF_STATUS status = QDF_STATUS_SUCCESS; + + rx_ops = wlan_psoc_get_lmac_if_rxops(psoc); + if (rx_ops && rx_ops->iot_sim_rx_ops.iot_sim_cmd_handler) { + data = (uint8_t *)qdf_nbuf_data(buf); + wh = (struct ieee80211_frame *)data; + addr = (uint8_t *)wh->i_addr3; + pdevid = rx_param->pdev_id; + dbgid = WLAN_IOT_SIM_ID; + if (qdf_is_macaddr_broadcast((struct qdf_mac_addr *)addr)) { + pdev = wlan_objmgr_get_pdev_by_id(psoc, pdevid, + dbgid); + if (pdev) { + vdev = wlan_objmgr_pdev_get_first_vdev(pdev, + dbgid); + wlan_objmgr_pdev_release_ref(pdev, dbgid); + } + } else + vdev = wlan_objmgr_get_vdev_by_macaddr_from_psoc(psoc, + pdevid, + addr, + dbgid); + if (vdev) { + status = rx_ops->iot_sim_rx_ops. + iot_sim_cmd_handler(vdev, buf, false); + if (status == QDF_STATUS_E_NULL_VALUE) { + wlan_objmgr_vdev_release_ref(vdev, dbgid); + mgmt_txrx_debug("iot_sim:Pkt processed at RX"); + return status; + } + wlan_objmgr_vdev_release_ref(vdev, dbgid); + } + } + return status; +} +#else +static QDF_STATUS simulation_frame_update(struct wlan_objmgr_psoc *psoc, + qdf_nbuf_t buf, + struct mgmt_rx_event_params *rx_param) +{ + return QDF_STATUS_SUCCESS; +} +#endif + /** * wlan_mgmt_txrx_rx_handler_list_copy() - copies rx handler list * @rx_handler: pointer to rx handler list @@ -1084,6 +1141,9 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( WLAN_SEQ_SEQ_SHIFT), mgmt_rx_params->rssi, mgmt_rx_params->tsf_delta); + if (simulation_frame_update(psoc, buf, mgmt_rx_params)) + return QDF_STATUS_E_FAILURE; + mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *) wlan_objmgr_psoc_get_comp_private_obj(psoc, WLAN_UMAC_COMP_MGMT_TXRX); diff --git a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h index 4c61469765..b75fe62652 100644 --- a/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h +++ b/umac/cmn_services/obj_mgr/inc/wlan_objmgr_cmn.h @@ -267,6 +267,7 @@ typedef void (*wlan_objmgr_peer_status_handler)( * @FTM_TIME_SYNC_ID: ftm time sync operations * @WLAN_PKT_CAPTURE_ID Packet capture operations * @WLAN_DCS_ID: DCS operations + * @WLAN_IOT_SIM_ID: IOT Simulation feature * @WLAN_REF_ID_MAX: Max id used to generate ref count tracking array */ /* New value added to the enum must also be reflected in function @@ -349,6 +350,7 @@ typedef enum { FTM_TIME_SYNC_ID = 73, WLAN_PKT_CAPTURE_ID = 74, WLAN_DCS_ID = 75, + WLAN_IOT_SIM_ID = 76, WLAN_REF_ID_MAX, } wlan_objmgr_ref_dbgid; @@ -437,7 +439,8 @@ static inline const char *string_from_dbgid(wlan_objmgr_ref_dbgid id) "WLAN_PSOC_TARGET_IF_ID", "FTM_TIME_SYNC_ID", "WLAN_PKT_CAPTURE_ID", - "WLAN_DCS_ID"}; + "WLAN_DCS_ID", + "WLAN_IOT_SIM_ID"}; if (id >= WLAN_REF_ID_MAX) return "Unknown"; diff --git a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h index e03a004999..260fae0b3e 100644 --- a/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h +++ b/umac/global_umac_dispatcher/lmac_if/inc/wlan_lmac_if_def.h @@ -1424,7 +1424,7 @@ struct wlan_lmac_if_sptrl_rx_ops { **/ struct wlan_lmac_if_iot_sim_rx_ops { QDF_STATUS (*iot_sim_cmd_handler)(struct wlan_objmgr_vdev *vdev, - qdf_nbuf_t n_buf); + qdf_nbuf_t n_buf, bool tx); }; #endif