From 647f1e9b91c297fa692348aacb6f4805d2706d17 Mon Sep 17 00:00:00 2001 From: Denis Kenzior Date: Thu, 3 Jun 2021 22:15:45 -0500 Subject: [PATCH] ie: Remove old data rate estimation utilities --- src/ie.c | 449 ------------------------------------------------------- src/ie.h | 7 - 2 files changed, 456 deletions(-) diff --git a/src/ie.c b/src/ie.c index 2e196fbb..3549fde2 100644 --- a/src/ie.c +++ b/src/ie.c @@ -31,7 +31,6 @@ #include "ell/useful.h" #include "src/util.h" #include "src/crypto.h" -#include "src/band.h" #include "src/ie.h" const unsigned char ieee_oui[3] = { 0x00, 0x0f, 0xac }; @@ -1632,454 +1631,6 @@ int ie_parse_bss_load_from_data(const uint8_t *data, uint8_t len, out_channel_utilization, out_admission_capacity); } -/* - * We have to store this mapping since basic rates don't come with a convenient - * MCS index. Rates are stored as they are encoded in the Supported Rates IE. - * This does not include non 802.11g data rates, e.g. 1/2/4Mbps. This data was - * taken from 802.11 Section 17.3.10.2 and Table 10-7. - * - * Section 17.3.10.2 defines minimum RSSI for modulations, and Table - * 10-7 defines reference rates for the different modulations. Together we - * have minimum RSSI required for a given data rate. - */ -struct basic_rate_map { - int32_t rssi; - uint8_t rate; -}; - -/* - * Rates are stored in 500Kbps increments. This is how the IE encodes the data - * so its more convenient to match by this encoding. The actual data rate is - * converted to Mbps after we find a match - */ -static const struct basic_rate_map rate_rssi_map[] = { - { -82, 12 }, - { -81, 18 }, - { -79, 24 }, - { -77, 36 }, - { -74, 48 }, - { -70, 72 }, - { -66, 96 }, - { -65, 108 }, -}; - -static int ie_parse_supported_rates_from_data(const uint8_t *supp_rates_ie, - const uint8_t *ext_supp_rates_ie, - int32_t rssi, uint64_t *data_rate) -{ - uint8_t max_rate = 0; - uint8_t highest = 0; - const uint8_t *rates; - unsigned int len; - unsigned int i; - - /* Find highest rates possible with our RSSI */ - for (i = 0; i < L_ARRAY_SIZE(rate_rssi_map); i++) { - const struct basic_rate_map *map = &rate_rssi_map[i]; - - if (rssi < map->rssi) - break; - - max_rate = map->rate; - } - - /* - * Find highest rate in Supported Rates IE. These IEs have at least - * been verfied that the length is within the buffer bounds (as has - * ext_supp_rates_ie). - */ - if (supp_rates_ie) { - len = supp_rates_ie[1]; - if (len == 0) - return -EINVAL; - - rates = supp_rates_ie + 2; - - for (i = 0; i < len; i++) { - uint8_t r = rates[i] & 0x7f; - - if (r <= max_rate && r > highest) - highest = r; - } - } - - /* Find highest rate in Extended Supported Rates IE */ - if (ext_supp_rates_ie) { - len = ext_supp_rates_ie[1]; - if (len == 0) - return -EINVAL; - - rates = ext_supp_rates_ie + 2; - - for (i = 0; i < len; i++) { - uint8_t r = rates[i] & 0x7f; - - if (r <= max_rate && r > highest) - highest = r; - } - } - - if (highest) - *data_rate = (highest / 2) * 1000000; - else - *data_rate = (max_rate / 2) * 1000000; - - return 0; -} - -static int ie_parse_ht_capability(struct ie_tlv_iter *iter, int32_t rssi, - uint64_t *data_rate) -{ - unsigned int len; - const uint8_t *data; - uint8_t ht_cap; - int i; - uint64_t highest_rate = 0; - bool support_40mhz; - bool short_gi_20mhz; - bool short_gi_40mhz; - - len = ie_tlv_iter_get_length(iter); - - if (len < 26) - return -EINVAL; - - if (ie_tlv_iter_get_tag(iter) != IE_TYPE_HT_CAPABILITIES) - return -EINVAL; - - data = ie_tlv_iter_get_data(iter); - - /* Parse out channel width set and short GI */ - ht_cap = l_get_u8(data++); - - support_40mhz = test_bit(&ht_cap, 1); - short_gi_20mhz = test_bit(&ht_cap, 5); - short_gi_40mhz = test_bit(&ht_cap, 6); - - data += 2; - - /* - * TODO: Support MCS values 32 - 76 - * - * The MCS values > 31 do not follow the same pattern since they use - * unequal modulation per spatial stream. These higher MCS values - * actually don't follow a pattern at all, since each stream can have a - * different modulation a higher MCS value does not mean higher - * throughput. For this reason these MCS indexes are left out. - */ - for (i = 31; i >= 0; i--) { - uint64_t drate; - - if (!test_bit(data, i)) - continue; - - if (!support_40mhz) - goto check_20; - - if (band_ofdm_rate(i % 8, OFDM_CHANNEL_WIDTH_40MHZ, - rssi, (i / 8) + 1, short_gi_40mhz, &drate)) { - *data_rate = drate; - return 0; - } - -check_20: - if (!band_ofdm_rate(i % 8, OFDM_CHANNEL_WIDTH_20MHZ, - rssi, (i / 8) + 1, short_gi_20mhz, &drate)) - continue; - - if (!support_40mhz) { - *data_rate = drate; - return 0; - } - - if (drate > highest_rate) - highest_rate = drate; - } - - if (!highest_rate) - return -ENOTSUP; - - *data_rate = highest_rate; - - return 0; -} - -static int ie_parse_ht_capability_from_data(const uint8_t *data, uint8_t len, - int32_t rssi, uint64_t *data_rate) -{ - struct ie_tlv_iter iter; - uint8_t tag; - - ie_tlv_iter_init(&iter, data, len); - - if (!ie_tlv_iter_next(&iter)) - return -EMSGSIZE; - - tag = ie_tlv_iter_get_tag(&iter); - - if (tag != IE_TYPE_HT_CAPABILITIES) - return -EPROTOTYPE; - - return ie_parse_ht_capability(&iter, rssi, data_rate); -} - -/* - * IEEE 802.11 - Table 9-250 - * - * For simplicity, we are ignoring the Extended BSS BW support, per NOTE 11: - * - * NOTE 11-A receiving STA in which dot11VHTExtendedNSSCapable is false will - * ignore the Extended NSS BW Support subfield and effectively evaluate this - * table only at the entries where Extended NSS BW Support is 0. - * - * This also allows us to group the 160/80+80 widths together, since they are - * the same when Extended NSS BW is zero. - */ -static const uint8_t vht_width_map[3][4] = { - [0] = { 1, 1, 1, 0 }, - [1] = { 1, 1, 1, 1 }, - [2] = { 1, 1, 1, 1 }, -}; - -static int ie_parse_vht_capability(struct ie_tlv_iter *vht_iter, - struct ie_tlv_iter *ht_iter, int32_t rssi, - uint64_t *data_rate) -{ - int width; - int bitoffset; - int mcs; - unsigned int nss; - unsigned int len; - const uint8_t *data; - uint8_t channel_width_set; - uint8_t rx_mcs_map[2]; - uint8_t tx_mcs_map[2]; - unsigned int max_rx_mcs = 0; - unsigned int rx_nss = 1; - unsigned int max_tx_mcs = 0; - unsigned int tx_nss = 1; - uint8_t ht_cap; - bool short_gi_20mhz; - bool short_gi_40mhz; - bool short_gi_80mhz; - bool short_gi_160mhz; - uint64_t highest_rate = 0; - - /* grab the short GI bits from the HT IE */ - len = ie_tlv_iter_get_length(ht_iter); - - if (len != 26) - return -EINVAL; - - data = ie_tlv_iter_get_data(ht_iter); - - ht_cap = l_get_u8(data); - - short_gi_20mhz = test_bit(&ht_cap, 5); - short_gi_40mhz = test_bit(&ht_cap, 6); - - /* now move onto VHT */ - len = ie_tlv_iter_get_length(vht_iter); - - if (len != 12) - return -EINVAL; - - data = ie_tlv_iter_get_data(vht_iter); - - channel_width_set = bit_field(*data, 2, 2); - short_gi_80mhz = bit_field(*data, 5, 1); - short_gi_160mhz = bit_field(*data, 6, 1); - - data += 4; - - rx_mcs_map[0] = *data++; - rx_mcs_map[1] = *data++; - - data += 2; - - tx_mcs_map[0] = *data++; - tx_mcs_map[1] = *data++; - - /* NSS->MCS map values are grouped in 2-bit values */ - for (bitoffset = 14; bitoffset >= 0; bitoffset -= 2) { - uint8_t rx_val = bit_field(rx_mcs_map[bitoffset / 8], - bitoffset % 8, 2); - uint8_t tx_val = bit_field(tx_mcs_map[bitoffset / 8], - bitoffset % 8, 2); - - /* - * 0 indicates support for MCS 0-7 - * 1 indicates support for MCS 0-8 - * 2 indicates support for MCS 0-9 - * - * Therefore 7 + rx/tx_val gives us our max MCS index. - */ - if (!max_rx_mcs && rx_val < 3) { - max_rx_mcs = 7 + rx_val; - rx_nss = (bitoffset / 2) + 1; - } - - if (!max_tx_mcs && tx_val < 3) { - max_tx_mcs = 7 + tx_val; - tx_nss = (bitoffset / 2) + 1; - } - - if (max_rx_mcs && max_tx_mcs) - break; - } - - if (!max_rx_mcs && !max_tx_mcs) - return -EINVAL; - - /* - * Now, using channel width, MCS index, and NSS we can determine the - * theoretical maximum data rate. We iterate through all possible - * combinations (width, MCS, NSS), saving the highest data rate we find. - * - * We could calculate a maximum data rate separately for TX/RX, but - * since this is only used for BSS ranking, the minimum between the - * two should be good enough. - */ - for (width = sizeof(vht_width_map[0]) - 1; width >= 0; width--) { - bool sgi = false; - - if (!vht_width_map[channel_width_set][width]) - continue; - - /* - * Consolidate short GI support into a single boolean, dependent - * on the channel width for this iteration. - */ - switch (width) { - case OFDM_CHANNEL_WIDTH_20MHZ: - sgi = short_gi_20mhz; - break; - case OFDM_CHANNEL_WIDTH_40MHZ: - sgi = short_gi_40mhz; - break; - case OFDM_CHANNEL_WIDTH_80MHZ: - sgi = short_gi_80mhz; - break; - case OFDM_CHANNEL_WIDTH_160MHZ: - sgi = short_gi_160mhz; - break; - } - - for (nss = minsize(rx_nss, tx_nss); nss > 0; nss--) { - /* NSS > 4 does not apply to 20/40MHz */ - if (width <= OFDM_CHANNEL_WIDTH_40MHZ && nss > 4) - continue; - - for (mcs = minsize(max_rx_mcs, max_tx_mcs); - mcs >= 0; mcs--) { - uint64_t drate; - - if (!band_ofdm_rate(mcs, width, rssi, - nss, sgi, &drate)) - continue; - - if (drate > highest_rate) - highest_rate = drate; - - /* Lower MCS index will only have lower rates */ - goto next_chanwidth; - } - } -next_chanwidth: ; /* empty statement */ - } - - if (highest_rate == 0) - return -ENOTSUP; - - *data_rate = highest_rate; - - return 0; -} - -static int ie_parse_vht_capability_from_data(const uint8_t *vht_ie, - size_t vht_len, const uint8_t *ht_ie, - size_t ht_len, int32_t rssi, - uint64_t *data_rate) -{ - struct ie_tlv_iter vht_iter; - struct ie_tlv_iter ht_iter; - uint8_t tag; - - ie_tlv_iter_init(&vht_iter, vht_ie, vht_len); - - if (!ie_tlv_iter_next(&vht_iter)) - return -EMSGSIZE; - - tag = ie_tlv_iter_get_tag(&vht_iter); - - if (tag != IE_TYPE_VHT_CAPABILITIES) - return -EPROTOTYPE; - - ie_tlv_iter_init(&ht_iter, ht_ie, ht_len); - - if (!ie_tlv_iter_next(&ht_iter)) - return -EMSGSIZE; - - tag = ie_tlv_iter_get_tag(&ht_iter); - - if (tag != IE_TYPE_HT_CAPABILITIES) - return -EPROTOTYPE; - - return ie_parse_vht_capability(&vht_iter, &ht_iter, rssi, data_rate); -} - -/* - * Calculates the theoretical maximum data rates out of the provided - * supported rates IE, HT IE, and VHT IE. All 3 parsing functions are allowed - * to return -ENOTSUP, which indicates that a data rate was not found given - * the provided data. This is not fatal, it most likely means our RSSI was too - * low. - */ -int ie_parse_data_rates(const uint8_t *supp_rates_ie, - const uint8_t *ext_supp_rates_ie, - const uint8_t *ht_ie, - const uint8_t *vht_ie, - int32_t rssi, - uint64_t *data_rate) -{ - int ret = -ENOTSUP; - uint64_t rate = 0; - - /* An RSSI this low will not yield any rate results */ - if (rssi < -82) - return -ENOTSUP; - - if (ht_ie && vht_ie) { - ret = ie_parse_vht_capability_from_data(vht_ie, IE_LEN(vht_ie), - ht_ie, IE_LEN(ht_ie), - rssi, &rate); - if (ret == 0) - goto done; - } - - if (ht_ie) { - ret = ie_parse_ht_capability_from_data(ht_ie, IE_LEN(ht_ie), - rssi, &rate); - if (ret == 0) - goto done; - } - - if (supp_rates_ie || ext_supp_rates_ie) { - ret = ie_parse_supported_rates_from_data(supp_rates_ie, - ext_supp_rates_ie, - rssi, &rate); - if (ret == 0) - goto done; - } - - return ret; - -done: - *data_rate = rate; - - return 0; -} - int ie_parse_mobility_domain(struct ie_tlv_iter *iter, uint16_t *mdid, bool *ft_over_ds, bool *resource_req) { diff --git a/src/ie.h b/src/ie.h index 5f7fa199..12961eca 100644 --- a/src/ie.h +++ b/src/ie.h @@ -484,13 +484,6 @@ int ie_parse_bss_load_from_data(const uint8_t *data, uint8_t len, uint8_t *out_channel_utilization, uint16_t *out_admission_capacity); -int ie_parse_data_rates(const uint8_t *supp_rates_ie, - const uint8_t *ext_supp_rates_ie, - const uint8_t *ht_ie, - const uint8_t *vht_ie, - int32_t rssi, - uint64_t *data_rate); - int ie_parse_mobility_domain(struct ie_tlv_iter *iter, uint16_t *mdid, bool *ft_over_ds, bool *resource_req); int ie_parse_mobility_domain_from_data(const uint8_t *data, uint8_t len,