svn commit: r202696 - in user/luigi/ipfw3-head/sys: conf
netinet/ipfw
Luigi Rizzo
luigi at FreeBSD.org
Wed Jan 20 13:50:30 UTC 2010
Author: luigi
Date: Wed Jan 20 13:50:30 2010
New Revision: 202696
URL: http://svn.freebsd.org/changeset/base/202696
Log:
add a round-robin scheduler
Added:
user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c (contents, props changed)
Modified:
user/luigi/ipfw3-head/sys/conf/files
Modified: user/luigi/ipfw3-head/sys/conf/files
==============================================================================
--- user/luigi/ipfw3-head/sys/conf/files Wed Jan 20 13:34:05 2010 (r202695)
+++ user/luigi/ipfw3-head/sys/conf/files Wed Jan 20 13:50:30 2010 (r202696)
@@ -2451,7 +2451,8 @@ netinet/in_rmx.c optional inet
netinet/ip_divert.c optional inet ipdivert ipfirewall
netinet/ipfw/dn_heap.c optional inet dummynet
netinet/ipfw/dn_sched_fifo.c optional inet dummynet
-netinet/ipfw/dn_sched_wf2q.c optional inet dummynet
+netinet/ipfw/dn_sched_rr.c optional inet dummynet
+netinet/ipfw/dn_sched_wf2q.c optional inet dummynet
netinet/ipfw/ip_dummynet.c optional inet dummynet
netinet/ipfw/ip_dn_io.c optional inet dummynet
netinet/ip_ecn.c optional inet | inet6
Added: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_rr.c Wed Jan 20 13:50:30 2010 (r202696)
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2010 Riccardo Panicucci, Universita` di Pisa
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/malloc.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/kernel.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <net/if.h> /* IFNAMSIZ */
+#include <netinet/in.h>
+#include <netinet/ip_var.h> /* ipfw_rule_ref */
+#include <netinet/ip_fw.h> /* flow_id */
+#include <netinet/ip_dummynet.h>
+#include <netinet/ipfw/dn_heap.h>
+#include <netinet/ipfw/ip_dn_private.h>
+#include <netinet/ipfw/dn_sched.h>
+
+#define DN_SCHED_RR 3 // XXX Where?
+
+/* rr_queue is appended to a struct new_queue */
+struct rr_queue {
+ struct new_queue *parent; /* Pointer to standard queue */
+ int status; /* 1: queue is in the list */
+ TAILQ_ENTRY(rr_queue) entries; /* List of active queue */
+ int credit; /* Number of bytes to transmit */
+ int quantum; /* quantum * C */
+};
+TAILQ_HEAD(rr_queue_head, rr_queue);
+
+/* struct rr_schk contains global config parameters
+ * and is right after new_schk
+ */
+struct rr_schk {
+ int min_q; /* Min quantum */
+ int max_q; /* Max quantum */
+ int q_bytes; /* Bytes per quantum */
+};
+
+/* per-instance info, right after new_sch_inst */
+struct rr_si {
+ struct rr_queue *pointer; /* Pointer to current queue */
+ struct rr_queue_head q_list; /* List of queues */
+ int queue_n; /* number of queues in the list */
+};
+
+static inline void
+insert_queue(struct rr_queue *q, struct rr_si *si)
+{
+
+ if (TAILQ_EMPTY(&si->q_list)) { /* or si->queue_n == 0 */
+ TAILQ_INSERT_HEAD(&si->q_list, q, entries);
+ si->pointer = q;
+ }
+ else {
+ TAILQ_INSERT_BEFORE(si->pointer, q, entries);
+ }
+ q->status = 1;
+ si->queue_n++;
+}
+
+static inline void
+remove_queue(struct rr_queue *q, struct rr_si *si)
+{
+ TAILQ_REMOVE(&si->q_list, q, entries);
+ q->status = 0;
+ si->queue_n--;
+}
+
+static inline struct rr_queue *
+next_pointer(struct rr_si *si)
+{
+ if (si->queue_n == 0) { /* XXX needed? */
+ si->pointer = NULL;
+ return NULL;
+ }
+ si->pointer = TAILQ_NEXT(si->pointer, entries);
+ if (si->pointer == NULL)
+ si->pointer = TAILQ_FIRST(&si->q_list);
+
+ return si->pointer;
+}
+
+static int
+rr_enqueue(struct new_sch_inst *_si, struct new_queue *q, struct mbuf *m)
+{
+ struct rr_si *si;
+ struct rr_queue *alg_fq;
+
+ if (m != q->mq.head) {
+ if (dn_enqueue(q, m, 0)) /* packet was dropped */
+ return 1;
+ if (m == q->mq.head)
+ return 0;
+ }
+
+ /* If reach this point, queue q was idle */
+ si = (struct rr_si *)(_si + 1);
+ alg_fq = (struct rr_queue *)(q+1);
+
+ if (alg_fq->status == 1) /* Queue is already in the queue list */
+ return 0;
+
+ /* Insert the queue in the queue list */
+ insert_queue(alg_fq, si);
+
+ return 0;
+}
+
+static struct mbuf *
+rr_dequeue(struct new_sch_inst *_si)
+{
+ /* Access scheduler instance private data */
+ struct rr_si *si = (struct rr_si *)(_si + 1);
+ struct mbuf *pkt;
+ struct rr_queue *q;
+ struct new_queue *_q;
+ uint64_t len;
+
+ if (si->queue_n == 0) /* scheduler empty */
+ return NULL;
+
+ while (si->queue_n > 0) {
+ q = si->pointer;
+ _q = q->parent;
+ /* or use: _q = ((struct new_queue *)q) - 1; */
+ si->pointer = next_pointer(si);
+ if (_q->mq.head == NULL) {
+ /* empty queue, remove from list */
+ remove_queue(q, si);
+ continue;
+ }
+ pkt = _q->mq.head;
+ len = pkt->m_pkthdr.len;
+
+ if (len > q->credit) {
+ /* Packet too big */
+ q->credit += q->quantum;
+ /* Try next queue */
+ } else {
+ q->credit = q->credit - len + q->quantum;
+ return dn_dequeue(_q);
+ }
+ }
+
+ /* no packet to dequeue*/
+ return NULL;
+}
+
+static int
+rr_config(struct new_schk *_schk)
+{
+ struct rr_schk *schk = (struct rr_schk *)(_schk + 1);
+ printf("%s called\n", __FUNCTION__);
+
+ schk->min_q = 1;
+ schk->max_q = 1000;
+ schk->q_bytes = 50;
+
+ return 0;
+}
+
+static int
+rr_new_sched(struct new_sch_inst *_si)
+{
+ struct rr_si *si = (struct rr_si *)(_si + 1);
+
+ printf("%s called\n", __FUNCTION__);
+ si->pointer = NULL;
+ si->queue_n = 0;
+ TAILQ_INIT(&si->q_list);
+
+ return 0;
+}
+
+static int
+rr_free_sched(struct new_sch_inst *_si)
+{
+ printf("%s called\n", __FUNCTION__);
+ /* Nothing to do? */
+ return 0;
+}
+
+static int
+rr_new_fsk(struct new_fsk *fs)
+{
+ struct rr_schk *schk = (struct rr_schk *)(fs->sched + 1);
+ printf("%s called\n", __FUNCTION__);
+ if (fs->fs.quantum < schk->min_q)
+ fs->fs.quantum = schk->min_q;
+ else if (fs->fs.quantum > schk->max_q)
+ fs->fs.quantum = schk->max_q;
+ return 0;
+}
+
+static int
+rr_new_queue(struct new_queue *_q)
+{
+ struct rr_queue *q = (struct rr_queue *)(_q + 1);
+ struct rr_schk *schk = (struct rr_schk *)(_q->_si->sched + 1);
+
+ printf("%s called, schk->quantum=%d\n", __FUNCTION__, schk->q_bytes);
+ _q->ni.oid.subtype = DN_SCHED_RR;
+
+ q->quantum = _q->fs->fs.quantum * schk->q_bytes;
+ q->credit = q->quantum;
+ q->status = 0;
+ q->parent = _q;
+
+ if (_q->mq.head != NULL) {
+ /* Queue NOT empty, insert in the queue list */
+ insert_queue(q, (struct rr_si *)(_q->_si + 1));
+ }
+ return 0;
+}
+
+static int
+rr_free_queue(struct new_queue *_q)
+{
+ struct rr_queue *q = (struct rr_queue *)(_q + 1);
+
+ printf("%s called\n", __FUNCTION__);
+ if (q->status == 1) {
+ struct rr_si *si = (struct rr_si *)(_q->_si + 1);
+ remove_queue(q, si);
+ if (si->pointer == q)
+ si->pointer = next_pointer(si);
+ }
+ return 0;
+}
+
+/*
+ * RR scheduler descriptor
+ * contains the type of the scheduler, the name, the size of the
+ * structures and function pointers.
+ */
+static struct dn_sched rr_desc = {
+ .type = DN_SCHED_RR,
+ .name = "RR",
+ .flags = DN_MULTIQUEUE,
+
+ .si_datalen = sizeof(struct rr_si),
+ .q_datalen = sizeof(struct rr_queue),
+
+ .enqueue = rr_enqueue,
+ .dequeue = rr_dequeue,
+
+ .config = rr_config,
+ .new_sched = rr_new_sched,
+ .free_sched = rr_free_sched,
+
+ .new_fsk = rr_new_fsk,
+
+ .new_queue = rr_new_queue,
+ .free_queue = rr_free_queue,
+};
+
+
+DECLARE_DNSCHED_MODULE(dn_rr, &rr_desc);
More information about the svn-src-user
mailing list