blob: 838fff348f022a0ce1748265968a4b1a11ae1bb4 [file] [log] [blame]
Kiran V1ccee932012-12-12 14:49:46 -08001/*
Gopichand Nakkala0c1331e2013-01-07 22:49:07 -08002 * Copyright (c) 2012-2013, 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 */
Kiran V1ccee932012-12-12 14:49:46 -080021
22/**========================================================================
23
24 \file wlan_hdd_tdls.c
25
Chilam NG571c65a2013-01-19 12:27:36 +053026 \brief WLAN Host Device Driver implementation for TDLS
Kiran V1ccee932012-12-12 14:49:46 -080027
Kiran V1ccee932012-12-12 14:49:46 -080028 ========================================================================*/
29
30#include <wlan_hdd_includes.h>
31#include <wlan_hdd_hostapd.h>
32#include <net/cfg80211.h>
33#include <linux/netdevice.h>
34#include <linux/skbuff.h>
Chilam NG571c65a2013-01-19 12:27:36 +053035#include <linux/list.h>
Kiran V1ccee932012-12-12 14:49:46 -080036#include <linux/etherdevice.h>
37#include <net/ieee80211_radiotap.h>
38#include "wlan_hdd_tdls.h"
Chilam NG571c65a2013-01-19 12:27:36 +053039#include "wlan_hdd_cfg80211.h"
Kiran V1ccee932012-12-12 14:49:46 -080040
Chilam NG571c65a2013-01-19 12:27:36 +053041
42typedef struct {
43 struct list_head node;
Kiran V1ccee932012-12-12 14:49:46 -080044 tSirMacAddr peerMac;
Chilam NG571c65a2013-01-19 12:27:36 +053045 tANI_U16 staId ;
46 tANI_S8 rssi;
47 tANI_S8 tdls_support;
48 tANI_S8 link_status;
49 tANI_U16 discovery_attempt;
50 tANI_U16 tx_pkt;
Chilam Ng1279e232013-01-25 15:06:52 -080051 tANI_U16 rx_pkt;
52 vos_timer_t peerIdleTimer;
Chilam NG571c65a2013-01-19 12:27:36 +053053} hddTdlsPeer_t;
Kiran V1ccee932012-12-12 14:49:46 -080054
Kiran V1ccee932012-12-12 14:49:46 -080055
Chilam NG571c65a2013-01-19 12:27:36 +053056typedef struct {
57 hddTdlsPeer_t* peer_list[256];
58 struct net_device *dev;
59 spinlock_t lock;
60 vos_timer_t peerDiscoverTimer;
61 vos_timer_t peerUpdateTimer;
Chilam NG571c65a2013-01-19 12:27:36 +053062 tdls_config_params_t threshold_config;
63 tANI_S8 ap_rssi;
64} tdlsCtx_t;
65
Chilam Nga75d8b62013-01-29 01:35:59 -080066static tdlsCtx_t *pHddTdlsCtx;
67static v_BOOL_t tdlsImplicitTrigger;
Chilam NG571c65a2013-01-19 12:27:36 +053068
Hoonki Leecdd8e962013-01-20 00:45:46 -080069void wlan_hdd_freeTdlsPeer(void);
Chilam NG571c65a2013-01-19 12:27:36 +053070
71static v_VOID_t wlan_hdd_discover_peer_cb( v_PVOID_t userData )
Hoonki Leef63df0d2013-01-16 19:29:14 -080072{
73 int i;
Chilam NG571c65a2013-01-19 12:27:36 +053074 hddTdlsPeer_t *curr_peer;
Hoonki Leebfee0342013-01-21 16:43:45 -080075 hdd_adapter_t *pAdapter;
76 hdd_context_t *pHddCtx;
77
78 if (NULL == pHddTdlsCtx) return;
79
80 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
81 pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Hoonki Leef63df0d2013-01-16 19:29:14 -080082
Chilam NG571c65a2013-01-19 12:27:36 +053083 for (i = 0; i < 256; i++) {
84 curr_peer = pHddTdlsCtx->peer_list[i];
85 if (NULL == curr_peer) continue;
86
87 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
88 "hdd discovery cb - %d: %x %x %x %x %x %x\n", i,
89 curr_peer->peerMac[0],
90 curr_peer->peerMac[1],
91 curr_peer->peerMac[2],
92 curr_peer->peerMac[3],
93 curr_peer->peerMac[4],
94 curr_peer->peerMac[5]);
95
96 do {
97 if ((eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) &&
98 (eTDLS_LINK_NOT_CONNECTED == curr_peer->link_status) &&
99 (curr_peer->discovery_attempt <
100 pHddTdlsCtx->threshold_config.discovery_tries_n)) {
101 wlan_hdd_cfg80211_send_tdls_discover_req(pHddCtx->wiphy,
102 pHddTdlsCtx->dev, curr_peer->peerMac);
103// cfg80211_tdls_oper_request(pHddTdlsCtx->dev, curr_peer->peerMac,
104// NL80211_TDLS_DISCOVERY_REQ, FALSE, GFP_KERNEL);
105
106// if (++curr_peer->discovery_attempt >= pHddTdlsCtx->threshold_config.discovery_tries_n) {
107// curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
108// }
109 }
110
111 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
112 } while (&curr_peer->node != curr_peer->node.next);
Hoonki Leef63df0d2013-01-16 19:29:14 -0800113 }
114
Chilam NG571c65a2013-01-19 12:27:36 +0530115 vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
116 pHddTdlsCtx->threshold_config.discovery_period_t );
117
118 wlan_hdd_get_rssi(pAdapter, &pHddTdlsCtx->ap_rssi);
119
120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
121 pHddTdlsCtx->ap_rssi);
Hoonki Leef63df0d2013-01-16 19:29:14 -0800122}
Chilam NG571c65a2013-01-19 12:27:36 +0530123
124static v_VOID_t wlan_hdd_update_peer_cb( v_PVOID_t userData )
125{
126 int i;
127 hddTdlsPeer_t *curr_peer;
128
Hoonki Leebfee0342013-01-21 16:43:45 -0800129 if (NULL == pHddTdlsCtx) return;
130
Chilam NG571c65a2013-01-19 12:27:36 +0530131 for (i = 0; i < 256; i++) {
132 curr_peer = pHddTdlsCtx->peer_list[i];
133 if (NULL == curr_peer) continue;
134
135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
136 "hdd update cb - %d: %x %x %x %x %x %x -> %d\n", i,
137 curr_peer->peerMac[0],
138 curr_peer->peerMac[1],
139 curr_peer->peerMac[2],
140 curr_peer->peerMac[3],
141 curr_peer->peerMac[4],
142 curr_peer->peerMac[5],
143 curr_peer->tx_pkt);
144
145 do {
146 if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
147 if (eTDLS_LINK_CONNECTED != curr_peer->link_status) {
148 if (curr_peer->tx_pkt >=
149 pHddTdlsCtx->threshold_config.tx_packet_n) {
150#ifdef CONFIG_TDLS_IMPLICIT
151 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
152 curr_peer->peerMac,
153 NL80211_TDLS_SETUP, FALSE,
154 GFP_KERNEL);
155#endif
Hoonki Leecdd8e962013-01-20 00:45:46 -0800156 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530157 }
158
Hoonki Leecdd8e962013-01-20 00:45:46 -0800159 if ((tANI_S32)curr_peer->rssi >
160 (tANI_S32)(pHddTdlsCtx->threshold_config.rssi_hysteresis +
Chilam NG571c65a2013-01-19 12:27:36 +0530161 pHddTdlsCtx->ap_rssi)) {
162
163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
164 "RSSI triggering");
165
166#ifdef CONFIG_TDLS_IMPLICIT
167 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
168 curr_peer->peerMac,
169 NL80211_TDLS_SETUP, FALSE,
170 GFP_KERNEL);
171#endif
172 }
173 } else {
Chilam Ng1279e232013-01-25 15:06:52 -0800174 if ((curr_peer->tx_pkt > 0 &&
175 curr_peer->tx_pkt <
176 pHddTdlsCtx->threshold_config.tx_packet_n) ||
177 (curr_peer->tx_pkt == 0 &&
178 curr_peer->rx_pkt == 0)) {
179 if (VOS_TIMER_STATE_RUNNING !=
180 vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) {
181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx/Rx Idle!");
182 vos_timer_start( &curr_peer->peerIdleTimer,
183 pHddTdlsCtx->threshold_config.rx_timeout_t );
184 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800185 goto next_peer;
Chilam NG571c65a2013-01-19 12:27:36 +0530186 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800187
188// if (curr_peer->rssi <
189// (pHddTdlsCtx->threshold_config.rssi_hysteresis +
190// pHddTdlsCtx->ap_rssi)) {
191//
192//#ifdef CONFIG_TDLS_IMPLICIT
193// cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
194// curr_peer->peerMac,
195// NL80211_TDLS_TEARDOWN, FALSE,
196// GFP_KERNEL);
197//#endif
198// }
Chilam NG571c65a2013-01-19 12:27:36 +0530199 }
200 }
201
Hoonki Leecdd8e962013-01-20 00:45:46 -0800202next_peer:
Chilam NG571c65a2013-01-19 12:27:36 +0530203 curr_peer->tx_pkt = 0;
Chilam Ng1279e232013-01-25 15:06:52 -0800204 curr_peer->rx_pkt = 0;
Chilam NG571c65a2013-01-19 12:27:36 +0530205
206 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
207 } while (&curr_peer->node != curr_peer->node.next);
208 }
209
210 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
211 pHddTdlsCtx->threshold_config.tx_period_t );
212}
213
Chilam Ng1279e232013-01-25 15:06:52 -0800214static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
215{
Lee Hoonkic1262f22013-01-24 21:59:00 -0800216#ifdef CONFIG_TDLS_IMPLICIT
Chilam Ng1279e232013-01-25 15:06:52 -0800217 hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
Lee Hoonkic1262f22013-01-24 21:59:00 -0800218#endif
Chilam Ng1279e232013-01-25 15:06:52 -0800219
220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx/Rx Idle - teardown!");
221
222#ifdef CONFIG_TDLS_IMPLICIT
223 cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
224 curr_peer->peerMac,
225 NL80211_TDLS_TEARDOWN, FALSE,
226 GFP_KERNEL);
227#endif
228}
229
Chilam NG571c65a2013-01-19 12:27:36 +0530230int wlan_hdd_tdls_init(struct net_device *dev)
231{
232 VOS_STATUS status;
Hoonki Leebf870f32013-01-19 15:53:30 +0530233 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
234 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Chilam NG571c65a2013-01-19 12:27:36 +0530235
Hoonki Leebf870f32013-01-19 15:53:30 +0530236 if(FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport)
237 {
238 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS not enabled!", __func__);
239 return -1;
240 }
241
242 pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
Chilam NG571c65a2013-01-19 12:27:36 +0530243 if (NULL == pHddTdlsCtx) {
244 hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
245 return -1;
246 }
247
248 vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
249
250 pHddTdlsCtx->dev = dev;
251
Chilam Nga75d8b62013-01-29 01:35:59 -0800252 tdlsImplicitTrigger = pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger;
253 if(FALSE == tdlsImplicitTrigger)
Hoonki Leebf870f32013-01-19 15:53:30 +0530254 {
255 hddLog(VOS_TRACE_LEVEL_ERROR, "%s TDLS Implicit trigger not enabled!", __func__);
256 return -1;
257 }
258 pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod;
259 pHddTdlsCtx->threshold_config.tx_packet_n = pHddCtx->cfg_ini->fTDLSTxPacketThreshold;
260 pHddTdlsCtx->threshold_config.discovery_period_t = pHddCtx->cfg_ini->fTDLSDiscoveryPeriod;
261 pHddTdlsCtx->threshold_config.discovery_tries_n = pHddCtx->cfg_ini->fTDLSMaxDiscoveryAttempt;
262 pHddTdlsCtx->threshold_config.rx_timeout_t = pHddCtx->cfg_ini->fTDLSRxIdleTimeout;
263 pHddTdlsCtx->threshold_config.rssi_hysteresis = pHddCtx->cfg_ini->fTDLSRssiHysteresis;
Chilam NG571c65a2013-01-19 12:27:36 +0530264
265 status = vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
266 VOS_TIMER_TYPE_SW,
267 wlan_hdd_discover_peer_cb,
268 pHddTdlsCtx);
269
270 status = vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
271 pHddTdlsCtx->threshold_config.discovery_period_t );
272
273 status = vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
274 VOS_TIMER_TYPE_SW,
275 wlan_hdd_update_peer_cb,
276 pHddTdlsCtx);
277
278 status = vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
279 pHddTdlsCtx->threshold_config.tx_period_t );
280
281 return 0;
282}
283
284void wlan_hdd_tdls_exit()
285{
Chilam Nga75d8b62013-01-29 01:35:59 -0800286 if (NULL == pHddTdlsCtx) {
Hoonki Leebfee0342013-01-21 16:43:45 -0800287 hddLog(VOS_TRACE_LEVEL_WARN, "%s TDLS not enabled, exiting!", __func__);
288 return;
289 }
290
Chilam Nga75d8b62013-01-29 01:35:59 -0800291 if(FALSE != tdlsImplicitTrigger) {
Hoonki Leebfee0342013-01-21 16:43:45 -0800292 vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
293 vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
294 vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
295 vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
296 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800297
298 wlan_hdd_freeTdlsPeer();
Chilam Nga75d8b62013-01-29 01:35:59 -0800299
300 vos_mem_free(pHddTdlsCtx);
301 pHddTdlsCtx = NULL;
Chilam NG571c65a2013-01-19 12:27:36 +0530302}
303
304int wlan_hdd_tdls_set_link_status(u8 *mac, int status)
305{
306 hddTdlsPeer_t *curr_peer;
307 int i;
308 u8 key = 0;
309
Hoonki Leebfee0342013-01-21 16:43:45 -0800310 if (NULL == pHddTdlsCtx) return -1;
311
Chilam NG571c65a2013-01-19 12:27:36 +0530312 for (i = 0; i < 6; i++)
313 key ^= mac[i];
314
315 curr_peer = pHddTdlsCtx->peer_list[key];
316
317 if (NULL == curr_peer) {
318 hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC!", __func__);
319 return -1;
320 }
321
322 do {
323 if (!memcmp(mac, curr_peer->peerMac, 6)) goto found_peer;
324 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
325 } while (&curr_peer->node != curr_peer->node.next);
326
327 hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC!", __func__);
328 return -1;
329
330found_peer:
331
332 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer %d link status to %d",
333 key, status);
334
335 curr_peer->link_status = status;
336
Chilam Nga75d8b62013-01-29 01:35:59 -0800337 if(FALSE != tdlsImplicitTrigger) {
338 if (eTDLS_LINK_CONNECTED == status) {
339 vos_timer_init(&curr_peer->peerIdleTimer,
340 VOS_TIMER_TYPE_SW,
341 wlan_hdd_tdls_idle_cb,
342 curr_peer);
343 }
Chilam Ng1279e232013-01-25 15:06:52 -0800344 }
345
Chilam NG571c65a2013-01-19 12:27:36 +0530346 return status;
347}
348
349int wlan_hdd_tdls_set_cap(u8 *mac, int cap)
350{
351 hddTdlsPeer_t *curr_peer;
352 int i;
353 u8 key = 0;
354
Hoonki Leebfee0342013-01-21 16:43:45 -0800355 if (NULL == pHddTdlsCtx) return -1;
356
Chilam NG571c65a2013-01-19 12:27:36 +0530357 for (i = 0; i < 6; i++)
358 key ^= mac[i];
359
360 curr_peer = pHddTdlsCtx->peer_list[key];
361
362 if (NULL == curr_peer) {
363 curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
364
365 if (NULL == curr_peer) {
366 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
367 return -1;
368 }
369 vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
370
371 INIT_LIST_HEAD(&curr_peer->node);
372 memcpy(curr_peer->peerMac, mac, 6);
373 curr_peer->tdls_support = cap;
374 pHddTdlsCtx->peer_list[key] = curr_peer;
375
376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
377 "new peer - key:%d, mac:%x %x %x %x %x %x, 0x%x",
378 key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
379 curr_peer );
380 return 0;
381 }
382
383 do {
384 if (!memcmp(mac, curr_peer->peerMac, 6)) goto found_peer;
385 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
386 } while (&curr_peer->node != curr_peer->node.next);
387
388 hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC %d: %x %x %x %x %x %x",
389 __func__, key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
390
391 return -1;
392
393found_peer:
394
395 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer %d support cap to %d",
396 key, cap);
397
398 curr_peer->tdls_support = cap;
399
400 return cap;
401}
402
403int wlan_hdd_tdls_set_rssi(u8 *mac, tANI_S8 rxRssi)
404{
405 hddTdlsPeer_t *curr_peer;
406 int i;
407 u8 key = 0;
408
Hoonki Leebfee0342013-01-21 16:43:45 -0800409 if (NULL == pHddTdlsCtx) return -1;
410
Chilam NG571c65a2013-01-19 12:27:36 +0530411 for (i = 0; i < 6; i++)
412 key ^= mac[i];
413
414 curr_peer = pHddTdlsCtx->peer_list[key];
415
416 if (NULL == curr_peer) {
417 curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
418
419 if (NULL == curr_peer) {
420 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
421 return -1;
422 }
423 vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
424
425 INIT_LIST_HEAD(&curr_peer->node);
426 memcpy(curr_peer->peerMac, mac, 6);
427 curr_peer->rssi = rxRssi;
428 pHddTdlsCtx->peer_list[key] = curr_peer;
429
430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
431 "new peer - key:%d, mac:%x %x %x %x %x %x, 0x%x",
432 key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
433 curr_peer );
434 return 0;
435 }
436
437 do {
438 if (!memcmp(mac, curr_peer->peerMac, 6)) goto found_peer;
439 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
440 } while (&curr_peer->node != curr_peer->node.next);
441
442 hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC %d: %x %x %x %x %x %x",
443 __func__, key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
444
445 return -1;
446
447found_peer:
448
449 hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer %d rssi to %d",
450 key, rxRssi);
451
452 curr_peer->rssi = rxRssi;
453
454 return rxRssi;
455}
456
457u8 wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
458{
459 int i;
460 u8 hash = 0;
461
462 memcpy(mac, skb->data, 6);
463 for (i = 0; i < 6; i++)
464 hash ^= mac[i];
465
466 return hash;
467}
468
Chilam Ng1279e232013-01-25 15:06:52 -0800469u8 wlan_hdd_tdls_extract_sa(struct sk_buff *skb, u8 *mac)
470{
471 int i;
472 u8 hash = 0;
473
474 memcpy(mac, skb->data+6, 6);
475 for (i = 0; i < 6; i++)
476 hash ^= mac[i];
477
478 return hash;
479}
480
481int wlan_hdd_tdls_add_peer_to_list(u8 key, u8 *mac, u8 tx)
Chilam NG571c65a2013-01-19 12:27:36 +0530482{
483 hddTdlsPeer_t *new_peer, *curr_peer;
484
Hoonki Leebfee0342013-01-21 16:43:45 -0800485 if (NULL == pHddTdlsCtx) return -1;
486
Chilam NG571c65a2013-01-19 12:27:36 +0530487 curr_peer = pHddTdlsCtx->peer_list[key];
488
489 if (NULL == curr_peer) {
490 curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
491
492 if (NULL == curr_peer) {
493 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
494 return -1;
495 }
496 vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
497 curr_peer->rssi = -120;
498
499 INIT_LIST_HEAD(&curr_peer->node);
500 memcpy(curr_peer->peerMac, mac, 6);
501
502 pHddTdlsCtx->peer_list[key] = curr_peer;
503
504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
505 "new peer - key:%d, mac:%x %x %x %x %x %x, 0x%x",
506 key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
507 curr_peer );
508 return 0;
509 }
510
511 do {
512 if (!memcmp(mac, curr_peer->peerMac, 6)) goto known_peer;
513 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
514 } while (&curr_peer->node != curr_peer->node.next);
515
516 new_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
517 if (NULL == new_peer) {
518 hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
519 return -1;
520 }
521 vos_mem_zero(new_peer, sizeof(hddTdlsPeer_t));
522 curr_peer->rssi = -120;
523 memcpy(new_peer->peerMac, mac, 6);
524
525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
526 "add peer - key:%d, mac:%x %x %x %x %x %x",
527 key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
528
529 list_add(&new_peer->node, &curr_peer->node);
530 curr_peer = new_peer;
531
532known_peer:
Chilam Ng1279e232013-01-25 15:06:52 -0800533 if (tx)
534 curr_peer->tx_pkt++;
535 else
536 curr_peer->rx_pkt++;
Chilam NG571c65a2013-01-19 12:27:36 +0530537
538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
539 "known peer - key:%d, mac:%x %x %x %x %x %x, tx:%d",
540 key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
541 curr_peer->tx_pkt );
542
543 return 0;
544}
545
546int wlan_hdd_tdls_set_params(tdls_config_params_t *config)
547{
Chilam Nga75d8b62013-01-29 01:35:59 -0800548 if (NULL == pHddTdlsCtx ||
549 FALSE == tdlsImplicitTrigger) return -1;
Hoonki Leebfee0342013-01-21 16:43:45 -0800550
Chilam NG571c65a2013-01-19 12:27:36 +0530551 vos_timer_stop( &pHddTdlsCtx->peerDiscoverTimer);
552
553 vos_timer_stop( &pHddTdlsCtx->peerUpdateTimer);
554
555 memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
556
557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
558 "iw set tdls params: %d %d %d %d %d %d",
559 pHddTdlsCtx->threshold_config.tx_period_t,
560 pHddTdlsCtx->threshold_config.tx_packet_n,
561 pHddTdlsCtx->threshold_config.discovery_period_t,
562 pHddTdlsCtx->threshold_config.discovery_tries_n,
563 pHddTdlsCtx->threshold_config.rx_timeout_t,
564 pHddTdlsCtx->threshold_config.rssi_hysteresis);
565
566 vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
567 pHddTdlsCtx->threshold_config.discovery_period_t );
568
569 vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
570 pHddTdlsCtx->threshold_config.tx_period_t );
571 return 0;
572}
573
Kiran V1ccee932012-12-12 14:49:46 -0800574int wlan_hdd_saveTdlsPeer(tCsrRoamInfo *pRoamInfo)
575{
Chilam NG571c65a2013-01-19 12:27:36 +0530576 hddTdlsPeer_t *new_peer, *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -0800577 int i;
Chilam NG571c65a2013-01-19 12:27:36 +0530578 u8 key = 0;
Kiran V1ccee932012-12-12 14:49:46 -0800579
Hoonki Leebfee0342013-01-21 16:43:45 -0800580 if (NULL == pHddTdlsCtx) return -1;
581
Chilam NG571c65a2013-01-19 12:27:36 +0530582 for (i = 0; i < 6; i++)
583 key ^= pRoamInfo->peerMac[i];
Kiran V1ccee932012-12-12 14:49:46 -0800584
Chilam NG571c65a2013-01-19 12:27:36 +0530585 curr_peer = pHddTdlsCtx->peer_list[key];
Kiran V1ccee932012-12-12 14:49:46 -0800586
Chilam NG571c65a2013-01-19 12:27:36 +0530587 if (NULL == curr_peer) {
588 curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
589
590 if (NULL == curr_peer) {
591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
592 "saveTdlsPeer: NOT saving staId %d", pRoamInfo->staId);
593 return -1;
594 }
595 vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
596
597 INIT_LIST_HEAD(&curr_peer->node);
598 memcpy(curr_peer->peerMac, pRoamInfo->peerMac, 6);
599 curr_peer->staId = pRoamInfo->staId;
600 pHddTdlsCtx->peer_list[key] = curr_peer;
601
602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Kiran V1ccee932012-12-12 14:49:46 -0800603 "saveTdlsPeer: saved staId %d", pRoamInfo->staId);
Chilam NG571c65a2013-01-19 12:27:36 +0530604 return 0;
Kiran V1ccee932012-12-12 14:49:46 -0800605 }
606
Chilam NG571c65a2013-01-19 12:27:36 +0530607 do {
608 if (!memcmp(pRoamInfo->peerMac, curr_peer->peerMac, 6)) goto known_peer;
609 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
610 } while (&curr_peer->node != curr_peer->node.next);
611
612 new_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
613 if (NULL == new_peer) {
614 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
615 "saveTdlsPeer: NOT saving staId %d", pRoamInfo->staId);
616 return -1;
617 }
618 vos_mem_zero(new_peer, sizeof(hddTdlsPeer_t));
619
620 list_add(&new_peer->node, &curr_peer->node);
621 curr_peer = new_peer;
622
623known_peer:
624 memcpy(curr_peer->peerMac, pRoamInfo->peerMac, 6);
625 curr_peer->staId = pRoamInfo->staId;
626
627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
628 "saveTdlsPeer: saved staId %d", pRoamInfo->staId);
629
630 return 0;
Kiran V1ccee932012-12-12 14:49:46 -0800631}
632
633int wlan_hdd_findTdlsPeer(tSirMacAddr peerMac)
634{
635 int i;
Chilam NG571c65a2013-01-19 12:27:36 +0530636 hddTdlsPeer_t *curr_peer;
Kiran V1ccee932012-12-12 14:49:46 -0800637
Hoonki Leebfee0342013-01-21 16:43:45 -0800638 if (NULL == pHddTdlsCtx) return -1;
639
Chilam NG571c65a2013-01-19 12:27:36 +0530640 for (i = 0; i < 256; i++) {
641 curr_peer = pHddTdlsCtx->peer_list[i];
642 if (NULL == curr_peer) continue;
643
644 do {
645 if (!memcmp(peerMac, curr_peer->peerMac, 6)) {
646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
647 "findTdlsPeer: found staId %d", curr_peer->staId);
648 return curr_peer->staId;
649 }
650
651 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
652 } while (&curr_peer->node != curr_peer->node.next);
Kiran V1ccee932012-12-12 14:49:46 -0800653 }
654
Chilam NG571c65a2013-01-19 12:27:36 +0530655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
656 "findTdlsPeer: staId NOT found");
Kiran V1ccee932012-12-12 14:49:46 -0800657
Kiran V1ccee932012-12-12 14:49:46 -0800658 return -1;
659}
Chilam NG571c65a2013-01-19 12:27:36 +0530660
661void wlan_hdd_removeTdlsPeer(tCsrRoamInfo *pRoamInfo)
662{
663 int i;
664 hddTdlsPeer_t *curr_peer;
665
Hoonki Leebfee0342013-01-21 16:43:45 -0800666 if (NULL == pHddTdlsCtx) return;
667
Chilam NG571c65a2013-01-19 12:27:36 +0530668 for (i = 0; i < 256; i++) {
669
670 curr_peer = pHddTdlsCtx->peer_list[i];
671
672 if (NULL == curr_peer) continue;
673
674 do {
675 if (curr_peer->staId == pRoamInfo->staId) goto found_peer;
676
677 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
678 } while (&curr_peer->node != curr_peer->node.next);
679 }
680
681 if (i == 256) return;
682
683found_peer:
Hoonki Leecdd8e962013-01-20 00:45:46 -0800684 curr_peer->link_status = eTDLS_LINK_NOT_CONNECTED;
685 curr_peer->staId = 0;
686 curr_peer->rssi = -120;
Chilam Nga75d8b62013-01-29 01:35:59 -0800687 if(FALSE != tdlsImplicitTrigger) {
688 vos_timer_stop( &curr_peer->peerIdleTimer );
689 vos_timer_destroy( &curr_peer->peerIdleTimer );
690 }
Hoonki Leecdd8e962013-01-20 00:45:46 -0800691}
692
693void wlan_hdd_freeTdlsPeer(void)
694{
695 int i;
696 hddTdlsPeer_t *curr_peer;
697 hddTdlsPeer_t *temp_peer;
698
Hoonki Leebfee0342013-01-21 16:43:45 -0800699 if (NULL == pHddTdlsCtx) return;
700
Hoonki Leecdd8e962013-01-20 00:45:46 -0800701 for (i = 0; i < 256; i++) {
702
703 curr_peer = pHddTdlsCtx->peer_list[i];
704
705 if (NULL != curr_peer) {
Hoonki Leebfee0342013-01-21 16:43:45 -0800706 while (&curr_peer->node != curr_peer->node.next) {
Hoonki Leecdd8e962013-01-20 00:45:46 -0800707 temp_peer = curr_peer;
708 curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
709 vos_mem_free(temp_peer);
Hoonki Leebfee0342013-01-21 16:43:45 -0800710 }
711 vos_mem_free(curr_peer);
Hoonki Leecdd8e962013-01-20 00:45:46 -0800712 }
713 }
Chilam NG571c65a2013-01-19 12:27:36 +0530714}
Lee Hoonkic1262f22013-01-24 21:59:00 -0800715
716/* TODO: Currently I am using conn_info.staId
717 here as per current design but tdls.c shouldn't
718 have touch this.*/
719u8 wlan_hdd_tdlsConnectedPeers(void)
720{
721 hdd_adapter_t *pAdapter;
722 hdd_station_ctx_t *pHddStaCtx;
723 u8 staIdx;
724 u8 count = 0;
725
726 if (NULL == pHddTdlsCtx) return -1;
727
728 pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
729 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
730
731 for ( staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
732 {
733 if (0 != pHddStaCtx->conn_info.staId[staIdx] )
734 count++;
735 }
736 return count;
737}