qcacld-3.0: Support SAP fast BSS transition in driver

When driver receive auth request frame with FT algorithm,
offload it to hostapd.

When driver receive (re)assoc request whith FT-PSK in RSN IE.
offload it to hostapd.

Filter FT related IE from hostapd, and append it to the end
of the (re)assoc response frame

Change-Id: Id11cce6898615bb6b0cb361ea7b23ea2014f0bae
CRs-Fixed: 4202696
Este commit está contenido en:
Ben Wang
2022-07-21 10:18:21 +08:00
cometido por Madan Koyyalamudi
padre cd67bc5cfa
commit dafdfb98ff
Se han modificado 20 ficheros con 506 adiciones y 7 borrados

Ver fichero

@@ -835,6 +835,7 @@ struct hdd_fw_txrx_stats {
* @acs_in_progress: In progress acs flag for an adapter * @acs_in_progress: In progress acs flag for an adapter
* @client_count: client count per dot11_mode * @client_count: client count per dot11_mode
* @country_ie_updated: country ie is updated or not by hdd hostapd * @country_ie_updated: country ie is updated or not by hdd hostapd
* @during_auth_offload: auth mgmt frame is offloading to hostapd
*/ */
struct hdd_ap_ctx { struct hdd_ap_ctx {
struct hdd_hostapd_state hostapd_state; struct hdd_hostapd_state hostapd_state;
@@ -855,6 +856,7 @@ struct hdd_ap_ctx {
qdf_atomic_t acs_in_progress; qdf_atomic_t acs_in_progress;
uint16_t client_count[QCA_WLAN_802_11_MODE_INVALID]; uint16_t client_count[QCA_WLAN_802_11_MODE_INVALID];
bool country_ie_updated; bool country_ie_updated;
bool during_auth_offload;
}; };
/** /**

Ver fichero

@@ -2244,6 +2244,50 @@ static inline void hdd_translate_sae_rsn_to_csr_auth(int8_t auth_suite[4],
} }
#endif #endif
void *hdd_filter_ft_info(const uint8_t *frame, size_t len,
uint32_t *ft_info_len)
{
uint32_t ft_ie_len, md_ie_len, rsn_ie_len, ie_len;
const uint8_t *rsn_ie, *md_ie, *ft_ie;
void *ft_info;
ft_ie_len = 0;
md_ie_len = 0;
rsn_ie_len = 0;
ie_len = len - DOT11F_FF_CAPABILITIES_LEN - DOT11F_FF_STATUS_LEN
- DOT11F_IE_AID_MAX_LEN - sizeof(tSirMacMgmtHdr);
rsn_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_RSN, frame, ie_len);
if (rsn_ie) {
rsn_ie_len = rsn_ie[1] + 2;
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
(void *)rsn_ie, rsn_ie_len);
}
md_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_MOBILITYDOMAIN,
frame, ie_len);
if (md_ie) {
md_ie_len = md_ie[1] + 2;
QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_HDD, QDF_TRACE_LEVEL_DEBUG,
(void *)md_ie, md_ie_len);
}
ft_ie = wlan_get_ie_ptr_from_eid(DOT11F_EID_FTINFO, frame, ie_len);
if (ft_ie)
ft_ie_len = ft_ie[1] + 2;
*ft_info_len = rsn_ie_len + md_ie_len + ft_ie_len;
ft_info = qdf_mem_malloc(*ft_info_len);
if (!ft_info)
return NULL;
if (rsn_ie_len)
qdf_mem_copy(ft_info, rsn_ie, rsn_ie_len);
if (md_ie_len)
qdf_mem_copy(ft_info + rsn_ie_len, md_ie, md_ie_len);
if (ft_ie_len)
qdf_mem_copy(ft_info + rsn_ie_len + md_ie_len,
ft_ie, ft_ie_len);
return ft_info;
}
/** /**
* hdd_translate_rsn_to_csr_auth_type() - Translate RSN to CSR auth type * hdd_translate_rsn_to_csr_auth_type() - Translate RSN to CSR auth type
* @auth_suite: auth suite * @auth_suite: auth suite

Ver fichero

@@ -20304,6 +20304,7 @@ static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
int errno; int errno;
enum wlan_crypto_cipher_type cipher; enum wlan_crypto_cipher_type cipher;
bool ft_mode = false; bool ft_mode = false;
struct hdd_ap_ctx *hdd_ap_ctx;
hdd_ctx = WLAN_HDD_GET_CTX(adapter); hdd_ctx = WLAN_HDD_GET_CTX(adapter);
@@ -20355,6 +20356,11 @@ static int wlan_hdd_add_key_vdev(mac_handle_t mac_handle,
switch (adapter->device_mode) { switch (adapter->device_mode) {
case QDF_SAP_MODE: case QDF_SAP_MODE:
case QDF_P2P_GO_MODE: case QDF_P2P_GO_MODE:
hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
if (hdd_ap_ctx->during_auth_offload) {
hdd_err("don't need install key during auth");
return -EINVAL;
}
errno = wlan_hdd_add_key_sap(adapter, pairwise, errno = wlan_hdd_add_key_sap(adapter, pairwise,
key_index, cipher); key_index, cipher);
break; break;

Ver fichero

@@ -4880,8 +4880,9 @@ int wlan_hdd_cfg80211_update_apies(struct hdd_adapter *adapter)
WLAN_EID_INTERWORKING); WLAN_EID_INTERWORKING);
wlan_hdd_add_extra_ie(adapter, genie, &total_ielen, wlan_hdd_add_extra_ie(adapter, genie, &total_ielen,
WLAN_EID_ADVERTISEMENT_PROTOCOL); WLAN_EID_ADVERTISEMENT_PROTOCOL);
wlan_hdd_add_extra_ie(adapter, genie, &total_ielen, WLAN_ELEMID_RSNXE); wlan_hdd_add_extra_ie(adapter, genie, &total_ielen, WLAN_ELEMID_RSNXE);
wlan_hdd_add_extra_ie(adapter, genie, &total_ielen,
WLAN_ELEMID_MOBILITY_DOMAIN);
#ifdef FEATURE_WLAN_WAPI #ifdef FEATURE_WLAN_WAPI
if (QDF_SAP_MODE == adapter->device_mode) { if (QDF_SAP_MODE == adapter->device_mode) {
wlan_hdd_add_extra_ie(adapter, genie, &total_ielen, wlan_hdd_add_extra_ie(adapter, genie, &total_ielen,
@@ -4918,6 +4919,8 @@ int wlan_hdd_cfg80211_update_apies(struct hdd_adapter *adapter)
&proberesp_ies_len); &proberesp_ies_len);
wlan_hdd_add_extra_ie(adapter, proberesp_ies, &proberesp_ies_len, wlan_hdd_add_extra_ie(adapter, proberesp_ies, &proberesp_ies_len,
WLAN_ELEMID_RSNXE); WLAN_ELEMID_RSNXE);
wlan_hdd_add_extra_ie(adapter, proberesp_ies, &proberesp_ies_len,
WLAN_ELEMID_MOBILITY_DOMAIN);
if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) { if (test_bit(SOFTAP_BSS_STARTED, &adapter->event_flags)) {
update_ie.ieBufferlength = proberesp_ies_len; update_ie.ieBufferlength = proberesp_ies_len;

Ver fichero

@@ -44,6 +44,20 @@ struct hdd_adapter *hdd_wlan_create_ap_dev(struct hdd_context *hdd_ctx,
enum csr_akm_type enum csr_akm_type
hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]); hdd_translate_rsn_to_csr_auth_type(uint8_t auth_suite[4]);
/**
* hdd_filter_ft_info() -
* This function to filter fast BSS transition related IE
* @frame: pointer to the input frame.
* @len: input frame length.
* @ft_info_len: store the total length of FT related IE.
*
* Return: pointer to a buffer which stored the FT related IE
* This is a malloced memory that must be freed by the caller
*/
void *hdd_filter_ft_info(const uint8_t *frame,
size_t len, uint32_t *ft_info_len);
/** /**
* hdd_softap_set_channel_change() - * hdd_softap_set_channel_change() -
* This function to support SAP channel change with CSA IE * This function to support SAP channel change with CSA IE

Ver fichero

@@ -290,6 +290,10 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
uint16_t auth_algo; uint16_t auth_algo;
QDF_STATUS qdf_status; QDF_STATUS qdf_status;
int ret; int ret;
uint32_t ft_info_len = 0;
const uint8_t *assoc_resp;
void *ft_info;
struct hdd_ap_ctx *hdd_ap_ctx;
if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) { if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
hdd_err("Command not allowed in FTM mode"); hdd_err("Command not allowed in FTM mode");
@@ -305,6 +309,7 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]);
sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); sub_type = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]);
hdd_debug("type %d, sub_type %d", type, sub_type);
/* When frame to be transmitted is auth mgmt, then trigger /* When frame to be transmitted is auth mgmt, then trigger
* sme_send_mgmt_tx to send auth frame without need for policy manager. * sme_send_mgmt_tx to send auth frame without need for policy manager.
@@ -326,6 +331,12 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
sizeof(struct wlan_frame_hdr)); sizeof(struct wlan_frame_hdr));
if (auth_algo == eSIR_AUTH_TYPE_PASN) if (auth_algo == eSIR_AUTH_TYPE_PASN)
goto off_chan_tx; goto off_chan_tx;
if ((auth_algo == eSIR_FT_AUTH) &&
(adapter->device_mode == QDF_SAP_MODE ||
adapter->device_mode == QDF_P2P_GO_MODE)) {
hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
hdd_ap_ctx->during_auth_offload = false;
}
} }
qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_SME, qdf_mtrace(QDF_MODULE_ID_HDD, QDF_MODULE_ID_SME,
@@ -335,7 +346,32 @@ static int __wlan_hdd_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
adapter->vdev_id, buf, len); adapter->vdev_id, buf, len);
if (QDF_IS_STATUS_SUCCESS(qdf_status)) if (QDF_IS_STATUS_SUCCESS(qdf_status))
return 0; return qdf_status_to_os_return(qdf_status);
else
return -EINVAL;
}
/* Only when SAP working on Fast BSS transition mode. Driver offload
* (re)assoc request to hostapd. Here driver receive (re)assoc response
* frame from hostapd.
*/
if ((adapter->device_mode == QDF_SAP_MODE ||
adapter->device_mode == QDF_P2P_GO_MODE) &&
(type == SIR_MAC_MGMT_FRAME) &&
(sub_type == SIR_MAC_MGMT_ASSOC_RSP ||
sub_type == SIR_MAC_MGMT_REASSOC_RSP)) {
assoc_resp = &((struct ieee80211_mgmt *)buf)->u.assoc_resp.variable[0];
ft_info = hdd_filter_ft_info(assoc_resp, len, &ft_info_len);
if (!ft_info || !ft_info_len)
return -EINVAL;
hdd_debug("get ft_info_len from Assoc rsp :%d", ft_info_len);
hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
qdf_status = wlansap_update_ft_info(hdd_ap_ctx->sap_context,
((struct ieee80211_mgmt *)buf)->da,
ft_info, ft_info_len, 0);
qdf_mem_free(ft_info);
if (QDF_IS_STATUS_SUCCESS(qdf_status))
return qdf_status_to_os_return(qdf_status);
else else
return -EINVAL; return -EINVAL;
} }
@@ -1064,6 +1100,7 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
bool is_pasn_auth_frame = false; bool is_pasn_auth_frame = false;
struct hdd_adapter *assoc_adapter; struct hdd_adapter *assoc_adapter;
bool eht_capab; bool eht_capab;
struct hdd_ap_ctx *hdd_ap_ctx;
hdd_debug("Frame Type = %d Frame Length = %d freq = %d", hdd_debug("Frame Type = %d Frame Length = %d freq = %d",
frame_type, frm_len, rx_freq); frame_type, frm_len, rx_freq);
@@ -1092,8 +1129,15 @@ __hdd_indicate_mgmt_frame_to_user(struct hdd_adapter *adapter,
WLAN_AUTH_FRAME_MIN_LEN)) { WLAN_AUTH_FRAME_MIN_LEN)) {
auth_algo = *(uint16_t *)(pb_frames + auth_algo = *(uint16_t *)(pb_frames +
sizeof(struct wlan_frame_hdr)); sizeof(struct wlan_frame_hdr));
if (auth_algo == eSIR_AUTH_TYPE_PASN) if (auth_algo == eSIR_AUTH_TYPE_PASN) {
is_pasn_auth_frame = true; is_pasn_auth_frame = true;
} else if (auth_algo == eSIR_FT_AUTH) {
if (adapter->device_mode == QDF_SAP_MODE ||
adapter->device_mode == QDF_P2P_GO_MODE) {
hdd_ap_ctx = WLAN_HDD_GET_AP_CTX_PTR(adapter);
hdd_ap_ctx->during_auth_offload = true;
}
}
} }
/* Get adapter from Destination mac address of the frame */ /* Get adapter from Destination mac address of the frame */

