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