diff --git a/include/Makefile.am b/include/Makefile.am
index c5e0a90..7b8f0bd 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -59,6 +59,11 @@ nobase_libnlinclude_HEADERS = \
 	netlink/route/qdisc/codel.h \
 	netlink/route/qdisc/fq_codel.h \
 	netlink/route/qdisc/plug.h \
+	netlink/route/qdisc/nssbf.h \
+	netlink/route/qdisc/nsscodel.h \
+	netlink/route/qdisc/nssfifo.h \
+	netlink/route/qdisc/nssprio.h \
+	netlink/route/qdisc/nsstbl.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 fdc441a..4eb702a 100644
--- a/include/linux/pkt_sched.h
+++ b/include/linux/pkt_sched.h
@@ -755,5 +755,96 @@ struct tc_bf_xstats {
 
 #define TCA_BF_MAX      (__TCA_BF_MAX - 1)
 
+/* NSSFIFO section */
+
+enum {
+	TCA_NSSFIFO_UNSPEC,
+	TCA_NSSFIFO_PARMS,
+	__TCA_NSSFIFO_MAX
+};
+
+#define	TCA_NSSFIFO_MAX	(__TCA_NSSFIFO_MAX - 1)
+
+struct tc_nssfifo_qopt {
+	__u32   limit;		/* Queue length: bytes for bfifo, packets for pfifo */
+	__u8    set_default;	/* Sets qdisc to be the default qdisc for enqueue */
+};
+
+/* NSSCODEL section */
+
+enum {
+	TCA_NSSCODEL_UNSPEC,
+	TCA_NSSCODEL_PARMS,
+	__TCA_NSSCODEL_MAX
+};
+
+#define TCA_NSSCODEL_MAX	(__TCA_NSSCODEL_MAX - 1)
+
+struct tc_nsscodel_qopt {
+	__u32	target;		/* Acceptable queueing delay */
+	__u32	limit;		/* Maximum number of packets that can be held in the queue */
+	__u32	interval;	/* Monitoring interval */
+	__u8	set_default;	/* Sets qdisc to be the default qdisc for enqueue */
+};
+
+struct tc_nsscodel_xstats {
+	__u32 peak_queue_delay;	/* Peak delay experienced by a dequeued packet */
+	__u32 peak_drop_delay;	/* Peak delay experienced by a dropped packet */
+};
+
+/* NSSTBL section */
+
+enum {
+	TCA_NSSTBL_UNSPEC,
+	TCA_NSSTBL_PARMS,
+	__TCA_NSSTBL_MAX
+};
+
+#define TCA_NSSTBL_MAX	(__TCA_NSSTBL_MAX - 1)
+
+struct tc_nsstbl_qopt {
+	__u32	burst;		/* Maximum burst size */
+	__u32	rate;		/* Limiting rate of TBF */
+	__u32	peakrate;	/* Maximum rate at which TBF is allowed to send */
+	__u32	mtu;		/* Max size of packet, or minumim burst size */
+};
+
+/* NSSPRIO section */
+
+#define TCA_NSSPRIO_MAX_BANDS 256
+
+enum {
+	TCA_NSSPRIO_UNSPEC,
+	TCA_NSSPRIO_PARMS,
+	__TCA_NSSPRIO_MAX
+};
+
+#define TCA_NSSPRIO_MAX	(__TCA_NSSPRIO_MAX - 1)
+
+struct tc_nssprio_qopt {
+	int	bands;				/* Number of bands */
+};
+
+/* NSSBF section */
+
+enum {
+	TCA_NSSBF_UNSPEC,
+	TCA_NSSBF_CLASS_PARMS,
+	TCA_NSSBF_QDISC_PARMS,
+	__TCA_NSSBF_MAX
+};
+
+#define TCA_NSSBF_MAX	(__TCA_NSSBF_MAX - 1)
+
+struct tc_nssbf_class_qopt {
+	__u32	burst;		/* Maximum burst size */
+	__u32	rate;		/* Allowed bandwidth for this class */
+	__u32	mtu;		/* MTU of attached interface */
+	__u32	quantum;	/* Quantum allocation value for DRR */
+};
+
+struct tc_nssbf_qopt {
+	__u16	defcls;		/* Default class value */
+};
 
 #endif
diff --git a/include/netlink-private/types.h b/include/netlink-private/types.h
index fe97fa4..42eb07f 100644
--- a/include/netlink-private/types.h
+++ b/include/netlink-private/types.h
@@ -659,6 +659,47 @@ struct rtnl_sfb
 	uint32_t	qsb_mask;
 };
 
