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