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 (at) suug.ch> 10 */ 11 12 #include <netlink/cli/utils.h> 13 #include <netlink/cli/link.h> 14 #include <netlink/cli/qdisc.h> 15 #include <netlink/cli/class.h> 16 #include <linux/pkt_sched.h> 17 18 static struct nl_sock *sock; 19 static struct nl_cache *qdisc_cache, *class_cache; 20 static struct nl_dump_params params = { 21 .dp_type = NL_DUMP_DETAILS, 22 }; 23 24 static int ifindex; 25 static void print_qdisc(struct nl_object *, void *); 26 static void print_tc_childs(struct rtnl_tc *, void *); 27 28 static void print_usage(void) 29 { 30 printf( 31 "Usage: nl-tctree-list [OPTION]...\n" 32 "\n" 33 "Options\n" 34 " -f, --format=TYPE Output format { brief | details | stats }\n" 35 " -h, --help Show this help\n" 36 " -v, --version Show versioning information\n" 37 ); 38 exit(0); 39 } 40 41 static void print_class(struct nl_object *obj, void *arg) 42 { 43 struct rtnl_qdisc *leaf; 44 struct rtnl_class *class = (struct rtnl_class *) obj; 45 struct nl_cache *cls_cache; 46 uint32_t parent = rtnl_tc_get_handle((struct rtnl_tc *) class); 47 48 params.dp_prefix = (int)(long) arg; 49 nl_object_dump(obj, ¶ms); 50 51 leaf = rtnl_class_leaf_qdisc(class, qdisc_cache); 52 if (leaf) 53 print_qdisc((struct nl_object *) leaf, arg + 2); 54 55 print_tc_childs(TC_CAST(class), arg + 2); 56 57 if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) 58 return; 59 60 params.dp_prefix = (int)(long) arg + 2; 61 nl_cache_dump(cls_cache, ¶ms); 62 nl_cache_free(cls_cache); 63 } 64 65 static void print_tc_childs(struct rtnl_tc *tc, void *arg) 66 { 67 struct rtnl_class *filter; 68 69 filter = nl_cli_class_alloc(); 70 71 rtnl_tc_set_parent(TC_CAST(filter), rtnl_tc_get_handle(tc)); 72 rtnl_tc_set_ifindex(TC_CAST(filter), rtnl_tc_get_ifindex(tc)); 73 74 nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), &print_class, arg); 75 76 rtnl_class_put(filter); 77 } 78 79 static void print_qdisc(struct nl_object *obj, void *arg) 80 { 81 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) obj; 82 struct nl_cache *cls_cache; 83 uint32_t parent = rtnl_tc_get_handle((struct rtnl_tc *) qdisc); 84 85 params.dp_prefix = (int)(long) arg; 86 nl_object_dump(obj, ¶ms); 87 88 print_tc_childs(TC_CAST(qdisc), arg + 2); 89 90 if (rtnl_cls_alloc_cache(sock, ifindex, parent, &cls_cache) < 0) 91 return; 92 93 params.dp_prefix = (int)(long) arg + 2; 94 nl_cache_dump(cls_cache, ¶ms); 95 nl_cache_free(cls_cache); 96 } 97 98 static void print_link(struct nl_object *obj, void *arg) 99 { 100 struct rtnl_link *link = (struct rtnl_link *) obj; 101 struct rtnl_qdisc *qdisc; 102 103 ifindex = rtnl_link_get_ifindex(link); 104 params.dp_prefix = 0; 105 nl_object_dump(obj, ¶ms); 106 107 if (rtnl_class_alloc_cache(sock, ifindex, &class_cache) < 0) 108 return; 109 110 qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_ROOT); 111 if (qdisc) { 112 print_qdisc((struct nl_object *) qdisc, (void *) 2); 113 rtnl_qdisc_put(qdisc); 114 } 115 116 qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, 0); 117 if (qdisc) { 118 print_qdisc((struct nl_object *) qdisc, (void *) 2); 119 rtnl_qdisc_put(qdisc); 120 } 121 122 qdisc = rtnl_qdisc_get_by_parent(qdisc_cache, ifindex, TC_H_INGRESS); 123 if (qdisc) { 124 print_qdisc((struct nl_object *) qdisc, (void *) 2); 125 rtnl_qdisc_put(qdisc); 126 } 127 128 nl_cache_free(class_cache); 129 } 130 131 int main(int argc, char *argv[]) 132 { 133 struct nl_cache *link_cache; 134 135 sock = nl_cli_alloc_socket(); 136 nl_cli_connect(sock, NETLINK_ROUTE); 137 link_cache = nl_cli_link_alloc_cache(sock); 138 qdisc_cache = nl_cli_qdisc_alloc_cache(sock); 139 140 params.dp_fd = stdout; 141 142 for (;;) { 143 int c, optidx = 0; 144 static struct option long_opts[] = { 145 { "format", 1, 0, 'f' }, 146 { "help", 0, 0, 'h' }, 147 { "version", 0, 0, 'v' }, 148 { 0, 0, 0, 0 } 149 }; 150 151 c = getopt_long(argc, argv, "f:hv", long_opts, &optidx); 152 if (c == -1) 153 break; 154 155 switch (c) { 156 case 'f': params.dp_type = nl_cli_parse_dumptype(optarg); break; 157 case 'h': print_usage(); break; 158 case 'v': nl_cli_print_version(); break; 159 } 160 } 161 162 nl_cache_foreach(link_cache, &print_link, NULL); 163 164 return 0; 165 } 166