19 #include <netlink-private/netlink.h>
20 #include <netlink-private/tc.h>
21 #include <netlink/netlink.h>
22 #include <netlink/cache.h>
23 #include <netlink/utils.h>
24 #include <netlink-private/route/tc-api.h>
25 #include <netlink/route/qdisc.h>
26 #include <netlink/route/class.h>
27 #include <netlink/route/link.h>
28 #include <netlink/route/qdisc/hfsc.h>
31 #define SCH_HFSC_CLS_HAS_RSC 0x001
32 #define SCH_HFSC_CLS_HAS_FSC 0x002
33 #define SCH_HFSC_CLS_HAS_USC 0x004
35 #define SCH_HFSC_QD_HAS_DEFCLS 0x01
38 static struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
39 [TCA_HFSC_RSC] = { .
minlen =
sizeof(
struct tc_service_curve) },
40 [TCA_HFSC_FSC] = { .minlen =
sizeof(
struct tc_service_curve) },
41 [TCA_HFSC_USC] = { .minlen =
sizeof(
struct tc_service_curve) },
44 static int hfsc_qdisc_msg_parser(
struct rtnl_tc *tc,
void *data)
46 struct rtnl_hfsc_qdisc *hfsc = data;
47 struct tc_hfsc_qopt *opts;
49 opts = (
struct tc_hfsc_qopt *) tc->tc_opts->d_data;
50 hfsc->qh_defcls = opts->defcls;
51 hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
55 static int hfsc_class_msg_parser(
struct rtnl_tc *tc,
void *data)
57 struct nlattr *tb[TCA_HFSC_MAX + 1];
58 struct rtnl_hfsc_class *hfsc = data;
61 if ((err = tca_parse(tb, TCA_HFSC_MAX, tc, hfsc_policy)) < 0)
64 if (tb[TCA_HFSC_RSC]) {
65 struct tc_service_curve tsc;
67 nla_memcpy(&tsc, tb[TCA_HFSC_RSC],
sizeof(tsc));
69 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
72 if (tb[TCA_HFSC_FSC]) {
73 struct tc_service_curve tsc;
75 nla_memcpy(&tsc, tb[TCA_HFSC_FSC],
sizeof(tsc));
77 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
80 if (tb[TCA_HFSC_USC]) {
81 struct tc_service_curve tsc;
83 nla_memcpy(&tsc, tb[TCA_HFSC_USC],
sizeof(tsc));
85 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
91 static void hfsc_qdisc_dump_line(
struct rtnl_tc *tc,
void *data,
94 struct rtnl_hfsc_qdisc *hfsc = data;
99 if (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS) {
101 nl_dump(p,
" default-class %s",
106 static void hfsc_dump_tsc(
struct nl_dump_params *p,
struct tc_service_curve *tsc)
108 nl_dump(p,
" m1 %u d %u m2 %u\n", tsc->m1, tsc->d, tsc->m2);
111 static void hfsc_class_dump_line(
struct rtnl_tc *tc,
void *data,
114 struct rtnl_hfsc_class *hfsc = data;
118 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)
119 hfsc_dump_tsc(p, &hfsc->ch_rsc);
120 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)
121 hfsc_dump_tsc(p, &hfsc->ch_fsc);
122 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)
123 hfsc_dump_tsc(p, &hfsc->ch_usc);
126 static void hfsc_class_dump_details(
struct rtnl_tc *tc,
void *data,
132 static int hfsc_qdisc_msg_fill(
struct rtnl_tc *tc,
void *data,
135 struct rtnl_hfsc_qdisc *hfsc = data;
136 struct tc_hfsc_qopt opts = {0};
141 opts.defcls = hfsc->qh_defcls;
142 return nlmsg_append(msg, &opts,
sizeof(opts), NL_DONTPAD);
145 static int hfsc_class_msg_fill(
struct rtnl_tc *tc,
void *data,
148 struct rtnl_hfsc_class *hfsc = data;
149 struct tc_service_curve tsc;
154 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC) {
156 NLA_PUT(msg, TCA_HFSC_RSC,
sizeof(tsc), &tsc);
159 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC) {
161 NLA_PUT(msg, TCA_HFSC_FSC,
sizeof(tsc), &tsc);
164 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC) {
166 NLA_PUT(msg, TCA_HFSC_USC,
sizeof(tsc), &tsc);
175 static struct rtnl_tc_ops hfsc_qdisc_ops;
176 static struct rtnl_tc_ops hfsc_class_ops;
178 static struct rtnl_hfsc_qdisc *hfsc_qdisc_data(
const struct rtnl_qdisc *qdisc,
int *err)
183 static struct rtnl_hfsc_class *hfsc_class_data(
const struct rtnl_class *
class,
int *err)
204 struct rtnl_hfsc_qdisc *hfsc;
206 if ((hfsc = hfsc_qdisc_data(qdisc, NULL)) &&
207 (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS))
208 return hfsc->qh_defcls;
220 struct rtnl_hfsc_qdisc *hfsc;
223 if (!(hfsc = hfsc_qdisc_data(qdisc, &err)))
226 hfsc->qh_defcls = defcls;
227 hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
232 int rtnl_class_hfsc_get_rsc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
234 struct rtnl_hfsc_class *hfsc;
235 int err = -NLE_OPNOTSUPP;
237 if ((hfsc = hfsc_class_data(
class, &err)) &&
238 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)) {
246 int rtnl_class_hfsc_set_rsc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
248 struct rtnl_hfsc_class *hfsc;
251 if (!(hfsc = hfsc_class_data(
class, &err)))
255 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
260 int rtnl_class_hfsc_get_fsc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
262 struct rtnl_hfsc_class *hfsc;
263 int err = -NLE_OPNOTSUPP;
265 if ((hfsc = hfsc_class_data(
class, &err)) &&
266 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)) {
274 int rtnl_class_hfsc_set_fsc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
276 struct rtnl_hfsc_class *hfsc;
279 if (!(hfsc = hfsc_class_data(
class, &err)))
283 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
288 int rtnl_class_hfsc_get_usc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
290 struct rtnl_hfsc_class *hfsc;
291 int err = -NLE_OPNOTSUPP;
293 if ((hfsc = hfsc_class_data(
class, &err)) &&
294 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)) {
302 int rtnl_class_hfsc_set_usc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
304 struct rtnl_hfsc_class *hfsc;
307 if (!(hfsc = hfsc_class_data(
class, &err)))
311 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
318 static struct rtnl_tc_ops hfsc_qdisc_ops = {
320 .to_type = RTNL_TC_TYPE_QDISC,
321 .to_size =
sizeof(
struct rtnl_hfsc_qdisc),
322 .to_msg_parser = hfsc_qdisc_msg_parser,
324 .to_msg_fill = hfsc_qdisc_msg_fill,
327 static struct rtnl_tc_ops hfsc_class_ops = {
329 .to_type = RTNL_TC_TYPE_CLASS,
330 .to_size =
sizeof(
struct rtnl_hfsc_class),
331 .to_msg_parser = hfsc_class_msg_parser,
336 .to_msg_fill = hfsc_class_msg_fill,
339 static void __init hfsc_init(
void)
345 static void __exit hfsc_exit(
void)
Dump object briefly on one line.
int rtnl_tc_register(struct rtnl_tc_ops *ops)
Register a traffic control module.
Attribute validation policy.
Dump all attributes but no statistics.
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.
void rtnl_tc_unregister(struct rtnl_tc_ops *ops)
Unregister a traffic control module.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
uint16_t minlen
Minimal length of payload required.
int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
Set default class of the hfsc qdisc to the specified value.
uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *qdisc)
Return default class of HFSC qdisc.
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.