qcacmn: Support roam sync ind in CM

Add support for roam sync indication in
connection manager.

Change-Id: I750403aa0dfa6c615f9bca832898c63af608d28d
CRs-Fixed: 2901863
This commit is contained in:
Amruta Kulkarni
2021-03-17 14:46:03 -07:00
committed by snandini
parent 80d5b0dc18
commit 5c1ca03ebe
13 changed files with 512 additions and 32 deletions

View File

@@ -276,9 +276,9 @@ struct osif_cm_ops {
#ifdef CONN_MGR_ADV_FEATURE
osif_cm_netif_queue_ctrl_cb netif_queue_control_cb;
os_if_cm_napi_serialize_ctrl_cb napi_serialize_control_cb;
osif_cm_save_gtk_cb save_gtk_cb;
#endif
#ifdef WLAN_FEATURE_FILS_SK
osif_cm_save_gtk_cb save_gtk_cb;
osif_cm_set_hlp_data_cb set_hlp_data_cb;
#endif
};
@@ -343,9 +343,7 @@ QDF_STATUS osif_cm_netif_queue_ind(struct wlan_objmgr_vdev *vdev,
* Return: QDF_STATUS
*/
QDF_STATUS osif_cm_napi_serialize(bool action);
#endif
#ifdef WLAN_FEATURE_FILS_SK
/**
* osif_cm_save_gtk() - Function to save gtk in legacy module
* @vdev: vdev pointer
@@ -358,7 +356,9 @@ QDF_STATUS osif_cm_napi_serialize(bool action);
*/
QDF_STATUS osif_cm_save_gtk(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *rsp);
#endif
#ifdef WLAN_FEATURE_FILS_SK
/**
* osif_cm_set_hlp_data() - Function to set hlp data for dhcp in legacy module
* @dev: Pointer to net device

View File

@@ -28,6 +28,10 @@
#include <osif_cm_util.h>
#include <wlan_cfg80211.h>
#include <wlan_cfg80211_scan.h>
#ifdef CONN_MGR_ADV_FEATURE
#include "wlan_mlme_ucfg_api.h"
#endif
#include "wlan_crypto_global_api.h"
#ifdef CONN_MGR_ADV_FEATURE
#ifdef WLAN_FEATURE_FILS_SK
@@ -85,6 +89,291 @@ static inline void osif_roamed_ind(struct net_device *dev,
}
#endif
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
#ifdef WLAN_FEATURE_FILS_SK
/**
* wlan_hdd_add_fils_params_roam_auth_event() - Adds FILS params in roam auth
* @skb: SK buffer
* @roam_info: Roam info
*
* API adds fils params[pmk, pmkid, next sequence number] to roam auth event
*
* Return: zero on success, error code on failure
*/
static int
osif_add_fils_params_roam_auth_event(struct sk_buff *skb,
struct wlan_roam_sync_info *roam_info)
{
if (roam_info->pmk_len &&
nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMK,
roam_info->pmk_len, roam_info->pmk)) {
osif_err("pmk send fail");
return -EINVAL;
}
if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PMKID,
PMKID_LEN, roam_info->pmkid)) {
osif_err("pmkid send fail");
return -EINVAL;
}
osif_debug("Update ERP Seq Num %d, Next ERP Seq Num %d",
roam_info->update_erp_next_seq_num,
roam_info->next_erp_seq_num);
if (roam_info->update_erp_next_seq_num &&
nla_put_u16(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_FILS_ERP_NEXT_SEQ_NUM,
roam_info->next_erp_seq_num)) {
osif_err("ERP seq num send fail");
return -EINVAL;
}
return 0;
}
#else
static inline int
osif_add_fils_params_roam_auth_event(struct sk_buff *skb,
struct wlan_roam_sync_info *roam_info)
{
return 0;
}
#endif
/**
* osif_get_roam_reason() - convert wmi roam reason to
* enum qca_roam_reason
* @roam_scan_trigger: wmi roam scan trigger ID
*
* Return: Meaningful qca_roam_reason from enum WMI_ROAM_TRIGGER_REASON_ID
*/
static enum qca_roam_reason osif_get_roam_reason(uint16_t roam_scan_trigger)
{
switch (roam_scan_trigger) {
case ROAM_TRIGGER_REASON_PER:
return QCA_ROAM_REASON_PER;
case ROAM_TRIGGER_REASON_BMISS:
return QCA_ROAM_REASON_BEACON_MISS;
case ROAM_TRIGGER_REASON_LOW_RSSI:
case ROAM_TRIGGER_REASON_BACKGROUND:
return QCA_ROAM_REASON_POOR_RSSI;
case ROAM_TRIGGER_REASON_HIGH_RSSI:
return QCA_ROAM_REASON_BETTER_RSSI;
case ROAM_TRIGGER_REASON_DENSE:
return QCA_ROAM_REASON_CONGESTION;
case ROAM_TRIGGER_REASON_FORCED:
return QCA_ROAM_REASON_USER_TRIGGER;
case ROAM_TRIGGER_REASON_BTM:
return QCA_ROAM_REASON_BTM;
case ROAM_TRIGGER_REASON_BSS_LOAD:
return QCA_ROAM_REASON_BSS_LOAD;
default:
return QCA_ROAM_REASON_UNKNOWN;
}
return QCA_ROAM_REASON_UNKNOWN;
}
/**
* osif_send_roam_auth_event() - API to send roam auth event response to kernel
* @vdev: vdev pointer
* @osif_priv: OS private structure of vdev
* @rsp: Connection manager response
*
* This is called when wlan driver needs to send the roaming and
* authorization information after roaming.
*
* The information that would be sent is the request RSN IE, response
* RSN IE and BSSID of the newly roamed AP.
*
* If the Authorized status is authenticated, then additional parameters
* like PTK's KCK and KEK and Replay Counter would also be passed to the
* supplicant.
*
* The supplicant upon receiving this event would ignore the legacy
* cfg80211_roamed call and use the entire information from this event.
* The cfg80211_roamed should still co-exist since the kernel will
* make use of the parameters even if the supplicant ignores it.
*
*
* Context: Any context.
* Return: int
*/
static int osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
struct vdev_osif_priv *osif_priv,
struct wlan_cm_connect_resp *rsp,
const uint8_t *req_ie,
size_t req_ie_len, const uint8_t *resp_ie,
size_t resp_ie_len)
{
struct wlan_objmgr_psoc *psoc;
uint32_t fils_params_len;
struct sk_buff *skb = NULL;
struct wlan_roam_sync_info *roaming_info;
int status;
int32_t akm;
bool roam_offload_enable;
psoc = wlan_vdev_get_psoc(vdev);
ucfg_mlme_get_roaming_offload(psoc, &roam_offload_enable);
if (!roam_offload_enable)
return 0;
roaming_info = rsp->roaming_info;
/*
* PMK is sent from FW in Roam Synch Event for FILS Roaming.
* In that case, add three more NL attributes.ie. PMK, PMKID
* and ERP next sequence number. Add corresponding lengths
* with 3 extra NL message headers for each of the
* aforementioned params.
*/
fils_params_len = roaming_info->pmk_len + PMKID_LEN +
sizeof(uint16_t) + (3 * NLMSG_HDRLEN);
skb = cfg80211_vendor_event_alloc(osif_priv->wdev->wiphy,
osif_priv->wdev,
ETH_ALEN + req_ie_len +
resp_ie_len +
sizeof(uint8_t) + REPLAY_CTR_LEN +
KCK_KEY_LEN + roaming_info->kek_len +
sizeof(uint16_t) + sizeof(uint8_t) +
(9 * NLMSG_HDRLEN) + fils_params_len,
QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_ROAM_AUTH_INDEX,
GFP_KERNEL);
if (!skb) {
osif_err("cfg80211_vendor_event_alloc failed");
return -1;
}
if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_BSSID,
ETH_ALEN, rsp->bssid.bytes) ||
nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REQ_IE,
req_ie_len, req_ie) ||
nla_put(skb, QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_RESP_IE,
resp_ie_len, resp_ie)) {
osif_err("nla put fail");
goto nla_put_failure;
}
if (roaming_info->auth_status == ROAM_AUTH_STATUS_AUTHENTICATED) {
osif_debug("Include Auth Params TLV's");
if (nla_put_u8(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
true)) {
osif_err("nla put fail");
goto nla_put_failure;
}
akm = wlan_crypto_get_param(vdev,
WLAN_CRYPTO_PARAM_KEY_MGMT);
/* if FT or CCKM connection: dont send replay counter */
if (!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X) &&
!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_PSK) &&
!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_SAE) &&
!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_FT_IEEE8021X_SHA384) &&
!QDF_HAS_PARAM(akm, WLAN_CRYPTO_KEY_MGMT_CCKM) &&
nla_put(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_KEY_REPLAY_CTR,
REPLAY_CTR_LEN,
roaming_info->replay_ctr)) {
osif_err("non FT/non CCKM connection");
osif_err("failed to send replay counter");
goto nla_put_failure;
}
if (roaming_info->kek_len > MAX_KEK_LENGTH ||
nla_put(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KCK,
roaming_info->kck_len, roaming_info->kck) ||
nla_put(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_PTK_KEK,
roaming_info->kek_len, roaming_info->kek)) {
osif_err("nla put fail, kek_len %d",
roaming_info->kek_len);
goto nla_put_failure;
}
if (nla_put_u16(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_REASON,
osif_get_roam_reason(roaming_info->roam_reason))) {
osif_err("roam reason send failure");
goto nla_put_failure;
}
status = osif_add_fils_params_roam_auth_event(skb,
roaming_info);
if (status)
goto nla_put_failure;
/*
* Save the gtk rekey parameters in HDD STA context. They will
* be used next time when host enables GTK offload and goes
* into power save state.
*/
osif_cm_save_gtk(vdev, rsp);
osif_debug("roam_info_ptr->replay_ctr 0x%llx",
*((uint64_t *)roaming_info->replay_ctr));
} else {
osif_debug("No Auth Params TLV's");
if (nla_put_u8(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_AUTHORIZED,
false)) {
osif_err("nla put fail");
goto nla_put_failure;
}
}
osif_debug("Auth Status = %d Subnet Change Status = %d",
roaming_info->auth_status,
roaming_info->subnet_change_status);
/*
* Add subnet change status if subnet has changed
* 0 = unchanged
* 1 = changed
* 2 = unknown
*/
if (roaming_info->subnet_change_status) {
if (nla_put_u8(skb,
QCA_WLAN_VENDOR_ATTR_ROAM_AUTH_SUBNET_STATUS,
roaming_info->subnet_change_status)) {
osif_err("nla put fail");
goto nla_put_failure;
}
}
cfg80211_vendor_event(skb, GFP_KERNEL);
return 0;
nla_put_failure:
kfree_skb(skb);
return -1;
}
#else
static inline int
osif_send_roam_auth_event(struct wlan_objmgr_vdev *vdev,
struct vdev_osif_priv *osif_priv,
struct wlan_cm_connect_resp *rsp,
const uint8_t *req_ie,
size_t req_ie_len, const uint8_t *resp_ie,
size_t resp_ie_len)
{
return 0;
}
#endif
static void osif_cm_get_reassoc_req_ie_data(struct element_info *assoc_req,
size_t *ie_data_len,
const uint8_t **ie_data_ptr)
{
/* Validate IE and length */
if (!assoc_req->len || !assoc_req->ptr ||
assoc_req->len <= WLAN_REASSOC_REQ_IES_OFFSET)
return;
*ie_data_len = assoc_req->len - WLAN_REASSOC_REQ_IES_OFFSET;
*ie_data_ptr = assoc_req->ptr + WLAN_REASSOC_REQ_IES_OFFSET;
}
void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
struct vdev_osif_priv *osif_priv,
struct wlan_cm_connect_resp *rsp)
@@ -96,10 +385,18 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
const uint8_t *rsp_ie = NULL;
struct cfg80211_bss *bss;
struct ieee80211_channel *chan;
struct wlan_objmgr_psoc *psoc;
bool roam_offload = false;
if (QDF_IS_STATUS_ERROR(rsp->connect_status))
return;
psoc = wlan_vdev_get_psoc(vdev);
if (!psoc)
return;
ucfg_mlme_is_roam_scan_offload_enabled(psoc, &roam_offload);
chan = ieee80211_get_channel(osif_priv->wdev->wiphy,
rsp->freq);
bss = wlan_cfg80211_get_bss(osif_priv->wdev->wiphy, chan,
@@ -107,15 +404,17 @@ void osif_indicate_reassoc_results(struct wlan_objmgr_vdev *vdev,
rsp->ssid.length);
if (!bss)
osif_warn("not able to find bss");
osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
&req_len, &req_ie);
if (!roam_offload || rsp->is_ft)
osif_cm_get_assoc_req_ie_data(&rsp->connect_ies.assoc_req,
&req_len, &req_ie);
else
osif_cm_get_reassoc_req_ie_data(&rsp->connect_ies.assoc_req,
&req_len, &req_ie);
osif_cm_get_assoc_rsp_ie_data(&rsp->connect_ies.assoc_rsp,
&rsp_len, &rsp_ie);
osif_roamed_ind(dev, bss, req_ie, req_len, rsp_ie, rsp_len);
osif_cm_save_gtk(vdev, rsp);
/* Add osif_send_roam_auth_event (wlan_hdd_send_roam_auth_event) */
osif_send_roam_auth_event(vdev, osif_priv, rsp, req_ie, req_len, rsp_ie,
rsp_len);
osif_update_fils_hlp_data(dev, vdev, rsp);
}

