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
);
337 cac_trigger_argv
= calloc(argc
+ 1, sizeof(char*));
338 if (!cac_trigger_argv
) {
343 cac_trigger_argv
[0] = argv
[0];
344 cac_trigger_argv
[1] = "cac";
345 cac_trigger_argv
[2] = "trigger";
346 memcpy(&cac_trigger_argv
[3], &argv
[2], (argc
- 2) * sizeof(char*));
348 err
= handle_cmd(state
, id
, argc
+ 1, cac_trigger_argv
);
353 cac_event
.freq
= chandef
.control_freq
;
355 __prepare_listen_events(state
);
356 nl_socket_set_cb(state
->nl_sock
, radar_cb
);
358 /* need to turn off sequence number checking */
359 nl_cb_set(radar_cb
, NL_CB_SEQ_CHECK
, NL_CB_CUSTOM
, no_seq_check
, NULL
);
360 nl_cb_set(radar_cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_cac_event
, &cac_event
);
361 while (cac_event
.ret
> 0)
362 nl_recvmsgs(state
->nl_sock
, radar_cb
);
368 if (cac_trigger_argv
)
369 free(cac_trigger_argv
);
372 TOPLEVEL(cac
, "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
373 "freq <freq> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
374 "freq <control freq> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
375 0, 0, CIB_NETDEV
, handle_cac
, NULL
);
376 COMMAND(cac
, trigger
,
377 "channel <channel> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
378 "freq <frequency> [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz]\n"
379 "freq <frequency> [5|10|20|40|80|80+80|160] [<center1_freq> [<center2_freq>]]",
380 NL80211_CMD_RADAR_DETECT
, 0, CIB_NETDEV
, handle_cac_trigger
,
381 "Start or trigger a channel availability check (CAC) looking to look for\n"
382 "radars on the given channel.");
384 static int handle_fragmentation(struct nl80211_state
*state
,
386 int argc
, char **argv
,
394 if (strcmp("off", argv
[0]) == 0)
401 frag
= strtoul(argv
[0], &end
, 10);
406 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_FRAG_THRESHOLD
, frag
);
412 COMMAND(set
, frag
, "<fragmentation threshold|off>",
413 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_fragmentation
,
414 "Set fragmentation threshold.");
416 static int handle_rts(struct nl80211_state
*state
,
418 int argc
, char **argv
,
426 if (strcmp("off", argv
[0]) == 0)
433 rts
= strtoul(argv
[0], &end
, 10);
438 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_RTS_THRESHOLD
, rts
);
444 COMMAND(set
, rts
, "<rts threshold|off>",
445 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_rts
,
446 "Set rts threshold.");
448 static int handle_retry(struct nl80211_state
*state
,
450 int argc
, char **argv
, enum id_input id
)
452 unsigned int retry_short
= 0, retry_long
= 0;
453 bool have_retry_s
= false, have_retry_l
= false;
459 } parser_state
= S_NONE
;
461 if (!argc
|| (argc
!= 2 && argc
!= 4))
464 for (i
= 0; i
< argc
; i
++) {
468 if (strcmp(argv
[i
], "short") == 0) {
471 parser_state
= S_SHORT
;
473 } else if (strcmp(argv
[i
], "long") == 0) {
476 parser_state
= S_LONG
;
479 tmpul
= strtoul(argv
[i
], &end
, 10);
482 if (!tmpul
|| tmpul
> 255)
484 switch (parser_state
) {
497 if (!have_retry_s
&& !have_retry_l
)
500 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_SHORT
, retry_short
);
502 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_RETRY_LONG
, retry_long
);
508 COMMAND(set
, retry
, "[short <limit>] [long <limit>]",
509 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_retry
,
512 #ifndef NETNS_RUN_DIR
513 #define NETNS_RUN_DIR "/var/run/netns"
515 static int netns_get_fd(const char *name
)
517 char pathbuf
[MAXPATHLEN
];
518 const char *path
, *ptr
;
521 ptr
= strchr(name
, '/');
523 snprintf(pathbuf
, sizeof(pathbuf
), "%s/%s",
524 NETNS_RUN_DIR
, name
);
527 return open(path
, O_RDONLY
);
530 static int handle_netns(struct nl80211_state
*state
,
532 int argc
, char **argv
,
538 if (argc
< 1 || !*argv
[0])
542 NLA_PUT_U32(msg
, NL80211_ATTR_PID
,
543 strtoul(argv
[0], &end
, 10));
545 printf("Invalid parameter: pid(%s)\n", argv
[0]);
551 if (argc
!= 2 || strcmp(argv
[0], "name"))
554 if ((fd
= netns_get_fd(argv
[1])) >= 0) {
555 NLA_PUT_U32(msg
, NL80211_ATTR_NETNS_FD
, fd
);
558 printf("Invalid parameter: nsname(%s)\n", argv
[0]);
568 COMMAND(set
, netns
, "{ <pid> | name <nsname> }",
569 NL80211_CMD_SET_WIPHY_NETNS
, 0, CIB_PHY
, handle_netns
,
570 "Put this wireless device into a different network namespace:\n"
571 " <pid> - change network namespace by process id\n"
572 " <nsname> - change network namespace by name from "NETNS_RUN_DIR
"\n"
573 " or by absolute path (man ip-netns)\n");
575 static int handle_coverage(struct nl80211_state
*state
,
577 int argc
, char **argv
,
581 unsigned int coverage
;
588 coverage
= strtoul(argv
[0], &end
, 10);
595 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
601 COMMAND(set
, coverage
, "<coverage class>",
602 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_coverage
,
603 "Set coverage class (1 for every 3 usec of air propagation time).\n"
604 "Valid values: 0 - 255.");
606 static int handle_distance(struct nl80211_state
*state
,
608 int argc
, char **argv
,
617 if (strcmp("auto", argv
[0]) == 0) {
618 NLA_PUT_FLAG(msg
, NL80211_ATTR_WIPHY_DYN_ACK
);
621 unsigned int distance
, coverage
;
623 distance
= strtoul(argv
[0], &end
, 10);
629 * Divide double the distance by the speed of light
630 * in m/usec (300) to get round-trip time in microseconds
631 * and then divide the result by three to get coverage class
632 * as specified in IEEE 802.11-2007 table 7-27.
633 * Values are rounded upwards.
635 coverage
= (distance
+ 449) / 450;
639 NLA_PUT_U8(msg
, NL80211_ATTR_WIPHY_COVERAGE_CLASS
, coverage
);
646 COMMAND(set
, distance
, "<auto|distance>",
647 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_distance
,
648 "Enable ACK timeout estimation algorithm (dynack) or set appropriate\n"
649 "coverage class for given link distance in meters.\n"
650 "To disable dynack set valid value for coverage class.\n"
651 "Valid values: 0 - 114750");
653 static int handle_txpower(struct nl80211_state
*state
,
655 int argc
, char **argv
,
658 enum nl80211_tx_power_setting type
;
661 /* get the required args */
662 if (argc
!= 1 && argc
!= 2)
665 if (!strcmp(argv
[0], "auto"))
666 type
= NL80211_TX_POWER_AUTOMATIC
;
667 else if (!strcmp(argv
[0], "fixed"))
668 type
= NL80211_TX_POWER_FIXED
;
669 else if (!strcmp(argv
[0], "limit"))
670 type
= NL80211_TX_POWER_LIMITED
;
672 printf("Invalid parameter: %s\n", argv
[0]);
676 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_SETTING
, type
);
678 if (type
!= NL80211_TX_POWER_AUTOMATIC
) {
681 printf("Missing TX power level argument.\n");
685 mbm
= strtol(argv
[1], &endptr
, 10);
688 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_TX_POWER_LEVEL
, mbm
);
689 } else if (argc
!= 1)
697 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
698 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_txpower
,
699 "Specify transmit power level and setting type.");
700 COMMAND(set
, txpower
, "<auto|fixed|limit> [<tx power in mBm>]",
701 NL80211_CMD_SET_WIPHY
, 0, CIB_NETDEV
, handle_txpower
,
702 "Specify transmit power level and setting type.");
704 static int handle_antenna(struct nl80211_state
*state
,
706 int argc
, char **argv
,
710 uint32_t tx_ant
= 0, rx_ant
= 0;
712 if (argc
== 1 && strcmp(argv
[0], "all") == 0) {
715 } else if (argc
== 1) {
716 tx_ant
= rx_ant
= strtoul(argv
[0], &end
, 0);
720 else if (argc
== 2) {
721 tx_ant
= strtoul(argv
[0], &end
, 0);
724 rx_ant
= strtoul(argv
[1], &end
, 0);
730 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_TX
, tx_ant
);
731 NLA_PUT_U32(msg
, NL80211_ATTR_WIPHY_ANTENNA_RX
, rx_ant
);
738 COMMAND(set
, antenna
, "<bitmap> | all | <tx bitmap> <rx bitmap>",
739 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_antenna
,
740 "Set a bitmap of allowed antennas to use for TX and RX.\n"
741 "The driver may reject antenna configurations it cannot support.");
743 static int handle_set_txq(struct nl80211_state
*state
,
745 int argc
, char **argv
,
754 if (!*argv
[0] || !*argv
[1])
757 argval
= strtoul(argv
[1], &end
, 10);
765 if (strcmp("limit", argv
[0]) == 0)
766 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_LIMIT
, argval
);
767 else if (strcmp("memory_limit", argv
[0]) == 0)
768 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_MEMORY_LIMIT
, argval
);
769 else if (strcmp("quantum", argv
[0]) == 0)
770 NLA_PUT_U32(msg
, NL80211_ATTR_TXQ_QUANTUM
, argval
);
778 COMMAND(set
, txq
, "limit <packets> | memory_limit <bytes> | quantum <bytes>",
779 NL80211_CMD_SET_WIPHY
, 0, CIB_PHY
, handle_set_txq
,
780 "Set TXQ parameters. The limit and memory_limit are global queue limits\n"
781 "for the whole phy. The quantum is the DRR scheduler quantum setting.\n"
782 "Valid values: 1 - 2**32");
784 static int print_txq_handler(struct nl_msg
*msg
, void *arg
)
786 struct nlattr
*attrs
[NL80211_ATTR_MAX
+ 1];
787 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
788 struct nlattr
*txqstats_info
[NL80211_TXQ_STATS_MAX
+ 1], *txqinfo
;
789 static struct nla_policy txqstats_policy
[NL80211_TXQ_STATS_MAX
+ 1] = {
790 [NL80211_TXQ_STATS_BACKLOG_PACKETS
] = { .type
= NLA_U32
},
791 [NL80211_TXQ_STATS_BACKLOG_BYTES
] = { .type
= NLA_U32
},
792 [NL80211_TXQ_STATS_OVERLIMIT
] = { .type
= NLA_U32
},
793 [NL80211_TXQ_STATS_OVERMEMORY
] = { .type
= NLA_U32
},
794 [NL80211_TXQ_STATS_COLLISIONS
] = { .type
= NLA_U32
},
795 [NL80211_TXQ_STATS_MAX_FLOWS
] = { .type
= NLA_U32
},
798 nla_parse(attrs
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
799 genlmsg_attrlen(gnlh
, 0), NULL
);
802 if (attrs
[NL80211_ATTR_TXQ_LIMIT
])
803 printf("Packet limit:\t\t%u pkts\n",
804 nla_get_u32(attrs
[NL80211_ATTR_TXQ_LIMIT
]));
805 if (attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
])
806 printf("Memory limit:\t\t%u bytes\n",
807 nla_get_u32(attrs
[NL80211_ATTR_TXQ_MEMORY_LIMIT
]));
808 if (attrs
[NL80211_ATTR_TXQ_QUANTUM
])
809 printf("Quantum:\t\t%u bytes\n",
810 nla_get_u32(attrs
[NL80211_ATTR_TXQ_QUANTUM
]));
812 if (attrs
[NL80211_ATTR_TXQ_STATS
]) {
813 if (nla_parse_nested(txqstats_info
, NL80211_TXQ_STATS_MAX
,
814 attrs
[NL80211_ATTR_TXQ_STATS
],
816 printf("failed to parse nested TXQ stats attributes!");
819 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_MAX_FLOWS
];
821 printf("Number of queues:\t%u\n", nla_get_u32(txqinfo
));
823 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_PACKETS
];
825 printf("Backlog:\t\t%u pkts\n", nla_get_u32(txqinfo
));
827 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_BACKLOG_BYTES
];
829 printf("Memory usage:\t\t%u bytes\n", nla_get_u32(txqinfo
));
831 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERLIMIT
];
833 printf("Packet limit overflows:\t%u\n", nla_get_u32(txqinfo
));
835 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_OVERMEMORY
];
837 printf("Memory limit overflows:\t%u\n", nla_get_u32(txqinfo
));
838 txqinfo
= txqstats_info
[NL80211_TXQ_STATS_COLLISIONS
];
840 printf("Hash collisions:\t%u\n", nla_get_u32(txqinfo
));
845 static int handle_get_txq(struct nl80211_state
*state
,
847 int argc
, char **argv
,
850 nla_put_flag(msg
, NL80211_ATTR_SPLIT_WIPHY_DUMP
);
851 nlmsg_hdr(msg
)->nlmsg_flags
|= NLM_F_DUMP
;
852 register_handler(print_txq_handler
, NULL
);
855 COMMAND(get
, txq
, "",
856 NL80211_CMD_GET_WIPHY
, 0, CIB_PHY
, handle_get_txq
,
857 "Get TXQ parameters.");