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.
This commit is contained in:
Emmanuel Grumbach 2022-02-28 18:46:12 +02:00
parent 721008f1c3
commit 526c4b3293
7 changed files with 140 additions and 0 deletions

View file

@ -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;

View file

@ -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)
{

View file

@ -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);

View file

@ -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 *

View file

@ -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 {

View file

@ -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

View file

@ -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);