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
);
198 return put_chandef(msg
, &chandef
);
202 "<freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\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]\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_chan(struct nl80211_state
*state
, struct nl_msg
*msg
,
213 int argc
, char **argv
,
216 struct chandef chandef
;
219 res
= parse_freqchan(&chandef
, true, argc
, argv
, NULL
);
223 return put_chandef(msg
, &chandef
);
225 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
226 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_chan
, NULL
);
227 COMMAND(set
, channel
, "<channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]",
228 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_chan
, NULL
);
236 static int print_cac_event(struct nl_msg
*msg
, void *arg
)
238 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
239 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
240 enum nl80211_radar_event event_type
;
241 struct cac_event
*cac_event
= arg
;
244 if (gnlh
->cmd
!= NL80211_CMD_RADAR_DETECT
)
247 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
248 genlmsg_attrlen(gnlh
, 0), NULL
);
250 if (!tb
[NL80211_ATTR_RADAR_EVENT
] || !tb
[NL80211_ATTR_WIPHY_FREQ
])
253 freq
= nla_get_u32(tb
[NL80211_ATTR_WIPHY_FREQ
]);
254 event_type
= nla_get_u32(tb
[NL80211_ATTR_RADAR_EVENT
]);
255 if (freq
!= cac_event
->freq
)
258 switch (event_type
) {
259 case NL80211_RADAR_DETECTED
:
260 printf("%d MHz: radar detected\n", freq
);
262 case NL80211_RADAR_CAC_FINISHED
:
263 printf("%d MHz: CAC finished\n", freq
);
265 case NL80211_RADAR_CAC_ABORTED
:
266 printf("%d MHz: CAC was aborted\n", freq
);
268 case NL80211_RADAR_NOP_FINISHED
:
269 printf("%d MHz: NOP finished\n", freq
);
272 printf("%d MHz: unknown radar event\n", freq
);
279 static int handle_cac_trigger(struct nl80211_state
*state
,
281 int argc
, char **argv
,
284 struct chandef chandef
;
290 if (strcmp(argv
[0], "channel") == 0) {
291 res
= parse_freqchan(&chandef
, true, argc
- 1, argv
+ 1, NULL
);
292 } else if (strcmp(argv
[0], "freq") == 0) {
293 res
= parse_freqchan(&chandef
, false, argc
- 1, argv
+ 1, NULL
);
301 return put_chandef(msg
, &chandef
);
304 static int no_seq_check(struct nl_msg
*msg
, void *arg
)
309 static int handle_cac(struct nl80211_state
*state
,
311 int argc
, char **argv
,
315 struct nl_cb
*radar_cb
;
316 struct chandef chandef
;
317 struct cac_event cac_event
;
318 char **cac_trigger_argv
= NULL
;
320 radar_cb
= nl_cb_alloc(iw_debug
? NL_CB_DEBUG
: NL_CB_DEFAULT
);
327 if (strcmp(argv
[2], "channel") == 0) {
328 err
= parse_freqchan(&chandef
, true, argc
- 3, argv
+ 3, NULL
);
329 } else if (strcmp(argv
[2], "freq") == 0) {
330 err
= parse_freqchan(&chandef
, false, argc
- 3, argv
+ 3, NULL
);
336 cac_trigger_argv
= calloc(argc
+ 1, sizeof(char*));
337 if (!cac_trigger_argv
) {
342 cac_trigger_argv
[0] = argv
[0];
343 cac_trigger_argv
[1] = "cac";
344 cac_trigger_argv
[2] = "trigger";
345 memcpy(&cac_trigger_argv
[3], &argv
[2], (argc
- 2) * sizeof(char*));
347 err
= handle_cmd(state
, id
, argc
+ 1, cac_trigger_argv
);
352 cac_event
.freq
= chandef
.control_freq
;
354 __prepare_listen_events(state
);
355 nl_socket_set_cb(state
->nl_sock
, radar_cb
);
357 /* need to turn off sequence number checking */
358 nl_cb_set(radar_cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
359 nl_cb_set(radar_cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_cac_event
, &cac_event
);
360 while (cac_event
.ret
> 0)
361 nl_recvmsgs(state
->nl_sock
, radar_cb
);
367 if (cac_trigger_argv
)
368 free(cac_trigger_argv
);
371 TOPLEVEL(cac
, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
372 "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
373 "freq <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
374 0, 0, CIB_NETDEV
, handle_cac
, NULL
);
375 COMMAND(cac
, trigger
,
376 "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
377 "freq <frequency> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
378 "freq <frequency> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
379 NL80211_CMD_RADAR_DETECT
, 0, CIB_NETDEV
, handle_cac_trigger
,
380 "Start or trigger a channel availability check (CAC) looking to look for\n"
381 "radars on the given channel.");
383 static int handle_fragmentation(struct nl80211_state
*state
,
385 int argc
, char **argv
,
393 if (strcmp("off", argv
[0]) == 0)
400 frag
= strtoul(argv
[0], &end
, 10);
405 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FRAG_THRESHOLD
, frag
);
411 COMMAND(set
, frag
, "<fragmentation threshold|off>",
412 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_fragmentation
,
413 "Set fragmentation threshold.");
415 static int handle_rts(struct nl80211_state
*state
,
417 int argc
, char **argv
,
425 if (strcmp("off", argv
[0]) == 0)
432 rts
= strtoul(argv
[0], &end
, 10);
437 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_RTS_THRESHOLD
, rts
);
443 COMMAND(set
, rts
, "<rts threshold|off>",
444 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_rts
,
445 "Set rts threshold.");
447 static int handle_retry(struct nl80211_state
*state
,
449 int argc
, char **argv
, enum id_input id
)
451 unsigned int retry_short
= 0, retry_long
= 0;
452 bool have_retry_s
= false, have_retry_l
= false;
458 } parser_state
= S_NONE
;
460 if (!argc
|| (argc
!= 2 && argc
!= 4))
463 for (i
= 0; i
< argc
; i
++) {
467 if (strcmp(argv
[i
], "short") == 0) {
470 parser_state
= S_SHORT
;
472 } else if (strcmp(argv
[i
], "long") == 0) {
475 parser_state
= S_LONG
;
478 tmpul
= strtoul(argv
[i
], &end
, 10);
481 if (!tmpul
|| tmpul
> 255)
483 switch (parser_state
) {
496 if (!have_retry_s
&& !have_retry_l
)
499 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_SHORT
, retry_short
);
501 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_LONG
, retry_long
);
507 COMMAND(set
, retry
, "[short <limit>] [long <limit>]",
508 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_retry
,
511 #ifndef NETNS_RUN_DIR
512 #define NETNS_RUN_DIR "/var/run/netns"
514 static int netns_get_fd(const char *name
)
516 char pathbuf
[MAXPATHLEN
];
517 const char *path
, *ptr
;
520 ptr
= strchr(name
, '/');
522 snprintf(pathbuf
, sizeof(pathbuf
), "%s/%s",
523 NETNS_RUN_DIR
, name
);
526 return open(path
, O_RDONLY
);
529 static int handle_netns(struct nl80211_state
*state
,
531 int argc
, char **argv
,
537 if (argc
< 1 || !*argv
[0])
541 NLA_PUT_U32(msg
, NL80211_ATTR_PID
,
542 strtoul(argv
[0], &end
, 10));
544 printf("Invalid parameter: pid(%s)\n", argv
[0]);
550 if (argc
!= 2 || strcmp(argv
[0], "name"))
553 if ((fd
= netns_get_fd(argv
[1])) >= 0) {
554 NLA_PUT_U32(msg
, NL80211_ATTR_NETNS_FD
, fd
);
557 printf("Invalid parameter: nsname(%s)\n", argv
[0]);
567 COMMAND(set
, netns
, "{ <pid> | name <nsname> }",
568 NL80211_CMD_SET_WIPHY_NETNS
, 0, CIB_PHY
, handle_netns
,
569 "Put this wireless device into a different network namespace:\n"
570 " <pid> - change network namespace by process id\n"
571 " <nsname> - change network namespace by name from "NETNS_RUN_DIR
"\n"
572 " or by absolute path (man ip-netns)\n");
574 static int handle_coverage(struct nl80211_state
*state
,
576 int argc
, char **argv
,
580 unsigned int coverage
;
587 coverage
= strtoul(argv
[0], &end
, 10);
594 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
600 COMMAND(set
, coverage
, "<coverage class>",
601 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_coverage
,
602 "Set coverage class (1 for every 3 usec of air propagation time).\n"
603 "Valid values: 0 - 255.");
605 static int handle_distance(struct nl80211_state
*state
,
607 int argc
, char **argv
,
616 if (strcmp("auto", argv
[0]) == 0) {
617 NLA_PUT_FLAG(msg
, NL80211_ATTR_WIPHY_DYN_ACK
);
620 unsigned int distance
, coverage
;
622 distance
= strtoul(argv
[0], &end
, 10);
628 * Divide double the distance by the speed of light
629 * in m/usec (300) to get round-trip time in microseconds
630 * and then divide the result by three to get coverage class
631 * as specified in IEEE 802.11-2007 table 7-27.
632 * Values are rounded upwards.
634 coverage
= (distance
+ 449) / 450;
638 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
645 COMMAND(set
, distance
, "<auto|distance>",
646 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_distance
,
647 "Enable ACK timeout estimation algorithm (dynack) or set appropriate\n"
648 "coverage class for given link distance in meters.\n"
649 "To disable dynack set valid value for coverage class.\n"
650 "Valid values: 0 - 114750");
652 static int handle_txpower(struct nl80211_state
*state
,
654 int argc
, char **argv
,
657 enum nl80211_tx_power_setting type
;
660 /* get the required args */
661 if (argc
!= 1 && argc
!= 2)
664 if (!strcmp(argv
[0], "auto"))
665 type
= NL80211_TX_POWER_AUTOMATIC
;
666 else if (!strcmp(argv
[0], "fixed"))
667 type
= NL80211_TX_POWER_FIXED
;
668 else if (!strcmp(argv
[0], "limit"))
669 type
= NL80211_TX_POWER_LIMITED
;
671 printf("Invalid parameter: %s\n", argv
[0]);
675 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_SETTING
, type
);
677 if (type
!= NL80211_TX_POWER_AUTOMATIC
) {
680 printf("Missing TX power level argument.\n");
684 mbm
= strtol(argv
[1], &endptr
, 10);
687 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_LEVEL
, mbm
);
688 } else if (argc
!= 1)
696 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
697 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_txpower
,
698 "Specify transmit power level and setting type.");
699 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
700 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_txpower
,
701 "Specify transmit power level and setting type.");
703 static int handle_antenna(struct nl80211_state
*state
,
705 int argc
, char **argv
,
709 uint32_t tx_ant
= 0, rx_ant
= 0;
711 if (argc
== 1 && strcmp(argv
[0], "all") == 0) {
714 } else if (argc
== 1) {
715 tx_ant
= rx_ant
= strtoul(argv
[0], &end
, 0);
719 else if (argc
== 2) {
720 tx_ant
= strtoul(argv
[0], &end
, 0);
723 rx_ant
= strtoul(argv
[1], &end
, 0);
729 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_TX
, tx_ant
);
730 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_RX
, rx_ant
);
737 COMMAND(set
, antenna
, "<bitmap> | all | <tx bitmap> <rx bitmap>",
738 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_antenna
,
739 "Set a bitmap of allowed antennas to use for TX and RX.\n"
740 "The driver may reject antenna configurations it cannot support.");
742 static int handle_set_txq(struct nl80211_state
*state
,
744 int argc
, char **argv
,
753 if (!*argv
[0] || !*argv
[1])
756 argval
= strtoul(argv
[1], &end
, 10);
764 if (strcmp("limit", argv
[0]) == 0)
765 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_LIMIT
, argval
);
766 else if (strcmp("memory_limit", argv
[0]) == 0)
767 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_MEMORY_LIMIT
, argval
);
768 else if (strcmp("quantum", argv
[0]) == 0)
769 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_QUANTUM
, argval
);
777 COMMAND(set
, txq
, "limit <packets> | memory_limit <bytes> | quantum <bytes>",
778 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_set_txq
,
779 "Set TXQ parameters. The limit and memory_limit are global queue limits\n"
780 "for the whole phy. The quantum is the DRR scheduler quantum setting.\n"
781 "Valid values: 1 - 2**32");
783 static int print_txq_handler(struct nl_msg
*msg
, void *arg
)
785 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
786 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
787 struct nlattr
*txqstats_info
[NL80211_TXQ_STATS_MAX
+ 1], *txqinfo
;
788 static struct nla_policy txqstats_policy
[NL80211_TXQ_STATS_MAX
+ 1] = {
789 [NL80211_TXQ_STATS_BACKLOG_PACKETS
] = { .type
= NLA_U32
},
790 [NL80211_TXQ_STATS_BACKLOG_BYTES
] = { .type
= NLA_U32
},
791 [NL80211_TXQ_STATS_OVERLIMIT
] = { .type
= NLA_U32
},
792 [NL80211_TXQ_STATS_OVERMEMORY
] = { .type
= NLA_U32
},
793 [NL80211_TXQ_STATS_COLLISIONS
] = { .type
= NLA_U32
},
794 [NL80211_TXQ_STATS_MAX_FLOWS
] = { .type
= NLA_U32
},
797 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
798 genlmsg_attrlen(gnlh
, 0), NULL
);
801 if (attrs
[NL80211_ATTR_TXQ_LIMIT
])
802 printf("Packet limit:\t\t%u pkts\n",
803 nla_get_u32(attrs
[NL80211_ATTR_TXQ_LIMIT
]));
804 if (attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
])
805 printf("Memory limit:\t\t%u bytes\n",
806 nla_get_u32(attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
]));
807 if (attrs
[NL80211_ATTR_TXQ_QUANTUM
])
808 printf("Quantum:\t\t%u bytes\n",
809 nla_get_u32(attrs
[NL80211_ATTR_TXQ_QUANTUM
]));
811 if (attrs
[NL80211_ATTR_TXQ_STATS
]) {
812 if (nla_parse_nested(txqstats_info
, NL80211_TXQ_STATS_MAX
,
813 attrs
[NL80211_ATTR_TXQ_STATS
],
815 printf("failed to parse nested TXQ stats attributes!");
818 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_MAX_FLOWS
];
820 printf("Number of queues:\t%u\n", nla_get_u32(txqinfo
));
822 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_PACKETS
];
824 printf("Backlog:\t\t%u pkts\n", nla_get_u32(txqinfo
));
826 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_BYTES
];
828 printf("Memory usage:\t\t%u bytes\n", nla_get_u32(txqinfo
));
830 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERLIMIT
];
832 printf("Packet limit overflows:\t%u\n", nla_get_u32(txqinfo
));
834 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERMEMORY
];
836 printf("Memory limit overflows:\t%u\n", nla_get_u32(txqinfo
));
837 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_COLLISIONS
];
839 printf("Hash collisions:\t%u\n", nla_get_u32(txqinfo
));
844 static int handle_get_txq(struct nl80211_state
*state
,
846 int argc
, char **argv
,
849 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
);
850 nlmsg_hdr(msg
)->nlmsg_flags
|= NLM_F_DUMP
;
851 register_handler(print_txq_handler
, NULL
);
854 COMMAND(get
, txq
, "",
855 NL80211_CMD_GET_WIPHY
, 0, CIB_PHY
, handle_get_txq
,
856 "Get TXQ parameters.");