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>
25#define SCH_HFSC_CLS_HAS_RSC 0x001
26#define SCH_HFSC_CLS_HAS_FSC 0x002
27#define SCH_HFSC_CLS_HAS_USC 0x004
29#define SCH_HFSC_QD_HAS_DEFCLS 0x01
32static 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) },
38static int hfsc_qdisc_msg_parser(
struct rtnl_tc *tc,
void *data)
40 struct rtnl_hfsc_qdisc *hfsc = data;
41 struct tc_hfsc_qopt *opts;
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;
49static int hfsc_class_msg_parser(
struct rtnl_tc *tc,
void *data)
51 struct nlattr *tb[TCA_HFSC_MAX + 1];
52 struct rtnl_hfsc_class *hfsc = data;
55 if ((err = tca_parse(tb, TCA_HFSC_MAX, tc, hfsc_policy)) < 0)
58 if (tb[TCA_HFSC_RSC]) {
59 struct tc_service_curve tsc;
61 nla_memcpy(&tsc, tb[TCA_HFSC_RSC],
sizeof(tsc));
63 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
66 if (tb[TCA_HFSC_FSC]) {
67 struct tc_service_curve tsc;
69 nla_memcpy(&tsc, tb[TCA_HFSC_FSC],
sizeof(tsc));
71 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
74 if (tb[TCA_HFSC_USC]) {
75 struct tc_service_curve tsc;
77 nla_memcpy(&tsc, tb[TCA_HFSC_USC],
sizeof(tsc));
79 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
85static void hfsc_qdisc_dump_line(
struct rtnl_tc *tc,
void *data,
88 struct rtnl_hfsc_qdisc *hfsc = data;
93 if (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS) {
100static void hfsc_dump_tsc(
struct nl_dump_params *p,
struct tc_service_curve *tsc)
102 nl_dump(p,
" m1 %u d %u m2 %u\n", tsc->m1, tsc->d, tsc->m2);
105static void hfsc_class_dump_line(
struct rtnl_tc *tc,
void *data,
108 struct rtnl_hfsc_class *hfsc = data;
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);
120static void hfsc_class_dump_details(
struct rtnl_tc *tc,
void *data,
126static int hfsc_qdisc_msg_fill(
struct rtnl_tc *tc,
void *data,
129 struct rtnl_hfsc_qdisc *hfsc = data;
130 struct tc_hfsc_qopt opts = {0};
135 opts.defcls = hfsc->qh_defcls;
136 return nlmsg_append(msg, &opts,
sizeof(opts), NL_DONTPAD);
139static int hfsc_class_msg_fill(
struct rtnl_tc *tc,
void *data,
142 struct rtnl_hfsc_class *hfsc = data;
143 struct tc_service_curve tsc;
148 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC) {
150 NLA_PUT(msg, TCA_HFSC_RSC,
sizeof(tsc), &tsc);
153 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC) {
155 NLA_PUT(msg, TCA_HFSC_FSC,
sizeof(tsc), &tsc);
158 if (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC) {
160 NLA_PUT(msg, TCA_HFSC_USC,
sizeof(tsc), &tsc);
169static struct rtnl_tc_ops hfsc_qdisc_ops;
170static struct rtnl_tc_ops hfsc_class_ops;
172static struct rtnl_hfsc_qdisc *hfsc_qdisc_data(
const struct rtnl_qdisc *qdisc,
int *err)
177static struct rtnl_hfsc_class *hfsc_class_data(
const struct rtnl_class *
class,
int *err)
198 struct rtnl_hfsc_qdisc *hfsc;
200 if ((hfsc = hfsc_qdisc_data(qdisc, NULL)) &&
201 (hfsc->qh_mask & SCH_HFSC_QD_HAS_DEFCLS))
202 return hfsc->qh_defcls;
214 struct rtnl_hfsc_qdisc *hfsc;
217 if (!(hfsc = hfsc_qdisc_data(qdisc, &err)))
220 hfsc->qh_defcls = defcls;
221 hfsc->qh_mask |= SCH_HFSC_QD_HAS_DEFCLS;
226int rtnl_class_hfsc_get_rsc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
228 struct rtnl_hfsc_class *hfsc;
229 int err = -NLE_OPNOTSUPP;
231 if ((hfsc = hfsc_class_data(
class, &err)) &&
232 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_RSC)) {
240int rtnl_class_hfsc_set_rsc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
242 struct rtnl_hfsc_class *hfsc;
245 if (!(hfsc = hfsc_class_data(
class, &err)))
249 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_RSC;
254int rtnl_class_hfsc_get_fsc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
256 struct rtnl_hfsc_class *hfsc;
257 int err = -NLE_OPNOTSUPP;
259 if ((hfsc = hfsc_class_data(
class, &err)) &&
260 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_FSC)) {
268int rtnl_class_hfsc_set_fsc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
270 struct rtnl_hfsc_class *hfsc;
273 if (!(hfsc = hfsc_class_data(
class, &err)))
277 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_FSC;
282int rtnl_class_hfsc_get_usc(
const struct rtnl_class *
class,
struct tc_service_curve *tsc)
284 struct rtnl_hfsc_class *hfsc;
285 int err = -NLE_OPNOTSUPP;
287 if ((hfsc = hfsc_class_data(
class, &err)) &&
288 (hfsc->ch_mask & SCH_HFSC_CLS_HAS_USC)) {
296int rtnl_class_hfsc_set_usc(
struct rtnl_class *
class,
const struct tc_service_curve *tsc)
298 struct rtnl_hfsc_class *hfsc;
301 if (!(hfsc = hfsc_class_data(
class, &err)))
305 hfsc->ch_mask |= SCH_HFSC_CLS_HAS_USC;
312static struct rtnl_tc_ops hfsc_qdisc_ops = {
314 .to_type = RTNL_TC_TYPE_QDISC,
315 .to_size =
sizeof(
struct rtnl_hfsc_qdisc),
316 .to_msg_parser = hfsc_qdisc_msg_parser,
318 .to_msg_fill = hfsc_qdisc_msg_fill,
321static struct rtnl_tc_ops hfsc_class_ops = {
323 .to_type = RTNL_TC_TYPE_CLASS,
324 .to_size =
sizeof(
struct rtnl_hfsc_class),
325 .to_msg_parser = hfsc_class_msg_parser,
330 .to_msg_fill = hfsc_class_msg_fill,
333static void __init hfsc_init(
void)
339static void __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 *tc, struct rtnl_tc_ops *ops, int *err)
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 *ops)
Register a traffic control module.
void rtnl_tc_unregister(struct rtnl_tc_ops *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.