Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Jan 2010 22:37:53 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r201844 - in user/luigi/ipfw3-head/sys/netinet: . ipfw
Message-ID:  <201001082237.o08MbrEY012907@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Fri Jan  8 22:37:52 2010
New Revision: 201844
URL: http://svn.freebsd.org/changeset/base/201844

Log:
  partial processing of 'configure'

Modified:
  user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
  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	Fri Jan  8 22:34:17 2010	(r201843)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Fri Jan  8 22:37:52 2010	(r201844)
@@ -66,13 +66,15 @@ enum {
 	DN_FS_EXT,
 	DN_QUEUE_EXT,
 	DN_UNKNOW,
-	DN_CMD_CONFIGURE,
-	DN_CMD_DELETE,
+	DN_CMD_CONFIGURE,	/* objects follow */
+	DN_CMD_DELETE,		/* subtype + list of entries */
+	DN_CMD_GET,		/* subtype + list of entries */
+	DN_CMD_FLUSH,
 	DN_LAST,
 };
  
 /* These values are in the subtype field of struct gen */
-enum dn_configure {
+enum {
 	DN_CONF_PIPE  = 1,
 	DN_CONF_QUEUE = 2,
 	DN_CONF_SCHED = 3,
@@ -93,13 +95,21 @@ enum sched_flag {
 
 typedef uint64_t dn_key;
 
+struct new_cmd {	/* header for all sockopt */
+	struct dn_id oid;
+	int entries;
+	uint32_t	data[0];	/* actually, entries elements */
+};
+
 #define	ED_MAX_SAMPLES_NO	1024
 struct new_profile {
 	struct dn_id oid;
 	/* fields to simulate a delay profile */
 #define ED_MAX_NAME_LEN         32
 	char name[ED_MAX_NAME_LEN];
+	int pipe_nr;
 	int loss_level;
+	int bandwidth;
 	int samples_no;
 	int samples[ED_MAX_SAMPLES_NO]; /* this has actually samples_no slots */
 };

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Fri Jan  8 22:34:17 2010	(r201843)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_io.c	Fri Jan  8 22:37:52 2010	(r201844)
@@ -245,12 +245,12 @@ struct dn_pkt_tag {
 static struct dn_pkt_tag *
 dn_tag_get(struct mbuf *m)
 {
-    struct m_tag *mtag = m_tag_first(m);
-    KASSERT(mtag != NULL &&
+	struct m_tag *mtag = m_tag_first(m);
+	KASSERT(mtag != NULL &&
 	    mtag->m_tag_cookie == MTAG_ABI_COMPAT &&
 	    mtag->m_tag_id == PACKET_TAG_DUMMYNET,
 	    ("packet on dummynet queue w/o dummynet tag!"));
-    return (struct dn_pkt_tag *)(mtag+1);
+	return (struct dn_pkt_tag *)(mtag+1);
 }
 
 /*
@@ -262,6 +262,7 @@ transmit_event(struct delay_line *dline,
 {
 	struct mbuf *m;
 	struct mbuf *head = NULL, *tail = NULL;
+	struct dn_pkt_tag *pkt = NULL;
 
 	/* XXX we are under scheduler lock */
 	while ((m = dline->head) != NULL) {
@@ -280,7 +281,6 @@ transmit_event(struct delay_line *dline,
 		tail->m_nextpkt = NULL;
 
 	if ((m = dline->head) != NULL) {
-		struct dn_pkt_tag *pkt = dn_tag_get(m);
 		DN_HEAP_LOCK();
 		heap_insert(&dn_cfg.system_heap, pkt->output_time, dline);
 		DN_HEAP_UNLOCK();
@@ -471,7 +471,7 @@ create_scheduler_instance(struct new_sch
 
 	if (si == NULL)
 		goto error;
-	si->dline = malloc(sizeof(*si->dline, M_DUMMYNET, M_NOWAIT | M_ZERO);
+	si->dline = malloc(sizeof(*si->dline), M_DUMMYNET, M_NOWAIT | M_ZERO);
 	if (si->dline == NULL)
 		goto error;
 
@@ -670,7 +670,7 @@ dummynet_task(void *context, int pending
 	struct mbuf *head = NULL;
 
 	DN_HEAP_LOCK();
-	if (&dn_cfg.system_heap->elements > 0 &&
+	if (dn_cfg.system_heap.elements > 0 &&
 		DN_KEY_LEQ(HEAP_TOP(&dn_cfg.system_heap)->key, curr_time)) {
 	    p = HEAP_TOP(&dn_cfg.system_heap)->object;
 	    heap_extract(&dn_cfg.system_heap, NULL);
@@ -735,8 +735,6 @@ dummynet_task(void *context, int pending
 		DN_S_LOCK(dline->si->ptr_sched);
 		head = transmit_event(dline, curr_time);
 		DN_S_UNLOCK(dline->si->ptr_sched);
-		if (head != NULL)
-		    dummynet_send(head);
 	    }
 	}
 	if (head != NULL)
@@ -1256,11 +1254,10 @@ dummynet_io(struct mbuf **m0, int dir, s
 		*m0 = NULL;
 	}
 done:
-    DUMMYNET_UNLOCK();
-    if (head != NULL)
-        dummynet_send(head);
-
-    return 0;
+	DUMMYNET_UNLOCK();
+	if (head != NULL)
+		dummynet_send(head);
+	return 0;
 
 dropit:
 	io_pkt_drop++;

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Fri Jan  8 22:34:17 2010	(r201843)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dn_private.h	Fri Jan  8 22:37:52 2010	(r201844)
@@ -78,6 +78,7 @@ struct dn_parms {
 
 	int	io_fast;
 	struct timeval prev_t;
+	struct dn_heap	system_heap;
 };
 
 static inline void

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Fri Jan  8 22:34:17 2010	(r201843)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Fri Jan  8 22:37:52 2010	(r201844)
@@ -76,6 +76,10 @@ static struct taskqueue	*dn_tq = NULL;
 
 static struct dn_sched_head    list_of_scheduler;
 
+static int config_pipe(struct new_pipe *p);
+static int config_profile(struct new_profile *p);
+static int config_fs(struct new_fs *p);
+static int config_sched(struct new_sch *p);
 /*
  * This is called one tick, after previous run. It is used to
  * schedule next run.
@@ -183,7 +187,7 @@ really_deletescheduler(struct new_sch *s
     return 0;
 }
 
-
+/* remove a pipe and attached objects */
 static void
 free_pipe(struct new_pipe *p)
 {
@@ -193,63 +197,6 @@ free_pipe(struct new_pipe *p)
 }
 
 /*
- * Dispose all packets and flow_queues on a flow_set.
- * If all=1, also remove red lookup table and other storage,
- * including the descriptor itself.
- * For the one in dn_pipe MUST also cleanup ready_heap...
- */
-static void
-purge_flow_set(struct new_fs *fs, int all)
-{
-#if 0
-	struct new_queue *q, *qn;
-	int i;
-
-	DUMMYNET_LOCK_ASSERT();
-
-	for (i = 0; i <= fs->rq_size; i++) {
-		for (q = fs->rq[i]; q != NULL; q = qn) {
-			dn_free_pkts(q->head);
-			qn = q->next;
-			free(q, M_DUMMYNET);
-		}
-		fs->rq[i] = NULL;
-	}
-
-	fs->rq_elements = 0;
-	if (all) {
-		/* RED - free lookup table. */
-		if (fs->w_q_lookup != NULL)
-			free(fs->w_q_lookup, M_DUMMYNET);
-		if (fs->rq != NULL)
-			free(fs->rq, M_DUMMYNET);
-		/* If this fs is not part of a pipe, free it. */
-		if (fs->pipe == NULL || fs != &(fs->pipe->fs))
-			free(fs, M_DUMMYNET);
-	}
-#endif
-}
-
-/*
- * Dispose all packets queued on a pipe (not a flow_set).
- * Also free all resources associated to a pipe, which is about
- * to be deleted.
- */
-static void
-purge_pipe(struct new_pipe *pipe)
-{
-#if 0
-    purge_flow_set( &(pipe->fs), 1 );
-
-    dn_free_pkts(pipe->head);
-
-    heap_free( pipe->scheduler_heap );
-    heap_free( pipe->not_eligible_heap );
-    heap_free( pipe->idle_heap );
-#endif
-}
-
-/*
  * Deelete all objects.
  */
 static void
@@ -257,6 +204,7 @@ dummynet_flush(void)
 {
 	struct new_pipe *pipe, *pipe1;
 	struct new_fs *fs, *fs1;
+	struct new_sch *sch_t, *sch_t1;
 	int i;
 
 	DUMMYNET_LOCK();
@@ -265,7 +213,7 @@ dummynet_flush(void)
     heap_free(&dn_cfg.system_heap);
 
     /* Free all pipes */
-    for (i = 0; i < HASHSIZE; i++) {
+    for (i = 0; i < DN_HASHSIZE; i++) {
         SLIST_FOREACH_SAFE(pipe, &pipehash[i], next, pipe1) {
             SLIST_REMOVE(&pipehash[i], pipe, new_pipe, next);
             free_pipe(pipe);
@@ -279,10 +227,10 @@ dummynet_flush(void)
     }
 
     /* Free all flowsets in the system */
-    for (i = 0; i < HASHSIZE; i++) {
+    for (i = 0; i < DN_HASHSIZE; i++) {
         SLIST_FOREACH_SAFE(fs, &flowsethash[i], next, fs1) {
             SLIST_REMOVE(&flowsethash[i], fs, new_fs, next);
-            fs->fp->delete_alg_fs(fs->alg_fs);
+            fs->fp->free_fs(fs->alg_fs);
             fs->fp->ref_count--;
             free(fs->alg_fs, M_DUMMYNET);
             free(fs, M_DUMMYNET);
@@ -290,7 +238,7 @@ dummynet_flush(void)
     }
 
     /* Free all schedulers */
-    for (i = 0; i < HASHSIZE; i++) {
+    for (i = 0; i < DN_HASHSIZE; i++) {
         SLIST_FOREACH_SAFE(sch_t, &schedulerhash[i], next, sch_t1) {
             SLIST_REMOVE(&schedulerhash[i], sch_t, new_sch, next);
             sch_t->flags |= DN_SCH_DELETE_DELAY_LINE;
@@ -418,13 +366,44 @@ set_fs_parms(struct dn_flow_set *x, stru
 static int
 do_config(void *p, int l)
 {
-	struct dn_id *o = p;
+	struct dn_id *next, *o;
+	int err = 0, cmd = 0;
 
-	while (l && o->len > 0) {
+	for (o = p; l >= sizeof(*o); o = next) {
+		err = EINVAL;
+		if (o->len < sizeof(*o) || l < o->len) {
+			printf("bad len o->len %d len %d\n", o->len, l);
+			break;
+		}
 		l -= o->len;
-		o = (struct dn_id *)((char *)o + l);
+		printf("%s cmd %d len %d left %d\n",
+			__FUNCTION__, o->type, o->len, l);
+		next = (struct dn_id *)((char *)o + o->len);
+		switch (o->type) {
+		case DN_CMD_CONFIGURE:
+		case DN_CMD_GET:
+		case DN_CMD_DELETE:
+		case DN_CMD_FLUSH:
+			cmd = o->type;
+			err = 0;
+			break;
+		case DN_PIPE:
+			err = config_pipe((struct new_pipe *)o);
+			break;
+		case DN_PROFILE:
+			err = config_profile((struct new_profile *)o);
+			break;
+		case DN_SCH:
+			err = config_sched((struct new_sch *)o);
+			break;
+		case DN_FS:
+			err = config_fs((struct new_fs *)o);
+			break;
+		}
+		if (err != 0)
+			break;
 	}
-	return 0;
+	return err;
 }
 
 static struct new_sch *
@@ -673,16 +652,17 @@ dn_fs_config(struct new_fs *fs)
  *	(re)configures the WFQ scheduler for the pipe.
  */
 static int
-config_pipe(struct dn_pipe *p)
+config_pipe(struct new_pipe *p)
 {
-#if 0
-	struct dn_flow_set *pfs = &(p->fs);
-	struct dn_flow_queue *q;
-	int i, error;
+	struct new_pipe *pipe;
 
+	if (p->oid.len < sizeof(*p)) {
+		printf("%s: short pipe\n", __FUNCTION__);
+		return EINVAL;
+	}
 	/* We need either a pipe number or a flow_set number. */
-	if (p->pipe_nr == 0 && pfs->fs_nr == 0)
-		return (EINVAL);
+	if (p->pipe_nr <= 0 || p->pipe_nr >= DN_PIPEOFFSET)
+		return EINVAL;
 	/*
 	 * The config program passes parameters as follows:
 	 * bw = bits/second (0 means no limits),
@@ -694,79 +674,103 @@ config_pipe(struct dn_pipe *p)
 	p->burst *= 8 * hz;
 
 	DUMMYNET_LOCK();
-	if (p->pipe_nr != 0) {			/* this is a pipe */
-		struct dn_pipe *pipe;
-
-		pipe = locate_pipe(p->pipe_nr);	/* locate pipe */
+	pipe = locate_pipe(p->pipe_nr);	/* locate pipe */
 
-		if (pipe == NULL) {		/* new pipe */
-			/* space for pipe + 3 heaps right after the pipe */
-			pipe = malloc(sizeof(struct dn_pipe) +
-				3 * sizeof(struct dn_heap), M_DUMMYNET,
-			    M_NOWAIT | M_ZERO);
-			if (pipe == NULL) {
-				DUMMYNET_UNLOCK();
-				printf("dummynet: no memory for new pipe\n");
-				return (ENOMEM);
-			}
+	if (pipe == NULL) { /* brand new pipe */
+		pipe = malloc(sizeof(*pipe), M_DUMMYNET, M_NOWAIT | M_ZERO);
+		if (pipe == NULL) {
+			DUMMYNET_UNLOCK();
+			printf("dummynet: no memory for new pipe\n");
+			return (ENOMEM);
+		}
+		bcopy(p, pipe, sizeof(*pipe));
+		/* XXX schedulers should attach to us... */
+	} else {
+	    /* pipe already exists, reconfigure it. */
+	    struct new_sch *sch;
+	    struct new_sch_inst *si;
+	    int i;
+
+	    sch = locate_scheduler(pipe->pipe_nr + DN_PIPEOFFSET);
+	    if (sch) {
+		/* Flush accumulated credit for all queues. */
+		for (i = 0; i < sch->sch_i_size; i++)
+		    for (si = sch->sch_i[i]; si; si = si->next)
+			si->numbytes = p->burst + dn_cfg.io_fast ?
+				    p->bandwidth : 0;
+	    }
+	    pipe->delay = p->delay;
+	    pipe->bandwidth = p->bandwidth;
+	    pipe->burst = p->burst;
+	    bcopy(p->if_name, pipe->if_name, sizeof(p->if_name));
+	    pipe->ifp = NULL;		/* reset interface ptr */
+	}
+	dn_cfg.id++;
+	DUMMYNET_UNLOCK();
+	return 0;
+}
 
-			pipe->scheduler_heap = (struct dn_heap *)(pipe + 1);
-			pipe->not_eligible_heap = pipe->scheduler_heap + 1;
-			pipe->idle_heap = pipe->scheduler_heap + 2;
+static int
+config_sched(struct new_sch *sch)
+{
+	return 0;
+}
 
-			pipe->pipe_nr = p->pipe_nr;
-			pipe->fs.pipe = pipe;
-			/*
-			 * idle_heap is the only one from which
-			 * we extract from the middle.
-			 */
-			pipe->idle_heap->ofs =
-			    offsetof(struct dn_flow_queue, heap_pos);
-		} else {
-			/* Flush accumulated credit for all queues. */
-			for (i = 0; i <= pipe->fs.rq_size; i++) {
-				for (q = pipe->fs.rq[i]; q; q = q->next) {
-					q->numbytes = p->burst +
-					    (dn_cfg.io_fast ? p->bandwidth : 0);
-				}
-			}
-		}
+static int
+config_fs(struct new_fs *fs)
+{
+	return 0;
+}
+/*
+ * attach a profile to a pipe
+ */
+static int
+config_profile(struct new_profile *pf)
+{
+	struct new_pipe *pipe;
 
-		pipe->bandwidth = p->bandwidth;
-		pipe->burst = p->burst;
-		pipe->numbytes = pipe->burst + (dn_cfg.io_fast ? pipe->bandwidth : 0);
-		bcopy(p->if_name, pipe->if_name, sizeof(p->if_name));
-		pipe->ifp = NULL;		/* reset interface ptr */
-		pipe->delay = p->delay;
-		set_fs_parms(&(pipe->fs), pfs);
+	if (pf->oid.len < sizeof(*pf)) {
+		printf("%s: short profile\n", __FUNCTION__);
+		return EINVAL;
+	}
+	/* We need a pipe number . */
+	if (pf->pipe_nr <= 0 || pf->pipe_nr >= DN_PIPEOFFSET)
+		return EINVAL;
+	/* XXX other sanity checks */
+	DUMMYNET_LOCK();
+	pipe = locate_pipe(pf->pipe_nr);	/* locate pipe */
 
-		/* Handle changes in the delay profile. */
-		if (p->samples_no > 0) {
-			if (pipe->samples_no != p->samples_no) {
-				if (pipe->samples != NULL)
-					free(pipe->samples, M_DUMMYNET);
-				pipe->samples =
-				    malloc(p->samples_no*sizeof(dn_key),
-					M_DUMMYNET, M_NOWAIT | M_ZERO);
-				if (pipe->samples == NULL) {
-					DUMMYNET_UNLOCK();
-					printf("dummynet: no memory "
-						"for new samples\n");
-					return (ENOMEM);
-				}
-				pipe->samples_no = p->samples_no;
-			}
+	if (pipe == NULL) { /* brand new pipe */
+		DUMMYNET_UNLOCK();
+		printf("%s: no pipe %d\n", __FUNCTION__, pf->pipe_nr);
+		return EINVAL;
+	}
 
-			strncpy(pipe->name,p->name,sizeof(pipe->name));
-			pipe->loss_level = p->loss_level;
-			for (i = 0; i<pipe->samples_no; ++i)
-				pipe->samples[i] = p->samples[i];
-		} else if (pipe->samples != NULL) {
-			free(pipe->samples, M_DUMMYNET);
-			pipe->samples = NULL;
-			pipe->samples_no = 0;
+	dn_cfg.id++;
+	/* see if we need to allocate memory */
+	if (pipe->profile && (pf->samples_no == 0 ||
+			pipe->profile->oid.len < pf->oid.len)) {
+		free(pipe->profile, M_DUMMYNET);
+		pipe->profile = NULL;
+	}
+	if (pf->samples_no > 0) {
+		if (pipe->profile == NULL)
+			pipe->profile = malloc(pf->oid.len,
+			    M_DUMMYNET, M_NOWAIT | M_ZERO);
+		if (pipe->profile == NULL) {
+			DUMMYNET_UNLOCK();
+			printf("%s: no memory\n", __FUNCTION__);
+			return ENOMEM;
 		}
-
+		bcopy(pf, pipe->profile, pf->oid.len);
+	}
+	DUMMYNET_UNLOCK();
+	return 0;
+}
+	
+#if 0
+	/* We need either a pipe number or a flow_set number. */
+		set_fs_parms(&(pipe->fs), pfs);
 		if (pipe->fs.rq == NULL) {	/* a new pipe */
 			error = alloc_hash(&(pipe->fs), pfs);
 			if (error) {
@@ -828,11 +832,9 @@ config_pipe(struct dn_pipe *p)
 		}
 	}
 	DUMMYNET_UNLOCK();
-#endif
 	return (0);
 }
 
-#if 0
 /*
  * Helper function to remove from a heap queues which are linked to
  * a flow_set about to be deleted.
@@ -860,16 +862,14 @@ scan_remove_pipe(void *_o, uintptr_t p)
 {
 	return (0 == (void *)p) ? HEAP_SCAN_DEL | HEAP_SCAN_END : 0;
 }
-#endif
 
 /*
  * Fully delete a pipe or a queue, cleaning up associated info.
  */
 static int
-delete_pipe(struct dn_pipe *p)
+delete_pipe(struct dn_id *p, int l)
 {
     int err = 0;
-#if 0
     struct dn_pipe *pipe;
     struct new_fs *fs;
     
@@ -931,11 +931,9 @@ done:
     DUMMYNET_UNLOCK();
     if (pipe)
 	free_pipe(pipe);
-#endif
     return err;
 }
 
-#if 0
 /*
  * helper function used to copy data from kernel in DUMMYNET_GET
  */
@@ -1088,65 +1086,54 @@ dummynet_get(struct sockopt *sopt)
 static int
 ip_dn_ctl(struct sockopt *sopt)
 {
-    int error;
-    struct dn_pipe *p = NULL;
-    int l;
-
-    error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET);
-    if (error)
-	return (error);
-
-    /* Disallow sets in really-really secure mode. */
-    if (sopt->sopt_dir == SOPT_SET) {
-	error =  securelevel_ge(sopt->sopt_td->td_ucred, 3);
+	void *p = NULL;
+	int error, l;
+
+	error = priv_check(sopt->sopt_td, PRIV_NETINET_DUMMYNET);
 	if (error)
-	    return (error);
-    }
+		return (error);
 
-    switch (sopt->sopt_name) {
-    default :
-	printf("dummynet: -- unknown option %d", sopt->sopt_name);
-	error = EINVAL ;
-	break;
-
-    case IP_DUMMYNET_GET :
-	error = dummynet_get(sopt);
-	break ;
-
-    case IP_DUMMYNET_FLUSH :
-	dummynet_flush() ;
-	break ;
-
-    case IP_DUMMYNET_CONFIGURE :
-	l = (sopt->sopt_dir == SOPT_SET) ? sopt->sopt_valsize :
-		*(int *)(sopt->sopt_valsize);
-	if (l < 0 || l > 12000) {
-		printf("argument too large, %d\n", l);
-		break;
+	/* Disallow sets in really-really secure mode. */
+	if (sopt->sopt_dir == SOPT_SET) {
+		error =  securelevel_ge(sopt->sopt_td->td_ucred, 3);
+			if (error)
+		return (error);
 	}
-	printf("%s size %d\n", __FUNCTION__, l);
-	p = malloc(l, M_TEMP, M_WAITOK);
-	error = sooptcopyin(sopt, p, l, l);
-	if (error)
-	    break ;
 
-	error = do_config(p, l);
-	break;
-	error = config_pipe(p);
-	break ;
-
-    case IP_DUMMYNET_DEL :	/* remove a pipe or queue */
-	p = malloc(sizeof(struct dn_pipe), M_TEMP, M_WAITOK);
-	error = sooptcopyin(sopt, p, sizeof(struct dn_pipe), sizeof *p);
-	if (error)
-	    break ;
+	switch (sopt->sopt_name) {
+	default :
+		printf("dummynet: -- unknown option %d", sopt->sopt_name);
+		error = EINVAL;
+		break;
 
-	error = delete_pipe(p);
-	break ;
-    }
+	case IP_DUMMYNET_GET :
+		error = dummynet_get(sopt);
+		break;
+
+	case IP_DUMMYNET_FLUSH :
+		dummynet_flush();
+		break;
+
+	case IP_DUMMYNET_CONFIGURE :
+	case IP_DUMMYNET_DEL :	/* remove a pipe or queue */
+		l = (sopt->sopt_dir == SOPT_SET) ? sopt->sopt_valsize :
+			*(int *)(sopt->sopt_valsize);
+		if (l < 0 || l > 12000) {
+			printf("argument too large, %d\n", l);
+			break;
+		}
+		printf("%s size %d\n", __FUNCTION__, l);
+		p = malloc(l, M_TEMP, M_WAITOK);
+		error = sooptcopyin(sopt, p, l, l);
+		if (error)
+			break ;
+
+		error = do_config(p, l);
+		break;
+	}
 
-    if (p != NULL)
-	free(p, M_TEMP);
+	if (p != NULL)
+		free(p, M_TEMP);
 
     return error ;
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001082237.o08MbrEY012907>