Browse Source

qcacld-3.0: Fix bss_transition bit in reassoc request frame

bss_transition bit is not set in extend capability IE of reassoc request
frame, while it is set in extend capability IE of assoc request frame.

The way to populate extend capability IE of reassoc request should be
the same as we do for assoc reqest frame.

Change-Id: I22a56c7c9f8926d88d0da7d0445ff5f6a8249320
CRs-Fixed: 3200723
Bing Sun 3 years ago
parent
commit
6d71f2d38d
1 changed files with 170 additions and 14 deletions
  1. 170 14
      core/mac/src/pe/lim/lim_send_frames_host_roam.c

+ 170 - 14
core/mac/src/pe/lim/lim_send_frames_host_roam.c

@@ -83,6 +83,15 @@ void lim_send_reassoc_req_with_ft_ies_mgmt_frame(struct mac_context *mac_ctx,
 	bool vht_enabled = false;
 	tpSirMacMgmtHdr mac_hdr;
 	struct mlme_legacy_priv *mlme_priv;
+	int ret;
+	tDot11fIEExtCap extr_ext_cap;
+	QDF_STATUS sir_status;
+	bool extr_ext_flag = true;
+	uint32_t ie_offset = 0;
+	tDot11fIEExtCap bcn_ext_cap;
+	uint8_t *bcn_ie = NULL;
+	uint32_t bcn_ie_len = 0;
+	uint8_t *p_ext_cap = NULL;
 
 	if (!pe_session)
 		return;
@@ -107,6 +116,28 @@ void lim_send_reassoc_req_with_ft_ies_mgmt_frame(struct mac_context *mac_ctx,
 
 	qdf_mem_zero((uint8_t *) frm, sizeof(*frm));
 
+	if (add_ie_len && pe_session->is_ext_caps_present) {
+		qdf_mem_zero((uint8_t *)&extr_ext_cap,
+			     sizeof(tDot11fIEExtCap));
+		sir_status = lim_strip_extcap_update_struct(
+				mac_ctx, add_ie, &add_ie_len, &extr_ext_cap);
+		if (QDF_STATUS_SUCCESS != sir_status) {
+			extr_ext_flag = false;
+			pe_debug("Unable to Stripoff ExtCap IE from Assoc Req");
+		} else {
+			struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)
+							extr_ext_cap.bytes;
+
+			if (p_ext_cap->interworking_service)
+				p_ext_cap->qos_map = 1;
+			extr_ext_cap.num_bytes =
+				lim_compute_ext_cap_ie_length(&extr_ext_cap);
+			extr_ext_flag = (extr_ext_cap.num_bytes > 0);
+		}
+	} else {
+		pe_debug("No addn IE or peer doesn't support addnIE for Assoc Req");
+		extr_ext_flag = false;
+	}
 	caps = mlm_reassoc_req->capabilityInfo;
 #if defined(FEATURE_WLAN_WAPI)
 	/*
@@ -321,6 +352,59 @@ void lim_send_reassoc_req_with_ft_ies_mgmt_frame(struct mac_context *mac_ctx,
 		populate_dot11f_he_6ghz_cap(mac_ctx, pe_session,
 					    &frm->he_6ghz_band_cap);
 	}
+	/*
+	 * Extcap IE now support variable length, merge Extcap IE from addn_ie
+	 * may change the frame size. Therefore, MUST merge ExtCap IE before
+	 * dot11f get packed payload size.
+	 */
+	if (extr_ext_flag)
+		lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap, true);
+
+	/* Clear the bits in EXTCAP IE if AP not advertise it in beacon */
+	if (frm->ExtCap.present && pe_session->is_ext_caps_present) {
+		ie_offset = DOT11F_FF_TIMESTAMP_LEN +
+				DOT11F_FF_BEACONINTERVAL_LEN +
+				DOT11F_FF_CAPABILITIES_LEN;
+
+		qdf_mem_zero((uint8_t *)&bcn_ext_cap, sizeof(tDot11fIEExtCap));
+		if (pe_session->beacon && (pe_session->bcnLen >
+		    (ie_offset + sizeof(struct wlan_frame_hdr)))) {
+			bcn_ie = pe_session->beacon + ie_offset +
+						sizeof(struct wlan_frame_hdr);
+			bcn_ie_len = pe_session->bcnLen - ie_offset -
+						sizeof(struct wlan_frame_hdr);
+			p_ext_cap = (uint8_t *)wlan_get_ie_ptr_from_eid(
+							DOT11F_EID_EXTCAP,
+							bcn_ie, bcn_ie_len);
+			lim_update_extcap_struct(mac_ctx, p_ext_cap,
+						 &bcn_ext_cap);
+			lim_merge_extcap_struct(&frm->ExtCap, &bcn_ext_cap,
+						false);
+		}
+		/*
+		 * TWT extended capabilities should be populated after the
+		 * intersection of beacon caps and self caps is done because
+		 * the bits for TWT are unique to STA and AP and cannot be
+		 * intersected.
+		 */
+		populate_dot11f_twt_extended_caps(mac_ctx, pe_session,
+						  &frm->ExtCap);
+	}
+
+	/*
+	 * Do unpack to populate the add_ie buffer to frm structure
+	 * before packing the frm structure. In this way, the IE ordering
+	 * which the latest 802.11 spec mandates is maintained.
+	 */
+	if (add_ie_len) {
+		ret = dot11f_unpack_re_assoc_request(mac_ctx, add_ie,
+						     add_ie_len,
+						     frm, true);
+		if (DOT11F_FAILED(ret)) {
+			pe_err("unpack failed, ret: 0x%x", ret);
+			goto end;
+		}
+	}
 
 	if (lim_is_session_eht_capable(pe_session)) {
 		pe_debug("Populate EHT IEs");
@@ -337,7 +421,7 @@ void lim_send_reassoc_req_with_ft_ies_mgmt_frame(struct mac_context *mac_ctx,
 		pe_warn("Warnings in size calculation (0x%08x)", status);
 	}
 
-	bytes = payload + sizeof(tSirMacMgmtHdr) + add_ie_len;
+	bytes = payload + sizeof(tSirMacMgmtHdr);
 
 	pe_debug("FT IE Reassoc Req %d",
 		 mlme_priv->connect_info.ft_info.reassoc_ie_len);
@@ -379,12 +463,6 @@ void lim_send_reassoc_req_with_ft_ies_mgmt_frame(struct mac_context *mac_ctx,
 	pe_debug("*** Sending Re-Assoc Request length: %d %d to",
 		       bytes, payload);
 
-	if (add_ie_len) {
-		qdf_mem_copy(frame + sizeof(tSirMacMgmtHdr) + payload,
-			     add_ie, add_ie_len);
-		payload += add_ie_len;
-	}
-
 	if (pe_session->is11Rconnection &&
 	    mlme_priv->connect_info.ft_info.reassoc_ie_len) {
 		int i = 0;
@@ -544,6 +622,15 @@ void lim_send_reassoc_req_mgmt_frame(struct mac_context *mac,
 	uint8_t smeSessionId = 0;
 	bool isVHTEnabled = false;
 	tpSirMacMgmtHdr pMacHdr;
+	int ret;
+	tDot11fIEExtCap extr_ext_cap;
+	QDF_STATUS sir_status;
+	bool extr_ext_flag = true;
+	uint32_t ie_offset = 0;
+	tDot11fIEExtCap bcn_ext_cap;
+	uint8_t *bcn_ie = NULL;
+	uint32_t bcn_ie_len = 0;
+	uint8_t *p_ext_cap = NULL;
 
 	if (!pe_session)
 		return;
@@ -560,6 +647,29 @@ void lim_send_reassoc_req_mgmt_frame(struct mac_context *mac,
 
 	qdf_mem_zero((uint8_t *) frm, sizeof(*frm));
 
+	if (nAddIELen && pe_session->is_ext_caps_present) {
+		qdf_mem_zero((uint8_t *)&extr_ext_cap,
+			     sizeof(tDot11fIEExtCap));
+		sir_status = lim_strip_extcap_update_struct(
+					mac, pAddIE, &nAddIELen, &extr_ext_cap);
+		if (QDF_STATUS_SUCCESS != sir_status) {
+			extr_ext_flag = false;
+			pe_debug("Unable to Stripoff ExtCap IE from Assoc Req");
+		} else {
+			struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)
+							extr_ext_cap.bytes;
+
+			if (p_ext_cap->interworking_service)
+				p_ext_cap->qos_map = 1;
+			extr_ext_cap.num_bytes =
+				lim_compute_ext_cap_ie_length(&extr_ext_cap);
+			extr_ext_flag = (extr_ext_cap.num_bytes > 0);
+		}
+	} else {
+		pe_debug("No addn IE or peer doesn't support addnIE for Assoc Req");
+		extr_ext_flag = false;
+	}
+
 	caps = pMlmReassocReq->capabilityInfo;
 #if defined(FEATURE_WLAN_WAPI)
 	/*
@@ -689,6 +799,58 @@ void lim_send_reassoc_req_mgmt_frame(struct mac_context *mac,
 		pe_debug("Populate EHT IEs");
 		populate_dot11f_eht_caps(mac, pe_session, &frm->eht_cap);
 	}
+	/*
+	 * Extcap IE now support variable length, merge Extcap IE from addn_ie
+	 * may change the frame size. Therefore, MUST merge ExtCap IE before
+	 * dot11f get packed payload size.
+	 */
+	if (extr_ext_flag)
+		lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap, true);
+
+	/* Clear the bits in EXTCAP IE if AP not advertise it in beacon */
+	if (frm->ExtCap.present && pe_session->is_ext_caps_present) {
+		ie_offset = DOT11F_FF_TIMESTAMP_LEN +
+				DOT11F_FF_BEACONINTERVAL_LEN +
+				DOT11F_FF_CAPABILITIES_LEN;
+
+		qdf_mem_zero((uint8_t *)&bcn_ext_cap, sizeof(tDot11fIEExtCap));
+		if (pe_session->beacon && (pe_session->bcnLen >
+		    (ie_offset + sizeof(struct wlan_frame_hdr)))) {
+			bcn_ie = pe_session->beacon + ie_offset +
+						sizeof(struct wlan_frame_hdr);
+			bcn_ie_len = pe_session->bcnLen - ie_offset -
+						sizeof(struct wlan_frame_hdr);
+			p_ext_cap = (uint8_t *)wlan_get_ie_ptr_from_eid(
+							DOT11F_EID_EXTCAP,
+							bcn_ie, bcn_ie_len);
+			lim_update_extcap_struct(mac, p_ext_cap,
+						 &bcn_ext_cap);
+			lim_merge_extcap_struct(&frm->ExtCap, &bcn_ext_cap,
+						false);
+		}
+		/*
+		 * TWT extended capabilities should be populated after the
+		 * intersection of beacon caps and self caps is done because
+		 * the bits for TWT are unique to STA and AP and cannot be
+		 * intersected.
+		 */
+		populate_dot11f_twt_extended_caps(mac, pe_session,
+						  &frm->ExtCap);
+	}
+
+	/*
+	 * Do unpack to populate the add_ie buffer to frm structure
+	 * before packing the frm structure. In this way, the IE ordering
+	 * which the latest 802.11 spec mandates is maintained.
+	 */
+	if (nAddIELen) {
+		ret = dot11f_unpack_re_assoc_request(mac, pAddIE, nAddIELen,
+						     frm, true);
+		if (DOT11F_FAILED(ret)) {
+			pe_err("unpack failed, ret: 0x%x", ret);
+			goto end;
+		}
+	}
 
 	nStatus =
 		dot11f_get_packed_re_assoc_request_size(mac, frm, &nPayload);
@@ -700,7 +862,7 @@ void lim_send_reassoc_req_mgmt_frame(struct mac_context *mac,
 		pe_err("warning for size:ReAssoc Req: (0x%08x)", nStatus);
 	}
 
-	nBytes = nPayload + sizeof(tSirMacMgmtHdr) + nAddIELen;
+	nBytes = nPayload + sizeof(tSirMacMgmtHdr);
 
 	qdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
 				      (void **)&pPacket);
@@ -742,12 +904,6 @@ void lim_send_reassoc_req_mgmt_frame(struct mac_context *mac,
 		pe_session->assocReqLen = 0;
 	}
 
-	if (nAddIELen) {
-		qdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload,
-			     pAddIE, nAddIELen);
-		nPayload += nAddIELen;
-	}
-
 	pe_session->assoc_req = qdf_mem_malloc(nPayload);
 	if (pe_session->assoc_req) {
 		/* Store the Assocrequest. It is sent to csr in joincnfrsp */