root/tools/net/ynl/samples/tc.c
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <string.h>

#include <ynl.h>

#include <net/if.h>

#include "tc-user.h"

static void tc_qdisc_print(struct tc_getqdisc_rsp *q)
{
        char ifname[IF_NAMESIZE];
        const char *name;

        name = if_indextoname(q->_hdr.tcm_ifindex, ifname);
        if (name)
                printf("%16s: ", name);

        if (q->_len.kind) {
                printf("%s  ", q->kind);

                if (q->options._present.fq_codel) {
                        struct tc_fq_codel_attrs *fq_codel;
                        struct tc_fq_codel_xstats *stats;

                        fq_codel = &q->options.fq_codel;
                        stats = q->stats2.app.fq_codel;

                        if (fq_codel->_present.limit)
                                printf("limit: %dp ", fq_codel->limit);
                        if (fq_codel->_present.target)
                                printf("target: %dms ",
                                       (fq_codel->target + 500) / 1000);
                        if (q->stats2.app._len.fq_codel)
                                printf("new_flow_cnt: %d ",
                                       stats->qdisc_stats.new_flow_count);
                }
        }

        printf("\n");
}

int main(int argc, char **argv)
{
        struct tc_getqdisc_req_dump *req;
        struct tc_getqdisc_list *rsp;
        struct ynl_error yerr;
        struct ynl_sock *ys;

        ys = ynl_sock_create(&ynl_tc_family, &yerr);
        if (!ys) {
                fprintf(stderr, "YNL: %s\n", yerr.msg);
                return 1;
        }

        req = tc_getqdisc_req_dump_alloc();
        if (!req)
                goto err_destroy;

        rsp = tc_getqdisc_dump(ys, req);
        tc_getqdisc_req_dump_free(req);
        if (!rsp)
                goto err_close;

        if (ynl_dump_empty(rsp))
                fprintf(stderr, "Error: no addresses reported\n");
        ynl_dump_foreach(rsp, qdisc)
                tc_qdisc_print(qdisc);
        tc_getqdisc_list_free(rsp);

        ynl_sock_destroy(ys);
        return 0;

err_close:
        fprintf(stderr, "YNL: %s\n", ys->err.msg);
err_destroy:
        ynl_sock_destroy(ys);
        return 2;
}