1 /* 2 * src/nl-qdisc-list.c List Queueing Disciplines 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-2010 Thomas Graf <tgraf (at) suug.ch> 10 */ 11 12 #include <netlink/cli/utils.h> 13 #include <netlink/cli/tc.h> 14 #include <netlink/cli/qdisc.h> 15 #include <netlink/cli/class.h> 16 #include <netlink/cli/cls.h> 17 #include <netlink/cli/link.h> 18 19 #define NUM_INDENT 4 20 21 static struct nl_sock *sock; 22 static int recursive = 0; 23 static struct nl_dump_params params = { 24 .dp_type = NL_DUMP_LINE, 25 }; 26 27 static void print_usage(void) 28 { 29 printf( 30 "Usage: nl-qdisc-list [OPTION]... [QDISC]\n" 31 "\n" 32 "OPTIONS\n" 33 " --details Show details\n" 34 " --stats Show statistics\n" 35 " -r, --recursive Show recursive tree\n" 36 " -h, --help Show this help\n" 37 " -v, --version Show versioning information\n" 38 "\n" 39 " -d, --dev=DEV Device the qdisc is attached to. (default: all)\n" 40 " -p, --parent=ID Identifier of parent qdisc.\n" 41 " -i, --id=ID Identifier.\n" 42 " -k, --kind=NAME Kind of qdisc (e.g. pfifo_fast)\n" 43 "\n" 44 "EXAMPLE\n" 45 " # Display statistics of all qdiscs attached to eth0\n" 46 " $ nl-qdisc-list --details --dev=eth0\n" 47 "\n" 48 ); 49 exit(0); 50 } 51 52 static void list_classes(int ifindex, uint32_t parent); 53 static void list_qdiscs(int ifindex, uint32_t parent); 54 55 static void list_class(struct nl_object *obj, void *arg) 56 { 57 struct rtnl_tc *tc = nl_object_priv(obj); 58 nl_object_dump(obj, ¶ms); 59 60 list_classes(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); 61 list_qdiscs(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); 62 } 63 64 static void list_classes(int ifindex, uint32_t parent) 65 { 66 struct nl_cache *class_cache; 67 struct rtnl_class *filter = nl_cli_class_alloc(); 68 69 class_cache = nl_cli_class_alloc_cache(sock, ifindex); 70 71 rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); 72 params.dp_prefix += NUM_INDENT; 73 nl_cache_foreach_filter(class_cache, OBJ_CAST(filter), list_class, NULL); 74 params.dp_prefix -= NUM_INDENT; 75 76 rtnl_class_put(filter); 77 nl_cache_free(class_cache); 78 } 79 80 static void list_cls(int ifindex, uint32_t parent) 81 { 82 struct nl_cache *cls_cache; 83 84 cls_cache = nl_cli_cls_alloc_cache(sock, ifindex, parent); 85 86 params.dp_prefix += NUM_INDENT; 87 nl_cache_dump(cls_cache, ¶ms); 88 params.dp_prefix -= NUM_INDENT; 89 90 nl_cache_free(cls_cache); 91 } 92 93 static void list_qdisc(struct nl_object *obj, void *arg) 94 { 95 struct rtnl_qdisc *qdisc = nl_object_priv(obj); 96 struct rtnl_tc *tc = (struct rtnl_tc *) qdisc; 97 98 nl_object_dump(obj, ¶ms); 99 100 list_cls(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); 101 102 if (rtnl_tc_get_parent(tc) == TC_H_ROOT) { 103 list_cls(rtnl_tc_get_ifindex(tc), TC_H_ROOT); 104 list_classes(rtnl_tc_get_ifindex(tc), TC_H_ROOT); 105 } 106 107 list_classes(rtnl_tc_get_ifindex(tc), rtnl_tc_get_handle(tc)); 108 } 109 110 static void list_qdiscs(int ifindex, uint32_t parent) 111 { 112 struct nl_cache *qdisc_cache; 113 struct rtnl_qdisc *filter = nl_cli_qdisc_alloc(); 114 115 qdisc_cache = nl_cli_qdisc_alloc_cache(sock); 116 117 rtnl_tc_set_ifindex((struct rtnl_tc *) filter, ifindex); 118 rtnl_tc_set_parent((struct rtnl_tc *) filter, parent); 119 params.dp_prefix += NUM_INDENT; 120 nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(filter), list_qdisc, NULL); 121 params.dp_prefix -= NUM_INDENT; 122 123 rtnl_qdisc_put(filter); 124 nl_cache_free(qdisc_cache); 125 } 126 127 int main(int argc, char *argv[]) 128 { 129 struct rtnl_qdisc *qdisc; 130 struct rtnl_tc *tc; 131 struct nl_cache *link_cache, *qdisc_cache; 132 133 params.dp_fd = stdout; 134 sock = nl_cli_alloc_socket(); 135 nl_cli_connect(sock, NETLINK_ROUTE); 136 link_cache = nl_cli_link_alloc_cache(sock); 137 qdisc_cache = nl_cli_qdisc_alloc_cache(sock); 138 qdisc = nl_cli_qdisc_alloc(); 139 tc = (struct rtnl_tc *) qdisc; 140 141 for (;;) { 142 int c, optidx = 0; 143 enum { 144 ARG_DETAILS = 257, 145 ARG_STATS = 258, 146 }; 147 static struct option long_opts[] = { 148 { "details", 0, 0, ARG_DETAILS }, 149 { "stats", 0, 0, ARG_STATS }, 150 { "recursive", 0, 0, 'r' }, 151 { "help", 0, 0, 'h' }, 152 { "version", 0, 0, 'v' }, 153 { "dev", 1, 0, 'd' }, 154 { "parent", 1, 0, 'p' }, 155 { "id", 1, 0, 'i' }, 156 { "kind", 1, 0, 'k' }, 157 { 0, 0, 0, 0 } 158 }; 159 160 c = getopt_long(argc, argv, "rhvd:p:i:k:", long_opts, &optidx); 161 if (c == -1) 162 break; 163 164 switch (c) { 165 case ARG_DETAILS: params.dp_type = NL_DUMP_DETAILS; break; 166 case ARG_STATS: params.dp_type = NL_DUMP_STATS; break; 167 case 'r': recursive = 1; break; 168 case 'h': print_usage(); break; 169 case 'v': nl_cli_print_version(); break; 170 case 'd': nl_cli_tc_parse_dev(tc, link_cache, optarg); break; 171 case 'p': nl_cli_tc_parse_parent(tc, optarg); break; 172 case 'i': nl_cli_tc_parse_handle(tc, optarg, 0); break; 173 case 'k': nl_cli_tc_parse_kind(tc, optarg); break; 174 } 175 } 176 177 if (recursive) 178 nl_cache_foreach_filter(qdisc_cache, OBJ_CAST(qdisc), list_qdisc, NULL); 179 else 180 nl_cache_dump_filter(qdisc_cache, ¶ms, OBJ_CAST(qdisc)); 181 182 return 0; 183 } 184