qcacld-3.0: Add support for sae auth retry

Host retransmits WPA3 SAE authentication frames after 1 second
if there is no response for previous auth frames from AP.
Host keep retransmitting SAE auth frames for max WLAN_SAE_AUTH_RETRY
times.

Change-Id: I1be0bd5354586518781876646b063592e667b0bb
CRs-Fixed: 2716719
This commit is contained in:
Abhishek Ambure 2020-06-29 11:12:55 +05:30 • committed by nshrivas
commit e5b5a03aeb
8 changed files with 237 additions and 31 deletions

View file

@ -59,6 +59,16 @@ struct wlan_disconnect_info {
bool from_ap;
};
/**
* struct sae_auth_retry - SAE auth retry Information
* @sae_auth_max_retry: Max number of sae auth retries
* @sae_auth: SAE auth frame information
*/
struct sae_auth_retry {
uint8_t sae_auth_max_retry;
struct wlan_ies sae_auth;
};
/**
* struct peer_mlme_priv_obj - peer MLME component object
* @last_pn_valid if last PN is valid
@ -147,6 +157,7 @@ struct wlan_mlme_roam {
* @vdev_stop_type: vdev stop type request
* @roam_off_state: Roam offload state
* @bigtk_vdev_support: BIGTK feature support for this vdev (SAP)
* @sae_auth_retry: SAE auth retry information
*/
struct mlme_legacy_priv {
bool chan_switch_in_progress;
@ -165,6 +176,7 @@ struct mlme_legacy_priv {
uint32_t vdev_stop_type;
struct wlan_mlme_roam mlme_roam;
bool bigtk_vdev_support;
struct sae_auth_retry sae_retry;
};
/**
@ -270,6 +282,22 @@ struct wlan_mlme_psoc_ext_obj *mlme_get_psoc_ext_obj_fl(struct wlan_objmgr_psoc
const char *func,
uint32_t line);
/**
* mlme_get_sae_auth_retry() - Get sae_auth_retry pointer
* @vdev: vdev pointer
*
* Return: Pointer to struct sae_auth_retry or NULL
*/
struct sae_auth_retry *mlme_get_sae_auth_retry(struct wlan_objmgr_vdev *vdev);
/**
* mlme_free_sae_auth_retry() - Free the SAE auth info
* @vdev: vdev pointer
*
* Return: None
*/
void mlme_free_sae_auth_retry(struct wlan_objmgr_vdev *vdev);
/**
* mlme_set_self_disconnect_ies() - Set diconnect IEs configured from userspace
* @vdev: vdev pointer

View file

@ -2253,6 +2253,36 @@ QDF_STATUS mlme_cfg_on_psoc_enable(struct wlan_objmgr_psoc *psoc)
return status;
}
struct sae_auth_retry *mlme_get_sae_auth_retry(struct wlan_objmgr_vdev *vdev)
{
struct mlme_legacy_priv *mlme_priv;
mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
if (!mlme_priv) {
mlme_legacy_err("vdev legacy private object is NULL");
return NULL;
}
return &mlme_priv->sae_retry;
}
void mlme_free_sae_auth_retry(struct wlan_objmgr_vdev *vdev)
{
struct mlme_legacy_priv *mlme_priv;
mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev);
if (!mlme_priv) {
mlme_legacy_err("vdev legacy private object is NULL");
return;
}
mlme_priv->sae_retry.sae_auth_max_retry = 0;
if (mlme_priv->sae_retry.sae_auth.data)
qdf_mem_free(mlme_priv->sae_retry.sae_auth.data);
mlme_priv->sae_retry.sae_auth.data = NULL;
mlme_priv->sae_retry.sae_auth.len = 0;
}
void mlme_set_self_disconnect_ies(struct wlan_objmgr_vdev *vdev,
struct wlan_ies *ie)
{

View file

@ -973,6 +973,7 @@ QDF_STATUS vdevmgr_mlme_ext_hdl_destroy(struct vdev_mlme_obj *vdev_mlme)
mlme_free_self_disconnect_ies(vdev_mlme->vdev);
mlme_free_peer_disconnect_ies(vdev_mlme->vdev);
mlme_free_sae_auth_retry(vdev_mlme->vdev);
qdf_mem_free(vdev_mlme->ext_vdev_ptr);
vdev_mlme->ext_vdev_ptr = NULL;

View file

@ -338,6 +338,22 @@ static void lim_external_auth_add_pre_auth_node(struct mac_context *mac_ctx,
lim_add_pre_auth_node(mac_ctx, auth_node);
}
void lim_sae_auth_cleanup_retry(struct mac_context *mac_ctx,
uint8_t vdev_id)
{
struct pe_session *pe_session;
pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
if (!pe_session) {
pe_err("session not found for given vdev_id %d", vdev_id);
return;
}
pe_debug("sae auth cleanup for vdev_id %d", vdev_id);
lim_deactivate_and_change_timer(mac_ctx, eLIM_AUTH_RETRY_TIMER);
mlme_free_sae_auth_retry(pe_session->vdev);
}
/**
* lim_process_sae_auth_frame()-Process SAE authentication frame
* @mac_ctx: MAC context
@ -353,6 +369,7 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
uint32_t frame_len;
uint8_t *body_ptr;
enum rxmgmt_flags rx_flags = RXMGMT_FLAG_NONE;
struct sae_auth_retry *sae_retry;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
@ -389,6 +406,12 @@ static void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
}
}
sae_retry = mlme_get_sae_auth_retry(pe_session->vdev);
if (LIM_IS_STA_ROLE(pe_session) && sae_retry &&
sae_retry->sae_auth.data)
lim_sae_auth_cleanup_retry(mac_ctx,
pe_session->vdev_id);
lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
(uint8_t *)mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr),

View file

@ -1627,6 +1627,36 @@ static void lim_process_periodic_join_probe_req_timer(struct mac_context *mac_ct
}
}
static void lim_handle_sae_auth_timeout(struct mac_context *mac_ctx,
struct pe_session *session_entry)
{
struct sae_auth_retry *sae_retry;
sae_retry = mlme_get_sae_auth_retry(session_entry->vdev);
if (!(sae_retry && sae_retry->sae_auth.data)) {
pe_debug("sae auth frame is not buffered vdev id %d",
session_entry->vdev_id);
return;
}
pe_debug("retry sae auth for seq num %d vdev id %d",
mac_ctx->mgmtSeqNum, session_entry->vdev_id);
lim_send_frame(mac_ctx, session_entry->vdev_id,
sae_retry->sae_auth.data, sae_retry->sae_auth.len);
sae_retry->sae_auth_max_retry--;
/* Activate Auth Retry timer if max_retries are not done */
if (!sae_retry->sae_auth_max_retry || (tx_timer_activate(
&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) !=
TX_SUCCESS))
goto free_and_deactivate_timer;
return;
free_and_deactivate_timer:
lim_sae_auth_cleanup_retry(mac_ctx, session_entry->vdev_id);
}
/**
* lim_process_auth_retry_timer()- function to Retry Auth when auth timeout
* occurs
@ -1639,15 +1669,19 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
struct pe_session *session_entry;
tAniAuthType auth_type;
tLimTimers *lim_timers = &mac_ctx->lim.lim_timers;
uint16_t vdev_id =
uint16_t pe_session_id =
lim_timers->g_lim_periodic_auth_retry_timer.sessionId;
session_entry = pe_find_session_by_session_id(mac_ctx, vdev_id);
session_entry = pe_find_session_by_session_id(mac_ctx, pe_session_id);
if (!session_entry) {
pe_err("session does not exist for vdev_id: %d", vdev_id);
pe_err("session does not exist for pe_session_id: %d",
pe_session_id);
return;
}
/** For WPA3 SAE gLimAuthFailureTimer is not running hence
* we don't enter in below "if" block in case of wpa3 sae
*/
if (tx_timer_running(&mac_ctx->lim.lim_timers.gLimAuthFailureTimer) &&
(session_entry->limMlmState == eLIM_MLM_WT_AUTH_FRAME2_STATE) &&
(LIM_AUTH_ACK_RCD_SUCCESS != mac_ctx->auth_ack_status)) {
@ -1684,12 +1718,14 @@ static void lim_process_auth_retry_timer(struct mac_context *mac_ctx)
/* Activate Auth Retry timer */
if (tx_timer_activate
(&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer)
!= TX_SUCCESS) {
!= TX_SUCCESS)
pe_err("could not activate Auth Retry failure timer");
return;
}
return;
}
return;
/* Auth retry time out for wpa3 sae */
lim_handle_sae_auth_timeout(mac_ctx, session_entry);
} /*** lim_process_auth_retry_timer() ***/
void lim_process_auth_failure_timeout(struct mac_context *mac_ctx)

