diff options
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.c | 18 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_cfg80211.h | 23 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_subnet_detect.c | 195 | ||||
| -rw-r--r-- | core/hdd/src/wlan_hdd_subnet_detect.h | 44 |
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 */ |
