blob: fa5a0ab3010c41d8b0cad7d0a04a4d426d105b56 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
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 * lim_process_tdls.c
30 * OVERVIEW:
31 *
32 * DEPENDENCIES:
33 *
34 * Are listed for each API below.
35 * ===========================================================================*/
36
37/*===========================================================================
38
39 * EDIT HISTORY FOR FILE
40
41 * This section contains comments describing changes made to the module.
42 * Notice that changes are listed in reverse chronological order.
43
44 * $Header$$DateTime$$Author$
45
46 * when who what, where, why
47 * ---------- --- ------------------------------------------------------
48 * 05/05/2010 Ashwani Initial Creation, added TDLS action frame
49 * functionality,TDLS message exchange with SME..etc..
50
51 ===========================================================================*/
52
53/**
54 * \file lim_process_tdls.c
55 *
56 * \brief Code for preparing,processing and sending 802.11z action frames
57 *
58 */
59
60#ifdef FEATURE_WLAN_TDLS
61
62#include "sir_api.h"
63#include "ani_global.h"
64#include "sir_mac_prot_def.h"
65#include "cfg_api.h"
66#include "utils_api.h"
67#include "lim_types.h"
68#include "lim_utils.h"
69#include "lim_security_utils.h"
70#include "dot11f.h"
71#include "lim_sta_hash_api.h"
72#include "sch_api.h"
73#include "lim_send_messages.h"
74#include "utils_parser.h"
75#include "lim_assoc_utils.h"
76#include "dph_hash_table.h"
77#include "wma_types.h"
78#include "cds_regdomain_common.h"
79
80/* define NO_PAD_TDLS_MIN_8023_SIZE to NOT padding: See CR#447630
81 There was IOT issue with cisco 1252 open mode, where it pads
82 discovery req/teardown frame with some junk value up to min size.
83 To avoid this issue, we pad QCOM_VENDOR_IE.
84 If there is other IOT issue because of this bandage, define NO_PAD...
85 */
86#ifndef NO_PAD_TDLS_MIN_8023_SIZE
87#define MIN_IEEE_8023_SIZE 46
88#define MIN_VENDOR_SPECIFIC_IE_SIZE 5
89#endif
90
91static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac,
92 tSirTdlsAddStaReq * pAddStaReq, tpPESession psessionEntry);
93void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry,
94 tDot11fIELinkIdentifier *linkIden,
95 tSirMacAddr peerMac, uint8_t reqType);
96void populate_dot11f_tdls_ext_capability(tpAniSirGlobal pMac,
97 tpPESession psessionEntry,
98 tDot11fIEExtCap *extCapability);
99
100void populate_dot11f_tdls_offchannel_params(tpAniSirGlobal pMac,
101 tpPESession psessionEntry,
102 tDot11fIESuppChannels *suppChannels,
103 tDot11fIESuppOperatingClasses *
104 suppOperClasses);
105void lim_log_vht_cap(tpAniSirGlobal pMac, tDot11fIEVHTCaps *pDot11f);
106tSirRetStatus lim_populate_vht_mcs_set(tpAniSirGlobal pMac,
107 tpSirSupportedRates pRates,
108 tDot11fIEVHTCaps *pPeerVHTCaps,
109 tpPESession psessionEntry);
110ePhyChanBondState lim_get_htcb_state(ePhyChanBondState aniCBMode);
111
112/*
113 * TDLS data frames will go out/come in as non-qos data.
114 * so, eth_890d_header will be aligned access..
115 */
116static const uint8_t eth_890d_header[] = {
117 0xaa, 0xaa, 0x03, 0x00,
118 0x00, 0x00, 0x89, 0x0d,
119};
120
121/*
122 * type of links used in TDLS
123 */
124enum tdlsLinks {
125 TDLS_LINK_AP,
126 TDLS_LINK_DIRECT
127} e_tdls_link;
128
129/*
130 * node status in node searching
131 */
132enum tdlsLinkNodeStatus {
133 TDLS_NODE_NOT_FOUND,
134 TDLS_NODE_FOUND
135} e_tdls_link_node_status;
136
137enum tdlsReqType {
138 TDLS_INITIATOR,
139 TDLS_RESPONDER
140} e_tdls_req_type;
141
142typedef enum tdlsLinkSetupStatus {
143 TDLS_SETUP_STATUS_SUCCESS = 0,
144 TDLS_SETUP_STATUS_FAILURE = 37
145} etdlsLinkSetupStatus;
146
147/* These maps to Kernel TDLS peer capability
148 * flags and should get changed as and when necessary
149 */
150enum tdls_peer_capability {
151 TDLS_PEER_HT_CAP = 0,
152 TDLS_PEER_VHT_CAP = 1,
153 TDLS_PEER_WMM_CAP = 2
154} e_tdls_peer_capability;
155
156/* some local defines */
157#define LINK_IDEN_ADDR_OFFSET(x) (&x.LinkIdentifier)
158#define PTI_LINK_IDEN_OFFSET (5)
159#define PTI_BUF_STATUS_OFFSET (25)
160
161/* TODO, Move this parameters to configuration */
162#define PEER_PSM_SUPPORT (0)
163#define TDLS_SUPPORT (1)
164#define TDLS_PROHIBITED (0)
165#define TDLS_CH_SWITCH_PROHIBITED (1)
166/** @brief Set bit manipulation macro */
167#define SET_BIT(value, mask) ((value) |= (1 << (mask)))
168/** @brief Clear bit manipulation macro */
169#define CLEAR_BIT(value, mask) ((value) &= ~(1 << (mask)))
170/** @brief Check bit manipulation macro */
171#define CHECK_BIT(value, mask) ((value) & (1 << (mask)))
172
173#define SET_PEER_AID_BITMAP(peer_bitmap, aid) \
174 do { \
175 if ((aid) < (sizeof(uint32_t) << 3)) \
176 SET_BIT(peer_bitmap[0], (aid)); \
177 else if ((aid) < (sizeof(uint32_t) << 4)) \
178 SET_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\
179 } while (0);
180
181#define CLEAR_PEER_AID_BITMAP(peer_bitmap, aid) \
182 do { \
183 if ((aid) < (sizeof(uint32_t) << 3)) \
184 CLEAR_BIT(peer_bitmap[0], (aid)); \
185 else if ((aid) < (sizeof(uint32_t) << 4)) \
186 CLEAR_BIT(peer_bitmap[1], ((aid) - (sizeof(uint32_t) << 3)));\
187 } while (0);
188
189#ifdef LIM_DEBUG_TDLS
190
191#ifdef FEATURE_WLAN_TDLS
192#define WNI_CFG_TDLS_LINK_SETUP_RSP_TIMEOUT (800)
193#define WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT (200)
194#endif
195
196#define IS_QOS_ENABLED(psessionEntry) ((((psessionEntry)->limQosEnabled) && \
197 SIR_MAC_GET_QOS((psessionEntry)->limCurrentBssCaps)) || \
198 (((psessionEntry)->limWmeEnabled) && \
199 LIM_BSS_CAPS_GET(WME, (psessionEntry)->limCurrentBssQosCaps)))
200
201#define TID_AC_VI 4
202#define TID_AC_BK 1
203
204const uint8_t *lim_trace_tdls_action_string(uint8_t tdlsActionCode)
205{
206 switch (tdlsActionCode) {
207 CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_REQ);
208 CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_RSP);
209 CASE_RETURN_STRING(SIR_MAC_TDLS_SETUP_CNF);
210 CASE_RETURN_STRING(SIR_MAC_TDLS_TEARDOWN);
211 CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_IND);
212 CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_REQ);
213 CASE_RETURN_STRING(SIR_MAC_TDLS_CH_SWITCH_RSP);
214 CASE_RETURN_STRING(SIR_MAC_TDLS_PEER_TRAFFIC_RSP);
215 CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_REQ);
216 CASE_RETURN_STRING(SIR_MAC_TDLS_DIS_RSP);
217 }
218 return (const uint8_t *)"UNKNOWN";
219}
220#endif
221/*
222 * initialize TDLS setup list and related data structures.
223 */
224void lim_init_tdls_data(tpAniSirGlobal pMac, tpPESession pSessionEntry)
225{
226 lim_init_peer_idxpool(pMac, pSessionEntry);
227
228 return;
229}
230
231/*
232 * prepare TDLS frame header, it includes
233 * | | | |
234 * |802.11 header|RFC1042 header|TDLS_PYLOAD_TYPE|PAYLOAD
235 * | | | |
236 */
237static uint32_t lim_prepare_tdls_frame_header(tpAniSirGlobal pMac, uint8_t *pFrame,
238 tDot11fIELinkIdentifier *link_iden,
239 uint8_t tdlsLinkType, uint8_t reqType,
240 uint8_t tid,
241 tpPESession psessionEntry)
242{
243 tpSirMacDataHdr3a pMacHdr;
244 uint32_t header_offset = 0;
245 uint8_t *addr1 = NULL;
246 uint8_t *addr3 = NULL;
247 uint8_t toDs = (tdlsLinkType == TDLS_LINK_AP)
248 ? ANI_TXDIR_TODS : ANI_TXDIR_IBSS;
249 uint8_t *peerMac = (reqType == TDLS_INITIATOR)
250 ? link_iden->RespStaAddr : link_iden->InitStaAddr;
251 uint8_t *staMac = (reqType == TDLS_INITIATOR)
252 ? link_iden->InitStaAddr : link_iden->RespStaAddr;
253
254 pMacHdr = (tpSirMacDataHdr3a) (pFrame);
255
256 /*
257 * if TDLS frame goes through the AP link, it follows normal address
258 * pattern, if TDLS frame goes thorugh the direct link, then
259 * A1--> Peer STA addr, A2-->Self STA address, A3--> BSSID
260 */
261 (tdlsLinkType == TDLS_LINK_AP) ? ((addr1 = (link_iden->bssid)),
262 (addr3 = (peerMac)))
263 : ((addr1 = (peerMac)), (addr3 = (link_iden->bssid)));
264 /*
265 * prepare 802.11 header
266 */
267 pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION;
268 pMacHdr->fc.type = SIR_MAC_DATA_FRAME;
269 pMacHdr->fc.subType =
270 IS_QOS_ENABLED(psessionEntry) ? SIR_MAC_DATA_QOS_DATA :
271 SIR_MAC_DATA_DATA;
272
273 /*
274 * TL is not setting up below fields, so we are doing it here
275 */
276 pMacHdr->fc.toDS = toDs;
277 pMacHdr->fc.powerMgmt = 0;
278 pMacHdr->fc.wep = (psessionEntry->encryptType == eSIR_ED_NONE) ? 0 : 1;
279
280 cdf_mem_copy((uint8_t *) pMacHdr->addr1,
281 (uint8_t *) addr1, sizeof(tSirMacAddr));
282 cdf_mem_copy((uint8_t *) pMacHdr->addr2,
283 (uint8_t *) staMac, sizeof(tSirMacAddr));
284
285 cdf_mem_copy((uint8_t *) pMacHdr->addr3,
286 (uint8_t *) (addr3), sizeof(tSirMacAddr));
287
288 lim_log(pMac, LOG1,
289 FL(
290 "Preparing TDLS frame header to %s A1:"
291 MAC_ADDRESS_STR", A2:"MAC_ADDRESS_STR", A3:"
292 MAC_ADDRESS_STR
293 ),
294 (tdlsLinkType == TDLS_LINK_AP) ? "AP" : "DIRECT",
295 MAC_ADDR_ARRAY(pMacHdr->addr1),
296 MAC_ADDR_ARRAY(pMacHdr->addr2),
297 MAC_ADDR_ARRAY(pMacHdr->addr3));
298
299 if (IS_QOS_ENABLED(psessionEntry)) {
300 pMacHdr->qosControl.tid = tid;
301 header_offset += sizeof(tSirMacDataHdr3a);
302 } else
303 header_offset += sizeof(tSirMacMgmtHdr);
304
305 /*
306 * Now form RFC1042 header
307 */
308 cdf_mem_copy((uint8_t *) (pFrame + header_offset),
309 (uint8_t *) eth_890d_header, sizeof(eth_890d_header));
310
311 header_offset += sizeof(eth_890d_header);
312
313 /* add payload type as TDLS */
314 *(pFrame + header_offset) = PAYLOAD_TYPE_TDLS;
315 header_offset += PAYLOAD_TYPE_TDLS_SIZE;
316 return header_offset;
317}
318
319/*
320 * TX Complete for Management frames
321 */
322CDF_STATUS lim_mgmt_tx_complete(tpAniSirGlobal pMac, uint32_t txCompleteSuccess)
323{
324 tpPESession psessionEntry = NULL;
325
326 if (0xff != pMac->lim.mgmtFrameSessionId) {
327 psessionEntry =
328 pe_find_session_by_session_id(pMac,
329 pMac->lim.mgmtFrameSessionId);
330 if (NULL == psessionEntry) {
331 lim_log(pMac, LOGE, FL("sessionID %d is not found"),
332 pMac->lim.mgmtFrameSessionId);
333 return CDF_STATUS_E_FAILURE;
334 }
335 lim_send_sme_mgmt_tx_completion(pMac, psessionEntry,
336 txCompleteSuccess);
337 pMac->lim.mgmtFrameSessionId = 0xff;
338 }
339 return CDF_STATUS_SUCCESS;
340}
341
342/*
343 * This function can be used for bacst or unicast discovery request
344 * We are not differentiating it here, it will all depnds on peer MAC address,
345 */
346tSirRetStatus lim_send_tdls_dis_req_frame(tpAniSirGlobal pMac, tSirMacAddr peer_mac,
347 uint8_t dialog, tpPESession psessionEntry)
348{
349 tDot11fTDLSDisReq tdlsDisReq;
350 uint32_t status = 0;
351 uint32_t nPayload = 0;
352 uint32_t size = 0;
353 uint32_t nBytes = 0;
354 uint32_t header_offset = 0;
355 uint8_t *pFrame;
356 void *pPacket;
357 CDF_STATUS cdf_status;
358#ifndef NO_PAD_TDLS_MIN_8023_SIZE
359 uint32_t padLen = 0;
360#endif
361 uint8_t smeSessionId = 0;
362
363 if (NULL == psessionEntry) {
364 lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
365 return eSIR_FAILURE;
366 }
367 smeSessionId = psessionEntry->smeSessionId;
368 /*
369 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
370 * and then hand it off to 'dot11f_pack_probe_request' (for
371 * serialization). We start by zero-initializing the structure:
372 */
373 cdf_mem_set((uint8_t *) &tdlsDisReq, sizeof(tDot11fTDLSDisReq), 0);
374
375 /*
376 * setup Fixed fields,
377 */
378 tdlsDisReq.Category.category = SIR_MAC_ACTION_TDLS;
379 tdlsDisReq.Action.action = SIR_MAC_TDLS_DIS_REQ;
380 tdlsDisReq.DialogToken.token = dialog;
381
382 size = sizeof(tSirMacAddr);
383
384 populate_dot11f_link_iden(pMac, psessionEntry, &tdlsDisReq.LinkIdentifier,
385 peer_mac, TDLS_INITIATOR);
386
387 /*
388 * now we pack it. First, how much space are we going to need?
389 */
390 status = dot11f_get_packed_tdls_dis_req_size(pMac, &tdlsDisReq, &nPayload);
391 if (DOT11F_FAILED(status)) {
392 lim_log(pMac, LOGP,
393 FL(
394 "Failed to calculate the packed size for a discovery Request (0x%08x)."
395 ),
396 status);
397 /* We'll fall back on the worst case scenario: */
398 nPayload = sizeof(tDot11fTDLSDisReq);
399 } else if (DOT11F_WARNED(status)) {
400 lim_log(pMac, LOGW,
401 FL(
402 "There were warnings while calculating the packed size for a discovery Request (0x%08x)."
403 ),
404 status);
405 }
406
407 /*
408 * This frame is going out from PE as data frames with special ethertype
409 * 89-0d.
410 * 8 bytes of RFC 1042 header
411 */
412
413 nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
414 ? sizeof(tSirMacDataHdr3a) :
415 sizeof(tSirMacMgmtHdr))
416 + sizeof(eth_890d_header)
417 + PAYLOAD_TYPE_TDLS_SIZE;
418
419#ifndef NO_PAD_TDLS_MIN_8023_SIZE
420 /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
421 Hence AP itself padding some bytes, which caused teardown packet is dropped at
422 receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
423 */
424 if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
425 padLen =
426 MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
427
428 /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
429 if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
430 padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
431
432 nBytes += padLen;
433 }
434#endif
435
436 /* Ok-- try to allocate memory from MGMT PKT pool */
437
438 cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
439 (void **)&pPacket);
440 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
441 lim_log(pMac, LOGP,
442 FL(
443 "Failed to allocate %d bytes for a TDLS Discovery Request."
444 ),
445 nBytes);
446 return eSIR_MEM_ALLOC_FAILED;
447 }
448
449 /* zero out the memory */
450 cdf_mem_set(pFrame, nBytes, 0);
451
452 /*
453 * IE formation, memory allocation is completed, Now form TDLS discovery
454 * request frame
455 */
456
457 /* fill out the buffer descriptor */
458
459 header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
460 LINK_IDEN_ADDR_OFFSET
461 (tdlsDisReq), TDLS_LINK_AP,
462 TDLS_INITIATOR, TID_AC_VI,
463 psessionEntry);
464
465 status = dot11f_pack_tdls_dis_req(pMac, &tdlsDisReq, pFrame
466 + header_offset, nPayload, &nPayload);
467
468 if (DOT11F_FAILED(status)) {
469 lim_log(pMac, LOGE,
470 FL("Failed to pack a TDLS discovery req (0x%08x)."),
471 status);
472 cds_packet_free((void *)pPacket);
473 return eSIR_FAILURE;
474 } else if (DOT11F_WARNED(status)) {
475 lim_log(pMac, LOGW,
476 FL(
477 "There were warnings while packing TDLS Discovery Request (0x%08x)."
478 ),
479 status);
480 }
481#ifndef NO_PAD_TDLS_MIN_8023_SIZE
482 if (padLen != 0) {
483 /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
484 uint8_t *padVendorSpecific = pFrame + header_offset + nPayload;
485 /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
486 padVendorSpecific[0] = 221;
487 padVendorSpecific[1] = padLen - 2;
488 padVendorSpecific[2] = 0x00;
489 padVendorSpecific[3] = 0xA0;
490 padVendorSpecific[4] = 0xC6;
491
492 lim_log(pMac, LOGW,
493 FL("Padding Vendor Specific Ie Len = %d"), padLen);
494
495 /* padding zero if more than 5 bytes are required */
496 if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
497 cdf_mem_set(pFrame + header_offset + nPayload +
498 MIN_VENDOR_SPECIFIC_IE_SIZE,
499 padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0);
500 }
501#endif
502
503 lim_log(pMac, LOG1,
504 FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
505 SIR_MAC_TDLS_DIS_REQ,
506 lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_REQ),
507 MAC_ADDR_ARRAY(peer_mac));
508
509 pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
510 cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
511 TXRX_FRM_802_11_DATA,
512 ANI_TXDIR_TODS,
513 TID_AC_VI,
514 lim_tx_complete, pFrame,
515 lim_mgmt_tx_complete,
516 HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
517 smeSessionId, false, 0);
518 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
519 pMac->lim.mgmtFrameSessionId = 0xff;
520 lim_log(pMac, LOGE,
521 FL("could not send TDLS Discovery Request frame"));
522 return eSIR_FAILURE;
523 }
524
525 return eSIR_SUCCESS;
526
527}
528
529/*
530 * This static function is consistent with any kind of TDLS management
531 * frames we are sending. Currently it is being used by lim_send_tdls_dis_rsp_frame,
532 * lim_send_tdls_link_setup_req_frame and lim_send_tdls_setup_rsp_frame
533 */
534static void populate_dot11f_tdls_ht_vht_cap(tpAniSirGlobal pMac,
535 uint32_t selfDot11Mode,
536 tDot11fIEHTCaps *htCap,
537 tDot11fIEVHTCaps *vhtCap,
538 tpPESession psessionEntry)
539{
540 if (IS_DOT11_MODE_HT(selfDot11Mode)) {
541 /* Include HT Capability IE */
542 populate_dot11f_ht_caps(pMac, NULL, htCap);
543 /*
544 * Advertise ht capability and max supported channel bandwidth
545 * when populating HT IE in TDLS Setup Request/Setup Response/
546 * Setup Confirmation frames.
547 * 11.21.6.2 Setting up a 40 MHz direct link: A 40 MHz
548 * off-channel direct link may be started if both TDLS peer STAs
549 * indicated 40 MHz support in the Supported Channel Width Set
550 * field of the HT Capabilities element (which is included in
551 * the TDLS Setup Request frame and the TDLS Setup Response
552 * frame). Switching to a 40 MHz off-channel direct link is
553 * achieved by including the following information in the TDLS
554 * Channel Switch Request
555 * 11.21.1 General: The channel width of the TDLS direct link on
556 * the base channel shall not exceed the channel width of the
557 * BSS to which the TDLS peer STAs are associated.
558 */
559 htCap->supportedChannelWidthSet = 1;
560 } else {
561 htCap->present = 0;
562 }
563 lim_log(pMac, LOG1, FL("HT present = %hu, Chan Width = %hu"),
564 htCap->present, htCap->supportedChannelWidthSet);
565#ifdef WLAN_FEATURE_11AC
566 if (((psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) &&
567 pMac->roam.configParam.enableVhtFor24GHz) ||
568 (psessionEntry->currentOperChannel >= SIR_11B_CHANNEL_END)) {
569 if (IS_DOT11_MODE_VHT(selfDot11Mode) &&
570 IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
571 /* Include VHT Capability IE */
572 populate_dot11f_vht_caps(pMac, psessionEntry, vhtCap);
573 vhtCap->suBeamformeeCap = 0;
574 vhtCap->suBeamFormerCap = 0;
575 vhtCap->muBeamformeeCap = 0;
576 vhtCap->muBeamformerCap = 0;
577 } else {
578 vhtCap->present = 0;
579 }
580 } else {
581 /* Vht Disable from ini in 2.4 GHz */
582 vhtCap->present = 0;
583 }
584 lim_log(pMac, LOG1, FL("VHT present = %hu, Chan Width = %hu"),
585 vhtCap->present, vhtCap->supportedChannelWidthSet);
586#endif
587}
588
589/*
590 * Send TDLS discovery response frame on direct link.
591 */
592
593static tSirRetStatus lim_send_tdls_dis_rsp_frame(tpAniSirGlobal pMac,
594 tSirMacAddr peerMac, uint8_t dialog,
595 tpPESession psessionEntry,
596 uint8_t *addIe, uint16_t addIeLen)
597{
598 tDot11fTDLSDisRsp tdlsDisRsp;
599 uint16_t caps = 0;
600 uint32_t status = 0;
601 uint32_t nPayload = 0;
602 uint32_t nBytes = 0;
603 uint8_t *pFrame;
604 void *pPacket;
605 CDF_STATUS cdf_status;
606 uint32_t selfDot11Mode;
607/* Placeholder to support different channel bonding mode of TDLS than AP. */
608/* Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
609/* To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
610/* As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
611/* uint32_t tdlsChannelBondingMode; */
612 uint8_t smeSessionId = 0;
613
614 if (NULL == psessionEntry) {
615 lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
616 return eSIR_FAILURE;
617 }
618 smeSessionId = psessionEntry->smeSessionId;
619
620 /*
621 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
622 * and then hand it off to 'dot11f_pack_probe_request' (for
623 * serialization). We start by zero-initializing the structure:
624 */
625 cdf_mem_set((uint8_t *) &tdlsDisRsp, sizeof(tDot11fTDLSDisRsp), 0);
626
627 /*
628 * setup Fixed fields,
629 */
630 tdlsDisRsp.Category.category = SIR_MAC_ACTION_PUBLIC_USAGE;
631 tdlsDisRsp.Action.action = SIR_MAC_TDLS_DIS_RSP;
632 tdlsDisRsp.DialogToken.token = dialog;
633
634 populate_dot11f_link_iden(pMac, psessionEntry,
635 &tdlsDisRsp.LinkIdentifier,
636 peerMac, TDLS_RESPONDER);
637
638 if (cfg_get_capability_info(pMac, &caps, psessionEntry)
639 != eSIR_SUCCESS) {
640 /*
641 * Could not get Capabilities value
642 * from CFG. Log error.
643 */
644 lim_log(pMac, LOGE,
645 FL("could not retrieve Capabilities value"));
646 }
647 swap_bit_field16(caps, (uint16_t *) &tdlsDisRsp.Capabilities);
648
649 /* populate supported rate and ext supported rate IE */
650 if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac,
651 &tdlsDisRsp.SuppRates,
652 &tdlsDisRsp.ExtSuppRates))
653 lim_log(pMac, LOGE,
654 FL("could not populate supported data rates"));
655
656 /* populate extended capability IE */
657 populate_dot11f_tdls_ext_capability(pMac,
658 psessionEntry,
659 &tdlsDisRsp.ExtCap);
660
661 wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode);
662
663 /* Populate HT/VHT Capabilities */
664 populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsDisRsp.HTCaps,
665 &tdlsDisRsp.VHTCaps, psessionEntry);
666
667 /* Populate TDLS offchannel param only if offchannel is enabled
668 * and TDLS Channel Switching is not prohibited by AP in ExtCap
669 * IE in assoc/re-assoc response.
670 */
671 if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
672 (!psessionEntry->tdls_chan_swit_prohibited)) {
673 populate_dot11f_tdls_offchannel_params(pMac, psessionEntry,
674 &tdlsDisRsp.SuppChannels,
675 &tdlsDisRsp.
676 SuppOperatingClasses);
677 if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) {
678 tdlsDisRsp.ht2040_bss_coexistence.present = 1;
679 tdlsDisRsp.ht2040_bss_coexistence.info_request = 1;
680 }
681 } else {
682 lim_log(pMac, LOG1,
683 FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"),
684 pMac->lim.gLimTDLSOffChannelEnabled,
685 psessionEntry->tdls_chan_swit_prohibited);
686 }
687 /*
688 * now we pack it. First, how much space are we going to need?
689 */
690 status = dot11f_get_packed_tdls_dis_rsp_size(pMac, &tdlsDisRsp, &nPayload);
691 if (DOT11F_FAILED(status)) {
692 lim_log(pMac, LOGE,
693 FL(
694 "Failed to calculate the packed size for a Discovery Response (0x%08x)."
695 ),
696 status);
697 /* We'll fall back on the worst case scenario: */
698 nPayload = sizeof(tDot11fProbeRequest);
699 } else if (DOT11F_WARNED(status)) {
700 lim_log(pMac, LOGW,
701 FL(
702 "There were warnings while calculating the packed size for a Discovery Response (0x%08x)."
703 ),
704 status);
705 }
706
707 /*
708 * This frame is going out from PE as data frames with special ethertype
709 * 89-0d.
710 * 8 bytes of RFC 1042 header
711 */
712
713 nBytes = nPayload + sizeof(tSirMacMgmtHdr) + addIeLen;
714
715 /* Ok-- try to allocate memory from MGMT PKT pool */
716 cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
717 (void **)&pPacket);
718 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
719 lim_log(pMac, LOGE,
720 FL(
721 "Failed to allocate %d bytes for a TDLS Discovery Request."
722 ),
723 nBytes);
724 return eSIR_MEM_ALLOC_FAILED;
725 }
726
727 /* zero out the memory */
728 cdf_mem_set(pFrame, nBytes, 0);
729
730 /*
731 * IE formation, memory allocation is completed, Now form TDLS discovery
732 * response frame
733 */
734
735 /* Make public Action Frame */
736
737 lim_populate_mac_header(pMac, pFrame, SIR_MAC_MGMT_FRAME,
738 SIR_MAC_MGMT_ACTION, peerMac,
739 psessionEntry->selfMacAddr);
740
741 {
742 tpSirMacMgmtHdr pMacHdr;
743 pMacHdr = (tpSirMacMgmtHdr) pFrame;
744 pMacHdr->fc.toDS = ANI_TXDIR_IBSS;
745 pMacHdr->fc.powerMgmt = 0;
746 sir_copy_mac_addr(pMacHdr->bssId, psessionEntry->bssId);
747 }
748
749 status = dot11f_pack_tdls_dis_rsp(pMac, &tdlsDisRsp, pFrame +
750 sizeof(tSirMacMgmtHdr),
751 nPayload, &nPayload);
752
753 if (DOT11F_FAILED(status)) {
754 lim_log(pMac, LOGE,
755 FL(
756 "Failed to pack a TDLS discovery response (0x%08x)."
757 ),
758 status);
759 cds_packet_free((void *)pPacket);
760 return eSIR_FAILURE;
761 } else if (DOT11F_WARNED(status)) {
762 lim_log(pMac, LOGW,
763 FL(
764 "There were warnings while packing TDLS Discovery Response (0x%08x)."
765 ),
766 status);
767 }
768 if (0 != addIeLen) {
769 lim_log(pMac, LOG1,
770 FL("Copy Additional Ie Len = %d"), addIeLen);
771 cdf_mem_copy(pFrame + sizeof(tSirMacMgmtHdr) + nPayload, addIe,
772 addIeLen);
773 }
774 lim_log(pMac, LOG1,
775 FL("[TDLS] action %d (%s) -DIRECT-> OTA peer="MAC_ADDRESS_STR),
776 SIR_MAC_TDLS_DIS_RSP,
777 lim_trace_tdls_action_string(SIR_MAC_TDLS_DIS_RSP),
778 MAC_ADDR_ARRAY(peerMac));
779
780 pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
781 /*
782 * Transmit Discovery response and watch if this is delivered to
783 * peer STA.
784 */
785 /* In CLD 2.0, pass Discovery Response as mgmt frame so that
786 * wma does not do header conversion to 802.3 before calling tx/rx
787 * routine and subsequenly target also sends frame as is OTA
788 */
789 cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
790 TXRX_FRM_802_11_MGMT,
791 ANI_TXDIR_IBSS,
792 0,
793 lim_tx_complete, pFrame,
794 lim_mgmt_tx_complete,
795 HAL_USE_SELF_STA_REQUESTED_MASK,
796 smeSessionId, false, 0);
797 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
798 pMac->lim.mgmtFrameSessionId = 0xff;
799 lim_log(pMac, LOGE,
800 FL("could not send TDLS Discovery Response frame!"));
801 return eSIR_FAILURE;
802 }
803
804 return eSIR_SUCCESS;
805
806}
807
808/*
809 * This static function is currently used by lim_send_tdls_link_setup_req_frame and
810 * lim_send_tdls_setup_rsp_frame to populate the AID if device is 11ac capable.
811 */
812static void populate_dotf_tdls_vht_aid(tpAniSirGlobal pMac, uint32_t selfDot11Mode,
813 tSirMacAddr peerMac, tDot11fIEAID *Aid,
814 tpPESession psessionEntry)
815{
816 if (((psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) &&
817 pMac->roam.configParam.enableVhtFor24GHz) ||
818 (psessionEntry->currentOperChannel >= SIR_11B_CHANNEL_END)) {
819 if (IS_DOT11_MODE_VHT(selfDot11Mode) &&
820 IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) {
821
822 uint16_t aid;
823 tpDphHashNode pStaDs;
824
825 pStaDs =
826 dph_lookup_hash_entry(pMac, peerMac, &aid,
827 &psessionEntry->dph.
828 dphHashTable);
829 if (NULL != pStaDs) {
830 Aid->present = 1;
831 Aid->assocId = aid | LIM_AID_MASK; /* set bit 14 and 15 1's */
832 } else {
833 Aid->present = 0;
834 lim_log(pMac, LOGE,
835 FL("pStaDs is NULL for "
836 MAC_ADDRESS_STR),
837 MAC_ADDR_ARRAY(peerMac));
838 }
839 }
840 } else {
841 Aid->present = 0;
842 lim_log(pMac, LOGW, FL("Vht not enable from ini for 2.4GHz."));
843 }
844}
845
846/*
847 * TDLS setup Request frame on AP link
848 */
849
850tSirRetStatus lim_send_tdls_link_setup_req_frame(tpAniSirGlobal pMac,
851 tSirMacAddr peerMac, uint8_t dialog,
852 tpPESession psessionEntry,
853 uint8_t *addIe, uint16_t addIeLen)
854{
855 tDot11fTDLSSetupReq tdlsSetupReq;
856 uint16_t caps = 0;
857 uint32_t status = 0;
858 uint32_t nPayload = 0;
859 uint32_t nBytes = 0;
860 uint32_t header_offset = 0;
861 uint8_t *pFrame;
862 void *pPacket;
863 CDF_STATUS cdf_status;
864 uint32_t selfDot11Mode;
865 uint8_t smeSessionId = 0;
866/* Placeholder to support different channel bonding mode of TDLS than AP. */
867/* Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
868/* To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
869/* As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
870/* uint32_t tdlsChannelBondingMode; */
871
872 /*
873 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
874 * and then hand it off to 'dot11f_pack_probe_request' (for
875 * serialization). We start by zero-initializing the structure:
876 */
877 smeSessionId = psessionEntry->smeSessionId;
878
879 cdf_mem_set((uint8_t *) &tdlsSetupReq, sizeof(tDot11fTDLSSetupReq), 0);
880 tdlsSetupReq.Category.category = SIR_MAC_ACTION_TDLS;
881 tdlsSetupReq.Action.action = SIR_MAC_TDLS_SETUP_REQ;
882 tdlsSetupReq.DialogToken.token = dialog;
883
884 populate_dot11f_link_iden(pMac, psessionEntry,
885 &tdlsSetupReq.LinkIdentifier, peerMac,
886 TDLS_INITIATOR);
887
888 if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) {
889 /*
890 * Could not get Capabilities value
891 * from CFG. Log error.
892 */
893 lim_log(pMac, LOGE,
894 FL("could not retrieve Capabilities value"));
895 }
896 swap_bit_field16(caps, (uint16_t *) &tdlsSetupReq.Capabilities);
897
898 /* populate supported rate and ext supported rate IE */
899 if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac,
900 &tdlsSetupReq.SuppRates,
901 &tdlsSetupReq.ExtSuppRates))
902 lim_log(pMac, LOGE,
903 FL("could not populate supported data rates"));
904
905 /* Populate extended capability IE */
906 populate_dot11f_tdls_ext_capability(pMac,
907 psessionEntry,
908 &tdlsSetupReq.ExtCap);
909
910 if (1 == pMac->lim.gLimTDLSWmmMode) {
911 uint32_t val = 0;
912
913 lim_log(pMac, LOG1,
914 FL("populate WMM IE in Setup Request Frame"));
915 /* include WMM IE */
916 tdlsSetupReq.WMMInfoStation.version = SIR_MAC_OUI_VERSION_1;
917 tdlsSetupReq.WMMInfoStation.acvo_uapsd =
918 (pMac->lim.gLimTDLSUapsdMask & 0x01);
919 tdlsSetupReq.WMMInfoStation.acvi_uapsd =
920 ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
921 tdlsSetupReq.WMMInfoStation.acbk_uapsd =
922 ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
923 tdlsSetupReq.WMMInfoStation.acbe_uapsd =
924 ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
925
926 if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) !=
927 eSIR_SUCCESS)
928 lim_log(pMac, LOGE,
929 FL("could not retrieve Max SP Length"));
930
931 tdlsSetupReq.WMMInfoStation.max_sp_length = (uint8_t) val;
932 tdlsSetupReq.WMMInfoStation.present = 1;
933 } else {
934 /*
935 * TODO: we need to see if we have to support conditions where
936 * we have EDCA parameter info element is needed a) if we need
937 * different QOS parameters for off channel operations or QOS
938 * is not supported on AP link and we wanted to QOS on direct
939 * link.
940 */
941
942 /* Populate QOS info, needed for Peer U-APSD session */
943
944 /*
945 * TODO: Now hardcoded, since populate_dot11f_qos_caps_station()
946 * depends on AP's capability, and TDLS doesn't want to depend
947 * on AP's capability
948 */
949
950 lim_log(pMac, LOG1,
951 FL("populate QOS IE in Setup Request Frame"));
952 tdlsSetupReq.QOSCapsStation.present = 1;
953 tdlsSetupReq.QOSCapsStation.max_sp_length = 0;
954 tdlsSetupReq.QOSCapsStation.qack = 0;
955 tdlsSetupReq.QOSCapsStation.acbe_uapsd =
956 ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
957 tdlsSetupReq.QOSCapsStation.acbk_uapsd =
958 ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
959 tdlsSetupReq.QOSCapsStation.acvi_uapsd =
960 ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
961 tdlsSetupReq.QOSCapsStation.acvo_uapsd =
962 (pMac->lim.gLimTDLSUapsdMask & 0x01);
963 }
964
965 /*
966 * we will always try to init TDLS link with 11n capabilities
967 * let TDLS setup response to come, and we will set our caps based
968 * of peer caps
969 */
970
971 wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode);
972
973 /* Populate HT/VHT Capabilities */
974 populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsSetupReq.HTCaps,
975 &tdlsSetupReq.VHTCaps, psessionEntry);
976
977 /* Populate AID */
978 populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peerMac,
979 &tdlsSetupReq.AID, psessionEntry);
980
981 /* Populate TDLS offchannel param only if offchannel is enabled
982 * and TDLS Channel Switching is not prohibited by AP in ExtCap
983 * IE in assoc/re-assoc response.
984 */
985 if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
986 (!psessionEntry->tdls_chan_swit_prohibited)) {
987 populate_dot11f_tdls_offchannel_params(pMac, psessionEntry,
988 &tdlsSetupReq.SuppChannels,
989 &tdlsSetupReq.
990 SuppOperatingClasses);
991 if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) {
992 tdlsSetupReq.ht2040_bss_coexistence.present = 1;
993 tdlsSetupReq.ht2040_bss_coexistence.info_request = 1;
994 }
995 } else {
996 lim_log(pMac, LOG1,
997 FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"),
998 pMac->lim.gLimTDLSOffChannelEnabled,
999 psessionEntry->tdls_chan_swit_prohibited);
1000 }
1001 /*
1002 * now we pack it. First, how much space are we going to need?
1003 */
1004 status = dot11f_get_packed_tdls_setup_req_size(pMac, &tdlsSetupReq,
1005 &nPayload);
1006 if (DOT11F_FAILED(status)) {
1007 lim_log(pMac, LOGE,
1008 FL(
1009 "Failed to calculate the packed size for a Setup Request (0x%08x)."
1010 ),
1011 status);
1012 /* We'll fall back on the worst case scenario: */
1013 nPayload = sizeof(tDot11fProbeRequest);
1014 } else if (DOT11F_WARNED(status)) {
1015 lim_log(pMac, LOGW,
1016 FL(
1017 "There were warnings while calculating the packed size for a Setup Request (0x%08x)."
1018 ),
1019 status);
1020 }
1021
1022 /*
1023 * This frame is going out from PE as data frames with special ethertype
1024 * 89-0d.
1025 * 8 bytes of RFC 1042 header
1026 */
1027
1028 nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
1029 ? sizeof(tSirMacDataHdr3a) :
1030 sizeof(tSirMacMgmtHdr))
1031 + sizeof(eth_890d_header)
1032 + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
1033
1034 /* Ok-- try to allocate memory from MGMT PKT pool */
1035 cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
1036 (void **)&pPacket);
1037 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1038 lim_log(pMac, LOGE,
1039 FL(
1040 "Failed to allocate %d bytes for a TDLS Setup Request."
1041 ),
1042 nBytes);
1043 return eSIR_MEM_ALLOC_FAILED;
1044 }
1045
1046 /* zero out the memory */
1047 cdf_mem_set(pFrame, nBytes, 0);
1048
1049 /*
1050 * IE formation, memory allocation is completed, Now form TDLS discovery
1051 * request frame
1052 */
1053
1054 /* fill out the buffer descriptor */
1055
1056 header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
1057 LINK_IDEN_ADDR_OFFSET
1058 (tdlsSetupReq), TDLS_LINK_AP,
1059 TDLS_INITIATOR, TID_AC_BK,
1060 psessionEntry);
1061
1062 lim_log(pMac, LOGW,
1063 FL(
1064 "SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x"
1065 ),
1066 tdlsSetupReq.VHTCaps.supportedChannelWidthSet,
1067 tdlsSetupReq.VHTCaps.rxMCSMap,
1068 tdlsSetupReq.VHTCaps.txMCSMap,
1069 tdlsSetupReq.VHTCaps.txSupDataRate);
1070
1071 status = dot11f_pack_tdls_setup_req(pMac, &tdlsSetupReq, pFrame
1072 + header_offset, nPayload, &nPayload);
1073
1074 if (DOT11F_FAILED(status)) {
1075 lim_log(pMac, LOGE,
1076 FL("Failed to pack a TDLS Setup request (0x%08x)."),
1077 status);
1078 cds_packet_free((void *)pPacket);
1079 return eSIR_FAILURE;
1080 } else if (DOT11F_WARNED(status)) {
1081 lim_log(pMac, LOGW,
1082 FL(
1083 "There were warnings while packing TDLS Setup Request (0x%08x)."
1084 ),
1085 status);
1086 }
1087 /* Copy the additional IE. */
1088 /* TODO : addIe is added at the end of the frame. This means it doesnt */
1089 /* follow the order. This should be ok, but we should consider changing this */
1090 /* if there is any IOT issue. */
1091 if (addIeLen != 0) {
1092 lim_log(pMac, LOG1, FL("Copy Additional Ie Len = %d"),
1093 addIeLen);
1094 cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
1095 addIeLen);
1096 }
1097
1098 lim_log(pMac, LOG1,
1099 FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
1100 SIR_MAC_TDLS_SETUP_REQ,
1101 lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_REQ),
1102 MAC_ADDR_ARRAY(peerMac));
1103
1104 pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
1105
1106 cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
1107 TXRX_FRM_802_11_DATA,
1108 ANI_TXDIR_TODS,
1109 TID_AC_BK,
1110 lim_tx_complete, pFrame,
1111 lim_mgmt_tx_complete,
1112 HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
1113 smeSessionId, false, 0);
1114
1115 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1116 pMac->lim.mgmtFrameSessionId = 0xff;
1117 lim_log(pMac, LOGE,
1118 FL("could not send TDLS Setup Request frame!"));
1119 return eSIR_FAILURE;
1120 }
1121
1122 return eSIR_SUCCESS;
1123
1124}
1125
1126/*
1127 * Send TDLS Teardown frame on Direct link or AP link, depends on reason code.
1128 */
1129
1130tSirRetStatus lim_send_tdls_teardown_frame(tpAniSirGlobal pMac,
1131 tSirMacAddr peerMac, uint16_t reason,
1132 uint8_t responder,
1133 tpPESession psessionEntry,
1134 uint8_t *addIe, uint16_t addIeLen)
1135{
1136 tDot11fTDLSTeardown teardown;
1137 uint32_t status = 0;
1138 uint32_t nPayload = 0;
1139 uint32_t nBytes = 0;
1140 uint32_t header_offset = 0;
1141 uint8_t *pFrame;
1142 void *pPacket;
1143 CDF_STATUS cdf_status;
1144#ifndef NO_PAD_TDLS_MIN_8023_SIZE
1145 uint32_t padLen = 0;
1146#endif
1147 uint8_t smeSessionId = 0;
1148
1149 if (NULL == psessionEntry) {
1150 lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
1151 return eSIR_FAILURE;
1152 }
1153 smeSessionId = psessionEntry->smeSessionId;
1154 /*
1155 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
1156 * and then hand it off to 'dot11f_pack_probe_request' (for
1157 * serialization). We start by zero-initializing the structure:
1158 */
1159 cdf_mem_set((uint8_t *) &teardown, sizeof(tDot11fTDLSTeardown), 0);
1160 teardown.Category.category = SIR_MAC_ACTION_TDLS;
1161 teardown.Action.action = SIR_MAC_TDLS_TEARDOWN;
1162 teardown.Reason.code = reason;
1163
1164 populate_dot11f_link_iden(pMac, psessionEntry, &teardown.LinkIdentifier,
1165 peerMac,
1166 (responder ==
1167 true) ? TDLS_RESPONDER : TDLS_INITIATOR);
1168
1169 /*
1170 * now we pack it. First, how much space are we going to need?
1171 */
1172 status = dot11f_get_packed_tdls_teardown_size(pMac, &teardown, &nPayload);
1173 if (DOT11F_FAILED(status)) {
1174 lim_log(pMac, LOGE,
1175 FL(
1176 "Failed to calculate the packed size for a discovery Request (0x%08x)."
1177 ),
1178 status);
1179 /* We'll fall back on the worst case scenario: */
1180 nPayload = sizeof(tDot11fProbeRequest);
1181 } else if (DOT11F_WARNED(status)) {
1182 lim_log(pMac, LOGW,
1183 FL(
1184 "There were warnings while calculating the packed size for a discovery Request (0x%08x)."
1185 ),
1186 status);
1187 }
1188
1189 /*
1190 * This frame is going out from PE as data frames with special ethertype
1191 * 89-0d.
1192 * 8 bytes of RFC 1042 header
1193 */
1194
1195 nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
1196 ? sizeof(tSirMacDataHdr3a) :
1197 sizeof(tSirMacMgmtHdr))
1198 + sizeof(eth_890d_header)
1199 + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
1200
1201#ifndef NO_PAD_TDLS_MIN_8023_SIZE
1202 /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
1203 Hence AP itself padding some bytes, which caused teardown packet is dropped at
1204 receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
1205 */
1206 if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
1207 padLen =
1208 MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
1209
1210 /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
1211 if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
1212 padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
1213
1214 nBytes += padLen;
1215 }
1216#endif
1217
1218 /* Ok-- try to allocate memory from MGMT PKT pool */
1219 cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
1220 (void **)&pPacket);
1221 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1222 lim_log(pMac, LOGE,
1223 FL(
1224 "Failed to allocate %d bytes for a TDLS Teardown Frame."
1225 ),
1226 nBytes);
1227 return eSIR_MEM_ALLOC_FAILED;
1228 }
1229
1230 /* zero out the memory */
1231 cdf_mem_set(pFrame, nBytes, 0);
1232
1233 /*
1234 * IE formation, memory allocation is completed, Now form TDLS discovery
1235 * request frame
1236 */
1237
1238 /* fill out the buffer descriptor */
1239 lim_log(pMac, LOGE, FL("Reason of TDLS Teardown: %d"), reason);
1240 header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
1241 LINK_IDEN_ADDR_OFFSET
1242 (teardown),
1243 (reason ==
1244 eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE)
1245 ? TDLS_LINK_AP :
1246 TDLS_LINK_DIRECT,
1247 (responder ==
1248 true) ? TDLS_RESPONDER :
1249 TDLS_INITIATOR, TID_AC_VI,
1250 psessionEntry);
1251
1252 status = dot11f_pack_tdls_teardown(pMac, &teardown, pFrame
1253 + header_offset, nPayload, &nPayload);
1254
1255 if (DOT11F_FAILED(status)) {
1256 lim_log(pMac, LOGE,
1257 FL("Failed to pack a TDLS Teardown frame (0x%08x)."),
1258 status);
1259 cds_packet_free((void *)pPacket);
1260 return eSIR_FAILURE;
1261 } else if (DOT11F_WARNED(status)) {
1262 lim_log(pMac, LOGW,
1263 FL(
1264 "There were warnings while packing TDLS Teardown frame (0x%08x)."
1265 ),
1266 status);
1267 }
1268
1269 if (addIeLen != 0) {
1270 lim_log(pMac, LOGW,
1271 FL("Copy Additional Ie Len = %d"), addIeLen);
1272 cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
1273 addIeLen);
1274 }
1275#ifndef NO_PAD_TDLS_MIN_8023_SIZE
1276 if (padLen != 0) {
1277 /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
1278 uint8_t *padVendorSpecific =
1279 pFrame + header_offset + nPayload + addIeLen;
1280 /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
1281 padVendorSpecific[0] = 221;
1282 padVendorSpecific[1] = padLen - 2;
1283 padVendorSpecific[2] = 0x00;
1284 padVendorSpecific[3] = 0xA0;
1285 padVendorSpecific[4] = 0xC6;
1286
1287 lim_log(pMac, LOG1, FL("Padding Vendor Specific Ie Len = %d"),
1288 padLen);
1289
1290 /* padding zero if more than 5 bytes are required */
1291 if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
1292 cdf_mem_set(pFrame + header_offset + nPayload +
1293 addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE,
1294 padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0);
1295 }
1296#endif
1297 lim_log(pMac, LOG1,
1298 FL("[TDLS] action %d (%s) -%s-> OTA peer="MAC_ADDRESS_STR),
1299 SIR_MAC_TDLS_TEARDOWN,
1300 lim_trace_tdls_action_string(SIR_MAC_TDLS_TEARDOWN),
1301 ((reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? "AP" :
1302 "DIRECT"),
1303 MAC_ADDR_ARRAY(peerMac));
1304
1305 pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
1306
1307 cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
1308 TXRX_FRM_802_11_DATA,
1309 ANI_TXDIR_TODS,
1310 TID_AC_VI,
1311 lim_tx_complete, pFrame,
1312 lim_mgmt_tx_complete,
1313 HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
1314 smeSessionId, false, 0);
1315
1316 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1317 pMac->lim.mgmtFrameSessionId = 0xff;
1318 lim_log(pMac, LOGE,
1319 FL("could not send TDLS Teardown frame"));
1320 return eSIR_FAILURE;
1321
1322 }
1323 return eSIR_SUCCESS;
1324
1325}
1326
1327/*
1328 * Send Setup RSP frame on AP link.
1329 */
1330static tSirRetStatus lim_send_tdls_setup_rsp_frame(tpAniSirGlobal pMac,
1331 tSirMacAddr peerMac,
1332 uint8_t dialog,
1333 tpPESession psessionEntry,
1334 etdlsLinkSetupStatus setupStatus,
1335 uint8_t *addIe,
1336 uint16_t addIeLen)
1337{
1338 tDot11fTDLSSetupRsp tdlsSetupRsp;
1339 uint32_t status = 0;
1340 uint16_t caps = 0;
1341 uint32_t nPayload = 0;
1342 uint32_t header_offset = 0;
1343 uint32_t nBytes = 0;
1344 uint8_t *pFrame;
1345 void *pPacket;
1346 CDF_STATUS cdf_status;
1347 uint32_t selfDot11Mode;
1348/* Placeholder to support different channel bonding mode of TDLS than AP. */
1349/* Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP */
1350/* To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE */
1351/* As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) */
1352/* uint32_t tdlsChannelBondingMode; */
1353 uint8_t smeSessionId = 0;
1354
1355 if (NULL == psessionEntry) {
1356 lim_log(pMac, LOGE, FL("psessionEntry is NULL"));
1357 return eSIR_FAILURE;
1358 }
1359 smeSessionId = psessionEntry->smeSessionId;
1360
1361 /*
1362 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
1363 * and then hand it off to 'dot11f_pack_probe_request' (for
1364 * serialization). We start by zero-initializing the structure:
1365 */
1366 cdf_mem_set((uint8_t *) &tdlsSetupRsp, sizeof(tDot11fTDLSSetupRsp), 0);
1367
1368 /*
1369 * setup Fixed fields,
1370 */
1371 tdlsSetupRsp.Category.category = SIR_MAC_ACTION_TDLS;
1372 tdlsSetupRsp.Action.action = SIR_MAC_TDLS_SETUP_RSP;
1373 tdlsSetupRsp.DialogToken.token = dialog;
1374
1375 populate_dot11f_link_iden(pMac, psessionEntry,
1376 &tdlsSetupRsp.LinkIdentifier, peerMac,
1377 TDLS_RESPONDER);
1378
1379 if (cfg_get_capability_info(pMac, &caps, psessionEntry) != eSIR_SUCCESS) {
1380 /*
1381 * Could not get Capabilities value
1382 * from CFG. Log error.
1383 */
1384 lim_log(pMac, LOGE,
1385 FL("could not retrieve Capabilities value"));
1386 }
1387 swap_bit_field16(caps, (uint16_t *) &tdlsSetupRsp.Capabilities);
1388
1389 /* populate supported rate and ext supported rate IE */
1390 if (eSIR_FAILURE == populate_dot11f_rates_tdls(pMac,
1391 &tdlsSetupRsp.SuppRates,
1392 &tdlsSetupRsp.ExtSuppRates))
1393 lim_log(pMac, LOGE,
1394 FL("could not populate supported data rates"));
1395
1396 /* Populate extended capability IE */
1397 populate_dot11f_tdls_ext_capability(pMac,
1398 psessionEntry,
1399 &tdlsSetupRsp.ExtCap);
1400
1401 if (1 == pMac->lim.gLimTDLSWmmMode) {
1402 uint32_t val = 0;
1403
1404 lim_log(pMac, LOG1,
1405 FL("populate WMM IE in Setup Response frame"));
1406 /* include WMM IE */
1407 tdlsSetupRsp.WMMInfoStation.version = SIR_MAC_OUI_VERSION_1;
1408 tdlsSetupRsp.WMMInfoStation.acvo_uapsd =
1409 (pMac->lim.gLimTDLSUapsdMask & 0x01);
1410 tdlsSetupRsp.WMMInfoStation.acvi_uapsd =
1411 ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
1412 tdlsSetupRsp.WMMInfoStation.acbk_uapsd =
1413 ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
1414 tdlsSetupRsp.WMMInfoStation.acbe_uapsd =
1415 ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
1416 if (wlan_cfg_get_int(pMac, WNI_CFG_MAX_SP_LENGTH, &val) !=
1417 eSIR_SUCCESS)
1418 lim_log(pMac, LOGE,
1419 FL("could not retrieve Max SP Length"));
1420 tdlsSetupRsp.WMMInfoStation.max_sp_length = (uint8_t) val;
1421 tdlsSetupRsp.WMMInfoStation.present = 1;
1422 } else {
1423 /*
1424 * TODO: we need to see if we have to support conditions where
1425 * we have EDCA parameter info element is needed a) if we need
1426 * different QOS parameters for off channel operations or QOS
1427 * is not supported on AP link and we wanted to QOS on direct
1428 * link.
1429 */
1430 /* Populate QOS info, needed for Peer U-APSD session */
1431 /*
1432 * TODO: Now hardcoded, because
1433 * populate_dot11f_qos_caps_station() depends on AP's
1434 * capability, and TDLS doesn't want to depend on AP's
1435 * capability
1436 */
1437 lim_log(pMac, LOG1,
1438 FL("populate QOS IE in Setup Response frame"));
1439 tdlsSetupRsp.QOSCapsStation.present = 1;
1440 tdlsSetupRsp.QOSCapsStation.max_sp_length = 0;
1441 tdlsSetupRsp.QOSCapsStation.qack = 0;
1442 tdlsSetupRsp.QOSCapsStation.acbe_uapsd =
1443 ((pMac->lim.gLimTDLSUapsdMask & 0x08) >> 3);
1444 tdlsSetupRsp.QOSCapsStation.acbk_uapsd =
1445 ((pMac->lim.gLimTDLSUapsdMask & 0x04) >> 2);
1446 tdlsSetupRsp.QOSCapsStation.acvi_uapsd =
1447 ((pMac->lim.gLimTDLSUapsdMask & 0x02) >> 1);
1448 tdlsSetupRsp.QOSCapsStation.acvo_uapsd =
1449 (pMac->lim.gLimTDLSUapsdMask & 0x01);
1450 }
1451
1452 wlan_cfg_get_int(pMac, WNI_CFG_DOT11_MODE, &selfDot11Mode);
1453
1454 /* Populate HT/VHT Capabilities */
1455 populate_dot11f_tdls_ht_vht_cap(pMac, selfDot11Mode, &tdlsSetupRsp.HTCaps,
1456 &tdlsSetupRsp.VHTCaps, psessionEntry);
1457
1458 /* Populate AID */
1459 populate_dotf_tdls_vht_aid(pMac, selfDot11Mode, peerMac,
1460 &tdlsSetupRsp.AID, psessionEntry);
1461
1462 /* Populate TDLS offchannel param only if offchannel is enabled
1463 * and TDLS Channel Switching is not prohibited by AP in ExtCap
1464 * IE in assoc/re-assoc response.
1465 */
1466 if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
1467 (!psessionEntry->tdls_chan_swit_prohibited)) {
1468 populate_dot11f_tdls_offchannel_params(pMac, psessionEntry,
1469 &tdlsSetupRsp.SuppChannels,
1470 &tdlsSetupRsp.
1471 SuppOperatingClasses);
1472 if (pMac->roam.configParam.bandCapability != eCSR_BAND_24) {
1473 tdlsSetupRsp.ht2040_bss_coexistence.present = 1;
1474 tdlsSetupRsp.ht2040_bss_coexistence.info_request = 1;
1475 }
1476 } else {
1477 lim_log(pMac, LOG1,
1478 FL("TDLS offchan not enabled, or channel switch prohibited by AP, gLimTDLSOffChannelEnabled (%d), tdls_chan_swit_prohibited (%d)"),
1479 pMac->lim.gLimTDLSOffChannelEnabled,
1480 psessionEntry->tdls_chan_swit_prohibited);
1481 }
1482 tdlsSetupRsp.Status.status = setupStatus;
1483 /*
1484 * now we pack it. First, how much space are we going to need?
1485 */
1486 status = dot11f_get_packed_tdls_setup_rsp_size(pMac, &tdlsSetupRsp,
1487 &nPayload);
1488 if (DOT11F_FAILED(status)) {
1489 lim_log(pMac, LOGE,
1490 FL(
1491 "Failed to calculate the packed size for a Setup Response (0x%08x)."
1492 ),
1493 status);
1494 /* We'll fall back on the worst case scenario: */
1495 nPayload = sizeof(tDot11fProbeRequest);
1496 } else if (DOT11F_WARNED(status)) {
1497 lim_log(pMac, LOGW,
1498 FL(
1499 "There were warnings while calculating the packed size for Setup Response (0x%08x)."
1500 ),
1501 status);
1502 }
1503
1504 /*
1505 * This frame is going out from PE as data frames with special ethertype
1506 * 89-0d.
1507 * 8 bytes of RFC 1042 header
1508 */
1509
1510 nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
1511 ? sizeof(tSirMacDataHdr3a) :
1512 sizeof(tSirMacMgmtHdr))
1513 + sizeof(eth_890d_header)
1514 + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
1515
1516 /* Ok-- try to allocate memory from MGMT PKT pool */
1517 cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
1518 (void **)&pPacket);
1519 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1520 lim_log(pMac, LOGE,
1521 FL(
1522 "Failed to allocate %d bytes for a TDLS Setup Response."
1523 ),
1524 nBytes);
1525 return eSIR_MEM_ALLOC_FAILED;
1526 }
1527
1528 /* zero out the memory */
1529 cdf_mem_set(pFrame, nBytes, 0);
1530
1531 /*
1532 * IE formation, memory allocation is completed, Now form TDLS discovery
1533 * request frame
1534 */
1535
1536 /* fill out the buffer descriptor */
1537
1538 header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
1539 LINK_IDEN_ADDR_OFFSET
1540 (tdlsSetupRsp), TDLS_LINK_AP,
1541 TDLS_RESPONDER, TID_AC_BK,
1542 psessionEntry);
1543
1544 lim_log(pMac, LOG1,
1545 FL(
1546 "SupportedChnlWidth %x rxMCSMap %x rxMCSMap %x txSupDataRate %x"
1547 ),
1548 tdlsSetupRsp.VHTCaps.supportedChannelWidthSet,
1549 tdlsSetupRsp.VHTCaps.rxMCSMap,
1550 tdlsSetupRsp.VHTCaps.txMCSMap,
1551 tdlsSetupRsp.VHTCaps.txSupDataRate);
1552 status = dot11f_pack_tdls_setup_rsp(pMac, &tdlsSetupRsp,
1553 pFrame + header_offset,
1554 nPayload, &nPayload);
1555
1556 if (DOT11F_FAILED(status)) {
1557 lim_log(pMac, LOGE,
1558 FL("Failed to pack a TDLS Setup Response (0x%08x)."),
1559 status);
1560 cds_packet_free((void *)pPacket);
1561 return eSIR_FAILURE;
1562 } else if (DOT11F_WARNED(status)) {
1563 lim_log(pMac, LOGW,
1564 FL(
1565 "There were warnings while packing TDLS Setup Response (0x%08x)."
1566 ),
1567 status);
1568 }
1569 /* Copy the additional IE. */
1570 /* TODO : addIe is added at the end of the frame. This means it doesnt */
1571 /* follow the order. This should be ok, but we should consider changing this */
1572 /* if there is any IOT issue. */
1573 if (addIeLen != 0) {
1574 cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
1575 addIeLen);
1576 }
1577
1578 lim_log(pMac, LOG1,
1579 FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
1580 SIR_MAC_TDLS_SETUP_RSP,
1581 lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_RSP),
1582 MAC_ADDR_ARRAY(peerMac));
1583
1584 pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
1585
1586 cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
1587 TXRX_FRM_802_11_DATA,
1588 ANI_TXDIR_TODS,
1589 TID_AC_BK,
1590 lim_tx_complete, pFrame,
1591 lim_mgmt_tx_complete,
1592 HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
1593 smeSessionId, false, 0);
1594
1595 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1596 pMac->lim.mgmtFrameSessionId = 0xff;
1597 lim_log(pMac, LOGE,
1598 FL("could not send TDLS Dis Request frame!"));
1599 return eSIR_FAILURE;
1600 }
1601
1602 return eSIR_SUCCESS;
1603
1604}
1605
1606/*
1607 * Send TDLS setup CNF frame on AP link
1608 */
1609
1610tSirRetStatus lim_send_tdls_link_setup_cnf_frame(tpAniSirGlobal pMac,
1611 tSirMacAddr peerMac,
1612 uint8_t dialog,
1613 uint32_t peerCapability,
1614 tpPESession psessionEntry,
1615 uint8_t *addIe, uint16_t addIeLen)
1616{
1617 tDot11fTDLSSetupCnf tdlsSetupCnf;
1618 uint32_t status = 0;
1619 uint32_t nPayload = 0;
1620 uint32_t nBytes = 0;
1621 uint32_t header_offset = 0;
1622 uint8_t *pFrame;
1623 void *pPacket;
1624 CDF_STATUS cdf_status;
1625#ifndef NO_PAD_TDLS_MIN_8023_SIZE
1626 uint32_t padLen = 0;
1627#endif
1628 uint8_t smeSessionId = 0;
1629
1630 /*
1631 * The scheme here is to fill out a 'tDot11fProbeRequest' structure
1632 * and then hand it off to 'dot11f_pack_probe_request' (for
1633 * serialization). We start by zero-initializing the structure:
1634 */
1635 smeSessionId = psessionEntry->smeSessionId;
1636
1637 cdf_mem_set((uint8_t *) &tdlsSetupCnf, sizeof(tDot11fTDLSSetupCnf), 0);
1638
1639 /*
1640 * setup Fixed fields,
1641 */
1642 tdlsSetupCnf.Category.category = SIR_MAC_ACTION_TDLS;
1643 tdlsSetupCnf.Action.action = SIR_MAC_TDLS_SETUP_CNF;
1644 tdlsSetupCnf.DialogToken.token = dialog;
1645
1646 populate_dot11f_link_iden(pMac, psessionEntry,
1647 &tdlsSetupCnf.LinkIdentifier, peerMac,
1648 TDLS_INITIATOR);
1649 /*
1650 * TODO: we need to see if we have to support conditions where we have
1651 * EDCA parameter info element is needed a) if we need different QOS
1652 * parameters for off channel operations or QOS is not supported on
1653 * AP link and we wanted to QOS on direct link.
1654 */
1655
1656 /* Check self and peer WMM capable */
1657 if ((1 == pMac->lim.gLimTDLSWmmMode) &&
1658 (CHECK_BIT(peerCapability, TDLS_PEER_WMM_CAP))) {
1659 lim_log(pMac, LOG1, FL("populate WMM praram in Setup Confirm"));
1660 populate_dot11f_wmm_params(pMac, &tdlsSetupCnf.WMMParams,
1661 psessionEntry);
1662 }
1663
1664 /* Check peer is VHT capable */
1665 if (CHECK_BIT(peerCapability, TDLS_PEER_VHT_CAP)) {
1666 populate_dot11f_vht_operation(pMac,
1667 psessionEntry,
1668 &tdlsSetupCnf.VHTOperation);
1669 populate_dot11f_ht_info(pMac, &tdlsSetupCnf.HTInfo, psessionEntry);
1670 } else if (CHECK_BIT(peerCapability, TDLS_PEER_HT_CAP)) { /* Check peer is HT capable */
1671 populate_dot11f_ht_info(pMac, &tdlsSetupCnf.HTInfo, psessionEntry);
1672 }
1673
1674 /*
1675 * now we pack it. First, how much space are we going to need?
1676 */
1677 status = dot11f_get_packed_tdls_setup_cnf_size(pMac, &tdlsSetupCnf,
1678 &nPayload);
1679 if (DOT11F_FAILED(status)) {
1680 lim_log(pMac, LOGE,
1681 FL(
1682 "Failed to calculate the packed size for a Setup Confirm (0x%08x)."
1683 ),
1684 status);
1685 /* We'll fall back on the worst case scenario: */
1686 nPayload = sizeof(tDot11fProbeRequest);
1687 } else if (DOT11F_WARNED(status)) {
1688 lim_log(pMac, LOGW,
1689 FL(
1690 "There were warnings while calculating the packed size for Setup Confirm (0x%08x)."
1691 ),
1692 status);
1693 }
1694
1695 /*
1696 * This frame is going out from PE as data frames with special ethertype
1697 * 89-0d.
1698 * 8 bytes of RFC 1042 header
1699 */
1700
1701 nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry))
1702 ? sizeof(tSirMacDataHdr3a) :
1703 sizeof(tSirMacMgmtHdr))
1704 + sizeof(eth_890d_header)
1705 + PAYLOAD_TYPE_TDLS_SIZE + addIeLen;
1706
1707#ifndef NO_PAD_TDLS_MIN_8023_SIZE
1708 /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64)
1709 Hence AP itself padding some bytes, which caused teardown packet is dropped at
1710 receiver side. To avoid such IOT issue, we added some extra bytes to meet data frame size >= 64
1711 */
1712 if (nPayload + PAYLOAD_TYPE_TDLS_SIZE < MIN_IEEE_8023_SIZE) {
1713 padLen =
1714 MIN_IEEE_8023_SIZE - (nPayload + PAYLOAD_TYPE_TDLS_SIZE);
1715
1716 /* if padLen is less than minimum vendorSpecific (5), pad up to 5 */
1717 if (padLen < MIN_VENDOR_SPECIFIC_IE_SIZE)
1718 padLen = MIN_VENDOR_SPECIFIC_IE_SIZE;
1719
1720 nBytes += padLen;
1721 }
1722#endif
1723
1724 /* Ok-- try to allocate memory from MGMT PKT pool */
1725 cdf_status = cds_packet_alloc((uint16_t) nBytes, (void **)&pFrame,
1726 (void **)&pPacket);
1727 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1728 lim_log(pMac, LOGE,
1729 FL(
1730 "Failed to allocate %d bytes for a TDLS Setup Confirm."
1731 ),
1732 nBytes);
1733 return eSIR_MEM_ALLOC_FAILED;
1734 }
1735
1736 /* zero out the memory */
1737 cdf_mem_set(pFrame, nBytes, 0);
1738
1739 /*
1740 * IE formation, memory allocation is completed, Now form TDLS discovery
1741 * request frame
1742 */
1743
1744 /* fill out the buffer descriptor */
1745
1746 header_offset = lim_prepare_tdls_frame_header(pMac, pFrame,
1747 LINK_IDEN_ADDR_OFFSET
1748 (tdlsSetupCnf), TDLS_LINK_AP,
1749 TDLS_INITIATOR, TID_AC_VI,
1750 psessionEntry);
1751
1752 status = dot11f_pack_tdls_setup_cnf(pMac, &tdlsSetupCnf, pFrame
1753 + header_offset, nPayload, &nPayload);
1754
1755 if (DOT11F_FAILED(status)) {
1756 lim_log(pMac, LOGE,
1757 FL("Failed to pack a TDLS discovery req (0x%08x)."),
1758 status);
1759 cds_packet_free((void *)pPacket);
1760 return eSIR_FAILURE;
1761 } else if (DOT11F_WARNED(status)) {
1762 lim_log(pMac, LOGW,
1763 FL(
1764 "There were warnings while packing TDLS Discovery Request (0x%08x)."
1765 ),
1766 status);
1767 }
1768 /* Copy the additional IE. */
1769 /* TODO : addIe is added at the end of the frame. This means it doesnt */
1770 /* follow the order. This should be ok, but we should consider changing this */
1771 /* if there is any IOT issue. */
1772 if (addIeLen != 0) {
1773 cdf_mem_copy(pFrame + header_offset + nPayload, addIe,
1774 addIeLen);
1775 }
1776#ifndef NO_PAD_TDLS_MIN_8023_SIZE
1777 if (padLen != 0) {
1778 /* QCOM VENDOR OUI = { 0x00, 0xA0, 0xC6, type = 0x0000 }; */
1779 uint8_t *padVendorSpecific =
1780 pFrame + header_offset + nPayload + addIeLen;
1781 /* make QCOM_VENDOR_OUI, and type = 0x0000, and all the payload to be zero */
1782 padVendorSpecific[0] = 221;
1783 padVendorSpecific[1] = padLen - 2;
1784 padVendorSpecific[2] = 0x00;
1785 padVendorSpecific[3] = 0xA0;
1786 padVendorSpecific[4] = 0xC6;
1787
1788 lim_log(pMac, LOG1, FL("Padding Vendor Specific Ie Len = %d"),
1789 padLen);
1790
1791 /* padding zero if more than 5 bytes are required */
1792 if (padLen > MIN_VENDOR_SPECIFIC_IE_SIZE)
1793 cdf_mem_set(pFrame + header_offset + nPayload +
1794 addIeLen + MIN_VENDOR_SPECIFIC_IE_SIZE,
1795 padLen - MIN_VENDOR_SPECIFIC_IE_SIZE, 0);
1796 }
1797#endif
1798
1799 lim_log(pMac, LOG1,
1800 FL("[TDLS] action %d (%s) -AP-> OTA peer="MAC_ADDRESS_STR),
1801 SIR_MAC_TDLS_SETUP_CNF,
1802 lim_trace_tdls_action_string(SIR_MAC_TDLS_SETUP_CNF),
1803 MAC_ADDR_ARRAY(peerMac));
1804
1805 pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId;
1806
1807 cdf_status = wma_tx_frameWithTxComplete(pMac, pPacket, (uint16_t) nBytes,
1808 TXRX_FRM_802_11_DATA,
1809 ANI_TXDIR_TODS,
1810 TID_AC_VI,
1811 lim_tx_complete, pFrame,
1812 lim_mgmt_tx_complete,
1813 HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME,
1814 smeSessionId, false, 0);
1815
1816 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1817 pMac->lim.mgmtFrameSessionId = 0xff;
1818 lim_log(pMac, LOGE,
1819 FL("could not send TDLS Setup Confirm frame"));
1820 return eSIR_FAILURE;
1821
1822 }
1823
1824 return eSIR_SUCCESS;
1825}
1826
1827/* This Function is similar to populate_dot11f_ht_caps, except that the HT Capabilities
1828 * are considered from the AddStaReq rather from the cfg.dat as in populate_dot11f_ht_caps
1829 */
1830static tSirRetStatus lim_tdls_populate_dot11f_ht_caps(tpAniSirGlobal pMac,
1831 tpPESession psessionEntry,
1832 tSirTdlsAddStaReq *
1833 pTdlsAddStaReq,
1834 tDot11fIEHTCaps *pDot11f)
1835{
1836 uint32_t nCfgValue;
1837 uint8_t nCfgValue8;
1838 tSirMacHTParametersInfo *pHTParametersInfo;
1839 union {
1840 uint16_t nCfgValue16;
1841 tSirMacHTCapabilityInfo htCapInfo;
1842 tSirMacExtendedHTCapabilityInfo extHtCapInfo;
1843 } uHTCapabilityInfo;
1844
1845 tSirMacTxBFCapabilityInfo *pTxBFCapabilityInfo;
1846 tSirMacASCapabilityInfo *pASCapabilityInfo;
1847
1848 nCfgValue = pTdlsAddStaReq->htCap.capInfo;
1849
1850 uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
1851
1852 pDot11f->advCodingCap = uHTCapabilityInfo.htCapInfo.advCodingCap;
1853 pDot11f->mimoPowerSave = uHTCapabilityInfo.htCapInfo.mimoPowerSave;
1854 pDot11f->greenField = uHTCapabilityInfo.htCapInfo.greenField;
1855 pDot11f->shortGI20MHz = uHTCapabilityInfo.htCapInfo.shortGI20MHz;
1856 pDot11f->shortGI40MHz = uHTCapabilityInfo.htCapInfo.shortGI40MHz;
1857 pDot11f->txSTBC = uHTCapabilityInfo.htCapInfo.txSTBC;
1858 pDot11f->rxSTBC = uHTCapabilityInfo.htCapInfo.rxSTBC;
1859 pDot11f->delayedBA = uHTCapabilityInfo.htCapInfo.delayedBA;
1860 pDot11f->maximalAMSDUsize =
1861 uHTCapabilityInfo.htCapInfo.maximalAMSDUsize;
1862 pDot11f->dsssCckMode40MHz =
1863 uHTCapabilityInfo.htCapInfo.dsssCckMode40MHz;
1864 pDot11f->psmp = uHTCapabilityInfo.htCapInfo.psmp;
1865 pDot11f->stbcControlFrame =
1866 uHTCapabilityInfo.htCapInfo.stbcControlFrame;
1867 pDot11f->lsigTXOPProtection =
1868 uHTCapabilityInfo.htCapInfo.lsigTXOPProtection;
1869
1870 /*
1871 * All sessionized entries will need the check below
1872 * Only in case of NO session
1873 */
1874 if (psessionEntry == NULL) {
1875 pDot11f->supportedChannelWidthSet =
1876 uHTCapabilityInfo.htCapInfo.supportedChannelWidthSet;
1877 } else {
1878 pDot11f->supportedChannelWidthSet =
1879 psessionEntry->htSupportedChannelWidthSet;
1880 }
1881
1882 /* Ensure that shortGI40MHz is Disabled if supportedChannelWidthSet is
1883 eHT_CHANNEL_WIDTH_20MHZ */
1884 if (pDot11f->supportedChannelWidthSet == eHT_CHANNEL_WIDTH_20MHZ) {
1885 pDot11f->shortGI40MHz = 0;
1886 }
1887
1888 lim_log(pMac, LOG1,
1889 FL(
1890 "SupportedChnlWidth: %d, mimoPS: %d, GF: %d, shortGI20:%d, shortGI40: %d, dsssCck: %d"
1891 ),
1892 pDot11f->supportedChannelWidthSet,
1893 pDot11f->mimoPowerSave,
1894 pDot11f->greenField,
1895 pDot11f->shortGI20MHz,
1896 pDot11f->shortGI40MHz,
1897 pDot11f->dsssCckMode40MHz);
1898
1899 nCfgValue = pTdlsAddStaReq->htCap.ampduParamsInfo;
1900
1901 nCfgValue8 = (uint8_t) nCfgValue;
1902 pHTParametersInfo = (tSirMacHTParametersInfo *) &nCfgValue8;
1903
1904 pDot11f->maxRxAMPDUFactor = pHTParametersInfo->maxRxAMPDUFactor;
1905 pDot11f->mpduDensity = pHTParametersInfo->mpduDensity;
1906 pDot11f->reserved1 = pHTParametersInfo->reserved;
1907
1908 lim_log(pMac, LOG1, FL("AMPDU Param: %x"), nCfgValue);
1909
1910 cdf_mem_copy(pDot11f->supportedMCSSet, pTdlsAddStaReq->htCap.suppMcsSet,
1911 SIZE_OF_SUPPORTED_MCS_SET);
1912
1913 nCfgValue = pTdlsAddStaReq->htCap.extendedHtCapInfo;
1914
1915 uHTCapabilityInfo.nCfgValue16 = nCfgValue & 0xFFFF;
1916
1917 pDot11f->pco = uHTCapabilityInfo.extHtCapInfo.pco;
1918 pDot11f->transitionTime = uHTCapabilityInfo.extHtCapInfo.transitionTime;
1919 pDot11f->mcsFeedback = uHTCapabilityInfo.extHtCapInfo.mcsFeedback;
1920
1921 nCfgValue = pTdlsAddStaReq->htCap.txBFCapInfo;
1922
1923 pTxBFCapabilityInfo = (tSirMacTxBFCapabilityInfo *) &nCfgValue;
1924 pDot11f->txBF = pTxBFCapabilityInfo->txBF;
1925 pDot11f->rxStaggeredSounding = pTxBFCapabilityInfo->rxStaggeredSounding;
1926 pDot11f->txStaggeredSounding = pTxBFCapabilityInfo->txStaggeredSounding;
1927 pDot11f->rxZLF = pTxBFCapabilityInfo->rxZLF;
1928 pDot11f->txZLF = pTxBFCapabilityInfo->txZLF;
1929 pDot11f->implicitTxBF = pTxBFCapabilityInfo->implicitTxBF;
1930 pDot11f->calibration = pTxBFCapabilityInfo->calibration;
1931 pDot11f->explicitCSITxBF = pTxBFCapabilityInfo->explicitCSITxBF;
1932 pDot11f->explicitUncompressedSteeringMatrix =
1933 pTxBFCapabilityInfo->explicitUncompressedSteeringMatrix;
1934 pDot11f->explicitBFCSIFeedback =
1935 pTxBFCapabilityInfo->explicitBFCSIFeedback;
1936 pDot11f->explicitUncompressedSteeringMatrixFeedback =
1937 pTxBFCapabilityInfo->explicitUncompressedSteeringMatrixFeedback;
1938 pDot11f->explicitCompressedSteeringMatrixFeedback =
1939 pTxBFCapabilityInfo->explicitCompressedSteeringMatrixFeedback;
1940 pDot11f->csiNumBFAntennae = pTxBFCapabilityInfo->csiNumBFAntennae;
1941 pDot11f->uncompressedSteeringMatrixBFAntennae =
1942 pTxBFCapabilityInfo->uncompressedSteeringMatrixBFAntennae;
1943 pDot11f->compressedSteeringMatrixBFAntennae =
1944 pTxBFCapabilityInfo->compressedSteeringMatrixBFAntennae;
1945
1946 nCfgValue = pTdlsAddStaReq->htCap.antennaSelectionInfo;
1947
1948 nCfgValue8 = (uint8_t) nCfgValue;
1949
1950 pASCapabilityInfo = (tSirMacASCapabilityInfo *) &nCfgValue8;
1951 pDot11f->antennaSelection = pASCapabilityInfo->antennaSelection;
1952 pDot11f->explicitCSIFeedbackTx =
1953 pASCapabilityInfo->explicitCSIFeedbackTx;
1954 pDot11f->antennaIndicesFeedbackTx =
1955 pASCapabilityInfo->antennaIndicesFeedbackTx;
1956 pDot11f->explicitCSIFeedback = pASCapabilityInfo->explicitCSIFeedback;
1957 pDot11f->antennaIndicesFeedback =
1958 pASCapabilityInfo->antennaIndicesFeedback;
1959 pDot11f->rxAS = pASCapabilityInfo->rxAS;
1960 pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs;
1961
1962 pDot11f->present = pTdlsAddStaReq->htcap_present;
1963
1964 return eSIR_SUCCESS;
1965
1966}
1967
1968tSirRetStatus
1969lim_tdls_populate_dot11f_vht_caps(tpAniSirGlobal pMac,
1970 tSirTdlsAddStaReq *pTdlsAddStaReq,
1971 tDot11fIEVHTCaps *pDot11f)
1972{
1973 uint32_t nCfgValue = 0;
1974 union {
1975 uint32_t nCfgValue32;
1976 tSirMacVHTCapabilityInfo vhtCapInfo;
1977 } uVHTCapabilityInfo;
1978 union {
1979 uint16_t nCfgValue16;
1980 tSirMacVHTTxSupDataRateInfo vhtTxSupDataRateInfo;
1981 tSirMacVHTRxSupDataRateInfo vhtRxsupDataRateInfo;
1982 } uVHTSupDataRateInfo;
1983
1984 pDot11f->present = pTdlsAddStaReq->vhtcap_present;
1985
1986 nCfgValue = pTdlsAddStaReq->vhtCap.vhtCapInfo;
1987 uVHTCapabilityInfo.nCfgValue32 = nCfgValue;
1988
1989 pDot11f->maxMPDULen = uVHTCapabilityInfo.vhtCapInfo.maxMPDULen;
1990 pDot11f->supportedChannelWidthSet =
1991 uVHTCapabilityInfo.vhtCapInfo.supportedChannelWidthSet;
1992 pDot11f->ldpcCodingCap = uVHTCapabilityInfo.vhtCapInfo.ldpcCodingCap;
1993 pDot11f->shortGI80MHz = uVHTCapabilityInfo.vhtCapInfo.shortGI80MHz;
1994 pDot11f->shortGI160and80plus80MHz =
1995 uVHTCapabilityInfo.vhtCapInfo.shortGI160and80plus80MHz;
1996 pDot11f->txSTBC = uVHTCapabilityInfo.vhtCapInfo.txSTBC;
1997 pDot11f->rxSTBC = uVHTCapabilityInfo.vhtCapInfo.rxSTBC;
1998 pDot11f->suBeamFormerCap = 0;
1999 pDot11f->suBeamformeeCap = 0;
2000 pDot11f->csnofBeamformerAntSup =
2001 uVHTCapabilityInfo.vhtCapInfo.csnofBeamformerAntSup;
2002 pDot11f->numSoundingDim = uVHTCapabilityInfo.vhtCapInfo.numSoundingDim;
2003 pDot11f->muBeamformerCap = 0;
2004 pDot11f->muBeamformeeCap = 0;
2005 pDot11f->vhtTXOPPS = uVHTCapabilityInfo.vhtCapInfo.vhtTXOPPS;
2006 pDot11f->htcVHTCap = uVHTCapabilityInfo.vhtCapInfo.htcVHTCap;
2007 pDot11f->maxAMPDULenExp = uVHTCapabilityInfo.vhtCapInfo.maxAMPDULenExp;
2008 pDot11f->vhtLinkAdaptCap =
2009 uVHTCapabilityInfo.vhtCapInfo.vhtLinkAdaptCap;
2010 pDot11f->rxAntPattern = uVHTCapabilityInfo.vhtCapInfo.rxAntPattern;
2011 pDot11f->txAntPattern = uVHTCapabilityInfo.vhtCapInfo.txAntPattern;
2012 pDot11f->reserved1 = uVHTCapabilityInfo.vhtCapInfo.reserved1;
2013
2014 pDot11f->rxMCSMap = pTdlsAddStaReq->vhtCap.suppMcs.rxMcsMap;
2015
2016 nCfgValue = pTdlsAddStaReq->vhtCap.suppMcs.rxHighest;
2017 uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff;
2018 pDot11f->rxHighSupDataRate =
2019 uVHTSupDataRateInfo.vhtRxsupDataRateInfo.rxSupDataRate;
2020
2021 pDot11f->txMCSMap = pTdlsAddStaReq->vhtCap.suppMcs.txMcsMap;
2022
2023 nCfgValue = pTdlsAddStaReq->vhtCap.suppMcs.txHighest;
2024 uVHTSupDataRateInfo.nCfgValue16 = nCfgValue & 0xffff;
2025 pDot11f->txSupDataRate =
2026 uVHTSupDataRateInfo.vhtTxSupDataRateInfo.txSupDataRate;
2027
2028 pDot11f->reserved3 = uVHTSupDataRateInfo.vhtTxSupDataRateInfo.reserved;
2029
2030 lim_log_vht_cap(pMac, pDot11f);
2031
2032 return eSIR_SUCCESS;
2033
2034}
2035
2036/**
2037 * lim_tdls_populate_matching_rate_set() - populate matching rate set
2038 *
2039 * @mac_ctx - global MAC context
2040 * @stads - station hash entry
2041 * @supp_rate_set - pointer to supported rate set
2042 * @supp_rates_len - length of the supported rates
2043 * @supp_mcs_set - pointer to supported MSC set
2044 * @session_entry - pointer to PE session entry
2045 * @vht_caps - pointer to VHT capability
2046 *
2047 *
2048 * This function gets set of available rates from the config and compare them
2049 * against the set of received supported rates. After the comparison station
2050 * entry's rates is populated with 11A rates and 11B rates.
2051 *
2052 * Return: eSIR_SUCCESS on success, eSIR_FAILURE on failure.
2053 */
2054static tSirRetStatus
2055lim_tdls_populate_matching_rate_set(tpAniSirGlobal mac_ctx, tpDphHashNode stads,
2056 uint8_t *supp_rate_set,
2057 uint8_t supp_rates_len,
2058 uint8_t *supp_mcs_set,
2059 tpPESession session_entry,
2060 tDot11fIEVHTCaps *vht_caps)
2061{
2062 tSirMacRateSet temp_rate_set;
2063 uint32_t i, j, val, min, is_a_rate;
2064 tSirMacRateSet temp_rate_set2;
2065 uint32_t phymode;
2066 uint8_t mcsSet[SIZE_OF_SUPPORTED_MCS_SET];
2067 tpSirSupportedRates rates;
2068 uint8_t a_rateindex = 0;
2069 uint8_t b_rateindex = 0;
2070 is_a_rate = 0;
2071 temp_rate_set2.numRates = 0;
2072
2073 lim_get_phy_mode(mac_ctx, &phymode, NULL);
2074
2075 /* get own rate set */
2076 val = WNI_CFG_OPERATIONAL_RATE_SET_LEN;
2077 if (wlan_cfg_get_str(mac_ctx, WNI_CFG_OPERATIONAL_RATE_SET,
2078 (uint8_t *) &temp_rate_set.rate,
2079 &val) != eSIR_SUCCESS) {
2080 /* Could not get rateset from CFG. Log error. */
2081 lim_log(mac_ctx, LOGE, FL("could not retrieve rateset"));
2082 val = 0;
2083 }
2084 temp_rate_set.numRates = val;
2085
2086 if (phymode == WNI_CFG_PHY_MODE_11G) {
2087 /* get own extended rate set */
2088 val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN;
2089 if (wlan_cfg_get_str(mac_ctx,
2090 WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET,
2091 (uint8_t *) &temp_rate_set2.rate,
2092 &val) != eSIR_SUCCESS)
2093 temp_rate_set2.numRates = val;
2094 }
2095
2096 if ((temp_rate_set.numRates + temp_rate_set2.numRates) > 12) {
2097 lim_log(mac_ctx, LOGE, FL("more than 12 rates in CFG"));
2098 goto error;
2099 }
2100
2101 /**
2102 * Handling of the rate set IEs is the following:
2103 * - keep only rates that we support and that the station supports
2104 * - sort and the rates into the pSta->rate array
2105 */
2106
2107 /* Copy all rates in temp_rate_set, there are 12 rates max */
2108 for (i = 0; i < temp_rate_set2.numRates; i++)
2109 temp_rate_set.rate[i + temp_rate_set.numRates] =
2110 temp_rate_set2.rate[i];
2111
2112 temp_rate_set.numRates += temp_rate_set2.numRates;
2113
2114 /**
2115 * Sort rates in temp_rate_set (they are likely to be already sorted)
2116 * put the result in temp_rate_set2
2117 */
2118 temp_rate_set2.numRates = 0;
2119
2120 for (i = 0; i < temp_rate_set.numRates; i++) {
2121 min = 0;
2122 val = 0xff;
2123
2124 for (j = 0; j < temp_rate_set.numRates; j++)
2125 if ((uint32_t) (temp_rate_set.rate[j] & 0x7f) < val) {
2126 val = temp_rate_set.rate[j] & 0x7f;
2127 min = j;
2128 }
2129
2130 temp_rate_set2.rate[temp_rate_set2.numRates++] =
2131 temp_rate_set.rate[min];
2132 temp_rate_set.rate[min] = 0xff;
2133 }
2134
2135 /**
2136 * Copy received rates in temp_rate_set, the parser has ensured
2137 * unicity of the rates so there cannot be more than 12 .
2138 */
2139 if (supp_rates_len > SIR_MAC_RATESET_EID_MAX) {
2140 lim_log(mac_ctx, LOGW,
2141 FL(
2142 "Supported rates length %d more than the Max limit, reset to Max"
2143 ),
2144 supp_rates_len);
2145 supp_rates_len = SIR_MAC_RATESET_EID_MAX;
2146 }
2147
2148 for (i = 0; i < supp_rates_len; i++)
2149 temp_rate_set.rate[i] = supp_rate_set[i];
2150
2151 temp_rate_set.numRates = supp_rates_len;
2152
2153 rates = &stads->supportedRates;
2154 cdf_mem_set((uint8_t *) rates, sizeof(tSirSupportedRates), 0);
2155
2156 for (i = 0; i < temp_rate_set2.numRates; i++) {
2157 for (j = 0; j < temp_rate_set.numRates; j++) {
2158 if ((temp_rate_set2.rate[i] & 0x7F) !=
2159 (temp_rate_set.rate[j] & 0x7F))
2160 continue;
2161
2162#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2163 if ((b_rateindex > HAL_NUM_11B_RATES) ||
2164 (a_rateindex > HAL_NUM_11A_RATES)) {
2165 lim_log(mac_ctx, LOGE,
2166 FL("Invalid number of rates (11b->%d, 11a->%d)"),
2167 b_rateindex, a_rateindex);
2168 return eSIR_FAILURE;
2169 }
2170#endif
2171 if (sirIsArate(temp_rate_set2.rate[i] & 0x7f)) {
2172 is_a_rate = 1;
2173 if (a_rateindex < SIR_NUM_11A_RATES)
2174 rates->llaRates[a_rateindex++] = temp_rate_set2.rate[i];
2175 } else {
2176 if (b_rateindex < SIR_NUM_11B_RATES)
2177 rates->llbRates[b_rateindex++] = temp_rate_set2.rate[i];
2178 }
2179 break;
2180 }
2181 }
2182
2183 /* compute the matching MCS rate set, if peer is 11n capable and self mode is 11n */
2184#ifdef FEATURE_WLAN_TDLS
2185 if (stads->mlmStaContext.htCapability)
2186#else
2187 if (IS_DOT11_MODE_HT(session_entry->dot11mode) &&
2188 (stads->mlmStaContext.htCapability))
2189#endif
2190 {
2191 val = SIZE_OF_SUPPORTED_MCS_SET;
2192 if (wlan_cfg_get_str(mac_ctx, WNI_CFG_SUPPORTED_MCS_SET,
2193 mcsSet, &val) != eSIR_SUCCESS) {
2194 /* Could not get rateset from CFG. Log error. */
2195 lim_log(mac_ctx, LOGP,
2196 FL("could not retrieve supportedMCSSet"));
2197 goto error;
2198 }
2199
2200 for (i = 0; i < val; i++)
2201 stads->supportedRates.supportedMCSSet[i] =
2202 mcsSet[i] & supp_mcs_set[i];
2203
2204 lim_log(mac_ctx, LOG1,
2205 FL("MCS Rate Set Bitmap from CFG and DPH"));
2206 for (i = 0; i < SIR_MAC_MAX_SUPPORTED_MCS_SET; i++) {
2207 lim_log(mac_ctx, LOG1, FL("%x %x"), mcsSet[i],
2208 stads->supportedRates.supportedMCSSet[i]);
2209 }
2210 }
2211#ifdef WLAN_FEATURE_11AC
2212 lim_populate_vht_mcs_set(mac_ctx, &stads->supportedRates, vht_caps,
2213 session_entry);
2214#endif
2215 /**
2216 * Set the erpEnabled bit if the phy is in G mode and at least
2217 * one A rate is supported
2218 */
2219 if ((phymode == WNI_CFG_PHY_MODE_11G) && is_a_rate)
2220 stads->erpEnabled = eHAL_SET;
2221
2222 return eSIR_SUCCESS;
2223
2224error:
2225 return eSIR_FAILURE;
2226}
2227
2228/*
2229 * update HASH node entry info
2230 */
2231static void lim_tdls_update_hash_node_info(tpAniSirGlobal pMac,
2232 tDphHashNode *pStaDs,
2233 tSirTdlsAddStaReq *pTdlsAddStaReq,
2234 tpPESession psessionEntry)
2235{
2236 tDot11fIEHTCaps htCap = {0,};
2237 tDot11fIEHTCaps *htCaps;
2238 tDot11fIEVHTCaps *pVhtCaps = NULL;
2239 tDot11fIEVHTCaps *pVhtCaps_txbf = NULL;
2240#ifdef WLAN_FEATURE_11AC
2241 tDot11fIEVHTCaps vhtCap;
2242 uint8_t cbMode;
2243#endif
2244 tpDphHashNode pSessStaDs = NULL;
2245 uint16_t aid;
2246
2247 if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_ADD) {
2248 populate_dot11f_ht_caps(pMac, psessionEntry, &htCap);
2249 } else if (pTdlsAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE) {
2250 lim_tdls_populate_dot11f_ht_caps(pMac, NULL, pTdlsAddStaReq, &htCap);
2251 }
2252 htCaps = &htCap;
2253 if (htCaps->present) {
2254 pStaDs->mlmStaContext.htCapability = 1;
2255 pStaDs->htGreenfield = htCaps->greenField;
2256 pStaDs->htSupportedChannelWidthSet =
2257 htCaps->supportedChannelWidthSet;
2258 pStaDs->htMIMOPSState = htCaps->mimoPowerSave;
2259 pStaDs->htMaxAmsduLength = htCaps->maximalAMSDUsize;
2260 pStaDs->htAMpduDensity = htCaps->mpduDensity;
2261 pStaDs->htDsssCckRate40MHzSupport = htCaps->dsssCckMode40MHz;
2262 pStaDs->htShortGI20Mhz = htCaps->shortGI20MHz;
2263 pStaDs->htShortGI40Mhz = htCaps->shortGI40MHz;
2264 pStaDs->htMaxRxAMpduFactor = htCaps->maxRxAMPDUFactor;
2265 lim_fill_rx_highest_supported_rate(pMac,
2266 &pStaDs->supportedRates.
2267 rxHighestDataRate,
2268 htCaps->supportedMCSSet);
2269 pStaDs->baPolicyFlag = 0xFF;
2270 pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_N;
2271 pStaDs->ht_caps = pTdlsAddStaReq->htCap.capInfo;
2272 } else {
2273 pStaDs->mlmStaContext.htCapability = 0;
2274 pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_BG;
2275 }
2276#ifdef WLAN_FEATURE_11AC
2277 lim_tdls_populate_dot11f_vht_caps(pMac, pTdlsAddStaReq, &vhtCap);
2278 pVhtCaps = &vhtCap;
2279 if (pVhtCaps->present) {
2280 pStaDs->mlmStaContext.vhtCapability = 1;
2281
2282 if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) {
2283 /*
2284 * if the channel is 2G then update the min channel
2285 * widthset in pStaDs. These values are used when
2286 * sending a AddSta request to firmware
2287 * 11.21.1 General: The channel width of the TDLS direct
2288 * link on the base channel shall not exceed the channel
2289 * width of the BSS to which the TDLS peer STAs are
2290 * associated.
2291 */
2292 pStaDs->vhtSupportedChannelWidthSet =
2293 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
2294 pStaDs->htSupportedChannelWidthSet =
2295 eHT_CHANNEL_WIDTH_20MHZ;
2296 lim_log(pMac, LOG1, FL("vhtSupportedChannelWidthSet = %hu, htSupportedChannelWidthSet %hu"),
2297 pStaDs->htSupportedChannelWidthSet,
2298 pStaDs->htSupportedChannelWidthSet);
2299 } else {
2300 pStaDs->vhtSupportedChannelWidthSet =
2301 WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ;
2302 pStaDs->htSupportedChannelWidthSet =
2303 eHT_CHANNEL_WIDTH_40MHZ;
2304 }
2305
2306 pStaDs->vhtLdpcCapable = pVhtCaps->ldpcCodingCap;
2307 pStaDs->vhtBeamFormerCapable = 0;
2308 pMac->lim.gLimTdlsLinkMode = TDLS_LINK_MODE_AC;
2309 pVhtCaps_txbf = (tDot11fIEVHTCaps *) (&pTdlsAddStaReq->vhtCap);
2310 pVhtCaps_txbf->suBeamformeeCap = 0;
2311 pVhtCaps_txbf->suBeamFormerCap = 0;
2312 pVhtCaps_txbf->muBeamformerCap = 0;
2313 pVhtCaps_txbf->muBeamformeeCap = 0;
2314 pStaDs->vht_caps = pTdlsAddStaReq->vhtCap.vhtCapInfo;
2315 } else {
2316 pStaDs->mlmStaContext.vhtCapability = 0;
2317 pStaDs->vhtSupportedChannelWidthSet =
2318 WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ;
2319 }
2320#endif
2321 /*Calculate the Secondary Coannel Offset */
2322 cbMode = lim_select_cb_mode(pStaDs, psessionEntry,
2323 psessionEntry->currentOperChannel,
2324 pStaDs->vhtSupportedChannelWidthSet);
2325
2326 pStaDs->htSecondaryChannelOffset = cbMode;
2327
2328#ifdef WLAN_FEATURE_11AC
2329 if (pStaDs->mlmStaContext.vhtCapability) {
2330 pStaDs->htSecondaryChannelOffset = lim_get_htcb_state(cbMode);
2331 }
2332#endif
2333
2334 pSessStaDs = dph_lookup_hash_entry(pMac, psessionEntry->bssId, &aid,
2335 &psessionEntry->dph.dphHashTable);
2336
2337 /* Lets enable QOS parameter */
2338 pStaDs->qosMode = 1;
2339 pStaDs->wmeEnabled = 1;
2340 pStaDs->lleEnabled = 0;
2341 /* TDLS Dummy AddSTA does not have qosInfo , is it OK ??
2342 */
2343 pStaDs->qos.capability.qosInfo =
2344 (*(tSirMacQosInfoStation *) &pTdlsAddStaReq->uapsd_queues);
2345
2346 /* populate matching rate set */
2347
2348 /* TDLS Dummy AddSTA does not have HTCap,VHTCap,Rates info , is it OK ??
2349 */
2350 lim_tdls_populate_matching_rate_set(pMac, pStaDs,
2351 pTdlsAddStaReq->supported_rates,
2352 pTdlsAddStaReq->supported_rates_length,
2353 (uint8_t *) pTdlsAddStaReq->htCap.
2354 suppMcsSet, psessionEntry, pVhtCaps);
2355
2356 /* TDLS Dummy AddSTA does not have right capability , is it OK ??
2357 */
2358 pStaDs->mlmStaContext.capabilityInfo =
2359 (*(tSirMacCapabilityInfo *) &pTdlsAddStaReq->capability);
2360
2361 return;
2362}
2363
2364/*
2365 * Add STA for TDLS setup procedure
2366 */
2367static tSirRetStatus lim_tdls_setup_add_sta(tpAniSirGlobal pMac,
2368 tSirTdlsAddStaReq *pAddStaReq,
2369 tpPESession psessionEntry)
2370{
2371 tpDphHashNode pStaDs = NULL;
2372 tSirRetStatus status = eSIR_SUCCESS;
2373 uint16_t aid = 0;
2374
2375 pStaDs = dph_lookup_hash_entry(pMac, pAddStaReq->peerMac, &aid,
2376 &psessionEntry->dph.dphHashTable);
2377 if (NULL == pStaDs) {
2378 aid = lim_assign_peer_idx(pMac, psessionEntry);
2379
2380 if (!aid) {
2381 lim_log(pMac, LOGE,
2382 FL("No more free AID for peer "
2383 MAC_ADDRESS_STR),
2384 MAC_ADDR_ARRAY(pAddStaReq->peerMac));
2385 return eSIR_FAILURE;
2386 }
2387
2388 /* Set the aid in peerAIDBitmap as it has been assigned to TDLS peer */
2389 SET_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap, aid);
2390
2391 lim_log(pMac, LOG1, FL("Aid = %d, for peer =" MAC_ADDRESS_STR),
2392 aid, MAC_ADDR_ARRAY(pAddStaReq->peerMac));
2393 pStaDs =
2394 dph_get_hash_entry(pMac, aid,
2395 &psessionEntry->dph.dphHashTable);
2396
2397 if (pStaDs) {
2398 (void)lim_del_sta(pMac, pStaDs, false /*asynchronous */,
2399 psessionEntry);
2400 lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, aid,
2401 psessionEntry);
2402 }
2403
2404 pStaDs = dph_add_hash_entry(pMac, pAddStaReq->peerMac, aid,
2405 &psessionEntry->dph.dphHashTable);
2406
2407 if (NULL == pStaDs) {
2408 lim_log(pMac, LOGE, FL("add hash entry failed"));
2409 CDF_ASSERT(0);
2410 return eSIR_FAILURE;
2411 }
2412 }
2413
2414 lim_tdls_update_hash_node_info(pMac, pStaDs, pAddStaReq, psessionEntry);
2415
2416 pStaDs->staType = STA_ENTRY_TDLS_PEER;
2417
2418 status =
2419 lim_add_sta(pMac, pStaDs,
2420 (pAddStaReq->tdlsAddOper ==
2421 TDLS_OPER_UPDATE) ? true : false, psessionEntry);
2422
2423 if (eSIR_SUCCESS != status) {
2424 /* should not fail */
2425 CDF_ASSERT(0);
2426 }
2427 return status;
2428}
2429
2430/*
2431 * Del STA, after Link is teardown or discovery response sent on direct link
2432 */
2433static tpDphHashNode lim_tdls_del_sta(tpAniSirGlobal pMac, tSirMacAddr peerMac,
2434 tpPESession psessionEntry)
2435{
2436 tSirRetStatus status = eSIR_SUCCESS;
2437 uint16_t peerIdx = 0;
2438 tpDphHashNode pStaDs = NULL;
2439
2440 pStaDs = dph_lookup_hash_entry(pMac, peerMac, &peerIdx,
2441 &psessionEntry->dph.dphHashTable);
2442
2443 if (pStaDs) {
2444
2445 lim_log(pMac, LOG1, FL("DEL STA peer MAC: "MAC_ADDRESS_STR),
2446 MAC_ADDR_ARRAY(pStaDs->staAddr));
2447
2448 lim_log(pMac, LOG1, FL("STA type = %x, sta idx = %x"),
2449 pStaDs->staType,
2450 pStaDs->staIndex);
2451
2452 status = lim_del_sta(pMac, pStaDs, false, psessionEntry);
2453 }
2454
2455 return pStaDs;
2456}
2457
2458/*
2459 * Once Link is setup with PEER, send Add STA ind to SME
2460 */
2461static CDF_STATUS lim_send_sme_tdls_add_sta_rsp(tpAniSirGlobal pMac,
2462 uint8_t sessionId,
2463 tSirMacAddr peerMac,
2464 uint8_t updateSta,
2465 tDphHashNode *pStaDs, uint8_t status)
2466{
2467 tSirMsgQ mmhMsg = { 0 };
2468 tSirTdlsAddStaRsp *addStaRsp = NULL;
2469 mmhMsg.type = eWNI_SME_TDLS_ADD_STA_RSP;
2470
2471 addStaRsp = cdf_mem_malloc(sizeof(tSirTdlsAddStaRsp));
2472 if (NULL == addStaRsp) {
2473 lim_log(pMac, LOGE, FL("Failed to allocate memory"));
2474 return CDF_STATUS_E_NOMEM;
2475 }
2476
2477 addStaRsp->sessionId = sessionId;
2478 addStaRsp->statusCode = status;
2479 if (pStaDs) {
2480 addStaRsp->staId = pStaDs->staIndex;
2481 addStaRsp->ucastSig = pStaDs->ucUcastSig;
2482 addStaRsp->bcastSig = pStaDs->ucBcastSig;
2483 }
2484 if (peerMac) {
2485 cdf_mem_copy(addStaRsp->peerMac,
2486 (uint8_t *) peerMac, sizeof(tSirMacAddr));
2487 }
2488 if (updateSta)
2489 addStaRsp->tdlsAddOper = TDLS_OPER_UPDATE;
2490 else
2491 addStaRsp->tdlsAddOper = TDLS_OPER_ADD;
2492
2493 addStaRsp->length = sizeof(tSirTdlsAddStaRsp);
2494 addStaRsp->messageType = eWNI_SME_TDLS_ADD_STA_RSP;
2495
2496 mmhMsg.bodyptr = addStaRsp;
2497 mmhMsg.bodyval = 0;
2498 lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
2499
2500 return CDF_STATUS_SUCCESS;
2501
2502}
2503
2504/*
2505 * STA RSP received from HAL
2506 */
2507CDF_STATUS lim_process_tdls_add_sta_rsp(tpAniSirGlobal pMac, void *msg,
2508 tpPESession psessionEntry)
2509{
2510 tAddStaParams *pAddStaParams = (tAddStaParams *) msg;
2511 uint8_t status = eSIR_SUCCESS;
2512 tDphHashNode *pStaDs = NULL;
2513 uint16_t aid = 0;
2514
2515 SET_LIM_PROCESS_DEFD_MESGS(pMac, true);
2516 lim_log(pMac, LOG1, FL("staIdx=%d, staMac="MAC_ADDRESS_STR),
2517 pAddStaParams->staIdx,
2518 MAC_ADDR_ARRAY(pAddStaParams->staMac));
2519
2520 if (pAddStaParams->status != CDF_STATUS_SUCCESS) {
2521 CDF_ASSERT(0);
2522 lim_log(pMac, LOGE, FL("Add sta failed "));
2523 status = eSIR_FAILURE;
2524 goto add_sta_error;
2525 }
2526
2527 pStaDs = dph_lookup_hash_entry(pMac, pAddStaParams->staMac, &aid,
2528 &psessionEntry->dph.dphHashTable);
2529 if (NULL == pStaDs) {
2530 lim_log(pMac, LOGE, FL("pStaDs is NULL "));
2531 status = eSIR_FAILURE;
2532 goto add_sta_error;
2533 }
2534
2535 pStaDs->bssId = pAddStaParams->bssIdx;
2536 pStaDs->staIndex = pAddStaParams->staIdx;
2537 pStaDs->ucUcastSig = pAddStaParams->ucUcastSig;
2538 pStaDs->ucBcastSig = pAddStaParams->ucBcastSig;
2539 pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE;
2540 pStaDs->valid = 1;
2541add_sta_error:
2542 status = lim_send_sme_tdls_add_sta_rsp(pMac, psessionEntry->smeSessionId,
2543 pAddStaParams->staMac,
2544 pAddStaParams->updateSta, pStaDs,
2545 status);
2546 cdf_mem_free(pAddStaParams);
2547 return status;
2548}
2549
2550void populate_dot11f_tdls_offchannel_params(tpAniSirGlobal pMac,
2551 tpPESession psessionEntry,
2552 tDot11fIESuppChannels *suppChannels,
2553 tDot11fIESuppOperatingClasses *
2554 suppOperClasses)
2555{
2556 uint32_t numChans = WNI_CFG_VALID_CHANNEL_LIST_LEN;
2557 uint8_t validChan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
2558 uint8_t i;
2559 uint8_t valid_count = 0;
2560 uint8_t chanOffset;
2561 uint8_t op_class;
2562 uint8_t numClasses;
2563 uint8_t classes[SIR_MAC_MAX_SUPP_OPER_CLASSES];
2564 if (wlan_cfg_get_str(pMac, WNI_CFG_VALID_CHANNEL_LIST,
2565 validChan, &numChans) != eSIR_SUCCESS) {
2566 /**
2567 * Could not get Valid channel list from CFG.
2568 * Log error.
2569 */
2570 lim_log(pMac, LOGE,
2571 FL("could not retrieve Valid channel list"));
2572 return;
2573 }
2574
2575 /* validating the channel list for DFS channels */
2576 for (i = 0U; i < numChans; i++) {
2577 if (CHANNEL_STATE_DFS ==
2578 cds_get_channel_state(validChan[i])) {
2579 lim_log(pMac, LOG1,
2580 FL(
2581 "skipping DFS channel %d from the valid channel list"
2582 ),
2583 validChan[i]);
2584 continue;
2585 }
2586
2587 if (valid_count >= ARRAY_SIZE(suppChannels->bands))
2588 break;
2589 suppChannels->bands[valid_count][0] = validChan[i];
2590 suppChannels->bands[valid_count][1] = 1;
2591 valid_count++;
2592 }
2593
2594 suppChannels->num_bands = valid_count;
2595 suppChannels->present = 1;
2596
2597 /* find channel offset and get op class for current operating channel */
2598 switch (psessionEntry->htSecondaryChannelOffset) {
2599 case PHY_SINGLE_CHANNEL_CENTERED:
2600 chanOffset = BW20;
2601 break;
2602
2603 case PHY_DOUBLE_CHANNEL_LOW_PRIMARY:
2604 chanOffset = BW40_LOW_PRIMARY;
2605 break;
2606
2607 case PHY_DOUBLE_CHANNEL_HIGH_PRIMARY:
2608 chanOffset = BW40_HIGH_PRIMARY;
2609 break;
2610
2611 default:
2612 chanOffset = BWALL;
2613 break;
2614
2615 }
2616
2617 op_class = cds_regdm_get_opclass_from_channel(
2618 pMac->scan.countryCodeCurrent,
2619 psessionEntry->currentOperChannel,
2620 chanOffset);
2621
2622 if (op_class == 0) {
2623 lim_log(pMac, LOGE,
2624 FL(
2625 "Present Operating class is wrong, countryCodeCurrent: %s, currentOperChannel: %d, htSecondaryChannelOffset: %d, chanOffset: %d"
2626 ),
2627 pMac->scan.countryCodeCurrent,
2628 psessionEntry->currentOperChannel,
2629 psessionEntry->htSecondaryChannelOffset,
2630 chanOffset);
2631 } else {
2632 lim_log(pMac, LOG1,
2633 FL(
2634 "Present Operating channel: %d chanOffset: %d, op class=%d"
2635 ),
2636 psessionEntry->currentOperChannel, chanOffset,
2637 op_class);
2638 }
2639 suppOperClasses->present = 1;
2640 suppOperClasses->classes[0] = op_class;
2641
2642 cds_regdm_get_curr_opclasses(&numClasses, &classes[0]);
2643
2644 for (i = 0; i < numClasses; i++) {
2645 suppOperClasses->classes[i + 1] = classes[i];
2646 }
2647 /* add one for present operating class, added in the beginning */
2648 suppOperClasses->num_classes = numClasses + 1;
2649
2650 return;
2651}
2652
2653/*
2654 * FUNCTION: Populate Link Identifier element IE
2655 *
2656 */
2657
2658void populate_dot11f_link_iden(tpAniSirGlobal pMac, tpPESession psessionEntry,
2659 tDot11fIELinkIdentifier *linkIden,
2660 tSirMacAddr peerMac, uint8_t reqType)
2661{
2662 uint8_t *initStaAddr = NULL;
2663 uint8_t *respStaAddr = NULL;
2664
2665 (reqType == TDLS_INITIATOR) ? ((initStaAddr = linkIden->InitStaAddr),
2666 (respStaAddr = linkIden->RespStaAddr))
2667 : ((respStaAddr = linkIden->InitStaAddr),
2668 (initStaAddr = linkIden->RespStaAddr));
2669 cdf_mem_copy((uint8_t *) linkIden->bssid,
2670 (uint8_t *) psessionEntry->bssId, sizeof(tSirMacAddr));
2671
2672 cdf_mem_copy((uint8_t *) initStaAddr,
2673 psessionEntry->selfMacAddr, sizeof(tSirMacAddr));
2674
2675 cdf_mem_copy((uint8_t *) respStaAddr, (uint8_t *) peerMac,
2676 sizeof(tSirMacAddr));
2677
2678 linkIden->present = 1;
2679 return;
2680
2681}
2682
2683void populate_dot11f_tdls_ext_capability(tpAniSirGlobal pMac,
2684 tpPESession psessionEntry,
2685 tDot11fIEExtCap *extCapability)
2686{
2687 struct s_ext_cap *p_ext_cap = (struct s_ext_cap *)extCapability->bytes;
2688
2689 p_ext_cap->tdls_peer_psm_supp = PEER_PSM_SUPPORT;
2690 p_ext_cap->tdls_peer_uapsd_buffer_sta = pMac->lim.gLimTDLSBufStaEnabled;
2691
2692 /*
2693 * Set TDLS channel switching bits only if offchannel is enabled
2694 * and TDLS Channel Switching is not prohibited by AP in ExtCap
2695 * IE in assoc/re-assoc response.
2696 */
2697 if ((1 == pMac->lim.gLimTDLSOffChannelEnabled) &&
2698 (!psessionEntry->tdls_chan_swit_prohibited)) {
2699 p_ext_cap->tdls_channel_switching = 1;
2700 p_ext_cap->tdls_chan_swit_prohibited = 0;
2701 } else {
2702 p_ext_cap->tdls_channel_switching = 0;
2703 p_ext_cap->tdls_chan_swit_prohibited = TDLS_CH_SWITCH_PROHIBITED;
2704 }
2705 p_ext_cap->tdls_support = TDLS_SUPPORT;
2706 p_ext_cap->tdls_prohibited = TDLS_PROHIBITED;
2707
2708 extCapability->present = 1;
2709 /* For STA cases we alwasy support 11mc - Allow MAX length */
2710 extCapability->num_bytes = DOT11F_IE_EXTCAP_MAX_LEN;
2711
2712 return;
2713}
2714
2715/**
2716 * lim_process_sme_tdls_mgmt_send_req() - send out tdls management frames
2717 *
2718 * @mac_ctx - global mac context
2719 * @msg - message buffer received from SME.
2720 *
2721 * Process Send Mgmt Request from SME and transmit to AP.
2722 *
2723 * Return: eSIR_SUCCESS on success, error code otherwise
2724 */
2725tSirRetStatus lim_process_sme_tdls_mgmt_send_req(tpAniSirGlobal mac_ctx,
2726 uint32_t *msg)
2727{
2728 /* get all discovery request parameters */
2729 tSirTdlsSendMgmtReq *send_req = (tSirTdlsSendMgmtReq *) msg;
2730 tpPESession session_entry;
2731 uint8_t session_id;
2732 tSirResultCodes result_code = eSIR_SME_INVALID_PARAMETERS;
2733
2734 lim_log(mac_ctx, LOG1, FL("Send Mgmt Recieved"));
2735 session_entry = pe_find_session_by_bssid(mac_ctx,
2736 send_req->bssid, &session_id);
2737 if (NULL == session_entry) {
2738 lim_log(mac_ctx, LOGE,
2739 FL("PE Session does not exist for given sme session_id %d"),
2740 send_req->sessionId);
2741 goto lim_tdls_send_mgmt_error;
2742 }
2743
2744 /* check if we are in proper state to work as TDLS client */
2745 if (!LIM_IS_STA_ROLE(session_entry)) {
2746 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
2747 FL("send mgmt received in wrong system Role %d"),
2748 GET_LIM_SYSTEM_ROLE(session_entry));
2749 goto lim_tdls_send_mgmt_error;
2750 }
2751
2752 /*
2753 * if we are still good, go ahead and check if we are in proper state to
2754 * do TDLS discovery req/rsp/....frames.
2755 */
2756 if ((session_entry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
2757 (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
2758 lim_log(mac_ctx, LOGE,
2759 FL("send mgmt received in invalid LIMsme state (%d)"),
2760 session_entry->limSmeState);
2761 goto lim_tdls_send_mgmt_error;
2762 }
2763
2764 switch (send_req->reqType) {
2765 case SIR_MAC_TDLS_DIS_REQ:
2766 lim_log(mac_ctx, LOG1, FL("Transmit Discovery Request Frame"));
2767 /* format TDLS discovery request frame and transmit it */
2768 lim_send_tdls_dis_req_frame(mac_ctx, send_req->peerMac,
2769 send_req->dialog, session_entry);
2770 result_code = eSIR_SME_SUCCESS;
2771 break;
2772 case SIR_MAC_TDLS_DIS_RSP:
2773 lim_log(mac_ctx, LOG1, FL("Transmit Discovery Response Frame"));
2774 /* Send a response mgmt action frame */
2775 lim_send_tdls_dis_rsp_frame(mac_ctx, send_req->peerMac,
2776 send_req->dialog, session_entry, &send_req->addIe[0],
2777 (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
2778 result_code = eSIR_SME_SUCCESS;
2779 break;
2780 case SIR_MAC_TDLS_SETUP_REQ:
2781 lim_log(mac_ctx, LOG1, FL("Transmit Setup Request Frame"));
2782 lim_send_tdls_link_setup_req_frame(mac_ctx,
2783 send_req->peerMac, send_req->dialog, session_entry,
2784 &send_req->addIe[0],
2785 (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
2786 result_code = eSIR_SME_SUCCESS;
2787 break;
2788 case SIR_MAC_TDLS_SETUP_RSP:
2789 lim_log(mac_ctx, LOG1, FL("Transmit Setup Response Frame"));
2790 lim_send_tdls_setup_rsp_frame(mac_ctx,
2791 send_req->peerMac, send_req->dialog, session_entry,
2792 send_req->statusCode, &send_req->addIe[0],
2793 (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
2794 result_code = eSIR_SME_SUCCESS;
2795 break;
2796 case SIR_MAC_TDLS_SETUP_CNF:
2797 lim_log(mac_ctx, LOG1, FL("Transmit Setup Confirm Frame"));
2798 lim_send_tdls_link_setup_cnf_frame(mac_ctx,
2799 send_req->peerMac, send_req->dialog,
2800 send_req->peerCapability, session_entry,
2801 &send_req->addIe[0],
2802 (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
2803 result_code = eSIR_SME_SUCCESS;
2804 break;
2805 case SIR_MAC_TDLS_TEARDOWN:
2806 lim_log(mac_ctx, LOG1, FL("Transmit Teardown Frame"));
2807 lim_send_tdls_teardown_frame(mac_ctx,
2808 send_req->peerMac, send_req->statusCode,
2809 send_req->responder, session_entry,
2810 &send_req->addIe[0],
2811 (send_req->length - sizeof(tSirTdlsSendMgmtReq)));
2812 result_code = eSIR_SME_SUCCESS;
2813 break;
2814 case SIR_MAC_TDLS_PEER_TRAFFIC_IND:
2815 break;
2816 case SIR_MAC_TDLS_CH_SWITCH_REQ:
2817 break;
2818 case SIR_MAC_TDLS_CH_SWITCH_RSP:
2819 break;
2820 case SIR_MAC_TDLS_PEER_TRAFFIC_RSP:
2821 break;
2822 default:
2823 break;
2824 }
2825
2826lim_tdls_send_mgmt_error:
2827 lim_send_sme_rsp(mac_ctx, eWNI_SME_TDLS_SEND_MGMT_RSP,
2828 result_code, send_req->sessionId,
2829 send_req->transactionId);
2830
2831 return eSIR_SUCCESS;
2832}
2833
2834/*
2835 * Send Response to Link Establish Request to SME
2836 */
2837void lim_send_sme_tdls_link_establish_req_rsp(tpAniSirGlobal pMac,
2838 uint8_t sessionId, tSirMacAddr peerMac,
2839 tDphHashNode *pStaDs, uint8_t status)
2840{
2841 tSirMsgQ mmhMsg = { 0 };
2842
2843 tSirTdlsLinkEstablishReqRsp *pTdlsLinkEstablishReqRsp = NULL;
2844
2845 pTdlsLinkEstablishReqRsp =
2846 cdf_mem_malloc(sizeof(tSirTdlsLinkEstablishReqRsp));
2847 if (NULL == pTdlsLinkEstablishReqRsp) {
2848 lim_log(pMac, LOGE, FL("Failed to allocate memory"));
2849 return;
2850 }
2851 pTdlsLinkEstablishReqRsp->statusCode = status;
2852 if (peerMac) {
2853 cdf_mem_copy(pTdlsLinkEstablishReqRsp->peerMac, peerMac,
2854 sizeof(tSirMacAddr));
2855 }
2856 pTdlsLinkEstablishReqRsp->sessionId = sessionId;
2857 mmhMsg.type = eWNI_SME_TDLS_LINK_ESTABLISH_RSP;
2858 mmhMsg.bodyptr = pTdlsLinkEstablishReqRsp;
2859 mmhMsg.bodyval = 0;
2860 lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
2861 return;
2862
2863}
2864
2865/*
2866 * Once link is teardown, send Del Peer Ind to SME
2867 */
2868static CDF_STATUS lim_send_sme_tdls_del_sta_rsp(tpAniSirGlobal pMac,
2869 uint8_t sessionId,
2870 tSirMacAddr peerMac,
2871 tDphHashNode *pStaDs, uint8_t status)
2872{
2873 tSirMsgQ mmhMsg = { 0 };
2874 tSirTdlsDelStaRsp *pDelSta = NULL;
2875 mmhMsg.type = eWNI_SME_TDLS_DEL_STA_RSP;
2876
2877 pDelSta = cdf_mem_malloc(sizeof(tSirTdlsDelStaRsp));
2878 if (NULL == pDelSta) {
2879 lim_log(pMac, LOGE, FL("Failed to allocate memory"));
2880 return CDF_STATUS_E_NOMEM;
2881 }
2882
2883 pDelSta->sessionId = sessionId;
2884 pDelSta->statusCode = status;
2885 if (pStaDs) {
2886 pDelSta->staId = pStaDs->staIndex;
2887 } else
2888 pDelSta->staId = STA_INVALID_IDX;
2889
2890 if (peerMac) {
2891 cdf_mem_copy(pDelSta->peerMac, peerMac, sizeof(tSirMacAddr));
2892 }
2893
2894 pDelSta->length = sizeof(tSirTdlsDelStaRsp);
2895 pDelSta->messageType = eWNI_SME_TDLS_DEL_STA_RSP;
2896
2897 mmhMsg.bodyptr = pDelSta;
2898
2899 mmhMsg.bodyval = 0;
2900 lim_sys_process_mmh_msg_api(pMac, &mmhMsg, ePROT);
2901 return CDF_STATUS_SUCCESS;
2902
2903}
2904
2905/*
2906 * Process Send Mgmt Request from SME and transmit to AP.
2907 */
2908tSirRetStatus lim_process_sme_tdls_add_sta_req(tpAniSirGlobal pMac,
2909 uint32_t *pMsgBuf)
2910{
2911 /* get all discovery request parameters */
2912 tSirTdlsAddStaReq *pAddStaReq = (tSirTdlsAddStaReq *) pMsgBuf;
2913 tpPESession psessionEntry;
2914 uint8_t sessionId;
2915
2916 lim_log(pMac, LOG1, FL("TDLS Add STA Request Recieved"));
2917 psessionEntry =
2918 pe_find_session_by_bssid(pMac, pAddStaReq->bssid, &sessionId);
2919 if (psessionEntry == NULL) {
2920 lim_log(pMac, LOGE,
2921 FL(
2922 "PE Session does not exist for given sme sessionId %d"
2923 ),
2924 pAddStaReq->sessionId);
2925 goto lim_tdls_add_sta_error;
2926 }
2927
2928 /* check if we are in proper state to work as TDLS client */
2929 if (!LIM_IS_STA_ROLE(psessionEntry)) {
2930 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
2931 "send mgmt received in wrong system Role %d",
2932 GET_LIM_SYSTEM_ROLE(psessionEntry));
2933 goto lim_tdls_add_sta_error;
2934 }
2935
2936 /*
2937 * if we are still good, go ahead and check if we are in proper state to
2938 * do TDLS discovery req/rsp/....frames.
2939 */
2940 if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
2941 (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
2942
2943 lim_log(pMac, LOGE,
2944 FL("send mgmt received in invalid LIMsme state (%d)"),
2945 psessionEntry->limSmeState);
2946 goto lim_tdls_add_sta_error;
2947 }
2948
2949 pMac->lim.gLimAddStaTdls = true;
2950
2951 /* To start with, send add STA request to HAL */
2952 if (eSIR_FAILURE == lim_tdls_setup_add_sta(pMac, pAddStaReq, psessionEntry)) {
2953 lim_log(pMac, LOGE,
2954 FL("Add TDLS Station request failed"));
2955 goto lim_tdls_add_sta_error;
2956 }
2957 return eSIR_SUCCESS;
2958lim_tdls_add_sta_error:
2959 lim_send_sme_tdls_add_sta_rsp(pMac,
2960 pAddStaReq->sessionId, pAddStaReq->peerMac,
2961 (pAddStaReq->tdlsAddOper == TDLS_OPER_UPDATE),
2962 NULL, eSIR_FAILURE);
2963
2964 return eSIR_SUCCESS;
2965}
2966
2967/*
2968 * Process Del Sta Request from SME .
2969 */
2970tSirRetStatus lim_process_sme_tdls_del_sta_req(tpAniSirGlobal pMac,
2971 uint32_t *pMsgBuf)
2972{
2973 /* get all discovery request parameters */
2974 tSirTdlsDelStaReq *pDelStaReq = (tSirTdlsDelStaReq *) pMsgBuf;
2975 tpPESession psessionEntry;
2976 uint8_t sessionId;
2977 tpDphHashNode pStaDs = NULL;
2978
2979 lim_log(pMac, LOG1, FL("TDLS Delete STA Request Recieved"));
2980 psessionEntry =
2981 pe_find_session_by_bssid(pMac, pDelStaReq->bssid, &sessionId);
2982 if (psessionEntry == NULL) {
2983 lim_log(pMac, LOGE,
2984 FL(
2985 "PE Session does not exist for given sme sessionId %d"
2986 ),
2987 pDelStaReq->sessionId);
2988 lim_send_sme_tdls_del_sta_rsp(pMac, pDelStaReq->sessionId,
2989 pDelStaReq->peerMac, NULL,
2990 eSIR_FAILURE);
2991 return eSIR_FAILURE;
2992 }
2993
2994 /* check if we are in proper state to work as TDLS client */
2995 if (!LIM_IS_STA_ROLE(psessionEntry)) {
2996 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
2997 "Del sta received in wrong system Role %d",
2998 GET_LIM_SYSTEM_ROLE(psessionEntry));
2999 goto lim_tdls_del_sta_error;
3000 }
3001
3002 /*
3003 * if we are still good, go ahead and check if we are in proper state to
3004 * do TDLS discovery req/rsp/....frames.
3005 */
3006 if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
3007 (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
3008
3009 lim_log(pMac, LOGE,
3010 FL("Del Sta received in invalid LIMsme state (%d)"),
3011 psessionEntry->limSmeState);
3012 goto lim_tdls_del_sta_error;
3013 }
3014
3015 pStaDs = lim_tdls_del_sta(pMac, pDelStaReq->peerMac, psessionEntry);
3016
3017 /* now send indication to SME-->HDD->TL to remove STA from TL */
3018
3019 if (pStaDs) {
3020 lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId,
3021 pDelStaReq->peerMac, pStaDs,
3022 eSIR_SUCCESS);
3023 lim_release_peer_idx(pMac, pStaDs->assocId, psessionEntry);
3024
3025 /* Clear the aid in peerAIDBitmap as this aid is now in freepool */
3026 CLEAR_PEER_AID_BITMAP(psessionEntry->peerAIDBitmap,
3027 pStaDs->assocId);
3028 lim_delete_dph_hash_entry(pMac, pStaDs->staAddr, pStaDs->assocId,
3029 psessionEntry);
3030
3031 return eSIR_SUCCESS;
3032
3033 }
3034
3035lim_tdls_del_sta_error:
3036 lim_send_sme_tdls_del_sta_rsp(pMac, psessionEntry->smeSessionId,
3037 pDelStaReq->peerMac, NULL, eSIR_FAILURE);
3038
3039 return eSIR_SUCCESS;
3040}
3041
3042/* Intersects the two input arrays and outputs an array */
3043/* For now the array length of uint8_t suffices */
3044static void lim_tdls_get_intersection(uint8_t *input_array1,
3045 uint8_t input1_length,
3046 uint8_t *input_array2,
3047 uint8_t input2_length,
3048 uint8_t *output_array,
3049 uint8_t *output_length)
3050{
3051 uint8_t i, j, k = 0, flag = 0;
3052 for (i = 0; i < input1_length; i++) {
3053 flag = 0;
3054 for (j = 0; j < input2_length; j++) {
3055 if (input_array1[i] == input_array2[j]) {
3056 flag = 1;
3057 break;
3058 }
3059 }
3060 if (flag == 1) {
3061 output_array[k] = input_array1[i];
3062 k++;
3063 }
3064 }
3065 *output_length = k;
3066}
3067
3068/**
3069 * lim_process_sme_tdls_link_establish_req() - process tdls link establishment
3070 * request
3071 *
3072 * @mac_ctx - global MAC context
3073 * @msg_buf - message buffer from SME
3074 *
3075 * Process Link Establishment Request from SME
3076 *
3077 * Return: eSIR_SUCCESS on success, failure code otherwise.
3078 */
3079tSirRetStatus lim_process_sme_tdls_link_establish_req(tpAniSirGlobal mac_ctx,
3080 uint32_t *msg_buf)
3081{
3082 /* get all discovery request parameters */
3083 tSirTdlsLinkEstablishReq *tdls_req =
3084 (tSirTdlsLinkEstablishReq *) msg_buf;
3085 tpPESession session_entry;
3086 uint8_t session_id;
3087 tpTdlsLinkEstablishParams tdls_req_params;
3088 tSirMsgQ msg;
3089 uint16_t peer_idx = 0;
3090 tpDphHashNode stads = NULL;
3091 uint32_t self_num_chan = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3092 uint8_t self_supp_chan[WNI_CFG_VALID_CHANNEL_LIST_LEN];
3093
3094 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_INFO,
3095 FL("Send Mgmt Recieved"));
3096
3097 session_entry = pe_find_session_by_bssid(mac_ctx, tdls_req->bssid,
3098 &session_id);
3099 if (NULL == session_entry) {
3100 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
3101 FL("PE Session does not exist for sme session_id %d"),
3102 tdls_req->sessionId);
3103 lim_send_sme_tdls_link_establish_req_rsp(mac_ctx,
3104 tdls_req->sessionId, tdls_req->peerMac, NULL,
3105 eSIR_FAILURE);
3106 return eSIR_FAILURE;
3107 }
3108
3109 /* check if we are in proper state to work as TDLS client */
3110 if (!LIM_IS_STA_ROLE(session_entry)) {
3111 CDF_TRACE(CDF_MODULE_ID_PE, CDF_TRACE_LEVEL_ERROR,
3112 FL("TDLS Link Establish Request received in wrong system Role %d"),
3113 GET_LIM_SYSTEM_ROLE(session_entry));
3114 goto lim_tdls_link_establish_error;
3115 }
3116
3117 /*
3118 * if we are still good, go ahead and check if we are in proper state to
3119 * do TDLS discovery req/rsp/....frames.
3120 */
3121 if ((session_entry->limSmeState != eLIM_SME_ASSOCIATED_STATE) &&
3122 (session_entry->limSmeState != eLIM_SME_LINK_EST_STATE)) {
3123 lim_log(mac_ctx, LOGE,
3124 FL("TDLS Link Establish Request received in invalid LIMsme state (%d)"),
3125 session_entry->limSmeState);
3126 goto lim_tdls_link_establish_error;
3127 }
3128
3129 stads = dph_lookup_hash_entry(mac_ctx, tdls_req->peerMac, &peer_idx,
3130 &session_entry->dph.dphHashTable);
3131 if (NULL == stads) {
3132 lim_log(mac_ctx, LOGE, FL("stads is NULL"));
3133 goto lim_tdls_link_establish_error;
3134 }
3135 tdls_req_params = cdf_mem_malloc(sizeof(tTdlsLinkEstablishParams));
3136 if (NULL == tdls_req_params) {
3137 lim_log(mac_ctx, LOGE,
3138 FL("Unable to allocate memory TDLS Link Establish Request"));
3139 return eSIR_MEM_ALLOC_FAILED;
3140 }
3141
3142 cdf_mem_set((uint8_t *) tdls_req_params,
3143 sizeof(tTdlsLinkEstablishParams), 0);
3144
3145 tdls_req_params->staIdx = stads->staIndex;
3146 tdls_req_params->isResponder = tdls_req->isResponder;
3147 tdls_req_params->uapsdQueues = tdls_req->uapsdQueues;
3148 tdls_req_params->maxSp = tdls_req->maxSp;
3149 tdls_req_params->isBufsta = tdls_req->isBufSta;
3150 tdls_req_params->isOffChannelSupported =
3151 tdls_req->isOffChannelSupported;
3152
3153 if (0 == tdls_req->supportedChannelsLen)
3154 goto send_tdls_establish_request;
3155
3156 if (wlan_cfg_get_str(mac_ctx, WNI_CFG_VALID_CHANNEL_LIST,
3157 self_supp_chan,
3158 &self_num_chan) != eSIR_SUCCESS) {
3159 /**
3160 * Could not get Valid channel list from CFG.
3161 * Log error.
3162 */
3163 lim_log(mac_ctx, LOGE,
3164 FL("could not retrieve Valid channel list"));
3165 }
3166
3167 if (self_num_chan > WNI_CFG_VALID_CHANNEL_LIST_LEN) {
3168 lim_log(mac_ctx, LOGE,
3169 FL("Channel List more than Valid Channel list"));
3170 self_num_chan = WNI_CFG_VALID_CHANNEL_LIST_LEN;
3171 }
3172
3173 if (tdls_req->supportedChannelsLen > SIR_MAC_MAX_SUPP_CHANNELS) {
3174 lim_log(mac_ctx, LOGE,
3175 FL("Channel List is more than the supported Channel list"));
3176 tdls_req->supportedChannelsLen = SIR_MAC_MAX_SUPP_CHANNELS;
3177 }
3178
3179 lim_tdls_get_intersection(self_supp_chan, self_num_chan,
3180 tdls_req->supportedChannels, tdls_req->supportedChannelsLen,
3181 tdls_req_params->validChannels,
3182 &tdls_req_params->validChannelsLen);
3183
3184send_tdls_establish_request:
3185 cdf_mem_copy(tdls_req_params->validOperClasses,
3186 tdls_req->supportedOperClasses,
3187 tdls_req->supportedOperClassesLen);
3188 tdls_req_params->validOperClassesLen =
3189 tdls_req->supportedOperClassesLen;
3190
3191 msg.type = WMA_SET_TDLS_LINK_ESTABLISH_REQ;
3192 msg.reserved = 0;
3193 msg.bodyptr = tdls_req_params;
3194 msg.bodyval = 0;
3195 if (eSIR_SUCCESS != wma_post_ctrl_msg(mac_ctx, &msg)) {
3196 lim_log(mac_ctx, LOGE, FL("halPostMsgApi failed"));
3197 goto lim_tdls_link_establish_error;
3198 }
3199 return eSIR_SUCCESS;
3200
3201lim_tdls_link_establish_error:
3202 lim_send_sme_tdls_link_establish_req_rsp(mac_ctx,
3203 session_entry->smeSessionId, tdls_req->peerMac, NULL,
3204 eSIR_FAILURE);
3205
3206 return eSIR_SUCCESS;
3207}
3208
3209/**
3210 * lim_delete_tdls_peers() - delete tdls peers
3211 *
3212 * @mac_ctx - global MAC context
3213 * @session_entry - PE session entry
3214 *
3215 * Delete all the TDLS peer connected before leaving the BSS
3216 *
3217 * Return: eSIR_SUCCESS on success, error code otherwise
3218 */
3219tSirRetStatus lim_delete_tdls_peers(tpAniSirGlobal mac_ctx,
3220 tpPESession session_entry)
3221{
3222 tpDphHashNode stads = NULL;
3223 int i, aid;
3224 size_t aid_bitmap_size = sizeof(session_entry->peerAIDBitmap);
3225
3226 if (NULL == session_entry) {
3227 lim_log(mac_ctx, LOGE, FL("NULL session_entry"));
3228 return eSIR_FAILURE;
3229 }
3230
3231 /*
3232 * Check all the set bit in peerAIDBitmap and delete the peer
3233 * (with that aid) entry from the hash table and add the aid
3234 * in free pool
3235 */
3236 for (i = 0; i < aid_bitmap_size / sizeof(uint32_t); i++) {
3237 for (aid = 0; aid < (sizeof(uint32_t) << 3); aid++) {
3238 if (!CHECK_BIT(session_entry->peerAIDBitmap[i], aid))
3239 continue;
3240 stads = dph_get_hash_entry(mac_ctx,
3241 (aid + i * (sizeof(uint32_t) << 3)),
3242 &session_entry->dph.dphHashTable);
3243
3244 if (NULL != stads) {
3245 lim_log(mac_ctx, LOGE,
3246 FL("Deleting "MAC_ADDRESS_STR),
3247 MAC_ADDR_ARRAY(stads->staAddr));
3248
3249 lim_send_deauth_mgmt_frame(mac_ctx,
3250 eSIR_MAC_DEAUTH_LEAVING_BSS_REASON,
3251 stads->staAddr, session_entry, false);
3252 dph_delete_hash_entry(mac_ctx,
3253 stads->staAddr, stads->assocId,
3254 &session_entry->dph.dphHashTable);
3255 }
3256 lim_release_peer_idx(mac_ctx,
3257 (aid + i * (sizeof(uint32_t) << 3)),
3258 session_entry);
3259 CLEAR_BIT(session_entry->peerAIDBitmap[i], aid);
3260 }
3261 }
3262 lim_send_sme_tdls_delete_all_peer_ind(mac_ctx, session_entry);
3263
3264 return eSIR_SUCCESS;
3265}
3266
3267#endif