summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2020-01-27 20:16:22 +0100
committerThomas Haller <thaller@redhat.com>2020-02-10 19:11:50 +0100
commitcc002ed3c1ec651b4dc52026e44340880fe643d6 (patch)
treec9bc84c687cc2b24caa80008282675667592983a
parent05ff735ec00aa32c6c7b3b2f80606a4e1cb06f95 (diff)
wifi: move nm_wifi_utils_parse_ies() to "src/nm-core-utils.h"
We will need it in "src/supplicant".
-rw-r--r--src/devices/wifi/nm-wifi-ap.c325
-rw-r--r--src/nm-core-utils.c332
-rw-r--r--src/nm-core-utils.h5
3 files changed, 338 insertions, 324 deletions
diff --git a/src/devices/wifi/nm-wifi-ap.c b/src/devices/wifi/nm-wifi-ap.c
index e07fde543..18f1a5a91 100644
--- a/src/devices/wifi/nm-wifi-ap.c
+++ b/src/devices/wifi/nm-wifi-ap.c
@@ -452,329 +452,6 @@ security_from_vardict (GVariant *security)
/*****************************************************************************/
-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 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 */
- 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
-#define WLAN_EID_VENDOR_SPECIFIC 221
-
-static void
-parse_ies (const guint8 *bytes, gsize len, guint32 *out_max_rate, gboolean *out_metered)
-{
- guint8 id, elem_len;
- guint32 m;
-
- *out_max_rate = 0;
- *out_metered = FALSE;
-
- while (len) {
- if (len < 2)
- break;
-
- id = *bytes++;
- elem_len = *bytes++;
- len -= 2;
-
- if (elem_len > len)
- break;
-
- switch (id) {
- case WLAN_EID_HT_CAPABILITY:
- if (get_max_rate_ht (bytes, elem_len, &m))
- *out_max_rate = NM_MAX (*out_max_rate, m);
- break;
- case WLAN_EID_VHT_CAPABILITY:
- if (get_max_rate_vht (bytes, elem_len, &m))
- *out_max_rate = NM_MAX (*out_max_rate, m);
- break;
- case WLAN_EID_VENDOR_SPECIFIC:
- if ( len == 8
- && bytes[0] == 0x00 /* OUI: Microsoft */
- && bytes[1] == 0x50
- && bytes[2] == 0xf2
- && bytes[3] == 0x11) /* OUI type: Network cost */
- *out_metered = (bytes[7] > 1); /* Cost level > 1 */
- break;
- }
-
- len -= elem_len;
- bytes += elem_len;
- }
-}
-
-/*****************************************************************************/
-
gboolean
nm_wifi_ap_update_from_properties (NMWifiAP *ap,
const char *supplicant_path,
@@ -872,7 +549,7 @@ nm_wifi_ap_update_from_properties (NMWifiAP *ap,
v = g_variant_lookup_value (properties, "IEs", G_VARIANT_TYPE_BYTESTRING);
if (v) {
bytes = g_variant_get_fixed_array (v, &len, 1);
- parse_ies (bytes, len, &rate, &metered);
+ nm_wifi_utils_parse_ies (bytes, len, &rate, &metered);
max_rate = NM_MAX (max_rate, rate);
g_variant_unref (v);
priv->metered = metered;
diff --git a/src/nm-core-utils.c b/src/nm-core-utils.c
index eccb5f7b1..9529c3e01 100644
--- a/src/nm-core-utils.c
+++ b/src/nm-core-utils.c
@@ -4073,6 +4073,338 @@ nm_utils_strdict_to_variant (GHashTable *options)
/*****************************************************************************/
+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 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 */
+ for (i = 0; i <= 76; i++) {
+ const unsigned mcs_octet = i / 8;
+ const unsigned 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
+#define WLAN_EID_VENDOR_SPECIFIC 221
+
+void
+nm_wifi_utils_parse_ies (const guint8 *bytes,
+ gsize len,
+ guint32 *out_max_rate,
+ gboolean *out_metered)
+{
+ guint8 id, elem_len;
+ guint32 m;
+
+ NM_SET_OUT (out_max_rate, 0);
+ NM_SET_OUT (out_metered, FALSE);
+
+ while (len) {
+ if (len < 2)
+ break;
+
+ id = *bytes++;
+ elem_len = *bytes++;
+ len -= 2;
+
+ if (elem_len > len)
+ break;
+
+ switch (id) {
+ case WLAN_EID_HT_CAPABILITY:
+ if (out_max_rate) {
+ if (get_max_rate_ht (bytes, elem_len, &m))
+ *out_max_rate = NM_MAX (*out_max_rate, m);
+ }
+ break;
+ case WLAN_EID_VHT_CAPABILITY:
+ if (out_max_rate) {
+ if (get_max_rate_vht (bytes, elem_len, &m))
+ *out_max_rate = NM_MAX (*out_max_rate, m);
+ }
+ break;
+ case WLAN_EID_VENDOR_SPECIFIC:
+ if (out_metered) {
+ if ( len == 8
+ && bytes[0] == 0x00 /* OUI: Microsoft */
+ && bytes[1] == 0x50
+ && bytes[2] == 0xf2
+ && bytes[3] == 0x11) /* OUI type: Network cost */
+ *out_metered = (bytes[7] > 1); /* Cost level > 1 */
+ }
+ break;
+ }
+
+ len -= elem_len;
+ bytes += elem_len;
+ }
+}
+
+/*****************************************************************************/
+
guint8
nm_wifi_utils_level_to_quality (int val)
{
diff --git a/src/nm-core-utils.h b/src/nm-core-utils.h
index ca3e7dbf3..14cdae3cd 100644
--- a/src/nm-core-utils.h
+++ b/src/nm-core-utils.h
@@ -473,6 +473,11 @@ const char *nm_utils_parse_dns_domain (const char *domain, gboolean *is_routing)
/*****************************************************************************/
+void nm_wifi_utils_parse_ies (const guint8 *bytes,
+ gsize len,
+ guint32 *out_max_rate,
+ gboolean *out_metered);
+
guint8 nm_wifi_utils_level_to_quality (int val);
/*****************************************************************************/