summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRajeev Kumar Sirasanagandla <rsirasan@codeaurora.org>2017-01-25 14:45:44 +0530
committerHanumanth Reddy Pothula <c_hpothu@codeaurora.org>2017-02-13 14:42:46 +0530
commit60eb9a3c5781a35f1c1cecbf3bffe0f6ff337f6b (patch)
treef1819182398ba0bad3a44894bed5daeba1a35296
parent8ac94bda17763849c50e3dd289a3f85b884e89cc (diff)
qcacld-2.0: Randomize sa of action frames
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.h63
-rw-r--r--CORE/HDD/inc/wlan_hdd_p2p.h16
-rw-r--r--CORE/HDD/src/wlan_hdd_cfg80211.c24
-rw-r--r--CORE/HDD/src/wlan_hdd_main.c35
-rw-r--r--CORE/HDD/src/wlan_hdd_p2p.c554
-rw-r--r--CORE/MAC/inc/sirApi.h28
-rw-r--r--CORE/MAC/src/include/sirParams.h1
-rw-r--r--CORE/SERVICES/WMA/wma.c160
-rw-r--r--CORE/SERVICES/WMA/wma.h2
-rw-r--r--CORE/SME/inc/sme_Api.h34
-rw-r--r--CORE/SME/src/sme_common/sme_Api.c94
-rw-r--r--CORE/SYS/legacy/src/utils/src/macTrace.c1
-rw-r--r--CORE/WDA/inc/wlan_qct_wda.h1
13 files changed, 1010 insertions, 3 deletions
diff --git a/CORE/HDD/inc/wlan_hdd_main.h b/CORE/HDD/inc/wlan_hdd_main.h
index a5601e1a0589..4c0ca17cd175 100644
--- a/CORE/HDD/inc/wlan_hdd_main.h
+++ b/CORE/HDD/inc/wlan_hdd_main.h
@@ -152,6 +152,8 @@
#define WLAN_WAIT_TIME_CHAIN_RSSI 1000
+#define WLAN_WAIT_TIME_SET_RND 100
+
#define MAX_NUMBER_OF_ADAPTERS 4
#define MAX_CFG_STRING_LEN 255
@@ -284,6 +286,12 @@ typedef enum
} scan_reject_states;
/*
+ * Maximum no.of random mac addresses supported by firmware
+ * for transmitting management action frames
+ */
+#define MAX_RANDOM_MAC_ADDRS 16
+
+/*
* Generic asynchronous request/response support
*
* Many of the APIs supported by HDD require a call to SME to
@@ -331,6 +339,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
@@ -343,6 +365,7 @@ extern spinlock_t hdd_context_lock;
#define FW_STATUS_MAGIC 0x46575354 /* FWSTATUS(FWST) */
#define POWER_STATS_MAGIC 0x14111990
#define BPF_CONTEXT_MAGIC 0x4575354 /* BPF */
+#define ACTION_FRAME_RANDOM_CONTEXT_MAGIC 0x87878787
#ifdef QCA_LL_TX_FLOW_CT
/* MAX OS Q block time value in msec
@@ -736,6 +759,28 @@ 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
+ * @cookie_list: List of cookies tied with random mac
+ */
+struct action_frame_random_mac {
+ bool in_use;
+ uint8_t addr[VOS_MAC_ADDR_SIZE];
+ struct list_head cookie_list;
+};
+
struct hdd_station_ctx
{
/** Handle to the Wireless Extension State */
@@ -1395,6 +1440,10 @@ struct hdd_adapter_s
queue_oper_history[WLAN_HDD_MAX_HISTORY_ENTRY];
struct hdd_netif_queue_stats queue_oper_stats[WLAN_REASON_TYPE_MAX];
struct power_stats_response *chip_power_stats;
+
+ /* random address management for management action frames */
+ spinlock_t random_mac_lock;
+ struct action_frame_random_mac random_mac[MAX_RANDOM_MAC_ADDRS];
};
#define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station)
@@ -2095,6 +2144,20 @@ hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
hdd_adapter_t * hdd_get_adapter_by_vdev( hdd_context_t *pHddCtx,
tANI_U32 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);
+
VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter );
hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode );
void hdd_deinit_adapter(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
diff --git a/CORE/HDD/inc/wlan_hdd_p2p.h b/CORE/HDD/inc/wlan_hdd_p2p.h
index 4126fc30e684..55236875ff24 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.
*
@@ -47,6 +47,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-"
@@ -209,4 +210,17 @@ void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter);
#define MAX_ROC_REQ_QUEUE_ENTRY 10
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 71fe89b9bd01..0a13285d4397 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -14047,6 +14047,29 @@ static void wlan_hdd_cfg80211_add_connected_pno_support(struct wiphy *wiphy)
}
#endif
+#ifdef CFG80211_RAND_TA_FOR_PUBLIC_ACTION_FRAME
+/**
+ * wlan_hdd_cfg80211_action_frame_randomization_init() - Randomize SA of MA frms
+ * @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)
+{
+ return;
+}
+#endif
+
/*
* FUNCTION: wlan_hdd_cfg80211_init
* This function is called by hdd_wlan_startup()
@@ -14302,6 +14325,7 @@ int wlan_hdd_cfg80211_init(struct device *dev,
hdd_config_sched_scan_plans_to_wiphy(wiphy, pCfg);
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 b12ed9be972c..664c8fd585b8 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -10270,6 +10270,19 @@ static inline void
hdd_adapter_runtime_suspend_denit(hdd_adapter_t *adapter) { }
#endif
+/**
+ * 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);
+ vos_mem_zero(adapter->random_mac, sizeof(adapter->random_mac));
+}
+
static hdd_adapter_t* hdd_alloc_station_adapter(hdd_context_t *pHddCtx,
tSirMacAddr macAddr,
unsigned char name_assign_type,
@@ -11102,6 +11115,9 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
if( VOS_STATUS_SUCCESS != status )
goto err_free_netdev;
+ /* initialize action frame random mac info */
+ hdd_adapter_init_action_frame_random_mac(pAdapter);
+
// Workqueue which gets scheduled in IPv4 notification callback
vos_init_work(&pAdapter->ipv4NotifierWorkQueue,
hdd_ipv4_notifier_work_queue);
@@ -12663,6 +12679,25 @@ hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
}
+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;
+ VOS_STATUS status;
+
+ status = hdd_get_front_adapter(hdd_ctx, &adapter_node);
+ while (adapter_node && status == VOS_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;
+}
+
hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
{
hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
index df5f60a4dbd7..931346ecd522 100644
--- a/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -162,6 +162,500 @@ 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) {
+ hddLog(LOGE, FL("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);
+ hddLog(VOS_TRACE_LEVEL_WARN,
+ FL("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
+ *
+ * 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)
+{
+ struct random_mac_context context;
+ hdd_context_t *hdd_ctx;
+ eHalStatus sme_status;
+ unsigned long rc;
+ bool status = false;
+
+ ENTER();
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ if (wlan_hdd_validate_context(hdd_ctx)) {
+ hddLog(LOGE,FL("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,
+ &context);
+
+ if (sme_status != eHAL_STATUS_SUCCESS) {
+ hddLog(LOGE,FL("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) {
+ hddLog(LOGE,
+ FL("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
+ *
+ * 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)
+{
+ hdd_context_t *hdd_ctx;
+ eHalStatus status;
+
+ ENTER();
+ hdd_ctx = WLAN_HDD_GET_CTX(adapter);
+ if (wlan_hdd_validate_context(hdd_ctx)) {
+ hddLog(LOGE,FL("Invalid hdd ctx"));
+ return false;
+ }
+
+ status = sme_clear_random_mac(hdd_ctx->hHal, adapter->sessionId,
+ random_mac_addr);
+
+ if (status != eHAL_STATUS_SUCCESS) {
+ hddLog(LOGE,FL("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) &&
+ (!memcmp(adapter->random_mac[i].addr, random_mac_addr,
+ VOS_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 = vos_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);
+ vos_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 successfull 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
+ *
+ * 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 i = 0;
+ uint32_t in_use_cnt = 0;
+ struct action_frame_cookie *action_cookie = NULL;
+ int32_t append_ret = 0;
+
+ if (!cookie) {
+ hddLog(LOGE, FL("Invalid cookie"));
+ return -EINVAL;
+ }
+
+ hddLog(LOG1, FL("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) {
+ in_use_cnt++;
+ if (!memcmp(adapter->random_mac[i].addr,
+ random_mac_addr, VOS_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) {
+ hddLog(LOGE, FL("No Sufficient memory for cookie"));
+ return append_ret;
+ }
+
+ return 0;
+ }
+
+ if (in_use_cnt == MAX_RANDOM_MAC_ADDRS) {
+ spin_unlock(&adapter->random_mac_lock);
+ hddLog(LOGE, FL("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);
+ hddLog(LOGE, FL("No Sufficient memory for cookie"));
+ return -ENOMEM;
+ }
+ vos_mem_copy(adapter->random_mac[i].addr, random_mac_addr,
+ VOS_MAC_ADDR_SIZE);
+ adapter->random_mac[i].in_use = true;
+ spin_unlock(&adapter->random_mac_lock);
+ /* Program random mac_addr */
+ if (!hdd_set_random_mac(adapter, adapter->random_mac[i].addr)) {
+ 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);
+ hddLog(LOGE, FL("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;
+ struct action_frame_cookie *action_cookie = NULL;
+
+ if (!cookie) {
+ hddLog(LOGE, FL("Invalid cookie"));
+ return -EINVAL;
+ }
+
+ hddLog(LOG1, FL("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) &&
+ (!memcmp(adapter->random_mac[i].addr,
+ random_mac_addr, VOS_MAC_ADDR_SIZE)))
+ break;
+ }
+
+ if (i == MAX_RANDOM_MAC_ADDRS) {
+ spin_unlock(&adapter->random_mac_lock);
+ hddLog(LOGE, FL("trying to delete cookie of random mac-addr"
+ " for which entry is not present"));
+ return -EINVAL;
+ }
+
+ action_cookie = find_action_frame_cookie(&adapter->random_mac[i].cookie_list,
+ cookie);
+
+ if (!action_cookie) {
+ spin_unlock(&adapter->random_mac_lock);
+ hddLog(LOG1, FL("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;
+ spin_unlock(&adapter->random_mac_lock);
+ hdd_clear_random_mac(adapter, random_mac_addr);
+ hddLog(LOG1, FL("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;
+
+ hddLog(LOG1, FL("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;
+ spin_unlock(&adapter->random_mac_lock);
+ hdd_clear_random_mac(adapter,
+ adapter->random_mac[i].addr);
+ hddLog(LOG1, FL("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);
+ hddLog(LOG1, FL("Invalid cookie"));
+ return -EINVAL;
+}
+
+/**
+ * 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;
+
+ 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);
+ vos_mem_free(action_cookie);
+ }
+
+ adapter->random_mac[i].in_use = false;
+ spin_unlock(&adapter->random_mac_lock);
+ hdd_clear_random_mac(adapter, adapter->random_mac[i].addr);
+ hddLog(LOG1, FL("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 eHalStatus
wlan_hdd_remain_on_channel_callback(tHalHandle hHal, void* pCtx,
eHalStatus status)
@@ -360,6 +854,7 @@ void wlan_hdd_cancel_existing_remain_on_channel(hdd_adapter_t *pAdapter)
( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
)
{
+ hdd_delete_all_action_frame_cookies(pAdapter);
sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
pAdapter->sessionId );
}
@@ -463,6 +958,7 @@ void wlan_hdd_cleanup_remain_on_channel_ctx(hdd_adapter_t *pAdapter)
} else if (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT ||
pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
{
+ hdd_delete_all_action_frame_cookies(pAdapter);
sme_CancelRemainOnChannel(WLAN_HDD_GET_HAL_CTX(pAdapter),
pAdapter->sessionId);
}
@@ -548,6 +1044,7 @@ void wlan_hdd_remain_on_chan_timeout(void *data)
( WLAN_HDD_P2P_DEVICE == pAdapter->device_mode )
)
{
+ hdd_delete_all_action_frame_cookies(pAdapter);
sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
pAdapter->sessionId );
}
@@ -1352,6 +1849,7 @@ int __wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
(WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ||
(WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)) {
tANI_U8 sessionId = pAdapter->sessionId;
+ hdd_delete_all_action_frame_cookies(pAdapter);
sme_CancelRemainOnChannel( WLAN_HDD_GET_HAL_CTX( pAdapter ),
sessionId );
} else if ((WLAN_HDD_SOFTAP== pAdapter->device_mode) ||
@@ -1404,7 +1902,6 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy,
return ret;
}
-
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS)
int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
struct ieee80211_channel *chan, bool offchan,
@@ -1446,6 +1943,7 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
unsigned long rc;
hdd_adapter_t *goAdapter;
uint8_t home_ch = 0;
+ bool enb_random_mac = false;
ENTER();
@@ -1609,6 +2107,7 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
home_ch = goAdapter->sessionCtx.ap.operatingChannel;
}
+
if (ieee80211_frequency_to_channel(chan->center_freq) == home_ch) {
/* if adapter is already on requested ch, no need for ROC */
wait = 0;
@@ -1795,6 +2294,19 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
}
}
+ if (!vos_mem_compare((uint8_t *)(&buf[WLAN_HDD_80211_FRM_SA_OFFSET]),
+ &pAdapter->macAddressCurrent, VOS_MAC_ADDR_SIZE)) {
+ hddLog(LOG1, "%s: sa of action frame is randomized with mac-addr: "
+ 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);
+
if (eHAL_STATUS_SUCCESS !=
sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter),
sessionId, buf, len, extendedWait, noack))
@@ -1827,6 +2339,13 @@ int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
err:
if(!noack)
{
+ if (enb_random_mac &&
+ ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) ||
+ (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
+ (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)))
+ hdd_reset_action_frame_random_mac(pAdapter,
+ (uint8_t *)(&buf[WLAN_HDD_80211_FRM_SA_OFFSET]),
+ *cookie);
hdd_sendActionCnf( pAdapter, FALSE );
}
return 0;
@@ -1900,6 +2419,31 @@ int wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
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 == WLAN_HDD_INFRA_STATION) ||
+ (adapter->device_mode == WLAN_HDD_P2P_CLIENT) ||
+ (adapter->device_mode == WLAN_HDD_P2P_DEVICE)) {
+ hdd_delete_action_frame_cookie(adapter, cookie);
+ }
+
+ return 0;
+}
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) || defined(WITH_BACKPORTS)
int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
struct wireless_dev *wdev,
@@ -1910,6 +2454,8 @@ int __wlan_hdd_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
return -EINVAL;
}
+ hdd_wlan_delete_mgmt_tx_cookie(wdev, cookie);
+
return wlan_hdd_cfg80211_cancel_remain_on_channel(wiphy, wdev, cookie);
}
#else
@@ -2575,6 +3121,12 @@ void __hdd_indicate_mgmt_frame(hdd_adapter_t *pAdapter,
&pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
if (NULL == pAdapter)
{
+ pAdapter = hdd_get_adapter_by_rand_macaddr(pHddCtx,
+ &pbFrames[WLAN_HDD_80211_FRM_DA_OFFSET]);
+ }
+
+ if (NULL == pAdapter)
+ {
/* We will receive broadcast management frames in OCB mode */
pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_OCB);
if (NULL == pAdapter || !vos_is_macaddr_broadcast(
diff --git a/CORE/MAC/inc/sirApi.h b/CORE/MAC/inc/sirApi.h
index bb7af9a1c2b7..59952c6effd3 100644
--- a/CORE/MAC/inc/sirApi.h
+++ b/CORE/MAC/inc/sirApi.h
@@ -8356,4 +8356,32 @@ struct sir_peer_set_rx_blocksize {
uint32_t rx_block_ack_win_limit;
};
+/**
+ * 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
+ */
+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[VOS_MAC_ADDR_SIZE];
+};
+
#endif /* __SIR_API_H */
diff --git a/CORE/MAC/src/include/sirParams.h b/CORE/MAC/src/include/sirParams.h
index 0fe84ba295ac..b8e957f689a8 100644
--- a/CORE/MAC/src/include/sirParams.h
+++ b/CORE/MAC/src/include/sirParams.h
@@ -794,6 +794,7 @@ typedef struct sSirMbMsgP2p
#define SIR_HAL_POWER_DEBUG_STATS_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 371)
#define SIR_HAL_GET_PEER_INFO_EXT (SIR_HAL_ITC_MSG_TYPES_BEGIN + 372)
#define SIR_HAL_GET_PEER_INFO_EXT_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 373)
+#define SIR_HAL_ACTION_FRAME_RANDOM_MAC (SIR_HAL_ITC_MSG_TYPES_BEGIN + 374)
#define SIR_HAL_MSG_TYPES_END (SIR_HAL_MSG_TYPES_BEGIN + 0x1FF)
diff --git a/CORE/SERVICES/WMA/wma.c b/CORE/SERVICES/WMA/wma.c
index 2946215de3ff..46d19e5cb74f 100644
--- a/CORE/SERVICES/WMA/wma.c
+++ b/CORE/SERVICES/WMA/wma.c
@@ -8524,6 +8524,59 @@ static void wma_register_debug_callback(void)
vos_register_debug_callback(VOS_MODULE_ID_WDA, &wma_state_info_dump);
}
+/**
+ * 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 progess */
+ if(!intr->action_frame_filter) {
+ WMA_LOGE(FL("no action frame req is pending - invalid event"));
+ return -1;
+ }
+ filter = intr->action_frame_filter;
+ if (event->status)
+ status = true;
+
+ (filter->callback)(status, filter->context);
+ intr->action_frame_filter = NULL;
+ vos_mem_free(filter);
+
+ return 0;
+}
+
struct wma_version_info g_wmi_version_info;
/*
@@ -8961,6 +9014,10 @@ VOS_STATUS WDA_open(v_VOID_t *vos_context, v_VOID_t *os_ctx,
WMI_CHAN_INFO_EVENTID,
wma_chan_info_event_handler);
+ 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_register_debug_callback();
wma_ndp_register_all_event_handlers(wma_handle);
@@ -19571,6 +19628,14 @@ static void wma_delete_bss(tp_wma_handle wma, tpDeleteBssParams params)
wma->interfaces[params->smesessionId].psnr_req = NULL;
}
+ 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;
+ vos_mem_free(action_frame_filter);
+ }
+
if (wlan_op_mode_ibss == txrx_vdev->opmode) {
wma->ibss_started = 0;
}
@@ -32433,6 +32498,96 @@ static VOS_STATUS wma_set_rx_blocksize(tp_wma_handle wma_handle,
return VOS_STATUS_SUCCESS;
}
+/**
+ * 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: VOS_STATUS_SUCCESS for success or error code.
+ */
+static VOS_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 VOS_STATUS_E_INVAL;
+ }
+
+ if (!wma_handle) {
+ WMA_LOGE(FL("WMA context is invald!"));
+ return VOS_STATUS_E_INVAL;
+ }
+
+ if (filter->filter_type == SME_ACTION_FRAME_RANDOM_MAC_SET) {
+ intr = &wma_handle->interfaces[filter->session_id];
+ /* command is in progess */
+ if(intr->action_frame_filter != NULL) {
+ WMA_LOGE(FL("previous action frame req is pending"));
+ return VOS_STATUS_SUCCESS;
+ }
+
+ filter_bkup = adf_os_mem_alloc(NULL, sizeof(*filter));
+ if (!filter_bkup) {
+ WMA_LOGE(
+ FL("action frame filter mem alloc failed"));
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ adf_os_mem_set(filter_bkup, 0, sizeof(*filter));
+ filter_bkup->session_id = filter->session_id;
+ filter_bkup->callback = filter->callback;
+ filter_bkup->filter_type = filter->filter_type;
+ filter_bkup->context = filter->context;
+
+ vos_mem_copy(filter_bkup->mac_addr, filter->mac_addr,
+ VOS_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 VOS_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;
+ 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) {
+ adf_os_mem_free(filter_bkup);
+ intr->action_frame_filter = NULL;
+ }
+ return VOS_STATUS_E_FAILURE;
+ }
+
+ return VOS_STATUS_SUCCESS;
+}
+
/*
* function : wma_mc_process_msg
* Description :
@@ -33358,6 +33513,11 @@ VOS_STATUS wma_mc_process_msg(v_VOID_t *vos_context, vos_msg_t *msg)
case SIR_HAL_POWER_DEBUG_STATS_REQ:
wma_process_power_debug_stats_req(wma_handle);
break;
+ case WDA_ACTION_FRAME_RANDOM_MAC:
+ wma_process_action_frame_random_mac(wma_handle,
+ (struct action_frame_random_filter *)msg->bodyptr);
+ vos_mem_free(msg->bodyptr);
+ break;
default:
WMA_LOGD("unknow msg type %x", msg->type);
/* Do Nothing? MSG Body should be freed at here */
diff --git a/CORE/SERVICES/WMA/wma.h b/CORE/SERVICES/WMA/wma.h
index 21eaeef546e9..2332d0156c04 100644
--- a/CORE/SERVICES/WMA/wma.h
+++ b/CORE/SERVICES/WMA/wma.h
@@ -646,7 +646,7 @@ struct wma_txrx_node {
uint8_t wep_default_key_idx;
bool is_vdev_valid;
uint16_t channelwidth;
-
+ struct action_frame_random_filter *action_frame_filter;
};
#if defined(QCA_WIFI_FTM)
diff --git a/CORE/SME/inc/sme_Api.h b/CORE/SME/inc/sme_Api.h
index 1faabd332c6a..b9a6c028cdf2 100644
--- a/CORE/SME/inc/sme_Api.h
+++ b/CORE/SME/inc/sme_Api.h
@@ -4764,4 +4764,38 @@ eHalStatus sme_power_debug_stats_req(tHalHandle hal, void (*callback_fn)
(struct power_stats_response *response,
void *context), void *power_stats_context);
#endif
+
+/**
+ * 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
+ * @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.
+ */
+eHalStatus sme_set_random_mac(tHalHandle hal,
+ action_frame_random_filter_callback callback,
+ uint32_t session_id, uint8_t *random_mac,
+ 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
+ *
+ * This function is used to clear the randmom mac address filters
+ * which are set with sme_set_random_mac
+ *
+ * Return: eHalStatus enumeration.
+ */
+eHalStatus sme_clear_random_mac(tHalHandle hal, uint32_t session_id,
+ uint8_t *random_mac);
+
#endif //#if !defined( __SME_API_H )
diff --git a/CORE/SME/src/sme_common/sme_Api.c b/CORE/SME/src/sme_common/sme_Api.c
index e89fedf2dcd7..d2fa3d2c2d37 100644
--- a/CORE/SME/src/sme_common/sme_Api.c
+++ b/CORE/SME/src/sme_common/sme_Api.c
@@ -20260,3 +20260,97 @@ eHalStatus sme_update_sub20_channel_width(tHalHandle hal_handle,
return status;
}
#endif
+
+eHalStatus sme_set_random_mac(tHalHandle hal,
+ action_frame_random_filter_callback callback,
+ uint32_t session_id, uint8_t *random_mac,
+ void *context)
+{
+
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+ vos_msg_t vos_msg;
+ struct action_frame_random_filter *filter;
+
+ filter = vos_mem_malloc(sizeof(*filter));
+
+ if (!filter) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to alloc random mac filter"));
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_zero(filter, sizeof(*filter));
+
+ filter->session_id = session_id;
+ filter->filter_type = SME_ACTION_FRAME_RANDOM_MAC_SET;
+ filter->callback = callback;
+ filter->context = context;
+ vos_mem_copy(filter->mac_addr, random_mac, VOS_MAC_ADDR_SIZE);
+
+ status = sme_AcquireGlobalLock(&mac_ctx->sme);
+ if (status == eHAL_STATUS_SUCCESS) {
+ /* Serialize the req through MC thread */
+ vos_msg.bodyptr = filter;
+ vos_msg.type = WDA_ACTION_FRAME_RANDOM_MAC;
+ vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("action frame set random mac msg fail"));
+ status = eHAL_STATUS_FAILURE;
+ vos_mem_free(filter);
+ }
+ sme_ReleaseGlobalLock(&mac_ctx->sme);
+ } else {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("sme_AcquireGlobalLock failed"));
+ vos_mem_free(filter);
+ }
+ return status;
+}
+
+eHalStatus sme_clear_random_mac(tHalHandle hal, uint32_t session_id,
+ uint8_t *random_mac)
+{
+
+ eHalStatus status = eHAL_STATUS_SUCCESS;
+ VOS_STATUS vos_status = VOS_STATUS_SUCCESS;
+ tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal);
+ vos_msg_t vos_msg;
+ struct action_frame_random_filter *filter;
+
+ filter = vos_mem_malloc(sizeof(*filter));
+
+ if (!filter) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("Failed to alloc random mac filter"));
+ return eHAL_STATUS_FAILED_ALLOC;
+ }
+ vos_mem_zero(filter, sizeof(*filter));
+
+ filter->session_id = session_id;
+ filter->filter_type = SME_ACTION_FRAME_RANDOM_MAC_CLEAR;
+ vos_mem_copy(filter->mac_addr, random_mac, VOS_MAC_ADDR_SIZE);
+
+ status = sme_AcquireGlobalLock(&mac_ctx->sme);
+ if (status == eHAL_STATUS_SUCCESS) {
+ /* Serialize the req through MC thread */
+ vos_msg.bodyptr = filter;
+ vos_msg.type = WDA_ACTION_FRAME_RANDOM_MAC;
+ vos_status = vos_mq_post_message(VOS_MQ_ID_WDA, &vos_msg);
+
+ if (!VOS_IS_STATUS_SUCCESS(vos_status)) {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("action frame clear random mac msg fail"));
+ status = eHAL_STATUS_FAILURE;
+ vos_mem_free(filter);
+ }
+ sme_ReleaseGlobalLock(&mac_ctx->sme);
+ } else {
+ VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR,
+ FL("sme_AcquireGlobalLock failed"));
+ vos_mem_free(filter);
+ }
+ return status;
+}
diff --git a/CORE/SYS/legacy/src/utils/src/macTrace.c b/CORE/SYS/legacy/src/utils/src/macTrace.c
index ea7bb57b530f..21e0ad168e25 100644
--- a/CORE/SYS/legacy/src/utils/src/macTrace.c
+++ b/CORE/SYS/legacy/src/utils/src/macTrace.c
@@ -1000,6 +1000,7 @@ tANI_U8* macTraceGetWdaMsgString(tANI_U16 wdaMsg)
CASE_RETURN_STRING(WDA_SET_MIB_STATS_ENABLE);
CASE_RETURN_STRING(WDA_SET_MIB_STATS_DISABLE);
CASE_RETURN_STRING(SIR_HAL_POWER_DEBUG_STATS_REQ);
+ CASE_RETURN_STRING(WDA_ACTION_FRAME_RANDOM_MAC);
default:
return((tANI_U8*) "UNKNOWN");
break;
diff --git a/CORE/WDA/inc/wlan_qct_wda.h b/CORE/WDA/inc/wlan_qct_wda.h
index 5fa36324979a..a4569bb524bd 100644
--- a/CORE/WDA/inc/wlan_qct_wda.h
+++ b/CORE/WDA/inc/wlan_qct_wda.h
@@ -1107,6 +1107,7 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb);
#define WDA_UPDATE_STA_INACTIVITY_TIMEOUT SIR_HAL_STA_INACTIVITY_TIMEOUT
+#define WDA_ACTION_FRAME_RANDOM_MAC SIR_HAL_ACTION_FRAME_RANDOM_MAC
tSirRetStatus wdaPostCtrlMsg(tpAniSirGlobal pMac, tSirMsgQ *pMsg);