Ver fichero

@@ -1085,6 +1085,9 @@ struct assoc_ind {
const uint8_t *owe_ie; const uint8_t *owe_ie;
uint32_t owe_ie_len; uint32_t owe_ie_len;
uint16_t owe_status; uint16_t owe_status;
const uint8_t *ft_ie;
uint32_t ft_ie_len;
uint16_t ft_status;
bool need_assoc_rsp_tx_cb; bool need_assoc_rsp_tx_cb;
tSirMacAddr peer_mld_addr; tSirMacAddr peer_mld_addr;
}; };
@@ -1099,6 +1102,16 @@ struct owe_assoc_ind {
struct assoc_ind *assoc_ind; struct assoc_ind *assoc_ind;
}; };
/**
* struct ft_assoc_ind - ft association indication
* @node: List entry element
* @assoc_ind: pointer to assoc ind
*/
struct ft_assoc_ind {
qdf_list_node_t node;
struct assoc_ind *assoc_ind;
};
/* / Definition for Association confirm */ /* / Definition for Association confirm */
/* / ---> MAC */ /* / ---> MAC */
struct assoc_cnf { struct assoc_cnf {
@@ -1111,6 +1124,8 @@ struct assoc_cnf {
enum wlan_status_code mac_status_code; enum wlan_status_code mac_status_code;
uint8_t *owe_ie; uint8_t *owe_ie;
uint32_t owe_ie_len; uint32_t owe_ie_len;
uint8_t *ft_ie;
uint32_t ft_ie_len;
bool need_assoc_rsp_tx_cb; bool need_assoc_rsp_tx_cb;
}; };

Ver fichero

@@ -136,6 +136,7 @@ typedef enum eLimMlmStates {
eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE, eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE,
eLIM_MLM_WT_FT_REASSOC_RSP_STATE, eLIM_MLM_WT_FT_REASSOC_RSP_STATE,
eLIM_MLM_WT_SAE_AUTH_STATE, eLIM_MLM_WT_SAE_AUTH_STATE,
eLIM_MLM_WT_FT_AUTH_STATE,
} tLimMlmStates; } tLimMlmStates;
/* 11h channel switch states */ /* 11h channel switch states */
@@ -246,6 +247,8 @@ typedef struct tLimPreAuthTable {
* @he_capable: 802.11ax HE capability * @he_capable: 802.11ax HE capability
* @owe_ie: Pointer to OWE IE * @owe_ie: Pointer to OWE IE
* @owe_ie_len: Length of OWE IE * @owe_ie_len: Length of OWE IE
* @ft_ie: Pointer to FT related IE
* @ft_ie_len: Length of FT related IE
* @eht_capable: 802.11be EHT capability * @eht_capable: 802.11be EHT capability
*/ */
struct lim_sta_context { struct lim_sta_context {
@@ -272,6 +275,8 @@ struct lim_sta_context {
bool force_1x1; bool force_1x1;
uint8_t *owe_ie; uint8_t *owe_ie;
uint32_t owe_ie_len; uint32_t owe_ie_len;
uint8_t *ft_ie;
uint32_t ft_ie_len;
#ifdef WLAN_FEATURE_11BE #ifdef WLAN_FEATURE_11BE
bool eht_capable; bool eht_capable;
#endif #endif

Ver fichero

@@ -2668,6 +2668,14 @@ void lim_process_assoc_req_frame(struct mac_context *mac_ctx,
sub_type, GET_LIM_SYSTEM_ROLE(session), sub_type, GET_LIM_SYSTEM_ROLE(session),
QDF_MAC_ADDR_REF(hdr->sa)); QDF_MAC_ADDR_REF(hdr->sa));
return; return;
} else if (sta_ds->mlmStaContext.akm_type == ANI_AKM_TYPE_FT_RSN_PSK) {
pe_debug("FT Assoc Req, delete STA hash entry");
lim_release_peer_idx(mac_ctx, sta_ds->assocId, session);
if (dph_delete_hash_entry(mac_ctx, hdr->sa,
sta_ds->assocId,
&session->dph.dphHashTable)
!= QDF_STATUS_SUCCESS)
pe_err("error deleting hash entry");
} else if (!sta_ds->rmfEnabled && (sub_type == LIM_REASSOC)) { } else if (!sta_ds->rmfEnabled && (sub_type == LIM_REASSOC)) {
/* /*
* SAP should send reassoc response with reject code * SAP should send reassoc response with reject code
@@ -3442,6 +3450,15 @@ QDF_STATUS lim_send_mlm_assoc_ind(struct mac_context *mac_ctx,
qdf_mem_free(assoc_ind); qdf_mem_free(assoc_ind);
return QDF_STATUS_E_INVAL; return QDF_STATUS_E_INVAL;
} }
pe_debug("assoc_ind->akm_type:%d ", assoc_ind->akm_type);
if (assoc_ind->akm_type == ANI_AKM_TYPE_FT_RSN_PSK) {
lim_send_sme_mgmt_frame_ind(mac_ctx, sub_type,
qdf_nbuf_data(assoc_req->assoc_req_buf),
qdf_nbuf_len(assoc_req->assoc_req_buf),
session_entry->smeSessionId,
0, 0, RXMGMT_FLAG_NONE);
}
lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND, lim_post_sme_message(mac_ctx, LIM_MLM_ASSOC_IND,
(uint32_t *)assoc_ind); (uint32_t *)assoc_ind);
qdf_mem_free(assoc_ind); qdf_mem_free(assoc_ind);

Ver fichero

@@ -508,6 +508,73 @@ static inline void lim_process_sae_auth_frame(struct mac_context *mac_ctx,
{} {}
#endif #endif
static void lim_process_ft_auth_frame(struct mac_context *mac_ctx,
uint8_t *rx_pkt_info,
struct pe_session *pe_session)
{
tpSirMacMgmtHdr mac_hdr;
uint32_t frame_len;
uint8_t *body_ptr;
enum rxmgmt_flags rx_flags = RXMGMT_FLAG_NONE;
uint16_t auth_algo;
mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info);
body_ptr = WMA_GET_RX_MPDU_DATA(rx_pkt_info);
frame_len = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info);
pe_debug("FT Auth RX type %d subtype %d from " QDF_MAC_ADDR_FMT,
mac_hdr->fc.type, mac_hdr->fc.subType,
QDF_MAC_ADDR_REF(mac_hdr->sa));
if (LIM_IS_AP_ROLE(pe_session)) {
struct tLimPreAuthNode *sta_pre_auth_ctx;
rx_flags = RXMGMT_FLAG_EXTERNAL_AUTH;
/* Extract pre-auth context for the STA, if any. */
sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx,
mac_hdr->sa);
if (sta_pre_auth_ctx) {
pe_debug("STA Auth ctx have ininted");
/* Pre-auth context exists for the STA */
if (sta_pre_auth_ctx->mlmState == eLIM_MLM_WT_FT_AUTH_STATE) {
pe_warn("previous Auth not completed, don't process this auth frame");
return;
}
lim_delete_pre_auth_node(mac_ctx, mac_hdr->sa);
}
/* Create entry for this STA in pre-auth list */
sta_pre_auth_ctx = lim_acquire_free_pre_auth_node(mac_ctx,
&mac_ctx->lim.gLimPreAuthTimerTable);
if (!sta_pre_auth_ctx) {
pe_warn("Max pre-auth nodes reached ");
lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOGW);
return;
}
pe_debug("Alloc new data: %pK peer", sta_pre_auth_ctx);
auth_algo = *(uint16_t *)body_ptr;
lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOGD);
qdf_mem_copy((uint8_t *)sta_pre_auth_ctx->peerMacAddr,
mac_hdr->sa, sizeof(tSirMacAddr));
sta_pre_auth_ctx->mlmState = eLIM_MLM_WT_FT_AUTH_STATE;
sta_pre_auth_ctx->authType = (tAniAuthType) auth_algo;
sta_pre_auth_ctx->fSeen = 0;
sta_pre_auth_ctx->fTimerStarted = 0;
sta_pre_auth_ctx->seq_num =
((mac_hdr->seqControl.seqNumHi << 4) |
(mac_hdr->seqControl.seqNumLo));
sta_pre_auth_ctx->timestamp = qdf_mc_timer_get_system_ticks();
lim_add_pre_auth_node(mac_ctx, sta_pre_auth_ctx);
lim_send_sme_mgmt_frame_ind(mac_ctx, mac_hdr->fc.subType,
(uint8_t *)mac_hdr,
frame_len + sizeof(tSirMacMgmtHdr),
pe_session->smeSessionId,
WMA_GET_RX_FREQ(rx_pkt_info),
WMA_GET_RX_RSSI_NORMALIZED(rx_pkt_info),
rx_flags);
}
}
static uint8_t static uint8_t
lim_get_pasn_peer_vdev_id(struct mac_context *mac, uint8_t *bssid) lim_get_pasn_peer_vdev_id(struct mac_context *mac, uint8_t *bssid)
{ {
@@ -1669,6 +1736,11 @@ lim_process_auth_frame(struct mac_context *mac_ctx, uint8_t *rx_pkt_info,
lim_process_pasn_auth_frame(mac_ctx, pe_session->vdev_id, lim_process_pasn_auth_frame(mac_ctx, pe_session->vdev_id,
rx_pkt_info); rx_pkt_info);
goto free; goto free;
} else if (auth_alg == eSIR_FT_AUTH && LIM_IS_AP_ROLE(pe_session)) {
pe_debug("Auth Frame auth_alg eSIR_FT_AUTH");
lim_process_ft_auth_frame(mac_ctx,
rx_pkt_info, pe_session);
goto free;
} else if ((sir_convert_auth_frame2_struct(mac_ctx, body_ptr, } else if ((sir_convert_auth_frame2_struct(mac_ctx, body_ptr,
frame_len, rx_auth_frame) != QDF_STATUS_SUCCESS) frame_len, rx_auth_frame) != QDF_STATUS_SUCCESS)
|| (!is_auth_valid(mac_ctx, rx_auth_frame, || (!is_auth_valid(mac_ctx, rx_auth_frame,

Ver fichero

@@ -6638,6 +6638,8 @@ void __lim_process_sme_assoc_cnf_new(struct mac_context *mac_ctx, uint32_t msg_t
eLIM_MLM_LINK_ESTABLISHED_STATE; eLIM_MLM_LINK_ESTABLISHED_STATE;
sta_ds->mlmStaContext.owe_ie = assoc_cnf.owe_ie; sta_ds->mlmStaContext.owe_ie = assoc_cnf.owe_ie;
sta_ds->mlmStaContext.owe_ie_len = assoc_cnf.owe_ie_len; sta_ds->mlmStaContext.owe_ie_len = assoc_cnf.owe_ie_len;
sta_ds->mlmStaContext.ft_ie = assoc_cnf.ft_ie;
sta_ds->mlmStaContext.ft_ie_len = assoc_cnf.ft_ie_len;
pe_debug("sending Assoc Rsp frame to STA assoc id=%d, tx cb %d", pe_debug("sending Assoc Rsp frame to STA assoc id=%d, tx cb %d",
sta_ds->assocId, assoc_cnf.need_assoc_rsp_tx_cb); sta_ds->assocId, assoc_cnf.need_assoc_rsp_tx_cb);
lim_send_assoc_rsp_mgmt_frame( lim_send_assoc_rsp_mgmt_frame(
@@ -6648,6 +6650,8 @@ void __lim_process_sme_assoc_cnf_new(struct mac_context *mac_ctx, uint32_t msg_t
assoc_cnf.need_assoc_rsp_tx_cb); assoc_cnf.need_assoc_rsp_tx_cb);
sta_ds->mlmStaContext.owe_ie = NULL; sta_ds->mlmStaContext.owe_ie = NULL;
sta_ds->mlmStaContext.owe_ie_len = 0; sta_ds->mlmStaContext.owe_ie_len = 0;
sta_ds->mlmStaContext.ft_ie = NULL;
sta_ds->mlmStaContext.ft_ie_len = 0;
goto end; goto end;
} else { } else {
uint8_t add_pre_auth_context = true; uint8_t add_pre_auth_context = true;
@@ -6691,6 +6695,7 @@ end:
session_entry->parsedAssocReq[sta_ds->assocId] = NULL; session_entry->parsedAssocReq[sta_ds->assocId] = NULL;
} }
qdf_mem_free(assoc_cnf.owe_ie); qdf_mem_free(assoc_cnf.owe_ie);
qdf_mem_free(assoc_cnf.ft_ie);
} }
static void static void

Ver fichero

@@ -1906,9 +1906,10 @@ lim_send_assoc_rsp_mgmt_frame(struct mac_context *mac_ctx,
bytes += sizeof(tSirMacMgmtHdr) + payload + mlo_ie_len; bytes += sizeof(tSirMacMgmtHdr) + payload + mlo_ie_len;
if (sta) if (sta) {
bytes += sta->mlmStaContext.owe_ie_len; bytes += sta->mlmStaContext.owe_ie_len;
bytes += sta->mlmStaContext.ft_ie_len;
}
qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame, qdf_status = cds_packet_alloc((uint16_t) bytes, (void **)&frame,
(void **)&packet); (void **)&packet);
if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
@@ -2028,6 +2029,13 @@ lim_send_assoc_rsp_mgmt_frame(struct mac_context *mac_ctx,
payload += sta->mlmStaContext.owe_ie_len; payload += sta->mlmStaContext.owe_ie_len;
} }
if (sta && sta->mlmStaContext.ft_ie_len) {
qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
sta->mlmStaContext.ft_ie,
sta->mlmStaContext.ft_ie_len);
payload += sta->mlmStaContext.ft_ie_len;
}
if (sta && mlo_ie_len) { if (sta && mlo_ie_len) {
qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len, qdf_status = lim_fill_complete_mlo_ie(pe_session, mlo_ie_len,
frame + sizeof(tSirMacMgmtHdr) + payload); frame + sizeof(tSirMacMgmtHdr) + payload);
@@ -6610,6 +6618,19 @@ void lim_send_mgmt_frame_tx(struct mac_context *mac_ctx,
if (auth_algo == eSIR_AUTH_TYPE_SAE) if (auth_algo == eSIR_AUTH_TYPE_SAE)
lim_handle_sae_auth_retry(mac_ctx, vdev_id, lim_handle_sae_auth_retry(mac_ctx, vdev_id,
mb_msg->data, msg_len); mb_msg->data, msg_len);
if (auth_algo == eSIR_FT_AUTH) {
struct tLimPreAuthNode *sta_pre_auth_ctx;
sta_pre_auth_ctx = lim_search_pre_auth_list(mac_ctx,
((tpSirMacMgmtHdr)(mb_msg->data))->da);
pe_debug("FT Auth TX to " QDF_MAC_ADDR_FMT,
QDF_MAC_ADDR_REF(((tpSirMacMgmtHdr)(mb_msg->data))->da));
if (sta_pre_auth_ctx) {
pe_debug("STA is AUTHENTICATED_STATE");
sta_pre_auth_ctx->mlmState =
eLIM_MLM_AUTHENTICATED_STATE;
}
}
} }
mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD; mac_ctx->auth_ack_status = LIM_ACK_NOT_RCD;
lim_send_frame(mac_ctx, vdev_id, mb_msg->data, msg_len); lim_send_frame(mac_ctx, vdev_id, mb_msg->data, msg_len);

Ver fichero

@@ -1501,6 +1501,20 @@ QDF_STATUS wlansap_update_owe_info(struct sap_context *sap_ctx,
uint8_t *peer, const uint8_t *ie, uint8_t *peer, const uint8_t *ie,
uint32_t ie_len, uint16_t owe_status); uint32_t ie_len, uint16_t owe_status);
/**
* wlansap_update_ft_info() - Update FT info
* @sap_ctx: sap context
* @peer: peer mac
* @ie: IE from hostapd
* @ie_len: IE length
* @ft_status: wlan status codes
*
* Return: QDF_STATUS
*/
QDF_STATUS wlansap_update_ft_info(struct sap_context *sap_ctx,
uint8_t *peer, const uint8_t *ie,
uint32_t ie_len, uint16_t ft_status);
/** /**
* wlansap_filter_ch_based_acs() -filter out channel based on acs * wlansap_filter_ch_based_acs() -filter out channel based on acs
* @sap_ctx: sap context * @sap_ctx: sap context

Ver fichero

@@ -1898,6 +1898,27 @@ static bool sap_save_owe_pending_assoc_ind(struct sap_context *sap_ctx,
return true; return true;
} }
static bool sap_save_ft_pending_assoc_ind(struct sap_context *sap_ctx,
struct assoc_ind *sme_assoc_ind)
{
struct ft_assoc_ind *assoc_ind;
QDF_STATUS status;
assoc_ind = qdf_mem_malloc(sizeof(*assoc_ind));
if (!assoc_ind)
return false;
assoc_ind->assoc_ind = sme_assoc_ind;
status = qdf_list_insert_back(&sap_ctx->ft_pending_assoc_ind_list,
&assoc_ind->node);
if (QDF_STATUS_SUCCESS != status) {
qdf_mem_free(assoc_ind);
return false;
}
qdf_event_set(&sap_ctx->ft_pending_event);
return true;
}
#ifdef FEATURE_RADAR_HISTORY #ifdef FEATURE_RADAR_HISTORY
/* Last cac result */ /* Last cac result */
static struct prev_cac_result prev_cac_history; static struct prev_cac_result prev_cac_history;
@@ -2313,6 +2334,18 @@ QDF_STATUS sap_signal_hdd_event(struct sap_context *sap_ctx,
} }
csr_roaminfo->owe_pending_assoc_ind = NULL; csr_roaminfo->owe_pending_assoc_ind = NULL;
} }
if (csr_roaminfo->ft_pending_assoc_ind) {
if (!sap_save_ft_pending_assoc_ind(sap_ctx,
csr_roaminfo->ft_pending_assoc_ind)) {
sap_err("Failed to save ft assoc ind");
qdf_mem_free(csr_roaminfo->ft_pending_assoc_ind);
csr_roaminfo->ft_pending_assoc_ind = NULL;
qdf_mem_free(sap_ap_event);
return QDF_STATUS_E_INVAL;
}
csr_roaminfo->ft_pending_assoc_ind = NULL;
}
break; break;
case eSAP_START_BSS_EVENT: case eSAP_START_BSS_EVENT:
sap_ap_event->sapHddEventCode = eSAP_START_BSS_EVENT; sap_ap_event->sapHddEventCode = eSAP_START_BSS_EVENT;

