From fbd279de9d1e967ca1381e2f7d52f14f75ec9535 Mon Sep 17 00:00:00 2001 From: Hu Wang Date: Mon, 31 Oct 2016 18:24:34 +0800 Subject: [PATCH] qcacld-3.0: Clear the bits in Ext Cap IE if AP not support qcacld-2.0 to qcacld-3.0 propagation Some specific AP will send assoc reject if DUT set the bits in Ext Cap IE which AP not advertise in beacon or probe response. To avoid the IoT issue, clear the bits in Ext Cap IE if AP not support. Change-Id: I632f5474331abf51257cacdcce412d7a110d2433 CRs-Fixed: 1052140 --- core/mac/src/pe/lim/lim_api.c | 2 +- .../src/pe/lim/lim_send_management_frames.c | 37 +++++++++++++++++-- core/mac/src/pe/lim/lim_utils.c | 29 ++++++++++++--- core/mac/src/pe/lim/lim_utils.h | 3 +- core/mac/src/pe/sch/sch_api.c | 3 +- core/mac/src/pe/sch/sch_beacon_gen.c | 3 +- 6 files changed, 63 insertions(+), 14 deletions(-) diff --git a/core/mac/src/pe/lim/lim_api.c b/core/mac/src/pe/lim/lim_api.c index fe6e0767dfc3..1bd1af39d5e7 100644 --- a/core/mac/src/pe/lim/lim_api.c +++ b/core/mac/src/pe/lim/lim_api.c @@ -2397,7 +2397,7 @@ QDF_STATUS lim_update_ext_cap_ie(tpAniSirGlobal mac_ctx, (*local_ie_len) += DOT11F_IE_EXTCAP_MAX_LEN; return QDF_STATUS_SUCCESS; } - lim_merge_extcap_struct(&driver_ext_cap, &default_scan_ext_cap); + lim_merge_extcap_struct(&driver_ext_cap, &default_scan_ext_cap, true); qdf_mem_copy(local_ie_buf + (*local_ie_len), driver_ext_cap.bytes, DOT11F_IE_EXTCAP_MAX_LEN); diff --git a/core/mac/src/pe/lim/lim_send_management_frames.c b/core/mac/src/pe/lim/lim_send_management_frames.c index 94c2f30c018e..991d2ee57ad8 100644 --- a/core/mac/src/pe/lim/lim_send_management_frames.c +++ b/core/mac/src/pe/lim/lim_send_management_frames.c @@ -376,7 +376,7 @@ lim_send_probe_req_mgmt_frame(tpAniSirGlobal mac_ctx, * dot11f get packed payload size. */ if (extracted_ext_cap_flag) - lim_merge_extcap_struct(&pr.ExtCap, &extracted_ext_cap); + lim_merge_extcap_struct(&pr.ExtCap, &extracted_ext_cap, true); /* That's it-- now we pack it. First, how much space are we going to */ status = dot11f_get_packed_probe_request_size(mac_ctx, &pr, &payload); @@ -778,7 +778,8 @@ lim_send_probe_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, * dot11f get packed payload size. */ if (extracted_ext_cap_flag) - lim_merge_extcap_struct(&frm->ExtCap, &extracted_ext_cap); + lim_merge_extcap_struct(&frm->ExtCap, &extracted_ext_cap, + true); status = dot11f_get_packed_probe_response_size(mac_ctx, frm, &payload); if (DOT11F_FAILED(status)) { @@ -1370,7 +1371,8 @@ lim_send_assoc_rsp_mgmt_frame(tpAniSirGlobal mac_ctx, * dot11f get packed payload size. */ if (extracted_flag) - lim_merge_extcap_struct(&(frm.ExtCap), &extracted_ext_cap); + lim_merge_extcap_struct(&(frm.ExtCap), &extracted_ext_cap, + true); /* Allocate a buffer for this frame: */ status = dot11f_get_packed_assoc_response_size(mac_ctx, &frm, &payload); @@ -1657,6 +1659,11 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, tDot11fIEExtCap extr_ext_cap; bool extr_ext_flag = true; tpSirMacMgmtHdr mac_hdr; + uint32_t ie_offset = 0; + uint8_t *p_ext_cap = NULL; + tDot11fIEExtCap bcn_ext_cap; + uint8_t *bcn_ie = NULL; + uint32_t bcn_ie_len = 0; if (NULL == pe_session) { lim_log(mac_ctx, LOGE, FL("pe_session is NULL")); @@ -1906,7 +1913,29 @@ lim_send_assoc_req_mgmt_frame(tpAniSirGlobal mac_ctx, * dot11f get packed payload size. */ if (extr_ext_flag) - lim_merge_extcap_struct(&frm->ExtCap, &extr_ext_cap); + 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) { + bcn_ie = pe_session->beacon + ie_offset; + bcn_ie_len = pe_session->bcnLen - ie_offset; + p_ext_cap = lim_get_ie_ptr_new(mac_ctx, + bcn_ie, + bcn_ie_len, + DOT11F_EID_EXTCAP, + ONE_BYTE); + lim_update_extcap_struct(mac_ctx, p_ext_cap, + &bcn_ext_cap); + lim_merge_extcap_struct(&frm->ExtCap, &bcn_ext_cap, + false); + } + } status = dot11f_get_packed_assoc_request_size(mac_ctx, frm, &payload); if (DOT11F_FAILED(status)) { diff --git a/core/mac/src/pe/lim/lim_utils.c b/core/mac/src/pe/lim/lim_utils.c index 02eb896363fc..5cc00df9946b 100644 --- a/core/mac/src/pe/lim/lim_utils.c +++ b/core/mac/src/pe/lim/lim_utils.c @@ -6647,7 +6647,7 @@ QDF_STATUS lim_send_ext_cap_ie(tpAniSirGlobal mac_ctx, if (merge && NULL != extra_extcap && extra_extcap->num_bytes > 0) { if (extra_extcap->num_bytes > ext_cap_data.num_bytes) num_bytes = extra_extcap->num_bytes; - lim_merge_extcap_struct(&ext_cap_data, extra_extcap); + lim_merge_extcap_struct(&ext_cap_data, extra_extcap, true); } /* Allocate memory for the WMI request, and copy the parameter */ @@ -6855,26 +6855,43 @@ tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx, * lim_merge_extcap_struct() - merge extended capabilities info * @dst: destination extended capabilities * @src: source extended capabilities + * @add: true if add the capabilites, false if strip the capabilites. * - * This function is used to take @src info and merge it with @dst - * extended capabilities info. + * This function is used to take @src info and add/strip it to/from + * @dst extended capabilities info. * * Return: None */ void lim_merge_extcap_struct(tDot11fIEExtCap *dst, - tDot11fIEExtCap *src) + tDot11fIEExtCap *src, + bool add) { uint8_t *tempdst = (uint8_t *)dst->bytes; uint8_t *tempsrc = (uint8_t *)src->bytes; uint8_t structlen = member_size(tDot11fIEExtCap, bytes); + /* Return if @src not present */ + if (!src->present) + return; + + /* Return if strip the capabilites from @dst which not present */ + if (!dst->present && !add) + return; + + /* Merge the capabilites info in other cases */ while (tempdst && tempsrc && structlen--) { - *tempdst |= *tempsrc; + if (add) + *tempdst |= *tempsrc; + else + *tempdst &= *tempsrc; tempdst++; tempsrc++; } - dst->present |= src->present; dst->num_bytes = lim_compute_ext_cap_ie_length(dst); + if (dst->num_bytes == 0) + dst->present = 0; + else + dst->present = 1; } /** diff --git a/core/mac/src/pe/lim/lim_utils.h b/core/mac/src/pe/lim/lim_utils.h index e175545489ae..97ccf1796782 100644 --- a/core/mac/src/pe/lim/lim_utils.h +++ b/core/mac/src/pe/lim/lim_utils.h @@ -608,7 +608,8 @@ void lim_update_extcap_struct(tpAniSirGlobal mac_ctx, uint8_t *buf, tDot11fIEExtCap *ext_cap); tSirRetStatus lim_strip_extcap_update_struct(tpAniSirGlobal mac_ctx, uint8_t *addn_ie, uint16_t *addn_ielen, tDot11fIEExtCap *dst); -void lim_merge_extcap_struct(tDot11fIEExtCap *dst, tDot11fIEExtCap *src); +void lim_merge_extcap_struct(tDot11fIEExtCap *dst, tDot11fIEExtCap *src, + bool add); uint8_t lim_get_80Mhz_center_channel(uint8_t primary_channel); void lim_update_obss_scanparams(tpPESession session, diff --git a/core/mac/src/pe/sch/sch_api.c b/core/mac/src/pe/sch/sch_api.c index 2a62188f4192..20347bbbe0f4 100644 --- a/core/mac/src/pe/sch/sch_api.c +++ b/core/mac/src/pe/sch/sch_api.c @@ -414,7 +414,8 @@ uint32_t lim_send_probe_rsp_template_to_hal(tpAniSirGlobal pMac, prb_rsp_frm = &psessionEntry->probeRespFrame; if (extcap_present) lim_merge_extcap_struct(&prb_rsp_frm->ExtCap, - &extracted_extcap); + &extracted_extcap, + true); nStatus = dot11f_get_packed_probe_response_size(pMac, &psessionEntry->probeRespFrame, &nPayload); diff --git a/core/mac/src/pe/sch/sch_beacon_gen.c b/core/mac/src/pe/sch/sch_beacon_gen.c index c1d5235b50f8..6edd75e7d77d 100644 --- a/core/mac/src/pe/sch/sch_beacon_gen.c +++ b/core/mac/src/pe/sch/sch_beacon_gen.c @@ -493,7 +493,8 @@ sch_set_fixed_beacon_fields(tpAniSirGlobal mac_ctx, tpPESession session) if (extcap_present && session->limSystemRole != eLIM_STA_IN_IBSS_ROLE) lim_merge_extcap_struct(&bcn_2->ExtCap, - &extracted_extcap); + &extracted_extcap, + true); }