Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools: ynl: add a sample for TC

Add a very simple TC dump sample with decoding of fq_codel attrs:

# ./tools/net/ynl/samples/tc
dummy0: fq_codel limit: 10240p target: 5ms new_flow_cnt: 0

proving that selector passing (for stats) works.

Reviewed-by: Donald Hunter <donald.hunter@gmail.com>
Link: https://patch.msgid.link/20250520161916.413298-13-kuba@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+81
+1
tools/net/ynl/samples/.gitignore
··· 6 6 rt-addr 7 7 rt-link 8 8 rt-route 9 + tc
+80
tools/net/ynl/samples/tc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <stdio.h> 3 + #include <string.h> 4 + 5 + #include <ynl.h> 6 + 7 + #include <net/if.h> 8 + 9 + #include "tc-user.h" 10 + 11 + static void tc_qdisc_print(struct tc_getqdisc_rsp *q) 12 + { 13 + char ifname[IF_NAMESIZE]; 14 + const char *name; 15 + 16 + name = if_indextoname(q->_hdr.tcm_ifindex, ifname); 17 + if (name) 18 + printf("%16s: ", name); 19 + 20 + if (q->_len.kind) { 21 + printf("%s ", q->kind); 22 + 23 + if (q->options._present.fq_codel) { 24 + struct tc_fq_codel_attrs *fq_codel; 25 + struct tc_fq_codel_xstats *stats; 26 + 27 + fq_codel = &q->options.fq_codel; 28 + stats = q->stats2.app.fq_codel; 29 + 30 + if (fq_codel->_present.limit) 31 + printf("limit: %dp ", fq_codel->limit); 32 + if (fq_codel->_present.target) 33 + printf("target: %dms ", 34 + (fq_codel->target + 500) / 1000); 35 + if (q->stats2.app._len.fq_codel) 36 + printf("new_flow_cnt: %d ", 37 + stats->qdisc_stats.new_flow_count); 38 + } 39 + } 40 + 41 + printf("\n"); 42 + } 43 + 44 + int main(int argc, char **argv) 45 + { 46 + struct tc_getqdisc_req_dump *req; 47 + struct tc_getqdisc_list *rsp; 48 + struct ynl_error yerr; 49 + struct ynl_sock *ys; 50 + 51 + ys = ynl_sock_create(&ynl_tc_family, &yerr); 52 + if (!ys) { 53 + fprintf(stderr, "YNL: %s\n", yerr.msg); 54 + return 1; 55 + } 56 + 57 + req = tc_getqdisc_req_dump_alloc(); 58 + if (!req) 59 + goto err_destroy; 60 + 61 + rsp = tc_getqdisc_dump(ys, req); 62 + tc_getqdisc_req_dump_free(req); 63 + if (!rsp) 64 + goto err_close; 65 + 66 + if (ynl_dump_empty(rsp)) 67 + fprintf(stderr, "Error: no addresses reported\n"); 68 + ynl_dump_foreach(rsp, qdisc) 69 + tc_qdisc_print(qdisc); 70 + tc_getqdisc_list_free(rsp); 71 + 72 + ynl_sock_destroy(ys); 73 + return 0; 74 + 75 + err_close: 76 + fprintf(stderr, "YNL: %s\n", ys->err.msg); 77 + err_destroy: 78 + ynl_sock_destroy(ys); 79 + return 2; 80 + }