Ver fichero

@@ -229,6 +229,8 @@ struct sap_context {
/* Disabled mcs13 by sap or not */ /* Disabled mcs13 by sap or not */
bool disabled_mcs13; bool disabled_mcs13;
qdf_list_t owe_pending_assoc_ind_list; qdf_list_t owe_pending_assoc_ind_list;
qdf_list_t ft_pending_assoc_ind_list;
qdf_event_t ft_pending_event;
uint32_t freq_before_ch_switch; uint32_t freq_before_ch_switch;
#ifdef WLAN_FEATURE_P2P_P2P_STA #ifdef WLAN_FEATURE_P2P_P2P_STA
/* /*

Ver fichero

@@ -239,6 +239,14 @@ static QDF_STATUS wlansap_owe_init(struct sap_context *sap_ctx)
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
} }
static QDF_STATUS wlansap_ft_init(struct sap_context *sap_ctx)
{
qdf_list_create(&sap_ctx->ft_pending_assoc_ind_list, 0);
qdf_event_create(&sap_ctx->ft_pending_event);
return QDF_STATUS_SUCCESS;
}
static void wlansap_owe_cleanup(struct sap_context *sap_ctx) static void wlansap_owe_cleanup(struct sap_context *sap_ctx)
{ {
struct mac_context *mac; struct mac_context *mac;
@@ -289,11 +297,65 @@ static void wlansap_owe_cleanup(struct sap_context *sap_ctx)
} }
} }
static void wlansap_ft_cleanup(struct sap_context *sap_ctx)
{
struct mac_context *mac;
struct ft_assoc_ind *ft_assoc_ind;
struct assoc_ind *assoc_ind = NULL;
qdf_list_node_t *node = NULL, *next_node = NULL;
QDF_STATUS status;
if (!sap_ctx) {
sap_err("Invalid SAP context");
return;
}
mac = sap_get_mac_context();
if (!mac) {
sap_err("Invalid MAC context");
return;
}
if (QDF_STATUS_SUCCESS !=
qdf_list_peek_front(&sap_ctx->ft_pending_assoc_ind_list,
&node)) {
sap_debug("Failed to find assoc ind list");
return;
}
while (node) {
qdf_list_peek_next(&sap_ctx->ft_pending_assoc_ind_list,
node, &next_node);
ft_assoc_ind = qdf_container_of(node, struct ft_assoc_ind,
node);
status = qdf_list_remove_node(
&sap_ctx->ft_pending_assoc_ind_list, node);
if (status == QDF_STATUS_SUCCESS) {
assoc_ind = ft_assoc_ind->assoc_ind;
qdf_mem_free(ft_assoc_ind);
assoc_ind->ft_ie = NULL;
assoc_ind->ft_ie_len = 0;
assoc_ind->ft_status = STATUS_UNSPECIFIED_FAILURE;
qdf_mem_free(assoc_ind);
} else {
sap_err("Failed to remove assoc ind");
}
node = next_node;
next_node = NULL;
}
}
static void wlansap_owe_deinit(struct sap_context *sap_ctx) static void wlansap_owe_deinit(struct sap_context *sap_ctx)
{ {
qdf_list_destroy(&sap_ctx->owe_pending_assoc_ind_list); qdf_list_destroy(&sap_ctx->owe_pending_assoc_ind_list);
} }
static void wlansap_ft_deinit(struct sap_context *sap_ctx)
{
qdf_list_destroy(&sap_ctx->ft_pending_assoc_ind_list);
qdf_event_destroy(&sap_ctx->ft_pending_event);
}
QDF_STATUS sap_init_ctx(struct sap_context *sap_ctx, QDF_STATUS sap_init_ctx(struct sap_context *sap_ctx,
enum QDF_OPMODE mode, enum QDF_OPMODE mode,
uint8_t *addr, uint32_t session_id, bool reinit) uint8_t *addr, uint32_t session_id, bool reinit)
@@ -334,6 +396,11 @@ QDF_STATUS sap_init_ctx(struct sap_context *sap_ctx,
sap_err("OWE init failed"); sap_err("OWE init failed");
return QDF_STATUS_E_FAILURE; return QDF_STATUS_E_FAILURE;
} }
status = wlansap_ft_init(sap_ctx);
if (QDF_STATUS_SUCCESS != status) {
sap_err("FT init failed");
return QDF_STATUS_E_FAILURE;
}
} }
return QDF_STATUS_SUCCESS; return QDF_STATUS_SUCCESS;
@@ -351,9 +418,10 @@ QDF_STATUS sap_deinit_ctx(struct sap_context *sap_ctx)
return QDF_STATUS_E_FAULT; return QDF_STATUS_E_FAULT;
} }
wlansap_ft_cleanup(sap_ctx);
wlansap_ft_deinit(sap_ctx);
wlansap_owe_cleanup(sap_ctx); wlansap_owe_cleanup(sap_ctx);
wlansap_owe_deinit(sap_ctx); wlansap_owe_deinit(sap_ctx);
mac = sap_get_mac_context(); mac = sap_get_mac_context();
if (!mac) { if (!mac) {
sap_err("Invalid MAC context"); sap_err("Invalid MAC context");
@@ -3000,6 +3068,71 @@ QDF_STATUS wlansap_update_owe_info(struct sap_context *sap_ctx,
return status; return status;
} }
QDF_STATUS wlansap_update_ft_info(struct sap_context *sap_ctx,
uint8_t *peer, const uint8_t *ie,
uint32_t ie_len, uint16_t ft_status)
{
struct mac_context *mac;
struct ft_assoc_ind *ft_assoc_ind;
struct assoc_ind *assoc_ind = NULL;
qdf_list_node_t *node = NULL, *next_node = NULL;
QDF_STATUS status;
if (!sap_ctx) {
sap_err("Invalid SAP context");
return QDF_STATUS_E_FAULT;
}
mac = sap_get_mac_context();
if (!mac) {
sap_err("Invalid MAC context");
return QDF_STATUS_E_FAULT;
}
status = qdf_wait_single_event(&sap_ctx->ft_pending_event,
500);
if (!QDF_IS_STATUS_SUCCESS(status)) {
sap_err("wait for ft pending event timeout");
wlansap_ft_cleanup(sap_ctx);
return QDF_STATUS_E_FAULT;
}
if (QDF_STATUS_SUCCESS !=
qdf_list_peek_front(&sap_ctx->ft_pending_assoc_ind_list,
&next_node)) {
sap_err("Failed to find ft assoc ind list");
return QDF_STATUS_E_FAILURE;
}
do {
node = next_node;
ft_assoc_ind = qdf_container_of(node, struct ft_assoc_ind, node);
if (qdf_mem_cmp(peer,
ft_assoc_ind->assoc_ind->peerMacAddr,
QDF_MAC_ADDR_SIZE) == 0) {
status = qdf_list_remove_node(&sap_ctx->ft_pending_assoc_ind_list,
node);
if (status != QDF_STATUS_SUCCESS) {
sap_err("Failed to remove ft assoc ind");
return status;
}
assoc_ind = ft_assoc_ind->assoc_ind;
qdf_mem_free(ft_assoc_ind);
break;
}
} while (QDF_STATUS_SUCCESS ==
qdf_list_peek_next(&sap_ctx->ft_pending_assoc_ind_list,
node, &next_node));
if (assoc_ind) {
assoc_ind->ft_ie = ie;
assoc_ind->ft_ie_len = ie_len;
assoc_ind->ft_status = ft_status;
status = sme_update_ft_info(mac, assoc_ind);
qdf_mem_free(assoc_ind);
}
return status;
}
bool wlansap_is_channel_present_in_acs_list(uint32_t freq, bool wlansap_is_channel_present_in_acs_list(uint32_t freq,
uint32_t *ch_freq_list, uint32_t *ch_freq_list,
uint8_t ch_count) uint8_t ch_count)

Ver fichero

@@ -593,6 +593,8 @@ struct csr_roam_info {
struct sir_sae_info *sae_info; struct sir_sae_info *sae_info;
#endif #endif
struct assoc_ind *owe_pending_assoc_ind; struct assoc_ind *owe_pending_assoc_ind;
struct assoc_ind *ft_pending_assoc_ind;
struct qdf_mac_addr peer_mld; struct qdf_mac_addr peer_mld;
#ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE #ifdef WLAN_FEATURE_SAP_ACS_OPTIMIZE
uint32_t chan_info_freq; uint32_t chan_info_freq;
@@ -859,6 +861,17 @@ static inline void csr_packetdump_timer_start(void) {}
QDF_STATUS csr_update_owe_info(struct mac_context *mac, QDF_STATUS csr_update_owe_info(struct mac_context *mac,
struct assoc_ind *assoc_ind); struct assoc_ind *assoc_ind);
/**
* csr_update_ft_info() - Update FT info
* @mac: mac context
* @assoc_ind: assoc ind
*
* Return: QDF_STATUS
*/
QDF_STATUS csr_update_ft_info(struct mac_context *mac,
struct assoc_ind *assoc_ind);
typedef void (*csr_ani_callback)(int8_t *ani, void *context); typedef void (*csr_ani_callback)(int8_t *ani, void *context);
/* /*

Ver fichero

@@ -4236,6 +4236,17 @@ QDF_STATUS sme_update_hidden_ssid_status_cb(mac_handle_t mac_handle,
QDF_STATUS sme_update_owe_info(struct mac_context *mac, QDF_STATUS sme_update_owe_info(struct mac_context *mac,
struct assoc_ind *assoc_ind); struct assoc_ind *assoc_ind);
/**
* sme_update_ft_info() - Update FT info
* @mac: mac context
* @assoc_ind: assoc ind
*
* Return: QDF_STATUS
*/
QDF_STATUS sme_update_ft_info(struct mac_context *mac,
struct assoc_ind *assoc_ind);
#ifdef WLAN_MWS_INFO_DEBUGFS #ifdef WLAN_MWS_INFO_DEBUGFS
/** /**
* sme_get_mws_coex_info() - SME API to get the coex information * sme_get_mws_coex_info() - SME API to get the coex information

Ver fichero

@@ -15765,6 +15765,20 @@ QDF_STATUS sme_update_owe_info(struct mac_context *mac,
return status; return status;
} }
QDF_STATUS sme_update_ft_info(struct mac_context *mac,
struct assoc_ind *assoc_ind)
{
QDF_STATUS status;
status = sme_acquire_global_lock(&mac->sme);
if (QDF_IS_STATUS_SUCCESS(status)) {
status = csr_update_ft_info(mac, assoc_ind);
sme_release_global_lock(&mac->sme);
}
return status;
}
#ifdef WLAN_MWS_INFO_DEBUGFS #ifdef WLAN_MWS_INFO_DEBUGFS
QDF_STATUS QDF_STATUS
sme_get_mws_coex_info(mac_handle_t mac_handle, uint32_t vdev_id, sme_get_mws_coex_info(mac_handle_t mac_handle, uint32_t vdev_id,

Ver fichero

@@ -4006,12 +4006,19 @@ csr_roam_chk_lnk_assoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
} else { } else {
roam_info->fAuthRequired = true; roam_info->fAuthRequired = true;
} }
sme_debug("Receive AUTH_TYPE of %d", csr_akm_type);
if (csr_akm_type == eCSR_AUTH_TYPE_OWE) { if (csr_akm_type == eCSR_AUTH_TYPE_OWE) {
roam_info->owe_pending_assoc_ind = qdf_mem_malloc( roam_info->owe_pending_assoc_ind = qdf_mem_malloc(
sizeof(*pAssocInd)); sizeof(*pAssocInd));
if (roam_info->owe_pending_assoc_ind) if (roam_info->owe_pending_assoc_ind)
qdf_mem_copy(roam_info->owe_pending_assoc_ind, qdf_mem_copy(roam_info->owe_pending_assoc_ind,
pAssocInd, sizeof(*pAssocInd)); pAssocInd, sizeof(*pAssocInd));
} else if (csr_akm_type == eCSR_AUTH_TYPE_FT_RSN_PSK) {
roam_info->ft_pending_assoc_ind = qdf_mem_malloc(
sizeof(*pAssocInd));
if (roam_info->ft_pending_assoc_ind)
qdf_mem_copy(roam_info->ft_pending_assoc_ind,
pAssocInd, sizeof(*pAssocInd));
} }
status = csr_roam_call_callback(mac_ctx, sessionId, status = csr_roam_call_callback(mac_ctx, sessionId,
roam_info, eCSR_ROAM_INFRA_IND, roam_info, eCSR_ROAM_INFRA_IND,
@@ -4042,8 +4049,10 @@ csr_roam_chk_lnk_assoc_ind(struct mac_context *mac_ctx, tSirSmeRsp *msg_ptr)
} }
} }
} }
sme_debug("csr_akm_type: %d", csr_akm_type);
if (csr_akm_type != eCSR_AUTH_TYPE_OWE) { if (csr_akm_type != eCSR_AUTH_TYPE_OWE &&
csr_akm_type != eCSR_AUTH_TYPE_FT_RSN_PSK) {
if ((opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) && if ((opmode == QDF_SAP_MODE || opmode == QDF_P2P_GO_MODE) &&
roam_info->status_code != eSIR_SME_ASSOC_REFUSED) roam_info->status_code != eSIR_SME_ASSOC_REFUSED)
pAssocInd->need_assoc_rsp_tx_cb = true; pAssocInd->need_assoc_rsp_tx_cb = true;
@@ -6140,6 +6149,15 @@ QDF_STATUS csr_send_assoc_cnf_msg(struct mac_context *mac,
pAssocInd->owe_ie_len); pAssocInd->owe_ie_len);
pMsg->owe_ie_len = pAssocInd->owe_ie_len; pMsg->owe_ie_len = pAssocInd->owe_ie_len;
} }
if (pAssocInd->ft_ie_len) {
pMsg->ft_ie = qdf_mem_malloc(pAssocInd->ft_ie_len);
if (!pMsg->ft_ie)
return QDF_STATUS_E_NOMEM;
qdf_mem_copy(pMsg->ft_ie, pAssocInd->ft_ie,
pAssocInd->ft_ie_len);
pMsg->ft_ie_len = pAssocInd->ft_ie_len;
}
pMsg->need_assoc_rsp_tx_cb = pAssocInd->need_assoc_rsp_tx_cb; pMsg->need_assoc_rsp_tx_cb = pAssocInd->need_assoc_rsp_tx_cb;
msg.type = pMsg->messageType; msg.type = pMsg->messageType;
@@ -7713,6 +7731,19 @@ QDF_STATUS csr_update_owe_info(struct mac_context *mac,
return status; return status;
} }
QDF_STATUS csr_update_ft_info(struct mac_context *mac,
struct assoc_ind *assoc_ind)
{
QDF_STATUS status;
/* Send Association completion message to PE */
status = assoc_ind->ft_status ? QDF_STATUS_E_INVAL : QDF_STATUS_SUCCESS;
assoc_ind->need_assoc_rsp_tx_cb = true;
status = csr_send_assoc_cnf_msg(mac, assoc_ind, status,
assoc_ind->ft_status);
return status;
}
/** /**
* csr_set_sap_ser_params() - API to fill serialization parameters for * csr_set_sap_ser_params() - API to fill serialization parameters for
* SAP requests * SAP requests