959 lines
27 KiB
Diff
Executable File
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);
|
|
+}
|
|
+
|
|
+/** @} */
|