View File

@@ -336,7 +336,7 @@ osif_cm_roam_start_cb(struct wlan_objmgr_vdev *vdev)
* @vdev: vdev pointer
*
* This callback indicates os_if that roaming has been aborted
* so that os_if can stop all the activity on this connection
* so that os_if can resume all the activity on this connection
*
* Return: QDF_STATUS
*/
@@ -348,6 +348,42 @@ osif_cm_roam_abort_cb(struct wlan_objmgr_vdev *vdev)
WLAN_WAKE_ALL_NETIF_QUEUE,
WLAN_CONTROL_PATH);
}
/**
* osif_cm_roam_sync_cb() - Roam sync callback
* @vdev: vdev pointer
*
* This callback indicates os_if that roam sync ind received
* so that os_if can stop all the activity on this connection
*
* Return: QDF_STATUS
*/
static QDF_STATUS
osif_cm_roam_sync_cb(struct wlan_objmgr_vdev *vdev)
{
osif_cm_napi_serialize(true);
return osif_cm_netif_queue_ind(vdev,
WLAN_STOP_ALL_NETIF_QUEUE,
WLAN_CONTROL_PATH);
}
/**
* osif_cm_roam_cmpl_cb() - Roam sync complete callback
* @vdev: vdev pointer
* @rsp: connect rsp
*
* This callback indicates os_if that roam sync is complete
* so that os_if can stop all the activity on this connection
*
* Return: QDF_STATUS
*/
static QDF_STATUS
osif_cm_roam_cmpl_cb(struct wlan_objmgr_vdev *vdev)
{
return osif_cm_napi_serialize(false);
}
#endif
static struct mlme_cm_ops cm_ops = {
@@ -359,6 +395,8 @@ static struct mlme_cm_ops cm_ops = {
#ifdef WLAN_FEATURE_ROAM_OFFLOAD
.mlme_cm_roam_start_cb = osif_cm_roam_start_cb,
.mlme_cm_roam_abort_cb = osif_cm_roam_abort_cb,
.mlme_cm_roam_sync_cb = osif_cm_roam_sync_cb,
.mlme_cm_roam_cmpl_cb = osif_cm_roam_cmpl_cb,
#endif
};
@@ -472,8 +510,7 @@ QDF_STATUS osif_cm_napi_serialize(bool action)
return ret;
}
#endif
#ifdef WLAN_FEATURE_FILS_SK
QDF_STATUS osif_cm_save_gtk(struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *rsp)
{
@@ -487,7 +524,9 @@ QDF_STATUS osif_cm_save_gtk(struct wlan_objmgr_vdev *vdev,
return ret;
}
#endif
#ifdef WLAN_FEATURE_FILS_SK
QDF_STATUS osif_cm_set_hlp_data(struct net_device *dev,
struct wlan_objmgr_vdev *vdev,
struct wlan_cm_connect_resp *rsp)