svn commit: r201996 - in user/luigi/ipfw3-head/sys/netinet: . ipfw

Luigi Rizzo luigi at FreeBSD.org
Sun Jan 10 12:31:36 UTC 2010


Author: luigi
Date: Sun Jan 10 12:31:35 2010
New Revision: 201996
URL: http://svn.freebsd.org/changeset/base/201996

Log:
  another batch of changes

Modified:
  user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c

Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Sun Jan 10 12:03:53 2010	(r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Sun Jan 10 12:31:35 2010	(r201996)
@@ -196,10 +196,11 @@ struct new_sch {
 /*
  * "queue N" and "pipe N" accept 1<=N<=65535. To map the values in
  * the same namespace (which we search through a hash table) we add
- * an offset to 'pipe N' below. The value is not so important, but
- * it should be known to userland as well so we can print it.
+ * an offset to 'pipe N' below.
+ * 'queue' -> 1..0x0ffff , 'pipe': 0x10001-0x1ffff
  */
-#define	DN_PIPEOFFSET	1000000
+#define	DN_MAXID	0x1ffff
+#define	DN_PIPEOFFSET	0x10000
 
 /*---- old parameters ---*/
 /*

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h	Sun Jan 10 12:03:53 2010	(r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched.h	Sun Jan 10 12:31:35 2010	(r201996)
@@ -47,27 +47,28 @@ struct dn_sched {
 
 	/*
 	 * The following define the size of 4 optional data structures
-	 * that may need to be allocated at runtime:
+	 * that may need to be allocated at runtime, and are appended
+	 * to each of the base data structures.
 	 */
 
 	/*    + parameters attached to the template, e.g.
 	 *	default queue sizes, weights, quantum size, and so on;
 	 */
-	size_t scheduler_size;      // sch_arg
+	size_t schk_len;
 
 	/*    + per-instance parameters, such as timestamps,
 	 *	ccontainers for queues, etc;
 	 */
-	size_t scheduler_i_size;    // sch_runtime
+	size_t sch_inst_len;
 
 	/*    + per-flowset parameters, such as individual weights,
 	 *	priorities, queue limits, slot sizes...
 	 */
-	size_t flowset_size;        // fs_arg
+	size_t fs_len;        // fs_arg
 
 	/*    + per-queue parameters (what for ?)
 	 */
-	size_t queue_size;          // queue_arg
+	size_t queue_len;          // queue_arg
 
 	SLIST_ENTRY(dn_sched) next; /* Next scheduler in the list */
 
@@ -114,22 +115,27 @@ struct dn_sched {
 	 *  drain_queue     called to free all idle queues, or possibly all of
 	 *                  them (this is a subset of delete_scheduler_instance)
 	 */
-	int (*enqueue)(struct new_sch_inst *s, void *f, struct mbuf *m,
-		    struct ipfw_flow_id *id);
+	int (*enqueue)(struct new_sch_inst *, struct new_fsk *,
+		struct mbuf *, struct ipfw_flow_id *);
 	struct mbuf * (*dequeue)(struct new_sch_inst *);
 
-	int (*config)(char *command, void *sch, int reconfigure);
-	int (*destroy)(void* sch);
-	int (*new_sched)(struct new_schk *s, struct new_sch_inst *si);
-	int (*free_sched)(struct new_sch_inst *si);
+	/* config or destroy the scheduler template */
+	int (*config)(struct new_schk *, int reconfigure);
+	int (*destroy)(struct new_schk*);
+
+	/* create, drain or destroy a new scheduler instance */
+	int (*new_sched)(struct new_schk *, struct new_sch_inst *);
+	int (*drain_sched)(struct new_sch_inst *, int flag);
+	int (*free_sched)(struct new_sch_inst *);
 
+	/* create or destroy a flowset attached to this scheduler */
 	int (*new_fs)(void *command, struct dn_id *g, int reconfigure);
-	int (*free_fs)(struct dn_id *f);
+	int (*free_fs)(struct new_fsk *);
 
+	/* create or destroy a queue attached to this scheduler */
 	int (*new_queue)(struct new_queue *q, struct dn_id *f);
 	int (*free_queue)(struct new_queue *q);
 
-	int (*drain_queue)(void *s, int flag);
 };
 SLIST_HEAD(dn_sched_head, dn_sched);
 

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c	Sun Jan 10 12:03:53 2010	(r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_sched_fifo.c	Sun Jan 10 12:31:35 2010	(r201996)
@@ -63,7 +63,7 @@ struct fifo_si {
 };
 
 static int 
-fifo_enqueue(struct new_sch_inst *_si, void *f,
+fifo_enqueue(struct new_sch_inst *_si, struct new_fs *f,
 	struct mbuf *m, struct ipfw_flow_id *id)
 {
     /*
@@ -180,14 +180,14 @@ fifo_free_sched(struct new_sch_inst *_si
 }
 
 static int
-drain_queue_fifo(void *s, int flag)
+fifo_drain(struct new_sch_inst *_si, int flag)
 {
     /*
      * Called by the system to free memory.
      * Remove the queue if it is empty or if the DN_FORCE flag is set
      */
 
-    struct fifo_si *si = (struct fifo_si *)s;
+    struct fifo_si *si = (struct fifo_si *)(_si + 1);
 
     if (si->q && (si->q->head == NULL || flag & DN_FORCE)) {
         dn_delete_queue(si->q, 0);
@@ -207,15 +207,15 @@ static struct dn_sched fifo_desc = {
     .type = DN_FIFO,
     .name = "FIFO scheduler algorithm descriptor",
 
-    .scheduler_i_size = sizeof(struct fifo_si),
-    .queue_size = sizeof(struct new_queue),
+    .sch_inst_len = sizeof(struct fifo_si),
+    .queue_len = sizeof(struct new_queue),
 
     .enqueue = fifo_enqueue,
     .dequeue = fifo_dequeue,
 
     .new_sched = fifo_new_sched,
     .free_sched = fifo_free_sched,
-    .drain_queue = drain_queue_fifo,
+    .drain_sched = fifo_drain,
 };
 
 DECLARE_DNSCHED_MODULE(dn_fifo, &fifo_desc);

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Sun Jan 10 12:03:53 2010	(r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Sun Jan 10 12:31:35 2010	(r201996)
@@ -461,7 +461,7 @@ create_scheduler_instance(struct new_sch
 	struct new_sch_inst *si;
 	int ret;
 	const char *msg = "malloc failure";
-	int l = sizeof(*si) + s->fp->scheduler_i_size;
+	int l = sizeof(*si) + s->fp->sch_inst_len;
 
 	si = malloc(l, M_DUMMYNET, M_NOWAIT | M_ZERO);
 
@@ -1111,13 +1111,22 @@ red_drops(struct dn_flow_set *fs, struct
 struct new_fsk *
 ipdn_locate_flowset(int fs_nr)
 {
-	struct new_fsk *fs;
+	struct new_fsk *fs = NULL;
 
-	SLIST_FOREACH(fs, &dn_cfg.fshash[HASH(fs_nr)], next)
-		if (fs->fs.fs_nr == fs_nr)
-			return (fs);
+	for (;;) {
+		SLIST_FOREACH(fs, &dn_cfg.fshash[HASH(fs_nr)], next)
+			if (fs->fs.fs_nr == fs_nr)
+				break;
+		if (!fs || fs->sched_id == dn_cfg.id)
+			break;
+		/* configuration changed, update */
+		if (dn_fs_config(fs)) {
+			fs = NULL;
+			break;
+		}
+	}
 
-	return (NULL);
+	return (fs);
 }
 
 /*
@@ -1138,7 +1147,7 @@ ipdn_locate_flowset(int fs_nr)
 int
 dummynet_io(struct mbuf **m0, int dir, struct ip_fw_args *fwa)
 {
-	struct mbuf *m = *m0, *head = NULL;
+	struct mbuf *m = *m0;
 	struct dn_pkt_tag *pkt;
 	struct m_tag *mtag;
 	struct new_fsk *fs = NULL;
@@ -1157,31 +1166,22 @@ dummynet_io(struct mbuf **m0, int dir, s
 	/* find flowset and schedset, protected by the UH lock */
 	DUMMYNET_LOCK();
 	io_pkt++;
+	/* XXX locate_flowset could be optimised with a direct ref. */
 	fs = ipdn_locate_flowset(fs_id);
 
 	if (fs == NULL)
 		goto dropit;	/* This queue/pipe does not exist! */
 
-	if (fs->sched_id != dn_cfg.id) { /* fs->sched invalid, update */
-		/* configuration changed, update */
-		int ret = dn_fs_config(fs);
-		if (ret)
-			goto dropit;
-		/* find again, just in case things changed */
-		fs = ipdn_locate_flowset(fs_id);
-		if (fs == NULL)
-			goto dropit;
-	}
 	sch = fs->sched;
-	if (sch == NULL)
+	if (sch == NULL)	/* should not happen */
 		goto dropit;
-	pipe = sch->pipe;
+	/* find_scheduler can be fast */
 	sch_inst = find_scheduler(sch, fs, &(fwa->f_id));
 	if (sch_inst == NULL)
 		goto dropit;
 
-	/* Apply the flow_mask */
-	do_mask(&fs->fs.flow_mask, &(fwa->f_id));
+	if (fs->kflags & DN_HAVE_MASK)
+		do_mask(&fs->fs.flow_mask, &(fwa->f_id));
 
 	/* tag the mbuf */
 	mtag = m_tag_get(PACKET_TAG_DUMMYNET,
@@ -1202,16 +1202,7 @@ dummynet_io(struct mbuf **m0, int dir, s
 	now = curr_time; /* in case it changes, use the same value */
 	pkt->output_time = now; /* XXX rewritten when reaches head */
 
-	/*
-	 * - 'sch_inst + 1' is the pointer to scheduler instance's
-	 *   private data, 'fs->alg_fs' is the flowset's private data,
-	 *   'm' is the packet, 'id' is the masked flowid of the packet
-	 *
-	 * NOTE: If the scheduler function wants really enqueue the
-	 *       packet, it must call the queue_packet()
-	 */
-
-	ret = sch->fp->enqueue(sch_inst + 1, fs->alg_fs, m, &(fwa->f_id));
+	ret = sch->fp->enqueue(sch_inst, fs, m, &(fwa->f_id));
 
 	if (ret) { /* packet was dropped by enqueue() */
 		*m0 = NULL;
@@ -1225,6 +1216,7 @@ dummynet_io(struct mbuf **m0, int dir, s
 	 */
 	if (sch_inst->flags & DN_ACTIVE)
 		goto done;
+	pipe = sch->pipe;
         sch_inst->numbytes = dn_cfg.io_fast ? pipe->bandwidth : 0;
         if (pipe->burst) {
 		uint64_t burst = (now - sch_inst->idle_time) *
@@ -1233,23 +1225,24 @@ dummynet_io(struct mbuf **m0, int dir, s
 			burst = pipe->burst;
 		sch_inst->numbytes += burst;
         }
-	head = serve_sched(sch_inst, now);
+	m = serve_sched(sch_inst, now);
 
 	/* optimization -- pass it back to ipfw for immediate send */
-	if (dn_cfg.io_fast && head == m && (dir & PROTO_LAYER2) == 0 ) {
+	if (dn_cfg.io_fast && m == *m0 && (dir & PROTO_LAYER2) == 0 ) {
 		/* fast io */
 		io_pkt_fast++;
 		printf("dummynet TEST: ** IOFAST **\n");
-		if (m->m_nextpkt != NULL)
+		if (m->m_nextpkt != NULL) {
 			printf("dummynet: fast io: pkt chain detected!\n");
-		head = m->m_nextpkt = NULL;
+			m->m_nextpkt = NULL;
+		}
 	} else {
 		*m0 = NULL;
+		if (m)
+			dummynet_send(m);
 	}
 done:
 	DUMMYNET_UNLOCK();
-	if (head != NULL)
-		dummynet_send(head);
 	return 0;
 
 dropit:

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Sun Jan 10 12:03:53 2010	(r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Sun Jan 10 12:31:35 2010	(r201996)
@@ -152,9 +152,9 @@ struct new_schk {
 	*/
 	int inst_counter;
 
-	/* Pointer to the parent pipe, and generation number */
-	int pipe_id;
+	/* Pointer to the parent pipe, always valid */
 	struct new_pipe *pipe;
+	struct new_id *private; /* per-scheduler data */
 
 	struct dn_id *cfg; /* extra config arguments */
 

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Sun Jan 10 12:03:53 2010	(r201995)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Sun Jan 10 12:31:35 2010	(r201996)
@@ -178,7 +178,8 @@ really_deletescheduler(struct new_schk *
             delete_scheduler_instance(sid);
         }
     }
-    s->fp->free_sched(s + 1);
+    if (s->fp->destroy)
+	    s->fp->destroy(s);
     s->fp->ref_count--;
     DN_S_LOCK_DESTROY(s);
     if (s->sch_i_size > 0)
@@ -495,7 +496,7 @@ dn_fs_config(struct new_fsk *fs)
 	fs = newfs;
 	fs->fp = s;
 	fs->active_f = 0;
-	fs->alg_fs = malloc(fs->fp->flowset_size, M_DUMMYNET, M_NOWAIT);
+	fs->alg_fs = malloc(fs->fp->fs_len, M_DUMMYNET, M_NOWAIT);
 	if (fs->alg_fs == NULL) {
 	    DN_S_UNLOCK(sch_t);
 	    printf("dummynet: no memory for new flowset ext\n");
@@ -643,7 +644,7 @@ config_pipe(struct new_pipe *p, struct d
 		return EINVAL;
 	}
 	i = p->pipe_nr;
-	if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+	if (i <= 0 || i > DN_MAXID)
 		return EINVAL;
 	/*
 	 * The config program passes parameters as follows:
@@ -672,8 +673,19 @@ config_pipe(struct new_pipe *p, struct d
 	return 0;
 }
 
+static struct new_schk *
+destroy_sched(struct new_schk *s)
+{
+	if (s->fp->destroy)
+		s->fp->destroy(s);
+	if (s->private)
+		free(s->private, M_DUMMYNET);
+	free(s, M_DUMMYNET);
+	return NULL;
+}
+
 /*
- * Configure a scheduler possibly allocating it (and the pipe)
+ * Configure a scheduler possibly allocating it (and the pipe).
  * XXX check link to type etc.
  * XXX postpone call 
  */
@@ -681,15 +693,15 @@ static int
 config_sched(struct new_sch *nsch, struct dn_id *arg)
 {
 	struct new_schk *s;
-	int i;
 	struct dn_sched *fp;
+	int i;
 
 	if (nsch->oid.len != sizeof(*nsch)) {
 		printf("%s: bad sched len\n", __FUNCTION__);
 		return EINVAL;
 	}
 	i = nsch->sched_nr;
-	if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+	if (i <= 0 || i > DN_MAXID)
 		return EINVAL;
 	/* XXX other sanity checks */
 	/* XXX make sure the type exists */
@@ -700,6 +712,8 @@ config_sched(struct new_sch *nsch, struc
 	}
 	DUMMYNET_LOCK();
 	s = locate_scheduler(i);
+	if (s && s->fp != fp)	/* type changed */
+		s = destroy_sched(s);
 	if (s == NULL) {
 		/* add a scheduler to the hash table */
 		s = malloc(sizeof(*s) + sizeof(struct new_pipe),
@@ -707,14 +721,15 @@ config_sched(struct new_sch *nsch, struc
 		if (s == NULL)
 			return ENOMEM;
 		s->pipe = (struct new_pipe *)(s+1);
+		s->fp = fp;
 		/* XXX init pipe ? */
 		SLIST_INSERT_HEAD(&dn_cfg.schedhash[HASH(i)], s, next);
 	}
 	s->sch = *nsch;
 	s->cfg = arg;
-	s->fp = fp;
 	/* call init function  */
-	s->fp->new_sched(s, s+1);
+	if (s->fp->config)
+		s->fp->config(s, 0);
 	reset_credit(s);
 	dn_cfg.id++;
 	DUMMYNET_UNLOCK();
@@ -735,7 +750,7 @@ config_fs(struct new_fs *nfs, struct dn_
 		return EINVAL;
 	}
 	i = nfs->fs_nr;
-	if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+	if (i <= 0 || i > DN_MAXID)
 		return EINVAL;
 	/* XXX other sanity checks */
 	DUMMYNET_LOCK();
@@ -771,7 +786,7 @@ config_profile(struct new_profile *pf, s
 		return EINVAL;
 	}
 	i = pf->pipe_nr;
-	if (i <= 0 || i >= 2*DN_PIPEOFFSET)
+	if (i <= 0 || i > DN_MAXID)
 		return EINVAL;
 	/* XXX other sanity checks */
 	DUMMYNET_LOCK();


More information about the svn-src-user mailing list