+struct rtnl_nssfifo
+{
+	uint32_t	qpf_limit;
+	uint32_t	qpf_mask;
+	uint8_t		qpf_set_default;
+};
+
+struct rtnl_nsscodel {
+	uint32_t	anf_target;
+	uint32_t	anf_limit;
+	uint32_t	anf_interval;
+	uint32_t	anf_mask;
+	uint8_t		anf_set_default;
+};
+
+struct rtnl_nsstbl {
+	uint32_t	ias_rate;
+	uint32_t	ias_burst;
+	uint32_t	ias_peakrate;
+	uint32_t	ias_mtu;
+	uint32_t	ias_mask;
+};
+
+struct rtnl_nssprio {
+	int		agj_bands;
+	uint32_t	agj_mask;
+};
+
+struct rtnl_nssbf_class {
+	uint32_t	ery_burst;
+	uint32_t	ery_rate;
+	uint32_t	ery_mtu;
+	uint32_t	ery_quantum;
+	uint32_t	ery_mask;
+};
+
+struct rtnl_nssbf_qdisc {
+	uint16_t	awv_defcls;
+	uint32_t	awv_mask;
+};
+
 struct rtnl_netem_corr
 {
 	uint32_t	nmc_delay;
diff --git a/include/netlink/route/qdisc/nssbf.h b/include/netlink/route/qdisc/nssbf.h
new file mode 100644
index 0000000..3d03126
--- /dev/null
+++ b/include/netlink/route/qdisc/nssbf.h
@@ -0,0 +1,49 @@
+/*
+ * netlink/route/sch/nssbf.h	NSSBF Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_NSSBF_H_
+#define NETLINK_NSSBF_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/tc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int rtnl_nssbf_qdisc_set_defcls(struct rtnl_qdisc *qdisc, uint16_t defcls);
+extern uint32_t rtnl_nssbf_qdisc_get_defcls(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nssbf_class_set_rate(struct rtnl_class *class, uint32_t rate);
+extern uint32_t rtnl_nssbf_class_get_rate(struct rtnl_class *class);
+
+extern int rtnl_nssbf_class_set_burst(struct rtnl_class *class, uint32_t burst);
+extern uint32_t rtnl_nssbf_class_get_burst(struct rtnl_class *class);
+
+extern int rtnl_nssbf_class_set_mtu(struct rtnl_class *class, uint32_t mtu);
+extern uint32_t rtnl_nssbf_class_get_mtu(struct rtnl_class *class);
+
+extern int rtnl_nssbf_class_set_quantum(struct rtnl_class *class, uint32_t q);
+extern uint32_t rtnl_nssbf_class_get_quantum(struct rtnl_class *class);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/qdisc/nsscodel.h b/include/netlink/route/qdisc/nsscodel.h
new file mode 100644
index 0000000..331032b
--- /dev/null
+++ b/include/netlink/route/qdisc/nsscodel.h
@@ -0,0 +1,46 @@
+/*
+ * netlink/route/sch/nsscodel.h	NSSCODEL Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_NSSCODEL_H_
+#define NETLINK_NSSCODEL_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/tc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int rtnl_nsscodel_set_limit(struct rtnl_qdisc *qdisc, uint32_t limit);
+extern uint32_t rtnl_nsscodel_get_limit(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nsscodel_set_target(struct rtnl_qdisc *qdisc, uint32_t target);
+extern uint32_t rtnl_nsscodel_get_target(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nsscodel_set_interval(struct rtnl_qdisc *qdisc, uint32_t interval);
+extern uint32_t rtnl_nsscodel_get_interval(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nsscodel_set_default(struct rtnl_qdisc *qdisc, uint8_t set_default);
+extern uint8_t rtnl_nsscodel_get_default(struct rtnl_qdisc *qdisc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/qdisc/nssfifo.h b/include/netlink/route/qdisc/nssfifo.h
new file mode 100644
index 0000000..37e6475
--- /dev/null
+++ b/include/netlink/route/qdisc/nssfifo.h
@@ -0,0 +1,40 @@
+/*
+ * netlink/route/sch/nssfifo.c	NSSFIFO Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_NSSFIFO_H_
+#define NETLINK_NSSFIFO_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/qdisc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int	rtnl_nssfifo_set_limit(struct rtnl_qdisc *, uint32_t);
+extern uint32_t	rtnl_nssfifo_get_limit(struct rtnl_qdisc *);
+
+extern int	rtnl_nssfifo_set_default(struct rtnl_qdisc *, uint8_t);
+extern uint8_t	rtnl_nssfifo_get_default(struct rtnl_qdisc *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/qdisc/nssprio.h b/include/netlink/route/qdisc/nssprio.h
new file mode 100644
index 0000000..39296d8
--- /dev/null
+++ b/include/netlink/route/qdisc/nssprio.h
@@ -0,0 +1,37 @@
+/*
+ * netlink/route/sch/nssprio.h	NSSPRIO Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_NSSPRIO_H_
+#define NETLINK_NSSPRIO_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/tc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int rtnl_nssprio_set_bands(struct rtnl_qdisc *qdisc, int bands);
+extern int rtnl_nssprio_get_bands(struct rtnl_qdisc *qdisc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/include/netlink/route/qdisc/nsstbl.h b/include/netlink/route/qdisc/nsstbl.h
new file mode 100644
index 0000000..c896540
--- /dev/null
+++ b/include/netlink/route/qdisc/nsstbl.h
@@ -0,0 +1,46 @@
+/*
+ * netlink/route/sch/nsstbl.h	NSSTBL Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_NSSTBL_H_
+#define NETLINK_NSSTBL_H_
+
+#include <netlink/netlink.h>
+#include <netlink/route/tc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int rtnl_nsstbl_set_rate(struct rtnl_qdisc *qdisc, uint32_t rate);
+extern uint32_t rtnl_nsstbl_get_rate(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nsstbl_set_burst(struct rtnl_qdisc *qdisc, uint32_t burst);
+extern uint32_t rtnl_nsstbl_get_burst(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nsstbl_set_mtu(struct rtnl_qdisc *qdisc, uint32_t mtu);
+extern uint32_t rtnl_nsstbl_get_mtu(struct rtnl_qdisc *qdisc);
+
+extern int rtnl_nsstbl_set_peakrate(struct rtnl_qdisc *qdisc, uint32_t peakrate);
+extern uint32_t rtnl_nsstbl_get_peakrate(struct rtnl_qdisc *qdisc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c6f5639..8891a0f 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -81,6 +81,8 @@ libnl_route_3_la_SOURCES = \
 	route/qdisc/drr.c \
 	route/qdisc/sfb.c \
 	route/qdisc/bf.c \
+	route/qdisc/nssfifo.c route/qdisc/nsstbl.c route/qdisc/nssbf.c \
+	route/qdisc/nssprio.c route/qdisc/nsscodel.c \
 	\
 	fib_lookup/lookup.c fib_lookup/request.c \
 	\
@@ -113,6 +115,7 @@ nobase_pkglib_LTLIBRARIES = \
 	cli/qdisc/pfifo.la \
 	cli/qdisc/plug.la \
 	cli/qdisc/bfifo.la \
+	cli/qdisc/nsspfifo.la \
 	cli/cls/basic.la \
 	cli/cls/cgroup.la
 
@@ -123,6 +126,7 @@ cli_qdisc_blackhole_la_LDFLAGS = -module -avoid-version
 cli_qdisc_pfifo_la_LDFLAGS = -module -avoid-version
 cli_qdisc_plug_la_LDFLAGS = -module -avoid-version
 cli_qdisc_bfifo_la_LDFLAGS = -module -avoid-version
+cli_qdisc_nsspfifo_la_LDFLAGS = -module -avoid-version
 cli_cls_basic_la_LDFLAGS = -module -avoid-version
 cli_cls_cgroup_la_LDFLAGS = -module -avoid-version
 endif
diff --git a/lib/cli/qdisc/nsspfifo.c b/lib/cli/qdisc/nsspfifo.c
new file mode 100644
index 0000000..b9d3cf8
--- /dev/null
+++ b/lib/cli/qdisc/nsspfifo.c
@@ -0,0 +1,92 @@
+/*
+ * src/lib/nsspfifo.c     	nsspfifo module for CLI lib
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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.
+ **************************************************************************
+ */
+
+#include <netlink/cli/utils.h>
+#include <netlink/cli/tc.h>
+#include <netlink/route/qdisc/nssfifo.h>
+
+static void print_usage(void)
+{
+	printf(
+"Usage: nl-qdisc-add [...] nsspfifo [OPTIONS]...\n"
+"\n"
+"OPTIONS\n"
+"     --help                Show this help text.\n"
+"     --limit=LIMIT         Maximum queue length in number of packets.\n"
+"     --set_default         Set, if this needs to be the default enqueue node.\n"
+"\n"
+"EXAMPLE"
+"    # Attach nsspfifo with a 32 packet limit to eth1, and set as default\n"
+"    nl-qdisc-add --dev=eth1 --parent=root nsspfifo --limit=32 --set_default\n");
+}
+
+static void nsspfifo_parse_argv(struct rtnl_tc *tc, int argc, char **argv)
+{
+	struct rtnl_qdisc *qdisc = (struct rtnl_qdisc *) tc;
+
+	rtnl_qdisc_nssfifo_set_set_default(qdisc, 0);
+	for (;;) {
+		int c, optidx = 0;
+		enum {
+			ARG_LIMIT = 257,
+			ARG_SET_DEFAULT = 258,
+		};
+		static struct option long_opts[] = {
+			{ "help", 0, 0, 'h' },
+			{ "limit", 1, 0, ARG_LIMIT },
+			{ "set_default", 1, 0, ARG_SET_DEFAULT },
+			{ 0, 0, 0, 0 }
+		};
+	
+		c = getopt_long(argc, argv, "h", long_opts, &optidx);
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'h':
+			print_usage();
+			return;
+
+		case ARG_LIMIT:
+			rtnl_qdisc_nssfifo_set_limit(qdisc, nl_cli_parse_u32(optarg));
+			break;
+
+		case ARG_SET_DEFAULT:
+			rtnl_qdisc_nssfifo_set_set_default(qdisc, 1);
+			break;
+		}
+ 	}
+}
+
+static struct nl_cli_tc_module nsspfifo_module =
+{
+	.tm_name		= "nsspfifo",
+	.tm_type		= RTNL_TC_TYPE_QDISC,
+	.tm_parse_argv		= nsspfifo_parse_argv,
+};
+
+static void __init nsspfifo_init(void)
+{
+	nl_cli_tc_register(&nsspfifo_module);
+}
+
+static void __exit nsspfifo_exit(void)
+{
+	nl_cli_tc_unregister(&nsspfifo_module);
+}
diff --git a/lib/route/qdisc/nssbf.c b/lib/route/qdisc/nssbf.c
new file mode 100644
index 0000000..bc94114
--- /dev/null
+++ b/lib/route/qdisc/nssbf.c
@@ -0,0 +1,411 @@
+/*
+ * lib/route/qdisc/nssbf.c		NSSBF Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_nssbf BF Scheduler (NSSBF)
+ * @{
+ */
+
+#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/nssbf.h>
+
+/** @cond SKIP */
+#define NSSBF_QDISC_ATTR_DEFCLS		0x001
+#define NSSBF_CLASS_ATTR_RATE		0x002
+#define NSSBF_CLASS_ATTR_BURST		0x004
+#define NSSBF_CLASS_ATTR_MTU		0x008
+#define NSSBF_CLASS_ATTR_QUANTUM	0x010
+/** @endcond */
+
+static struct nla_policy nssbf_policy[TCA_NSSBF_MAX+1] = {
+	[TCA_NSSBF_QDISC_PARMS]	= { .minlen = sizeof(struct tc_nssbf_qopt) },
+	[TCA_NSSBF_CLASS_PARMS]	= { .minlen = sizeof(struct tc_nssbf_class_qopt) },
+};
+
+static struct nla_policy nssbf_class_policy[TCA_NSSBF_MAX+1] = {
+};
+
+static int nssbf_qdisc_msg_parser(struct rtnl_tc *tc, void *data)
+{
+	struct nlattr *tb[TCA_NSSBF_MAX + 1];
+	struct rtnl_nssbf_qdisc *nssbf = data;
+	struct tc_nssbf_qopt *opts;
+	int err;
+
+	if ((err = tca_parse(tb, TCA_NSSBF_MAX, tc, nssbf_policy)) < 0)
+		return err;
+
+	if (tb[TCA_NSSBF_QDISC_PARMS]) {
+		opts = nla_data(tb[TCA_NSSBF_QDISC_PARMS]);
+
+		nssbf->awv_mask = 0;
+
+		nssbf->awv_defcls = opts->defcls;
+		nssbf->awv_mask |= NSSBF_QDISC_ATTR_DEFCLS;
+	}
+
+	return 0;
+}
+
+static int nssbf_class_msg_parser(struct rtnl_tc *tc, void *data)
+{
+	struct nlattr *tb[TCA_NSSBF_MAX + 1];
+	struct rtnl_nssbf_class *nssbf = data;
+	struct tc_nssbf_class_qopt *opts;
+	int err;
+
+	if ((err = tca_parse(tb, TCA_NSSBF_MAX, tc, nssbf_policy)) < 0)
+		return err;
+
+	if (tb[TCA_NSSBF_CLASS_PARMS]) {
+		opts = nla_data(tb[TCA_NSSBF_CLASS_PARMS]);
+
+		nssbf->ery_mask = 0;
+
+		nssbf->ery_rate = opts->rate;
+		nssbf->ery_mask |= NSSBF_CLASS_ATTR_RATE;
+
+		nssbf->ery_burst = opts->burst;
+		nssbf->ery_mask |= NSSBF_CLASS_ATTR_BURST;
+
+		nssbf->ery_mtu = opts->mtu;
+		nssbf->ery_mask |= NSSBF_CLASS_ATTR_MTU;
+
+		nssbf->ery_quantum = opts->quantum;
+		nssbf->ery_mask |= NSSBF_CLASS_ATTR_QUANTUM;
+	}
+
+	return 0;
+}
+
+static void nssbf_qdisc_dump_line(struct rtnl_tc *tc, void *data,
+			       struct nl_dump_params *p)
+{
+	struct rtnl_nssbf_qdisc *nssbf = data;
+
+	if (!nssbf)
+		return;
+
+	if (nssbf->awv_mask & NSSBF_QDISC_ATTR_DEFCLS) {
+		char buf[64];
+		nl_dump(p, " default-class %s",
+			rtnl_tc_handle2str(nssbf->awv_defcls,
+			buf, sizeof(buf)));
+	}
+}
+
+static void nssbf_class_dump_line(struct rtnl_tc *tc, void *data,
+			       struct nl_dump_params *p)
+{
+	struct rtnl_nssbf_class *nssbf = data;
+
+	if (!nssbf)
+		return;
+
+	if (nssbf->ery_mask & NSSBF_CLASS_ATTR_RATE) {
+		nl_dump(p, " Rate %u", nssbf->ery_rate);
+	}
+}
+
+static int nssbf_qdisc_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+	struct rtnl_nssbf_qdisc *nssbf = data;
+	struct tc_nssbf_qopt opts;
+
+	memset(&opts, 0, sizeof(opts));
+
+	if (nssbf) {
+		if (nssbf->awv_mask & NSSBF_QDISC_ATTR_DEFCLS)
+			opts.defcls = nssbf->awv_defcls;
+	}
+
+	NLA_PUT(msg, TCA_NSSBF_QDISC_PARMS, sizeof(opts), &opts);
+	return 0;
+
+nla_put_failure:
+	return -NLE_MSGSIZE;
+}
+
+static int nssbf_class_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+	struct rtnl_nssbf_class *nssbf = data;
+	struct tc_nssbf_class_qopt opts;
+	uint32_t required = NSSBF_CLASS_ATTR_RATE | NSSBF_CLASS_ATTR_BURST;
+
+	if (!nssbf)
+		return 0;
+
+	if ((nssbf->ery_mask & required) != required)
+		return -NLE_MISSING_ATTR;
+
+	memset(&opts, 0, sizeof(opts));
+
+	opts.rate = nssbf->ery_rate;
+	opts.burst = nssbf->ery_burst;
+
+	if (nssbf->ery_mask & NSSBF_CLASS_ATTR_MTU) {
+		opts.mtu = nssbf->ery_mtu;
+	}
+
+	if (nssbf->ery_mask & NSSBF_CLASS_ATTR_QUANTUM) {
+		opts.quantum = nssbf->ery_quantum;
+	}
+
+	NLA_PUT(msg, TCA_NSSBF_CLASS_PARMS, sizeof(opts), &opts);
+
+	return 0;
+
+nla_put_failure:
+	return -NLE_MSGSIZE;
+}
+
+/**
+ * @name Attribute Access
+ * @{
+ */
+
+/**
+ * Set defcls of NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc to be modified
+ * @arg defcls		New defcls for the qdisc
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssbf_qdisc_set_defcls(struct rtnl_qdisc *qdisc, uint16_t defcls)
+{
+	struct rtnl_nssbf_qdisc *nssbf_qdisc;
+
+	if (!(nssbf_qdisc = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nssbf_qdisc->awv_defcls = defcls;
+	nssbf_qdisc->awv_mask |= NSSBF_QDISC_ATTR_DEFCLS;
+	return 0;
+}
+
+/**
+ * Get defcls of a NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc.
+ * @return defcls value.
+ */
+uint32_t rtnl_nssbf_qdisc_get_defcls(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nssbf_qdisc *nssbf_qdisc;
+
+	if ((nssbf_qdisc = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nssbf_qdisc->awv_mask & NSSBF_QDISC_ATTR_DEFCLS)) {
+
+		return nssbf_qdisc->awv_defcls;
+	}
+
+	return TC_H_UNSPEC;
+}
+
+/**
+ * Set rate of NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc to be modified
+ * @arg rate		New rate in bytes per second
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssbf_class_set_rate(struct rtnl_class *class, uint32_t rate)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if (!(nssbf_class = rtnl_tc_data(TC_CAST(class))))
+		return -NLE_NOMEM;
+
+	nssbf_class->ery_rate = rate;
+	nssbf_class->ery_mask |= NSSBF_CLASS_ATTR_RATE;
+	return 0;
+}
+
+/**
+ * Get rate of a NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc.
+ * @return configured rate in bytes per second.
+ */
+uint32_t rtnl_nssbf_class_get_rate(struct rtnl_class *class)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if ((nssbf_class = rtnl_tc_data(TC_CAST(class))) &&
+		(nssbf_class->ery_mask & NSSBF_CLASS_ATTR_RATE)) {
+
+		return nssbf_class->ery_rate;
+	}
+
+	return 0;
+}
+
+/**
+ * Set burst of NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc to be modified
+ * @arg burst		New burst size in bytes.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssbf_class_set_burst(struct rtnl_class *class, uint32_t burst)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if (!(nssbf_class = rtnl_tc_data(TC_CAST(class))))
+		return -NLE_NOMEM;
+
+	nssbf_class->ery_burst = burst;
+	nssbf_class->ery_mask |= NSSBF_CLASS_ATTR_BURST;
+	return 0;
+}
+
+/**
+ * Get burst of a NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc.
+ * @return configured burst in bytes.
+ */
+uint32_t rtnl_nssbf_class_get_burst(struct rtnl_class *class)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if ((nssbf_class = rtnl_tc_data(TC_CAST(class))) &&
+		(nssbf_class->ery_mask & NSSBF_CLASS_ATTR_BURST)) {
+
+		return nssbf_class->ery_burst;
+	}
+
+	return 0;
+}
+
+/**
+ * Set mtu of NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc to be modified
+ * @arg mtu		New mtu in bytes
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssbf_class_set_mtu(struct rtnl_class *class, uint32_t mtu)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if (!(nssbf_class = rtnl_tc_data(TC_CAST(class))))
+		return -NLE_NOMEM;
+
+	nssbf_class->ery_mtu = mtu;
+	nssbf_class->ery_mask |= NSSBF_CLASS_ATTR_MTU;
+	return 0;
+}
+
+/**
+ * Get mtu of a NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc.
+ * @return configured mtu in bytes.
+ */
+uint32_t rtnl_nssbf_class_get_mtu(struct rtnl_class *class)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if ((nssbf_class = rtnl_tc_data(TC_CAST(class))) &&
+		(nssbf_class->ery_mask & NSSBF_CLASS_ATTR_MTU)) {
+
+		return nssbf_class->ery_mtu;
+	}
+
+	return 0;
+}
+
+/**
+ * Set quantum of NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc to be modified
+ * @arg quantum		New quantum
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssbf_class_set_quantum(struct rtnl_class *class, uint32_t quantum)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if (!(nssbf_class = rtnl_tc_data(TC_CAST(class))))
+		return -NLE_NOMEM;
+
+	nssbf_class->ery_quantum = quantum;
+	nssbf_class->ery_mask |= NSSBF_CLASS_ATTR_QUANTUM;
+	return 0;
+}
+
+/**
+ * Get quantum of a NSSBF qdisc.
+ * @arg qdisc		NSSBF qdisc.
+ * @return configured quantum
+ */
+uint32_t rtnl_nssbf_class_get_quantum(struct rtnl_class *class)
+{
+	struct rtnl_nssbf_class *nssbf_class;
+
+	if ((nssbf_class = rtnl_tc_data(TC_CAST(class))) &&
+		(nssbf_class->ery_mask & NSSBF_CLASS_ATTR_QUANTUM)) {
+
+		return nssbf_class->ery_quantum;
+	}
+
+	return 0;
+}
+
+/** @} */
+
+static struct rtnl_tc_ops nssbf_qdisc_ops = {
+	.to_kind		= "nssbf",
+	.to_type		= RTNL_TC_TYPE_QDISC,
+	.to_size		= sizeof(struct rtnl_nssbf_qdisc),
+	.to_msg_parser		= nssbf_qdisc_msg_parser,
+	.to_dump = {
+	    [NL_DUMP_LINE]	= nssbf_qdisc_dump_line,
+	    [NL_DUMP_DETAILS]	= NULL,
+	},
+	.to_msg_fill		= nssbf_qdisc_msg_fill,
+};
+
+static struct rtnl_tc_ops nssbf_class_ops = {
+	.to_kind		= "nssbf",
+	.to_type		= RTNL_TC_TYPE_CLASS,
+	.to_size		= sizeof(struct rtnl_nssbf_class),
+	.to_msg_parser		= nssbf_class_msg_parser,
+	.to_dump = {
+	    [NL_DUMP_LINE]	= nssbf_class_dump_line,
+	    [NL_DUMP_DETAILS]	= NULL,
+	},
+	.to_msg_fill		= nssbf_class_msg_fill,
+};
+
+static void __init nssbf_init(void)
+{
+	rtnl_tc_register(&nssbf_qdisc_ops);
+	rtnl_tc_register(&nssbf_class_ops);
+}
+
+static void __exit nssbf_exit(void)
+{
+	rtnl_tc_unregister(&nssbf_class_ops);
+	rtnl_tc_unregister(&nssbf_qdisc_ops);
+}
+
+/** @} */
diff --git a/lib/route/qdisc/nsscodel.c b/lib/route/qdisc/nsscodel.c
new file mode 100644
index 0000000..c8b5fa9
--- /dev/null
+++ b/lib/route/qdisc/nsscodel.c
@@ -0,0 +1,312 @@
+/*
+ * lib/route/qdisc/nsscodel.c		NSSCODEL Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_nsscodel CODEL Queue (NSSCODEL)
+ * @{
+ */
+
+#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/link.h>
+#include <netlink/route/qdisc/nsscodel.h>
+
+/** @cond SKIP */
+#define NSSCODEL_ATTR_TARGET		0x01
+#define NSSCODEL_ATTR_LIMIT		0x02
+#define NSSCODEL_ATTR_INTERVAL		0x04
+#define NSSCODEL_ATTR_SET_DEFAULT	0x08
+/** @endcond */
+
+static struct nla_policy nsscodel_policy[TCA_NSSCODEL_MAX + 1] = {
+	[TCA_NSSCODEL_PARMS]	= { .minlen = sizeof(struct tc_nsscodel_qopt) },
+};
+
+static int nsscodel_msg_parser(struct rtnl_tc *tc, void *data)
+{
+	struct rtnl_nsscodel *nsscodel = data;
+	struct nlattr *tb[TCA_NSSCODEL_MAX + 1];
+	struct tc_nsscodel_qopt *opts;
+	int err;
+
+	err = tca_parse(tb, TCA_NSSCODEL_MAX, tc, nsscodel_policy);
+	if (err < 0)
+		return err;
+
+
+	if (!tb[TCA_NSSCODEL_PARMS])
+		return -NLE_MISSING_ATTR;
+
+	opts = nla_data(tb[TCA_NSSCODEL_PARMS]);
+
+	nsscodel->anf_mask = 0;
+
+	nsscodel->anf_target = opts->target;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_TARGET;
+
+	nsscodel->anf_limit = opts->limit;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_LIMIT;
+
+	nsscodel->anf_interval = opts->interval;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_INTERVAL;
+
+	nsscodel->anf_set_default = opts->set_default;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_SET_DEFAULT;
+
+	return 0;
+}
+
+static void nsscodel_dump_line(struct rtnl_tc *tc, void *data,
+				  struct nl_dump_params *p)
+{
+	struct rtnl_nsscodel *nsscodel = data;
+
+	if (nsscodel && (nsscodel->anf_mask & NSSCODEL_ATTR_TARGET))
+		nl_dump(p, " target %u ms", nsscodel->anf_target);
+}
+
+static void nsscodel_dump_details(struct rtnl_tc *tc, void *data,
+				     struct nl_dump_params *p)
+{
+	struct rtnl_nsscodel *nsscodel = data;
+
+	if (!nsscodel)
+		return;
+
+	if (nsscodel->anf_mask & NSSCODEL_ATTR_LIMIT)
+		nl_dump(p, " limit %u packets", nsscodel->anf_limit);
+
+	if (nsscodel->anf_mask & NSSCODEL_ATTR_INTERVAL)
+		nl_dump(p, " interval %u ms", nsscodel->anf_interval);
+
+	if (nsscodel->anf_mask & NSSCODEL_ATTR_SET_DEFAULT)
+		nl_dump(p, " set_default %u", nsscodel->anf_set_default);
+}
+
+static int nsscodel_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+	struct tc_nsscodel_qopt opts;
+	struct rtnl_nsscodel *nsscodel = data;
+	uint32_t required = NSSCODEL_ATTR_TARGET | NSSCODEL_ATTR_INTERVAL;
+
+	if (!nsscodel )
+		return 0;
+
+	if ((nsscodel->anf_mask & required) != required)
+		return -NLE_MISSING_ATTR;
+
+	memset(&opts, 0, sizeof(opts));
+
+	opts.target = nsscodel->anf_target;
+	opts.interval = nsscodel->anf_interval;
+
+	if (nsscodel->anf_mask & NSSCODEL_ATTR_LIMIT)
+		opts.limit = nsscodel->anf_limit;
+
+	if (nsscodel->anf_mask & NSSCODEL_ATTR_SET_DEFAULT)
+		opts.set_default = nsscodel->anf_set_default;
+
+	NLA_PUT(msg, TCA_NSSCODEL_PARMS, sizeof(opts), &opts);
+
+	return 0;
+
+nla_put_failure:
+	return -NLE_MSGSIZE;
+}
+
+/**
+ * @name Attribute Access
+ * @{
+ */
+
+/**
+ * Set limit of NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc to be modified
+ * @arg limit		Queue limit in packets
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsscodel_set_limit(struct rtnl_qdisc *qdisc, uint32_t limit)
+{
+	struct rtnl_nsscodel *nsscodel;
+
+	if (!(nsscodel = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsscodel->anf_limit = limit;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_LIMIT;
+	return 0;
+}
+
+/**
+ * Get limit of a NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc.
+ * @return limit value in number of packets.
+ */
+uint32_t rtnl_nsscodel_get_limit(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsscodel *nsscodel;
+	
+	if ((nsscodel = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsscodel->anf_mask & NSSCODEL_ATTR_LIMIT)) {
+
+		return nsscodel->anf_limit;
+	}
+
+	return 0;
+}
+
+/**
+ * Set target of NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc to be modified
+ * @arg target		New target delay in usec.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsscodel_set_target(struct rtnl_qdisc *qdisc, uint32_t target)
+{
+	struct rtnl_nsscodel *nsscodel;
+
+	if (!(nsscodel = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsscodel->anf_target = target;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_TARGET;
+	return 0;
+}
+
+/**
+ * Get target of a NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc.
+ * @return target value in usec.
+ */
+uint32_t rtnl_nsscodel_get_target(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsscodel *nsscodel;
+	
+	if ((nsscodel = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsscodel->anf_mask & NSSCODEL_ATTR_TARGET)) {
+
+		return nsscodel->anf_target;
+	}
+
+	return 0;
+}
+
+/**
+ * Set interval of NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc to be modified
+ * @arg interval	New interval for the qdisc in usec.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsscodel_set_interval(struct rtnl_qdisc *qdisc, uint32_t interval)
+{
+	struct rtnl_nsscodel *nsscodel;
+
+	if (!(nsscodel = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsscodel->anf_interval = interval;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_INTERVAL;
+	return 0;
+}
+
+/**
+ * Get interval of a NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc.
+ * @return interval in usec.
+ */
+uint32_t rtnl_nsscodel_get_interval(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsscodel *nsscodel;
+	
+	if ((nsscodel = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsscodel->anf_mask & NSSCODEL_ATTR_INTERVAL)) {
+
+		return nsscodel->anf_interval;
+	}
+
+	return 0;
+}
+
+/**
+ * Set set_default of NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc to be modified
+ * @arg set_default	A value > 0 will make this the default enqueue node.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsscodel_set_default(struct rtnl_qdisc *qdisc, uint8_t set_default)
+{
+	struct rtnl_nsscodel *nsscodel;
+
+	if (!(nsscodel = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsscodel->anf_set_default = set_default;
+	nsscodel->anf_mask |= NSSCODEL_ATTR_SET_DEFAULT;
+	return 0;
+}
+
+/**
+ * Get set_default of a NSSCODEL qdisc.
+ * @arg qdisc		NSSCODEL qdisc.
+ * @return set_default value. Value > 0 means this is the default enqueue node.
+ */
+uint8_t rtnl_nsscodel_get_default(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsscodel *nsscodel;
+	
+	if ((nsscodel = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsscodel->anf_mask & NSSCODEL_ATTR_SET_DEFAULT)) {
+
+		return nsscodel->anf_set_default;
+	}
+
+	return 0;
+}
+
+/** @} */
+
+static struct rtnl_tc_ops nsscodel_qdisc_ops = {
+	.to_kind		= "nsscodel",
+	.to_type		= RTNL_TC_TYPE_QDISC,
+	.to_size		= sizeof(struct rtnl_nsscodel),
+	.to_msg_parser		= nsscodel_msg_parser,
+	.to_dump = {
+	    [NL_DUMP_LINE]      = nsscodel_dump_line,
+	    [NL_DUMP_DETAILS]   = nsscodel_dump_details,
+	},
+	.to_msg_fill		= nsscodel_msg_fill,
+};
+
+static void __init nsscodel_init(void)
+{
+	rtnl_tc_register(&nsscodel_qdisc_ops);
+}
+
+static void __exit nsscodel_exit(void)
+{
+	rtnl_tc_unregister(&nsscodel_qdisc_ops);
+}
+
+/** @} */
diff --git a/lib/route/qdisc/nssfifo.c b/lib/route/qdisc/nssfifo.c
new file mode 100644
index 0000000..fc95b10
--- /dev/null
+++ b/lib/route/qdisc/nssfifo.c
@@ -0,0 +1,216 @@
+/*
+ * lib/route/qdisc/nssfifo.c
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_nssfifo FIFO Queue (NSSFIFO)
+ * @{
+ */
+
+#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/nssfifo.h>
+#include <netlink/utils.h>
+
+/** @cond */
+#define NSSFIFO_ATTR_LIMIT		0x01
+#define NSSFIFO_ATTR_SET_DEFAULT	0x02
+/** @endcond */
+
+static struct nla_policy nssfifo_policy[TCA_NSSFIFO_MAX + 1] = {
+	[TCA_NSSFIFO_PARMS]	= { .minlen = sizeof(struct tc_nssfifo_qopt) },
+};
+
+static int nssfifo_msg_parser(struct rtnl_tc *tc, void *data)
+{
+	struct nlattr *tb[TCA_NSSFIFO_MAX + 1];
+	struct rtnl_nssfifo *nssfifo = data;
+	struct tc_nssfifo_qopt *opts;
+	int err;
+
+	err = tca_parse(tb, TCA_NSSFIFO_MAX, tc, nssfifo_policy);
+	if (err < 0)
+		return err;
+
+	if (!tb[TCA_NSSFIFO_PARMS])
+		return -NLE_MISSING_ATTR;
+
+	opts = nla_data(tb[TCA_NSSFIFO_PARMS]);
+
+	nssfifo->qpf_mask = 0;
+
+	nssfifo->qpf_limit = opts->limit;
+	nssfifo->qpf_mask |= NSSFIFO_ATTR_LIMIT;
+
+	nssfifo->qpf_set_default = opts->set_default;
+	nssfifo->qpf_mask |= NSSFIFO_ATTR_SET_DEFAULT;
+
+	return 0;
+}
+
+static void nssfifo_dump_line(struct rtnl_tc *tc, void *data,
+			    struct nl_dump_params *p)
+{
+	struct rtnl_nssfifo *nssfifo = data;
+
+	if (nssfifo && (nssfifo->qpf_mask & NSSFIFO_ATTR_LIMIT))
+		nl_dump(p, " limit %u packets", nssfifo->qpf_limit);
+}
+
+static void nssfifo_dump_details(struct rtnl_tc *tc, void *data, struct nl_dump_params *p)
+{
+	struct rtnl_nssfifo *nssfifo = data;
+
+	if (!nssfifo)
+		return;
+
+	if (nssfifo && (nssfifo->qpf_mask & NSSFIFO_ATTR_SET_DEFAULT))
+		nl_dump(p, " set_default %u", nssfifo->qpf_set_default);
+}
+
+static int nssfifo_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+	struct rtnl_nssfifo *nssfifo = data;
+	struct tc_nssfifo_qopt opts;
+
+	if (!nssfifo)
+		return -NLE_INVAL;
+
+	memset(&opts, 0, sizeof(opts));
+
+	if (nssfifo->qpf_mask & NSSFIFO_ATTR_LIMIT)
+		opts.limit = nssfifo->qpf_limit;
+
+	if (nssfifo->qpf_mask & NSSFIFO_ATTR_SET_DEFAULT)
+		opts.set_default = nssfifo->qpf_set_default;
+
+	NLA_PUT(msg, TCA_NSSFIFO_PARMS, sizeof(opts), &opts);
+	return 0;
+
+nla_put_failure:
+	return -NLE_MSGSIZE;
+}
+
+/**
+ * @name Attribute Modification
+ * @{
+ */
+
+/**
+ * Set limit of NSSFIFO qdisc.
+ * @arg qdisc		NSSFIFO qdisc to be modified.
+ * @arg limit		New limit in number of packets.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssfifo_set_limit(struct rtnl_qdisc *qdisc, uint32_t limit)
+{
+	struct rtnl_nssfifo *nssfifo;
+
+	if (!(nssfifo = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nssfifo->qpf_limit = limit;
+	nssfifo->qpf_mask |= NSSFIFO_ATTR_LIMIT;
+
+	return 0;
+}
+
+/**
+ * Get limit of a NSSFIFO qdisc.
+ * @arg qdisc		NSSFIFO qdisc.
+ * @return limit in number of packets.
+ */
+uint32_t rtnl_nssfifo_get_limit(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nssfifo *nssfifo;
+
+	if ((nssfifo = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nssfifo->qpf_mask & NSSFIFO_ATTR_LIMIT)) {
+
+		return nssfifo->qpf_limit;
+	}
+
+	return 0;
+}
+
+/**
+ * Set set_default of NSSFIFO qdisc.
+ * @arg qdisc		NSSFIFO 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_nssfifo_set_default(struct rtnl_qdisc *qdisc, uint8_t set_default)
+{
+	struct rtnl_nssfifo *nssfifo;
+
+	if (!(nssfifo = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nssfifo->qpf_set_default = set_default;
+	nssfifo->qpf_mask |= NSSFIFO_ATTR_SET_DEFAULT;
+
+	return 0;
+}
+
+/**
+ * Get limit of a NSSFIFO qdisc.
+ * @arg qdisc		NSSFIFO qdisc.
+ * @return set_default flag
+ */
+uint8_t rtnl_nssfifo_get_default(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nssfifo *nssfifo;
+
+	if ((nssfifo = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nssfifo->qpf_mask & NSSFIFO_ATTR_SET_DEFAULT)) {
+
+		return nssfifo->qpf_set_default;
+	}
+
+	return 0;
+}
+
+/** @} */
+
+static struct rtnl_tc_ops nsspfifo_ops = {
+	.to_kind		= "nsspfifo",
+	.to_type		= RTNL_TC_TYPE_QDISC,
+	.to_size		= sizeof(struct rtnl_nssfifo),
+	.to_msg_parser		= nssfifo_msg_parser,
+	.to_dump = {
+	    [NL_DUMP_LINE]	= nssfifo_dump_line,
+	    [NL_DUMP_DETAILS]	= nssfifo_dump_details,
+	},
+	.to_msg_fill		= nssfifo_msg_fill,
+};
+
+static void __init nssfifo_init(void)
+{
+	rtnl_tc_register(&nsspfifo_ops);
+}
+
+static void __exit nssfifo_exit(void)
+{
+	rtnl_tc_unregister(&nsspfifo_ops);
+}
+
+/** @} */
diff --git a/lib/route/qdisc/nssprio.c b/lib/route/qdisc/nssprio.c
new file mode 100644
index 0000000..77e6363
--- /dev/null
+++ b/lib/route/qdisc/nssprio.c
@@ -0,0 +1,162 @@
+/*
+ * lib/route/qdisc/nssprio.c		NSSPRIO Qdisc/Class
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_nssprio PRIO Qdisc/Class (NSSPRIO)
+ * @{
+ */
+
+#include <netlink-private/netlink.h>
+#include <netlink-private/tc.h>
+#include <netlink/netlink.h>
+#include <netlink/utils.h>
+#include <netlink-private/route/tc-api.h>
+#include <netlink/route/qdisc.h>
+#include <netlink/route/qdisc/nssprio.h>
+
+/** @cond SKIP */
+#define NSSPRIO_ATTR_BANDS	0x01
+/** @endcond */
+
+static struct nla_policy nssprio_policy[TCA_NSSPRIO_MAX + 1] = {
+	[TCA_NSSPRIO_PARMS]     = { .minlen = sizeof(struct tc_nssprio_qopt) },
+};
+
+static int nssprio_msg_parser(struct rtnl_tc *tc, void *data)
+{
+	struct nlattr *tb[TCA_NSSPRIO_MAX + 1];
+	struct rtnl_nssprio *nssprio = data;
+	struct tc_nssprio_qopt *opt;
+	int err;
+
+	err = tca_parse(tb, TCA_NSSPRIO_MAX, tc, nssprio_policy);
+	if (err < 0)
+		return err;
+
+	if (!tb[TCA_NSSPRIO_PARMS])
+		return -NLE_MISSING_ATTR;
+
+	opt = nla_data(tb[TCA_NSSPRIO_PARMS]);
+
+	nssprio->agj_mask = 0;
+
+	nssprio->agj_bands = opt->bands;
+	nssprio->agj_mask |= NSSPRIO_ATTR_BANDS;
+
+	return 0;
+}
+
+static void nssprio_dump_line(struct rtnl_tc *tc, void *data,
+			   struct nl_dump_params *p)
+{
+	struct rtnl_nssprio *nssprio = data;
+
+	if (nssprio && (nssprio->agj_mask & NSSPRIO_ATTR_BANDS))
+		nl_dump(p, " bands %u", nssprio->agj_bands);
+}
+
+static int nssprio_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+	struct rtnl_nssprio *nssprio = data;
+	struct tc_nssprio_qopt opt;
+
+	if (!nssprio)
+		return -NLE_INVAL;
+
+	memset(&opt, 0, sizeof(opt));
+
+	if (nssprio->agj_mask & NSSPRIO_ATTR_BANDS)
+		opt.bands = nssprio->agj_bands;
+
+	NLA_PUT(msg, TCA_NSSPRIO_PARMS, sizeof(opt), &opt);
+	return 0;
+
+nla_put_failure:
+	return -NLE_MSGSIZE;
+}
+
+/**
+ * @name Attribute Modification
+ * @{
+ */
+
+/**
+ * Set bands for NSSPRIO qdisc.
+ * @arg qdisc		NSSPRIO qdisc to be modified.
+ * @arg bands		Number of bands for nssprio.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nssprio_set_bands(struct rtnl_qdisc *qdisc, int bands)
+{
+	struct rtnl_nssprio *nssprio;
+
+	if (!(nssprio = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nssprio->agj_bands = bands;
+	nssprio->agj_mask |= NSSPRIO_ATTR_BANDS;
+
+	return 0;
+}
+
+/**
+ * Get bands of a NSSPRIO qdisc.
+ * @arg qdisc		NSSPRIO qdisc.
+ * @return number of bands used.
+ */
+int rtnl_nssprio_get_bands(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nssprio *nssprio;
+
+	if ((nssprio = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nssprio->agj_mask & NSSPRIO_ATTR_BANDS)) {
+
+		return nssprio->agj_bands;
+	}
+
+	return 0;
+}
+
+/** @} */
+
+static struct rtnl_tc_ops nssprio_ops = {
+	.to_kind		= "nssprio",
+	.to_type		= RTNL_TC_TYPE_QDISC,
+	.to_size		= sizeof(struct rtnl_nssprio),
+	.to_msg_parser		= nssprio_msg_parser,
+	.to_dump = {
+	    [NL_DUMP_LINE]	= nssprio_dump_line,
+	    [NL_DUMP_DETAILS]	= NULL,
+	},
+	.to_msg_fill		= nssprio_msg_fill,
+};
+
+static void __init nssprio_init(void)
+{
+	rtnl_tc_register(&nssprio_ops);
+}
+
+static void __exit nssprio_exit(void)
+{
+	rtnl_tc_unregister(&nssprio_ops);
+}
+
+/** @} */
diff --git a/lib/route/qdisc/nsstbl.c b/lib/route/qdisc/nsstbl.c
new file mode 100644
index 0000000..637917d
--- /dev/null
+++ b/lib/route/qdisc/nsstbl.c
@@ -0,0 +1,331 @@
+/*
+ * lib/route/qdisc/nsstbl.c		NSSTBL Qdisc
+ */
+/*
+ **************************************************************************
+ * Copyright (c) 2015, 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_nsstbl NSS Token Bucket Limiter (NSSTBL)
+ * @{
+ */
+
+#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/nsstbl.h>
+
+/** @cond SKIP */
+#define NSSTBL_ATTR_RATE			0x01
+#define NSSTBL_ATTR_BURST			0x02
+#define NSSTBL_ATTR_PEAKRATE			0x04
+#define NSSTBL_ATTR_MTU				0x08
+/** @endcond */
+
+static struct nla_policy nsstbl_policy[TCA_NSSTBL_MAX+1] = {
+	[TCA_NSSTBL_PARMS]	= { .minlen = sizeof(struct tc_nsstbl_qopt) },
+};
+
+static int nsstbl_msg_parser(struct rtnl_tc *tc, void *data)
+{
+	struct nlattr *tb[TCA_NSSTBL_MAX + 1];
+	struct rtnl_nsstbl *nsstbl = data;
+	struct tc_nsstbl_qopt *opts;
+	int err;
+
+	if ((err = tca_parse(tb, TCA_NSSTBL_MAX, tc, nsstbl_policy)) < 0)
+		return err;
+
+	if (!tb[TCA_NSSTBL_PARMS])
+		return -NLE_MISSING_ATTR;
+
+	opts = nla_data(tb[TCA_NSSTBL_PARMS]);
+
+	nsstbl->ias_mask = 0;
+
+	nsstbl->ias_rate = opts->rate;
+	nsstbl->ias_mask |= NSSTBL_ATTR_RATE;
+
+	nsstbl->ias_burst = opts->burst;
+	nsstbl->ias_mask |= NSSTBL_ATTR_BURST;
+
+	nsstbl->ias_peakrate = opts->peakrate;
+	nsstbl->ias_mask |= NSSTBL_ATTR_PEAKRATE;
+
+	nsstbl->ias_mtu = opts->mtu;
+	nsstbl->ias_mask |= NSSTBL_ATTR_MTU;
+
+	return 0;
+}
+
+static void nsstbl_dump_line(struct rtnl_tc *tc, void *data,
+			  struct nl_dump_params *p)
+{
+	double r, rbit;
+	char *ru, *rubit;
+	struct rtnl_nsstbl *nsstbl = data;
+
+	if (!nsstbl)
+		return;
+
+	r = nl_cancel_down_bytes(nsstbl->ias_rate, &ru);
+	rbit = nl_cancel_down_bits(nsstbl->ias_rate*8, &rubit);
+
+	nl_dump(p, " rate %.2f%s/s (%.0f%s)",
+		r, ru, rbit, rubit);
+}
+
+static void nsstbl_dump_details(struct rtnl_tc *tc, void *data,
+			     struct nl_dump_params *p)
+{
+	struct rtnl_nsstbl *nsstbl = data;
+
+	if (!nsstbl)
+		return;
+
+	if (1) {
+		char *bu;
+		double bs = nl_cancel_down_bytes(nsstbl->ias_burst, &bu);
+
+		nl_dump(p, "rate-bucket-size %1.f%s ",
+			bs, bu);
+
+	}
+
+	if (nsstbl->ias_mask & NSSTBL_ATTR_PEAKRATE) {
+		char *pru, *prbu, *bsu;
+		double pr, prb, bs;
+		
+		pr = nl_cancel_down_bytes(nsstbl->ias_peakrate, &pru);
+		prb = nl_cancel_down_bits(nsstbl->ias_peakrate*8, &prbu);
+		bs = nl_cancel_down_bits(nsstbl->ias_mtu, &bsu);
+
+		nl_dump_line(p, "    peak-rate %.2f%s/s (%.0f%s) "
+				"bucket-size %.1f%s",
+			     pr, pru, prb, prbu, bs, bsu);
+	}
+}
+
+static int nsstbl_msg_fill(struct rtnl_tc *tc, void *data, struct nl_msg *msg)
+{
+	struct tc_nsstbl_qopt opts;
+	struct rtnl_nsstbl *nsstbl = data;
+	int required = NSSTBL_ATTR_RATE | NSSTBL_ATTR_BURST;
+
+	if ((nsstbl->ias_mask & required) != required)
+		return -NLE_MISSING_ATTR;
+
+	memset(&opts, 0, sizeof(opts));
+
+	opts.rate = nsstbl->ias_rate;
+	opts.burst = nsstbl->ias_burst;
+
+	if (nsstbl->ias_mask & NSSTBL_ATTR_MTU) {
+		opts.mtu = nsstbl->ias_mtu;
+	}
+
+	if (nsstbl->ias_mask & NSSTBL_ATTR_PEAKRATE) {
+		opts.peakrate = nsstbl->ias_peakrate;
+	}
+
+	NLA_PUT(msg, TCA_NSSTBL_PARMS, sizeof(opts), &opts);
+
+	return 0;
+
+nla_put_failure:
+	return -NLE_MSGSIZE;
+}
+
+/**
+ * @name Attribute Access
+ * @{
+ */
+
+/**
+ * Set rate of NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc to be modified
+ * @arg rate		New rate in bytes per second
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsstbl_set_rate(struct rtnl_qdisc *qdisc, uint32_t rate)
+{
+	struct rtnl_nsstbl *nsstbl;
+
+	if (!(nsstbl = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsstbl->ias_rate = rate;
+	nsstbl->ias_mask |= NSSTBL_ATTR_RATE;
+	return 0;
+}
+
+/**
+ * Get rate of a NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc.
+ * @return configured rate in bytes per second.
+ */
+uint32_t rtnl_nsstbl_get_rate(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsstbl *nsstbl;
+	
+	if ((nsstbl = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsstbl->ias_mask & NSSTBL_ATTR_RATE)) {
+
+		return nsstbl->ias_rate;
+	}
+
+	return 0;
+}
+
+/**
+ * Set burst of NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc to be modified
+ * @arg burst		New burst size in bytes.
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsstbl_set_burst(struct rtnl_qdisc *qdisc, uint32_t burst)
+{
+	struct rtnl_nsstbl *nsstbl;
+
+	if (!(nsstbl = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsstbl->ias_burst = burst;
+	nsstbl->ias_mask |= NSSTBL_ATTR_BURST;
+	return 0;
+}
+
+/**
+ * Get burst of a NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc.
+ * @return configured burst in bytes.
+ */
+uint32_t rtnl_nsstbl_get_burst(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsstbl *nsstbl;
+	
+	if ((nsstbl = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsstbl->ias_mask & NSSTBL_ATTR_BURST)) {
+
+		return nsstbl->ias_burst;
+	}
+
+	return 0;
+}
+
+/**
+ * Set mtu of NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc to be modified
+ * @arg mtu		New mtu in bytes
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsstbl_set_mtu(struct rtnl_qdisc *qdisc, uint32_t mtu)
+{
+	struct rtnl_nsstbl *nsstbl;
+
+	if (!(nsstbl = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsstbl->ias_mtu = mtu;
+	nsstbl->ias_mask |= NSSTBL_ATTR_MTU;
+	return 0;
+}
+
+/**
+ * Get mtu of a NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc.
+ * @return configured mtu in bytes.
+ */
+uint32_t rtnl_nsstbl_get_mtu(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsstbl *nsstbl;
+	
+	if ((nsstbl = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsstbl->ias_mask & NSSTBL_ATTR_MTU)) {
+
+		return nsstbl->ias_mtu;
+	}
+
+	return 0;
+}
+
+/**
+ * Set peakrate of NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc to be modified
+ * @arg peakrate	New peakrate in bytes per second
+ * @return 0 on success or a negative error code.
+ */
+int rtnl_nsstbl_set_peakrate(struct rtnl_qdisc *qdisc, uint32_t peakrate)
+{
+	struct rtnl_nsstbl *nsstbl;
+
+	if (!(nsstbl = rtnl_tc_data(TC_CAST(qdisc))))
+		return -NLE_NOMEM;
+
+	nsstbl->ias_peakrate = peakrate;
+	nsstbl->ias_mask |= NSSTBL_ATTR_PEAKRATE;
+	return 0;
+}
+
+/**
+ * Get peakrate of a NSSTBL qdisc.
+ * @arg qdisc		NSSTBL qdisc.
+ * @return configured peakrate in bytes per second.
+ */
+uint32_t rtnl_nsstbl_get_peakrate(struct rtnl_qdisc *qdisc)
+{
+	struct rtnl_nsstbl *nsstbl;
+	
+	if ((nsstbl = rtnl_tc_data(TC_CAST(qdisc))) &&
+		(nsstbl->ias_mask & NSSTBL_ATTR_PEAKRATE)) {
+
+		return nsstbl->ias_peakrate;
+	}
+
+	return 0;
+}
+
+/** @} */
+
+static struct rtnl_tc_ops nsstbl_tc_ops = {
+	.to_kind		= "nsstbl",
+	.to_type		= RTNL_TC_TYPE_QDISC,
+	.to_size		= sizeof(struct rtnl_nsstbl),
+	.to_msg_parser		= nsstbl_msg_parser,
+	.to_dump = {
+	    [NL_DUMP_LINE]	= nsstbl_dump_line,
+	    [NL_DUMP_DETAILS]	= nsstbl_dump_details,
+	},
+	.to_msg_fill		= nsstbl_msg_fill,
+};
+
+static void __init nsstbl_init(void)
+{
+	rtnl_tc_register(&nsstbl_tc_ops);
+}
+
+static void __exit nsstbl_exit(void)
+{
+	rtnl_tc_unregister(&nsstbl_tc_ops);
+}
+
+/** @} */
