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