View file

@ -5294,28 +5294,28 @@ error_delba:
return qdf_status;
}
#define WLAN_SAE_AUTH_TIMEOUT 1000
#define WLAN_SAE_AUTH_RETRY 1
/**
* lim_tx_mgmt_frame() - Transmits Auth mgmt frame
* @mac_ctx Pointer to Global MAC structure
* @mb_msg: Received message info
* @vdev_id: vdev id
* @msg_len: Received message length
* @packet: Packet to be transmitted
* @frame: Received frame
*
* Return: None
*/
static void lim_tx_mgmt_frame(struct mac_context *mac_ctx,
struct sir_mgmt_msg *mb_msg, uint32_t msg_len,
void *packet, uint8_t *frame)
static void lim_tx_mgmt_frame(struct mac_context *mac_ctx, uint8_t vdev_id,
uint32_t msg_len, void *packet, uint8_t *frame)
{
tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data;
tpSirMacFrameCtl fc = (tpSirMacFrameCtl)frame;
QDF_STATUS qdf_status;
uint8_t vdev_id = 0;
struct pe_session *session;
uint16_t auth_ack_status;
enum rateid min_rid = RATEID_DEFAULT;
vdev_id = mb_msg->vdev_id;
session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
if (!session) {
cds_packet_free((void *)packet);
@ -5349,35 +5349,99 @@ static void lim_tx_mgmt_frame(struct mac_context *mac_ctx,
}
}
void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx,
struct scheduler_msg *msg)
static void
lim_handle_sae_auth_retry(struct mac_context *mac_ctx, uint8_t vdev_id,
uint8_t *frame, uint32_t frame_len)
{
struct pe_session *session;
struct sae_auth_retry *sae_retry;
session = pe_find_session_by_vdev_id(mac_ctx, vdev_id);
if (!session) {
pe_err("session not found for given vdev_id %d",
vdev_id);
return;
}
sae_retry = mlme_get_sae_auth_retry(session->vdev);
if (!sae_retry) {
pe_err("sae retry pointer is NULL for vdev_id %d",
vdev_id);
return;
}
if (sae_retry->sae_auth.data)
lim_sae_auth_cleanup_retry(mac_ctx, vdev_id);
sae_retry->sae_auth.data = qdf_mem_malloc(frame_len);
if (!sae_retry->sae_auth.data) {
pe_err("failed to alloc memory for sae auth");
return;
}
pe_debug("SAE auth frame queued vdev_id %d seq_num %d",
vdev_id, mac_ctx->mgmtSeqNum);
qdf_mem_copy(sae_retry->sae_auth.data, frame, frame_len);
mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer.sessionId =
session->peSessionId;
sae_retry->sae_auth.len = frame_len;
sae_retry->sae_auth_max_retry = WLAN_SAE_AUTH_RETRY;
tx_timer_change(
&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer,
SYS_MS_TO_TICKS(WLAN_SAE_AUTH_TIMEOUT), 0);
/* Activate Auth Retry timer */
if (tx_timer_activate(
&mac_ctx->lim.lim_timers.g_lim_periodic_auth_retry_timer) !=
TX_SUCCESS) {
pe_err("failed to start periodic auth retry timer");
lim_sae_auth_cleanup_retry(mac_ctx, vdev_id);
}
}
void lim_send_frame(struct mac_context *mac_ctx, uint8_t vdev_id, uint8_t *buf,
uint16_t buf_len)
{
struct sir_mgmt_msg *mb_msg = (struct sir_mgmt_msg *)msg->bodyptr;
uint32_t msg_len;
tpSirMacFrameCtl fc = (tpSirMacFrameCtl) mb_msg->data;
uint8_t vdev_id;
QDF_STATUS qdf_status;
uint8_t *frame;
void *packet;
tpSirMacMgmtHdr mac_hdr;
tpSirMacFrameCtl fc = (tpSirMacFrameCtl)buf;
tpSirMacMgmtHdr mac_hdr = (tpSirMacMgmtHdr)buf;
msg_len = mb_msg->msg_len - sizeof(*mb_msg);
pe_debug("sending fc->type: %d fc->subType: %d",
fc->type, fc->subType);
vdev_id = mb_msg->vdev_id;
mac_hdr = (tpSirMacMgmtHdr)mb_msg->data;
fc->type, fc->subType);
lim_add_mgmt_seq_num(mac_ctx, mac_hdr);
qdf_status = cds_packet_alloc((uint16_t) msg_len, (void **)&frame,
(void **)&packet);
qdf_status = cds_packet_alloc(buf_len, (void **)&frame,
(void **)&packet);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
pe_err("call to bufAlloc failed for AUTH frame");
return;
}
qdf_mem_copy(frame, mb_msg->data, msg_len);
lim_tx_mgmt_frame(mac_ctx, mb_msg, msg_len, packet, frame);
qdf_mem_copy(frame, buf, buf_len);
lim_tx_mgmt_frame(mac_ctx, vdev_id, buf_len, packet, frame);
}
void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx,
struct scheduler_msg *msg)
{
struct sir_mgmt_msg *mb_msg = (struct sir_mgmt_msg *)msg->bodyptr;
uint32_t msg_len;
tpSirMacFrameCtl fc = (tpSirMacFrameCtl)mb_msg->data;
uint8_t vdev_id;
uint16_t auth_algo;
msg_len = mb_msg->msg_len - sizeof(*mb_msg);
vdev_id = mb_msg->vdev_id;
if (fc->subType == SIR_MAC_MGMT_AUTH) {
auth_algo = *(uint16_t *)(mb_msg->data +
sizeof(tSirMacMgmtHdr));
if (auth_algo == eSIR_AUTH_TYPE_SAE)
lim_handle_sae_auth_retry(mac_ctx, vdev_id,
mb_msg->data, msg_len);
}
lim_send_frame(mac_ctx, vdev_id, mb_msg->data, msg_len);
}

