From 4a58a871c46a589263f565ee7b755d5f3d695580 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 23 Jan 2020 14:51:58 +0100 Subject: [PATCH] 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 --- ...ix-WMM-queue-mapping-for-regulatory-.patch | 41 ++++++++++++++++ ...ix-regulatory-limits-for-wmm-cwmin-c.patch | 47 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 package/network/services/hostapd/patches/070-driver_nl80211-fix-WMM-queue-mapping-for-regulatory-.patch create mode 100644 package/network/services/hostapd/patches/071-driver_nl80211-fix-regulatory-limits-for-wmm-cwmin-c.patch diff --git a/package/network/services/hostapd/patches/070-driver_nl80211-fix-WMM-queue-mapping-for-regulatory-.patch b/package/network/services/hostapd/patches/070-driver_nl80211-fix-WMM-queue-mapping-for-regulatory-.patch new file mode 100644 index 0000000000..240411236a --- /dev/null +++ b/package/network/services/hostapd/patches/070-driver_nl80211-fix-WMM-queue-mapping-for-regulatory-.patch @@ -0,0 +1,41 @@ +From: Felix Fietkau +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 +--- + +--- 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 = diff --git a/package/network/services/hostapd/patches/071-driver_nl80211-fix-regulatory-limits-for-wmm-cwmin-c.patch b/package/network/services/hostapd/patches/071-driver_nl80211-fix-regulatory-limits-for-wmm-cwmin-c.patch new file mode 100644 index 0000000000..fe41e2b788 --- /dev/null +++ b/package/network/services/hostapd/patches/071-driver_nl80211-fix-regulatory-limits-for-wmm-cwmin-c.patch @@ -0,0 +1,47 @@ +From: Felix Fietkau +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 +--- + +--- 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 =