libnl: /data/src/libnl3/lib/cli/qdisc/hfsc.c Source File

libnl 3.7.0

hfsc.c
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3 * Copyright (c) 2014 Cong Wang <xiyou.wangcong@gmail.com>
4 */
5
6 #include <netlink/cli/utils.h>
7 #include <netlink/cli/tc.h>
8 #include <netlink/route/qdisc/hfsc.h>
9 #include <linux/pkt_sched.h>
10
11 static void print_qdisc_usage(void)
12 {
13 printf(
14 "Usage: nl-qdisc-add [...] hfsc [OPTIONS]...\n"
15 "\n"
16 "OPTIONS\n"
17 " --help Show this help text.\n"
18 " --default=ID Default class for unclassified traffic.\n"
19 "\n"
20 "EXAMPLE"
21 " # Create hfsc root qdisc 1: and direct unclassified traffic to class 1:10\n"
22 " nl-qdisc-add --dev=eth1 --parent=root --handle=1: hfsc --default=10\n");
23 }
24
25 static void hfsc_parse_qdisc_argv(struct rtnl_tc *tc, int argc, char **argv)
26 {
27 struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
28
29 for (;;) {
30 int c, optidx = 0;
31 enum {
32 ARG_DEFAULT = 257,
33 };
34 static struct option long_opts[] = {
35 { "help", 0, 0, 'h' },
36 { "default", 1, 0, ARG_DEFAULT },
37 { 0, 0, 0, 0 }
38 };
39
40 c = getopt_long(argc, argv, "hv", long_opts, &optidx);
41 if (c == -1)
42 break;
43
44 switch (c) {
45 case 'h':
46 print_qdisc_usage();
47 return;
48
49 case ARG_DEFAULT:
50 rtnl_qdisc_hfsc_set_defcls(qdisc, nl_cli_parse_u32(optarg));
51 break;
52 }
53 }
54 }
55
56 static void print_class_usage(void)
57 {
58 printf(
59 "Usage: nl-class-add [...] hfsc [OPTIONS]...\n"
60 "\n"
61 "OPTIONS\n"
62 " --help Show this help text.\n"
63 " --ls=SC Link-sharing service curve\n"
64 " --rt=SC Real-time service curve\n"
65 " --sc=SC Specifiy both of the above\n"
66 " --ul=SC Upper limit\n"
67 " where SC := [ [ m1 bits ] d usec ] m2 bits\n"
68 "\n"
69 "EXAMPLE"
70 " # Attach class 1:1 to hfsc qdisc 1: and use rt and ls curve\n"
71 " nl-class-add --dev=eth1 --parent=1: --classid=1:1 hfsc --sc=m1:250,d:8,m2:100\n");
72 }
73
74 static int
75 hfsc_get_sc(char *optarg, struct tc_service_curve *sc)
76 {
77 unsigned int m1 = 0, d = 0, m2 = 0;
78 char *tmp = strdup(optarg);
79 char *p, *endptr;
80 char *pp = tmp;
81
82 if (!tmp)
83 return -ENOMEM;
84
85 p = strstr(pp, "m1:");
86 if (p) {
87 char *q;
88 p += 3;
89 if (*p == 0)
90 goto err;
91 q = strchr(p, ',');
92 if (!q)
93 goto err;
94 *q = 0;
95 m1 = strtoul(p, &endptr, 10);
96 if (endptr == p)
97 goto err;
98 pp = q + 1;
99 }
100
101 p = strstr(pp, "d:");
102 if (p) {
103 char *q;
104 p += 2;
105 if (*p == 0)
106 goto err;
107 q = strchr(p, ',');
108 if (!q)
109 goto err;
110 *q = 0;
111 d = strtoul(p, &endptr, 10);
112 if (endptr == p)
113 goto err;
114 pp = q + 1;
115 }
116
117 p = strstr(pp, "m2:");
118 if (p) {
119 p += 3;
120 if (*p == 0)
121 goto err;
122 m2 = strtoul(p, &endptr, 10);
123 if (endptr == p)
124 goto err;
125 } else
126 goto err;
127
128 free(tmp);
129 sc->m1 = m1;
130 sc->d = d;
131 sc->m2 = m2;
132 return 0;
133
134 err:
135 free(tmp);
136 return -EINVAL;
137 }
138
139 static void hfsc_parse_class_argv(struct rtnl_tc *tc, int argc, char **argv)
140 {
141 struct rtnl_class *class = (struct rtnl_class *) tc;
142 int arg_ok = 0, ret = -EINVAL;
143
144 for (;;) {
145 int c, optidx = 0;
146 enum {
147 ARG_RT = 257,
148 ARG_LS = 258,
149 ARG_SC,
150 ARG_UL,
151 };
152 static struct option long_opts[] = {
153 { "help", 0, 0, 'h' },
154 { "rt", 1, 0, ARG_RT },
155 { "ls", 1, 0, ARG_LS },
156 { "sc", 1, 0, ARG_SC },
157 { "ul", 1, 0, ARG_UL },
158 { 0, 0, 0, 0 }
159 };
160 struct tc_service_curve tsc;
161
162 c = getopt_long(argc, argv, "h", long_opts, &optidx);
163 if (c == -1)
164 break;
165
166 switch (c) {
167 case 'h':
168 print_class_usage();
169 return;
170
171 case ARG_RT:
172 ret = hfsc_get_sc(optarg, &tsc);
173 if (ret < 0) {
174 nl_cli_fatal(ret, "Unable to parse sc "
175 "\"%s\": Invalid format.", optarg);
176 }
177
178 rtnl_class_hfsc_set_rsc(class, &tsc);
179 arg_ok++;
180 break;
181
182 case ARG_LS:
183 ret = hfsc_get_sc(optarg, &tsc);
184 if (ret < 0) {
185 nl_cli_fatal(ret, "Unable to parse sc "
186 "\"%s\": Invalid format.", optarg);
187 }
188
189 rtnl_class_hfsc_set_fsc(class, &tsc);
190 arg_ok++;
191 break;
192
193 case ARG_SC:
194 ret = hfsc_get_sc(optarg, &tsc);
195 if (ret < 0) {
196 nl_cli_fatal(ret, "Unable to parse sc "
197 "\"%s\": Invalid format.", optarg);
198 }
199
200 rtnl_class_hfsc_set_rsc(class, &tsc);
201 rtnl_class_hfsc_set_fsc(class, &tsc);
202 arg_ok++;
203 break;
204
205 case ARG_UL:
206 ret = hfsc_get_sc(optarg, &tsc);
207 if (ret < 0) {
208 nl_cli_fatal(ret, "Unable to parse sc "
209 "\"%s\": Invalid format.", optarg);
210 }
211
212 rtnl_class_hfsc_set_usc(class, &tsc);
213 arg_ok++;
214 break;
215 }
216 }
217
218 if (!arg_ok)
219 nl_cli_fatal(ret, "Invalid arguments");
220 }
221
222 static struct nl_cli_tc_module hfsc_qdisc_module =
223 {
224 .tm_name = "hfsc",
225 .tm_type = RTNL_TC_TYPE_QDISC,
226 .tm_parse_argv = hfsc_parse_qdisc_argv,
227 };
228
229 static struct nl_cli_tc_module hfsc_class_module =
230 {
231 .tm_name = "hfsc",
232 .tm_type = RTNL_TC_TYPE_CLASS,
233 .tm_parse_argv = hfsc_parse_class_argv,
234 };
235
236 static void __init hfsc_init(void)
237 {
238 nl_cli_tc_register(&hfsc_qdisc_module);
239 nl_cli_tc_register(&hfsc_class_module);
240 }
241
242 static void __exit hfsc_exit(void)
243 {
244 nl_cli_tc_unregister(&hfsc_class_module);
245 nl_cli_tc_unregister(&hfsc_qdisc_module);
246 }
nl_cli_fatal
void nl_cli_fatal(int err, const char *fmt,...)
Print error message and quit application.
Definition: utils.c:71
nl_cli_parse_u32
uint32_t nl_cli_parse_u32(const char *arg)
Parse a text based 32 bit unsigned integer argument.
Definition: utils.c:36
rtnl_qdisc_hfsc_set_defcls
int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
Set default class of the hfsc qdisc to the specified value.
Definition: hfsc.c:212
nl_cli_tc_module
Definition: tc.h:27