9 #include <netlink/genl/genl.h>
10 #include <netlink/genl/family.h>
11 #include <netlink/genl/ctrl.h>
12 #include <netlink/msg.h>
13 #include <netlink/attr.h>
25 static char *dfs_state_name(enum nl80211_dfs_state state
)
28 case NL80211_DFS_USABLE
:
30 case NL80211_DFS_AVAILABLE
:
32 case NL80211_DFS_UNAVAILABLE
:
39 static int print_channels_handler(struct nl_msg
*msg
, void *arg
)
41 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
42 struct channels_ctx
*ctx
= arg
;
43 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
44 struct nlattr
*tb_band
[NL80211_BAND_ATTR_MAX
+ 1];
45 struct nlattr
*tb_freq
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
46 struct nlattr
*nl_band
;
47 struct nlattr
*nl_freq
;
48 int rem_band
, rem_freq
;
50 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0), genlmsg_attrlen(gnlh
, 0), NULL
);
52 if (tb_msg
[NL80211_ATTR_WIPHY_BANDS
]) {
53 nla_for_each_nested(nl_band
, tb_msg
[NL80211_ATTR_WIPHY_BANDS
], rem_band
) {
54 if (ctx
->last_band
!= nl_band
->nla_type
) {
55 printf("Band %d:\n", nl_band
->nla_type
+ 1);
56 ctx
->width_40
= false;
57 ctx
->width_80
= false;
58 ctx
->width_160
= false;
59 ctx
->last_band
= nl_band
->nla_type
;
62 nla_parse(tb_band
, NL80211_BAND_ATTR_MAX
, nla_data(nl_band
), nla_len(nl_band
), NULL
);
64 if (tb_band
[NL80211_BAND_ATTR_HT_CAPA
]) {
65 __u16 cap
= nla_get_u16(tb_band
[NL80211_BAND_ATTR_HT_CAPA
]);
71 if (tb_band
[NL80211_BAND_ATTR_VHT_CAPA
]) {
76 capa
= nla_get_u32(tb_band
[NL80211_BAND_ATTR_VHT_CAPA
]);
77 switch ((capa
>> 2) & 3) {
79 /* width_80p80 = true; */
82 ctx
->width_160
= true;
87 if (tb_band
[NL80211_BAND_ATTR_FREQS
]) {
88 nla_for_each_nested(nl_freq
, tb_band
[NL80211_BAND_ATTR_FREQS
], rem_freq
) {
91 nla_parse(tb_freq
, NL80211_FREQUENCY_ATTR_MAX
, nla_data(nl_freq
), nla_len(nl_freq
), NULL
);
93 if (!tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
])
95 freq
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
]);
96 printf("\t* %d MHz [%d] ", freq
, ieee80211_frequency_to_channel(freq
));
98 if (tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
]) {
99 printf("(disabled)\n");
104 if (tb_freq
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
])
105 printf("\t Maximum TX power: %.1f dBm\n", 0.01 * nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
]));
107 /* If both flags are set assume an new kernel */
108 if (tb_freq
[NL80211_FREQUENCY_ATTR_NO_IR
] && tb_freq
[__NL80211_FREQUENCY_ATTR_NO_IBSS
]) {
109 printf("\t No IR\n");
110 } else if (tb_freq
[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN
]) {
111 printf("\t Passive scan\n");
112 } else if (tb_freq
[__NL80211_FREQUENCY_ATTR_NO_IBSS
]){
113 printf("\t No IBSS\n");
116 if (tb_freq
[NL80211_FREQUENCY_ATTR_RADAR
])
117 printf("\t Radar detection\n");
119 printf("\t Channel widths:");
120 if (!tb_freq
[NL80211_FREQUENCY_ATTR_NO_20MHZ
])
122 if (ctx
->width_40
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_HT40_MINUS
])
124 if (ctx
->width_40
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_HT40_PLUS
])
126 if (ctx
->width_80
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_80MHZ
])
128 if (ctx
->width_160
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_160MHZ
])
132 if (!tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
] && tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]) {
133 enum nl80211_dfs_state state
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]);
136 printf("\t DFS state: %s", dfs_state_name(state
));
137 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_TIME
]) {
138 time
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_TIME
]);
139 printf(" (for %lu sec)", time
/ 1000);
142 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
])
143 printf("\t DFS CAC time: %u ms\n",
144 nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
]));
154 static int handle_channels(struct nl80211_state
*state
, struct nl_msg
*msg
,
155 int argc
, char **argv
, enum id_input id
)
157 static struct channels_ctx ctx
= {
161 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
);
162 nlmsg_hdr(msg
)->nlmsg_flags
|= NLM_F_DUMP
;
164 register_handler(print_channels_handler
, &ctx
);
168 TOPLEVEL(channels
, NULL
, NL80211_CMD_GET_WIPHY
, 0, CIB_PHY
, handle_channels
, "Show available channels.");
170 static int handle_name(struct nl80211_state
*state
,
172 int argc
, char **argv
,
178 NLA_PUT_STRING(msg
, NL80211_ATTR_WIPHY_NAME
, *argv
);
184 COMMAND(set
, name
, "<new name>", NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_name
,
185 "Rename this wireless device.");
187 static int handle_freq(struct nl80211_state
*state
, struct nl_msg
*msg
,
188 int argc
, char **argv
,
191 struct chandef chandef
;
194 res
= parse_freqchan(&chandef
, false, argc
, argv
, NULL
, false);
198 return put_chandef(msg
, &chandef
);
202 "<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz]\n"
203 "<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
204 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_freq
,
205 "Set frequency/channel the hardware is using, including HT\n"
208 "<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz|320MHz]\n"
209 "<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
210 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_freq
, NULL
);
212 static int handle_freq_khz(struct nl80211_state
*state
, struct nl_msg
*msg
,
213 int argc
, char **argv
,
216 struct chandef chandef
;
219 res
= parse_freqchan(&chandef
, false, argc
, argv
, NULL
, true);
223 return put_chandef(msg
, &chandef
);
226 COMMAND(set
, freq_khz
,
227 "<freq> [1MHz|2MHz|4MHz|8MHz|16MHz]\n"
228 "<control freq> [1|2|4|8|16] [<center1_freq> [<center2_freq>]]",
229 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_freq_khz
,
230 "Set frequency in kHz the hardware is using\n"
232 COMMAND(set
, freq_khz
,
233 "<freq> [1MHz|2MHz|4MHz|8MHz|16MHz]\n"
234 "<control freq> [1|2|4|8|16] [<center1_freq> [<center2_freq>]]",
235 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_freq_khz
, NULL
);
237 static int handle_chan(struct nl80211_state
*state
, struct nl_msg
*msg
,
238 int argc
, char **argv
,
241 struct chandef chandef
;
244 res
= parse_freqchan(&chandef
, true, argc
, argv
, NULL
, false);
248 return put_chandef(msg
, &chandef
);
250 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]",
251 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_chan
, NULL
);
252 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz|160MHz]",
253 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_chan
, NULL
);
261 static int print_cac_event(struct nl_msg
*msg
, void *arg
)
263 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
264 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
265 enum nl80211_radar_event event_type
;
266 struct cac_event
*cac_event
= arg
;
269 if (gnlh
->cmd
!= NL80211_CMD_RADAR_DETECT
)
272 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
273 genlmsg_attrlen(gnlh
, 0), NULL
);
275 if (!tb
[NL80211_ATTR_RADAR_EVENT
] || !tb
[NL80211_ATTR_WIPHY_FREQ
])
278 freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
279 event_type
= nla_get_u32(tb
[NL80211_ATTR_RADAR_EVENT
]);
280 if (freq
!= cac_event
->freq
)
283 switch (event_type
) {
284 case NL80211_RADAR_DETECTED
:
285 printf("%d MHz: radar detected\n", freq
);
287 case NL80211_RADAR_CAC_FINISHED
:
288 printf("%d MHz: CAC finished\n", freq
);
290 case NL80211_RADAR_CAC_ABORTED
:
291 printf("%d MHz: CAC was aborted\n", freq
);
293 case NL80211_RADAR_NOP_FINISHED
:
294 printf("%d MHz: NOP finished\n", freq
);
297 printf("%d MHz: unknown radar event\n", freq
);
304 static int handle_cac_trigger(struct nl80211_state
*state
,
306 int argc
, char **argv
,
309 struct chandef chandef
;
315 if (strcmp(argv
[0], "channel") == 0) {
316 res
= parse_freqchan(&chandef
, true, argc
- 1, argv
+ 1, NULL
, false);
317 } else if (strcmp(argv
[0], "freq") == 0) {
318 res
= parse_freqchan(&chandef
, false, argc
- 1, argv
+ 1, NULL
, false);
326 return put_chandef(msg
, &chandef
);
329 static int handle_cac_background(struct nl80211_state
*state
,
331 int argc
, char **argv
,
334 nla_put_flag(msg
, NL80211_ATTR_RADAR_BACKGROUND
);
335 return handle_cac_trigger(state
, msg
, argc
, argv
, id
);
338 static int no_seq_check(struct nl_msg
*msg
, void *arg
)
343 static int handle_cac(struct nl80211_state
*state
,
345 int argc
, char **argv
,
349 struct nl_cb
*radar_cb
;
350 struct chandef chandef
;
351 struct cac_event cac_event
;
352 char **cac_trigger_argv
= NULL
;
354 radar_cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
361 if (strcmp(argv
[2], "channel") == 0) {
362 err
= parse_freqchan(&chandef
, true, argc
- 3, argv
+ 3, NULL
, false);
363 } else if (strcmp(argv
[2], "freq") == 0) {
364 err
= parse_freqchan(&chandef
, false, argc
- 3, argv
+ 3, NULL
, false);
371 cac_trigger_argv
= calloc(argc
+ 1, sizeof(char*));
372 if (!cac_trigger_argv
) {
377 cac_trigger_argv
[0] = argv
[0];
378 cac_trigger_argv
[1] = "cac";
379 cac_trigger_argv
[2] = "trigger";
380 memcpy(&cac_trigger_argv
[3], &argv
[2], (argc
- 2) * sizeof(char*));
382 err
= handle_cmd(state
, id
, argc
+ 1, cac_trigger_argv
);
387 cac_event
.freq
= chandef
.control_freq
;
389 __prepare_listen_events(state
);
390 nl_socket_set_cb(state
->nl_sock
, radar_cb
);
392 /* need to turn off sequence number checking */
393 nl_cb_set(radar_cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
394 nl_cb_set(radar_cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_cac_event
, &cac_event
);
395 while (cac_event
.ret
> 0)
396 nl_recvmsgs(state
->nl_sock
, radar_cb
);
402 if (cac_trigger_argv
)
403 free(cac_trigger_argv
);
406 TOPLEVEL(cac
, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
407 "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
408 "freq <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
409 0, 0, CIB_NETDEV
, handle_cac
, NULL
);
410 COMMAND(cac
, trigger
,
411 "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
412 "freq <frequency> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
413 "freq <frequency> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
414 NL80211_CMD_RADAR_DETECT
, 0, CIB_NETDEV
, handle_cac_trigger
,
415 "Start or trigger a channel availability check (CAC) looking to look for\n"
416 "radars on the given channel.");
418 COMMAND(cac
, background
,
419 "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
420 "freq <frequency> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
421 "freq <frequency> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
422 NL80211_CMD_RADAR_DETECT
, 0, CIB_NETDEV
, handle_cac_background
,
423 "Start background channel availability check (CAC) looking to look for\n"
424 "radars on the given channel.");
426 static int handle_fragmentation(struct nl80211_state
*state
,
428 int argc
, char **argv
,
436 if (strcmp("off", argv
[0]) == 0)
443 frag
= strtoul(argv
[0], &end
, 10);
448 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FRAG_THRESHOLD
, frag
);
454 COMMAND(set
, frag
, "<fragmentation threshold|off>",
455 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_fragmentation
,
456 "Set fragmentation threshold.");
458 static int handle_rts(struct nl80211_state
*state
,
460 int argc
, char **argv
,
468 if (strcmp("off", argv
[0]) == 0)
475 rts
= strtoul(argv
[0], &end
, 10);
480 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_RTS_THRESHOLD
, rts
);
486 COMMAND(set
, rts
, "<rts threshold|off>",
487 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_rts
,
488 "Set rts threshold.");
490 static int handle_retry(struct nl80211_state
*state
,
492 int argc
, char **argv
, enum id_input id
)
494 unsigned int retry_short
= 0, retry_long
= 0;
495 bool have_retry_s
= false, have_retry_l
= false;
501 } parser_state
= S_NONE
;
503 if (!argc
|| (argc
!= 2 && argc
!= 4))
506 for (i
= 0; i
< argc
; i
++) {
510 if (strcmp(argv
[i
], "short") == 0) {
513 parser_state
= S_SHORT
;
515 } else if (strcmp(argv
[i
], "long") == 0) {
518 parser_state
= S_LONG
;
521 tmpul
= strtoul(argv
[i
], &end
, 10);
524 if (!tmpul
|| tmpul
> 255)
526 switch (parser_state
) {
539 if (!have_retry_s
&& !have_retry_l
)
542 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_SHORT
, retry_short
);
544 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_LONG
, retry_long
);
550 COMMAND(set
, retry
, "[short <limit>] [long <limit>]",
551 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_retry
,
554 #ifndef NETNS_RUN_DIR
555 #define NETNS_RUN_DIR "/var/run/netns"
557 static int netns_get_fd(const char *name
)
559 char pathbuf
[MAXPATHLEN
];
560 const char *path
, *ptr
;
563 ptr
= strchr(name
, '/');
565 snprintf(pathbuf
, sizeof(pathbuf
), "%s/%s",
566 NETNS_RUN_DIR
, name
);
569 return open(path
, O_RDONLY
);
572 static int handle_netns(struct nl80211_state
*state
,
574 int argc
, char **argv
,
580 if (argc
< 1 || !*argv
[0])
584 NLA_PUT_U32(msg
, NL80211_ATTR_PID
,
585 strtoul(argv
[0], &end
, 10));
587 printf("Invalid parameter: pid(%s)\n", argv
[0]);
593 if (argc
!= 2 || strcmp(argv
[0], "name"))
596 if ((fd
= netns_get_fd(argv
[1])) >= 0) {
597 NLA_PUT_U32(msg
, NL80211_ATTR_NETNS_FD
, fd
);
600 printf("Invalid parameter: nsname(%s)\n", argv
[0]);
610 COMMAND(set
, netns
, "{ <pid> | name <nsname> }",
611 NL80211_CMD_SET_WIPHY_NETNS
, 0, CIB_PHY
, handle_netns
,
612 "Put this wireless device into a different network namespace:\n"
613 " <pid> - change network namespace by process id\n"
614 " <nsname> - change network namespace by name from "NETNS_RUN_DIR
"\n"
615 " or by absolute path (man ip-netns)\n");
617 static int handle_coverage(struct nl80211_state
*state
,
619 int argc
, char **argv
,
623 unsigned int coverage
;
630 coverage
= strtoul(argv
[0], &end
, 10);
637 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
643 COMMAND(set
, coverage
, "<coverage class>",
644 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_coverage
,
645 "Set coverage class (1 for every 3 usec of air propagation time).\n"
646 "Valid values: 0 - 255.");
648 static int handle_distance(struct nl80211_state
*state
,
650 int argc
, char **argv
,
659 if (strcmp("auto", argv
[0]) == 0) {
660 NLA_PUT_FLAG(msg
, NL80211_ATTR_WIPHY_DYN_ACK
);
663 unsigned int distance
, coverage
;
665 distance
= strtoul(argv
[0], &end
, 10);
671 * Divide double the distance by the speed of light
672 * in m/usec (300) to get round-trip time in microseconds
673 * and then divide the result by three to get coverage class
674 * as specified in IEEE 802.11-2007 table 7-27.
675 * Values are rounded upwards.
677 coverage
= (distance
+ 449) / 450;
681 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
688 COMMAND(set
, distance
, "<auto|distance>",
689 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_distance
,
690 "Enable ACK timeout estimation algorithm (dynack) or set appropriate\n"
691 "coverage class for given link distance in meters.\n"
692 "To disable dynack set valid value for coverage class.\n"
693 "Valid values: 0 - 114750");
695 static int handle_txpower(struct nl80211_state
*state
,
697 int argc
, char **argv
,
700 enum nl80211_tx_power_setting type
;
703 /* get the required args */
704 if (argc
!= 1 && argc
!= 2)
707 if (!strcmp(argv
[0], "auto"))
708 type
= NL80211_TX_POWER_AUTOMATIC
;
709 else if (!strcmp(argv
[0], "fixed"))
710 type
= NL80211_TX_POWER_FIXED
;
711 else if (!strcmp(argv
[0], "limit"))
712 type
= NL80211_TX_POWER_LIMITED
;
714 printf("Invalid parameter: %s\n", argv
[0]);
718 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_SETTING
, type
);
720 if (type
!= NL80211_TX_POWER_AUTOMATIC
) {
723 printf("Missing TX power level argument.\n");
727 mbm
= strtol(argv
[1], &endptr
, 10);
730 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_LEVEL
, mbm
);
731 } else if (argc
!= 1)
739 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
740 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_txpower
,
741 "Specify transmit power level and setting type.");
742 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
743 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_txpower
,
744 "Specify transmit power level and setting type.");
746 static int handle_antenna(struct nl80211_state
*state
,
748 int argc
, char **argv
,
752 uint32_t tx_ant
= 0, rx_ant
= 0;
754 if (argc
== 1 && strcmp(argv
[0], "all") == 0) {
757 } else if (argc
== 1) {
758 tx_ant
= rx_ant
= strtoul(argv
[0], &end
, 0);
762 else if (argc
== 2) {
763 tx_ant
= strtoul(argv
[0], &end
, 0);
766 rx_ant
= strtoul(argv
[1], &end
, 0);
772 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_TX
, tx_ant
);
773 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_RX
, rx_ant
);
780 COMMAND(set
, antenna
, "<bitmap> | all | <tx bitmap> <rx bitmap>",
781 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_antenna
,
782 "Set a bitmap of allowed antennas to use for TX and RX.\n"
783 "The driver may reject antenna configurations it cannot support.");
785 static int handle_set_txq(struct nl80211_state
*state
,
787 int argc
, char **argv
,
796 if (!*argv
[0] || !*argv
[1])
799 argval
= strtoul(argv
[1], &end
, 10);
807 if (strcmp("limit", argv
[0]) == 0)
808 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_LIMIT
, argval
);
809 else if (strcmp("memory_limit", argv
[0]) == 0)
810 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_MEMORY_LIMIT
, argval
);
811 else if (strcmp("quantum", argv
[0]) == 0)
812 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_QUANTUM
, argval
);
820 COMMAND(set
, txq
, "limit <packets> | memory_limit <bytes> | quantum <bytes>",
821 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_set_txq
,
822 "Set TXQ parameters. The limit and memory_limit are global queue limits\n"
823 "for the whole phy. The quantum is the DRR scheduler quantum setting.\n"
824 "Valid values: 1 - 2**32");
826 static int print_txq_handler(struct nl_msg
*msg
, void *arg
)
828 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
829 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
830 struct nlattr
*txqstats_info
[NL80211_TXQ_STATS_MAX
+ 1], *txqinfo
;
831 static struct nla_policy txqstats_policy
[NL80211_TXQ_STATS_MAX
+ 1] = {
832 [NL80211_TXQ_STATS_BACKLOG_PACKETS
] = { .type
= NLA_U32
},
833 [NL80211_TXQ_STATS_BACKLOG_BYTES
] = { .type
= NLA_U32
},
834 [NL80211_TXQ_STATS_OVERLIMIT
] = { .type
= NLA_U32
},
835 [NL80211_TXQ_STATS_OVERMEMORY
] = { .type
= NLA_U32
},
836 [NL80211_TXQ_STATS_COLLISIONS
] = { .type
= NLA_U32
},
837 [NL80211_TXQ_STATS_MAX_FLOWS
] = { .type
= NLA_U32
},
840 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
841 genlmsg_attrlen(gnlh
, 0), NULL
);
844 if (attrs
[NL80211_ATTR_TXQ_LIMIT
])
845 printf("Packet limit:\t\t%u pkts\n",
846 nla_get_u32(attrs
[NL80211_ATTR_TXQ_LIMIT
]));
847 if (attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
])
848 printf("Memory limit:\t\t%u bytes\n",
849 nla_get_u32(attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
]));
850 if (attrs
[NL80211_ATTR_TXQ_QUANTUM
])
851 printf("Quantum:\t\t%u bytes\n",
852 nla_get_u32(attrs
[NL80211_ATTR_TXQ_QUANTUM
]));
854 if (attrs
[NL80211_ATTR_TXQ_STATS
]) {
855 if (nla_parse_nested(txqstats_info
, NL80211_TXQ_STATS_MAX
,
856 attrs
[NL80211_ATTR_TXQ_STATS
],
858 printf("failed to parse nested TXQ stats attributes!");
861 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_MAX_FLOWS
];
863 printf("Number of queues:\t%u\n", nla_get_u32(txqinfo
));
865 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_PACKETS
];
867 printf("Backlog:\t\t%u pkts\n", nla_get_u32(txqinfo
));
869 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_BYTES
];
871 printf("Memory usage:\t\t%u bytes\n", nla_get_u32(txqinfo
));
873 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERLIMIT
];
875 printf("Packet limit overflows:\t%u\n", nla_get_u32(txqinfo
));
877 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERMEMORY
];
879 printf("Memory limit overflows:\t%u\n", nla_get_u32(txqinfo
));
880 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_COLLISIONS
];
882 printf("Hash collisions:\t%u\n", nla_get_u32(txqinfo
));
887 static int handle_get_txq(struct nl80211_state
*state
,
889 int argc
, char **argv
,
892 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
);
893 nlmsg_hdr(msg
)->nlmsg_flags
|= NLM_F_DUMP
;
894 register_handler(print_txq_handler
, NULL
);
897 COMMAND(get
, txq
, "",
898 NL80211_CMD_GET_WIPHY
, 0, CIB_PHY
, handle_get_txq
,
899 "Get TXQ parameters.");