Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
548 changes: 526 additions & 22 deletions api/nl80211.h

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions include/iwinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ enum iwinfo_80211 {
IWINFO_80211_AC,
IWINFO_80211_AD,
IWINFO_80211_AX,
IWINFO_80211_BE,

/* keep last */
IWINFO_80211_COUNT
Expand All @@ -43,6 +44,7 @@ enum iwinfo_80211 {
#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];

Expand Down Expand Up @@ -192,6 +194,12 @@ enum iwinfo_htmode {
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
Expand All @@ -210,6 +218,12 @@ enum iwinfo_htmode {
#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];

Expand All @@ -222,10 +236,13 @@ struct iwinfo_rate_entry {
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;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change breaks the ABI which I'd ideally like to avoid. If I am not mistaken, there should be two bytes of padding at the end of the struct, so maybe place the high mhz bits after the mss field. Also put the is_eht bitfield member directly after is_he to ensure that it ends up in the same byte.

Updated structure layout could look like:

struct iwinfo_rate_entry {
	uint32_t rate;
	int8_t mcs;
	uint8_t is_40mhz:1;
	uint8_t is_short_gi:1;
	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_lo;
	uint8_t nss;
        uint8_t mhz_hi;
        uint8_t eht_gi;    
};

uint8_t nss;
uint8_t mhz_hi;
uint8_t eht_gi;
};

struct iwinfo_assoclist_entry {
Expand Down
1 change: 1 addition & 0 deletions include/iwinfo/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ size_t iwinfo_format_hwmodes(int modes, char *buf, size_t len);
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);
Expand Down
11 changes: 11 additions & 0 deletions iwinfo_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,17 @@ static char * format_assocrate(struct iwinfo_rate_entry *r)
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;
Expand Down
9 changes: 8 additions & 1 deletion iwinfo_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const char * const IWINFO_80211_NAMES[IWINFO_80211_COUNT] = {
"ac",
"ad",
"ax",
"be",
};

const char * const IWINFO_BAND_NAMES[IWINFO_BAND_COUNT] = {
Expand Down Expand Up @@ -92,7 +93,13 @@ const char * const IWINFO_HTMODE_NAMES[IWINFO_HTMODE_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] = {
Expand Down
15 changes: 13 additions & 2 deletions iwinfo_lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,10 @@ static void set_rateinfo(lua_State *L, struct iwinfo_rate_entry *r, bool rx)
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)
Expand All @@ -293,7 +296,7 @@ static void set_rateinfo(lua_State *L, struct iwinfo_rate_entry *r, bool rx)
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");
Expand All @@ -309,6 +312,11 @@ static void set_rateinfo(lua_State *L, struct iwinfo_rate_entry *r, bool rx)
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");
Expand Down Expand Up @@ -554,6 +562,9 @@ static int iwinfo_L_hwmodelist(lua_State *L, int (*func)(const char *, int *))
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;
}

Expand Down
61 changes: 55 additions & 6 deletions iwinfo_nl80211.c
Original file line number Diff line number Diff line change
Expand Up @@ -2047,7 +2047,17 @@ static void nl80211_parse_rateinfo(struct nlattr **ri,
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]);
Expand Down Expand Up @@ -2084,6 +2094,8 @@ static void nl80211_parse_rateinfo(struct nlattr **ri,
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;

Expand Down Expand Up @@ -3155,6 +3167,7 @@ struct nl80211_modes
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)
Expand Down Expand Up @@ -3183,6 +3196,22 @@ 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;
Expand Down Expand Up @@ -3252,6 +3281,8 @@ static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg)
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]);

Expand All @@ -3261,6 +3292,17 @@ static int nl80211_get_modelist_cb(struct nl_msg *msg, void *arg)
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);
}
}
}
}
Expand Down Expand Up @@ -3325,6 +3367,7 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
char *res, b[2] = { 0 };
int err;
bool he = false;
bool eht = false;

res = nl80211_phy2ifname(ifname);
*buf = 0;
Expand All @@ -3335,6 +3378,9 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
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)))
Expand All @@ -3343,38 +3389,41 @@ static int nl80211_get_htmode(const char *ifname, int *buf)
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
*buf = IWINFO_HTMODE_HT20;
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
*buf = IWINFO_HTMODE_HT40;
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:
Expand Down
20 changes: 18 additions & 2 deletions iwinfo_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ uint8_t iwinfo_ghz2band(uint32_t ghz)

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;

Expand Down Expand Up @@ -216,6 +216,22 @@ int iwinfo_htmode_is_he(int htmode)
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;
Expand Down