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