diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h index 0fb48fd..07f00fa 100644 --- a/include/netlink-private/types.h +++ b/include/netlink-private/types.h @@ -565,6 +565,12 @@ struct rtnl_dsmark_class uint32_t cdm_mask; }; +struct rtnl_drr_class +{ + uint32_t cd_quantum; + uint32_t cd_mask; +}; + struct rtnl_fifo { uint32_t qf_limit; diff --git a/include/netlink/route/qdisc/drr.h b/include/netlink/route/qdisc/drr.h new file mode 100644 index 0000000..2d46e9d --- /dev/null +++ b/include/netlink/route/qdisc/drr.h @@ -0,0 +1,21 @@ +/* + * netlink/route/sch/drr.c Deficit Round Robin Qdisc + */ + +#ifndef NETLINK_DRR_H_ +#define NETLINK_DRR_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern int rtnl_class_drr_set_quantum(struct rtnl_qdisc *, uint32_t); +extern uint32_t rtnl_class_drr_get_quantum(struct rtnl_qdisc *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/lib/Makefile.am b/lib/Makefile.am index ff85974..b619198 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -78,6 +78,7 @@ libnl_route_3_la_SOURCES = \ route/qdisc/fq_codel.c \ route/qdisc/codel.c \ route/qdisc/hfsc.c \ + route/qdisc/drr.c \ \ fib_lookup/lookup.c fib_lookup/request.c \ \ diff --git a/lib/route/qdisc/drr.c b/lib/route/qdisc/drr.c new file mode 100644 index 0000000..7bf10d0 --- /dev/null +++ b/lib/route/qdisc/drr.c @@ -0,0 +1,150 @@ +/* + * lib/route/qdisc/drr.c DRR Qdisc + */ + +/** + * @ingroup qdisc + * @ingroup class + * @defgroup qdisc_drr Deficit Round Robin + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** @cond SKIP */ +#define SCH_DRR_HAS_QUANTUM 0x1 +/** @endcond */ + +static struct nla_policy drr_policy[TCA_DRR_MAX + 1] = { + [TCA_DRR_QUANTUM] = { .type = NLA_U32 }, +}; + +static int drr_class_msg_parser(struct rtnl_tc *tc, void *data) +{ + struct rtnl_drr_class *drr = data; + struct nlattr *tb[TCA_DRR_MAX + 1]; + int err; + + err = tca_parse(tb, TCA_DRR_MAX, tc, drr_policy); + if (err < 0) + return err; + + if (tb[TCA_DRR_QUANTUM]) { + drr->cd_quantum = nla_get_u32(tb[TCA_DRR_QUANTUM]); + drr->cd_mask |= SCH_DRR_HAS_QUANTUM; + } + + return 0; +} + +static void drr_class_dump_line(struct rtnl_tc *tc, void *data, + struct nl_dump_params *p) +{ + struct rtnl_drr_class *drr = data; + + if (drr && (drr->cd_mask & SCH_DRR_HAS_QUANTUM)) + nl_dump(p, " quantum %u", drr->cd_quantum); +} + +static int drr_class_msg_fill(struct rtnl_tc *tc, void *data, + struct nl_msg *msg) +{ + struct rtnl_drr_class *drr = data; + + if (drr && (drr->cd_mask & SCH_DRR_HAS_QUANTUM)) + NLA_PUT_U32(msg, TCA_DRR_QUANTUM, drr->cd_quantum); + +nla_put_failure: + return -NLE_MSGSIZE; +} + +/** + * @name Class Attribute Access + * @{ + */ + +/** + * Get quantum for DRR class. + * @arg cls DRR class. + * @return Quantum per DRR round in bytes, or 0 for error. + */ +int rtnl_drr_class_get_quantum(struct rtnl_class *cls) +{ + struct rtnl_drr_class *drr; + + if (!(drr = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + if (drr->cd_mask & SCH_DRR_HAS_QUANTUM) + return drr->cd_quantum; + else + return 0; +} + +/** + * Sets the quantum for a DRR class. + * @arg cls DRR class. + * @arg quantum Quantum per DRR round in bytes. + * @return 0 on success, or a negative error code. + */ +int rtnl_drr_qdisc_set_quantum(struct rtnl_class *cls, uint32_t quantum) +{ + struct rtnl_drr_class *drr; + + if (!(drr = rtnl_tc_data(TC_CAST(cls)))) + return -NLE_NOMEM; + + drr->cd_quantum = quantum; + drr->cd_mask |= SCH_DRR_HAS_QUANTUM; + + return 0; +} + + +/** @} */ + +static struct rtnl_tc_ops drr_qdisc_ops = { + .to_kind = "drr", + .to_type = RTNL_TC_TYPE_QDISC, + .to_size = 0, + .to_msg_parser = NULL, + .to_dump = { + [NL_DUMP_LINE] = NULL, + [NL_DUMP_DETAILS] = NULL, + }, + .to_msg_fill = NULL, +}; + +static struct rtnl_tc_ops drr_class_ops = { + .to_kind = "drr", + .to_type = RTNL_TC_TYPE_CLASS, + .to_size = sizeof(struct rtnl_drr_class), + .to_msg_parser = drr_class_msg_parser, + .to_dump = { + [NL_DUMP_LINE] = drr_class_dump_line, + [NL_DUMP_DETAILS] = NULL, + }, + .to_msg_fill = drr_class_msg_fill, +}; + +static void __init drr_init(void) +{ + rtnl_tc_register(&drr_qdisc_ops); + rtnl_tc_register(&drr_class_ops); +} + +static void __exit drr_exit(void) +{ + rtnl_tc_unregister(&drr_class_ops); + rtnl_tc_unregister(&drr_qdisc_ops); +} + +/** @} */