Merge "[qca-nss-qdisc] Add support for nss blackhole qdisc"
diff --git a/nss_qdisc/Makefile b/nss_qdisc/Makefile
index 4051a0e..ec25d0d 100755
--- a/nss_qdisc/Makefile
+++ b/nss_qdisc/Makefile
@@ -22,4 +22,5 @@
nss_prio.o \
nss_bf.o \
nss_wrr.o \
- nss_htb.o
+ nss_htb.o \
+ nss_blackhole.o
diff --git a/nss_qdisc/nss_blackhole.c b/nss_qdisc/nss_blackhole.c
new file mode 100644
index 0000000..6a4e753
--- /dev/null
+++ b/nss_qdisc/nss_blackhole.c
@@ -0,0 +1,253 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+#include "nss_qdisc.h"
+
+/*
+ * nss_blackhole private qdisc structure
+ */
+struct nss_blackhole_sched_data {
+ struct nss_qdisc nq; /* Common base class for all nss qdiscs */
+ u8 set_default; /* Flag to set qdisc as default qdisc for enqueue */
+};
+
+/*
+ * nss_blackhole_enqueue()
+ * Enqueue API for nss blackhole qdisc.
+ */
+static int nss_blackhole_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+{
+ return nss_qdisc_enqueue(skb, sch);
+}
+
+/*
+ * nss_blackhole_dequeue()
+ * Dequeue API for nss blackhole qdisc.
+ */
+static struct sk_buff *nss_blackhole_dequeue(struct Qdisc *sch)
+{
+ return nss_qdisc_dequeue(sch);
+}
+
+/*
+ * nss_blackhole_drop()
+ * The following function drops a packet from HLOS queue.
+ *
+ * Note, this does not drop packets from queues in the NSS. We do not support that.
+ */
+static unsigned int nss_blackhole_drop(struct Qdisc *sch)
+{
+ nss_qdisc_info("%s: qdisc %x dropping\n", __func__, sch->handle);
+ return nss_qdisc_drop(sch);
+}
+
+/*
+ * nss_blackhole_reset()
+ * Resets the nss blackhole qdisc.
+ */
+static void nss_blackhole_reset(struct Qdisc *sch)
+{
+ nss_qdisc_info("%s: qdisc %x resetting\n", __func__, sch->handle);
+ nss_qdisc_reset(sch);
+}
+
+/*
+ * nss_blackhole_destroy()
+ * Destroys the nss blackhole qdisc.
+ */
+static void nss_blackhole_destroy(struct Qdisc *sch)
+{
+ struct nss_qdisc *nq = (struct nss_qdisc *)qdisc_priv(sch);
+
+ /*
+ * Stop the polling of basic stats
+ */
+ nss_qdisc_stop_basic_stats_polling(nq);
+
+ nss_qdisc_info("%s: destroying qdisc %x\n", __func__, sch->handle);
+ nss_qdisc_destroy(nq);
+}
+
+/*
+ * nss_blackhole policy structure
+ */
+static const struct nla_policy nss_blackhole_policy[TCA_NSSBLACKHOLE_MAX + 1] = {
+ [TCA_NSSBLACKHOLE_PARMS] = { .len = sizeof(struct tc_nssblackhole_qopt) },
+};
+
+/*
+ * nss_blackhole_change()
+ * Function call used to configure the parameters of the nss blackhole qdisc.
+ */
+static int nss_blackhole_change(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct nss_blackhole_sched_data *q;
+ struct nlattr *na[TCA_NSSBLACKHOLE_MAX + 1];
+ struct tc_nssblackhole_qopt *qopt;
+ int err;
+ struct nss_if_msg nim;
+
+ q = qdisc_priv(sch);
+
+ if (opt == NULL) {
+ return -EINVAL;
+ }
+
+ err = nla_parse_nested(na, TCA_NSSBLACKHOLE_MAX, opt, nss_blackhole_policy);
+ if (err < 0)
+ return err;
+
+ if (na[TCA_NSSBLACKHOLE_PARMS] == NULL)
+ return -EINVAL;
+
+ qopt = nla_data(na[TCA_NSSBLACKHOLE_PARMS]);
+
+ /*
+ * Required for basic stats display
+ */
+ sch->limit = 0;
+
+ q->set_default = qopt->set_default;
+ nss_qdisc_info("%s: qdisc set_default = %u\n", __func__, qopt->set_default);
+
+ /*
+ * Underneath nss_bloackhole uses a fifo in the NSS. This is why we are sending down a configuration
+ * message to a fifo node. There are no blackhole shaper in the NSS as yet.
+ *
+ * Note: We simply set the limit of fifo to zero to get the blackhole behavior.
+ */
+ nim.msg.shaper_configure.config.msg.shaper_node_config.qos_tag = q->nq.qos_tag;
+ nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.limit = 0;
+ nim.msg.shaper_configure.config.msg.shaper_node_config.snc.fifo_param.drop_mode = NSS_SHAPER_FIFO_DROP_MODE_TAIL;
+ if (nss_qdisc_configure(&q->nq, &nim, NSS_SHAPER_CONFIG_TYPE_FIFO_CHANGE_PARAM) < 0) {
+ nss_qdisc_error("%s: qdisc %x configuration failed\n", __func__, sch->handle);
+ return -EINVAL;
+ }
+
+ /*
+ * There is nothing we need to do if the qdisc is not
+ * set as default qdisc.
+ */
+ if (q->set_default == 0)
+ return 0;
+
+ /*
+ * Set this qdisc to be the default qdisc for enqueuing packets.
+ */
+ if (nss_qdisc_set_default(&q->nq) < 0) {
+ nss_qdisc_error("%s: qdisc %x set_default failed\n", __func__, sch->handle);
+ return -EINVAL;
+ }
+
+ nss_qdisc_info("%s: qdisc %x set as default\n", __func__, q->nq.qos_tag);
+ return 0;
+}
+
+/*
+ * nss_blackhole_init()
+ * Initializes a nss blackhole qdisc.
+ */
+static int nss_blackhole_init(struct Qdisc *sch, struct nlattr *opt)
+{
+ struct nss_qdisc *nq = qdisc_priv(sch);
+
+ if (opt == NULL)
+ return -EINVAL;
+
+ nss_qdisc_info("%s: qdisc %x initializing\n", __func__, sch->handle);
+ nss_blackhole_reset(sch);
+
+ if (nss_qdisc_init(sch, nq, NSS_SHAPER_NODE_TYPE_FIFO, 0) < 0)
+ return -EINVAL;
+
+ nss_qdisc_info("%s: qdisc %x initialized with parent %x\n", __func__, sch->handle, sch->parent);
+ if (nss_blackhole_change(sch, opt) < 0) {
+ nss_qdisc_destroy(nq);
+ return -EINVAL;
+ }
+
+ /*
+ * Start the stats polling timer
+ */
+ nss_qdisc_start_basic_stats_polling(nq);
+
+ return 0;
+}
+
+/*
+ * nss_blackhole_dump()
+ * Dumps qdisc parameters for nss blackhole.
+ */
+static int nss_blackhole_dump(struct Qdisc *sch, struct sk_buff *skb)
+{
+ struct nss_blackhole_sched_data *q;
+ struct nlattr *opts = NULL;
+ struct tc_nssblackhole_qopt opt;
+
+ nss_qdisc_info("%s: qdisc %x dumping!\n", __func__, sch->handle);
+
+ q = qdisc_priv(sch);
+ if (q == NULL) {
+ return -1;
+ }
+
+ opt.set_default = q->set_default;
+
+ opts = nla_nest_start(skb, TCA_OPTIONS);
+ if (opts == NULL) {
+ goto nla_put_failure;
+ }
+ if (nla_put(skb, TCA_NSSBLACKHOLE_PARMS, sizeof(opt), &opt))
+ goto nla_put_failure;
+
+ return nla_nest_end(skb, opts);
+
+nla_put_failure:
+ nla_nest_cancel(skb, opts);
+ return -EMSGSIZE;
+}
+
+/*
+ * nss_blackhole_peek()
+ * Peeks the first packet in queue for this qdisc.
+ *
+ * Note: This just peeks at the first packet in what is present in HLOS. This does not
+ * perform an actual peak into the queue in the NSS. Given the async delay between
+ * the processors, there is less use in implementing this function.
+ */
+static struct sk_buff *nss_blackhole_peek(struct Qdisc *sch)
+{
+ nss_qdisc_info("%s: qdisc %x peeked\n", __func__, sch->handle);
+ return nss_qdisc_peek(sch);
+}
+
+/*
+ * Registration structure for nss blackhole qdisc
+ */
+struct Qdisc_ops nss_blackhole_qdisc_ops __read_mostly = {
+ .id = "nssblackhole",
+ .priv_size = sizeof(struct nss_blackhole_sched_data),
+ .enqueue = nss_blackhole_enqueue,
+ .dequeue = nss_blackhole_dequeue,
+ .peek = nss_blackhole_peek,
+ .drop = nss_blackhole_drop,
+ .init = nss_blackhole_init,
+ .reset = nss_blackhole_reset,
+ .destroy = nss_blackhole_destroy,
+ .change = nss_blackhole_change,
+ .dump = nss_blackhole_dump,
+ .owner = THIS_MODULE,
+};
diff --git a/nss_qdisc/nss_blackhole.h b/nss_qdisc/nss_blackhole.h
new file mode 100644
index 0000000..58dce8b
--- /dev/null
+++ b/nss_qdisc/nss_blackhole.h
@@ -0,0 +1,17 @@
+/*
+ **************************************************************************
+ * 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.
+ **************************************************************************
+ */
+
+extern struct Qdisc_ops nss_blackhole_qdisc_ops;
diff --git a/nss_qdisc/nss_fifo.c b/nss_qdisc/nss_fifo.c
index 4b873c4..7f4ab45 100644
--- a/nss_qdisc/nss_fifo.c
+++ b/nss_qdisc/nss_fifo.c
@@ -177,7 +177,7 @@
return nla_nest_end(skb, opts);
-nla_put_failure:
+nla_put_failure:
nla_nest_cancel(skb, opts);
return -EMSGSIZE;
}
diff --git a/nss_qdisc/nss_qdisc.c b/nss_qdisc/nss_qdisc.c
index 88011ea..7eaff17 100644
--- a/nss_qdisc/nss_qdisc.c
+++ b/nss_qdisc/nss_qdisc.c
@@ -24,6 +24,7 @@
#include "nss_wrr.h"
#include "nss_wfq.h"
#include "nss_htb.h"
+#include "nss_blackhole.h"
void *nss_qdisc_ctx; /* Shaping context for nss_qdisc */
wait_queue_head_t nss_qdics_wq; /* Wait queue used to wait on responses from the NSS */
@@ -2407,6 +2408,11 @@
return ret;
nss_qdisc_info("nsshtb registered");
+ ret = register_qdisc(&nss_blackhole_qdisc_ops);
+ if (ret != 0)
+ return ret;
+ nss_qdisc_info("nssblackhole registered");
+
ret = register_netdevice_notifier(&nss_qdisc_device_notifier);
if (ret != 0)
return ret;
@@ -2444,6 +2450,9 @@
unregister_qdisc(&nss_htb_qdisc_ops);
nss_qdisc_info("nsshtb unregistered\n");
+ unregister_qdisc(&nss_blackhole_qdisc_ops);
+ nss_qdisc_info("nssblackhole unregistered\n");
+
unregister_netdevice_notifier(&nss_qdisc_device_notifier);
}