diff options
| author | Hanumanth Reddy Pothula <c_hpothu@codeaurora.org> | 2017-02-07 01:48:53 +0530 |
|---|---|---|
| committer | Rajeev Kumar Sirasanagandla <rsirasan@codeaurora.org> | 2017-03-27 12:23:23 +0530 |
| commit | ff04da4130e5998afecdacb1013bfafa08961776 (patch) | |
| tree | 0c0adebb86fb0af67ed1fc2474aae2c62868c1a3 | |
| parent | bb535a3b325687d493f2862be83f26267d0b88dd (diff) | |
qcacld-3.0: Randomize sa of action frames
qcacld-2.0 to qcacld-3.0 propagation
This change add support to randomize source address of action frames
for improving user privacy.
Change-Id: I5a5b245677d968983705692a5e510bef121e089f
CRs-Fixed: 1102831
| -rw-r--r-- | core/hdd/inc/wlan_hdd_main.h | 65 | ||||
| -rw-r--r-- | core/hdd/inc/wlan_hdd_p2p.h | 15 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.c | 24 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_main.c | 36 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_p2p.c | 567 | ||||
| -rw-r--r-- | core/mac/inc/sir_api.h | 30 | ||||
| -rw-r--r-- | core/mac/src/include/sir_params.h | 2 | ||||
| -rw-r--r-- | core/mac/src/sys/legacy/src/utils/src/mac_trace.c | 1 | ||||
| -rw-r--r-- | core/sme/inc/sme_api.h | 35 | ||||
| -rw-r--r-- | core/sme/src/common/sme_api.c | 94 | ||||
| -rw-r--r-- | core/wma/inc/wma.h | 1 | ||||
| -rw-r--r-- | core/wma/inc/wma_types.h | 2 | ||||
| -rw-r--r-- | core/wma/src/wma_dev_if.c | 8 | ||||
| -rw-r--r-- | core/wma/src/wma_main.c | 156 |
14 files changed, 1035 insertions, 1 deletions
diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index ef425ddb5248..a7b7d66af0a7 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -157,6 +157,8 @@ /* Maximum time(ms) to wait for RSO CMD status event */ #define WAIT_TIME_RSO_CMD_STATUS 2000 +#define WLAN_WAIT_TIME_SET_RND 100 + #define MAX_NUMBER_OF_ADAPTERS 4 #define MAX_CFG_STRING_LEN 255 @@ -295,6 +297,12 @@ typedef enum { #define MAX_PROBE_REQ_OUIS 16 /* + * Maximum no.of random mac addresses supported by firmware + * for transmitting management action frames + */ +#define MAX_RANDOM_MAC_ADDRS 4 + +/* * Generic asynchronous request/response support * * Many of the APIs supported by HDD require a call to SME to @@ -338,6 +346,20 @@ struct linkspeedContext { unsigned int magic; }; +/** + * struct random_mac_context - Context used with hdd_random_mac_callback + * @random_mac_completion: Event on which hdd_set_random_mac will wait + * @adapter: Pointer to adapter + * @magic: For valid context this is set to ACTION_FRAME_RANDOM_CONTEXT_MAGIC + * @set_random_addr: Status of random filter set + */ +struct random_mac_context { + struct completion random_mac_completion; + hdd_adapter_t *adapter; + unsigned int magic; + bool set_random_addr; +}; + extern spinlock_t hdd_context_lock; #define STATS_CONTEXT_MAGIC 0x53544154 /* STAT */ @@ -350,6 +372,7 @@ extern spinlock_t hdd_context_lock; #define BPF_CONTEXT_MAGIC 0x4575354 /* BPF */ #define POWER_STATS_MAGIC 0x14111990 #define RCPI_CONTEXT_MAGIC 0x7778888 /* RCPI */ +#define ACTION_FRAME_RANDOM_CONTEXT_MAGIC 0x87878787 /* MAX OS Q block time value in msec * Prevent from permanent stall, resume OS Q if timer expired */ @@ -687,6 +710,31 @@ struct hdd_mon_set_ch_info { eCsrPhyMode phy_mode; }; +/** + * struct action_frame_cookie - Action frame cookie item in cookie list + * @cookie_node: List item + * @cookie: Cookie value + */ +struct action_frame_cookie { + struct list_head cookie_node; + uint64_t cookie; +}; + +/** + * struct action_frame_random_mac - Action Frame random mac addr & + * related attrs + * @in_use: Checks whether random mac is in use + * @addr: Contains random mac addr + * @freq: Channel frequency + * @cookie_list: List of cookies tied with random mac + */ +struct action_frame_random_mac { + bool in_use; + uint8_t addr[QDF_MAC_ADDR_SIZE]; + uint32_t freq; + struct list_head cookie_list; +}; + struct hdd_station_ctx { /** Handle to the Wireless Extension State */ hdd_wext_state_t WextState; @@ -1212,6 +1260,9 @@ struct hdd_adapter_s { struct lfr_firmware_status lfr_fw_status; bool con_status; bool dad; + /* random address management for management action frames */ + spinlock_t random_mac_lock; + struct action_frame_random_mac random_mac[MAX_RANDOM_MAC_ADDRS]; }; /* @@ -1742,6 +1793,20 @@ hdd_adapter_t *hdd_get_adapter_by_vdev(hdd_context_t *pHddCtx, uint32_t vdev_id); hdd_adapter_t *hdd_get_adapter_by_macaddr(hdd_context_t *pHddCtx, tSirMacAddr macAddr); +/** + * hdd_get_adapter_by_rand_macaddr() - Get adapter using random DA of MA frms + * @hdd_ctx: Pointer to hdd context + * @mac_addr: random mac address + * + * This function is used to get adapter from randomized destination mac + * address present in management action frames + * + * Return: If randomized addr is present then return pointer to adapter + * else NULL + */ +hdd_adapter_t *hdd_get_adapter_by_rand_macaddr(hdd_context_t *hdd_ctx, + tSirMacAddr mac_addr); + QDF_STATUS hdd_init_station_mode(hdd_adapter_t *pAdapter); hdd_adapter_t *hdd_get_adapter(hdd_context_t *pHddCtx, enum tQDF_ADAPTER_MODE mode); diff --git a/core/hdd/inc/wlan_hdd_p2p.h b/core/hdd/inc/wlan_hdd_p2p.h index dca03994011e..4164a10d81bc 100644 --- a/core/hdd/inc/wlan_hdd_p2p.h +++ b/core/hdd/inc/wlan_hdd_p2p.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. * @@ -49,6 +49,7 @@ #define WLAN_HDD_GET_TYPE_FRM_FC(__fc__) (((__fc__) & 0x0F) >> 2) #define WLAN_HDD_GET_SUBTYPE_FRM_FC(__fc__) (((__fc__) & 0xF0) >> 4) #define WLAN_HDD_80211_FRM_DA_OFFSET 4 +#define WLAN_HDD_80211_FRM_SA_OFFSET 10 #define P2P_WILDCARD_SSID_LEN 7 #define P2P_WILDCARD_SSID "DIRECT-" #define WLAN_HDD_80211_PEER_ADDR_OFFSET (WLAN_HDD_80211_FRM_DA_OFFSET + \ @@ -159,4 +160,16 @@ int __wlan_hdd_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter); void wlan_hdd_roc_request_dequeue(struct work_struct *work); + +/** + * hdd_check_random_mac() - Whether addr is present in random_mac array + * @adapter: Pointer to adapter + * @mac_addr: random mac address + * + * This function is used to check whether given mac addr is present in list of + * random_mac structures in specified adapter + * + * Return: If random addr is present return true else false + */ +bool hdd_check_random_mac(hdd_adapter_t *adapter, uint8_t *random_mac_addr); #endif /* __P2P_H */ diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 268694f60dcf..1a7fbdff829a 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -10185,6 +10185,29 @@ static void wlan_hdd_cfg80211_scan_randomization_init(struct wiphy *wiphy) */ #define WLAN_HDD_MAX_NUM_CSA_COUNTERS 2 +#ifdef CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME +/** + * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA + * frames + * @wiphy: Pointer to wiphy + * + * This function is used to indicate the support of source mac address + * randomization of management action frames + * + * Return: None + */ +static void +wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy) +{ + wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MGMT_TX_RANDOM_TA); +} +#else +static void +wlan_hdd_cfg80211_action_frame_randomization_init(struct wiphy *wiphy) +{ +} +#endif + /* * FUNCTION: wlan_hdd_cfg80211_init * This function is called by hdd_wlan_startup() @@ -10420,6 +10443,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, hdd_add_channel_switch_support(&wiphy->flags); wiphy->max_num_csa_counters = WLAN_HDD_MAX_NUM_CSA_COUNTERS; wlan_hdd_cfg80211_scan_randomization_init(wiphy); + wlan_hdd_cfg80211_action_frame_randomization_init(wiphy); EXIT(); return 0; diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index 0d4e5c27c8e7..34e805c40421 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -2513,6 +2513,20 @@ static void hdd_runtime_suspend_context_deinit(hdd_context_t *hdd_ctx) {} static inline void hdd_adapter_runtime_suspend_init(hdd_adapter_t *adapter) {} static inline void hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) {} #endif /* FEATURE_RUNTIME_PM */ + +/** + * hdd_adapter_init_action_frame_random_mac() - Initialze attributes needed for + * randomization of SA in management action frames + * @adapter: Pointer to adapter + * + * Return: None + */ +static void hdd_adapter_init_action_frame_random_mac(hdd_adapter_t *adapter) +{ + spin_lock_init(&adapter->random_mac_lock); + qdf_mem_zero(adapter->random_mac, sizeof(adapter->random_mac)); +} + /** * hdd_alloc_station_adapter() - allocate the station hdd adapter * @hdd_ctx: global hdd context @@ -3333,6 +3347,9 @@ hdd_adapter_t *hdd_open_adapter(hdd_context_t *hdd_ctx, uint8_t session_type, goto err_free_netdev; } + /* initialize action frame random mac info */ + hdd_adapter_init_action_frame_random_mac(adapter); + /* * Workqueue which gets scheduled in IPv4 notification * callback @@ -10735,6 +10752,25 @@ bool hdd_is_roaming_in_progress(hdd_adapter_t *adapter) return ret_status; } +hdd_adapter_t *hdd_get_adapter_by_rand_macaddr(hdd_context_t *hdd_ctx, + tSirMacAddr mac_addr) +{ + hdd_adapter_list_node_t *adapter_node = NULL, *next = NULL; + hdd_adapter_t *adapter; + QDF_STATUS status; + + status = hdd_get_front_adapter(hdd_ctx, &adapter_node); + while (adapter_node && status == QDF_STATUS_SUCCESS) { + adapter = adapter_node->pAdapter; + if (adapter && hdd_check_random_mac(adapter, mac_addr)) + return adapter; + status = hdd_get_next_adapter(hdd_ctx, adapter_node, &next); + adapter_node = next; + } + + return NULL; +} + /* Register the module init/exit functions */ module_init(hdd_module_init); module_exit(hdd_module_exit); diff --git a/core/hdd/src/wlan_hdd_p2p.c b/core/hdd/src/wlan_hdd_p2p.c index d0c36e3b0dfa..483c25c3647f 100644 --- a/core/hdd/src/wlan_hdd_p2p.c +++ b/core/hdd/src/wlan_hdd_p2p.c @@ -161,6 +161,514 @@ static bool hdd_p2p_is_action_type_rsp(const u8 *buf) return false; } +/** + * hdd_random_mac_callback() - Callback invoked from wmi layer + * @set_random_addr: Status of random mac filter set operation + * @context: Context passed while registring callback + * + * This function is invoked from wmi layer to give the status of + * random mac filter set operation by firmware. + * + * Return: None + */ +static void hdd_random_mac_callback(bool set_random_addr, void *context) +{ + struct random_mac_context *rnd_ctx; + hdd_adapter_t *adapter; + + if (!context) { + hdd_err("Bad param, pContext"); + return; + } + + rnd_ctx = context; + adapter = rnd_ctx->adapter; + + spin_lock(&hdd_context_lock); + if ((!adapter) || + (rnd_ctx->magic != ACTION_FRAME_RANDOM_CONTEXT_MAGIC)) { + spin_unlock(&hdd_context_lock); + hdd_err("Invalid context, magic [%08x]", rnd_ctx->magic); + return; + } + + rnd_ctx->magic = 0; + if (set_random_addr) + rnd_ctx->set_random_addr = true; + + complete(&rnd_ctx->random_mac_completion); + spin_unlock(&hdd_context_lock); +} + +/** + * hdd_set_random_mac() - Invoke sme api to set random mac filter + * @adapter: Pointer to adapter + * @random_mac_addr: Mac addr filter to be set + * @freq: Channel frequency + * + * Return: If set is successful return true else return false + */ +static bool hdd_set_random_mac(hdd_adapter_t *adapter, + uint8_t *random_mac_addr, + uint32_t freq) +{ + struct random_mac_context context; + hdd_context_t *hdd_ctx; + QDF_STATUS sme_status; + unsigned long rc; + bool status = false; + + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (wlan_hdd_validate_context(hdd_ctx)) { + hdd_err("Invalid hdd ctx"); + return false; + } + + init_completion(&context.random_mac_completion); + context.adapter = adapter; + context.magic = ACTION_FRAME_RANDOM_CONTEXT_MAGIC; + context.set_random_addr = false; + + sme_status = sme_set_random_mac(hdd_ctx->hHal, hdd_random_mac_callback, + adapter->sessionId, random_mac_addr, freq, + &context); + + if (sme_status != QDF_STATUS_SUCCESS) { + hdd_err("Unable to set random mac"); + } else { + rc = wait_for_completion_timeout(&context.random_mac_completion, + msecs_to_jiffies(WLAN_WAIT_TIME_SET_RND)); + if (!rc) + hdd_err("SME timed out while setting random mac"); + } + + spin_lock(&hdd_context_lock); + context.magic = 0; + status = context.set_random_addr; + spin_unlock(&hdd_context_lock); + + EXIT(); + return status; +} + +/** + * hdd_clear_random_mac() - Invoke sme api to clear random mac filter + * @adapter: Pointer to adapter + * @random_mac_addr: Mac addr filter to be cleared + * @freq: Channel frequency + * + * Return: If clear is successful return true else return false + */ +static bool hdd_clear_random_mac(hdd_adapter_t *adapter, + uint8_t *random_mac_addr, + uint32_t freq) +{ + hdd_context_t *hdd_ctx; + QDF_STATUS status; + + ENTER(); + hdd_ctx = WLAN_HDD_GET_CTX(adapter); + if (wlan_hdd_validate_context(hdd_ctx)) { + hdd_err("Invalid hdd ctx"); + return false; + } + + status = sme_clear_random_mac(hdd_ctx->hHal, adapter->sessionId, + random_mac_addr, freq); + + if (status != QDF_STATUS_SUCCESS) { + hdd_err("Unable to clear random mac"); + return false; + } + + EXIT(); + return true; +} + +bool hdd_check_random_mac(hdd_adapter_t *adapter, uint8_t *random_mac_addr) +{ + uint32_t i = 0; + + spin_lock(&adapter->random_mac_lock); + for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) { + if ((adapter->random_mac[i].in_use) && + (!qdf_mem_cmp(adapter->random_mac[i].addr, random_mac_addr, + QDF_MAC_ADDR_SIZE))) { + spin_unlock(&adapter->random_mac_lock); + return true; + } + } + spin_unlock(&adapter->random_mac_lock); + return false; +} + +/** + * find_action_frame_cookie() - Checks for action cookie in cookie list + * @cookie_list: List of cookies + * @cookie: Cookie to be searched + * + * Return: If search is successful return pointer to action_frame_cookie + * object in which cookie item is encapsulated. + */ +static struct action_frame_cookie *find_action_frame_cookie( + struct list_head *cookie_list, + uint64_t cookie) +{ + struct action_frame_cookie *action_cookie = NULL; + struct list_head *temp = NULL; + + list_for_each(temp, cookie_list) { + action_cookie = list_entry(temp, struct action_frame_cookie, + cookie_node); + if (action_cookie->cookie == cookie) + return action_cookie; + } + + return NULL; +} + +/** + * allocate_action_frame_cookie() - Allocate and add action cookie to + * given list + * @cookie_list: List of cookies + * @cookie: Cookie to be added + * + * Return: If allocation and addition is successful return pointer to + * action_frame_cookie object in which cookie item is encapsulated. + */ +static struct action_frame_cookie *allocate_action_frame_cookie( + struct list_head *cookie_list, + uint64_t cookie) +{ + struct action_frame_cookie *action_cookie = NULL; + + action_cookie = qdf_mem_malloc(sizeof(*action_cookie)); + if (!action_cookie) + return NULL; + + action_cookie->cookie = cookie; + list_add(&action_cookie->cookie_node, cookie_list); + + return action_cookie; +} + +/** + * delete_action_frame_cookie() - Delete the cookie from given list + * @cookie_list: List of cookies + * @cookie: Cookie to be deleted + * + * This function deletes the cookie item from given list and corresponding + * object in which it is encapsulated. + * + * Return: None + */ +static void delete_action_frame_cookie( + struct action_frame_cookie *action_cookie) +{ + list_del(&action_cookie->cookie_node); + qdf_mem_free(action_cookie); +} + +/** + * append_action_frame_cookie() - Append action cookie to given list + * @cookie_list: List of cookies + * @cookie: Cookie to be append + * + * This is a wrapper function which invokes allocate_action_frame_cookie + * if the cookie to be added is not duplicate + * + * Return: 0 - for successful case + * -EALREADY - if cookie is duplicate + * -ENOMEM - if allocation is failed + */ +static int32_t append_action_frame_cookie(struct list_head *cookie_list, + uint64_t cookie) +{ + struct action_frame_cookie *action_cookie = NULL; + + /* + * There should be no mac entry with empty cookie list, + * check and ignore if duplicate + */ + action_cookie = find_action_frame_cookie(cookie_list, cookie); + if (action_cookie) + /* random mac address is already programmed */ + return -EALREADY; + + /* insert new cookie in cookie list */ + action_cookie = allocate_action_frame_cookie(cookie_list, cookie); + if (!action_cookie) + return -ENOMEM; + + return 0; +} + +/** + * hdd_set_action_frame_random_mac() - Store action frame cookie + * @adapter: Pointer to adapter + * @random_mac_addr: Mac addr for cookie + * @cookie: Cookie to be stored + * @freq: Channel frequency + * + * This function is used to create cookie list and append the cookies + * to same for corresponding random mac addr. If this cookie is the first + * item in the list then random mac filter is set. + * + * Return: 0 - for success else negative value + */ +static int32_t hdd_set_action_frame_random_mac(hdd_adapter_t *adapter, + uint8_t *random_mac_addr, + uint64_t cookie, uint32_t freq) +{ + uint32_t i = 0; + uint32_t in_use_cnt = 0; + struct action_frame_cookie *action_cookie = NULL; + int32_t append_ret = 0; + + if (!cookie) { + hdd_err("Invalid cookie"); + return -EINVAL; + } + + hdd_info("mac_addr: " MAC_ADDRESS_STR " && cookie = %llu && freq = %u", + MAC_ADDR_ARRAY(random_mac_addr), cookie, freq); + + spin_lock(&adapter->random_mac_lock); + for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) { + if (adapter->random_mac[i].in_use) { + in_use_cnt++; + if (!qdf_mem_cmp(adapter->random_mac[i].addr, + random_mac_addr, QDF_MAC_ADDR_SIZE)) + break; + } + } + + if (i != MAX_RANDOM_MAC_ADDRS) { + append_ret = append_action_frame_cookie( + &adapter->random_mac[i].cookie_list, + cookie); + spin_unlock(&adapter->random_mac_lock); + + if (append_ret == -ENOMEM) { + hdd_err("No Sufficient memory for cookie"); + return append_ret; + } + + return 0; + } + + if (in_use_cnt == MAX_RANDOM_MAC_ADDRS) { + spin_unlock(&adapter->random_mac_lock); + hdd_err("Reached the limit of Max random addresses"); + return -EBUSY; + } + + /* get the first unused buf and store new random mac */ + for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) { + if (!adapter->random_mac[i].in_use) + break; + } + + INIT_LIST_HEAD(&adapter->random_mac[i].cookie_list); + action_cookie = allocate_action_frame_cookie( + &adapter->random_mac[i].cookie_list, + cookie); + if (!action_cookie) { + spin_unlock(&adapter->random_mac_lock); + hdd_err("No Sufficient memory for cookie"); + return -ENOMEM; + } + qdf_mem_copy(adapter->random_mac[i].addr, random_mac_addr, + QDF_MAC_ADDR_SIZE); + adapter->random_mac[i].in_use = true; + adapter->random_mac[i].freq = freq; + spin_unlock(&adapter->random_mac_lock); + /* Program random mac_addr */ + if (!hdd_set_random_mac(adapter, adapter->random_mac[i].addr, freq)) { + spin_lock(&adapter->random_mac_lock); + /* clear the cookie */ + delete_action_frame_cookie(action_cookie); + adapter->random_mac[i].in_use = false; + spin_unlock(&adapter->random_mac_lock); + hdd_err("random mac filter set failed for: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(adapter->random_mac[i].addr)); + return -EFAULT; + } + + return 0; +} + +/** + * hdd_reset_action_frame_random_mac() - Delete action frame cookie with + * given random mac addr + * @adapter: Pointer to adapter + * @random_mac_addr: Mac addr for cookie + * @cookie: Cookie to be deleted + * + * This function is used to delete the cookie from the cookie list + * corresponding to given random mac addr.If cookie list is empty after + * deleting, it will clear random mac filter. + * + * Return: 0 - for success else negative value + */ +static int32_t hdd_reset_action_frame_random_mac(hdd_adapter_t *adapter, + uint8_t *random_mac_addr, + uint64_t cookie) +{ + uint32_t i = 0; + uint32_t freq = 0; + struct action_frame_cookie *action_cookie = NULL; + + if (!cookie) { + hdd_err("Invalid cookie"); + return -EINVAL; + } + + hdd_info("mac_addr: " MAC_ADDRESS_STR " && cookie = %llu", + MAC_ADDR_ARRAY(random_mac_addr), cookie); + + spin_lock(&adapter->random_mac_lock); + for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) { + if ((adapter->random_mac[i].in_use) && + (!qdf_mem_cmp(adapter->random_mac[i].addr, + random_mac_addr, QDF_MAC_ADDR_SIZE))) + break; + } + + if (i == MAX_RANDOM_MAC_ADDRS) { + /* + * trying to delete cookie of random mac-addr + * for which entry is not present + */ + spin_unlock(&adapter->random_mac_lock); + return -EINVAL; + } + + action_cookie = find_action_frame_cookie( + &adapter->random_mac[i].cookie_list, + cookie); + + if (!action_cookie) { + spin_unlock(&adapter->random_mac_lock); + hdd_info("No cookie matches"); + return 0; + } + + delete_action_frame_cookie(action_cookie); + if (list_empty(&adapter->random_mac[i].cookie_list)) { + adapter->random_mac[i].in_use = false; + freq = adapter->random_mac[i].freq; + spin_unlock(&adapter->random_mac_lock); + hdd_clear_random_mac(adapter, random_mac_addr, + freq); + hdd_info("Deleted random mac_addr: "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(random_mac_addr)); + return 0; + } + + spin_unlock(&adapter->random_mac_lock); + return 0; +} + +/** + * hdd_delete_action_frame_cookie() - Delete action frame cookie + * @adapter: Pointer to adapter + * @cookie: Cookie to be deleted + * + * This function parses the cookie list of each random mac addr until the + * specified cookie is found and then deletes it. If cookie list is empty + * after deleting, it will clear random mac filter. + * + * Return: 0 - for success else negative value + */ +static int32_t hdd_delete_action_frame_cookie(hdd_adapter_t *adapter, + uint64_t cookie) +{ + uint32_t i = 0; + struct action_frame_cookie *action_cookie = NULL; + uint32_t freq = 0; + + hdd_info("Delete cookie = %llu", cookie); + + spin_lock(&adapter->random_mac_lock); + for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) { + if (!adapter->random_mac[i].in_use) + continue; + + action_cookie = find_action_frame_cookie( + &adapter->random_mac[i].cookie_list, + cookie); + + if (!action_cookie) + continue; + + delete_action_frame_cookie(action_cookie); + + if (list_empty(&adapter->random_mac[i].cookie_list)) { + adapter->random_mac[i].in_use = false; + freq = adapter->random_mac[i].freq; + spin_unlock(&adapter->random_mac_lock); + hdd_clear_random_mac(adapter, + adapter->random_mac[i].addr, + freq); + hdd_info("Deleted random addr "MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(adapter->random_mac[i].addr)); + return 0; + } + spin_unlock(&adapter->random_mac_lock); + return 0; + } + + spin_unlock(&adapter->random_mac_lock); + return 0; +} + +/** + * hdd_delete_all_action_frame_cookies() - Delete all action frame cookies + * @adapter: Pointer to adapter + * + * This function deletes all the cookie lists of each random mac addr and + * clears the corresponding random mac filters. + * + * Return: 0 - for success else negative value + */ +static void hdd_delete_all_action_frame_cookies(hdd_adapter_t *adapter) +{ + uint32_t i = 0; + struct action_frame_cookie *action_cookie = NULL; + struct list_head *n; + struct list_head *temp; + uint32_t freq = 0; + + spin_lock(&adapter->random_mac_lock); + + for (i = 0; i < MAX_RANDOM_MAC_ADDRS; i++) { + if (!adapter->random_mac[i].in_use) + continue; + + /* empty the list and clear random addr */ + list_for_each_safe(temp, n, + &adapter->random_mac[i].cookie_list) { + action_cookie = list_entry(temp, + struct action_frame_cookie, + cookie_node); + list_del(temp); + qdf_mem_free(action_cookie); + } + + adapter->random_mac[i].in_use = false; + freq = adapter->random_mac[i].freq; + spin_unlock(&adapter->random_mac_lock); + hdd_clear_random_mac(adapter, adapter->random_mac[i].addr, + freq); + hdd_info("Deleted random addr " MAC_ADDRESS_STR, + MAC_ADDR_ARRAY(adapter->random_mac[i].addr)); + spin_lock(&adapter->random_mac_lock); + } + + spin_unlock(&adapter->random_mac_lock); +} static QDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx, QDF_STATUS status, uint32_t scan_id) @@ -236,6 +744,7 @@ QDF_STATUS wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void *pCtx, (SIR_MAC_MGMT_PROBE_REQ << 4), NULL, 0); } + hdd_delete_all_action_frame_cookies(pAdapter); } else if ((QDF_SAP_MODE == pAdapter->device_mode) || (QDF_P2P_GO_MODE == pAdapter->device_mode) ) { @@ -338,6 +847,7 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter) (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) || (QDF_P2P_DEVICE_MODE == pAdapter->device_mode) ) { + hdd_delete_all_action_frame_cookies(pAdapter); sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX (pAdapter), pAdapter->sessionId, roc_scan_id); @@ -424,6 +934,7 @@ static void wlan_hdd_cancel_pending_roc(hdd_adapter_t *adapter) } else if (adapter->device_mode == QDF_P2P_CLIENT_MODE || adapter->device_mode == QDF_P2P_DEVICE_MODE) { + hdd_delete_all_action_frame_cookies(adapter); sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX (adapter), adapter->sessionId, roc_scan_id); @@ -525,6 +1036,7 @@ static void wlan_hdd_remain_on_chan_timeout(void *data) (QDF_P2P_CLIENT_MODE == pAdapter->device_mode) || (QDF_P2P_DEVICE_MODE == pAdapter->device_mode) ) { + hdd_delete_all_action_frame_cookies(pAdapter); sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, roc_scan_id); } else if ((QDF_SAP_MODE == pAdapter->device_mode) || @@ -1244,6 +1756,7 @@ __wlan_hdd_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, ) { uint8_t sessionId = pAdapter->sessionId; + hdd_delete_all_action_frame_cookies(pAdapter); sme_cancel_remain_on_channel(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId, roc_scan_id); } else if ((QDF_SAP_MODE == pAdapter->device_mode) || @@ -1305,6 +1818,7 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, hdd_adapter_t *goAdapter; uint16_t current_freq; uint8_t home_ch = 0; + bool enb_random_mac = false; ENTER(); @@ -1681,6 +2195,20 @@ send_frame: } } + if (qdf_mem_cmp((uint8_t *)(&buf[WLAN_HDD_80211_FRM_SA_OFFSET]), + &pAdapter->macAddressCurrent, QDF_MAC_ADDR_SIZE)) { + hdd_info("%s: action frame sa is randomized with mac: " + MAC_ADDRESS_STR, __func__, + MAC_ADDR_ARRAY((uint8_t *) + (&buf[WLAN_HDD_80211_FRM_SA_OFFSET]))); + enb_random_mac = true; + } + + if (enb_random_mac && !noack) + hdd_set_action_frame_random_mac(pAdapter, + (uint8_t *)(&buf[WLAN_HDD_80211_FRM_SA_OFFSET]), + *cookie, chan->center_freq); + if (QDF_STATUS_SUCCESS != sme_send_action(WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId, buf, len, extendedWait, noack, @@ -1701,6 +2229,14 @@ send_frame: return 0; err: if (!noack) { + if (enb_random_mac && + ((pAdapter->device_mode == QDF_STA_MODE) || + (pAdapter->device_mode == QDF_P2P_CLIENT_MODE) || + (pAdapter->device_mode == QDF_P2P_DEVICE_MODE))) + hdd_reset_action_frame_random_mac(pAdapter, + (uint8_t *)(&buf[WLAN_HDD_80211_FRM_SA_OFFSET]), + *cookie); + hdd_send_action_cnf(pAdapter, false); } return 0; @@ -1743,10 +2279,36 @@ int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, return ret; } +/** + * hdd_wlan_delete_mgmt_tx_cookie() - Wrapper to delete action frame cookie + * @wdev: Pointer to wireless device + * @cookie: Cookie to be deleted + * + * This is a wrapper function which actually invokes the hdd api to delete + * cookie based on the device mode of adapter. + * + * Return: 0 - for success else negative value + */ +static int hdd_wlan_delete_mgmt_tx_cookie(struct wireless_dev *wdev, + u64 cookie) +{ + struct net_device *dev = wdev->netdev; + hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev); + + if ((adapter->device_mode == QDF_STA_MODE) || + (adapter->device_mode == QDF_P2P_CLIENT_MODE) || + (adapter->device_mode == QDF_P2P_DEVICE_MODE)) { + hdd_delete_action_frame_cookie(adapter, cookie); + } + + return 0; +} + static int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct wireless_dev *wdev, u64 cookie) { + hdd_wlan_delete_mgmt_tx_cookie(wdev, cookie); return wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, wdev, cookie); } @@ -2424,6 +2986,11 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter, hdd_get_adapter_by_macaddr(pHddCtx, &pbFrames [WLAN_HDD_80211_FRM_DA_OFFSET]); + + if (pAdapter == NULL) + pAdapter = hdd_get_adapter_by_rand_macaddr(pHddCtx, + &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]); + if (NULL == pAdapter) { /* * Under assumtion that we don't receive any action diff --git a/core/mac/inc/sir_api.h b/core/mac/inc/sir_api.h index 300f80f48c45..fc97373b3d6a 100644 --- a/core/mac/inc/sir_api.h +++ b/core/mac/inc/sir_api.h @@ -7151,4 +7151,34 @@ struct sir_del_all_tdls_peers { uint16_t msg_len; struct qdf_mac_addr bssid; }; + +/** + * enum action_filter_type - Type of action frame filter + * @SME_ACTION_FRAME_RANDOM_MAC_SET: Set filter + * @SME_ACTION_FRAME_RANDOM_MAC_CLEAR: Clear filter + */ +enum action_filter_type { + SME_ACTION_FRAME_RANDOM_MAC_SET, + SME_ACTION_FRAME_RANDOM_MAC_CLEAR, +}; + +typedef void (*action_frame_random_filter_callback)(bool set_random_addr, + void *context); +/** + * struct action_frame_random_filter - Random mac filter attrs for set/clear + * @session_id: Session interface + * @filter_type: Type of filter from action_filter_type + * @callback: Invoked from wmi + * @context: Parameter to be used with callback + * @mac_addr: Random mac addr for which filter is to be set + * @freq: Channel frequency + */ +struct action_frame_random_filter { + uint32_t session_id; + enum action_filter_type filter_type; + action_frame_random_filter_callback callback; + void *context; + uint8_t mac_addr[QDF_MAC_ADDR_SIZE]; + uint32_t freq; +}; #endif /* __SIR_API_H */ diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index 05805f6dabcc..a367c7f0429e 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -655,6 +655,8 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_SET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 375) #define SIR_HAL_GET_ARP_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 376) +#define SIR_HAL_ACTION_FRAME_RANDOM_MAC (SIR_HAL_ITC_MSG_TYPES_BEGIN + 377) + #define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF) /* CFG message types */ diff --git a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c index d3b184d32dde..9ee229daec56 100644 --- a/core/mac/src/sys/legacy/src/utils/src/mac_trace.c +++ b/core/mac/src/sys/legacy/src/utils/src/mac_trace.c @@ -723,6 +723,7 @@ uint8_t *mac_trace_get_wma_msg_string(uint16_t wma_msg) CASE_RETURN_STRING(WMA_SET_WOW_PULSE_CMD); CASE_RETURN_STRING(WDA_SET_UDP_RESP_OFFLOAD); CASE_RETURN_STRING(WMA_SET_PER_ROAM_CONFIG_CMD); + CASE_RETURN_STRING(WDA_ACTION_FRAME_RANDOM_MAC); default: return (uint8_t *) "UNKNOWN"; break; diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index 0f55c4734d9b..631efbc093ed 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1552,4 +1552,39 @@ tCsrScanResultInfo *sme_scan_get_result_for_bssid(tHalHandle hal_handle, QDF_STATUS sme_delete_all_tdls_peers(tHalHandle hal, uint8_t session_id); +/** + * sme_set_random_mac() - Set random mac address filter + * @hal: hal handle for getting global mac struct + * @callback: callback to be invoked for response from firmware + * @session_id: interface id + * @random_mac: random mac address to be set + * @freq: Channel frequency + * @context: parameter to callback + * + * This function is used to set random mac address filter for action frames + * which are send with the same address, callback is invoked when corresponding + * event from firmware has come. + * + * Return: eHalStatus enumeration. + */ +QDF_STATUS sme_set_random_mac(tHalHandle hal, + action_frame_random_filter_callback callback, + uint32_t session_id, uint8_t *random_mac, + uint32_t freq, void *context); + +/** + * sme_clear_random_mac() - clear random mac address filter + * @hal: HAL handle + * @session_id: interface id + * @random_mac: random mac address to be cleared + * @freq: Channel frequency + * + * This function is used to clear the randmom mac address filters + * which are set with sme_set_random_mac + * + * Return: QDF_STATUS enumeration. + */ +QDF_STATUS sme_clear_random_mac(tHalHandle hal, uint32_t session_id, + uint8_t *random_mac, uint32_t freq); + #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 588cd3e576fb..82f44e3bce1d 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -17550,3 +17550,97 @@ QDF_STATUS sme_set_bt_activity_info_cb(tHalHandle hal, return status; } + +QDF_STATUS sme_set_random_mac(tHalHandle hal, + action_frame_random_filter_callback callback, + uint32_t session_id, uint8_t *random_mac, + uint32_t freq, void *context) +{ + + QDF_STATUS status = QDF_STATUS_SUCCESS; + QDF_STATUS vos_status = QDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + cds_msg_t vos_msg; + struct action_frame_random_filter *filter; + + filter = qdf_mem_malloc(sizeof(*filter)); + + if (!filter) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("Failed to alloc random mac filter")); + return QDF_STATUS_E_FAILURE; + } + + filter->session_id = session_id; + filter->filter_type = SME_ACTION_FRAME_RANDOM_MAC_SET; + filter->callback = callback; + filter->context = context; + filter->freq = freq; + qdf_mem_copy(filter->mac_addr, random_mac, QDF_MAC_ADDR_SIZE); + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (status == QDF_STATUS_SUCCESS) { + /* Serialize the req through MC thread */ + vos_msg.bodyptr = filter; + vos_msg.type = WDA_ACTION_FRAME_RANDOM_MAC; + vos_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &vos_msg); + + if (!QDF_IS_STATUS_SUCCESS(vos_status)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("action frame set random mac msg fail")); + status = QDF_STATUS_E_FAILURE; + qdf_mem_free(filter); + } + sme_release_global_lock(&mac_ctx->sme); + } else { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("sme_AcquireGlobalLock failed")); + qdf_mem_free(filter); + } + return status; +} + +QDF_STATUS sme_clear_random_mac(tHalHandle hal, uint32_t session_id, + uint8_t *random_mac, uint32_t freq) +{ + + QDF_STATUS status = QDF_STATUS_SUCCESS; + QDF_STATUS vos_status = QDF_STATUS_SUCCESS; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + cds_msg_t vos_msg; + struct action_frame_random_filter *filter; + + filter = qdf_mem_malloc(sizeof(*filter)); + + if (!filter) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("Failed to alloc random mac filter")); + return QDF_STATUS_E_FAILURE; + } + + filter->session_id = session_id; + filter->freq = freq; + filter->filter_type = SME_ACTION_FRAME_RANDOM_MAC_CLEAR; + qdf_mem_copy(filter->mac_addr, random_mac, QDF_MAC_ADDR_SIZE); + + status = sme_acquire_global_lock(&mac_ctx->sme); + if (status == QDF_STATUS_SUCCESS) { + /* Serialize the req through MC thread */ + vos_msg.bodyptr = filter; + vos_msg.type = WDA_ACTION_FRAME_RANDOM_MAC; + vos_status = cds_mq_post_message(QDF_MODULE_ID_WMA, &vos_msg); + + if (!QDF_IS_STATUS_SUCCESS(vos_status)) { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("action frame clear random mac msg fail")); + status = QDF_STATUS_E_FAILURE; + qdf_mem_free(filter); + } + sme_release_global_lock(&mac_ctx->sme); + } else { + QDF_TRACE(QDF_MODULE_ID_SME, QDF_TRACE_LEVEL_ERROR, + FL("sme_acquire_global_lock failed")); + qdf_mem_free(filter); + } + return status; +} diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index 3c75a625e017..d2faf3d6ce77 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -1101,6 +1101,7 @@ struct wma_txrx_node { bool is_vdev_valid; struct sir_vdev_wow_stats wow_stats; struct sme_rcpi_req *rcpi_req; + struct action_frame_random_filter *action_frame_filter; }; #if defined(QCA_WIFI_FTM) diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 70a7cf8be016..8792f409e69a 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -496,6 +496,8 @@ #define WMA_SET_ARP_STATS_REQ SIR_HAL_SET_ARP_STATS_REQ #define WMA_GET_ARP_STATS_REQ SIR_HAL_GET_ARP_STATS_REQ +#define WDA_ACTION_FRAME_RANDOM_MAC SIR_HAL_ACTION_FRAME_RANDOM_MAC + /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_dev_if.c b/core/wma/src/wma_dev_if.c index a7785470d9df..a41ed7a2475d 100644 --- a/core/wma/src/wma_dev_if.c +++ b/core/wma/src/wma_dev_if.c @@ -4696,6 +4696,14 @@ void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params) qdf_mem_free(rcpi_req); } + if (wma->interfaces[params->smesessionId].action_frame_filter) { + struct action_frame_random_filter *action_frame_filter = + wma->interfaces[params->smesessionId].action_frame_filter; + wma->interfaces[params->smesessionId].action_frame_filter = + NULL; + qdf_mem_free(action_frame_filter); + } + if (wlan_op_mode_ibss == ol_txrx_get_opmode(txrx_vdev)) wma->ibss_started = 0; diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 95cd77571c18..435b6b2e738f 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -1991,6 +1991,60 @@ static int wma_flush_complete_evt_handler(void *handle, } /** + * wma_action_frame_filter_mac_event_handler() - action frame filter evt handler + * @handle: wma handle + * @event_buf: event handler data + * @len: length of @event_buf + * + * this function will handle the + * WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_STATUS_EVENTID + * + * Return: int + */ +static int +wma_action_frame_filter_mac_event_handler(void *handle, u_int8_t *event_buf, + u_int32_t len) +{ + tp_wma_handle wma_handle = (tp_wma_handle)handle; + WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_STATUS_EVENTID_param_tlvs *param_buf; + wmi_vdev_add_mac_addr_to_rx_filter_status_event_fixed_param *event; + struct action_frame_random_filter *filter; + struct wma_txrx_node *intr; + bool status = false; + + WMA_LOGD("%s: Enter", __func__); + + param_buf = + (WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_STATUS_EVENTID_param_tlvs *) + event_buf; + if (!param_buf) { + WMA_LOGA(FL("Invalid action frame filter mac event")); + return -EINVAL; + } + event = param_buf->fixed_param; + if (!event) { + WMA_LOGA(FL("Invalid fixed param")); + return -EINVAL; + } + + intr = &wma_handle->interfaces[event->vdev_id]; + /* command is in progress */ + if (!intr->action_frame_filter) { + WMA_LOGE(FL("no action frame req is pending - invalid event")); + return -EPERM; + } + filter = intr->action_frame_filter; + if (event->status) + status = true; + + (filter->callback)(status, filter->context); + intr->action_frame_filter = NULL; + qdf_mem_free(filter); + + return 0; +} + +/** * wma_open() - Allocate wma context and initialize it. * @cds_context: cds context * @wma_tgt_cfg_cb: tgt config callback fun @@ -2506,6 +2560,11 @@ QDF_STATUS wma_open(void *cds_context, wma_flush_complete_evt_handler, WMA_RX_WORK_CTX); + wmi_unified_register_event_handler(wma_handle->wmi_handle, + WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_STATUS_EVENTID, + wma_action_frame_filter_mac_event_handler, + WMA_RX_SERIALIZER_CTX); + wma_ndp_register_all_event_handlers(wma_handle); wma_register_debug_callback(); @@ -6385,6 +6444,98 @@ static void wma_get_arp_req_stats(WMA_HANDLE handle, } /** + * wma_process_action_frame_random_mac() - set/clear action frame random mac + * @wma_handle: pointer to wma handle + * @filter: pointer to buffer containing random mac, session_id and callback + * + * Return: QDF_STATUS_SUCCESS for success or error code. + */ +static QDF_STATUS +wma_process_action_frame_random_mac(tp_wma_handle wma_handle, + struct action_frame_random_filter *filter) +{ + wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param *cmd; + uint32_t len; + wmi_buf_t buf; + int ret; + struct action_frame_random_filter *filter_bkup = NULL; + struct wma_txrx_node *intr = NULL; + + if (!filter) { + WMA_LOGE(FL("invalid pointer")); + return QDF_STATUS_E_INVAL; + } + + if (!wma_handle) { + WMA_LOGE(FL("WMA context is invald!")); + return QDF_STATUS_E_INVAL; + } + + if (filter->filter_type == SME_ACTION_FRAME_RANDOM_MAC_SET) { + intr = &wma_handle->interfaces[filter->session_id]; + /* command is in progress */ + if (intr->action_frame_filter != NULL) { + WMA_LOGE(FL("previous action frame req is pending")); + return QDF_STATUS_SUCCESS; + } + + filter_bkup = qdf_mem_malloc(sizeof(*filter)); + if (!filter_bkup) { + WMA_LOGE( + FL("action frame filter mem alloc failed")); + return QDF_STATUS_E_FAILURE; + } + + filter_bkup->session_id = filter->session_id; + filter_bkup->callback = filter->callback; + filter_bkup->filter_type = filter->filter_type; + filter_bkup->context = filter->context; + filter_bkup->freq = filter->freq; + + qdf_mem_copy(filter_bkup->mac_addr, filter->mac_addr, + QDF_MAC_ADDR_SIZE); + intr->action_frame_filter = (void *)filter_bkup; + } + + len = sizeof(*cmd); + buf = wmi_buf_alloc(wma_handle->wmi_handle, len); + + if (!buf) { + WMA_LOGE(FL("Failed allocate wmi buffer")); + return QDF_STATUS_E_NOMEM; + } + cmd = (wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param *) + wmi_buf_data(buf); + + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + wmi_vdev_add_mac_addr_to_rx_filter_cmd_fixed_param)); + + cmd->vdev_id = filter->session_id; + cmd->freq = filter->freq; + WMI_CHAR_ARRAY_TO_MAC_ADDR(filter->mac_addr, &cmd->mac_addr); + if (filter->filter_type == SME_ACTION_FRAME_RANDOM_MAC_SET) + cmd->enable = 1; + else + cmd->enable = 0; + + ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, + WMI_VDEV_ADD_MAC_ADDR_TO_RX_FILTER_CMDID); + if (ret) { + WMA_LOGE(FL("Failed to send action frame random mac cmd")); + wmi_buf_free(buf); + if (filter->filter_type == SME_ACTION_FRAME_RANDOM_MAC_SET) { + qdf_mem_free(filter_bkup); + intr->action_frame_filter = NULL; + } + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** * wma_mc_process_msg() - process wma messages and call appropriate function. * @cds_context: cds context * @msg: message @@ -7248,6 +7399,11 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) (struct get_arp_stats_params *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case WDA_ACTION_FRAME_RANDOM_MAC: + wma_process_action_frame_random_mac(wma_handle, + (struct action_frame_random_filter *)msg->bodyptr); + qdf_mem_free(msg->bodyptr); + break; default: WMA_LOGE("Unhandled WMA message of type %d", msg->type); if (msg->bodyptr) |
