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