IWINFO_80211_AC,
IWINFO_80211_AD,
IWINFO_80211_AX,
+ IWINFO_80211_BE,
/* keep last */
IWINFO_80211_COUNT
#define IWINFO_80211_AC (1 << IWINFO_80211_AC)
#define IWINFO_80211_AD (1 << IWINFO_80211_AD)
#define IWINFO_80211_AX (1 << IWINFO_80211_AX)
+#define IWINFO_80211_BE (1 << IWINFO_80211_BE)
extern const char * const IWINFO_80211_NAMES[IWINFO_80211_COUNT];
IWINFO_HTMODE_HE80,
IWINFO_HTMODE_HE80_80,
IWINFO_HTMODE_HE160,
+ IWINFO_HTMODE_EHT20,
+ IWINFO_HTMODE_EHT40,
+ IWINFO_HTMODE_EHT80,
+ IWINFO_HTMODE_EHT80_80,
+ IWINFO_HTMODE_EHT160,
+ IWINFO_HTMODE_EHT320,
/* keep last */
IWINFO_HTMODE_COUNT
#define IWINFO_HTMODE_HE80 (1 << IWINFO_HTMODE_HE80)
#define IWINFO_HTMODE_HE80_80 (1 << IWINFO_HTMODE_HE80_80)
#define IWINFO_HTMODE_HE160 (1 << IWINFO_HTMODE_HE160)
+#define IWINFO_HTMODE_EHT20 (1 << IWINFO_HTMODE_EHT20)
+#define IWINFO_HTMODE_EHT40 (1 << IWINFO_HTMODE_EHT40)
+#define IWINFO_HTMODE_EHT80 (1 << IWINFO_HTMODE_EHT80)
+#define IWINFO_HTMODE_EHT80_80 (1 << IWINFO_HTMODE_EHT80_80)
+#define IWINFO_HTMODE_EHT160 (1 << IWINFO_HTMODE_EHT160)
+#define IWINFO_HTMODE_EHT320 (1 << IWINFO_HTMODE_EHT320)
extern const char * const IWINFO_HTMODE_NAMES[IWINFO_HTMODE_COUNT];
uint8_t is_ht:1;
uint8_t is_vht:1;
uint8_t is_he:1;
+ uint8_t is_eht:1;
uint8_t he_gi;
uint8_t he_dcm;
uint8_t mhz;
uint8_t nss;
+ uint8_t mhz_hi;
+ uint8_t eht_gi;
};
struct iwinfo_assoclist_entry {
int iwinfo_htmode_is_ht(int htmode);
int iwinfo_htmode_is_vht(int htmode);
int iwinfo_htmode_is_he(int htmode);
+int iwinfo_htmode_is_eht(int htmode);
int iwinfo_ifup(const char *ifname);
int iwinfo_ifdown(const char *ifname);
p += snprintf(p, l, ", HE-DCM %d", r->he_dcm);
l = sizeof(buf) - (p - buf);
}
+ else if (r->is_eht)
+ {
+ p += snprintf(p, l, ", EHT-MCS %d, %dMHz", r->mcs, r->mhz_hi * 256 + r->mhz);
+ l = sizeof(buf) - (p - buf);
+
+ p += snprintf(p, l, ", EHT-NSS %d", r->nss);
+ l = sizeof(buf) - (p - buf);
+
+ p += snprintf(p, l, ", EHT-GI %d", r->eht_gi);
+ l = sizeof(buf) - (p - buf);
+ }
}
return buf;
"ac",
"ad",
"ax",
+ "be",
};
const char * const IWINFO_BAND_NAMES[IWINFO_BAND_COUNT] = {
"HE40",
"HE80",
"HE80+80",
- "HE160"
+ "HE160",
+ "EHT20",
+ "EHT40",
+ "EHT80",
+ "EHT80+80",
+ "EHT160",
+ "EHT320",
};
const char * const IWINFO_FREQ_FLAG_NAMES[IWINFO_FREQ_FLAG_COUNT] = {
lua_pushboolean(L, r->is_he);
lua_setfield(L, -2, rx ? "rx_he" : "tx_he");
- lua_pushnumber(L, r->mhz);
+ lua_pushboolean(L, r->is_eht);
+ lua_setfield(L, -2, rx ? "rx_eht" : "tx_eht");
+
+ lua_pushnumber(L, r->mhz_hi * 256 + r->mhz);
lua_setfield(L, -2, rx ? "rx_mhz" : "tx_mhz");
if (r->is_ht)
lua_pushboolean(L, r->is_short_gi);
lua_setfield(L, -2, rx ? "rx_short_gi" : "tx_short_gi");
}
- else if (r->is_vht || r->is_he)
+ else if (r->is_vht || r->is_he | r->is_eht)
{
lua_pushnumber(L, r->mcs);
lua_setfield(L, -2, rx ? "rx_mcs" : "tx_mcs");
lua_setfield(L, -2, rx ? "rx_he_dcm" : "tx_he_dcm");
}
+ if (r->is_eht) {
+ lua_pushnumber(L, r->eht_gi);
+ lua_setfield(L, -2, rx ? "rx_eht_gi" : "tx_eht_gi");
+ }
+
if (r->is_vht) {
lua_pushboolean(L, r->is_short_gi);
lua_setfield(L, -2, rx ? "rx_short_gi" : "tx_short_gi");
lua_pushboolean(L, hwmodes & IWINFO_80211_AX);
lua_setfield(L, -2, "ax");
+ lua_pushboolean(L, hwmodes & IWINFO_80211_BE);
+ lua_setfield(L, -2, "be");
+
return 1;
}
else if (ri[NL80211_RATE_INFO_BITRATE])
re->rate = nla_get_u16(ri[NL80211_RATE_INFO_BITRATE]) * 100;
- if (ri[NL80211_RATE_INFO_HE_MCS])
+ if (ri[NL80211_RATE_INFO_EHT_MCS])
+ {
+ re->is_eht = 1;
+ re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_EHT_MCS]);
+
+ if (ri[NL80211_RATE_INFO_EHT_NSS])
+ re->nss = nla_get_u8(ri[NL80211_RATE_INFO_EHT_NSS]);
+ if (ri[NL80211_RATE_INFO_EHT_GI])
+ re->eht_gi = nla_get_u8(ri[NL80211_RATE_INFO_EHT_GI]);
+ }
+ else if (ri[NL80211_RATE_INFO_HE_MCS])
{
re->is_he = 1;
re->mcs = nla_get_u8(ri[NL80211_RATE_INFO_HE_MCS]);
else if (ri[NL80211_RATE_INFO_80P80_MHZ_WIDTH] ||
ri[NL80211_RATE_INFO_160_MHZ_WIDTH])
re->mhz = 160;
+ else if (ri[NL80211_RATE_INFO_320_MHZ_WIDTH])
+ re->mhz_hi = 320 / 256, re->mhz = 320 % 256;
else
re->mhz = 20;
uint16_t nl_ht;
uint32_t nl_vht;
uint16_t he_phy_cap[6];
+ uint16_t eht_phy_cap[9];
};
static void nl80211_eval_modelist(struct nl80211_modes *m)
m->ht |= IWINFO_HTMODE_HE160 | IWINFO_HTMODE_HE80_80;
}
+ if (m->eht_phy_cap[0] != 0) {
+ m->hw |= IWINFO_80211_BE;
+ m->ht |= IWINFO_HTMODE_EHT20;
+
+ if (m->he_phy_cap[0] & BIT(9))
+ m->ht |= IWINFO_HTMODE_EHT40;
+ if (m->he_phy_cap[0] & BIT(10))
+ m->ht |= IWINFO_HTMODE_EHT40 | IWINFO_HTMODE_EHT80;
+ if (m->he_phy_cap[0] & BIT(11))
+ m->ht |= IWINFO_HTMODE_EHT160;
+ if (m->he_phy_cap[0] & BIT(12))
+ m->ht |= IWINFO_HTMODE_EHT160 | IWINFO_HTMODE_EHT80_80;
+ if ((m->eht_phy_cap[0] & BIT(9)) && (m->bands & IWINFO_BAND_6))
+ m->ht |= IWINFO_HTMODE_EHT320;
+ }
+
if (m->bands & IWINFO_BAND_24)
{
m->hw |= IWINFO_80211_B;
nla_for_each_nested(nl_iftype, bands[NL80211_BAND_ATTR_IFTYPE_DATA], rem_band) {
nla_parse(tb, NL80211_BAND_IFTYPE_ATTR_MAX,
nla_data(nl_iftype), nla_len(nl_iftype), NULL);
+
+ // HE
if (tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]) {
len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]);
nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY]),
len);
}
+
+ // EHT
+ if (tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]) {
+ len = nla_len(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]);
+
+ if (len > sizeof(m->eht_phy_cap) - 1)
+ len = sizeof(m->eht_phy_cap) - 1;
+ memcpy(&((uint8_t *)m->eht_phy_cap)[1],
+ nla_data(tb[NL80211_BAND_IFTYPE_ATTR_EHT_CAP_PHY]),
+ len);
+ }
}
}
}
char *res, b[2] = { 0 };
int err;
bool he = false;
+ bool eht = false;
res = nl80211_phy2ifname(ifname);
*buf = 0;
if (err)
return -1;
+ if (nl80211_hostapd_query(res ? res : ifname, "ieee80211be", b, sizeof(b)))
+ eht = b[0] == '1';
+
if (nl80211_hostapd_query(res ? res : ifname, "ieee80211ax", b, sizeof(b)))
he = b[0] == '1';
else if (nl80211_wpactl_query(res ? res : ifname, "wifi_generation", b, sizeof(b)))
switch (chn.width) {
case NL80211_CHAN_WIDTH_20:
if (he)
- *buf = IWINFO_HTMODE_HE20;
+ *buf = (eht == true) ? IWINFO_HTMODE_EHT20 : IWINFO_HTMODE_HE20;
else if (chn.mode == -1)
*buf = IWINFO_HTMODE_VHT20;
else
break;
case NL80211_CHAN_WIDTH_40:
if (he)
- *buf = IWINFO_HTMODE_HE40;
+ *buf = (eht == true) ? IWINFO_HTMODE_EHT40 : IWINFO_HTMODE_HE40;
else if (chn.mode == -1)
*buf = IWINFO_HTMODE_VHT40;
else
break;
case NL80211_CHAN_WIDTH_80:
if (he)
- *buf = IWINFO_HTMODE_HE80;
+ *buf = (eht == true) ? IWINFO_HTMODE_EHT80 : IWINFO_HTMODE_HE80;
else
*buf = IWINFO_HTMODE_VHT80;
break;
case NL80211_CHAN_WIDTH_80P80:
if (he)
- *buf = IWINFO_HTMODE_HE80_80;
+ *buf = (eht == true) ? IWINFO_HTMODE_EHT80_80 : IWINFO_HTMODE_HE80_80;
else
*buf = IWINFO_HTMODE_VHT80_80;
break;
case NL80211_CHAN_WIDTH_160:
if (he)
- *buf = IWINFO_HTMODE_HE160;
+ *buf = (eht == true) ? IWINFO_HTMODE_EHT160 : IWINFO_HTMODE_HE160;
else
*buf = IWINFO_HTMODE_VHT160;
break;
+ case NL80211_CHAN_WIDTH_320:
+ *buf = IWINFO_HTMODE_EHT320;
+ break;
case NL80211_CHAN_WIDTH_5:
case NL80211_CHAN_WIDTH_10:
case NL80211_CHAN_WIDTH_20_NOHT:
size_t iwinfo_format_hwmodes(int modes, char *buf, size_t len)
{
- // bit numbers as per IWINFO_80211_*: ad ac ax a b g n
- const int order[IWINFO_80211_COUNT] = { 5, 4, 6, 0, 1, 2, 3 };
+ // bit numbers as per IWINFO_80211_*: ad ac ax a b be g n
+ const int order[IWINFO_80211_COUNT] = { 5, 4, 6, 0, 1, 7, 2, 3 };
size_t res = 0;
int i;
return 0;
}
+int iwinfo_htmode_is_eht(int htmode)
+{
+ switch (htmode)
+ {
+ case IWINFO_HTMODE_EHT20:
+ case IWINFO_HTMODE_EHT40:
+ case IWINFO_HTMODE_EHT80:
+ case IWINFO_HTMODE_EHT80_80:
+ case IWINFO_HTMODE_EHT160:
+ case IWINFO_HTMODE_EHT320:
+ return 1;
+ }
+
+ return 0;
+}
+
int iwinfo_ifup(const char *ifname)
{
struct ifreq ifr;