Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 1 | /* |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 2 | * Copyright (c) 2011-2016 The Linux Foundation. All rights reserved. |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 3 | * |
| 4 | * Previously licensed under the ISC license by Qualcomm Atheros, Inc. |
| 5 | * |
| 6 | * |
| 7 | * Permission to use, copy, modify, and/or distribute this software for |
| 8 | * any purpose with or without fee is hereby granted, provided that the |
| 9 | * above copyright notice and this permission notice appear in all |
| 10 | * copies. |
| 11 | * |
| 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL |
| 13 | * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED |
| 14 | * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE |
| 15 | * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL |
| 16 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR |
| 17 | * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 18 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 19 | * PERFORMANCE OF THIS SOFTWARE. |
| 20 | */ |
| 21 | |
| 22 | /* |
| 23 | * This file was originally distributed by Qualcomm Atheros, Inc. |
| 24 | * under proprietary terms before Copyright ownership was assigned |
| 25 | * to the Linux Foundation. |
| 26 | */ |
| 27 | |
| 28 | /* |
| 29 | * |
| 30 | * This file lim_process_beacon_frame.cc contains the code |
| 31 | * for processing Received Beacon Frame. |
| 32 | * Author: Chandra Modumudi |
| 33 | * Date: 03/01/02 |
| 34 | * History:- |
| 35 | * Date Modified by Modification Information |
| 36 | * -------------------------------------------------------------------- |
| 37 | * |
| 38 | */ |
| 39 | |
| 40 | #include "wni_cfg.h" |
| 41 | #include "ani_global.h" |
| 42 | #include "cfg_api.h" |
| 43 | #include "sch_api.h" |
| 44 | #include "utils_api.h" |
| 45 | #include "lim_types.h" |
| 46 | #include "lim_utils.h" |
| 47 | #include "lim_assoc_utils.h" |
| 48 | #include "lim_prop_exts_utils.h" |
| 49 | #include "lim_ser_des_utils.h" |
| 50 | |
| 51 | /** |
| 52 | * lim_process_beacon_frame() - to process beacon frames |
| 53 | * @mac_ctx: Pointer to Global MAC structure |
| 54 | * @rx_pkt_info: A pointer to RX packet info structure |
| 55 | * @session: A pointer to session |
| 56 | * |
| 57 | * This function is called by limProcessMessageQueue() upon Beacon |
| 58 | * frame reception. |
| 59 | * Note: |
| 60 | * 1. Beacons received in 'normal' state in IBSS are handled by |
| 61 | * Beacon Processing module. |
| 62 | * |
| 63 | * Return: none |
| 64 | */ |
| 65 | |
| 66 | void |
| 67 | lim_process_beacon_frame(tpAniSirGlobal mac_ctx, uint8_t *rx_pkt_info, |
| 68 | tpPESession session) |
| 69 | { |
| 70 | tpSirMacMgmtHdr mac_hdr; |
| 71 | tSchBeaconStruct *bcn_ptr; |
| 72 | |
| 73 | mac_ctx->lim.gLimNumBeaconsRcvd++; |
| 74 | |
| 75 | /* |
| 76 | * here is it required to increment session specific heartBeat |
| 77 | * beacon counter |
| 78 | */ |
| 79 | mac_hdr = WMA_GET_RX_MAC_HEADER(rx_pkt_info); |
| 80 | lim_log(mac_ctx, LOG2, |
| 81 | FL("Received Beacon frame with length=%d from "), |
| 82 | WMA_GET_RX_MPDU_LEN(rx_pkt_info)); |
| 83 | lim_print_mac_addr(mac_ctx, mac_hdr->sa, LOG2); |
| 84 | |
| 85 | /* Expect Beacon in any state as Scan is independent of LIM state */ |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 86 | bcn_ptr = qdf_mem_malloc(sizeof(*bcn_ptr)); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 87 | if (NULL == bcn_ptr) { |
| 88 | lim_log(mac_ctx, LOGE, |
| 89 | FL("Unable to allocate memory")); |
| 90 | return; |
| 91 | } |
| 92 | /* Parse received Beacon */ |
| 93 | if (sir_convert_beacon_frame2_struct(mac_ctx, |
| 94 | rx_pkt_info, bcn_ptr) != |
| 95 | eSIR_SUCCESS) { |
| 96 | /* |
| 97 | * Received wrongly formatted/invalid Beacon. |
| 98 | * Ignore it and move on. |
| 99 | */ |
| 100 | lim_log(mac_ctx, LOGW, |
| 101 | FL("Received invalid Beacon in state %X"), |
| 102 | session->limMlmState); |
| 103 | lim_print_mlm_state(mac_ctx, LOGW, |
| 104 | session->limMlmState); |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 105 | qdf_mem_free(bcn_ptr); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 106 | return; |
| 107 | } |
| 108 | /* |
| 109 | * during scanning, when any session is active, and |
| 110 | * beacon/Pr belongs to one of the session, fill up the |
| 111 | * following, TBD - HB couter |
| 112 | */ |
| 113 | if ((!session->lastBeaconDtimPeriod) && |
| 114 | (sir_compare_mac_addr(session->bssId, |
| 115 | bcn_ptr->bssid))) { |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 116 | qdf_mem_copy((uint8_t *)&session->lastBeaconTimeStamp, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 117 | (uint8_t *) bcn_ptr->timeStamp, |
| 118 | sizeof(uint64_t)); |
| 119 | session->lastBeaconDtimCount = |
| 120 | bcn_ptr->tim.dtimCount; |
| 121 | session->lastBeaconDtimPeriod = |
| 122 | bcn_ptr->tim.dtimPeriod; |
| 123 | session->currentBssBeaconCnt++; |
| 124 | } |
| 125 | MTRACE(mac_trace(mac_ctx, |
| 126 | TRACE_CODE_RX_MGMT_TSF, 0, bcn_ptr->timeStamp[0]);) |
| 127 | MTRACE(mac_trace(mac_ctx, TRACE_CODE_RX_MGMT_TSF, 0, |
| 128 | bcn_ptr->timeStamp[1]);) |
| 129 | lim_check_and_add_bss_description(mac_ctx, bcn_ptr, |
| 130 | rx_pkt_info, false, true); |
| 131 | |
| 132 | if ((mac_ctx->lim.gLimMlmState == |
| 133 | eLIM_MLM_WT_PROBE_RESP_STATE) || |
| 134 | (mac_ctx->lim.gLimMlmState == |
| 135 | eLIM_MLM_PASSIVE_SCAN_STATE)) { |
| 136 | lim_check_and_add_bss_description(mac_ctx, bcn_ptr, |
| 137 | rx_pkt_info, |
| 138 | ((mac_ctx->lim.gLimHalScanState == |
| 139 | eLIM_HAL_SCANNING_STATE) ? true : false), |
| 140 | false); |
| 141 | /* |
| 142 | * Calling dfsChannelList which will convert DFS channel |
| 143 | * to active channel for x secs if this channel is DFS |
| 144 | */ |
| 145 | lim_set_dfs_channel_list(mac_ctx, |
| 146 | bcn_ptr->channelNumber, |
| 147 | &mac_ctx->lim.dfschannelList); |
| 148 | } else if (session->limMlmState == |
| 149 | eLIM_MLM_WT_JOIN_BEACON_STATE) { |
| 150 | if (session->beacon != NULL) { |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 151 | qdf_mem_free(session->beacon); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 152 | session->beacon = NULL; |
Sreelakshmi Konamki | 3b8ba61 | 2015-12-02 18:13:22 +0530 | [diff] [blame] | 153 | session->bcnLen = 0; |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 154 | } |
| 155 | session->bcnLen = WMA_GET_RX_PAYLOAD_LEN(rx_pkt_info); |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 156 | session->beacon = qdf_mem_malloc(session->bcnLen); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 157 | if (NULL == session->beacon) { |
| 158 | lim_log(mac_ctx, LOGE, |
| 159 | FL("fail to alloc mem to store bcn")); |
| 160 | } else { |
| 161 | /* |
| 162 | * Store the Beacon/ProbeRsp. This is sent to |
| 163 | * csr/hdd in join cnf response. |
| 164 | */ |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 165 | qdf_mem_copy(session->beacon, |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 166 | WMA_GET_RX_MPDU_DATA(rx_pkt_info), |
| 167 | session->bcnLen); |
| 168 | } |
| 169 | lim_check_and_announce_join_success(mac_ctx, bcn_ptr, |
| 170 | mac_hdr, session); |
| 171 | } |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 172 | qdf_mem_free(bcn_ptr); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 173 | return; |
| 174 | } |
| 175 | |
| 176 | /**--------------------------------------------------------------- |
| 177 | \fn lim_process_beacon_frame_no_session |
| 178 | \brief This function is called by limProcessMessageQueue() |
| 179 | \ upon Beacon reception. |
| 180 | \ |
| 181 | \param pMac |
| 182 | \param *pRxPacketInfo - A pointer to Rx packet info structure |
| 183 | \return None |
| 184 | ------------------------------------------------------------------*/ |
| 185 | void |
| 186 | lim_process_beacon_frame_no_session(tpAniSirGlobal pMac, uint8_t *pRxPacketInfo) |
| 187 | { |
| 188 | tpSirMacMgmtHdr pHdr; |
| 189 | tSchBeaconStruct *pBeacon; |
| 190 | |
| 191 | pMac->lim.gLimNumBeaconsRcvd++; |
| 192 | pHdr = WMA_GET_RX_MAC_HEADER(pRxPacketInfo); |
| 193 | |
| 194 | lim_log(pMac, LOG2, FL("Received Beacon frame with length=%d from "), |
| 195 | WMA_GET_RX_MPDU_LEN(pRxPacketInfo)); |
| 196 | lim_print_mac_addr(pMac, pHdr->sa, LOG2); |
| 197 | |
| 198 | |
| 199 | /** |
| 200 | * No session has been established. Expect Beacon only when |
| 201 | * 1. STA is in Scan mode waiting for Beacon/Probe response or |
| 202 | * 2. STA/AP is in Learn mode |
| 203 | */ |
| 204 | if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || |
| 205 | (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) || |
| 206 | (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE)) { |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 207 | pBeacon = qdf_mem_malloc(sizeof(tSchBeaconStruct)); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 208 | if (NULL == pBeacon) { |
| 209 | lim_log(pMac, LOGE, |
| 210 | FL |
| 211 | ("Unable to allocate memory in lim_process_beacon_frame_no_session")); |
| 212 | return; |
| 213 | } |
| 214 | |
| 215 | if (sir_convert_beacon_frame2_struct |
| 216 | (pMac, (uint8_t *) pRxPacketInfo, |
| 217 | pBeacon) != eSIR_SUCCESS) { |
| 218 | /* Received wrongly formatted/invalid Beacon. Ignore and move on. */ |
| 219 | lim_log(pMac, LOGW, |
| 220 | FL |
| 221 | ("Received invalid Beacon in global MLM state %X"), |
| 222 | pMac->lim.gLimMlmState); |
| 223 | lim_print_mlm_state(pMac, LOGW, pMac->lim.gLimMlmState); |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 224 | qdf_mem_free(pBeacon); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 225 | return; |
| 226 | } |
| 227 | |
| 228 | if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || |
| 229 | (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)) { |
| 230 | lim_check_and_add_bss_description(pMac, pBeacon, |
| 231 | pRxPacketInfo, true, |
| 232 | false); |
| 233 | /* Calling dfsChannelList which will convert DFS channel |
| 234 | * to Active channel for x secs if this channel is DFS channel */ |
| 235 | lim_set_dfs_channel_list(pMac, pBeacon->channelNumber, |
| 236 | &pMac->lim.dfschannelList); |
| 237 | } else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) { |
| 238 | } /* end of eLIM_MLM_LEARN_STATE) */ |
Anurag Chouhan | 600c3a0 | 2016-03-01 10:33:54 +0530 | [diff] [blame^] | 239 | qdf_mem_free(pBeacon); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 240 | } /* end of (eLIM_MLM_WT_PROBE_RESP_STATE) || (eLIM_MLM_PASSIVE_SCAN_STATE) */ |
| 241 | else { |
Sreelakshmi Konamki | 39acb13 | 2015-12-16 13:06:22 +0530 | [diff] [blame] | 242 | lim_log(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %s (%d)"), |
| 243 | lim_mlm_state_str(pMac->lim.gLimMlmState), |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 244 | pMac->lim.gLimMlmState); |
Prakash Dhavali | 7090c5f | 2015-11-02 17:55:19 -0800 | [diff] [blame] | 245 | #ifdef WLAN_DEBUG |
| 246 | pMac->lim.gLimUnexpBcnCnt++; |
| 247 | #endif |
| 248 | } |
| 249 | |
| 250 | return; |
| 251 | } /*** end lim_process_beacon_frame_no_session() ***/ |