qcacmn: Add debugfs support for iot_sim module

Following changes were done:
1. Adding debugfs functionality for iot_sim module
2. Changing the iot_sim context from psoc to pdev
3. Currently iot_sim support only bcast peer
4. Adding write handler to store user configured rules.

Change-Id: I4319bae3986874434f2a2e2397b1a8698c48d936
CRs-Fixed: 2657929
This commit is contained in:
nakul kachhwaha
2020-03-27 13:11:35 +05:30
committed by nshrivas
parent 861af9fad3
commit d20fe7aad4
5 changed files with 944 additions and 75 deletions

View File

@@ -18,35 +18,50 @@
#define _IOT_SIM_CMN_API_I_H_ #define _IOT_SIM_CMN_API_I_H_
#include "iot_sim_defs_i.h" #include "iot_sim_defs_i.h"
#include <qdf_net_types.h>
#define MAX_BUFFER_SIZE 2048
/* /*
* wlan_iot_sim_psoc_obj_create_handler() - handler for psoc object create * IOT SIM User Buf Format
* @psoc: reference to global psoc object *
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* | 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 * @arg: reference to argument provided during registration of handler
* *
* This is a handler to indicate psoc object created. Hence iot_sim_context * This is a handler to indicate pdev object created. Hence iot_sim_context
* object can be created and attached to psoc component list. * object can be created and attached to pdev component list.
* *
* Return: QDF_STATUS_SUCCESS on success * 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_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); void *arg);
/* /**
* wlan_iot_sim_psoc_obj_destroy_handler() - handler for psoc object delete * wlan_iot_sim_pdev_obj_destroy_handler() - handler for pdev object delete
* @psoc: reference to global psoc object * @pdev: reference to global pdev object
* @arg: reference to argument provided during registration of handler * @arg: reference to argument provided during registration of handler
* *
* This is a handler to indicate psoc object going to be deleted. * This is a handler to indicate pdev object going to be deleted.
* Hence iot_sim_context object can be detached from psoc component list. * Hence iot_sim_context object can be detached from pdev component list.
* Then iot_sim_context object can be deleted. * Then iot_sim_context object can be deleted.
* *
* Return: QDF_STATUS_SUCCESS on success * Return: QDF_STATUS_SUCCESS on success
* QDF_STATUS_E_FAILURE on failure * 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); 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 * 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; struct iot_sim_context *isc = NULL;
if (psoc) { if (pdev) {
isc = wlan_objmgr_psoc_get_comp_private_obj(psoc, isc = wlan_objmgr_pdev_get_comp_private_obj(pdev,
WLAN_IOT_SIM_COMP); WLAN_IOT_SIM_COMP);
} }
return isc; 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_ */ #endif /* _IOT_SIM_CMN_API_I_H_ */

View File

@@ -15,21 +15,680 @@
*/ */
#include "iot_sim_cmn_api_i.h" #include "iot_sim_cmn_api_i.h"
#include "iot_sim_defs_i.h"
#include <qdf_mem.h> #include <qdf_mem.h>
#include <qdf_types.h> #include <qdf_types.h>
#include <qdf_util.h>
/*
* 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
* <t_st> <seq> <offset> <length> <content> <MAC>
* 2. Add rule for broadcast peer
* <t_st> <seq> <offset> <length> <content>
* 3. Remove rule for specific peer
* <t_st> <seq> <offset> <length> <MAC>
* 4. Remove rule for broadcast peer
* <t_st> <seq> <offset> <length>
*/
/*
* 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 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; QDF_STATUS status = QDF_STATUS_E_FAILURE;
struct iot_sim_context *isc; struct iot_sim_context *isc;
if (!psoc) { if (!pdev) {
iot_sim_err("PDEV is NULL!"); iot_sim_err("PDEV is NULL!");
goto bad; goto bad;
} }
isc = iot_sim_get_ctx_from_psoc(psoc); isc = iot_sim_get_ctx_from_pdev(pdev);
if (!isc) { if (!isc) {
iot_sim_err("iot_sim context is NULL!"); iot_sim_err("iot_sim context is NULL!");
goto bad; goto bad;
@@ -53,52 +712,180 @@ iot_sim_ctx_deinit(struct iot_sim_context *isc)
isc->iot_sim_operation_handler = NULL; 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; debugfs_remove_recursive(isc->iot_sim_dbgfs_ctx.iot_sim_dir_de);
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");
return QDF_STATUS_SUCCESS; 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 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) void *arg)
{ {
struct iot_sim_context *isc = NULL; struct iot_sim_context *isc = NULL;
if (!psoc) { if (!pdev) {
iot_sim_err("PSOC is NULL"); iot_sim_err("pdev is NULL");
return QDF_STATUS_E_NULL_VALUE; 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); WLAN_IOT_SIM_COMP);
if (isc) { if (isc) {
wlan_objmgr_psoc_component_obj_detach(psoc, wlan_objmgr_pdev_component_obj_detach(pdev,
WLAN_IOT_SIM_COMP, WLAN_IOT_SIM_COMP,
(void *)isc); (void *)isc);
/* Deinitilise function pointers from iot_sim context */ /* Deinitilise function pointers from iot_sim context */
iot_sim_ctx_deinit(isc); 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); 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; return QDF_STATUS_SUCCESS;
} }

View File

