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