summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.c18
-rw-r--r--core/hdd/src/wlan_hdd_cfg80211.h23
-rw-r--r--core/hdd/src/wlan_hdd_subnet_detect.c195
-rw-r--r--core/hdd/src/wlan_hdd_subnet_detect.h44
4 files changed, 280 insertions, 0 deletions
diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c
index fcb331a9c22b..9f431ae95cd1 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.c
+++ b/core/hdd/src/wlan_hdd_cfg80211.c
@@ -87,6 +87,8 @@
#include "wlan_hdd_ocb.h"
+#include "wlan_hdd_subnet_detect.h"
+
#define g_mode_rates_size (12)
#define a_mode_rates_size (8)
#define GET_IE_LEN_IN_BSS_DESC(lenInBss) (lenInBss + sizeof(lenInBss) - \
@@ -1064,6 +1066,12 @@ static const struct nl80211_vendor_cmd_info wlan_hdd_cfg80211_vendor_events[] =
.vendor_id = QCA_NL80211_VENDOR_ID,
.subcmd = QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT
},
+#ifdef FEATURE_LFR_SUBNET_DETECTION
+ [QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX] = {
+ .vendor_id = QCA_NL80211_VENDOR_ID,
+ .subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG
+ },
+#endif /*FEATURE_LFR_SUBNET_DETECTION */
};
/**
@@ -4982,6 +4990,16 @@ const struct wiphy_vendor_command hdd_wiphy_vendor_commands[] = {
WIPHY_VENDOR_CMD_NEED_RUNNING,
.doit = wlan_hdd_cfg80211_set_ota_test
},
+#ifdef FEATURE_LFR_SUBNET_DETECTION
+ {
+ .info.vendor_id = QCA_NL80211_VENDOR_ID,
+ .info.subcmd = QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG,
+ .flags = WIPHY_VENDOR_CMD_NEED_WDEV |
+ WIPHY_VENDOR_CMD_NEED_NETDEV |
+ WIPHY_VENDOR_CMD_NEED_RUNNING,
+ .doit = wlan_hdd_cfg80211_set_gateway_params
+ },
+#endif /* FEATURE_LFR_SUBNET_DETECTION */
};
/*
diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h
index 34275409f0bd..34134d3b9ff4 100644
--- a/core/hdd/src/wlan_hdd_cfg80211.h
+++ b/core/hdd/src/wlan_hdd_cfg80211.h
@@ -249,6 +249,7 @@ typedef enum {
* @QCA_NL80211_VENDOR_SUBCMD_TRIGGER_SCAN: venodr scan command
* @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE: vendor scan complete
* @QCA_NL80211_VENDOR_SUBCMD_OTA_TEST: enable OTA test
+ * @QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG: set gateway parameters
*/
enum qca_nl80211_vendor_subcmds {
@@ -350,6 +351,8 @@ enum qca_nl80211_vendor_subcmds {
/* subcommand to get link properties */
QCA_NL80211_VENDOR_SUBCMD_LINK_PROPERTIES = 101,
+ /* LFR Subnet Detection */
+ QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG = 102,
/* DBS subcommands */
QCA_NL80211_VENDOR_SUBCMD_GET_PREFERRED_FREQ_LIST = 103,
@@ -420,6 +423,8 @@ enum qca_nl80211_vendor_subcmds {
* @QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX: vendor scan index
* @QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX:
* vendor scan complete event index
+ * @QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX:
+ * update gateway parameters index
*/
enum qca_nl80211_vendor_subcmds_index {
@@ -488,6 +493,7 @@ enum qca_nl80211_vendor_subcmds_index {
QCA_NL80211_VENDOR_SUBCMD_DCC_STATS_EVENT_INDEX,
QCA_NL80211_VENDOR_SUBCMD_SCAN_INDEX,
QCA_NL80211_VENDOR_SUBCMD_SCAN_DONE_INDEX,
+ QCA_NL80211_VENDOR_SUBCMD_GW_PARAM_CONFIG_INDEX,
};
/**
@@ -2166,6 +2172,23 @@ enum qca_vendor_attr_probable_oper_channel {
};
/**
+ * enum qca_wlan_vendor_attr_gw_param_config - gateway param config
+ * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_INVALID: Invalid
+ * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR: gateway mac addr
+ * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR: ipv4 addr
+ * @QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR: ipv6 addr
+ */
+enum qca_wlan_vendor_attr_gw_param_config {
+ QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_INVALID = 0,
+ QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR,
+ QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR,
+ QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR,
+ QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_AFTER_LAST,
+ QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX =
+ QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_AFTER_LAST - 1,
+};
+
+/**
* enum drv_dbs_capability - DBS capability
* @DRV_DBS_CAPABILITY_DISABLED: DBS disabled
* @DRV_DBS_CAPABILITY_1X1: 1x1
diff --git a/core/hdd/src/wlan_hdd_subnet_detect.c b/core/hdd/src/wlan_hdd_subnet_detect.c
new file mode 100644
index 000000000000..44d69b5c24b3
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_subnet_detect.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+/**
+ * DOC: wlan_hdd_subnet_detect.c
+ *
+ * WLAN Host Device Driver subnet detect API implementation
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <net/cfg80211.h>
+#include <ani_global.h>
+#include "sme_api.h"
+#include "wlan_hdd_main.h"
+#include "wlan_hdd_subnet_detect.h"
+
+/*
+ * define short names for the global vendor params
+ * used by __wlan_hdd_cfg80211_set_gateway_params()
+ */
+#define PARAM_MAC_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_GW_MAC_ADDR
+#define PARAM_IPV4_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV4_ADDR
+#define PARAM_IPV6_ADDR QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_IPV6_ADDR
+
+static const struct nla_policy
+ policy[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1] = {
+ [PARAM_MAC_ADDR] = {
+ .type = NLA_BINARY,
+ .len = CDF_MAC_ADDR_SIZE
+ },
+ [PARAM_IPV4_ADDR] = {
+ .type = NLA_BINARY,
+ .len = CDF_IPV4_ADDR_SIZE
+ },
+ [PARAM_IPV6_ADDR] = {
+ .type = NLA_BINARY,
+ .len = CDF_IPV6_ADDR_SIZE
+ }
+};
+
+/**
+ * __wlan_hdd_cfg80211_set_gateway_params() - set gateway params
+ * @wiphy: Pointer to wireless phy
+ * @wdev: Pointer to wireless device
+ * @data: Pointer to data
+ * @data_len: Data length
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+static int __wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy,
+ struct wireless_dev *wdev,
+ const void *data,
+ int data_len)
+{
+ struct net_device *dev = wdev->netdev;
+ hdd_adapter_t *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
+ hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
+ struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX + 1];
+ struct gateway_param_update_req req = { 0 };
+ int ret;
+ CDF_STATUS status;
+
+ ENTER();
+
+ ret = wlan_hdd_validate_context(hdd_ctx);
+ if (0 != ret)
+ return ret;
+
+ /* user may have disabled the feature in INI */
+ if (!hdd_ctx->config->enable_lfr_subnet_detection) {
+ hdd_info("LFR Subnet Detection disabled in INI");
+ return -ENOTSUPP;
+ }
+
+ /* The gateway parameters are only valid in the STA persona
+ * and only in the connected state.
+ */
+ if (WLAN_HDD_INFRA_STATION != adapter->device_mode) {
+ hdd_err("Received GW param update for non-STA mode adapter");
+ return -ENOTSUPP;
+ }
+
+ if (!hdd_conn_is_connected(WLAN_HDD_GET_STATION_CTX_PTR(adapter))) {
+ hdd_err("Received GW param update in disconnected state!");
+ return -ENOTSUPP;
+ }
+
+ /* Extract NL parameters
+ * mac_addr: 6 bytes
+ * ipv4 addr: 4 bytes
+ * ipv6 addr: 16 bytes
+ */
+ if (nla_parse(tb, QCA_WLAN_VENDOR_ATTR_GW_PARAM_CONFIG_MAX,
+ data, data_len, policy)) {
+ hdd_err("Invalid ATTR list");
+ return -EINVAL;
+ }
+
+ if (!tb[PARAM_MAC_ADDR]) {
+ hdd_err("request mac addr failed");
+ return -EINVAL;
+ }
+ nla_memcpy(req.gw_mac_addr.bytes, tb[PARAM_MAC_ADDR],
+ CDF_MAC_ADDR_SIZE);
+
+ /* req ipv4_addr_type and ipv6_addr_type are initially false due
+ * to zeroing the struct
+ */
+ if (tb[PARAM_IPV4_ADDR]) {
+ nla_memcpy(req.ipv4_addr, tb[PARAM_IPV4_ADDR],
+ CDF_IPV4_ADDR_SIZE);
+ req.ipv4_addr_type = true;
+ }
+
+ if (tb[PARAM_IPV6_ADDR]) {
+ nla_memcpy(&req.ipv6_addr, tb[PARAM_IPV6_ADDR],
+ CDF_IPV6_ADDR_SIZE);
+ req.ipv6_addr_type = true;
+ }
+
+ if (!req.ipv4_addr_type && !req.ipv6_addr_type) {
+ hdd_err("invalid ipv4 or ipv6 gateway address");
+ return -EINVAL;
+ }
+
+ req.max_retries = 3;
+ req.timeout = 100; /* in milliseconds */
+ req.session_id = adapter->sessionId;
+
+ hdd_info("**** Gateway Parameters: ****");
+ hdd_info("session id: %d", req.session_id);
+ hdd_info("ipv4 addr type: %d", req.ipv4_addr_type);
+ hdd_info("ipv6 addr type: %d", req.ipv6_addr_type);
+ hdd_info("gw mac addr: %pM", req.gw_mac_addr.bytes);
+ hdd_info("ipv4 addr: %pI4", req.ipv4_addr);
+ hdd_info("ipv6 addr: %pI6c", req.ipv6_addr);
+
+ status = sme_gateway_param_update(hdd_ctx->hHal, &req);
+ if (!CDF_IS_STATUS_SUCCESS(status)) {
+ hdd_err("sme_gateway_param_update failed(err=%d)", status);
+ ret = -EINVAL;
+ }
+
+ EXIT();
+ return ret;
+}
+
+/**
+ * wlan_hdd_cfg80211_set_gateway_params() - set gateway parameters
+ * @wiphy: wiphy structure pointer
+ * @wdev: Wireless device structure pointer
+ * @data: Pointer to the data received
+ * @data_len: Length of @data
+ *
+ * The API is invoked by the user space to set the gateway parameters
+ * such as mac address and the IP address which is used for detecting
+ * the IP subnet change
+ *
+ * Return: 0 on success; errno on failure
+ */
+int wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int data_len)
+{
+ int ret;
+
+ cds_ssr_protect(__func__);
+
+ ret = __wlan_hdd_cfg80211_set_gateway_params(
+ wiphy, wdev, data, data_len);
+ cds_ssr_unprotect(__func__);
+ return ret;
+}
+#undef PARAM_MAC_ADDR
+#undef PARAM_IPV4_ADDR
+#undef PARAM_IPV6_ADDR
diff --git a/core/hdd/src/wlan_hdd_subnet_detect.h b/core/hdd/src/wlan_hdd_subnet_detect.h
new file mode 100644
index 000000000000..ffab910884cb
--- /dev/null
+++ b/core/hdd/src/wlan_hdd_subnet_detect.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#ifndef __WLAN_HDD_SUBNET_DETECT_H
+#define __WLAN_HDD_SUBNET_DETECT_H
+
+/**
+ * DOC: wlan_hdd_subnet_detect.h
+ *
+ * WLAN Host Device Driver subnet detect API specification
+ */
+
+#ifdef FEATURE_LFR_SUBNET_DETECTION
+struct wiphy;
+struct wireless_dev;
+
+int wlan_hdd_cfg80211_set_gateway_params(struct wiphy *wiphy,
+ struct wireless_dev *wdev, const void *data, int data_len);
+#endif /* FEATURE_LFR_SUBNET_DETECTION */
+#endif /* __WLAN_HDD_SUBNET_DETECT_H */