@@ -19,7 +19,7 @@
#include <wlan_objmgr_cmn.h> #include <wlan_objmgr_cmn.h>
#include <wlan_objmgr_global_obj.h> #include <wlan_objmgr_global_obj.h>
#include <wlan_objmgr_psoc_obj.h> #include <wlan_objmgr_pdev_obj.h>
#include <qdf_list.h> #include <qdf_list.h>
#include <qdf_util.h> #include <qdf_util.h>
#include <qdf_types.h> #include <qdf_types.h>
@@ -74,46 +74,95 @@
#define N_FRAME_TYPE 0x4 #define N_FRAME_TYPE 0x4
#define N_FRAME_SUBTYPE 0xF #define N_FRAME_SUBTYPE 0xF
#define MAX_SEQ 0x4 #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 * @len - Length of the content provided by user
* @offset - offset at which modification done in capture frame * @offset - offset at which modification done in capture frame
* @frm_content - actual user data in hex * @frm_content - actual user data in hex
* @drop - frame marked for drop * @drop - frame marked for drop
* @delay_dur - duration of delay * @delay_dur - duration of delay
*/ */
struct iot_sim_content { struct iot_sim_rule {
uint16_t len; uint16_t len;
uint16_t offset; uint16_t offset;
uint8_t *frm_content; uint8_t *frm_content;
bool drop; bool drop;
uint16_t delay_dur; uint16_t delay_dur;
uint8_t rule_bitmap;
}; };
/* Per Peer iot_sim data per frame type/subtype */ /*
struct iot_sim_fb_array_peer { * struct iot_sim_rule_per_seq - rule structure per sequence iot sim files
struct qdf_mac_addr peer_addr; * and directory
struct iot_sim_content iot_sim_fb_array[N_FRAME_TYPE][N_FRAME_SUBTYPE]; *
* @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; qdf_list_t p_list;
}; };
/** /**
* struct iot_sim_context - iot_sim psoc private object * struct iot_sim_context - iot_sim pdev private object
* @psoc_obj:Reference to psoc global object * @pdev_obj:Reference to pdev global object
* @iot_sim_lock: spinlock for synchronization * @iot_sim_peer_list: peer list for peer specific rules
* * @bcast_peer: broadcast peer entry for storing rules for all peers
* Call back functions * @p_iot_sim_target_handle: handle to iot_sim target_if
* @iot_sim_opertion_handler: iot sim operations handler * @iot_sim_operation_handler: callback for iot sim operation handler
*/ */
struct iot_sim_context { struct iot_sim_context {
struct wlan_objmgr_psoc *psoc_obj; struct wlan_objmgr_pdev *pdev_obj;
qdf_spinlock_t iot_sim_lock; /* IOT_SIM Peer list & Bcast Peer */
/* IOT_SIM Peer list */ struct iot_sim_rule_per_peer *iot_sim_peer_list, bcast_peer;
struct iot_sim_fb_arrary_peer *iot_sim_peer_list;
void *p_iot_sim_target_handle; 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); 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_ */ #endif /* _IOT_SIM_DEFS_I_H_ */

View File

@@ -18,18 +18,18 @@
#include <wlan_iot_sim_utils_api.h> #include <wlan_iot_sim_utils_api.h>
void * void *
tgt_get_target_handle(struct wlan_objmgr_psoc *psoc) tgt_get_target_handle(struct wlan_objmgr_pdev *pdev)
{ {
struct iot_sim_context *isc; struct iot_sim_context *isc;
if (!psoc) { if (!pdev) {
iot_sim_err("psoc is NULL!"); iot_sim_err("pdev is NULL!");
return 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); WLAN_IOT_SIM_COMP);
if (!isc) { if (!isc) {
iot_sim_err("psoc IOT_SIM object is NULL!"); iot_sim_err("pdev IOT_SIM object is NULL!");
return NULL; return NULL;
} }
return isc->p_iot_sim_target_handle; return isc->p_iot_sim_target_handle;

View File

@@ -22,16 +22,16 @@
QDF_STATUS QDF_STATUS
wlan_iot_sim_init(void) 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_COMP,
wlan_iot_sim_psoc_obj_create_handler, wlan_iot_sim_pdev_obj_create_handler,
NULL) != NULL) !=
QDF_STATUS_SUCCESS) { QDF_STATUS_SUCCESS) {
return QDF_STATUS_E_FAILURE; 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_COMP,
wlan_iot_sim_psoc_obj_destroy_handler, wlan_iot_sim_pdev_obj_destroy_handler,
NULL) != NULL) !=
QDF_STATUS_SUCCESS) { QDF_STATUS_SUCCESS) {
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
@@ -43,16 +43,16 @@ wlan_iot_sim_init(void)
QDF_STATUS QDF_STATUS
wlan_iot_sim_deinit(void) 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_COMP,
wlan_iot_sim_psoc_obj_create_handler, wlan_iot_sim_pdev_obj_create_handler,
NULL) != NULL) !=
QDF_STATUS_SUCCESS) { QDF_STATUS_SUCCESS) {
return QDF_STATUS_E_FAILURE; 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_COMP,
wlan_iot_sim_psoc_obj_destroy_handler, wlan_iot_sim_pdev_obj_destroy_handler,
NULL) != NULL) !=
QDF_STATUS_SUCCESS) { QDF_STATUS_SUCCESS) {
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;