mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-18 02:40:19 +00:00
iw: add multi-radio support
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
parent
5db27664bc
commit
5c1ee08e2d
98
package/network/utils/iw/patches/001-nl80211_h_sync.patch
Normal file
98
package/network/utils/iw/patches/001-nl80211_h_sync.patch
Normal file
@ -0,0 +1,98 @@
|
||||
--- a/nl80211.h
|
||||
+++ b/nl80211.h
|
||||
@@ -2061,6 +2061,10 @@ enum nl80211_commands {
|
||||
* @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported
|
||||
* interface combinations. In each nested item, it contains attributes
|
||||
* defined in &enum nl80211_if_combination_attrs.
|
||||
+ * If the wiphy uses multiple radios (@NL80211_ATTR_WIPHY_RADIOS is set),
|
||||
+ * this attribute contains the interface combinations of the first radio.
|
||||
+ * See @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS for the global wiphy
|
||||
+ * combinations for the sum of all radios.
|
||||
* @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like
|
||||
* %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that
|
||||
* are managed in software: interfaces of these types aren't subject to
|
||||
@@ -2856,6 +2860,17 @@ enum nl80211_commands {
|
||||
* %NL80211_CMD_ASSOCIATE indicating the SPP A-MSDUs
|
||||
* are used on this connection
|
||||
*
|
||||
+ * @NL80211_ATTR_WIPHY_RADIOS: Nested attribute describing physical radios
|
||||
+ * belonging to this wiphy. See &enum nl80211_wiphy_radio_attrs.
|
||||
+ *
|
||||
+ * @NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS: Nested attribute listing the
|
||||
+ * supported interface combinations for all radios combined. In each
|
||||
+ * nested item, it contains attributes defined in
|
||||
+ * &enum nl80211_if_combination_attrs.
|
||||
+ *
|
||||
+ * @NL80211_ATTR_VIF_RADIO_MASK: Bitmask of allowed radios (u32).
|
||||
+ * A value of 0 means all radios.
|
||||
+ *
|
||||
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
|
||||
* @NL80211_ATTR_MAX: highest attribute number currently defined
|
||||
* @__NL80211_ATTR_AFTER_LAST: internal use
|
||||
@@ -3401,6 +3416,11 @@ enum nl80211_attrs {
|
||||
|
||||
NL80211_ATTR_ASSOC_SPP_AMSDU,
|
||||
|
||||
+ NL80211_ATTR_WIPHY_RADIOS,
|
||||
+ NL80211_ATTR_WIPHY_INTERFACE_COMBINATIONS,
|
||||
+
|
||||
+ NL80211_ATTR_VIF_RADIO_MASK,
|
||||
+
|
||||
/* add attributes here, update the policy in nl80211.c */
|
||||
|
||||
__NL80211_ATTR_AFTER_LAST,
|
||||
@@ -7987,4 +8007,54 @@ enum nl80211_ap_settings_flags {
|
||||
NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1,
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * enum nl80211_wiphy_radio_attrs - wiphy radio attributes
|
||||
+ *
|
||||
+ * @__NL80211_WIPHY_RADIO_ATTR_INVALID: Invalid
|
||||
+ *
|
||||
+ * @NL80211_WIPHY_RADIO_ATTR_INDEX: Index of this radio (u32)
|
||||
+ * @NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE: Frequency range supported by this
|
||||
+ * radio. Attribute may be present multiple times.
|
||||
+ * @NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION: Supported interface
|
||||
+ * combination for this radio. Attribute may be present multiple times
|
||||
+ * and contains attributes defined in &enum nl80211_if_combination_attrs.
|
||||
+ *
|
||||
+ * @__NL80211_WIPHY_RADIO_ATTR_LAST: Internal
|
||||
+ * @NL80211_WIPHY_RADIO_ATTR_MAX: Highest attribute
|
||||
+ */
|
||||
+enum nl80211_wiphy_radio_attrs {
|
||||
+ __NL80211_WIPHY_RADIO_ATTR_INVALID,
|
||||
+
|
||||
+ NL80211_WIPHY_RADIO_ATTR_INDEX,
|
||||
+ NL80211_WIPHY_RADIO_ATTR_FREQ_RANGE,
|
||||
+ NL80211_WIPHY_RADIO_ATTR_INTERFACE_COMBINATION,
|
||||
+
|
||||
+ /* keep last */
|
||||
+ __NL80211_WIPHY_RADIO_ATTR_LAST,
|
||||
+ NL80211_WIPHY_RADIO_ATTR_MAX = __NL80211_WIPHY_RADIO_ATTR_LAST - 1,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * enum nl80211_wiphy_radio_freq_range - wiphy radio frequency range
|
||||
+ *
|
||||
+ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID: Invalid
|
||||
+ *
|
||||
+ * @NL80211_WIPHY_RADIO_FREQ_ATTR_START: Frequency range start (u32).
|
||||
+ * The unit is kHz.
|
||||
+ * @NL80211_WIPHY_RADIO_FREQ_ATTR_END: Frequency range end (u32).
|
||||
+ * The unit is kHz.
|
||||
+ *
|
||||
+ * @__NL80211_WIPHY_RADIO_FREQ_ATTR_LAST: Internal
|
||||
+ * @NL80211_WIPHY_RADIO_FREQ_ATTR_MAX: Highest attribute
|
||||
+ */
|
||||
+enum nl80211_wiphy_radio_freq_range {
|
||||
+ __NL80211_WIPHY_RADIO_FREQ_ATTR_INVALID,
|
||||
+
|
||||
+ NL80211_WIPHY_RADIO_FREQ_ATTR_START,
|
||||
+ NL80211_WIPHY_RADIO_FREQ_ATTR_END,
|
||||
+
|
||||
+ __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST,
|
||||
+ NL80211_WIPHY_RADIO_FREQ_ATTR_MAX = __NL80211_WIPHY_RADIO_FREQ_ATTR_LAST - 1,
|
||||
+};
|
||||
+
|
||||
#endif /* __LINUX_NL80211_H */
|
252
package/network/utils/iw/patches/300-wiphy_radios.patch
Normal file
252
package/network/utils/iw/patches/300-wiphy_radios.patch
Normal file
@ -0,0 +1,252 @@
|
||||
--- 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]) {
|
99
package/network/utils/iw/patches/310-vif_radio_mask.patch
Normal file
99
package/network/utils/iw/patches/310-vif_radio_mask.patch
Normal file
@ -0,0 +1,99 @@
|
||||
--- a/interface.c
|
||||
+++ b/interface.c
|
||||
@@ -226,6 +226,43 @@ nla_put_failure:
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int parse_radio_list(char *str, struct nl_msg *msg)
|
||||
+{
|
||||
+ unsigned int mask = 0;
|
||||
+ unsigned long id;
|
||||
+ char *end;
|
||||
+
|
||||
+ if (!str)
|
||||
+ return 1;
|
||||
+
|
||||
+ if (!strcmp(str, "all"))
|
||||
+ goto out;
|
||||
+
|
||||
+ while (1) {
|
||||
+ if (!*str)
|
||||
+ return 1;
|
||||
+
|
||||
+ id = strtoul(str, &end, 0);
|
||||
+ if (id > 31)
|
||||
+ return 1;
|
||||
+
|
||||
+ mask |= 1 << id;
|
||||
+ if (!*end)
|
||||
+ break;
|
||||
+
|
||||
+ if (end == str || *end != ',')
|
||||
+ return 1;
|
||||
+
|
||||
+ str = end + 1;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ NLA_PUT_U32(msg, NL80211_ATTR_VIF_RADIO_MASK, mask);
|
||||
+ return 0;
|
||||
+nla_put_failure:
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int handle_interface_add(struct nl80211_state *state,
|
||||
struct nl_msg *msg,
|
||||
int argc, char **argv,
|
||||
@@ -287,6 +324,15 @@ try_another:
|
||||
fprintf(stderr, "flags error\n");
|
||||
return 2;
|
||||
}
|
||||
+ } else if (strcmp(argv[0], "radios") == 0) {
|
||||
+ argc--;
|
||||
+ argv++;
|
||||
+ if (parse_radio_list(argv[0], msg)) {
|
||||
+ fprintf(stderr, "Invalid radio list\n");
|
||||
+ return 2;
|
||||
+ }
|
||||
+ argc--;
|
||||
+ argv++;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
@@ -306,14 +352,14 @@ try_another:
|
||||
nla_put_failure:
|
||||
return -ENOBUFS;
|
||||
}
|
||||
-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>]",
|
||||
+COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>] [radios all|<id>[,<id>...]]",
|
||||
NL80211_CMD_NEW_INTERFACE, 0, CIB_PHY, handle_interface_add,
|
||||
"Add a new virtual interface with the given configuration.\n"
|
||||
IFACE_TYPES "\n\n"
|
||||
"The flags are only used for monitor interfaces, valid flags are:\n"
|
||||
VALID_FLAGS "\n\n"
|
||||
"The mesh_id is used only for mesh mode.");
|
||||
-COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>]",
|
||||
+COMMAND(interface, add, "<name> type <type> [mesh_id <meshid>] [4addr on|off] [flags <flag>*] [addr <mac-addr>] [radios all|<id>[,<id>...]]",
|
||||
NL80211_CMD_NEW_INTERFACE, 0, CIB_NETDEV, handle_interface_add, NULL);
|
||||
|
||||
static int handle_interface_del(struct nl80211_state *state,
|
||||
@@ -493,6 +539,19 @@ static int print_iface_handler(struct nl
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (tb_msg[NL80211_ATTR_VIF_RADIO_MASK]) {
|
||||
+ uint32_t mask = nla_get_u32(tb_msg[NL80211_ATTR_VIF_RADIO_MASK]);
|
||||
+ int i;
|
||||
+
|
||||
+ if (mask) {
|
||||
+ printf("%s\tRadios:", indent);
|
||||
+ for (i = 0; mask; i++, mask >>= 1)
|
||||
+ if (mask & 1)
|
||||
+ printf(" %d", i);
|
||||
+ printf("\n");
|
||||
+ }
|
||||
+ }
|
||||
|
||||
return NL_SKIP;
|
||||
}
|
Loading…
Reference in New Issue
Block a user