On Wed, Dec 09, 2015 at 12:20:33PM -0800, greearb@xxxxxxxxxxxxxxx wrote: > If user has configured TX antennas to be less than what > hardware advertises, the MCS reported by hardware will > be too large. So, remove MCS sets accordingly. The nl80211 related changes seem mostly reasonable, but I'm not sure I understood what exactly the HT/VHT changes were supposed to do. Why are they different? HT uses tx_ant & rx_ant and masks values from cap->supported_mcs_set[] until the highest 1 bit is found. VHT masks values separately for TX and RX and does this with |= 0x3 << i. Is that really correct? Should i be "i * 2"? Why is there difference in the configured bitmap checks (BIT(i) vs. BIT(i - 1) and different i > 0 vs. i >= 0 condition)? Is it correct to find the MSB 1 from the values instead of count the number of 1 bits (configured antennas)? I'm attaching the cleaned up patches from my work branch. Please provide any possible updated on top of these. -- Jouni Malinen PGP id EFC895FA
>From 06dbffa3c7be111e549a59dd5fad1fc8ba70b538 Mon Sep 17 00:00:00 2001 From: Ben Greear <greearb@xxxxxxxxxxxxxxx> Date: Wed, 9 Dec 2015 12:20:33 -0800 Subject: [PATCH 1/3] nl80211: Fetch antenna configuration This makes the current antenna mask configuration available to hostapd. Signed-off-by: Ben Greear <greearb@xxxxxxxxxxxxxxx> --- src/drivers/driver.h | 12 ++++++++++++ src/drivers/driver_nl80211_capa.c | 36 ++++++++++++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 6fd72c5..7dd4f9c 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -164,6 +164,18 @@ struct hostapd_hw_modes { u16 ht_capab; /** + * conf_tx_ant - Configured TX Antenna mask + * 0 means not reported by driver. + */ + u32 conf_tx_ant; + + /** + * conf_rx_ant - Configured RX Antenna mask + * 0 means not reported by driver + */ + u32 conf_rx_ant; + + /** * mcs_set - MCS (IEEE 802.11n) rate parameters */ u8 mcs_set[16]; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 8c3ba49..b28a494 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -989,6 +989,7 @@ struct phy_info_arg { struct hostapd_hw_modes *modes; int last_mode, last_chan_idx; int failed; + u32 conf_tx_ant, conf_rx_ant; }; static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa, @@ -1171,7 +1172,8 @@ static int phy_info_rates(struct hostapd_hw_modes *mode, struct nlattr *tb) } -static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band) +static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band, + struct hostapd_hw_modes **mode_used) { struct nlattr *tb_band[NL80211_BAND_ATTR_MAX + 1]; struct hostapd_hw_modes *mode; @@ -1210,6 +1212,8 @@ static int phy_info_band(struct phy_info_arg *phy_info, struct nlattr *nl_band) } else mode = &phy_info->modes[*(phy_info->num_modes) - 1]; + *mode_used = mode; + nla_parse(tb_band, NL80211_BAND_ATTR_MAX, nla_data(nl_band), nla_len(nl_band), NULL); @@ -1238,18 +1242,44 @@ static int phy_info_handler(struct nl_msg *msg, void *arg) struct phy_info_arg *phy_info = arg; struct nlattr *nl_band; int rem_band; + u32 tx, rx; nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), genlmsg_attrlen(gnlh, 0), NULL); + if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX] && + tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX]) { + tx = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX]); + rx = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX]); + wpa_printf(MSG_DEBUG, "Available Antennas: TX %#x RX %#x", + tx, rx); + } + + if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_TX] && + tb_msg[NL80211_ATTR_WIPHY_ANTENNA_RX]) { + tx = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_TX]); + rx = nla_get_u32(tb_msg[NL80211_ATTR_WIPHY_ANTENNA_RX]); + wpa_printf(MSG_DEBUG, "Configured Antennas: TX %#x RX %#x", + tx, rx); + phy_info->conf_tx_ant = tx; + phy_info->conf_rx_ant = rx; + } + if (!tb_msg[NL80211_ATTR_WIPHY_BANDS]) return NL_SKIP; nla_for_each_nested(nl_band, tb_msg[NL80211_ATTR_WIPHY_BANDS], rem_band) { - int res = phy_info_band(phy_info, nl_band); + struct hostapd_hw_modes *mode = NULL; + int res = phy_info_band(phy_info, nl_band, &mode); + if (res != NL_OK) return res; + + if (mode) { + mode->conf_tx_ant = phy_info->conf_tx_ant; + mode->conf_rx_ant = phy_info->conf_rx_ant; + } } return NL_SKIP; @@ -1652,6 +1682,8 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) .modes = NULL, .last_mode = -1, .failed = 0, + .conf_tx_ant = 0, + .conf_rx_ant = 0, }; *num_modes = 0; -- 1.9.1
>From 358854163b8f4a30058f4d4c21065c7d426a1c6f Mon Sep 17 00:00:00 2001 From: Ben Greear <greearb@xxxxxxxxxxxxxxx> Date: Wed, 9 Dec 2015 12:20:33 -0800 Subject: [PATCH 2/3] hostapd: Take configured antenna set into consideration If user has configured TX antennas to be less than what hardware advertises, the MCS reported by hardware will be too large. So, remove MCS sets accordingly. Signed-off-by: Ben Greear <greearb@xxxxxxxxxxxxxxx> --- src/ap/ieee802_11_ht.c | 25 +++++++++++++++++++++++++ src/ap/ieee802_11_vht.c | 23 +++++++++++++++++++++-- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c index 5eb1060..e75bda4 100644 --- a/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c @@ -25,6 +25,7 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) { struct ieee80211_ht_capabilities *cap; u8 *pos = eid; + int i; if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode || hapd->conf->disable_11n) @@ -40,6 +41,30 @@ u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set, 16); + /* + * Disable all MCS rates that are out of the configured nss (antenna) + * range. + */ + if (hapd->iface->current_mode->conf_tx_ant && + hapd->iface->current_mode->conf_rx_ant) { + int msk; + + msk = hapd->iface->current_mode->conf_tx_ant & + hapd->iface->current_mode->conf_rx_ant; + for (i = 7; i >= 0; i--) { + if (msk & BIT(i)) + break; + if (!cap->supported_mcs_set[i]) + continue; + wpa_printf(MSG_DEBUG, + "Decreasing MCS set due to configured antennas: conf-tx-ant: 0x%x conf-rx-ant: 0x%x mcs-set for nss: %d", + hapd->iface->current_mode->conf_tx_ant, + hapd->iface->current_mode->conf_rx_ant, + i + 1); + cap->supported_mcs_set[i] = 0; + } + } + /* TODO: ht_extended_capabilities (now fully disabled) */ /* TODO: tx_bf_capability_info (now fully disabled) */ /* TODO: asel_capabilities (now fully disabled) */ diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index 3236016..99787e9 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -25,14 +25,13 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid) struct ieee80211_vht_capabilities *cap; struct hostapd_hw_modes *mode = hapd->iface->current_mode; u8 *pos = eid; + int i; if (!mode) return eid; if (mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->conf->vendor_vht && mode->vht_capab == 0 && hapd->iface->hw_features) { - int i; - for (i = 0; i < hapd->iface->num_hw_features; i++) { if (hapd->iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211A) { @@ -53,6 +52,26 @@ u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid) /* Supported MCS set comes from hw */ os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8); + /* + * Disable all MCS rates that are out of the configured nss (antenna) + * range. + */ + if (mode->conf_tx_ant) { + for (i = 7; i > 0; i--) { + if (mode->conf_tx_ant & BIT(i - 1)) + break; + cap->vht_supported_mcs_set.tx_map |= (0x3 << i); + } + } + + if (mode->conf_rx_ant) { + for (i = 7; i > 0; i--) { + if (mode->conf_rx_ant & BIT(i - 1)) + break; + cap->vht_supported_mcs_set.rx_map |= (0x3 << i); + } + } + pos += sizeof(*cap); return pos; -- 1.9.1
>From 520923ac1289d37c17bcb854113c26c03e9915bc Mon Sep 17 00:00:00 2001 From: Jouni Malinen <j@xxxxx> Date: Sun, 20 Dec 2015 21:42:46 +0200 Subject: [PATCH 3/3] tests: HT/VHT and antenna configuration Signed-off-by: Jouni Malinen <j@xxxxx> --- tests/hwsim/test_ap_ht.py | 27 +++++++++++++++++++++++++++ tests/hwsim/test_ap_vht.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index 001e722..0922e3c 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -1128,3 +1128,30 @@ def test_ap_ht40_5ghz_invalid_pair(dev, apdev): raise Exception("AP setup failure timed out") finally: subprocess.call(['iw', 'reg', 'set', '00']) + +def test_ap_ht_antenna_config(dev, apdev): + """HT and antenna configuration""" + hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" }) + phy = hapd.get_driver_status_field("phyname") + hapd.disable() + + try: + subprocess.call(['iw', 'phy', phy, 'set', 'antenna', '0x1']) + hapd = None + params = { "ssid": "ht", + "country_code": "FI", + "hw_mode": "a", + "channel": "36", + "ieee80211n": "1" } + hapd = hostapd.add_ap(apdev[0]['ifname'], params) + bssid = apdev[0]['bssid'] + + dev[0].connect("ht", key_mgmt="NONE", scan_freq="5180") + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + dev[0].request("DISCONNECT") + if hapd: + hapd.request("DISABLE") + subprocess.call(['iw', 'reg', 'set', '00']) + dev[0].flush_scan_cache() + subprocess.call(['iw', 'phy', phy, 'set', 'antenna', 'all']) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index 38ecd4e..1fe539a 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -616,3 +616,39 @@ def test_ap_vht80_pwr_constraint(dev, apdev): hapd.request("DISABLE") subprocess.call(['iw', 'reg', 'set', '00']) dev[0].flush_scan_cache() + +def test_ap_vht80_antenna_config(dev, apdev): + """VHT with 80 MHz channel width and antenna configuration""" + hapd = hostapd.add_ap(apdev[0]['ifname'], { "ssid": "open" }) + phy = hapd.get_driver_status_field("phyname") + hapd.disable() + + try: + subprocess.call(['iw', 'phy', phy, 'set', 'antenna', '0x3']) + hapd = None + params = { "ssid": "vht", + "country_code": "FI", + "hw_mode": "a", + "channel": "36", + "ht_capab": "[HT40+]", + "ieee80211n": "1", + "ieee80211ac": "1", + "vht_oper_chwidth": "1", + "vht_oper_centr_freq_seg0_idx": "42" } + hapd = hostapd.add_ap(apdev[0]['ifname'], params) + bssid = apdev[0]['bssid'] + + dev[0].connect("vht", key_mgmt="NONE", scan_freq="5180") + hwsim_utils.test_connectivity(dev[0], hapd) + except Exception, e: + if isinstance(e, Exception) and str(e) == "AP startup failed": + if not vht_supported(): + raise HwsimSkip("80 MHz channel not supported in regulatory information") + raise + finally: + dev[0].request("DISCONNECT") + if hapd: + hapd.request("DISABLE") + subprocess.call(['iw', 'reg', 'set', '00']) + dev[0].flush_scan_cache() + subprocess.call(['iw', 'phy', phy, 'set', 'antenna', 'all']) -- 1.9.1
_______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap