Home | History | Annotate | Download | only in src
      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, &params);
     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, &params);
     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, &params);
     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, &params, OBJ_CAST(qdisc));
    181 
    182 	return 0;
    183 }
    184