13#include "nl-default.h"
15#include <netlink/netlink.h>
16#include <netlink/cache.h>
17#include <netlink/utils.h>
18#include <netlink/route/qdisc.h>
19#include <netlink/route/class.h>
20#include <netlink/route/link.h>
21#include <netlink/route/qdisc/hfsc.h>
26struct rtnl_hfsc_qdisc {
31struct rtnl_hfsc_class {
32 struct tc_service_curve ch_rsc;
33 struct tc_service_curve ch_fsc;
34 struct tc_service_curve ch_usc;
38#define SCH_HFSC_CLS_HAS_RSC 0x001
39#define SCH_HFSC_CLS_HAS_FSC 0x002
40#define SCH_HFSC_CLS_HAS_USC 0x004
42#define SCH_HFSC_QD_HAS_DEFCLS 0x01
45static struct nla_policy hfsc_policy[TCA_HFSC_MAX + 1] = {
46 [TCA_HFSC_RSC] = { .
minlen =
sizeof(
struct tc_service_curve) },
47 [TCA_HFSC_FSC] = { .minlen =
sizeof(
struct tc_service_curve) },
48 [TCA_HFSC_USC] = { .minlen =
sizeof(
struct tc_service_curve) },
51static int hfsc_qdisc_msg_parser(
struct rtnl_tc *tc,
void *data)
53 struct rtnl_hfsc_qdisc *hfsc = data;
54 struct tc_hfsc_qopt *opts;
56 opts = (
struct tc_hfsc_qopt *) tc->tc_opts->d_data;
57 hfsc->qh_defcls = opts->defcls;
58 hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
62static int hfsc_class_msg_parser(
struct rtnl_tc *tc,
void *data)
64 struct nlattr *tb[TCA_HFSC_MAX + 1];
65 struct rtnl_hfsc_class *hfsc = data;
68 if ((err = tca_parse(tb, TCA_HFSC_MAX, tc, hfsc_policy)) < 0)
71 if (tb[TCA_HFSC_RSC]) {
72 struct tc_service_curve tsc;
74 nla_memcpy(&tsc, tb[TCA_HFSC_RSC],
sizeof(tsc));
76 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
79 if (tb[TCA_HFSC_FSC]) {
80 struct tc_service_curve tsc;
82 nla_memcpy(&tsc, tb[TCA_HFSC_FSC],
sizeof(tsc));
84 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
87 if (tb[TCA_HFSC_USC]) {
88 struct tc_service_curve tsc;
90 nla_memcpy(&tsc, tb[TCA_HFSC_USC],
sizeof(tsc));
92 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
98static void hfsc_qdisc_dump_line(
struct rtnl_tc *tc,
void *data,
101 struct rtnl_hfsc_qdisc *hfsc = data;
106 if (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS) {
108 nl_dump(p,
" default-class %s",
113static void hfsc_dump_tsc(
struct nl_dump_params *p,
struct tc_service_curve *tsc)
115 nl_dump(p,
" m1 %u d %u m2 %u\n", tsc->m1, tsc->d, tsc->m2);
118static void hfsc_class_dump_line(
struct rtnl_tc *tc,
void *data,
121 struct rtnl_hfsc_class *hfsc = data;
125 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)
126 hfsc_dump_tsc(p, &hfsc->ch_rsc);
127 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)
128 hfsc_dump_tsc(p, &hfsc->ch_fsc);
129 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)
130 hfsc_dump_tsc(p, &hfsc->ch_usc);
133static void hfsc_class_dump_details(
struct rtnl_tc *tc,
void *data,
139static int hfsc_qdisc_msg_fill(
struct rtnl_tc *tc,
void *data,
142 struct rtnl_hfsc_qdisc *hfsc = data;
143 struct tc_hfsc_qopt opts = {0};
148 opts.defcls = hfsc->qh_defcls;
149 return nlmsg_append(msg, &opts,
sizeof(opts), NL_DONTPAD);
152static int hfsc_class_msg_fill(
struct rtnl_tc *tc,
void *data,
155 struct rtnl_hfsc_class *hfsc = data;
156 struct tc_service_curve tsc;
161 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC) {
163 NLA_PUT(msg, TCA_HFSC_RSC,
sizeof(tsc), &tsc);
166 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC) {
168 NLA_PUT(msg, TCA_HFSC_FSC,
sizeof(tsc), &tsc);
171 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC) {
173 NLA_PUT(msg, TCA_HFSC_USC,
sizeof(tsc), &tsc);
182static struct rtnl_tc_ops hfsc_qdisc_ops;
183static struct rtnl_tc_ops hfsc_class_ops;
185static struct rtnl_hfsc_qdisc *hfsc_qdisc_data(
const struct rtnl_qdisc *qdisc,
int *err)
190static struct rtnl_hfsc_class *hfsc_class_data(
const struct rtnl_class *
class,
int *err)
211 struct rtnl_hfsc_qdisc *hfsc;
213 if ((hfsc = hfsc_qdisc_data(qdisc, NULL)) &&
214 (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS))
215 return hfsc->qh_defcls;
227 struct rtnl_hfsc_qdisc *hfsc;
230 if (!(hfsc = hfsc_qdisc_data(qdisc, &err)))
233 hfsc->qh_defcls = defcls;
234 hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
239int rtnl_class_hfsc_get_rsc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
241 struct rtnl_hfsc_class *hfsc;
242 int err = -NLE_OPNOTSUPP;
244 if ((hfsc = hfsc_class_data(
class, &err)) &&
245 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)) {
253int rtnl_class_hfsc_set_rsc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
255 struct rtnl_hfsc_class *hfsc;
258 if (!(hfsc = hfsc_class_data(
class, &err)))
262 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
267int rtnl_class_hfsc_get_fsc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
269 struct rtnl_hfsc_class *hfsc;
270 int err = -NLE_OPNOTSUPP;
272 if ((hfsc = hfsc_class_data(
class, &err)) &&
273 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)) {
281int rtnl_class_hfsc_set_fsc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
283 struct rtnl_hfsc_class *hfsc;
286 if (!(hfsc = hfsc_class_data(
class, &err)))
290 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
295int rtnl_class_hfsc_get_usc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
297 struct rtnl_hfsc_class *hfsc;
298 int err = -NLE_OPNOTSUPP;
300 if ((hfsc = hfsc_class_data(
class, &err)) &&
301 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)) {
309int rtnl_class_hfsc_set_usc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
311 struct rtnl_hfsc_class *hfsc;
314 if (!(hfsc = hfsc_class_data(
class, &err)))
318 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
325static struct rtnl_tc_ops hfsc_qdisc_ops = {
327 .to_type = RTNL_TC_TYPE_QDISC,
328 .to_size =
sizeof(
struct rtnl_hfsc_qdisc),
329 .to_msg_parser = hfsc_qdisc_msg_parser,
331 .to_msg_fill = hfsc_qdisc_msg_fill,
334static struct rtnl_tc_ops hfsc_class_ops = {
336 .to_type = RTNL_TC_TYPE_CLASS,
337 .to_size =
sizeof(
struct rtnl_hfsc_class),
338 .to_msg_parser = hfsc_class_msg_parser,
343 .to_msg_fill = hfsc_class_msg_fill,
346static void _nl_init hfsc_init(
void)
352static void _nl_exit hfsc_exit(
void)
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
char * rtnl_tc_handle2str(uint32_t handle, char *buf, size_t len)
Convert a traffic control handle to a character string (Reentrant).
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
uint32_t rtnl_qdisc_hfsc_get_defcls(const struct rtnl_qdisc *qdisc)
Return default class of HFSC qdisc.
int rtnl_qdisc_hfsc_set_defcls(struct rtnl_qdisc *qdisc, uint32_t defcls)
Set default class of the hfsc qdisc to the specified value.
void * rtnl_tc_data_check(struct rtnl_tc *, struct rtnl_tc_ops *, int *)
Check traffic control object type and return private data section.
#define TC_CAST(ptr)
Macro to cast qdisc/class/classifier to tc object.
int rtnl_tc_register(struct rtnl_tc_ops *)
Register a traffic control module.
void rtnl_tc_unregister(struct rtnl_tc_ops *)
Unregister a traffic control module.
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
@ NL_DUMP_LINE
Dump object briefly on one line.
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Attribute validation policy.
uint16_t minlen
Minimal length of payload required.