1 /*
2  * src/lib/htb.c     	HTB module for CLI lib
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) 2010-2011 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 #include <netlink/cli/utils.h>
13 #include <netlink/cli/tc.h>
14 #include <netlink/route/qdisc/htb.h>
15 
print_qdisc_usage(void)16 static void print_qdisc_usage(void)
17 {
18 	printf(
19 "Usage: nl-qdisc-add [...] htb [OPTIONS]...\n"
20 "\n"
21 "OPTIONS\n"
22 "     --help                Show this help text.\n"
23 "     --r2q=DIV             Rate to quantum divisor (default: 10)\n"
24 "     --default=ID          Default class for unclassified traffic.\n"
25 "\n"
26 "EXAMPLE"
27 "    # Create htb root qdisc 1: and direct unclassified traffic to class 1:10\n"
28 "    nl-qdisc-add --dev=eth1 --parent=root --handle=1: htb --default=10\n");
29 }
30 
htb_parse_qdisc_argv(struct rtnl_tc * tc,int argc,char ** argv)31 static void htb_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv)
32 {
33 	struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
34 
35 	for (;;) {
36 		int c, optidx = 0;
37 		enum {
38 			ARG_R2Q = 257,
39 			ARG_DEFAULT = 258,
40 		};
41 		static struct option long_opts[] = {
42 			{ "help", 0, 0, 'h' },
43 			{ "r2q", 1, 0, ARG_R2Q },
44 			{ "default", 1, 0, ARG_DEFAULT },
45 			{ 0, 0, 0, 0 }
46 		};
47 
48 		c = getopt_long(argc, argv, "hv", long_opts, &optidx);
49 		if (c == -1)
50 			break;
51 
52 		switch (c) {
53 		case 'h':
54 			print_qdisc_usage();
55 			return;
56 
57 		case ARG_R2Q:
58 			rtnl_htb_set_rate2quantum(qdisc, nl_cli_parse_u32(optarg));
59 			break;
60 
61 		case ARG_DEFAULT:
62 			rtnl_htb_set_defcls(qdisc, nl_cli_parse_u32(optarg));
63 			break;
64 		}
65 	}
66 }
67 
print_class_usage(void)68 static void print_class_usage(void)
69 {
70 	printf(
71 "Usage: nl-class-add [...] htb [OPTIONS]...\n"
72 "\n"
73 "OPTIONS\n"
74 "     --help                Show this help text.\n"
75 "     --rate=RATE           Rate limit.\n"
76 "     --ceil=RATE           Rate limit while borrowing (default: equal to --rate).\n"
77 "     --prio=PRIO           Priority, lower is served first (default: 0).\n"
78 "     --quantum=SIZE        Amount of bytes to serve at once (default: rate/r2q).\n"
79 "     --burst=SIZE          Max charge size of rate burst buffer (default: auto).\n"
80 "     --cburst=SIZE         Max charge size of ceil rate burst buffer (default: auto)\n"
81 "\n"
82 "EXAMPLE"
83 "    # Attach class 1:1 to htb qdisc 1: and rate limit it to 20mbit\n"
84 "    nl-class-add --dev=eth1 --parent=1: --classid=1:1 htb --rate=20mbit\n");
85 }
86 
htb_parse_class_argv(struct rtnl_tc * tc,int argc,char ** argv)87 static void htb_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv)
88 {
89 	struct rtnl_class *class = (struct rtnl_class *) tc;
90 	long rate;
91 
92 	for (;;) {
93 		int c, optidx = 0;
94 		enum {
95 			ARG_RATE = 257,
96 			ARG_QUANTUM = 258,
97 			ARG_CEIL,
98 			ARG_PRIO,
99 			ARG_BURST,
100 			ARG_CBURST,
101 		};
102 		static struct option long_opts[] = {
103 			{ "help", 0, 0, 'h' },
104 			{ "rate", 1, 0, ARG_RATE },
105 			{ "quantum", 1, 0, ARG_QUANTUM },
106 			{ "ceil", 1, 0, ARG_CEIL },
107 			{ "prio", 1, 0, ARG_PRIO },
108 			{ "burst", 1, 0, ARG_BURST },
109 			{ "cburst", 1, 0, ARG_CBURST },
110 			{ 0, 0, 0, 0 }
111 		};
112 
113 		c = getopt_long(argc, argv, "h", long_opts, &optidx);
114 		if (c == -1)
115 			break;
116 
117 		switch (c) {
118 		case 'h':
119 			print_class_usage();
120 			return;
121 
122 		case ARG_RATE:
123 			rate = nl_size2int(optarg);
124 			if (rate < 0) {
125 				nl_cli_fatal(rate, "Unable to parse htb rate "
126 					"\"%s\": Invalid format.", optarg);
127 			}
128 
129 			rtnl_htb_set_rate(class, rate);
130 			break;
131 
132 		case ARG_CEIL:
133 			rate = nl_size2int(optarg);
134 			if (rate < 0) {
135 				nl_cli_fatal(rate, "Unable to parse htb ceil rate "
136 					"\"%s\": Invalid format.", optarg);
137 			}
138 
139 			rtnl_htb_set_ceil(class, rate);
140 			break;
141 
142 		case ARG_PRIO:
143 			rtnl_htb_set_prio(class, nl_cli_parse_u32(optarg));
144 			break;
145 
146 		case ARG_QUANTUM:
147 			rate = nl_size2int(optarg);
148 			if (rate < 0) {
149 				nl_cli_fatal(rate, "Unable to parse quantum "
150 					"\"%s\": Invalid format.", optarg);
151 			}
152 
153 			rtnl_htb_set_quantum(class, rate);
154 			break;
155 
156 		case ARG_BURST:
157 			rate = nl_size2int(optarg);
158 			if (rate < 0) {
159 				nl_cli_fatal(rate, "Unable to parse burst "
160 					"\"%s\": Invalid format.", optarg);
161 			}
162 
163 			rtnl_htb_set_rbuffer(class, rate);
164 			break;
165 
166 		case ARG_CBURST:
167 			rate = nl_size2int(optarg);
168 			if (rate < 0) {
169 				nl_cli_fatal(rate, "Unable to parse cburst "
170 					"\"%s\": Invalid format.", optarg);
171 			}
172 
173 			rtnl_htb_set_cbuffer(class, rate);
174 			break;
175 		}
176 	}
177 }
178 
179 static struct nl_cli_tc_module htb_qdisc_module =
180 {
181 	.tm_name		= "htb",
182 	.tm_type		= RTNL_TC_TYPE_QDISC,
183 	.tm_parse_argv		= htb_parse_qdisc_argv,
184 };
185 
186 static struct nl_cli_tc_module htb_class_module =
187 {
188 	.tm_name		= "htb",
189 	.tm_type		= RTNL_TC_TYPE_CLASS,
190 	.tm_parse_argv		= htb_parse_class_argv,
191 };
192 
htb_init(void)193 static void __init htb_init(void)
194 {
195 	nl_cli_tc_register(&htb_qdisc_module);
196 	nl_cli_tc_register(&htb_class_module);
197 }
198 
htb_exit(void)199 static void __exit htb_exit(void)
200 {
201 	nl_cli_tc_unregister(&htb_class_module);
202 	nl_cli_tc_unregister(&htb_qdisc_module);
203 }
204