View file

@ -803,6 +803,7 @@ void pe_delete_session(struct mac_context *mac_ctx, struct pe_session *session)
QDF_MAC_ADDR_ARRAY(session->bssId));
lim_reset_bcn_probe_filter(mac_ctx, session);
lim_sae_auth_cleanup_retry(mac_ctx, session->vdev_id);
/* Restore default failure timeout */
if (session->defaultAuthFailureTimeout) {

View file

@ -420,6 +420,17 @@ bool lim_fill_lim_assoc_ind_params(
tpDphHashNode sta_ds,
struct pe_session *session_entry);
/**
* lim_sae_auth_cleanup_retry() - API to cleanup sae auth frmae stored
* and deactivate the timer
* @mac_ctx: Pointer to mac context
* @vdev_id: vdev id
*
* Return: none
*/
void lim_sae_auth_cleanup_retry(struct mac_context *mac_ctx,
uint8_t vdev_id);
/**
* lim_fill_sme_assoc_ind_params() - Initialize association indication
* @mac_ctx: Pointer to Global MAC structure
@ -1220,6 +1231,18 @@ void lim_process_auth_failure_timeout(struct mac_context *mac_ctx);
void lim_process_assoc_failure_timeout(struct mac_context *mac_ctx,
uint32_t msg_type);
/**
* lim_send_frame() - API to send frame
* @mac_ctx Pointer to Global MAC structure
* @vdev_id: vdev id
* @buf: Pointer to SAE auth retry frame
* @buf_len: length of frame
*
* Return: None
*/
void lim_send_frame(struct mac_context *mac_ctx, uint8_t vdev_id, uint8_t *buf,
uint16_t buf_len);
/**
* lim_send_mgmt_frame_tx() - Sends mgmt frame
* @mac_ctx Pointer to Global MAC structure