1
1
Files
zyxel-vmg8825_b50b-cfw/package/libs/libnl/patches-3.2.21/0009-add-nsshtb-and-nssblackhole-support.patch
T
2026-04-17 18:33:03 +02:00

959 lines
27 KiB
Diff
Executable File

diff --git a/include/Makefile.am b/include/Makefile.am
index 7b8f0bd..cf8d548 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -64,6 +64,8 @@ nobase_libnlinclude_HEADERS = \
netlink/route/qdisc/nssfifo.h \
netlink/route/qdisc/nssprio.h \
netlink/route/qdisc/nsstbl.h \
+ netlink/route/qdisc/nssblackhole.h \
+ netlink/route/qdisc/nsshtb.h \
netlink/route/addr.h \
netlink/route/class.h \
netlink/route/classifier.h \
diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h
index 4eb702a..9e352c3 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -1,3 +1,19 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
#ifndef __LINUX_PKT_SCHED_H
#define __LINUX_PKT_SCHED_H
@@ -847,4 +863,43 @@ struct tc_nssbf_qopt {
__u16 defcls; /* Default class value */
};
+/* NSSBLACKHOLE section */
+
+enum {
+ TCA_NSSBLACKHOLE_UNSPEC,
+ TCA_NSSBLACKHOLE_PARMS,
+ __TCA_NSSBLACKHOLE_MAX
+};
+
+#define TCA_NSSBLACKHOLE_MAX (__TCA_NSSBLACKHOLE_MAX - 1)
+
+struct tc_nssblackhole_qopt {
+ __u8 set_default; /* Sets qdisc to be the default qdisc for enqueue */
+};
+
+/* NSSHTB section */
+
+enum {
+ TCA_NSSHTB_UNSPEC,
+ TCA_NSSHTB_CLASS_PARMS,
+ TCA_NSSHTB_QDISC_PARMS,
+ __TCA_NSSHTB_MAX
+};
+
+#define TCA_NSSHTB_MAX (__TCA_NSSHTB_MAX - 1)
+
+struct tc_nsshtb_class_qopt {
+ __u32 burst; /* Expected burst size */
+ __u32 rate; /* Expected bandwidth for this class */
+ __u32 cburst; /* Maximum burst size */
+ __u32 crate; /* Max allowed bandwidth for this class */
+ __u32 quantum; /* Quantum allocation value for DRR */
+ __u32 priority; /* Priority value associated with this class */
+ __u32 overhead; /* Overhead in bytes per packet */
+};
+
+struct tc_nsshtb_qopt {
+ __u32 r2q; /* Rate to quantum ratio */
+};
+
#endif
diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h
index 6b6f91b..a0fb9bb 100644
--- a/include/netlink-private/types.h
+++ b/include/netlink-private/types.h
@@ -700,6 +700,28 @@ struct rtnl_nssbf_qdisc {
uint32_t awv_mask;
};
+struct rtnl_nssblackhole
+{
+ uint32_t jsh_mask;
+ uint8_t jsh_set_default;
+};
+
+struct rtnl_nsshtb_class {
+ uint32_t sud_burst;
+ uint32_t sud_rate;
+ uint32_t sud_cburst;
+ uint32_t sud_crate;
+ uint32_t sud_quantum;
+ uint32_t sud_priority;
+ uint32_t sud_overhead;
+ uint32_t sud_mask;
+};
+
+struct rtnl_nsshtb_qdisc {
+ uint32_t wek_r2q;
+ uint32_t wek_mask;
+};
+
struct rtnl_netem_corr
{
uint32_t nmc_delay;
diff --git a/include/netlink/route/qdisc/nssblackhole.h b/include/netlink/route/qdisc/nssblackhole.h
new file mode 100644
index 0000000..586a8be
--- /dev/null
+++ b/include/netlink/route/qdisc/nssblackhole.h
@@ -0,0 +1,34 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#ifndef NETLINK_NSSBLACKHOLE_H_
+#define NETLINK_NSSBLACKHOLE_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/qdisc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int rtnl_nssblackhole_set_default(struct rtnl_qdisc *, uint8_t);
+extern uint8_t rtnl_nssblackhole_get_default(struct rtnl_qdisc *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/qdisc/nsshtb.h b/include/netlink/route/qdisc/nsshtb.h
new file mode 100644
index 0000000..2316696
--- /dev/null
+++ b/include/netlink/route/qdisc/nsshtb.h
@@ -0,0 +1,55 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+#ifndef NETLINK_NSSHTB_H_
+#define NETLINK_NSSHTB_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/tc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int rtnl_nsshtb_qdisc_set_r2q(struct rtnl_qdisc *qdisc, uint16_t r2q);
+extern uint32_t rtnl_nsshtb_qdisc_get_r2q(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nsshtb_class_set_rate(struct rtnl_class *class, uint32_t rate);
+extern uint32_t rtnl_nsshtb_class_get_rate(struct rtnl_class *class);
+
+extern int rtnl_nsshtb_class_set_burst(struct rtnl_class *class, uint32_t burst);
+extern uint32_t rtnl_nsshtb_class_get_burst(struct rtnl_class *class);
+
+extern int rtnl_nsshtb_class_set_crate(struct rtnl_class *class, uint32_t crate);
+extern uint32_t rtnl_nsshtb_class_get_crate(struct rtnl_class *class);
+
+extern int rtnl_nsshtb_class_set_cburst(struct rtnl_class *class, uint32_t cburst);
+extern uint32_t rtnl_nsshtb_class_get_cburst(struct rtnl_class *class);
+
+extern int rtnl_nsshtb_class_set_quantum(struct rtnl_class *class, uint32_t q);
+extern uint32_t rtnl_nsshtb_class_get_quantum(struct rtnl_class *class);
+
+extern int rtnl_nsshtb_class_set_priority(struct rtnl_class *class, uint32_t priority);
+extern uint32_t rtnl_nsshtb_class_get_priority(struct rtnl_class *class);
+
+extern int rtnl_nsshtb_class_set_overhead(struct rtnl_class *class, uint32_t overhead);
+extern uint32_t rtnl_nsshtb_class_get_overhead(struct rtnl_class *class);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 8891a0f..5771456 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -83,6 +83,7 @@ libnl_route_3_la_SOURCES = \
route/qdisc/bf.c \
route/qdisc/nssfifo.c route/qdisc/nsstbl.c route/qdisc/nssbf.c \
route/qdisc/nssprio.c route/qdisc/nsscodel.c \
+ route/qdisc/nssblackhole.c route/qdisc/nsshtb.c \
\
fib_lookup/lookup.c fib_lookup/request.c \
\
diff --git a/lib/route/qdisc/nssblackhole.c b/lib/route/qdisc/nssblackhole.c
new file mode 100644
index 0000000..9a69ee5
--- /dev/null
+++ b/lib/route/qdisc/nssblackhole.c
@@ -0,0 +1,169 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @ingroup qdisc
+ * @defgroup qdisc_nssblackhole FIFO Queue (NSSBLACKHOLE)
+ * @{
+ */
+
+#include <netlink-private/netlink.h>
+#include <netlink-private/tc.h>
+#include <netlink/netlink.h>
+#include <netlink-private/route/tc-api.h>
+#include <netlink/route/qdisc.h>
+#include <netlink/route/qdisc/nssblackhole.h>
+#include <netlink/utils.h>
+
+/** @cond */
+#define NSSBLACKHOLE_ATTR_SET_DEFAULT 0x01
+/** @endcond */
+
+static struct nla_policy nssblackhole_policy[TCA_NSSBLACKHOLE_MAX + 1] = {
+ [TCA_NSSBLACKHOLE_PARMS] = { .minlen = sizeof(struct tc_nssblackhole_qopt) },
+};
+
+static int nssblackhole_msg_parser(struct rtnl_tc *tc, void *data)
+{
+ struct nlattr *tb[TCA_NSSBLACKHOLE_MAX + 1];
+ struct rtnl_nssblackhole *nssblackhole = data;
+ struct tc_nssblackhole_qopt *opts;
+ int err;
+
+ err = tca_parse(tb, TCA_NSSBLACKHOLE_MAX, tc, nssblackhole_policy);
+ if (err < 0)
+ return err;
+
+ if (!tb[TCA_NSSBLACKHOLE_PARMS])
+ return -NLE_MISSING_ATTR;
+
+ opts = nla_data(tb[TCA_NSSBLACKHOLE_PARMS]);
+
+ nssblackhole->jsh_mask = 0;
+
+ nssblackhole->jsh_set_default = opts->set_default;
+ nssblackhole->jsh_mask |= NSSBLACKHOLE_ATTR_SET_DEFAULT;
+
+ return 0;
+}
+
+static void nssblackhole_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
+{
+ struct rtnl_nssblackhole *nssblackhole = data;
+
+ if (nssblackhole && (nssblackhole->jsh_mask & NSSBLACKHOLE_ATTR_SET_DEFAULT))
+ nl_dump(p, " set_default %u", nssblackhole->jsh_set_default);
+}
+
+static void nssblackhole_dump_details(struct rtnl_tc *tc, void *data, struct nl_dump_params *p)
+{
+ struct rtnl_nssblackhole *nssblackhole = data;
+
+ if (!nssblackhole)
+ return;
+
+ if (nssblackhole && (nssblackhole->jsh_mask & NSSBLACKHOLE_ATTR_SET_DEFAULT))
+ nl_dump(p, " set_default %u", nssblackhole->jsh_set_default);
+}
+
+static int nssblackhole_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+ struct rtnl_nssblackhole *nssblackhole = data;
+ struct tc_nssblackhole_qopt opts;
+
+ if (!nssblackhole)
+ return -NLE_INVAL;
+
+ memset(&opts, 0, sizeof(opts));
+
+ if (nssblackhole->jsh_mask & NSSBLACKHOLE_ATTR_SET_DEFAULT)
+ opts.set_default = nssblackhole->jsh_set_default;
+
+ NLA_PUT(msg, TCA_NSSBLACKHOLE_PARMS, sizeof(opts), &opts);
+ return 0;
+
+nla_put_failure:
+ return -NLE_MSGSIZE;
+}
+
+/**
+ * @name Attribute Modification
+ * @{
+ */
+
+/**
+ * Set set_default of NSSBLACKHOLE qdisc.
+ * @arg qdisc NSSBLACKHOLE qdisc to be modified.
+ * @arg set_default If this qdisc needs to be the default enqueue node.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssblackhole_set_default(struct rtnl_qdisc *qdisc, uint8_t set_default)
+{
+ struct rtnl_nssblackhole *nssblackhole;
+
+ if (!(nssblackhole = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ nssblackhole->jsh_set_default = set_default;
+ nssblackhole->jsh_mask |= NSSBLACKHOLE_ATTR_SET_DEFAULT;
+
+ return 0;
+}
+
+/**
+ * Get set_default of a NSSBLACKHOLE qdisc.
+ * @arg qdisc NSSBLACKHOLE qdisc.
+ * @return set_default flag
+ */
+uint8_t rtnl_nssblackhole_get_default(struct rtnl_qdisc *qdisc)
+{
+ struct rtnl_nssblackhole *nssblackhole;
+
+ if ((nssblackhole = rtnl_tc_data(TC_CAST(qdisc))) &&
+ (nssblackhole->jsh_mask & NSSBLACKHOLE_ATTR_SET_DEFAULT)) {
+
+ return nssblackhole->jsh_set_default;
+ }
+
+ return 0;
+}
+
+/** @} */
+
+static struct rtnl_tc_ops nssblackhole_ops = {
+ .to_kind = "nssblackhole",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_nssblackhole),
+ .to_msg_parser = nssblackhole_msg_parser,
+ .to_dump = {
+ [NL_DUMP_LINE] = nssblackhole_dump_line,
+ [NL_DUMP_DETAILS] = nssblackhole_dump_details,
+ },
+ .to_msg_fill = nssblackhole_msg_fill,
+};
+
+static void __init nssblackhole_init(void)
+{
+ rtnl_tc_register(&nssblackhole_ops);
+}
+
+static void __exit nssblackhole_exit(void)
+{
+ rtnl_tc_unregister(&nssblackhole_ops);
+}
+
+/** @} */
diff --git a/lib/route/qdisc/nsshtb.c b/lib/route/qdisc/nsshtb.c
new file mode 100644
index 0000000..31e520f
--- /dev/null
+++ b/lib/route/qdisc/nsshtb.c
@@ -0,0 +1,550 @@
+/*
+ **************************************************************************
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Permission to use, copy, modify, and/or distribute this software for
+ * any purpose with or without fee is hereby granted, provided that the
+ * above copyright notice and this permission notice appear in all copies.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ **************************************************************************
+ */
+
+/**
+ * @ingroup qdisc
+ * @ingroup class
+ * @defgroup qdisc_nsshtb HTB Scheduler (NSSHTB)
+ * @{
+ */
+
+#include <netlink-private/netlink.h>
+#include <netlink-private/tc.h>
+#include <netlink/netlink.h>
+#include <netlink/cache.h>
+#include <netlink/utils.h>
+#include <netlink-private/route/tc-api.h>
+#include <netlink/route/qdisc.h>
+#include <netlink/route/class.h>
+#include <netlink/route/link.h>
+#include <netlink/route/qdisc/nsshtb.h>
+
+/** @cond SKIP */
+#define NSSHTB_CLASS_ATTR_RATE 0x001
+#define NSSHTB_CLASS_ATTR_BURST 0x002
+#define NSSHTB_CLASS_ATTR_CRATE 0x004
+#define NSSHTB_CLASS_ATTR_CBURST 0x008
+#define NSSHTB_CLASS_ATTR_QUANTUM 0x010
+#define NSSHTB_CLASS_ATTR_PRIORITY 0x020
+#define NSSHTB_CLASS_ATTR_OVERHEAD 0x040
+#define NSSHTB_QDISC_ATTR_R2Q 0x080
+/** @endcond */
+
+static struct nla_policy nsshtb_policy[TCA_NSSHTB_MAX+1] = {
+ [TCA_NSSHTB_QDISC_PARMS] = { .minlen = sizeof(struct tc_nsshtb_qopt) },
+ [TCA_NSSHTB_CLASS_PARMS] = { .minlen = sizeof(struct tc_nsshtb_class_qopt) },
+};
+
+static struct nla_policy nsshtb_class_policy[TCA_NSSHTB_MAX+1] = {
+};
+
+static int nsshtb_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
+{
+ struct nlattr *tb[TCA_NSSHTB_MAX + 1];
+ struct rtnl_nsshtb_qdisc *nsshtb = data;
+ struct tc_nsshtb_qopt *opts;
+ int err;
+
+ if ((err = tca_parse(tb, TCA_NSSHTB_MAX, tc, nsshtb_policy)) < 0)
+ return err;
+
+ if (tb[TCA_NSSHTB_QDISC_PARMS]) {
+ opts = nla_data(tb[TCA_NSSHTB_QDISC_PARMS]);
+
+ nsshtb->wek_mask = 0;
+
+ nsshtb->wek_r2q = opts->r2q;
+ nsshtb->wek_mask |= NSSHTB_QDISC_ATTR_R2Q;
+ }
+
+ return 0;
+}
+
+static int nsshtb_class_msg_parser(struct rtnl_tc *tc, void *data)
+{
+ struct nlattr *tb[TCA_NSSHTB_MAX + 1];
+ struct rtnl_nsshtb_class *nsshtb = data;
+ struct tc_nsshtb_class_qopt *opts;
+ int err;
+
+ if ((err = tca_parse(tb, TCA_NSSHTB_MAX, tc, nsshtb_policy)) < 0)
+ return err;
+
+ if (tb[TCA_NSSHTB_CLASS_PARMS]) {
+ opts = nla_data(tb[TCA_NSSHTB_CLASS_PARMS]);
+
+ nsshtb->sud_mask = 0;
+
+ nsshtb->sud_rate = opts->rate;
+ nsshtb->sud_mask |= NSSHTB_CLASS_ATTR_RATE;
+
+ nsshtb->sud_burst = opts->burst;
+ nsshtb->sud_mask |= NSSHTB_CLASS_ATTR_BURST;
+
+ nsshtb->sud_crate = opts->crate;
+ nsshtb->sud_mask |= NSSHTB_CLASS_ATTR_CRATE;
+
+ nsshtb->sud_cburst = opts->cburst;
+ nsshtb->sud_mask |= NSSHTB_CLASS_ATTR_CBURST;
+
+ nsshtb->sud_quantum = opts->quantum;
+ nsshtb->sud_mask |= NSSHTB_CLASS_ATTR_QUANTUM;
+
+ nsshtb->sud_priority = opts->priority;
+ nsshtb->sud_mask |= NSSHTB_CLASS_ATTR_PRIORITY;
+
+ nsshtb->sud_overhead = opts->overhead;
+ nsshtb->sud_mask |= NSSHTB_CLASS_ATTR_OVERHEAD;
+ }
+
+ return 0;
+}
+
+static void nsshtb_qdisc_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
+{
+ struct rtnl_nsshtb_qdisc *nsshtb = data;
+
+ if (!nsshtb)
+ return;
+
+ if (nsshtb->wek_mask & NSSHTB_QDISC_ATTR_R2Q) {
+ char buf[64];
+ nl_dump(p, " r2q %s",
+ rtnl_tc_handle2str(nsshtb->wek_r2q,
+ buf, sizeof(buf)));
+ }
+}
+
+static void nsshtb_class_dump_line(struct rtnl_tc *tc, void *data,
+ struct nl_dump_params *p)
+{
+ struct rtnl_nsshtb_class *nsshtb = data;
+
+ if (!nsshtb)
+ return;
+
+ if (nsshtb->sud_mask & NSSHTB_CLASS_ATTR_RATE) {
+ nl_dump(p, " Rate %u Crate %u", nsshtb->sud_rate, nsshtb->sud_crate);
+ }
+}
+
+static int nsshtb_qdisc_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+ struct rtnl_nsshtb_qdisc *nsshtb = data;
+ struct tc_nsshtb_qopt opts;
+
+ memset(&opts, 0, sizeof(opts));
+
+ if (nsshtb) {
+ if (nsshtb->wek_mask & NSSHTB_QDISC_ATTR_R2Q)
+ opts.r2q = nsshtb->wek_r2q;
+ }
+
+ NLA_PUT(msg, TCA_NSSHTB_QDISC_PARMS, sizeof(opts), &opts);
+ return 0;
+
+nla_put_failure:
+ return -NLE_MSGSIZE;
+}
+
+static int nsshtb_class_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+ struct rtnl_nsshtb_class *nsshtb = data;
+ struct tc_nsshtb_class_qopt opts;
+
+ if (!nsshtb)
+ return 0;
+
+ memset(&opts, 0, sizeof(opts));
+
+ opts.rate = nsshtb->sud_rate;
+ opts.burst = nsshtb->sud_burst;
+
+ if (nsshtb->sud_mask & NSSHTB_CLASS_ATTR_RATE) {
+ /*
+ * Burst is needed if Rate is specified
+ */
+ if (!(nsshtb->sud_mask & NSSHTB_CLASS_ATTR_BURST))
+ return -NLE_MISSING_ATTR;
+
+ opts.rate = nsshtb->sud_rate;
+ opts.burst = nsshtb->sud_burst;
+ }
+
+ if (nsshtb->sud_mask & NSSHTB_CLASS_ATTR_CRATE) {
+ /*
+ * Cburst is needed if Crate is specified
+ */
+ if (!(nsshtb->sud_mask & NSSHTB_CLASS_ATTR_CBURST))
+ return -NLE_MISSING_ATTR;
+
+ opts.crate = nsshtb->sud_crate;
+ opts.cburst = nsshtb->sud_cburst;
+ }
+
+ if (nsshtb->sud_mask & NSSHTB_CLASS_ATTR_QUANTUM) {
+ opts.quantum = nsshtb->sud_quantum;
+ }
+
+ if (nsshtb->sud_mask & NSSHTB_CLASS_ATTR_PRIORITY) {
+ opts.priority = nsshtb->sud_priority;
+ }
+
+ if (nsshtb->sud_mask & NSSHTB_CLASS_ATTR_OVERHEAD) {
+ opts.overhead = nsshtb->sud_overhead;
+ }
+
+ NLA_PUT(msg, TCA_NSSHTB_CLASS_PARMS, sizeof(opts), &opts);
+
+ return 0;
+
+nla_put_failure:
+ return -NLE_MSGSIZE;
+}
+
+/**
+ * @name Attribute Access
+ * @{
+ */
+
+/**
+ * Set r2q of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg r2q New r2q for the qdisc
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_qdisc_set_r2q(struct rtnl_qdisc *qdisc, uint16_t r2q)
+{
+ struct rtnl_nsshtb_qdisc *nsshtb_qdisc;
+
+ if (!(nsshtb_qdisc = rtnl_tc_data(TC_CAST(qdisc))))
+ return -NLE_NOMEM;
+
+ nsshtb_qdisc->wek_r2q = r2q;
+ nsshtb_qdisc->wek_mask |= NSSHTB_QDISC_ATTR_R2Q;
+ return 0;
+}
+
+/**
+ * Get r2q of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return r2q value.
+ */
+uint32_t rtnl_nsshtb_qdisc_get_r2q(struct rtnl_qdisc *qdisc)
+{
+ struct rtnl_nsshtb_qdisc *nsshtb_qdisc;
+
+ if ((nsshtb_qdisc = rtnl_tc_data(TC_CAST(qdisc))) &&
+ (nsshtb_qdisc->wek_mask & NSSHTB_QDISC_ATTR_R2Q)) {
+
+ return nsshtb_qdisc->wek_r2q;
+ }
+
+ return TC_H_UNSPEC;
+}
+
+/**
+ * Set rate of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg rate New rate in bytes per second
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_class_set_rate(struct rtnl_class *class, uint32_t rate)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if (!(nsshtb_class = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
+
+ nsshtb_class->sud_rate = rate;
+ nsshtb_class->sud_mask |= NSSHTB_CLASS_ATTR_RATE;
+ return 0;
+}
+
+/**
+ * Get rate of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return configured rate in bytes per second.
+ */
+uint32_t rtnl_nsshtb_class_get_rate(struct rtnl_class *class)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if ((nsshtb_class = rtnl_tc_data(TC_CAST(class))) &&
+ (nsshtb_class->sud_mask & NSSHTB_CLASS_ATTR_RATE)) {
+
+ return nsshtb_class->sud_rate;
+ }
+
+ return 0;
+}
+
+/**
+ * Set burst of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg burst New burst size in bytes.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_class_set_burst(struct rtnl_class *class, uint32_t burst)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if (!(nsshtb_class = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
+
+ nsshtb_class->sud_burst = burst;
+ nsshtb_class->sud_mask |= NSSHTB_CLASS_ATTR_BURST;
+ return 0;
+}
+
+/**
+ * Get burst of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return configured burst in bytes.
+ */
+uint32_t rtnl_nsshtb_class_get_burst(struct rtnl_class *class)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if ((nsshtb_class = rtnl_tc_data(TC_CAST(class))) &&
+ (nsshtb_class->sud_mask & NSSHTB_CLASS_ATTR_BURST)) {
+
+ return nsshtb_class->sud_burst;
+ }
+
+ return 0;
+}
+
+/**
+ * Set crate of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg crate New crate in bytes per second
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_class_set_crate(struct rtnl_class *class, uint32_t crate)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if (!(nsshtb_class = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
+
+ nsshtb_class->sud_crate = crate;
+ nsshtb_class->sud_mask |= NSSHTB_CLASS_ATTR_CRATE;
+ return 0;
+}
+
+/**
+ * Get crate of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return configured crate in bytes per second.
+ */
+uint32_t rtnl_nsshtb_class_get_crate(struct rtnl_class *class)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if ((nsshtb_class = rtnl_tc_data(TC_CAST(class))) &&
+ (nsshtb_class->sud_mask & NSSHTB_CLASS_ATTR_CRATE)) {
+
+ return nsshtb_class->sud_crate;
+ }
+
+ return 0;
+}
+
+/**
+ * Set cburst of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg cburst New cburst size in bytes.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_class_set_cburst(struct rtnl_class *class, uint32_t cburst)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if (!(nsshtb_class = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
+
+ nsshtb_class->sud_cburst = cburst;
+ nsshtb_class->sud_mask |= NSSHTB_CLASS_ATTR_CBURST;
+ return 0;
+}
+
+/**
+ * Get cburst of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return configured cburst in bytes.
+ */
+uint32_t rtnl_nsshtb_class_get_cburst(struct rtnl_class *class)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if ((nsshtb_class = rtnl_tc_data(TC_CAST(class))) &&
+ (nsshtb_class->sud_mask & NSSHTB_CLASS_ATTR_CBURST)) {
+
+ return nsshtb_class->sud_cburst;
+ }
+
+ return 0;
+}
+
+/**
+ * Set quantum of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg quantum New quantum
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_class_set_quantum(struct rtnl_class *class, uint32_t quantum)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if (!(nsshtb_class = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
+
+ nsshtb_class->sud_quantum = quantum;
+ nsshtb_class->sud_mask |= NSSHTB_CLASS_ATTR_QUANTUM;
+ return 0;
+}
+
+/**
+ * Get quantum of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return configured quantum
+ */
+uint32_t rtnl_nsshtb_class_get_quantum(struct rtnl_class *class)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if ((nsshtb_class = rtnl_tc_data(TC_CAST(class))) &&
+ (nsshtb_class->sud_mask & NSSHTB_CLASS_ATTR_QUANTUM)) {
+
+ return nsshtb_class->sud_quantum;
+ }
+
+ return 0;
+}
+
+/**
+ * Set priority of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg priority New priority in bytes
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_class_set_priority(struct rtnl_class *class, uint32_t priority)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if (!(nsshtb_class = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
+
+ nsshtb_class->sud_priority = priority;
+ nsshtb_class->sud_mask |= NSSHTB_CLASS_ATTR_PRIORITY;
+ return 0;
+}
+
+/**
+ * Get priority of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return configured priority in bytes.
+ */
+uint32_t rtnl_nsshtb_class_get_priority(struct rtnl_class *class)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if ((nsshtb_class = rtnl_tc_data(TC_CAST(class))) &&
+ (nsshtb_class->sud_mask & NSSHTB_CLASS_ATTR_PRIORITY)) {
+
+ return nsshtb_class->sud_priority;
+ }
+
+ return 0;
+}
+
+/**
+ * Set overhead of NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc to be modified
+ * @arg overhead New overhead in bytes
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsshtb_class_set_overhead(struct rtnl_class *class, uint32_t overhead)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if (!(nsshtb_class = rtnl_tc_data(TC_CAST(class))))
+ return -NLE_NOMEM;
+
+ nsshtb_class->sud_overhead = overhead;
+ nsshtb_class->sud_mask |= NSSHTB_CLASS_ATTR_OVERHEAD;
+ return 0;
+}
+
+/**
+ * Get overhead of a NSSHTB qdisc.
+ * @arg qdisc NSSHTB qdisc.
+ * @return configured overhead in bytes.
+ */
+uint32_t rtnl_nsshtb_class_get_overhead(struct rtnl_class *class)
+{
+ struct rtnl_nsshtb_class *nsshtb_class;
+
+ if ((nsshtb_class = rtnl_tc_data(TC_CAST(class))) &&
+ (nsshtb_class->sud_mask & NSSHTB_CLASS_ATTR_OVERHEAD)) {
+
+ return nsshtb_class->sud_overhead;
+ }
+
+ return 0;
+}
+
+/** @} */
+
+static struct rtnl_tc_ops nsshtb_qdisc_ops = {
+ .to_kind = "nsshtb",
+ .to_type = RTNL_TC_TYPE_QDISC,
+ .to_size = sizeof(struct rtnl_nsshtb_qdisc),
+ .to_msg_parser = nsshtb_qdisc_msg_parser,
+ .to_dump = {
+ [NL_DUMP_LINE] = nsshtb_qdisc_dump_line,
+ [NL_DUMP_DETAILS] = NULL,
+ },
+ .to_msg_fill = nsshtb_qdisc_msg_fill,
+};
+
+static struct rtnl_tc_ops nsshtb_class_ops = {
+ .to_kind = "nsshtb",
+ .to_type = RTNL_TC_TYPE_CLASS,
+ .to_size = sizeof(struct rtnl_nsshtb_class),
+ .to_msg_parser = nsshtb_class_msg_parser,
+ .to_dump = {
+ [NL_DUMP_LINE] = nsshtb_class_dump_line,
+ [NL_DUMP_DETAILS] = NULL,
+ },
+ .to_msg_fill = nsshtb_class_msg_fill,
+};
+
+static void __init nsshtb_init(void)
+{
+ rtnl_tc_register(&nsshtb_qdisc_ops);
+ rtnl_tc_register(&nsshtb_class_ops);
+}
+
+static void __exit nsshtb_exit(void)
+{
+ rtnl_tc_unregister(&nsshtb_class_ops);
+ rtnl_tc_unregister(&nsshtb_qdisc_ops);
+}
+
+/** @} */