8 #include <netlink/genl/genl.h>
9 #include <netlink/genl/family.h>
10 #include <netlink/genl/ctrl.h>
11 #include <netlink/msg.h>
12 #include <netlink/attr.h>
24 static char *dfs_state_name(enum nl80211_dfs_state state
)
27 case NL80211_DFS_USABLE
:
29 case NL80211_DFS_AVAILABLE
:
31 case NL80211_DFS_UNAVAILABLE
:
38 static int print_channels_handler(struct nl_msg
*msg
, void *arg
)
40 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
41 struct channels_ctx
*ctx
= arg
;
42 struct nlattr
*tb_msg
[NL80211_ATTR_MAX
+ 1];
43 struct nlattr
*tb_band
[NL80211_BAND_ATTR_MAX
+ 1];
44 struct nlattr
*tb_freq
[NL80211_FREQUENCY_ATTR_MAX
+ 1];
45 struct nlattr
*nl_band
;
46 struct nlattr
*nl_freq
;
47 int rem_band
, rem_freq
;
49 nla_parse(tb_msg
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0), genlmsg_attrlen(gnlh
, 0), NULL
);
51 if (tb_msg
[NL80211_ATTR_WIPHY_BANDS
]) {
52 nla_for_each_nested(nl_band
, tb_msg
[NL80211_ATTR_WIPHY_BANDS
], rem_band
) {
53 if (ctx
->last_band
!= nl_band
->nla_type
) {
54 printf("Band %d:\n", nl_band
->nla_type
+ 1);
55 ctx
->width_40
= false;
56 ctx
->width_80
= false;
57 ctx
->width_160
= false;
58 ctx
->last_band
= nl_band
->nla_type
;
61 nla_parse(tb_band
, NL80211_BAND_ATTR_MAX
, nla_data(nl_band
), nla_len(nl_band
), NULL
);
63 if (tb_band
[NL80211_BAND_ATTR_HT_CAPA
]) {
64 __u16 cap
= nla_get_u16(tb_band
[NL80211_BAND_ATTR_HT_CAPA
]);
70 if (tb_band
[NL80211_BAND_ATTR_VHT_CAPA
]) {
75 capa
= nla_get_u32(tb_band
[NL80211_BAND_ATTR_VHT_CAPA
]);
76 switch ((capa
>> 2) & 3) {
78 /* width_80p80 = true; */
81 ctx
->width_160
= true;
86 if (tb_band
[NL80211_BAND_ATTR_FREQS
]) {
87 nla_for_each_nested(nl_freq
, tb_band
[NL80211_BAND_ATTR_FREQS
], rem_freq
) {
90 nla_parse(tb_freq
, NL80211_FREQUENCY_ATTR_MAX
, nla_data(nl_freq
), nla_len(nl_freq
), NULL
);
92 if (!tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
])
94 freq
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_FREQ
]);
95 printf("\t* %d MHz [%d] ", freq
, ieee80211_frequency_to_channel(freq
));
97 if (tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
]) {
98 printf("(disabled)\n");
103 if (tb_freq
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
])
104 printf("\t Maximum TX power: %.1f dBm\n", 0.01 * nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_MAX_TX_POWER
]));
106 /* If both flags are set assume an new kernel */
107 if (tb_freq
[NL80211_FREQUENCY_ATTR_NO_IR
] && tb_freq
[__NL80211_FREQUENCY_ATTR_NO_IBSS
]) {
108 printf("\t No IR\n");
109 } else if (tb_freq
[NL80211_FREQUENCY_ATTR_PASSIVE_SCAN
]) {
110 printf("\t Passive scan\n");
111 } else if (tb_freq
[__NL80211_FREQUENCY_ATTR_NO_IBSS
]){
112 printf("\t No IBSS\n");
115 if (tb_freq
[NL80211_FREQUENCY_ATTR_RADAR
])
116 printf("\t Radar detection\n");
118 printf("\t Channel widths:");
119 if (!tb_freq
[NL80211_FREQUENCY_ATTR_NO_20MHZ
])
121 if (ctx
->width_40
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_HT40_MINUS
])
123 if (ctx
->width_40
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_HT40_PLUS
])
125 if (ctx
->width_80
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_80MHZ
])
127 if (ctx
->width_160
&& !tb_freq
[NL80211_FREQUENCY_ATTR_NO_160MHZ
])
131 if (!tb_freq
[NL80211_FREQUENCY_ATTR_DISABLED
] && tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]) {
132 enum nl80211_dfs_state state
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_STATE
]);
135 printf("\t DFS state: %s", dfs_state_name(state
));
136 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_TIME
]) {
137 time
= nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_TIME
]);
138 printf(" (for %lu sec)", time
/ 1000);
141 if (tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
])
142 printf("\t DFS CAC time: %u ms\n",
143 nla_get_u32(tb_freq
[NL80211_FREQUENCY_ATTR_DFS_CAC_TIME
]));
153 static int handle_channels(struct nl80211_state
*state
, struct nl_msg
*msg
,
154 int argc
, char **argv
, enum id_input id
)
156 static struct channels_ctx ctx
= {
160 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
);
161 nlmsg_hdr(msg
)->nlmsg_flags
|= NLM_F_DUMP
;
163 register_handler(print_channels_handler
, &ctx
);
167 TOPLEVEL(channels
, NULL
, NL80211_CMD_GET_WIPHY
, 0, CIB_PHY
, handle_channels
, "Show available channels.");
169 static int handle_name(struct nl80211_state
*state
,
171 int argc
, char **argv
,
177 NLA_PUT_STRING(msg
, NL80211_ATTR_WIPHY_NAME
, *argv
);
183 COMMAND(set
, name
, "<new name>", NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_name
,
184 "Rename this wireless device.");
186 static int handle_freq(struct nl80211_state
*state
, struct nl_msg
*msg
,
187 int argc
, char **argv
,
190 struct chandef chandef
;
193 res
= parse_freqchan(&chandef
, false, argc
, argv
, NULL
);
197 return put_chandef(msg
, &chandef
);
201 "<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
202 "<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
203 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_freq
,
204 "Set frequency/channel the hardware is using, including HT\n"
207 "<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
208 "<control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
209 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_freq
, NULL
);
211 static int handle_chan(struct nl80211_state
*state
, struct nl_msg
*msg
,
212 int argc
, char **argv
,
215 struct chandef chandef
;
218 res
= parse_freqchan(&chandef
, true, argc
, argv
, NULL
);
222 return put_chandef(msg
, &chandef
);
224 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
225 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_chan
, NULL
);
226 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
227 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_chan
, NULL
);
235 static int print_cac_event(struct nl_msg
*msg
, void *arg
)
237 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
238 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
239 enum nl80211_radar_event event_type
;
240 struct cac_event
*cac_event
= arg
;
243 if (gnlh
->cmd
!= NL80211_CMD_RADAR_DETECT
)
246 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
247 genlmsg_attrlen(gnlh
, 0), NULL
);
249 if (!tb
[NL80211_ATTR_RADAR_EVENT
] || !tb
[NL80211_ATTR_WIPHY_FREQ
])
252 freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
253 event_type
= nla_get_u32(tb
[NL80211_ATTR_RADAR_EVENT
]);
254 if (freq
!= cac_event
->freq
)
257 switch (event_type
) {
258 case NL80211_RADAR_DETECTED
:
259 printf("%d MHz: radar detected\n", freq
);
261 case NL80211_RADAR_CAC_FINISHED
:
262 printf("%d MHz: CAC finished\n", freq
);
264 case NL80211_RADAR_CAC_ABORTED
:
265 printf("%d MHz: CAC was aborted\n", freq
);
267 case NL80211_RADAR_NOP_FINISHED
:
268 printf("%d MHz: NOP finished\n", freq
);
271 printf("%d MHz: unknown radar event\n", freq
);
278 static int handle_cac_trigger(struct nl80211_state
*state
,
280 int argc
, char **argv
,
283 struct chandef chandef
;
289 if (strcmp(argv
[0], "channel") == 0) {
290 res
= parse_freqchan(&chandef
, true, argc
- 1, argv
+ 1, NULL
);
291 } else if (strcmp(argv
[0], "freq") == 0) {
292 res
= parse_freqchan(&chandef
, false, argc
- 1, argv
+ 1, NULL
);
300 return put_chandef(msg
, &chandef
);
303 static int no_seq_check(struct nl_msg
*msg
, void *arg
)
308 static int handle_cac(struct nl80211_state
*state
,
310 int argc
, char **argv
,
314 struct nl_cb
*radar_cb
;
315 struct chandef chandef
;
316 struct cac_event cac_event
;
317 char **cac_trigger_argv
= NULL
;
319 radar_cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
326 if (strcmp(argv
[2], "channel") == 0) {
327 err
= parse_freqchan(&chandef
, true, argc
- 3, argv
+ 3, NULL
);
328 } else if (strcmp(argv
[2], "freq") == 0) {
329 err
= parse_freqchan(&chandef
, false, argc
- 3, argv
+ 3, NULL
);
334 cac_trigger_argv
= calloc(argc
+ 1, sizeof(char*));
335 if (!cac_trigger_argv
)
338 cac_trigger_argv
[0] = argv
[0];
339 cac_trigger_argv
[1] = "cac";
340 cac_trigger_argv
[2] = "trigger";
341 memcpy(&cac_trigger_argv
[3], &argv
[2], (argc
- 2) * sizeof(char*));
343 err
= handle_cmd(state
, id
, argc
+ 1, cac_trigger_argv
);
344 free(cac_trigger_argv
);
349 cac_event
.freq
= chandef
.control_freq
;
351 __prepare_listen_events(state
);
352 nl_socket_set_cb(state
->nl_sock
, radar_cb
);
354 /* need to turn off sequence number checking */
355 nl_cb_set(radar_cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
356 nl_cb_set(radar_cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_cac_event
, &cac_event
);
357 while (cac_event
.ret
> 0)
358 nl_recvmsgs(state
->nl_sock
, radar_cb
);
362 TOPLEVEL(cac
, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
363 "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
364 "freq <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
365 0, 0, CIB_NETDEV
, handle_cac
, NULL
);
366 COMMAND(cac
, trigger
,
367 "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
368 "freq <frequency> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
369 "freq <frequency> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
370 NL80211_CMD_RADAR_DETECT
, 0, CIB_NETDEV
, handle_cac_trigger
,
371 "Start or trigger a channel availability check (CAC) looking to look for\n"
372 "radars on the given channel.");
374 static int handle_fragmentation(struct nl80211_state
*state
,
376 int argc
, char **argv
,
384 if (strcmp("off", argv
[0]) == 0)
391 frag
= strtoul(argv
[0], &end
, 10);
396 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FRAG_THRESHOLD
, frag
);
402 COMMAND(set
, frag
, "<fragmentation threshold|off>",
403 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_fragmentation
,
404 "Set fragmentation threshold.");
406 static int handle_rts(struct nl80211_state
*state
,
408 int argc
, char **argv
,
416 if (strcmp("off", argv
[0]) == 0)
423 rts
= strtoul(argv
[0], &end
, 10);
428 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_RTS_THRESHOLD
, rts
);
434 COMMAND(set
, rts
, "<rts threshold|off>",
435 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_rts
,
436 "Set rts threshold.");
438 static int handle_retry(struct nl80211_state
*state
,
440 int argc
, char **argv
, enum id_input id
)
442 unsigned int retry_short
= 0, retry_long
= 0;
443 bool have_retry_s
= false, have_retry_l
= false;
449 } parser_state
= S_NONE
;
451 if (!argc
|| (argc
!= 2 && argc
!= 4))
454 for (i
= 0; i
< argc
; i
++) {
458 if (strcmp(argv
[i
], "short") == 0) {
461 parser_state
= S_SHORT
;
463 } else if (strcmp(argv
[i
], "long") == 0) {
466 parser_state
= S_LONG
;
469 tmpul
= strtoul(argv
[i
], &end
, 10);
472 if (!tmpul
|| tmpul
> 255)
474 switch (parser_state
) {
487 if (!have_retry_s
&& !have_retry_l
)
490 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_SHORT
, retry_short
);
492 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_LONG
, retry_long
);
498 COMMAND(set
, retry
, "[short <limit>] [long <limit>]",
499 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_retry
,
502 #ifndef NETNS_RUN_DIR
503 #define NETNS_RUN_DIR "/var/run/netns"
505 static int netns_get_fd(const char *name
)
507 char pathbuf
[MAXPATHLEN
];
508 const char *path
, *ptr
;
511 ptr
= strchr(name
, '/');
513 snprintf(pathbuf
, sizeof(pathbuf
), "%s/%s",
514 NETNS_RUN_DIR
, name
);
517 return open(path
, O_RDONLY
);
520 static int handle_netns(struct nl80211_state
*state
,
522 int argc
, char **argv
,
528 if (argc
< 1 || !*argv
[0])
532 NLA_PUT_U32(msg
, NL80211_ATTR_PID
,
533 strtoul(argv
[0], &end
, 10));
535 printf("Invalid parameter: pid(%s)\n", argv
[0]);
541 if (argc
!= 2 || strcmp(argv
[0], "name"))
544 if ((fd
= netns_get_fd(argv
[1])) >= 0) {
545 NLA_PUT_U32(msg
, NL80211_ATTR_NETNS_FD
, fd
);
548 printf("Invalid parameter: nsname(%s)\n", argv
[0]);
556 COMMAND(set
, netns
, "{ <pid> | name <nsname> }",
557 NL80211_CMD_SET_WIPHY_NETNS
, 0, CIB_PHY
, handle_netns
,
558 "Put this wireless device into a different network namespace:\n"
559 " <pid> - change network namespace by process id\n"
560 " <nsname> - change network namespace by name from "NETNS_RUN_DIR
"\n"
561 " or by absolute path (man ip-netns)\n");
563 static int handle_coverage(struct nl80211_state
*state
,
565 int argc
, char **argv
,
569 unsigned int coverage
;
576 coverage
= strtoul(argv
[0], &end
, 10);
583 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
589 COMMAND(set
, coverage
, "<coverage class>",
590 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_coverage
,
591 "Set coverage class (1 for every 3 usec of air propagation time).\n"
592 "Valid values: 0 - 255.");
594 static int handle_distance(struct nl80211_state
*state
,
596 int argc
, char **argv
,
605 if (strcmp("auto", argv
[0]) == 0) {
606 NLA_PUT_FLAG(msg
, NL80211_ATTR_WIPHY_DYN_ACK
);
609 unsigned int distance
, coverage
;
611 distance
= strtoul(argv
[0], &end
, 10);
617 * Divide double the distance by the speed of light
618 * in m/usec (300) to get round-trip time in microseconds
619 * and then divide the result by three to get coverage class
620 * as specified in IEEE 802.11-2007 table 7-27.
621 * Values are rounded upwards.
623 coverage
= (distance
+ 449) / 450;
627 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
634 COMMAND(set
, distance
, "<auto|distance>",
635 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_distance
,
636 "Enable ACK timeout estimation algorithm (dynack) or set appropriate\n"
637 "coverage class for given link distance in meters.\n"
638 "To disable dynack set valid value for coverage class.\n"
639 "Valid values: 0 - 114750");
641 static int handle_txpower(struct nl80211_state
*state
,
643 int argc
, char **argv
,
646 enum nl80211_tx_power_setting type
;
649 /* get the required args */
650 if (argc
!= 1 && argc
!= 2)
653 if (!strcmp(argv
[0], "auto"))
654 type
= NL80211_TX_POWER_AUTOMATIC
;
655 else if (!strcmp(argv
[0], "fixed"))
656 type
= NL80211_TX_POWER_FIXED
;
657 else if (!strcmp(argv
[0], "limit"))
658 type
= NL80211_TX_POWER_LIMITED
;
660 printf("Invalid parameter: %s\n", argv
[0]);
664 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_SETTING
, type
);
666 if (type
!= NL80211_TX_POWER_AUTOMATIC
) {
669 printf("Missing TX power level argument.\n");
673 mbm
= strtol(argv
[1], &endptr
, 10);
676 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_LEVEL
, mbm
);
677 } else if (argc
!= 1)
685 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
686 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_txpower
,
687 "Specify transmit power level and setting type.");
688 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
689 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_txpower
,
690 "Specify transmit power level and setting type.");
692 static int handle_antenna(struct nl80211_state
*state
,
694 int argc
, char **argv
,
698 uint32_t tx_ant
= 0, rx_ant
= 0;
700 if (argc
== 1 && strcmp(argv
[0], "all") == 0) {
703 } else if (argc
== 1) {
704 tx_ant
= rx_ant
= strtoul(argv
[0], &end
, 0);
708 else if (argc
== 2) {
709 tx_ant
= strtoul(argv
[0], &end
, 0);
712 rx_ant
= strtoul(argv
[1], &end
, 0);
718 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_TX
, tx_ant
);
719 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_RX
, rx_ant
);
726 COMMAND(set
, antenna
, "<bitmap> | all | <tx bitmap> <rx bitmap>",
727 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_antenna
,
728 "Set a bitmap of allowed antennas to use for TX and RX.\n"
729 "The driver may reject antenna configurations it cannot support.");
731 static int handle_set_txq(struct nl80211_state
*state
,
733 int argc
, char **argv
,
742 if (!*argv
[0] || !*argv
[1])
745 argval
= strtoul(argv
[1], &end
, 10);
753 if (strcmp("limit", argv
[0]) == 0)
754 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_LIMIT
, argval
);
755 else if (strcmp("memory_limit", argv
[0]) == 0)
756 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_MEMORY_LIMIT
, argval
);
757 else if (strcmp("quantum", argv
[0]) == 0)
758 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_QUANTUM
, argval
);
766 COMMAND(set
, txq
, "limit <packets> | memory_limit <bytes> | quantum <bytes>",
767 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_set_txq
,
768 "Set TXQ parameters. The limit and memory_limit are global queue limits\n"
769 "for the whole phy. The quantum is the DRR scheduler quantum setting.\n"
770 "Valid values: 1 - 2**32");
772 static int print_txq_handler(struct nl_msg
*msg
, void *arg
)
774 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
775 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
776 struct nlattr
*txqstats_info
[NL80211_TXQ_STATS_MAX
+ 1], *txqinfo
;
777 static struct nla_policy txqstats_policy
[NL80211_TXQ_STATS_MAX
+ 1] = {
778 [NL80211_TXQ_STATS_BACKLOG_PACKETS
] = { .type
= NLA_U32
},
779 [NL80211_TXQ_STATS_BACKLOG_BYTES
] = { .type
= NLA_U32
},
780 [NL80211_TXQ_STATS_OVERLIMIT
] = { .type
= NLA_U32
},
781 [NL80211_TXQ_STATS_OVERMEMORY
] = { .type
= NLA_U32
},
782 [NL80211_TXQ_STATS_COLLISIONS
] = { .type
= NLA_U32
},
783 [NL80211_TXQ_STATS_MAX_FLOWS
] = { .type
= NLA_U32
},
786 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
787 genlmsg_attrlen(gnlh
, 0), NULL
);
790 if (attrs
[NL80211_ATTR_TXQ_LIMIT
])
791 printf("Packet limit:\t\t%u pkts\n",
792 nla_get_u32(attrs
[NL80211_ATTR_TXQ_LIMIT
]));
793 if (attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
])
794 printf("Memory limit:\t\t%u bytes\n",
795 nla_get_u32(attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
]));
796 if (attrs
[NL80211_ATTR_TXQ_QUANTUM
])
797 printf("Quantum:\t\t%u bytes\n",
798 nla_get_u32(attrs
[NL80211_ATTR_TXQ_QUANTUM
]));
800 if (attrs
[NL80211_ATTR_TXQ_STATS
]) {
801 if (nla_parse_nested(txqstats_info
, NL80211_TXQ_STATS_MAX
,
802 attrs
[NL80211_ATTR_TXQ_STATS
],
804 printf("failed to parse nested TXQ stats attributes!");
807 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_MAX_FLOWS
];
809 printf("Number of queues:\t%u\n", nla_get_u32(txqinfo
));
811 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_PACKETS
];
813 printf("Backlog:\t\t%u pkts\n", nla_get_u32(txqinfo
));
815 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_BYTES
];
817 printf("Memory usage:\t\t%u bytes\n", nla_get_u32(txqinfo
));
819 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERLIMIT
];
821 printf("Packet limit overflows:\t%u\n", nla_get_u32(txqinfo
));
823 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERMEMORY
];
825 printf("Memory limit overflows:\t%u\n", nla_get_u32(txqinfo
));
826 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_COLLISIONS
];
828 printf("Hash collisions:\t%u\n", nla_get_u32(txqinfo
));
833 static int handle_get_txq(struct nl80211_state
*state
,
835 int argc
, char **argv
,
838 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
);
839 nlmsg_hdr(msg
)->nlmsg_flags
|= NLM_F_DUMP
;
840 register_handler(print_txq_handler
, NULL
);
843 COMMAND(get
, txq
, "",
844 NL80211_CMD_GET_WIPHY
, 0, CIB_PHY
, handle_get_txq
,
845 "Get TXQ parameters.");