summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2022-02-28 18:46:12 +0200
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2022-03-07 13:55:43 +0200
commit526c4b329332c1607732a9ca17fe11b0adeacf14 (patch)
treef8fde5fb8c8a63dad4aa16fcc86fd1b5a6a9e39c
parent721008f1c3b1c2c58934a950f49d5ca85c4cc3eb (diff)
downloadNetworkManager-526c4b329332c1607732a9ca17fe11b0adeacf14.tar.gz
platform: add the plumbing to get the CSME connection info
This allows to fetch the information about the AP that CSME if connected to. It'll allow us to connect to the exact same AP and shaving off the scan from the connection, improving the connection time.
-rw-r--r--src/libnm-platform/nm-linux-platform.c9
-rw-r--r--src/libnm-platform/nm-platform.c12
-rw-r--r--src/libnm-platform/nm-platform.h14
-rw-r--r--src/libnm-platform/wifi/nm-wifi-utils-nl80211.c87
-rw-r--r--src/libnm-platform/wifi/nm-wifi-utils-private.h3
-rw-r--r--src/libnm-platform/wifi/nm-wifi-utils.c11
-rw-r--r--src/libnm-platform/wifi/nm-wifi-utils.h4
7 files changed, 140 insertions, 0 deletions
diff --git a/src/libnm-platform/nm-linux-platform.c b/src/libnm-platform/nm-linux-platform.c
index 19a661b9f7..1c14c08b4a 100644
--- a/src/libnm-platform/nm-linux-platform.c
+++ b/src/libnm-platform/nm-linux-platform.c
@@ -8536,6 +8536,14 @@ wifi_set_wake_on_wlan(NMPlatform *platform, int ifindex, _NMSettingWirelessWakeO
return nm_wifi_utils_set_wake_on_wlan(wifi_data, wowl);
}
+static gboolean
+wifi_get_csme_conn_info(NMPlatform *platform, int ifindex, NMPlatformCsmeConnInfo *out_conn_info)
+{
+ WIFI_GET_WIFI_DATA_NETNS(wifi_data, platform, ifindex, FALSE);
+
+ return nm_wifi_utils_get_csme_conn_info(wifi_data, out_conn_info);
+}
+
/*****************************************************************************/
static gboolean
@@ -9954,6 +9962,7 @@ nm_linux_platform_class_init(NMLinuxPlatformClass *klass)
platform_class->wifi_indicate_addressing_running = wifi_indicate_addressing_running;
platform_class->wifi_get_wake_on_wlan = wifi_get_wake_on_wlan;
platform_class->wifi_set_wake_on_wlan = wifi_set_wake_on_wlan;
+ platform_class->wifi_get_csme_conn_info = wifi_get_csme_conn_info;
platform_class->mesh_get_channel = mesh_get_channel;
platform_class->mesh_set_channel = mesh_set_channel;
diff --git a/src/libnm-platform/nm-platform.c b/src/libnm-platform/nm-platform.c
index f76cdfcf78..52dc4779d2 100644
--- a/src/libnm-platform/nm-platform.c
+++ b/src/libnm-platform/nm-platform.c
@@ -3061,6 +3061,18 @@ nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, _NMSettingWirel
return klass->wifi_set_wake_on_wlan(self, ifindex, wowl);
}
+gboolean
+nm_platform_wifi_get_csme_conn_info(NMPlatform *self,
+ int ifindex,
+ NMPlatformCsmeConnInfo *out_conn_info)
+{
+ _CHECK_SELF(self, klass, FALSE);
+
+ g_return_val_if_fail(ifindex > 0, FALSE);
+
+ return klass->wifi_get_csme_conn_info(self, ifindex, out_conn_info);
+}
+
guint32
nm_platform_mesh_get_channel(NMPlatform *self, int ifindex)
{
diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h
index 8965336045..87441026c3 100644
--- a/src/libnm-platform/nm-platform.h
+++ b/src/libnm-platform/nm-platform.h
@@ -1017,6 +1017,14 @@ typedef void (*NMPlatformAsyncCallback)(GError *error, gpointer user_data);
/*****************************************************************************/
+typedef struct _NMPlatformCsmeConnInfo {
+ guint8 ssid[32];
+ guint32 channel;
+ NMEtherAddr addr;
+ guint8 sta_cipher;
+ guint8 auth_mode;
+} NMPlatformCsmeConnInfo;
+
typedef enum {
NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_L3MDEV,
NM_PLATFORM_KERNEL_SUPPORT_TYPE_FRA_UID_RANGE,
@@ -1204,6 +1212,9 @@ typedef struct {
gboolean (*wifi_set_wake_on_wlan)(NMPlatform *self,
int ifindex,
_NMSettingWirelessWakeOnWLan wowl);
+ gboolean (*wifi_get_csme_conn_info)(NMPlatform *self,
+ int ifindex,
+ NMPlatformCsmeConnInfo *out_conn_info);
guint32 (*mesh_get_channel)(NMPlatform *self, int ifindex);
gboolean (*mesh_set_channel)(NMPlatform *self, int ifindex, guint32 channel);
@@ -2028,6 +2039,9 @@ void nm_platform_wifi_indicate_addressing_running(NMPlatform *self, int ifindex,
_NMSettingWirelessWakeOnWLan nm_platform_wifi_get_wake_on_wlan(NMPlatform *self, int ifindex);
gboolean
nm_platform_wifi_set_wake_on_wlan(NMPlatform *self, int ifindex, _NMSettingWirelessWakeOnWLan wowl);
+gboolean nm_platform_wifi_get_csme_conn_info(NMPlatform *self,
+ int ifindex,
+ NMPlatformCsmeConnInfo *out_conn_info);
guint32 nm_platform_mesh_get_channel(NMPlatform *self, int ifindex);
gboolean nm_platform_mesh_set_channel(NMPlatform *self, int ifindex, guint32 channel);
diff --git a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c
index 2659414e11..8a56a02773 100644
--- a/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c
+++ b/src/libnm-platform/wifi/nm-wifi-utils-nl80211.c
@@ -15,6 +15,8 @@
#include <linux/nl80211.h>
#include <linux/if.h>
+#include "linux-headers/nl80211-vnd-intel.h"
+
#include "libnm-log-core/nm-logging.h"
#include "libnm-platform/nm-netlink.h"
#include "nm-wifi-utils-private.h"
@@ -817,6 +819,90 @@ nla_put_failure:
g_return_val_if_reached(FALSE);
}
+struct nl80211_csme_conn_info {
+ NMWifiUtilsNl80211 *self;
+ NMPlatformCsmeConnInfo *conn_info;
+};
+
+static int
+nl80211_csme_conn_event_handler(struct nl_msg *msg, void *arg)
+{
+ struct nl80211_csme_conn_info *info = arg;
+ NMPlatformCsmeConnInfo *out_conn_info = info->conn_info;
+ NMWifiUtilsNl80211 *self = info->self;
+ struct genlmsghdr *gnlh = (void *) nlmsg_data(nlmsg_hdr(msg));
+ struct nlattr *tb[NL80211_ATTR_MAX + 1];
+ struct nlattr *data;
+ struct nlattr *attrs[NUM_IWL_MVM_VENDOR_ATTR];
+ int err;
+
+ static const struct nla_policy iwl_vendor_policy[NUM_IWL_MVM_VENDOR_ATTR] = {
+ [IWL_MVM_VENDOR_ATTR_AUTH_MODE] = {.type = NLA_U32},
+ [IWL_MVM_VENDOR_ATTR_SSID] = {.type = NLA_UNSPEC, .maxlen = NM_IW_ESSID_MAX_SIZE},
+ [IWL_MVM_VENDOR_ATTR_STA_CIPHER] = {.type = NLA_U32},
+ [IWL_MVM_VENDOR_ATTR_CHANNEL_NUM] = {.type = NLA_U8},
+ [IWL_MVM_VENDOR_ATTR_ADDR] = {.type = NLA_UNSPEC, .minlen = ETH_ALEN, .maxlen = ETH_ALEN},
+ };
+
+ nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL);
+ data = tb[NL80211_ATTR_VENDOR_DATA];
+
+ *out_conn_info = (NMPlatformCsmeConnInfo){};
+
+ err = nla_parse_nested(attrs, MAX_IWL_MVM_VENDOR_ATTR, data, iwl_vendor_policy);
+ if (err) {
+ _LOGD("IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO Failed to parse CSME connection info: %s",
+ nm_strerror(err));
+ return -EINVAL;
+ }
+
+ if (attrs[IWL_MVM_VENDOR_ATTR_AUTH_MODE])
+ out_conn_info->auth_mode = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_AUTH_MODE]);
+
+ if (attrs[IWL_MVM_VENDOR_ATTR_SSID])
+ memcpy(out_conn_info->ssid,
+ nla_data(attrs[IWL_MVM_VENDOR_ATTR_SSID]),
+ nla_len(attrs[IWL_MVM_VENDOR_ATTR_SSID]));
+
+ if (attrs[IWL_MVM_VENDOR_ATTR_STA_CIPHER])
+ out_conn_info->sta_cipher = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_STA_CIPHER]);
+
+ if (attrs[IWL_MVM_VENDOR_ATTR_CHANNEL_NUM])
+ out_conn_info->channel = nla_get_u8(attrs[IWL_MVM_VENDOR_ATTR_CHANNEL_NUM]);
+
+ if (attrs[IWL_MVM_VENDOR_ATTR_ADDR])
+ memcpy(&out_conn_info->addr,
+ nla_data(attrs[IWL_MVM_VENDOR_ATTR_ADDR]),
+ sizeof(out_conn_info->addr));
+
+ return NL_SKIP;
+}
+
+static gboolean
+wifi_nl80211_intel_vnd_get_csme_conn_info(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info)
+{
+ NMWifiUtilsNl80211 *self = (NMWifiUtilsNl80211 *) data;
+ nm_auto_nlmsg struct nl_msg *msg = NULL;
+ int err;
+ struct nl80211_csme_conn_info conn_info = {
+ .self = self,
+ .conn_info = out_conn_info,
+ };
+
+ msg = nl80211_alloc_msg(self, NL80211_CMD_VENDOR, 0);
+ NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_ID, INTEL_OUI);
+ NLA_PUT_U32(msg, NL80211_ATTR_VENDOR_SUBCMD, IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO);
+
+ err = nl80211_send_and_recv(self, msg, nl80211_csme_conn_event_handler, &conn_info);
+ if (err < 0)
+ _LOGD("IWL_MVM_VENDOR_CMD_GET_CSME_CONN_INFO request failed: %s", nm_strerror(err));
+
+ return err >= 0;
+
+nla_put_failure:
+ g_return_val_if_reached(FALSE);
+}
+
static void
nm_wifi_utils_nl80211_init(NMWifiUtilsNl80211 *self)
{}
@@ -841,6 +927,7 @@ nm_wifi_utils_nl80211_class_init(NMWifiUtilsNl80211Class *klass)
wifi_utils_class->get_mesh_channel = wifi_nl80211_get_mesh_channel;
wifi_utils_class->set_mesh_channel = wifi_nl80211_set_mesh_channel;
wifi_utils_class->set_mesh_ssid = wifi_nl80211_set_mesh_ssid;
+ wifi_utils_class->get_csme_conn_info = wifi_nl80211_intel_vnd_get_csme_conn_info;
}
NMWifiUtils *
diff --git a/src/libnm-platform/wifi/nm-wifi-utils-private.h b/src/libnm-platform/wifi/nm-wifi-utils-private.h
index 7461b65e73..c71963682e 100644
--- a/src/libnm-platform/wifi/nm-wifi-utils-private.h
+++ b/src/libnm-platform/wifi/nm-wifi-utils-private.h
@@ -7,6 +7,7 @@
#define __WIFI_UTILS_PRIVATE_H__
#include "nm-wifi-utils.h"
+#include "libnm-platform/nm-platform.h"
typedef struct {
GObjectClass parent;
@@ -53,6 +54,8 @@ typedef struct {
gboolean (*set_mesh_ssid)(NMWifiUtils *data, const guint8 *ssid, gsize len);
gboolean (*indicate_addressing_running)(NMWifiUtils *data, gboolean running);
+
+ gboolean (*get_csme_conn_info)(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info);
} NMWifiUtilsClass;
struct NMWifiUtils {
diff --git a/src/libnm-platform/wifi/nm-wifi-utils.c b/src/libnm-platform/wifi/nm-wifi-utils.c
index 1e484cfd1b..dd2a9ab60e 100644
--- a/src/libnm-platform/wifi/nm-wifi-utils.c
+++ b/src/libnm-platform/wifi/nm-wifi-utils.c
@@ -157,6 +157,17 @@ nm_wifi_utils_is_wifi(int dirfd, const char *ifname)
return FALSE;
}
+gboolean
+nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data, NMPlatformCsmeConnInfo *out_conn_info)
+{
+ NMWifiUtilsClass *klass;
+
+ g_return_val_if_fail(data != NULL, FALSE);
+
+ klass = NM_WIFI_UTILS_GET_CLASS(data);
+ return klass->get_csme_conn_info ? klass->get_csme_conn_info(data, out_conn_info) : FALSE;
+}
+
/* OLPC Mesh-only functions */
guint32
diff --git a/src/libnm-platform/wifi/nm-wifi-utils.h b/src/libnm-platform/wifi/nm-wifi-utils.h
index be33b90ca8..327a9c24f1 100644
--- a/src/libnm-platform/wifi/nm-wifi-utils.h
+++ b/src/libnm-platform/wifi/nm-wifi-utils.h
@@ -63,6 +63,10 @@ _NMSettingWirelessWakeOnWLan nm_wifi_utils_get_wake_on_wlan(NMWifiUtils *data);
gboolean nm_wifi_utils_set_wake_on_wlan(NMWifiUtils *data, _NMSettingWirelessWakeOnWLan wowl);
+struct _NMPlatformCsmeConnInfo;
+gboolean nm_wifi_utils_get_csme_conn_info(NMWifiUtils *data,
+ struct _NMPlatformCsmeConnInfo *out_conn_info);
+
/* OLPC Mesh-only functions */
guint32 nm_wifi_utils_get_mesh_channel(NMWifiUtils *data);