TDLS: Fix to prevent 4 simultaneous TDLS links.
As a TDLS_INITIATOR we are preventing any TDLS_SETUP_REQ
to go out from HDD if we are already reached to maximum
TDLS peer connection.
CRs-Fixed: 444403
Change-Id: I96568dccd02a1ed45a565c609aadfe6856fc9587
diff --git a/CORE/HDD/inc/wlan_hdd_tdls.h b/CORE/HDD/inc/wlan_hdd_tdls.h
index 7363bb4..828a5cb 100644
--- a/CORE/HDD/inc/wlan_hdd_tdls.h
+++ b/CORE/HDD/inc/wlan_hdd_tdls.h
@@ -105,4 +105,7 @@
int wlan_hdd_tdls_set_params(tdls_config_params_t *config);
void wlan_hdd_removeTdlsPeer(tCsrRoamInfo *pRoamInfo);
+
+u8 wlan_hdd_tdlsConnectedPeers(void);
+
#endif // __HDD_TDSL_H
diff --git a/CORE/HDD/src/wlan_hdd_cfg80211.c b/CORE/HDD/src/wlan_hdd_cfg80211.c
index bc572f1..d82f82a 100644
--- a/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -138,6 +138,12 @@
.flags = flag, \
}
+#ifndef WLAN_FEATURE_TDLS_DEBUG
+#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO
+#else
+#define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_ERROR
+#endif
+
static const u32 hdd_cipher_suites[] =
{
WLAN_CIPHER_SUITE_WEP40,
@@ -6274,14 +6280,24 @@
Cannot process TDLS commands \n");
return -ENOTSUPP;
}
+ /* first to check if we reached to maximum supported TDLS peer.
+ TODO: for now, return -EPERM looks working fine,
+ but need to check if any other errno fit into this category.*/
+ if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "%s: TDLS Max peer already connected. Request declined. \n",
+ __func__);
+ return -EPERM;
+ }
mask = params->sta_flags_mask;
set = params->sta_flags_set;
- VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
- "Add Station Request Mask = 0x%x set = 0x%x\n", mask, set);
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "%s: mask 0x%x set 0x%x\n",__func__, mask, set);
if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
if (set & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
@@ -6476,6 +6492,32 @@
Cannot process TDLS commands \n");
return -ENOTSUPP;
}
+
+ if(SIR_MAC_TDLS_SETUP_REQ == action_code ||
+ SIR_MAC_TDLS_SETUP_RSP == action_code )
+ {
+ if(HDD_MAX_NUM_TDLS_STA == wlan_hdd_tdlsConnectedPeers())
+ {
+ /* supplicant still sends tdls_mgmt(SETUP_REQ) even after
+ we return error code at 'add_station()'. Hence we have this
+ check again in addtion to add_station().
+ Anyway, there is no hard to double-check. */
+ if(SIR_MAC_TDLS_SETUP_REQ == action_code)
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "%s: TDLS Max peer already connected. Request declined. \n",
+ __func__);
+ return -EPERM;
+ }
+ else
+ {
+ status_code = eSIR_MAC_UNSPEC_FAILURE_STATUS;
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "%s: TDLS Max peer already connected send response status %d \n",
+ __func__,status_code);
+ }
+ }
+ }
vos_mem_copy( peerMac, peer, 6);
#ifdef WLAN_FEATURE_TDLS_DEBUG
@@ -6590,9 +6632,19 @@
}
break;
case NL80211_TDLS_DISABLE_LINK:
- sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
- pAdapter->sessionId, peer );
- return 0;
+ {
+ if(-1 != wlan_hdd_findTdlsPeer(peer))
+ {
+ sme_DeleteTdlsPeerSta( WLAN_HDD_GET_HAL_CTX(pAdapter),
+ pAdapter->sessionId, peer );
+ }
+ else
+ {
+ VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL,
+ "%s: TDLS Peer Station doesn't exist \n",__func__);
+ }
+ return 0;
+ }
case NL80211_TDLS_TEARDOWN:
case NL80211_TDLS_SETUP:
case NL80211_TDLS_DISCOVERY_REQ:
diff --git a/CORE/HDD/src/wlan_hdd_tdls.c b/CORE/HDD/src/wlan_hdd_tdls.c
index 18c60e5..62cb864 100644
--- a/CORE/HDD/src/wlan_hdd_tdls.c
+++ b/CORE/HDD/src/wlan_hdd_tdls.c
@@ -212,7 +212,9 @@
static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData )
{
+#ifdef CONFIG_TDLS_IMPLICIT
hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData;
+#endif
VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, "Tx/Rx Idle - teardown!");
@@ -711,3 +713,26 @@
}
}
}
+
+/* TODO: Currently I am using conn_info.staId
+ here as per current design but tdls.c shouldn't
+ have touch this.*/
+u8 wlan_hdd_tdlsConnectedPeers(void)
+{
+ hdd_adapter_t *pAdapter;
+ hdd_station_ctx_t *pHddStaCtx;
+ u8 staIdx;
+ u8 count = 0;
+
+ if (NULL == pHddTdlsCtx) return -1;
+
+ pAdapter = WLAN_HDD_GET_PRIV_PTR(pHddTdlsCtx->dev);
+ pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
+
+ for ( staIdx = 0 ; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++ )
+ {
+ if (0 != pHddStaCtx->conn_info.staId[staIdx] )
+ count++;
+ }
+ return count;
+}