summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanumanth Reddy Pothula <c_hpothu@codeaurora.org>2017-02-07 01:48:53 +0530
committerRajeev Kumar Sirasanagandla <rsirasan@codeaurora.org>2017-03-27 12:23:23 +0530
commitff04da4130e5998afecdacb1013bfafa08961776 (patch)
tree0c0adebb86fb0af67ed1fc2474aae2c62868c1a3
parentbb535a3b325687d493f2862be83f26267d0b88dd (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.h65
-rw-r--r--core/hdd/inc/wlan_hdd_p2p.h15
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c24
-rw-r--r--core/hdd/src/wlan_hdd_main.c36
-rw-r--r--core/hdd/src/wlan_hdd_p2p.c567
-rw-r--r--core/mac/inc/sir_api.h30
-rw-r--r--core/mac/src/include/sir_params.h2
-rw-r--r--core/mac/src/sys/legacy/src/utils/src/mac_trace.c1
-rw-r--r--core/sme/inc/sme_api.h35
-rw-r--r--core/sme/src/common/sme_api.c94
-rw-r--r--core/wma/inc/wma.h1
-rw-r--r--core/wma/inc/wma_types.h2
-rw-r--r--core/wma/src/wma_dev_if.c8
-rw-r--r--core/wma/src/wma_main.c156
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)