1/* 2 * src/nl-tctree-list.c List Traffic Control Tree 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2009 Thomas Graf <tgraf@suug.ch> 10 */ 11 12#include <netlink/cli/utils.h> 13#include <netlink/cli/link.h> 14#include <netlink/cli/qdisc.h> 15#include <linux/pkt_sched.h> 16 17static struct nl_sock *sock; 18static struct nl_cache *qdisc_cache, *class_cache; 19static struct nl_dump_params params = { 20 .dp_type = NL_DUMP_DETAILS, 21}; 22 23static int ifindex; 24static void print_qdisc(struct nl_object *, void *); 25 26static void print_usage(void) 27{ 28 printf( 29 "Usage: nl-tctree-list [OPTION]...\n" 30 "\n" 31 "Options\n" 32 " -f, --format=TYPE Output format { brief | details | stats }\n" 33 " -h, --help Show this help\n" 34 " -v, --version Show versioning information\n" 35 ); 36 exit(0); 37} 38 39static void print_class(struct nl_object *obj, void *arg) 40{ 41 struct rtnl_qdisc *leaf; 42 struct rtnl_class *class = (struct rtnl_class *) obj; 43 struct nl_cache *cls_cache; 44 uint32_t parent = rtnl_class_get_handle(class); 45 46 params.dp_prefix = (int)(long) arg; 47 nl_object_dump(obj, ¶ms); 48 49 leaf = rtnl_class_leaf_qdisc(class, qdisc_cache); 50 if (leaf) 51 print_qdisc((struct nl_object *) leaf, arg + 2); 52 53 rtnl_class_foreach_child(class, class_cache, &print_class, arg + 2); 54 55 if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) 56 return; 57 58 params.dp_prefix = (int)(long) arg + 2; 59 nl_cache_dump(cls_cache, ¶ms); 60 nl_cache_free(cls_cache); 61} 62 63static void print_qdisc(struct nl_object *obj, void *arg) 64{ 65 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) obj; 66 struct nl_cache *cls_cache; 67 uint32_t parent = rtnl_qdisc_get_handle(qdisc); 68 69 params.dp_prefix = (int)(long) arg; 70 nl_object_dump(obj, ¶ms); 71 72 rtnl_qdisc_foreach_child(qdisc, class_cache, &print_class, arg + 2); 73 74 if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) 75 return; 76 77 params.dp_prefix = (int)(long) arg + 2; 78 nl_cache_dump(cls_cache, ¶ms); 79 nl_cache_free(cls_cache); 80} 81 82static void print_link(struct nl_object *obj, void *arg) 83{ 84 struct rtnl_link *link = (struct rtnl_link *) obj; 85 struct rtnl_qdisc *qdisc; 86 87 ifindex = rtnl_link_get_ifindex(link); 88 params.dp_prefix = 0; 89 nl_object_dump(obj, ¶ms); 90 91 if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0) 92 return; 93 94 qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); 95 if (qdisc) { 96 print_qdisc((struct nl_object *) qdisc, (void *) 2); 97 rtnl_qdisc_put(qdisc); 98 } 99 100 qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0); 101 if (qdisc) { 102 print_qdisc((struct nl_object *) qdisc, (void *) 2); 103 rtnl_qdisc_put(qdisc); 104 } 105 106 qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS); 107 if (qdisc) { 108 print_qdisc((struct nl_object *) qdisc, (void *) 2); 109 rtnl_qdisc_put(qdisc); 110 } 111 112 nl_cache_free(class_cache); 113} 114 115int main(int argc, char *argv[]) 116{ 117 struct nl_cache *link_cache; 118 119 sock = nl_cli_alloc_socket(); 120 nl_cli_connect(sock, NETLINK_ROUTE); 121 link_cache = nl_cli_link_alloc_cache(sock); 122 qdisc_cache = nl_cli_qdisc_alloc_cache(sock); 123 124 params.dp_fd = stdout; 125 126 for (;;) { 127 int c, optidx = 0; 128 static struct option long_opts[] = { 129 { "format", 1, 0, 'f' }, 130 { "help", 0, 0, 'h' }, 131 { "version", 0, 0, 'v' }, 132 { 0, 0, 0, 0 } 133 }; 134 135 c = getopt_long(argc, argv, "f:hv", long_opts, &optidx); 136 if (c == -1) 137 break; 138 139 switch (c) { 140 case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; 141 case 'h': print_usage(); break; 142 case 'v': nl_cli_print_version(); break; 143 } 144 } 145 146 nl_cache_foreach(link_cache, &print_link, NULL); 147 148 return 0; 149} 150