mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-30 00:20:11 +01:00
wifi: merge branch 'th/wifi-ap-max-rate-bgo779771'
https://bugzilla.gnome.org/show_bug.cgi?id=779771
This commit is contained in:
commit
608ac31e87
1 changed files with 335 additions and 11 deletions
|
|
@ -71,7 +71,7 @@ typedef struct {
|
|||
/* Non-scanned attributes */
|
||||
bool fake:1; /* Whether or not the AP is from a scan */
|
||||
bool hotspot:1; /* Whether the AP is a local device's hotspot network */
|
||||
gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */
|
||||
gint32 last_seen; /* Timestamp when the AP was seen lastly (obtained via nm_utils_get_monotonic_timestamp_s()) */
|
||||
} NMWifiAPPrivate;
|
||||
|
||||
struct _NMWifiAP {
|
||||
|
|
@ -79,7 +79,7 @@ struct _NMWifiAP {
|
|||
NMWifiAPPrivate _priv;
|
||||
};
|
||||
|
||||
struct _NMWifiAPClass{
|
||||
struct _NMWifiAPClass {
|
||||
NMExportedObjectClass parent;
|
||||
};
|
||||
|
||||
|
|
@ -435,6 +435,326 @@ security_from_vardict (GVariant *security)
|
|||
return flags;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
static guint32
|
||||
get_max_rate_ht_20 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 6500000;
|
||||
case 1:
|
||||
case 8: return 13000000;
|
||||
case 2:
|
||||
case 16: return 19500000;
|
||||
case 3:
|
||||
case 9:
|
||||
case 24: return 26000000;
|
||||
case 4:
|
||||
case 10:
|
||||
case 17: return 39000000;
|
||||
case 5:
|
||||
case 11:
|
||||
case 25: return 52000000;
|
||||
case 6:
|
||||
case 18: return 58500000;
|
||||
case 7: return 65000000;
|
||||
case 12:
|
||||
case 19:
|
||||
case 26: return 78000000;
|
||||
case 13:
|
||||
case 27: return 104000000;
|
||||
case 14:
|
||||
case 20: return 117000000;
|
||||
case 15: return 130000000;
|
||||
case 21:
|
||||
case 28: return 156000000;
|
||||
case 22: return 175500000;
|
||||
case 23: return 195000000;
|
||||
case 29: return 208000000;
|
||||
case 30: return 234000000;
|
||||
case 31: return 260000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_max_rate_ht_40 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 13500000;
|
||||
case 1:
|
||||
case 8: return 27000000;
|
||||
case 2: return 40500000;
|
||||
case 3:
|
||||
case 9:
|
||||
case 24: return 54000000;
|
||||
case 4:
|
||||
case 10:
|
||||
case 17: return 81000000;
|
||||
case 5:
|
||||
case 11:
|
||||
case 25: return 108000000;
|
||||
case 6:
|
||||
case 18: return 121500000;
|
||||
case 7: return 135000000;
|
||||
case 12:
|
||||
case 19:
|
||||
case 26: return 162000000;
|
||||
case 13:
|
||||
case 27: return 216000000;
|
||||
case 14:
|
||||
case 20: return 243000000;
|
||||
case 15: return 270000000;
|
||||
case 16: return 40500000;
|
||||
case 21:
|
||||
case 28: return 324000000;
|
||||
case 22: return 364500000;
|
||||
case 23: return 405000000;
|
||||
case 29: return 432000000;
|
||||
case 30: return 486000000;
|
||||
case 31: return 540000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_max_rate_vht_80_ss1 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 29300000;
|
||||
case 1: return 58500000;
|
||||
case 2: return 87800000;
|
||||
case 3: return 117000000;
|
||||
case 4: return 175500000;
|
||||
case 5: return 234000000;
|
||||
case 6: return 263300000;
|
||||
case 7: return 292500000;
|
||||
case 8: return 351000000;
|
||||
case 9: return 390000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_max_rate_vht_80_ss2 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 58500000;
|
||||
case 1: return 117000000;
|
||||
case 2: return 175500000;
|
||||
case 3: return 234000000;
|
||||
case 4: return 351000000;
|
||||
case 5: return 468000000;
|
||||
case 6: return 526500000;
|
||||
case 7: return 585000000;
|
||||
case 8: return 702000000;
|
||||
case 9: return 780000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_max_rate_vht_80_ss3 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 87800000;
|
||||
case 1: return 175500000;
|
||||
case 2: return 263300000;
|
||||
case 3: return 351000000;
|
||||
case 4: return 526500000;
|
||||
case 5: return 702000000;
|
||||
case 6: return 0;
|
||||
case 7: return 877500000;
|
||||
case 8: return 105300000;
|
||||
case 9: return 117000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_max_rate_vht_160_ss1 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 58500000;
|
||||
case 1: return 117000000;
|
||||
case 2: return 175500000;
|
||||
case 3: return 234000000;
|
||||
case 4: return 351000000;
|
||||
case 5: return 468000000;
|
||||
case 6: return 526500000;
|
||||
case 7: return 585000000;
|
||||
case 8: return 702000000;
|
||||
case 9: return 780000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_max_rate_vht_160_ss2 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 117000000;
|
||||
case 1: return 234000000;
|
||||
case 2: return 351000000;
|
||||
case 3: return 468000000;
|
||||
case 4: return 702000000;
|
||||
case 5: return 936000000;
|
||||
case 6: return 1053000000;
|
||||
case 7: return 1170000000;
|
||||
case 8: return 1404000000;
|
||||
case 9: return 1560000000;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint32
|
||||
get_max_rate_vht_160_ss3 (int mcs)
|
||||
{
|
||||
switch (mcs) {
|
||||
case 0: return 175500000;
|
||||
case 1: return 351000000;
|
||||
case 2: return 526500000;
|
||||
case 3: return 702000000;
|
||||
case 4: return 1053000000;
|
||||
case 5: return 1404000000;
|
||||
case 6: return 1579500000;
|
||||
case 7: return 1755000000;
|
||||
case 8: return 2106000000;
|
||||
case 9: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_max_rate_ht (const guint8 *bytes, guint len, guint32 *out_maxrate)
|
||||
{
|
||||
guint32 mcs, i;
|
||||
guint8 ht_cap_info;
|
||||
const guint8 *supported_mcs_set;
|
||||
guint32 rate;
|
||||
|
||||
/* http://standards.ieee.org/getieee802/download/802.11-2012.pdf
|
||||
* https://mrncciew.com/2014/10/19/cwap-ht-capabilities-ie/
|
||||
*/
|
||||
|
||||
if (len != 26)
|
||||
return FALSE;
|
||||
|
||||
ht_cap_info = bytes[0];
|
||||
supported_mcs_set = &bytes[3];
|
||||
*out_maxrate = 0;
|
||||
|
||||
/* Find the maximum supported mcs rate */
|
||||
mcs = -1;
|
||||
for (i = 0; i <= 76; i++) {
|
||||
unsigned int mcs_octet = i / 8;
|
||||
unsigned int MCS_RATE_BIT = 1 << i % 8;
|
||||
|
||||
if (supported_mcs_set[mcs_octet] & MCS_RATE_BIT) {
|
||||
/* Check for 40Mhz wide channel support */
|
||||
if (ht_cap_info & (1 << 1))
|
||||
rate = get_max_rate_ht_40 (i);
|
||||
else
|
||||
rate = get_max_rate_ht_20 (i);
|
||||
|
||||
if (rate > *out_maxrate)
|
||||
*out_maxrate = rate;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_max_rate_vht (const guint8 *bytes, guint len, guint32 *out_maxrate)
|
||||
{
|
||||
guint32 mcs, m;
|
||||
guint8 vht_cap, tx_map;
|
||||
|
||||
/* https://tda802dot11.blogspot.it/2014/10/vht-capabilities-element-vht.html
|
||||
* http://chimera.labs.oreilly.com/books/1234000001739/ch03.html#management_frames */
|
||||
|
||||
if (len != 12)
|
||||
return FALSE;
|
||||
|
||||
vht_cap = bytes[0];
|
||||
tx_map = bytes[8];
|
||||
|
||||
/* Check for mcs rates 8 and 9 support */
|
||||
if (tx_map & 0x2a)
|
||||
mcs = 9;
|
||||
else if (tx_map & 0x15)
|
||||
mcs = 8;
|
||||
else
|
||||
mcs = 7;
|
||||
|
||||
/* Check for 160Mhz wide channel support and
|
||||
* spatial stream support */
|
||||
if (vht_cap & (1 << 2)) {
|
||||
if (tx_map & 0x30)
|
||||
m = get_max_rate_vht_160_ss3 (mcs);
|
||||
else if (tx_map & 0x0C)
|
||||
m = get_max_rate_vht_160_ss2 (mcs);
|
||||
else
|
||||
m = get_max_rate_vht_160_ss1 (mcs);
|
||||
} else {
|
||||
if (tx_map & 0x30)
|
||||
m = get_max_rate_vht_80_ss3 (mcs);
|
||||
else if (tx_map & 0x0C)
|
||||
m = get_max_rate_vht_80_ss2 (mcs);
|
||||
else
|
||||
m = get_max_rate_vht_80_ss1 (mcs);
|
||||
}
|
||||
|
||||
*out_maxrate = m;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Management Frame Information Element IDs, ieee80211_eid */
|
||||
#define WLAN_EID_HT_CAPABILITY 45
|
||||
#define WLAN_EID_VHT_CAPABILITY 191
|
||||
|
||||
static guint32
|
||||
get_max_rate (const guint8 *bytes, gsize len)
|
||||
{
|
||||
guint8 id, elem_len;
|
||||
guint32 max_rate = 0;
|
||||
|
||||
while (len) {
|
||||
guint32 m;
|
||||
|
||||
if (len < 2)
|
||||
return 0;
|
||||
|
||||
id = *bytes++;
|
||||
elem_len = *bytes++;
|
||||
len -= 2;
|
||||
|
||||
if (elem_len > len)
|
||||
return 0;
|
||||
|
||||
switch (id) {
|
||||
case WLAN_EID_HT_CAPABILITY:
|
||||
if (!get_max_rate_ht (bytes, elem_len, &m))
|
||||
return 0;
|
||||
max_rate = NM_MAX (max_rate, m);
|
||||
break;
|
||||
case WLAN_EID_VHT_CAPABILITY:
|
||||
if (!get_max_rate_vht (bytes, elem_len, &m))
|
||||
return 0;
|
||||
max_rate = NM_MAX (max_rate, m);
|
||||
break;
|
||||
}
|
||||
|
||||
len -= elem_len;
|
||||
bytes += elem_len;
|
||||
}
|
||||
|
||||
return max_rate;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
gboolean
|
||||
nm_wifi_ap_update_from_properties (NMWifiAP *ap,
|
||||
const char *supplicant_path,
|
||||
|
|
@ -444,11 +764,13 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
|
|||
const guint8 *bytes;
|
||||
GVariant *v;
|
||||
gsize len;
|
||||
gsize i;
|
||||
gboolean b = FALSE;
|
||||
const char *s;
|
||||
gint16 i16;
|
||||
guint16 u16;
|
||||
gboolean changed = FALSE;
|
||||
guint32 max_rate;
|
||||
|
||||
g_return_val_if_fail (NM_IS_WIFI_AP (ap), FALSE);
|
||||
g_return_val_if_fail (properties, FALSE);
|
||||
|
|
@ -497,21 +819,23 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
|
|||
g_variant_unref (v);
|
||||
}
|
||||
|
||||
max_rate = 0;
|
||||
v = g_variant_lookup_value (properties, "Rates", G_VARIANT_TYPE ("au"));
|
||||
if (v) {
|
||||
const guint32 *rates = g_variant_get_fixed_array (v, &len, sizeof (guint32));
|
||||
guint32 maxrate = 0;
|
||||
int i;
|
||||
|
||||
/* Find the max AP rate */
|
||||
for (i = 0; i < len; i++) {
|
||||
if (rates[i] > maxrate)
|
||||
maxrate = rates[i];
|
||||
}
|
||||
if (maxrate)
|
||||
changed |= nm_wifi_ap_set_max_bitrate (ap, maxrate / 1000);
|
||||
for (i = 0; i < len; i++)
|
||||
max_rate = NM_MAX (max_rate, rates[i]);
|
||||
g_variant_unref (v);
|
||||
}
|
||||
v = g_variant_lookup_value (properties, "IEs", G_VARIANT_TYPE_BYTESTRING);
|
||||
if (v) {
|
||||
bytes = g_variant_get_fixed_array (v, &len, 1);
|
||||
max_rate = NM_MAX (max_rate, get_max_rate (bytes, len));
|
||||
g_variant_unref (v);
|
||||
}
|
||||
if (max_rate)
|
||||
changed |= nm_wifi_ap_set_max_bitrate (ap, max_rate / 1000);
|
||||
|
||||
v = g_variant_lookup_value (properties, "WPA", G_VARIANT_TYPE_VARDICT);
|
||||
if (v) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue