TDLS Changes for implicit trigger.
668299: Implicit triggering of TDLS (IEEE802.11z)
CRs-Fixed: 437836
Change-Id: I47c44b2650d19ad78600e2fa1c32233cac9ef3d9
diff --git a/CORE/HDD/inc/wlan_hdd_cfg80211.h b/CORE/HDD/inc/wlan_hdd_cfg80211.h
index 13bde22..c0cefb6 100644
--- a/CORE/HDD/inc/wlan_hdd_cfg80211.h
+++ b/CORE/HDD/inc/wlan_hdd_cfg80211.h
@@ -139,6 +139,10 @@
int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg);
extern v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx,
eConnectionState connState );
+#ifdef FEATURE_WLAN_TDLS
+int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
+ struct net_device *dev, u8 *peer);
+#endif
#endif // CONFIG_CFG80211
diff --git a/CORE/HDD/inc/wlan_hdd_p2p.h b/CORE/HDD/inc/wlan_hdd_p2p.h
index 8145de4..b8ad5d5 100644
--- a/CORE/HDD/inc/wlan_hdd_p2p.h
+++ b/CORE/HDD/inc/wlan_hdd_p2p.h
@@ -137,7 +137,7 @@
void hdd_indicateMgmtFrame( hdd_adapter_t *pAdapter,
tANI_U32 nFrameLength, tANI_U8* pbFrames,
tANI_U8 frameType,
- tANI_U32 rxChan);
+ tANI_U32 rxChan, tANI_S8 rxRssi);
void hdd_remainChanReadyHandler( hdd_adapter_t *pAdapter );
void hdd_sendActionCnf( hdd_adapter_t *pAdapter, tANI_BOOLEAN actionSendSuccess );
diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h
index a8a8256..48ac525 100644
--- a/CORE/HDD/inc/wlan_hdd_tdls.h
+++ b/CORE/HDD/inc/wlan_hdd_tdls.h
@@ -18,27 +18,6 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
- *
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
#ifndef __HDD_TDSL_H
#define __HDD_TDSL_H
/**===========================================================================
@@ -47,14 +26,81 @@
\brief Linux HDD TDLS include file
-
==========================================================================*/
-#define MAX_NUM_TDLS_PEER 4
+#define MAX_NUM_TDLS_PEER 3
-extern int wlan_hdd_saveTdlsPeer(tCsrRoamInfo *pRoamInfo);
+#define TDLS_MAX_DISCOVER_ATTEMPT 2
-extern int wlan_hdd_findTdlsPeer(tSirMacAddr peerMac);
+#define TDLS_DISCOVERY_PERIOD 3600000
-extern void wlan_hdd_removeTdlsPeer(tCsrRoamInfo *pRoamInfo);
+#define TDLS_TX_STATS_PERIOD 3600000
+
+#define TDLS_IMPLICIT_TRIGGER_PKT_THRESHOLD 100
+
+#define TDLS_RX_IDLE_TIMEOUT 5000
+
+#define TDLS_RSSI_TRIGGER_HYSTERESIS 50
+
+typedef struct
+{
+ tANI_U32 tx_period_t;
+ tANI_U32 tx_packet_n;
+ tANI_U32 discovery_period_t;
+ tANI_U32 discovery_tries_n;
+ tANI_U32 rx_timeout_t;
+ tANI_U32 rssi_hysteresis;
+} tdls_config_params_t;
+
+typedef enum {
+ eTDLS_CAP_NOT_SUPPORTED = -1,
+ eTDLS_CAP_UNKNOWN = 0,
+ eTDLS_CAP_SUPPORTED = 1,
+} eTDLSCapType;
+
+typedef enum {
+ eTDLS_LINK_NOT_CONNECTED = 0,
+ eTDLS_LINK_CONNECTED = 1,
+} eTDLSLinkStatus;
+
+typedef struct {
+ tANI_U16 period;
+ tANI_U16 bytes;
+} tdls_tx_tput_config_t;
+
+typedef struct {
+ tANI_U16 period;
+ tANI_U16 tries;
+} tdls_discovery_config_t;
+
+typedef struct {
+ tANI_U16 timeout;
+} tdls_rx_idle_config_t;
+
+typedef struct {
+ tANI_U16 rssi_thres;
+} tdls_rssi_config_t;
+
+
+int wlan_hdd_tdls_init(struct net_device *dev);
+
+void wlan_hdd_tdls_exit(void);
+
+u8 wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac);
+
+int wlan_hdd_tdls_add_peer_to_list(u8 key, u8 *mac);
+
+int wlan_hdd_saveTdlsPeer(tCsrRoamInfo *pRoamInfo);
+
+int wlan_hdd_findTdlsPeer(tSirMacAddr peerMac);
+
+int wlan_hdd_tdls_set_link_status(u8 *mac, int status);
+
+int wlan_hdd_tdls_set_cap(u8 *mac, int cap);
+
+int wlan_hdd_tdls_set_rssi(u8 *mac, tANI_S8 rxRssi);
+
+int wlan_hdd_tdls_set_params(tdls_config_params_t *config);
+
+void wlan_hdd_removeTdlsPeer(tCsrRoamInfo *pRoamInfo);
#endif // __HDD_TDSL_H
diff --git a/CORE/HDD/inc/wlan_hdd_wext.h b/CORE/HDD/inc/wlan_hdd_wext.h
index 84954f2..7d02626 100644
--- a/CORE/HDD/inc/wlan_hdd_wext.h
+++ b/CORE/HDD/inc/wlan_hdd_wext.h
@@ -411,6 +411,13 @@
VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter);
VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value);
+#if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR)
+VOS_STATUS wlan_hdd_get_roam_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value);
+#endif
+
+#ifdef FEATURE_WLAN_TDLS
+VOS_STATUS iw_set_tdls_params(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra, int nOffset);
+#endif
#endif // __WEXT_IW_H__
diff --git a/CORE/HDD/src/wlan_hdd_assoc.c b/CORE/HDD/src/wlan_hdd_assoc.c
index b074a13..00779e3 100644
--- a/CORE/HDD/src/wlan_hdd_assoc.c
+++ b/CORE/HDD/src/wlan_hdd_assoc.c
@@ -2192,7 +2192,8 @@
pRoamInfo->nFrameLength,
pRoamInfo->pbFrames,
pRoamInfo->frameType,
- pRoamInfo->rxChan );
+ pRoamInfo->rxChan,
+ pRoamInfo->rxRssi );
break;
case eCSR_ROAM_REMAIN_CHAN_READY:
hdd_remainChanReadyHandler( pAdapter );
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index e8b1efa..bc572f1 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -6582,6 +6582,8 @@
return -EINVAL;
}
+ wlan_hdd_tdls_set_link_status(peer, eTDLS_LINK_CONNECTED);
+
} else {
hddLog(VOS_TRACE_LEVEL_WARN, "wlan_hdd_cfg80211_add_key: peer NULL" );
}
@@ -6601,6 +6603,16 @@
}
return 0;
}
+
+int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy,
+ struct net_device *dev, u8 *peer)
+{
+ hddLog(VOS_TRACE_LEVEL_INFO, "tdls send discover req: %x %x %x %x %x %x",
+ peer[0], peer[1], peer[2], peer[3], peer[4], peer[5]);
+
+ return wlan_hdd_cfg80211_tdls_mgmt(wiphy, dev, peer,
+ WLAN_TDLS_DISCOVERY_REQUEST, 1, 0, NULL, 0);
+}
#endif
/* cfg80211_ops */
diff --git a/CORE/HDD/src/wlan_hdd_hostapd.c b/CORE/HDD/src/wlan_hdd_hostapd.c
index f227194..0e442a4 100644
--- a/CORE/HDD/src/wlan_hdd_hostapd.c
+++ b/CORE/HDD/src/wlan_hdd_hostapd.c
@@ -777,7 +777,7 @@
pSapEvent->sapevt.sapManagementFrameInfo.nFrameLength,
pSapEvent->sapevt.sapManagementFrameInfo.pbFrames,
pSapEvent->sapevt.sapManagementFrameInfo.frameType,
- pSapEvent->sapevt.sapManagementFrameInfo.rxChan);
+ pSapEvent->sapevt.sapManagementFrameInfo.rxChan, 0);
return VOS_STATUS_SUCCESS;
case eSAP_REMAIN_CHAN_READY:
hdd_remainChanReadyHandler( pHostapdAdapter );
diff --git a/CORE/HDD/src/wlan_hdd_main.c b/CORE/HDD/src/wlan_hdd_main.c
index e573c0a..cc16804 100644
--- a/CORE/HDD/src/wlan_hdd_main.c
+++ b/CORE/HDD/src/wlan_hdd_main.c
@@ -140,6 +140,9 @@
#endif /* FEATURE_WLAN_INTEGRATED_SOC */
#include "qwlan_version.h"
#include "wlan_qct_wda.h"
+#ifdef FEATURE_WLAN_TDLS
+#include "wlan_hdd_tdls.h"
+#endif
#ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
@@ -2789,6 +2792,10 @@
}
#endif //FEATURE_WLAN_INTEGRATED_SOC
+#ifdef FEATURE_WLAN_TDLS
+ wlan_hdd_tdls_exit();
+#endif
+
// Cancel any outstanding scan requests. We are about to close all
// of our adapters, but an adapter structure is what SME passes back
// to our callback function. Hence if there are any outstanding scan
@@ -3936,6 +3943,10 @@
// Initialize the restart logic
wlan_hdd_restart_init(pHddCtx);
+
+#ifdef FEATURE_WLAN_TDLS
+ wlan_hdd_tdls_init(pAdapter->dev);
+#endif
goto success;
diff --git a/CORE/HDD/src/wlan_hdd_p2p.c b/CORE/HDD/src/wlan_hdd_p2p.c
index c9d6746..a0a8bb8 100644
--- a/CORE/HDD/src/wlan_hdd_p2p.c
+++ b/CORE/HDD/src/wlan_hdd_p2p.c
@@ -1312,7 +1312,8 @@
tANI_U32 nFrameLength,
tANI_U8* pbFrames,
tANI_U8 frameType,
- tANI_U32 rxChan )
+ tANI_U32 rxChan,
+ tANI_S8 rxRssi )
{
tANI_U16 freq;
tANI_U8 type = 0;
@@ -1466,6 +1467,8 @@
#ifdef WLAN_FEATURE_TDLS_DEBUG
else if(pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+1] == WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP)
{
+ wlan_hdd_tdls_set_cap(&pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+6], 1);
+ wlan_hdd_tdls_set_rssi(&pbFrames[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET+6], rxRssi);
hddLog(VOS_TRACE_LEVEL_ERROR,"[TDLS] TDLS Discovery Response <--- OTA");
}
#endif
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 51ffaa2..3cea10b 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -18,33 +18,12 @@
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
- *
- * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
- *
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
-
/**========================================================================
\file wlan_hdd_tdls.c
- \brief WLAN Host Device Driver implementation for P2P commands interface
+ \brief WLAN Host Device Driver implementation for TDLS
========================================================================*/
@@ -53,75 +32,546 @@
#include <net/cfg80211.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
+#include <linux/list.h>
#include <linux/etherdevice.h>
#include <net/ieee80211_radiotap.h>
#include "wlan_hdd_tdls.h"
+#include "wlan_hdd_cfg80211.h"
-typedef struct hddTdlsPeerInfo {
+
+typedef struct {
+ struct list_head node;
tSirMacAddr peerMac;
- tANI_U16 staId ;
-} hddTdlsPInfo;
+ tANI_U16 staId ;
+ tANI_S8 rssi;
+ tANI_S8 tdls_support;
+ tANI_S8 link_status;
+ tANI_U16 discovery_attempt;
+ tANI_U16 tx_pkt;
+} hddTdlsPeer_t;
-static struct {
- hddTdlsPInfo peer;
-} hddTdlsPTable[MAX_NUM_TDLS_PEER];
-void wlan_hdd_removeTdlsPeer(tCsrRoamInfo *pRoamInfo)
+typedef struct {
+ hddTdlsPeer_t* peer_list[256];
+ struct net_device *dev;
+ spinlock_t lock;
+ vos_timer_t peerDiscoverTimer;
+ vos_timer_t peerUpdateTimer;
+ vos_timer_t peerIdleTimer;
+ tdls_config_params_t threshold_config;
+ tANI_S8 ap_rssi;
+} tdlsCtx_t;
+
+tdlsCtx_t *pHddTdlsCtx;
+
+
+static v_VOID_t wlan_hdd_discover_peer_cb( v_PVOID_t userData )
{
int i;
+ hddTdlsPeer_t *curr_peer;
+ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
+ hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
- for (i = 0; i < MAX_NUM_TDLS_PEER; i++)
- {
- if (pRoamInfo->staId == hddTdlsPTable[i].peer.staId)
- {
- vos_mem_zero( hddTdlsPTable[i].peer.peerMac, 6 );
- hddTdlsPTable[i].peer.staId = 0;
- VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
- "removeTdlsPeer: removed staId %d", pRoamInfo->staId);
- break;
- }
+ for (i = 0; i < 256; i++) {
+ curr_peer = pHddTdlsCtx->peer_list[i];
+ if (NULL == curr_peer) continue;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "hdd discovery cb - %d: %x %x %x %x %x %x\n", i,
+ curr_peer->peerMac[0],
+ curr_peer->peerMac[1],
+ curr_peer->peerMac[2],
+ curr_peer->peerMac[3],
+ curr_peer->peerMac[4],
+ curr_peer->peerMac[5]);
+
+ do {
+ if ((eTDLS_CAP_UNKNOWN == curr_peer->tdls_support) &&
+ (eTDLS_LINK_NOT_CONNECTED == curr_peer->link_status) &&
+ (curr_peer->discovery_attempt <
+ pHddTdlsCtx->threshold_config.discovery_tries_n)) {
+ wlan_hdd_cfg80211_send_tdls_discover_req(pHddCtx->wiphy,
+ pHddTdlsCtx->dev, curr_peer->peerMac);
+// cfg80211_tdls_oper_request(pHddTdlsCtx->dev, curr_peer->peerMac,
+// NL80211_TDLS_DISCOVERY_REQ, FALSE, GFP_KERNEL);
+
+// if (++curr_peer->discovery_attempt >= pHddTdlsCtx->threshold_config.discovery_tries_n) {
+// curr_peer->tdls_support = eTDLS_CAP_NOT_SUPPORTED;
+// }
+ }
+
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
}
- return;
+ vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
+ pHddTdlsCtx->threshold_config.discovery_period_t );
+
+ wlan_hdd_get_rssi(pAdapter, &pHddTdlsCtx->ap_rssi);
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "beacon rssi: %d",
+ pHddTdlsCtx->ap_rssi);
}
+
+static v_VOID_t wlan_hdd_update_peer_cb( v_PVOID_t userData )
+{
+ int i;
+ hddTdlsPeer_t *curr_peer;
+
+ for (i = 0; i < 256; i++) {
+ curr_peer = pHddTdlsCtx->peer_list[i];
+ if (NULL == curr_peer) continue;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "hdd update cb - %d: %x %x %x %x %x %x -> %d\n", i,
+ curr_peer->peerMac[0],
+ curr_peer->peerMac[1],
+ curr_peer->peerMac[2],
+ curr_peer->peerMac[3],
+ curr_peer->peerMac[4],
+ curr_peer->peerMac[5],
+ curr_peer->tx_pkt);
+
+ do {
+ if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) {
+ if (eTDLS_LINK_CONNECTED != curr_peer->link_status) {
+ if (curr_peer->tx_pkt >=
+ pHddTdlsCtx->threshold_config.tx_packet_n) {
+#ifdef CONFIG_TDLS_IMPLICIT
+ cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
+ curr_peer->peerMac,
+ NL80211_TDLS_SETUP, FALSE,
+ GFP_KERNEL);
+#endif
+ }
+
+ if (curr_peer->rssi >
+ (pHddTdlsCtx->threshold_config.rssi_hysteresis +
+ pHddTdlsCtx->ap_rssi)) {
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "RSSI triggering");
+
+#ifdef CONFIG_TDLS_IMPLICIT
+ cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
+ curr_peer->peerMac,
+ NL80211_TDLS_SETUP, FALSE,
+ GFP_KERNEL);
+#endif
+ }
+ } else {
+ if (curr_peer->rssi <
+ (pHddTdlsCtx->threshold_config.rssi_hysteresis +
+ pHddTdlsCtx->ap_rssi)) {
+
+#ifdef CONFIG_TDLS_IMPLICIT
+ cfg80211_tdls_oper_request(pHddTdlsCtx->dev,
+ curr_peer->peerMac,
+ NL80211_TDLS_TEARDOWN, FALSE,
+ GFP_KERNEL);
+#endif
+ }
+ }
+ }
+
+ curr_peer->tx_pkt = 0;
+
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
+ }
+
+ vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
+ pHddTdlsCtx->threshold_config.tx_period_t );
+}
+
+int wlan_hdd_tdls_init(struct net_device *dev)
+{
+ VOS_STATUS status;
+ pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t));
+
+ if (NULL == pHddTdlsCtx) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__);
+ return -1;
+ }
+
+ vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t));
+
+ pHddTdlsCtx->dev = dev;
+
+ pHddTdlsCtx->threshold_config.tx_period_t = TDLS_TX_STATS_PERIOD;
+ pHddTdlsCtx->threshold_config.tx_packet_n = TDLS_IMPLICIT_TRIGGER_PKT_THRESHOLD;
+ pHddTdlsCtx->threshold_config.discovery_period_t = TDLS_DISCOVERY_PERIOD;
+ pHddTdlsCtx->threshold_config.discovery_tries_n = TDLS_MAX_DISCOVER_ATTEMPT;
+ pHddTdlsCtx->threshold_config.rx_timeout_t = TDLS_RX_IDLE_TIMEOUT;
+ pHddTdlsCtx->threshold_config.rssi_hysteresis = TDLS_RSSI_TRIGGER_HYSTERESIS;
+
+ status = vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer,
+ VOS_TIMER_TYPE_SW,
+ wlan_hdd_discover_peer_cb,
+ pHddTdlsCtx);
+
+ status = vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
+ pHddTdlsCtx->threshold_config.discovery_period_t );
+
+ status = vos_timer_init(&pHddTdlsCtx->peerUpdateTimer,
+ VOS_TIMER_TYPE_SW,
+ wlan_hdd_update_peer_cb,
+ pHddTdlsCtx);
+
+ status = vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
+ pHddTdlsCtx->threshold_config.tx_period_t );
+
+ return 0;
+}
+
+void wlan_hdd_tdls_exit()
+{
+ vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer);
+ vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer);
+ vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer);
+ vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer);
+}
+
+int wlan_hdd_tdls_set_link_status(u8 *mac, int status)
+{
+ hddTdlsPeer_t *curr_peer;
+ int i;
+ u8 key = 0;
+
+ for (i = 0; i < 6; i++)
+ key ^= mac[i];
+
+ curr_peer = pHddTdlsCtx->peer_list[key];
+
+ if (NULL == curr_peer) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC!", __func__);
+ return -1;
+ }
+
+ do {
+ if (!memcmp(mac, curr_peer->peerMac, 6)) goto found_peer;
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC!", __func__);
+ return -1;
+
+found_peer:
+
+ hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer %d link status to %d",
+ key, status);
+
+ curr_peer->link_status = status;
+
+ return status;
+}
+
+int wlan_hdd_tdls_set_cap(u8 *mac, int cap)
+{
+ hddTdlsPeer_t *curr_peer;
+ int i;
+ u8 key = 0;
+
+ for (i = 0; i < 6; i++)
+ key ^= mac[i];
+
+ curr_peer = pHddTdlsCtx->peer_list[key];
+
+ if (NULL == curr_peer) {
+ curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
+
+ if (NULL == curr_peer) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
+ return -1;
+ }
+ vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
+
+ INIT_LIST_HEAD(&curr_peer->node);
+ memcpy(curr_peer->peerMac, mac, 6);
+ curr_peer->tdls_support = cap;
+ pHddTdlsCtx->peer_list[key] = curr_peer;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "new peer - key:%d, mac:%x %x %x %x %x %x, 0x%x",
+ key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ curr_peer );
+ return 0;
+ }
+
+ do {
+ if (!memcmp(mac, curr_peer->peerMac, 6)) goto found_peer;
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC %d: %x %x %x %x %x %x",
+ __func__, key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ return -1;
+
+found_peer:
+
+ hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer %d support cap to %d",
+ key, cap);
+
+ curr_peer->tdls_support = cap;
+
+ return cap;
+}
+
+int wlan_hdd_tdls_set_rssi(u8 *mac, tANI_S8 rxRssi)
+{
+ hddTdlsPeer_t *curr_peer;
+ int i;
+ u8 key = 0;
+
+ for (i = 0; i < 6; i++)
+ key ^= mac[i];
+
+ curr_peer = pHddTdlsCtx->peer_list[key];
+
+ if (NULL == curr_peer) {
+ curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
+
+ if (NULL == curr_peer) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
+ return -1;
+ }
+ vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
+
+ INIT_LIST_HEAD(&curr_peer->node);
+ memcpy(curr_peer->peerMac, mac, 6);
+ curr_peer->rssi = rxRssi;
+ pHddTdlsCtx->peer_list[key] = curr_peer;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "new peer - key:%d, mac:%x %x %x %x %x %x, 0x%x",
+ key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ curr_peer );
+ return 0;
+ }
+
+ do {
+ if (!memcmp(mac, curr_peer->peerMac, 6)) goto found_peer;
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
+
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s no matching MAC %d: %x %x %x %x %x %x",
+ __func__, key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ return -1;
+
+found_peer:
+
+ hddLog(VOS_TRACE_LEVEL_WARN, "tdls set peer %d rssi to %d",
+ key, rxRssi);
+
+ curr_peer->rssi = rxRssi;
+
+ return rxRssi;
+}
+
+u8 wlan_hdd_tdls_extract_da(struct sk_buff *skb, u8 *mac)
+{
+ int i;
+ u8 hash = 0;
+
+ memcpy(mac, skb->data, 6);
+ for (i = 0; i < 6; i++)
+ hash ^= mac[i];
+
+ return hash;
+}
+
+int wlan_hdd_tdls_add_peer_to_list(u8 key, u8 *mac)
+{
+ hddTdlsPeer_t *new_peer, *curr_peer;
+
+ curr_peer = pHddTdlsCtx->peer_list[key];
+
+ if (NULL == curr_peer) {
+ curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
+
+ if (NULL == curr_peer) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
+ return -1;
+ }
+ vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
+ curr_peer->rssi = -120;
+
+ INIT_LIST_HEAD(&curr_peer->node);
+ memcpy(curr_peer->peerMac, mac, 6);
+
+ pHddTdlsCtx->peer_list[key] = curr_peer;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "new peer - key:%d, mac:%x %x %x %x %x %x, 0x%x",
+ key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ curr_peer );
+ return 0;
+ }
+
+ do {
+ if (!memcmp(mac, curr_peer->peerMac, 6)) goto known_peer;
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
+
+ new_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
+ if (NULL == new_peer) {
+ hddLog(VOS_TRACE_LEVEL_ERROR, "%s peer malloc failed!", __func__);
+ return -1;
+ }
+ vos_mem_zero(new_peer, sizeof(hddTdlsPeer_t));
+ curr_peer->rssi = -120;
+ memcpy(new_peer->peerMac, mac, 6);
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "add peer - key:%d, mac:%x %x %x %x %x %x",
+ key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
+
+ list_add(&new_peer->node, &curr_peer->node);
+ curr_peer = new_peer;
+
+known_peer:
+ curr_peer->tx_pkt++;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "known peer - key:%d, mac:%x %x %x %x %x %x, tx:%d",
+ key, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
+ curr_peer->tx_pkt );
+
+ return 0;
+}
+
+int wlan_hdd_tdls_set_params(tdls_config_params_t *config)
+{
+ vos_timer_stop( &pHddTdlsCtx->peerDiscoverTimer);
+
+ vos_timer_stop( &pHddTdlsCtx->peerUpdateTimer);
+
+ memcpy(&pHddTdlsCtx->threshold_config, config, sizeof(tdls_config_params_t));
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "iw set tdls params: %d %d %d %d %d %d",
+ pHddTdlsCtx->threshold_config.tx_period_t,
+ pHddTdlsCtx->threshold_config.tx_packet_n,
+ pHddTdlsCtx->threshold_config.discovery_period_t,
+ pHddTdlsCtx->threshold_config.discovery_tries_n,
+ pHddTdlsCtx->threshold_config.rx_timeout_t,
+ pHddTdlsCtx->threshold_config.rssi_hysteresis);
+
+ vos_timer_start( &pHddTdlsCtx->peerDiscoverTimer,
+ pHddTdlsCtx->threshold_config.discovery_period_t );
+
+ vos_timer_start( &pHddTdlsCtx->peerUpdateTimer,
+ pHddTdlsCtx->threshold_config.tx_period_t );
+ return 0;
+}
+
int wlan_hdd_saveTdlsPeer(tCsrRoamInfo *pRoamInfo)
{
+ hddTdlsPeer_t *new_peer, *curr_peer;
int i;
+ u8 key = 0;
- for (i = 0; i < MAX_NUM_TDLS_PEER; i++) {
- if (0 == hddTdlsPTable[i].peer.staId) break;
+ for (i = 0; i < 6; i++)
+ key ^= pRoamInfo->peerMac[i];
- }
+ curr_peer = pHddTdlsCtx->peer_list[key];
- if (i < MAX_NUM_TDLS_PEER) {
- vos_mem_copy( hddTdlsPTable[i].peer.peerMac, pRoamInfo->peerMac, 6 );
- hddTdlsPTable[i].peer.staId = pRoamInfo->staId;
- VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ if (NULL == curr_peer) {
+ curr_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
+
+ if (NULL == curr_peer) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "saveTdlsPeer: NOT saving staId %d", pRoamInfo->staId);
+ return -1;
+ }
+ vos_mem_zero(curr_peer, sizeof(hddTdlsPeer_t));
+
+ INIT_LIST_HEAD(&curr_peer->node);
+ memcpy(curr_peer->peerMac, pRoamInfo->peerMac, 6);
+ curr_peer->staId = pRoamInfo->staId;
+ pHddTdlsCtx->peer_list[key] = curr_peer;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
"saveTdlsPeer: saved staId %d", pRoamInfo->staId);
- return i;
+ return 0;
}
- VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
- "saveTdlsPeer: NOT saving staId %d", pRoamInfo->staId);
- return -1;
+ do {
+ if (!memcmp(pRoamInfo->peerMac, curr_peer->peerMac, 6)) goto known_peer;
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
+
+ new_peer = vos_mem_malloc(sizeof(hddTdlsPeer_t));
+ if (NULL == new_peer) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "saveTdlsPeer: NOT saving staId %d", pRoamInfo->staId);
+ return -1;
+ }
+ vos_mem_zero(new_peer, sizeof(hddTdlsPeer_t));
+
+ list_add(&new_peer->node, &curr_peer->node);
+ curr_peer = new_peer;
+
+known_peer:
+ memcpy(curr_peer->peerMac, pRoamInfo->peerMac, 6);
+ curr_peer->staId = pRoamInfo->staId;
+
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "saveTdlsPeer: saved staId %d", pRoamInfo->staId);
+
+ return 0;
}
int wlan_hdd_findTdlsPeer(tSirMacAddr peerMac)
{
int i;
+ hddTdlsPeer_t *curr_peer;
- for (i = 0; i < MAX_NUM_TDLS_PEER; i++) {
- if (VOS_TRUE == vos_mem_compare( peerMac, hddTdlsPTable[i].peer.peerMac, 6 ))
- break;
+ for (i = 0; i < 256; i++) {
+ curr_peer = pHddTdlsCtx->peer_list[i];
+ if (NULL == curr_peer) continue;
+
+ do {
+ if (!memcmp(peerMac, curr_peer->peerMac, 6)) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
+ "findTdlsPeer: found staId %d", curr_peer->staId);
+ return curr_peer->staId;
+ }
+
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
}
- if (i < MAX_NUM_TDLS_PEER) {
- VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
- "findTdlsPeer: found staId %d", hddTdlsPTable[i].peer.staId);
- return hddTdlsPTable[i].peer.staId;
- }
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "findTdlsPeer: staId NOT found");
- VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
- "findTdlsPeer: staId NOT found");
return -1;
}
+
+void wlan_hdd_removeTdlsPeer(tCsrRoamInfo *pRoamInfo)
+{
+ int i;
+ hddTdlsPeer_t *curr_peer;
+
+ for (i = 0; i < 256; i++) {
+
+ curr_peer = pHddTdlsCtx->peer_list[i];
+
+ if (NULL == curr_peer) continue;
+
+ do {
+ if (curr_peer->staId == pRoamInfo->staId) goto found_peer;
+
+ curr_peer = (hddTdlsPeer_t *)curr_peer->node.next;
+ } while (&curr_peer->node != curr_peer->node.next);
+ }
+
+ if (i == 256) return;
+
+found_peer:
+ wlan_hdd_tdls_set_link_status(curr_peer->peerMac, 0);
+ wlan_hdd_tdls_set_cap(curr_peer->peerMac, 0);
+ wlan_hdd_tdls_set_rssi(curr_peer->peerMac, -120);
+}
diff --git a/CORE/HDD/src/wlan_hdd_tx_rx.c b/CORE/HDD/src/wlan_hdd_tx_rx.c
index 350937f..65787cd 100644
--- a/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -69,6 +69,10 @@
#include "sapApi.h"
#endif
+#ifdef FEATURE_WLAN_TDLS
+#include "wlan_hdd_tdls.h"
+#endif
+
/*---------------------------------------------------------------------------
Preprocessor definitions and constants
-------------------------------------------------------------------------*/
@@ -1059,6 +1063,31 @@
return VOS_STATUS_E_FAILURE;
}
+#ifdef FEATURE_WLAN_TDLS
+ {
+ hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
+ u8 key;
+ u8 mac[6];
+
+ key = wlan_hdd_tdls_extract_da(skb, mac);
+
+ if (vos_is_macaddr_broadcast((v_MACADDR_t *)mac)) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "broadcast packet, not adding to peer list");
+ } else if (memcmp(pHddStaCtx->conn_info.bssId,
+ mac, 6) != 0) {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "extract mac:%x %x %x %x %x %x",
+ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5] );
+
+ wlan_hdd_tdls_add_peer_to_list(key, mac);
+ } else {
+ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED,
+ "packet da is bssid, not adding to peer list");
+ }
+ }
+#endif
+
//Return VOS packet to TL;
*ppVosPacket = pVosPacket;
diff --git a/CORE/HDD/src/wlan_hdd_wext.c b/CORE/HDD/src/wlan_hdd_wext.c
index 7c9796b..c3bf66d 100644
--- a/CORE/HDD/src/wlan_hdd_wext.c
+++ b/CORE/HDD/src/wlan_hdd_wext.c
@@ -87,6 +87,9 @@
#ifdef WLAN_FEATURE_P2P
#include "wlan_hdd_p2p.h"
#endif
+#ifdef FEATURE_WLAN_TDLS
+#include "wlan_hdd_tdls.h"
+#endif
#ifdef CONFIG_HAS_EARLYSUSPEND
#include <linux/earlysuspend.h>
@@ -231,6 +234,10 @@
#define WE_MCC_CONFIG_CREDENTIAL 3
#define WE_MCC_CONFIG_PARAMS 4
+#ifdef FEATURE_WLAN_TDLS
+#define WE_TDLS_CONFIG_PARAMS 5
+#endif
+
#define MAX_VAR_ARGS 7
/* Private ioctls (with no sub-ioctls) */
@@ -4283,6 +4290,31 @@
}
break;
+#ifdef FEATURE_WLAN_TDLS
+ case WE_TDLS_CONFIG_PARAMS :
+ {
+ tdls_config_params_t tdlsParams;
+
+ tdlsParams.tx_period_t = apps_args[0];
+ tdlsParams.tx_packet_n = apps_args[1];
+ tdlsParams.discovery_period_t= apps_args[2];
+ tdlsParams.discovery_tries_n = apps_args[3];
+ tdlsParams.rx_timeout_t = apps_args[4];
+ tdlsParams.rssi_hysteresis = apps_args[5];
+
+ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
+ "iw set tdls params: %d %d %d %d %d %d",
+ tdlsParams.tx_period_t,
+ tdlsParams.tx_packet_n,
+ tdlsParams.discovery_period_t,
+ tdlsParams.discovery_tries_n,
+ tdlsParams.rx_timeout_t,
+ tdlsParams.rssi_hysteresis);
+
+ wlan_hdd_tdls_set_params(&tdlsParams);
+ }
+ break;
+#endif
default:
{
hddLog(LOGE, "Invalid IOCTL command %d", sub_cmd );
@@ -6287,6 +6319,15 @@
0,
"setMccConfig" },
+#ifdef FEATURE_WLAN_TDLS
+ /* handlers for sub ioctl */
+ {
+ WE_TDLS_CONFIG_PARAMS,
+ IW_PRIV_TYPE_INT | MAX_VAR_ARGS,
+ 0,
+ "setTdlsConfig" },
+#endif
+
/* handlers for main ioctl */
{ WLAN_PRIV_ADD_TSPEC,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | HDD_WLAN_WMM_PARAM_COUNT,