hostapd: fix faulty WMM IE parameters with ETSI regulatory domains

hostapd sets minimum values for CWmin/CWmax/AIFS and maximum for TXOP.
The code for applying those values had a few bugs leading to bogus values,
which caused significant latency and packet loss.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
master
Felix Fietkau 2020-01-23 14:51:58 +01:00
parent 6fe31abc5a
commit c07f6e8659
2 changed files with 88 additions and 0 deletions

View File

@ -0,0 +1,41 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 23 Jan 2020 13:50:47 +0100
Subject: [PATCH] driver_nl80211: fix WMM queue mapping for regulatory
limit
nl80211 uses a different queue mapping from hostap, so AC indexes need to
be converted.
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1403,6 +1403,12 @@ static void phy_info_freq(struct hostapd
[NL80211_WMMR_AIFSN] = { .type = NLA_U8 },
[NL80211_WMMR_TXOP] = { .type = NLA_U16 },
};
+ static const u8 wmm_map[4] = {
+ [NL80211_AC_BE] = WMM_AC_BE,
+ [NL80211_AC_BK] = WMM_AC_BK,
+ [NL80211_AC_VI] = WMM_AC_VI,
+ [NL80211_AC_VO] = WMM_AC_VO,
+ };
struct nlattr *nl_wmm;
struct nlattr *tb_wmm[NL80211_WMMR_MAX + 1];
int rem_wmm, ac, count = 0;
@@ -1424,12 +1430,13 @@ static void phy_info_freq(struct hostapd
return;
}
ac = nl_wmm->nla_type;
- if (ac < 0 || ac >= WMM_AC_NUM) {
+ if (ac >= ARRAY_SIZE(wmm_map)) {
wpa_printf(MSG_DEBUG,
"nl80211: Invalid AC value %d", ac);
return;
}
+ ac = wmm_map[ac];
chan->wmm_rules[ac].min_cwmin =
nla_get_u16(tb_wmm[NL80211_WMMR_CW_MIN]);
chan->wmm_rules[ac].min_cwmax =

View File

@ -0,0 +1,47 @@
From: Felix Fietkau <nbd@nbd.name>
Date: Thu, 23 Jan 2020 14:10:20 +0100
Subject: [PATCH] driver_nl80211: fix regulatory limits for wmm cwmin/cwmax
values
The internal WMM AC parameters use just the exponent of the CW value, while
nl80211 reports the full CW value.
This led to completely bogus CWmin/CWmax values in the WMM IE when a regulatory
limit was present. Fix this by converting the value to the exponent before
passing it on
Signed-off-by: Felix Fietkau <nbd@nbd.name>
---
--- a/src/drivers/driver_nl80211_capa.c
+++ b/src/drivers/driver_nl80211_capa.c
@@ -1336,6 +1336,18 @@ static void phy_info_vht_capa(struct hos
}
}
+static inline int cw2ecw(unsigned int cw)
+{
+ int bit;
+
+ if (cw == 0)
+ return 0;
+
+ for (bit = 1; cw != 1; bit++)
+ cw >>= 1;
+
+ return bit;
+}
static void phy_info_freq(struct hostapd_hw_modes *mode,
struct hostapd_channel_data *chan,
@@ -1438,9 +1450,9 @@ static void phy_info_freq(struct hostapd
ac = wmm_map[ac];
chan->wmm_rules[ac].min_cwmin =
- nla_get_u16(tb_wmm[NL80211_WMMR_CW_MIN]);
+ cw2ecw(nla_get_u16(tb_wmm[NL80211_WMMR_CW_MIN]));
chan->wmm_rules[ac].min_cwmax =
- nla_get_u16(tb_wmm[NL80211_WMMR_CW_MAX]);
+ cw2ecw(nla_get_u16(tb_wmm[NL80211_WMMR_CW_MAX]));
chan->wmm_rules[ac].min_aifs =
nla_get_u8(tb_wmm[NL80211_WMMR_AIFSN]);
chan->wmm_rules[ac].max_txop =