blob: d04247e8e7fd1af120607f36ac2722a286e0d4ef [file] [log] [blame]
Padma, Santhosh Kumar67f479b2016-12-28 15:43:42 +05301/*
2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#include "aniGlobal.h"
31#include "smeInside.h"
32#include "csrInsideApi.h"
33#include "smsDebug.h"
34#include "macTrace.h"
35#include "csrNeighborRoam.h"
36
37#define PREAUTH_REASSOC_MBB_TIMER_VALUE 60
38
39#define CSR_NEIGHBOR_ROAM_STATE_TRANSITION(newState)\
40{\
41 mac->roam.neighborRoamInfo.prevNeighborRoamState = mac->roam.neighborRoamInfo.neighborRoamState;\
42 mac->roam.neighborRoamInfo.neighborRoamState = newState;\
43 VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, \
44 FL("Neighbor Roam Transition from state %s ==> %s"), \
45 csrNeighborRoamStateToString (mac->roam.neighborRoamInfo.prevNeighborRoamState), \
46 csrNeighborRoamStateToString (newState));\
47}
48
49/**
50 * csr_roam_issue_preauth_reassoc_req() -Prepares preauth request
51 * @hal: HAL context
52 * @session_id: session id
53 * @bss_description: BSS description
54 *
55 * This function prepares preauth request and sends request to PE
56 *
57 * Return: eHAL_STATUS_SUCCESS on success,
58 * : eHAL_STATUS_RESOURCES when resource allocation is failure
59 * : eHAL_STATUS_FAILURE otherwise
60 */
61eHalStatus csr_roam_issue_preauth_reassoc_req(tHalHandle hal,
62 tANI_U32 session_id, tpSirBssDescription bss_description)
63{
64 tpAniSirGlobal mac = PMAC_STRUCT(hal);
65 tpSirFTPreAuthReq pre_auth_req;
66 tANI_U16 auth_req_len = 0;
67 tCsrRoamSession *session = CSR_GET_SESSION(mac, session_id);
68
69 auth_req_len = sizeof(tSirFTPreAuthReq);
70 pre_auth_req = (tpSirFTPreAuthReq)vos_mem_malloc(auth_req_len);
71 if (NULL == pre_auth_req) {
72 smsLog(mac, LOGE,
73 FL("Memory allocation for Preauth request failed"));
74 return eHAL_STATUS_RESOURCES;
75 }
76
77 /*
78 * Save the SME Session ID here. We need it while processing
79 * the preauth response.
80 */
81 mac->ft.ftSmeContext.smeSessionId = session_id;
82 vos_mem_zero(pre_auth_req, auth_req_len);
83
84 pre_auth_req->pbssDescription = (tpSirBssDescription)vos_mem_malloc(
85 sizeof(bss_description->length) + bss_description->length);
86
87 pre_auth_req->messageType =
88 pal_cpu_to_be16(eWNI_SME_MBB_PRE_AUTH_REASSOC_REQ);
89
90 pre_auth_req->preAuthchannelNum = bss_description->channelId;
91
92 /*
93 * Set is_preauth_lfr_mbb which will be checked in
94 * limProcessAuthFrameNoSession
95 */
96 mac->ft.ftSmeContext.is_preauth_lfr_mbb = true;
97 smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"),
98 mac->ft.ftSmeContext.is_preauth_lfr_mbb);
99
100 vos_mem_copy((void *)&pre_auth_req->currbssId,
101 (void *)session->connectedProfile.bssid, sizeof(tSirMacAddr));
102 vos_mem_copy((void *)&pre_auth_req->preAuthbssId,
103 (void *)bss_description->bssId, sizeof(tSirMacAddr));
104
105 vos_mem_copy(pre_auth_req->pbssDescription, bss_description,
106 sizeof(bss_description->length) + bss_description->length);
107 pre_auth_req->length = pal_cpu_to_be16(auth_req_len);
108 return palSendMBMessage(mac->hHdd, pre_auth_req);
109}
110
111/**
112 * csr_neighbor_roam_issue_preauth_reassoc() -issues preauth_reassoc request
113 * @mac: MAC context
114 *
115 * This function issues preauth_reassoc request to PE with the 1st AP
116 * entry in the roamable AP list
117 *
118 * Return: eHAL_STATUS_SUCCESS on success, eHAL_STATUS_FAILURE otherwise
119 */
120eHalStatus csr_neighbor_roam_issue_preauth_reassoc(tpAniSirGlobal mac)
121{
122 tpCsrNeighborRoamControlInfo neighbor_roam_info =
123 &mac->roam.neighborRoamInfo;
124 eHalStatus status = eHAL_STATUS_SUCCESS;
125 tpCsrNeighborRoamBSSInfo neighbor_bss_node;
126
127 VOS_ASSERT(neighbor_roam_info->FTRoamInfo.preauthRspPending ==
128 eANI_BOOLEAN_FALSE);
129
130 neighbor_bss_node = csrNeighborRoamGetRoamableAPListNextEntry(mac,
131 &neighbor_roam_info->roamableAPList, NULL);
132
133 if (neighbor_bss_node == NULL)
134 {
135 smsLog(mac, LOGE, FL("Roamable AP list is empty"));
136 return eHAL_STATUS_FAILURE;
137 }
138 else
139 {
140 status = csrRoamEnqueuePreauth(mac,
141 neighbor_roam_info->csrSessionId,
142 neighbor_bss_node->pBssDescription,
143 ecsr_mbb_perform_preauth_reassoc,
144 eANI_BOOLEAN_TRUE);
145
146 smsLog(mac, LOG1, FL("Before Pre-Auth: BSSID "MAC_ADDRESS_STR", Ch:%d"),
147 MAC_ADDR_ARRAY(neighbor_bss_node->pBssDescription->bssId),
148 neighbor_bss_node->pBssDescription->channelId);
149
150 if (eHAL_STATUS_SUCCESS != status)
151 {
152 smsLog(mac, LOGE,
153 FL("Send Preauth request to PE failed with status %d"),
154 status);
155 return status;
156 }
157 }
158
159 neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_TRUE;
160
161 CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC)
162 return status;
163}
164
165/**
166 * csr_stop_preauth_reassoc_mbb_timer() -stops preauth_reassoc timer
167 * @mac: MAC context
168 *
169 * This function stops preauth_reassoc timer
170 *
171 */
172void csr_stop_preauth_reassoc_mbb_timer(tpAniSirGlobal mac)
173{
174 if (mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started)
175 vos_timer_stop(&mac->ft.ftSmeContext.pre_auth_reassoc_mbb_timer);
176}
177
178
179/**
180 * csr_preauth_reassoc_mbb_timer_callback() -preauth_reassoc timer callback
181 * @mac: MAC context
182 *
183 * This function issues preauth_reassoc with another roamable entry
184 *
185 */
186void csr_preauth_reassoc_mbb_timer_callback(void *context)
187{
188 tpAniSirGlobal mac = (tpAniSirGlobal)context;
189
190 mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = 0;
191 csr_neighbor_roam_issue_preauth_reassoc(mac);
192}
193
194
195/**
196 * csr_roam_dequeue_preauth_reassoc() -Dequeues
197 * ecsr_mbb_perform_preauth_reassoc
198 * @mac: MAC context
199 *
200 * This function dequeues ecsr_mbb_perform_preauth_reassoc
201 *
202 */
203eHalStatus csr_roam_dequeue_preauth_reassoc(tpAniSirGlobal mac)
204{
205 tListElem *entry;
206 tSmeCmd *command;
207 entry = csrLLPeekHead(&mac->sme.smeCmdActiveList, LL_ACCESS_LOCK);
208 if (entry) {
209 command = GET_BASE_ADDR(entry, tSmeCmd, Link);
210 if ((eSmeCommandRoam == command->command) &&
211 (ecsr_mbb_perform_preauth_reassoc ==
212 command->u.roamCmd.roamReason)) {
213 smsLog(mac, LOG1, FL("DQ-Command = %d, Reason = %d"),
214 command->command, command->u.roamCmd.roamReason);
215 if (csrLLRemoveEntry( &mac->sme.smeCmdActiveList,
216 entry, LL_ACCESS_LOCK)) {
217 csrReleaseCommandPreauth( mac, command );
218 }
219 } else {
220 smsLog(mac, LOGE, FL("Command = %d, Reason = %d "),
221 command->command, command->u.roamCmd.roamReason);
222 }
223 }
224 else {
225 smsLog(mac, LOGE,
226 FL("pEntry NULL for eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP"));
227 }
228 smeProcessPendingQueue( mac );
229 return eHAL_STATUS_SUCCESS;
230}
231
232/**
233 * csr_neighbor_roam_preauth_reassoc_rsp_handler() -handles preauth
234 * reassoc response
235 * @mac: MAC context
236 * @lim_status: status of preauth reassoc response from lim
237 *
238 * This function handles preauth_reassoc response from PE. When
239 * preauth_reassoc response failure is received, preauth reassoc
240 * with new candidate will be attempted. In success case, candidate will be
241 * removed from roamable entry.
242 *
243 */
244eHalStatus
245csr_neighbor_roam_preauth_reassoc_rsp_handler(tpAniSirGlobal mac,
246 tSirRetStatus lim_status)
247{
248 tpCsrNeighborRoamControlInfo neighbor_roam_info =
249 &mac->roam.neighborRoamInfo;
250 eHalStatus status = eHAL_STATUS_SUCCESS;
251 eHalStatus preauth_processed = eHAL_STATUS_SUCCESS;
252 tpCsrNeighborRoamBSSInfo preauth_rsp_node = NULL;
253
254 if (eANI_BOOLEAN_FALSE ==
255 neighbor_roam_info->FTRoamInfo.preauthRspPending) {
256 /*
257 * This can happen when we disconnect immediately after sending
258 * a pre-auth request. During processing of the disconnect command,
259 * we would have reset preauthRspPending and transitioned to INIT state.
260 */
261 smsLog(mac, LOGE,
262 FL("Unexpected pre-auth response in state %d"),
263 neighbor_roam_info->neighborRoamState);
264 preauth_processed = eHAL_STATUS_FAILURE;
265 goto DEQ_PREAUTH;
266 }
267
268 if ((neighbor_roam_info->neighborRoamState !=
269 eCSR_NEIGHBOR_ROAM_STATE_MBB_PREAUTH_REASSOC)) {
270 smsLog(mac, LOGE,
271 FL("Preauth response received in state %s"),
272 macTraceGetNeighbourRoamState(
273 neighbor_roam_info->neighborRoamState));
274 preauth_processed = eHAL_STATUS_FAILURE;
275 goto DEQ_PREAUTH;
276 }
277
278 neighbor_roam_info->FTRoamInfo.preauthRspPending = eANI_BOOLEAN_FALSE;
279
280 if (eSIR_SUCCESS == lim_status)
281 preauth_rsp_node = csrNeighborRoamGetRoamableAPListNextEntry(mac,
282 &neighbor_roam_info->roamableAPList, NULL);
283
284 if ((eSIR_SUCCESS == lim_status) && (NULL != preauth_rsp_node)) {
285 smsLog(mac, LOG1, FL("MBB Reassoc completed successfully"));
286
287 smsLog(mac, LOG1, FL("After MBB reassoc BSSID "MAC_ADDRESS_STR" Ch %d"),
288 MAC_ADDR_ARRAY(preauth_rsp_node->pBssDescription->bssId),
289 preauth_rsp_node->pBssDescription->channelId);
290
291 /*
292 * MBB Reassoc competer successfully. Insert the preauthenticated
293 * node to tail of preAuthDoneList
294 */
295 csrNeighborRoamRemoveRoamableAPListEntry(mac,
296 &neighbor_roam_info->roamableAPList, preauth_rsp_node);
297 csrLLInsertTail(&neighbor_roam_info->FTRoamInfo.preAuthDoneList,
298 &preauth_rsp_node->List, LL_ACCESS_LOCK);
299 } else {
300 tpCsrNeighborRoamBSSInfo neighbor_bss_node = NULL;
301 tListElem *entry;
302
303 smsLog(mac, LOG1,
304 FL("Pre-Auth failed BSSID "MAC_ADDRESS_STR" Ch:%d status = %d"),
305 MAC_ADDR_ARRAY(preauth_rsp_node->pBssDescription->bssId),
306 preauth_rsp_node->pBssDescription->channelId, lim_status);
307
308 /*
309 * Pre-auth failed. Add the bssId to the preAuth failed list MAC Address.
310 * Also remove the AP from roamable AP list. The one in the head of the
311 * list should be one with which we issued pre-auth and failed.
312 */
313 entry = csrLLRemoveHead(&neighbor_roam_info->roamableAPList,
314 LL_ACCESS_LOCK);
315 if(entry) {
316 neighbor_bss_node = GET_BASE_ADDR(entry,
317 tCsrNeighborRoamBSSInfo, List);
318 /*
319 * Add the BSSID to pre-auth fail list if it is
320 * not requested by HDD
321 */
322 status = csrNeighborRoamAddBssIdToPreauthFailList(mac,
323 neighbor_bss_node->pBssDescription->bssId);
324
325 /* Now we can free this node */
326 csrNeighborRoamFreeNeighborRoamBSSNode(mac, neighbor_bss_node);
327 }
328
329 /* Dequeue ecsr_mbb_perform_preauth_reassoc */
330 csr_roam_dequeue_preauth_reassoc(mac);
331
332 /*
333 * Move state to Connected. Connected state here signifies connection
334 * with current AP as preauth failed with roamable AP. Still driver has
335 * connection with current AP.
336 */
337 CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
338
339 /* Start a timer to issue preauth_reassoc request for the next entry*/
340 status = vos_timer_start(&mac->ft.ftSmeContext.
341 pre_auth_reassoc_mbb_timer, PREAUTH_REASSOC_MBB_TIMER_VALUE);
342 if (eHAL_STATUS_SUCCESS != status) {
343 smsLog(mac, LOGE,
344 FL("pre_auth_reassoc_mbb_timer start failed status %d"),
345 status);
346 return eHAL_STATUS_FAILURE;
347 }
348 mac->roam.neighborRoamInfo.is_pre_auth_reassoc_mbb_timer_started = true;
349 return eHAL_STATUS_SUCCESS;
350 }
351
352DEQ_PREAUTH:
353 csr_roam_dequeue_preauth_reassoc(mac);
354 return preauth_processed;
355}
356
357/**
358 * csr_roam_preauth_rsp_mbb_processor() -handles
359 * eWNI_SME_MBB_PRE_AUTH_REASSOC_RSP
360 * @hal: HAL context
361 *
362 * This function invokes preauth reassoc response handler and
363 * updates CSR with new connection information.
364 *
365 */
366void csr_roam_preauth_rsp_mbb_processor(tHalHandle hal,
367 tpSirFTPreAuthRsp pre_auth_rsp)
368{
369 tpAniSirGlobal mac = PMAC_STRUCT(hal);
370 eHalStatus status;
371
372 mac->ft.ftSmeContext.is_preauth_lfr_mbb = false;
373 smsLog(mac, LOG1, FL("is_preauth_lfr_mbb %d"),
374 mac->ft.ftSmeContext.is_preauth_lfr_mbb);
375
376 status = csr_neighbor_roam_preauth_reassoc_rsp_handler(mac,
377 pre_auth_rsp->status);
378 if (status != eHAL_STATUS_SUCCESS) {
379 smsLog(mac, LOGE,FL("Preauth was not processed: %d SessionID: %d"),
380 status, pre_auth_rsp->smeSessionId);
381 return;
382 }
383
384 /*
385 * The below function calls/timers should be invoked only
386 * if the pre-auth is successful.
387 */
388 if (VOS_STATUS_SUCCESS != (VOS_STATUS)pre_auth_rsp->status)
389 return;
390
391 mac->ft.ftSmeContext.FTState = eFT_AUTH_COMPLETE;
392
393 /* Save the received response */
394 vos_mem_copy((void *)&mac->ft.ftSmeContext.preAuthbssId,
395 (void *)pre_auth_rsp->preAuthbssId, sizeof(tCsrBssid));
396
397
398 /* To Do: add code to update CSR for new connection */
399
400 CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED)
401}
402