libnl: /data/src/libnl3/lib/route/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 /**
7 * @ingroup qdisc
8 * @ingroup class
9 * @defgroup qdisc_hfsc Hierarchical Fair Service Curve (HFSC)
10 * @{
11 */
12
13 #include <netlink-private/netlink.h>
14 #include <netlink-private/tc.h>
15 #include <netlink/netlink.h>
16 #include <netlink/cache.h>
17 #include <netlink/utils.h>
18 #include <netlink-private/route/tc-api.h>
19 #include <netlink/route/qdisc.h>
20 #include <netlink/route/class.h>
21 #include <netlink/route/link.h>
22 #include <netlink/route/qdisc/hfsc.h>
23
24 /** @cond SKIP */
25 #define SCH_HFSC_CLS_HAS_RSC 0x001
26 #define SCH_HFSC_CLS_HAS_FSC 0x002
27 #define SCH_HFSC_CLS_HAS_USC 0x004
28
29 #define SCH_HFSC_QD_HAS_DEFCLS 0x01
30 /** @endcond */
31
32 static struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
33 [TCA_HFSC_RSC] = { .minlen = sizeof(struct tc_service_curve) },
34 [TCA_HFSC_FSC] = { .minlen = sizeof(struct tc_service_curve) },
35 [TCA_HFSC_USC] = { .minlen = sizeof(struct tc_service_curve) },
36 };
37
38 static int hfsc_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
39 {
40 struct rtnl_hfsc_qdisc *hfsc = data;
41 struct tc_hfsc_qopt *opts;
42
43 opts = (struct tc_hfsc_qopt *) tc->tc_opts->d_data;
44 hfsc->qh_defcls = opts->defcls;
45 hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
46 return 0;
47 }
48
49 static int hfsc_class_msg_parser(struct rtnl_tc *tc, void *data)
50 {
51 struct nlattr *tb[TCA_HFSC_MAX + 1];
52 struct rtnl_hfsc_class *hfsc = data;
53 int err;
54
55 if ((err = tca_parse(tb, TCA_HFSC_MAX, tc, hfsc_policy)) < 0)
56 return err;
57
58 if (tb[TCA_HFSC_RSC]) {
59 struct tc_service_curve tsc;
60
61 nla_memcpy(&tsc, tb[TCA_HFSC_RSC], sizeof(tsc));
62 hfsc->ch_rsc = tsc;
63 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
64 }
65
66 if (tb[TCA_HFSC_FSC]) {
67 struct tc_service_curve tsc;
68
69 nla_memcpy(&tsc, tb[TCA_HFSC_FSC], sizeof(tsc));
70 hfsc->ch_fsc = tsc;
71 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
72 }
73
74 if (tb[TCA_HFSC_USC]) {
75 struct tc_service_curve tsc;
76
77 nla_memcpy(&tsc, tb[TCA_HFSC_USC], sizeof(tsc));
78 hfsc->ch_usc = tsc;
79 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
80 }
81
82 return 0;
83 }
84
85 static void hfsc_qdisc_dump_line(struct rtnl_tc *tc, void *data,
86 struct nl_dump_params *p)
87 {
88 struct rtnl_hfsc_qdisc *hfsc = data;
89
90 if (!hfsc)
91 return;
92
93 if (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS) {
94 char buf[64];
95 nl_dump(p, " default-class %s",
96 rtnl_tc_handle2str(hfsc->qh_defcls, buf, sizeof(buf)));
97 }
98 }
99
100 static void hfsc_dump_tsc(struct nl_dump_params *p, struct tc_service_curve *tsc)
101 {
102 nl_dump(p, " m1 %u d %u m2 %u\n", tsc->m1, tsc->d, tsc->m2);
103 }
104
105 static void hfsc_class_dump_line(struct rtnl_tc *tc, void *data,
106 struct nl_dump_params *p)
107 {
108 struct rtnl_hfsc_class *hfsc = data;
109
110 if (!hfsc)
111 return;
112 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)
113 hfsc_dump_tsc(p, &hfsc->ch_rsc);
114 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)
115 hfsc_dump_tsc(p, &hfsc->ch_fsc);
116 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)
117 hfsc_dump_tsc(p, &hfsc->ch_usc);
118 }
119
120 static void hfsc_class_dump_details(struct rtnl_tc *tc, void *data,
121 struct nl_dump_params *p)
122 {
123 return;
124 }
125
126 static int hfsc_qdisc_msg_fill(struct rtnl_tc *tc, void *data,
127 struct nl_msg *msg)
128 {
129 struct rtnl_hfsc_qdisc *hfsc = data;
130 struct tc_hfsc_qopt opts = {0};
131
132 if (!hfsc)
133 BUG();
134
135 opts.defcls = hfsc->qh_defcls;
136 return nlmsg_append(msg, &opts, sizeof(opts), NL_DONTPAD);
137 }
138
139 static int hfsc_class_msg_fill(struct rtnl_tc *tc, void *data,
140 struct nl_msg *msg)
141 {
142 struct rtnl_hfsc_class *hfsc = data;
143 struct tc_service_curve tsc;
144
145 if (!hfsc)
146 BUG();
147
148 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC) {
149 tsc = hfsc->ch_rsc;
150 NLA_PUT(msg, TCA_HFSC_RSC, sizeof(tsc), &tsc);
151 }
152
153 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC) {
154 tsc = hfsc->ch_fsc;
155 NLA_PUT(msg, TCA_HFSC_FSC, sizeof(tsc), &tsc);
156 }
157
158 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC) {
159 tsc = hfsc->ch_usc;
160 NLA_PUT(msg, TCA_HFSC_USC, sizeof(tsc), &tsc);
161 }
162
163 return 0;
164
165 nla_put_failure:
166 return -NLE_MSGSIZE;
167 }
168
169 static struct rtnl_tc_ops hfsc_qdisc_ops;
170 static struct rtnl_tc_ops hfsc_class_ops;
171
172 static struct rtnl_hfsc_qdisc *hfsc_qdisc_data(const struct rtnl_qdisc *qdisc, int *err)
173 {
174 return rtnl_tc_data_check(TC_CAST(qdisc), &hfsc_qdisc_ops, err);
175 }
176
177 static struct rtnl_hfsc_class *hfsc_class_data(const struct rtnl_class *class, int *err)
178 {
179 return rtnl_tc_data_check(TC_CAST(class), &hfsc_class_ops, err);
180 }
181
182 /**
183 * @name Attribute Modifications
184 * @{
185 */
186
187 /**
188 * Return default class of HFSC qdisc
189 * @arg qdisc hfsc qdisc object
190 *
191 * Returns the classid of the class where all unclassified traffic
192 * goes to.
193 *
194 * @return classid or TC_H_UNSPEC if unspecified.
195 */
196 uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *qdisc)
197 {
198 struct rtnl_hfsc_qdisc *hfsc;
199
200 if ((hfsc = hfsc_qdisc_data(qdisc, NULL)) &&
201 (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS))
202 return hfsc->qh_defcls;
203
204 return TC_H_UNSPEC;
205 }
206
207 /**
208 * Set default class of the hfsc qdisc to the specified value
209 * @arg qdisc qdisc to change
210 * @arg defcls new default class
211 */
212 int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
213 {
214 struct rtnl_hfsc_qdisc *hfsc;
215 int err;
216
217 if (!(hfsc = hfsc_qdisc_data(qdisc, &err)))
218 return err;
219
220 hfsc->qh_defcls = defcls;
221 hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
222
223 return 0;
224 }
225
226 int rtnl_class_hfsc_get_rsc(const struct rtnl_class *class, struct tc_service_curve *tsc)
227 {
228 struct rtnl_hfsc_class *hfsc;
229 int err = -NLE_OPNOTSUPP;
230
231 if ((hfsc = hfsc_class_data(class, &err)) &&
232 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)) {
233 *tsc = hfsc->ch_rsc;
234 return 0;
235 }
236
237 return err;
238 }
239
240 int rtnl_class_hfsc_set_rsc(struct rtnl_class *class, const struct tc_service_curve *tsc)
241 {
242 struct rtnl_hfsc_class *hfsc;
243 int err;
244
245 if (!(hfsc = hfsc_class_data(class, &err)))
246 return err;
247
248 hfsc->ch_rsc = *tsc;
249 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
250
251 return 0;
252 }
253
254 int rtnl_class_hfsc_get_fsc(const struct rtnl_class *class, struct tc_service_curve *tsc)
255 {
256 struct rtnl_hfsc_class *hfsc;
257 int err = -NLE_OPNOTSUPP;
258
259 if ((hfsc = hfsc_class_data(class, &err)) &&
260 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)) {
261 *tsc = hfsc->ch_fsc;
262 return 0;
263 }
264
265 return err;
266 }
267
268 int rtnl_class_hfsc_set_fsc(struct rtnl_class *class, const struct tc_service_curve *tsc)
269 {
270 struct rtnl_hfsc_class *hfsc;
271 int err;
272
273 if (!(hfsc = hfsc_class_data(class, &err)))
274 return err;
275
276 hfsc->ch_fsc = *tsc;
277 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
278
279 return 0;
280 }
281
282 int rtnl_class_hfsc_get_usc(const struct rtnl_class *class, struct tc_service_curve *tsc)
283 {
284 struct rtnl_hfsc_class *hfsc;
285 int err = -NLE_OPNOTSUPP;
286
287 if ((hfsc = hfsc_class_data(class, &err)) &&
288 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)) {
289 *tsc = hfsc->ch_usc;
290 return 0;
291 }
292
293 return err;
294 }
295
296 int rtnl_class_hfsc_set_usc(struct rtnl_class *class, const struct tc_service_curve *tsc)
297 {
298 struct rtnl_hfsc_class *hfsc;
299 int err;
300
301 if (!(hfsc = hfsc_class_data(class, &err)))
302 return err;
303
304 hfsc->ch_usc = *tsc;
305 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
306
307 return 0;
308 }
309
310 /** @} */
311
312 static struct rtnl_tc_ops hfsc_qdisc_ops = {
313 .to_kind = "hfsc",
314 .to_type = RTNL_TC_TYPE_QDISC,
315 .to_size = sizeof(struct rtnl_hfsc_qdisc),
316 .to_msg_parser = hfsc_qdisc_msg_parser,
317 .to_dump[NL_DUMP_LINE] = hfsc_qdisc_dump_line,
318 .to_msg_fill = hfsc_qdisc_msg_fill,
319 };
320
321 static struct rtnl_tc_ops hfsc_class_ops = {
322 .to_kind = "hfsc",
323 .to_type = RTNL_TC_TYPE_CLASS,
324 .to_size = sizeof(struct rtnl_hfsc_class),
325 .to_msg_parser = hfsc_class_msg_parser,
326 .to_dump = {
327 [NL_DUMP_LINE] = hfsc_class_dump_line,
328 [NL_DUMP_DETAILS] = hfsc_class_dump_details,
329 },
330 .to_msg_fill = hfsc_class_msg_fill,
331 };
332
333 static void __init hfsc_init(void)
334 {
335 rtnl_tc_register(&hfsc_qdisc_ops);
336 rtnl_tc_register(&hfsc_class_ops);
337 }
338
339 static void __exit hfsc_exit(void)
340 {
341 rtnl_tc_unregister(&hfsc_qdisc_ops);
342 rtnl_tc_unregister(&hfsc_class_ops);
343 }
344
345 /** @} */
NLA_PUT
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition: attr.h:159
nla_memcpy
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition: attr.c:346
rtnl_tc_handle2str
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
Definition: classid.c:103
nlmsg_append
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition: msg.c:442
rtnl_qdisc_hfsc_get_defcls
uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *qdisc)
Return default class of HFSC qdisc.
Definition: hfsc.c:196
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
TC_CAST
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
Definition: tc.h:50
rtnl_tc_register
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Definition: tc.c:1015
rtnl_tc_unregister
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
Definition: tc.c:1049
rtnl_tc_data_check
void * rtnl_tc_data_check(struct rtnl_tc *tc, struct rtnl_tc_ops *ops, int *err)
Check traffic control object type and return private data section.
Definition: tc.c:1111
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
NL_DUMP_LINE
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
NL_DUMP_DETAILS
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
nl_dump_params
Dumping parameters.
Definition: types.h:28
nla_policy
Attribute validation policy.
Definition: attr.h:63
nla_policy::minlen
uint16_t minlen
Minimal length of payload required.
Definition: attr.h:68