openwrt/package/network/utils/iw/patches/300-wiphy_radios.patch
Felix Fietkau 5c1ee08e2d iw: add multi-radio support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
2024-10-22 14:40:43 +02:00

253 lines
8.0 KiB
Diff

--- a/info.c
+++ b/info.c
@@ -295,6 +295,151 @@ static void print_pmsr_capabilities(stru
}
}
+static void print_interface_combinations(struct nlattr *ifcomb, bool radio)
+{
+ const char *indent = radio ? "\t" : "";
+ struct nlattr *nl_combi;
+ bool have_combinations = false;
+ int rem;
+
+ nla_for_each_nested(nl_combi, ifcomb, rem) {
+ static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
+ [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
+ [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
+ [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
+ [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
+ [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
+ };
+ struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
+ static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
+ [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
+ [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
+ };
+ struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
+ struct nlattr *nl_limit;
+ int err, rem_limit;
+ bool comma = false;
+
+ if (radio && nla_type(nl_combi) !=
+ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION)
+ continue;
+
+ if (!have_combinations) {
+ printf("\t%svalid interface combinations:\n", indent);
+ have_combinations = true;
+ }
+
+ printf("\t\t%s * ", indent);
+
+ err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
+ nl_combi, iface_combination_policy);
+ if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
+ !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
+ !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
+ printf(" <failed to parse>\n");
+ goto broken_combination;
+ }
+
+ nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) {
+ err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
+ nl_limit, iface_limit_policy);
+ if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) {
+ printf("<failed to parse>\n");
+ goto broken_combination;
+ }
+
+ if (comma)
+ printf(", ");
+ comma = true;
+ printf("#{ ");
+ print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]);
+ printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]));
+ }
+ printf(",\n\t\t%s ", indent);
+
+ printf("total <= %d, #channels <= %d%s",
+ nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]),
+ nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]),
+ tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ?
+ ", STA/AP BI must match" : "");
+ if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) {
+ unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]);
+
+ if (widths) {
+ int width;
+ bool first = true;
+
+ printf(", radar detect widths: {");
+ for (width = 0; width < 32; width++)
+ if (widths & (1 << width)) {
+ printf("%s %s",
+ first ? "":",",
+ channel_width_name(width));
+ first = false;
+ }
+ printf(" }\n");
+ }
+ }
+ printf("\n");
+broken_combination:
+ ;
+ }
+
+ if (!have_combinations)
+ printf("\t%sinterface combinations are not supported\n", indent);
+}
+
+static void print_radio_freq(struct nlattr *freqs)
+{
+ struct nlattr *freq;
+ int rem;
+
+ nla_for_each_nested(freq, freqs, rem) {
+ static struct nla_policy freq_policy[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1] = {
+ [NL80211_WIPHY_RADIO_FREQ_ATTR_START] = { .type = NLA_U32 },
+ [NL80211_WIPHY_RADIO_FREQ_ATTR_END] = { .type = NLA_U32 },
+ };
+ struct nlattr *tb[NL80211_WIPHY_RADIO_FREQ_ATTR_MAX + 1];
+ uint32_t start, end;
+
+ if (nla_type(freq) != NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE)
+ continue;
+
+ if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1,
+ freq, freq_policy) ||
+ !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START] ||
+ !tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END])
+ continue;
+
+ start = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_START]);
+ end = nla_get_u32(tb[NL80211_WIPHY_RADIO_FREQ_ATTR_END]);
+
+ printf("\t\tfreq range: %.1f MHz - %.1f MHz\n", (float)start / 1000, (float)end / 1000);
+ }
+}
+
+static void print_radios(struct nlattr *radios)
+{
+ struct nlattr *radio;
+ int rem, idx = 0;
+
+ nla_for_each_nested(radio, radios, rem) {
+ static struct nla_policy radio_policy[NL80211_WIPHY_RADIO_ATTR_MAX + 1] = {
+ [NL80211_WIPHY_RADIO_ATTR_INDEX] = { .type = NLA_U32 },
+ };
+ struct nlattr *tb[NL80211_WIPHY_RADIO_ATTR_MAX + 1];
+
+ if (nla_parse_nested(tb, NL80211_WIPHY_RADIO_ATTR_MAX + 1,
+ radio, radio_policy) ||
+ !tb[NL80211_WIPHY_RADIO_ATTR_INDEX])
+ continue;
+
+ printf("\twiphy radio %d:\n", nla_get_u32(tb[NL80211_WIPHY_RADIO_ATTR_INDEX]));
+ print_radio_freq(radio);
+ print_interface_combinations(radio, true);
+ }
+}
+
static int print_phy_handler(struct nl_msg *msg, void *arg)
{
struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
@@ -565,93 +710,11 @@ next:
"\t\t", tb_msg[NL80211_ATTR_SOFTWARE_IFTYPES]);
#endif
- if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) {
- struct nlattr *nl_combi;
- int rem_combi;
- bool have_combinations = false;
-
- nla_for_each_nested(nl_combi, tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], rem_combi) {
- static struct nla_policy iface_combination_policy[NUM_NL80211_IFACE_COMB] = {
- [NL80211_IFACE_COMB_LIMITS] = { .type = NLA_NESTED },
- [NL80211_IFACE_COMB_MAXNUM] = { .type = NLA_U32 },
- [NL80211_IFACE_COMB_STA_AP_BI_MATCH] = { .type = NLA_FLAG },
- [NL80211_IFACE_COMB_NUM_CHANNELS] = { .type = NLA_U32 },
- [NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS] = { .type = NLA_U32 },
- };
- struct nlattr *tb_comb[NUM_NL80211_IFACE_COMB];
- static struct nla_policy iface_limit_policy[NUM_NL80211_IFACE_LIMIT] = {
- [NL80211_IFACE_LIMIT_TYPES] = { .type = NLA_NESTED },
- [NL80211_IFACE_LIMIT_MAX] = { .type = NLA_U32 },
- };
- struct nlattr *tb_limit[NUM_NL80211_IFACE_LIMIT];
- struct nlattr *nl_limit;
- int err, rem_limit;
- bool comma = false;
-
- if (!have_combinations) {
- printf("\tvalid interface combinations:\n");
- have_combinations = true;
- }
-
- printf("\t\t * ");
+ if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS])
+ print_interface_combinations(tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS], false);
- err = nla_parse_nested(tb_comb, MAX_NL80211_IFACE_COMB,
- nl_combi, iface_combination_policy);
- if (err || !tb_comb[NL80211_IFACE_COMB_LIMITS] ||
- !tb_comb[NL80211_IFACE_COMB_MAXNUM] ||
- !tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]) {
- printf(" <failed to parse>\n");
- goto broken_combination;
- }
-
- nla_for_each_nested(nl_limit, tb_comb[NL80211_IFACE_COMB_LIMITS], rem_limit) {
- err = nla_parse_nested(tb_limit, MAX_NL80211_IFACE_LIMIT,
- nl_limit, iface_limit_policy);
- if (err || !tb_limit[NL80211_IFACE_LIMIT_TYPES]) {
- printf("<failed to parse>\n");
- goto broken_combination;
- }
-
- if (comma)
- printf(", ");
- comma = true;
- printf("#{ ");
- print_iftype_line(tb_limit[NL80211_IFACE_LIMIT_TYPES]);
- printf(" } <= %u", nla_get_u32(tb_limit[NL80211_IFACE_LIMIT_MAX]));
- }
- printf(",\n\t\t ");
-
- printf("total <= %d, #channels <= %d%s",
- nla_get_u32(tb_comb[NL80211_IFACE_COMB_MAXNUM]),
- nla_get_u32(tb_comb[NL80211_IFACE_COMB_NUM_CHANNELS]),
- tb_comb[NL80211_IFACE_COMB_STA_AP_BI_MATCH] ?
- ", STA/AP BI must match" : "");
- if (tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]) {
- unsigned long widths = nla_get_u32(tb_comb[NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS]);
-
- if (widths) {
- int width;
- bool first = true;
-
- printf(", radar detect widths: {");
- for (width = 0; width < 32; width++)
- if (widths & (1 << width)) {
- printf("%s %s",
- first ? "":",",
- channel_width_name(width));
- first = false;
- }
- printf(" }\n");
- }
- }
- printf("\n");
-broken_combination:
- ;
- }
-
- if (!have_combinations)
- printf("\tinterface combinations are not supported\n");
- }
+ if (tb_msg[NL80211_ATTR_WIPHY_RADIOS])
+ print_radios(tb_msg[NL80211_ATTR_WIPHY_RADIOS]);
#ifdef IW_FULL
if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) {