svn commit: r202710 - in user/luigi/ipfw3-head: sbin/ipfw sys/netinet sys/netinet/ipfw

Luigi Rizzo luigi at FreeBSD.org
Wed Jan 20 18:28:24 UTC 2010


Author: luigi
Date: Wed Jan 20 18:28:24 2010
New Revision: 202710
URL: http://svn.freebsd.org/changeset/base/202710

Log:
  continue debugging in presence of sched and flow mask:
  In the kernel:
  - fix deletion of multiple scheduler instances
    by making the callback return DNHT_SCAN_DEL
  - remove some debugging messages;
  - copy more objects in dummynet_get()
  In userland:
  - fix parser so that flags are passed correctly when a mask is specified;
  - improve printing of 'ipfw pipe show' and 'ipfw sched show'
  - remove some debugging messages

Modified:
  user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
  user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c

Modified: user/luigi/ipfw3-head/sbin/ipfw/dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sbin/ipfw/dummynet.c	Wed Jan 20 18:22:56 2010	(r202709)
+++ user/luigi/ipfw3-head/sbin/ipfw/dummynet.c	Wed Jan 20 18:28:24 2010	(r202710)
@@ -137,115 +137,77 @@ sort_q(void *arg, const void *pa, const 
 		res = 1;
 	return (int)(rev ? res : -res);
 }
+#endif
 
 static void
-list_queues(struct dn_flow_set *fs, struct dn_flow_queue *q)
+print_mask(struct ipfw_flow_id *id)
+{
+	if (!IS_IP6_FLOW_ID(id)) {
+		printf("    "
+		    "mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
+		    id->proto,
+		    id->src_ip, id->src_port,
+		    id->dst_ip, id->dst_port);
+
+		printf("BKT Prot ___Source IP/port____ "
+		    "____Dest. IP/port____ "
+		    "Tot_pkt/bytes Pkt/Byte Drp\n");
+	} else {
+		char buf[255];
+		printf("\n        mask: proto: 0x%02x, flow_id: 0x%08x,  ",
+		    id->proto, id->flow_id6);
+		inet_ntop(AF_INET6, &(id->src_ip6), buf, sizeof(buf));
+		printf("%s/0x%04x -> ", buf, id->src_port);
+		inet_ntop(AF_INET6, &(id->dst_ip6), buf, sizeof(buf));
+		printf("%s/0x%04x\n", buf, id->dst_port);
+
+		printf("BKT ___Prot___ _flow-id_ "
+		    "______________Source IPv6/port_______________ "
+		    "_______________Dest. IPv6/port_______________ "
+		    "Tot_pkt/bytes Pkt/Byte Drp\n");
+	}
+}
+
+static void
+list_queue(struct new_inst *ni)
 {
-	int l;
-	int index_printed, indexes = 0;
 	char buff[255];
 	struct protoent *pe;
+	struct in_addr ina;
+	struct ipfw_flow_id *id = &ni->fid;
 
-	if (fs->rq_elements == 0)
-		return;
-
-	if (co.do_sort != 0)
-		qsort_r(q, fs->rq_elements, sizeof *q, NULL, sort_q);
-
-	/* Print IPv4 flows */
-	index_printed = 0;
-	for (l = 0; l < fs->rq_elements; l++) {
-		struct in_addr ina;
-
+	pe = getprotobynumber(id->proto);
 		/* XXX: Should check for IPv4 flows */
-		if (IS_IP6_FLOW_ID(&(q[l].id)))
-			continue;
-
-		if (!index_printed) {
-			index_printed = 1;
-			if (indexes > 0)	/* currently a no-op */
-				printf("\n");
-			indexes++;
-			printf("    "
-			    "mask: 0x%02x 0x%08x/0x%04x -> 0x%08x/0x%04x\n",
-			    fs->flow_mask.proto,
-			    fs->flow_mask.src_ip, fs->flow_mask.src_port,
-			    fs->flow_mask.dst_ip, fs->flow_mask.dst_port);
-
-			printf("BKT Prot ___Source IP/port____ "
-			    "____Dest. IP/port____ "
-			    "Tot_pkt/bytes Pkt/Byte Drp\n");
-		}
-
-		printf("%3d ", q[l].hash_slot);
-		pe = getprotobynumber(q[l].id.proto);
+	printf("%3d ", ni->oid.id);
+	if (!IS_IP6_FLOW_ID(id)) {
 		if (pe)
 			printf("%-4s ", pe->p_name);
 		else
-			printf("%4u ", q[l].id.proto);
-		ina.s_addr = htonl(q[l].id.src_ip);
+			printf("%4u ", id->proto);
+		ina.s_addr = htonl(id->src_ip);
 		printf("%15s/%-5d ",
-		    inet_ntoa(ina), q[l].id.src_port);
-		ina.s_addr = htonl(q[l].id.dst_ip);
+		    inet_ntoa(ina), id->src_port);
+		ina.s_addr = htonl(id->dst_ip);
 		printf("%15s/%-5d ",
-		    inet_ntoa(ina), q[l].id.dst_port);
-		printf("%4llu %8llu %2u %4u %3u\n",
-		    align_uint64(&q[l].tot_pkts),
-		    align_uint64(&q[l].tot_bytes),
-		    q[l].len, q[l].len_bytes, q[l].drops);
-		if (co.verbose)
-			printf("   S %20llu  F %20llu\n",
-			    align_uint64(&q[l].S), align_uint64(&q[l].F));
-	}
-
-	/* Print IPv6 flows */
-	index_printed = 0;
-	for (l = 0; l < fs->rq_elements; l++) {
-		if (!IS_IP6_FLOW_ID(&(q[l].id)))
-			continue;
-
-		if (!index_printed) {
-			index_printed = 1;
-			if (indexes > 0)
-				printf("\n");
-			indexes++;
-			printf("\n        mask: proto: 0x%02x, flow_id: 0x%08x,  ",
-			    fs->flow_mask.proto, fs->flow_mask.flow_id6);
-			inet_ntop(AF_INET6, &(fs->flow_mask.src_ip6),
-			    buff, sizeof(buff));
-			printf("%s/0x%04x -> ", buff, fs->flow_mask.src_port);
-			inet_ntop( AF_INET6, &(fs->flow_mask.dst_ip6),
-			    buff, sizeof(buff) );
-			printf("%s/0x%04x\n", buff, fs->flow_mask.dst_port);
-
-			printf("BKT ___Prot___ _flow-id_ "
-			    "______________Source IPv6/port_______________ "
-			    "_______________Dest. IPv6/port_______________ "
-			    "Tot_pkt/bytes Pkt/Byte Drp\n");
-		}
-		printf("%3d ", q[l].hash_slot);
-		pe = getprotobynumber(q[l].id.proto);
+		    inet_ntoa(ina), id->dst_port);
+	} else {
+		/* Print IPv6 flows */
 		if (pe != NULL)
 			printf("%9s ", pe->p_name);
 		else
-			printf("%9u ", q[l].id.proto);
-		printf("%7d  %39s/%-5d ", q[l].id.flow_id6,
-		    inet_ntop(AF_INET6, &(q[l].id.src_ip6), buff, sizeof(buff)),
-		    q[l].id.src_port);
+			printf("%9u ", id->proto);
+		printf("%7d  %39s/%-5d ", id->flow_id6,
+		    inet_ntop(AF_INET6, &(id->src_ip6), buff, sizeof(buff)),
+		    id->src_port);
 		printf(" %39s/%-5d ",
-		    inet_ntop(AF_INET6, &(q[l].id.dst_ip6), buff, sizeof(buff)),
-		    q[l].id.dst_port);
-		printf(" %4llu %8llu %2u %4u %3u\n",
-		    align_uint64(&q[l].tot_pkts),
-		    align_uint64(&q[l].tot_bytes),
-		    q[l].len, q[l].len_bytes, q[l].drops);
-		if (co.verbose)
-			printf("   S %20llu  F %20llu\n",
-			    align_uint64(&q[l].S),
-			    align_uint64(&q[l].F));
+		    inet_ntop(AF_INET6, &(id->dst_ip6), buff, sizeof(buff)),
+		    id->dst_port);
 	}
+	printf("%4llu %8llu %2u %4u %3u\n",
+	    align_uint64(&ni->tot_pkts),
+	    align_uint64(&ni->tot_bytes),
+	    ni->length, ni->len_bytes, ni->drops);
 }
-#endif
 
 static void
 print_flowset_parms(struct new_fs *fs, char *prefix)
@@ -256,7 +218,7 @@ print_flowset_parms(struct new_fs *fs, c
 	char red[90];	/* Display RED parameters */
 
 	l = fs->qsize;
-	if (fs->flags & DN_QSIZE_IS_BYTES) {
+	if (fs->flags & DN_QSIZE_BYTES) {
 		if (l >= 8192)
 			sprintf(qs, "%d KB", l / 1024);
 		else
@@ -335,11 +297,18 @@ list_pipes(struct dn_id *oid, struct dn_
 	    printf("respond to cmd %d buflen %d\n", oid->type, oid->id);
 	    break;
 	case DN_SCH: {
-	    struct new_sch *s = (struct new_sch *)s;
-	    sprintf(buf + strlen(buf), " type %s", s->type);
+	    struct new_sch *s = (struct new_sch *)oid;
+	    flush_buf(buf);
+	    printf(" type %s flags 0x%x %d buckets\n", s->type, s->flags, s->buckets);
+	    if (s->flags & DN_HAVE_MASK)
+		print_mask(&s->sched_mask);
 	    }
 	    break;
 
+	case DN_NI:
+	    list_queue((struct new_inst *)oid);
+	    break;
+
 	case DN_PIPE: {
 	    struct new_pipe *p = (struct new_pipe *)oid;
 	    double b = p->bandwidth;
@@ -350,7 +319,7 @@ list_pipes(struct dn_id *oid, struct dn_
 	    flush_buf(buf);
 	    /* data rate */
 	    if (b == 0)
-		sprintf(bwbuf, "unlimited");
+		sprintf(bwbuf, "unlimited     ");
 	    else if (b >= 1000000)
 		sprintf(bwbuf, "%7.3f Mbit/s", b/1000000);
 	    else if (b >= 1000)
@@ -359,8 +328,8 @@ list_pipes(struct dn_id *oid, struct dn_
 		sprintf(bwbuf, "%7.3f bit/s ", b);
 
 	    if (humanize_number(burst, sizeof(burst), p->burst,
-		    "Byte", HN_AUTOSCALE, 0) < 0 || co.verbose)
-		sprintf(burst, "%ju Byte\n", p->burst);
+		    "", HN_AUTOSCALE, 0) < 0 || co.verbose)
+		sprintf(burst, "%d", (int)p->burst);
 	    sprintf(buf, "%05d: %s %4d ms burst %s",
 		p->pipe_nr, bwbuf, p->delay, burst);
 	    }
@@ -783,6 +752,7 @@ ipfw_config_pipe(int ac, char **av)
 	struct new_cmd *cmd = NULL;
 	struct ipfw_flow_id *mask = NULL;
 	int lmax = sizeof(*cmd);	/* always present */
+	int _foo = 0, *flags = &_foo;
 
 	/* worst case: 2 schedulers, 1 profile, 1 pipe, 1 flowset */
 	lmax += 2*sizeof(*sch) + 2*sizeof(*p) + sizeof(*fs) + sizeof(*pf);
@@ -809,12 +779,13 @@ ipfw_config_pipe(int ac, char **av)
 		/* type should be wfq, but we set the default in the kernel. */
 		sch->oid.subtype = 0;
 		mask = &sch->sched_mask;
-		/* XXX the FIFO scheduler is created from the WFQ one */
+		flags = &sch->flags;
+		/* the FIFO scheduler is created in the kernel from the WFQ one */
 
 		/* the WFQ pipe */
 		p = o_next(&buf, sizeof(*p), DN_PIPE);
 		p->pipe_nr = i;
-		/* XXX the FIFO pipe is created from WFQ pipe */
+		/* the FIFO pipe is created in the kerne from WFQ pipe */
 
 		/*
 		 * FIFO flowsets N+i are automatically created for
@@ -830,12 +801,14 @@ ipfw_config_pipe(int ac, char **av)
 		fs = o_next(&buf, sizeof(*fs), DN_FS);
 		fs->fs_nr = i;
 		mask = &fs->flow_mask;
+		flags = &fs->flags;
 		break;
 
 	case 3: /* scheduler */
 		sch = o_next(&buf, sizeof(*sch), DN_SCH);
 		sch->sched_nr = i;
 		mask = &sch->sched_mask;
+		flags = &sch->flags;
 		/* room in case we have a FIFO scheduler */
 		fs = o_next(&buf, sizeof(*fs), DN_FS);
 		fs->fs_nr = i + DN_MAX_ID;
@@ -874,11 +847,11 @@ ipfw_config_pipe(int ac, char **av)
 			end = NULL;
 			fs->qsize = strtoul(av[0], &end, 0);
 			if (*end == 'K' || *end == 'k') {
-				fs->flags |= DN_QSIZE_IS_BYTES;
+				fs->flags |= DN_QSIZE_BYTES;
 				fs->qsize *= 1024;
 			} else if (*end == 'B' ||
 			    _substrcmp2(end, "by", "bytes") == 0) {
-				fs->flags |= DN_QSIZE_IS_BYTES;
+				fs->flags |= DN_QSIZE_BYTES;
 			}
 			ac--; av++;
 			break;
@@ -926,7 +899,7 @@ ipfw_config_pipe(int ac, char **av)
 				    n2mask(&mask->dst_ip6, 128);
 				    n2mask(&mask->src_ip6, 128);
 				    mask->flow_id6 = ~0;
-				    fs->flags |= DN_HAVE_FLOW_MASK;
+				    *flags |= DN_HAVE_MASK;
 				    goto end_mask;
 
 			    case TOK_DSTIP:
@@ -1002,7 +975,7 @@ ipfw_config_pipe(int ac, char **av)
 				    fs->flow_mask.proto = (uint8_t)a;
 			    }
 			    if (a != 0)
-				    fs->flags |= DN_HAVE_FLOW_MASK;
+				    *flags |= DN_HAVE_MASK;
 			    ac--; av++;
 			} /* end while, config masks */
 end_mask:
@@ -1134,8 +1107,8 @@ end_mask:
 			errx(EX_DATAERR, "sched must be > 0");
 #endif
 
-	    if (fs->flags & DN_QSIZE_IS_BYTES) {
-		size_t len;
+    if (fs->flags & DN_QSIZE_BYTES) {
+	size_t len;
 		long limit;
 
 		len = sizeof(limit);
@@ -1254,7 +1227,7 @@ dummynet_list(int ac, char *av[], int sh
 	oid.id = 0;
 	switch (co.do_pipe) {
 	case 1:
-		oid.subtype = DN_SCH;	/* list pipe */
+		oid.subtype = DN_PIPE;	/* list pipe */
 		break;
 	case 2:
 		oid.subtype = DN_FS;	/* list queue */
@@ -1265,7 +1238,7 @@ dummynet_list(int ac, char *av[], int sh
 	}
 	/* XXX we could use oid.id for the filter */
 	ret = do_cmd(-IP_DUMMYNET3, &oid, (uintptr_t)&l);
-	printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id);
+	// printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id);
 	if (ret != 0 || oid.id <= sizeof(oid))
 		return;
 	l = oid.id;
@@ -1274,7 +1247,7 @@ dummynet_list(int ac, char *av[], int sh
 		err(1, "no memory in %s", __FUNCTION__);
 	*x = oid;
 	ret = do_cmd(-IP_DUMMYNET3, x, (uintptr_t)&l);
-	printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id);
+	// printf("%s returns %d need %d\n", __FUNCTION__, ret, oid.id);
 	list_pipes(x, O_NEXT(x, l), NULL);
 	free(x);
 }

Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Wed Jan 20 18:22:56 2010	(r202709)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Wed Jan 20 18:28:24 2010	(r202710)
@@ -63,8 +63,9 @@ enum {
 	DN_QUEUE,
 	DN_DELAY_LINE,
 	DN_PROFILE,
-	DN_FS_EXT,
-	DN_QUEUE_EXT,
+	DN_NI,			/* new_inst */
+	//DN_FS_EXT,
+	//DN_QUEUE_EXT,
 	DN_TEXT,		/* subtype is the object */
 	DN_CMD_CONFIGURE,	/* objects follow */
 	DN_CMD_DELETE,		/* subtype + list of entries */
@@ -82,8 +83,13 @@ enum { /* subtype for schedulers, flowse
 
 enum {	/* user flags */
 	DN_HAVE_MASK	= 0x0001,
+	DN_NOERROR	= 0x0002,
 	DN_QSIZE_BYTES	= 0x0008,
-	DN_NOERROR	= 0x0010,
+	DN_IS_RED	= 0x0020,
+	DN_IS_GENTLE_RED= 0x0040,
+#if 0
+#define	DN_HAS_PROFILE		0x0020	/* the pipe has a delay profile. */
+#endif
 };
 
 typedef uint64_t dn_key;
@@ -253,11 +259,5 @@ flow using a number of heaps defined int
  *
  */
 
-#define DN_HAVE_FLOW_MASK	0x0001
-#define DN_IS_RED		0x0002
-#define DN_IS_GENTLE_RED	0x0004
-#define DN_QSIZE_IS_BYTES	0x0008	/* queue size is measured in bytes */
-#define DN_NOERROR		0x0010	/* do not report ENOBUFS on drops  */
-#define	DN_HAS_PROFILE		0x0020	/* the pipe has a delay profile. */
 
 #endif /* _IP_DUMMYNET_H */

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Wed Jan 20 18:22:56 2010	(r202709)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/dn_heap.c	Wed Jan 20 18:28:24 2010	(r202710)
@@ -447,7 +447,7 @@ dn_ht_scan(struct dn_ht *ht, int (*fn)(v
 			next = *(void **)((char *)cur + ht->ofs);
 			ret = fn(cur, arg);
 			if (ret & DNHT_SCAN_DEL) {
-				printf("element %p removed\n", cur);
+				// printf("element %p removed\n", cur);
 				found++;
 				ht->entries--;
 				*curp = next;

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Wed Jan 20 18:22:56 2010	(r202709)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Wed Jan 20 18:28:24 2010	(r202710)
@@ -117,6 +117,19 @@ void dn_free_pkts(struct mbuf *mnext)
         }
 }
 
+static int
+bound_var(int *v, int dflt, int lo, int hi, const char *msg)
+{
+	if (*v < lo) {
+		*v = dflt;
+		printf("force %s to %d\n", msg, *v);
+	} else if (*v > hi) {
+		*v = hi;
+		printf("clamp %s to %d\n", msg, *v);
+	}
+	return *v;
+}
+
 /*---- flow_id mask, hash and compare functions ---*/
 static struct ipfw_flow_id *
 flow_id_mask(struct ipfw_flow_id *mask, struct ipfw_flow_id *id)
@@ -264,7 +277,7 @@ dn_delete_queue(struct new_queue *q, int
 {
 	struct new_fsk *fs = q->fs;
 
-	printf("    +++ %s fs %p si %p\n", __FUNCTION__, fs, q->_si);
+	// printf("%s fs %p si %p\n", __FUNCTION__, fs, q->_si);
 	/* notify the parent scheduler that the queue is going away */
 	if (fs && fs->sched->fp->free_queue)
 		fs->sched->fp->free_queue(q);
@@ -272,6 +285,7 @@ dn_delete_queue(struct new_queue *q, int
 	if (flags & DN_DELETE) {
 		if (q->mq.head)
 			dn_free_pkts(q->mq.head);
+		bzero(q, sizeof(*q));	// safety
 		free(q, M_DUMMYNET);
 		dn_cfg.queue_count--;
 	}
@@ -408,8 +422,10 @@ si_new(uintptr_t key, int flags, void *a
 	return si;
 
 error:
-	if (si)
+	if (si) {
+		bzero(si, sizeof(*si)); // safety
 		free(si, M_DUMMYNET);
+	}
         return NULL;
 }
 
@@ -436,7 +452,7 @@ si_destroy(void *_si, void *arg)
 	bzero(si, sizeof(*si));	/* safety */
 	free(si, M_DUMMYNET);
 	dn_cfg.si_count--;
-	return 0;
+	return DNHT_SCAN_DEL;
 }
 
 /*
@@ -590,7 +606,7 @@ delete_fs(int i, int locked)
 	if (!locked)
 		DN_BH_WLOCK();
 	fs = dn_ht_find(dn_cfg.fshash, i, DNHT_REMOVE, NULL);
-	printf("%s fs %d found %p\n", __FUNCTION__, i, fs);
+	// printf("%s fs %d found %p\n", __FUNCTION__, i, fs);
 	if (fs) {
 		fsk_detach(fs, DN_DETACH | DN_DELETE_FS);
 		err = 0;
@@ -686,9 +702,8 @@ schk_delete_cb(void *obj, void *arg)
 	s->siht = NULL;
 	if (s->fp->destroy)
 		s->fp->destroy(s);
-	bzero(s, sizeof(*s));
+	bzero(s, sizeof(*s));	// safety
 	free(obj, M_DUMMYNET);
-	// printf("<<< %s done sched %d destroyed\n", __FUNCTION__, i);
 	dn_cfg.schk_count--;
 	return DNHT_SCAN_DEL;
 }
@@ -704,12 +719,12 @@ delete_schk(int i)
 	struct new_schk *s;
 
 	s = dn_ht_find(dn_cfg.schedhash, i, DNHT_REMOVE, NULL);
-	printf("%s sched %d %p\n", __FUNCTION__, i, s);
+	// printf("%s sched %d %p\n", __FUNCTION__, i, s);
 	if (!s)
 		return EINVAL;
 	/* detach flowsets, delete traffic */
+	delete_fs(i + DN_MAX_ID, 1);	/* first remove internal pipe */
 	schk_delete_cb(s, (void*)(uintptr_t)DN_DELETE);
-	delete_fs(i + DN_MAX_ID, 1);	/* remove internal pipe */
 	return 0;
 }
 
@@ -717,17 +732,17 @@ delete_schk(int i)
 /*--- end of schk hashtable support ---*/
 
 static int
-copy_obj(char **start, char *end, void *_o)
+copy_obj(char **start, char *end, void *_o, const char *msg, int i)
 {
 	struct dn_id *o = _o;
 	int have = end - *start;
 
 	if (have < o->len || o->len == 0 || o->type == 0) {
-		printf("XXX %s ERROR type %d have %d need %d\n",
-			__FUNCTION__, o->type, have, o->len);
+		printf("XXX %s ERROR type %d %s %d have %d need %d\n",
+			__FUNCTION__, o->type, msg, i, have, o->len);
 		return 1;
 	}
-	printf("%s type %d len %d\n", __FUNCTION__, o->type, o->len);
+	// printf("%s type %d %s %d len %d\n", __FUNCTION__, o->type, msg, i, o->len);
 	bcopy(_o, *start, o->len);
 	*start += o->len;
 	return 0;
@@ -748,7 +763,7 @@ copy_flowset(struct copy_args *a, struct
 	struct new_fs *ufs = (struct new_fs *)(*a->start);
 	if (!fs)
 		return 0;
-	if (copy_obj(a->start, a->end, &fs->fs))
+	if (copy_obj(a->start, a->end, &fs->fs, "flowset", fs->fs.fs_nr))
 		return DNHT_SCAN_END;
 	ufs->oid.id = 0; /* XXX number of queues ? */
 	if (flags) {	/* copy queues */
@@ -757,41 +772,63 @@ copy_flowset(struct copy_args *a, struct
 }
 
 static int
+copy_si_cb(void *obj, void *arg)
+{
+	struct new_sch_inst *si = obj;
+	struct copy_args *a = arg;
+	struct new_inst *ni = (struct new_inst *)(*a->start);
+	if (copy_obj(a->start, a->end, &si->ni, "inst", si->sched->sch.sched_nr))
+		return DNHT_SCAN_END;
+	ni->oid.type = DN_NI;
+	return 0;
+}
+
+static int
+copy_si(struct copy_args *a, struct new_schk *s, int flags)
+{
+	if (s->sch.flags & DN_HAVE_MASK) {
+		dn_ht_scan(s->siht, copy_si_cb, a);
+	} else {
+		if (s->siht)
+			copy_si_cb(s->siht, a);
+	}
+	return 0;
+}
+
+static int
 copy_data_helper(void *_o, void *_arg)
 {
 	struct copy_args *a = _arg;
 
-	if (a->type == DN_SCH) {	/* scanning schedulers */
-		struct new_schk *s = _o;
+	if (a->type == DN_PIPE ||	/* pipe show */
+	    a->type == DN_SCH) {	/* sched show */
+		struct new_schk *s = _o; /* we get only schedulers */
+		if (a->type == DN_SCH && s->sch.sched_nr >= DN_MAX_ID)
+			return 0;	/* not valid scheduler */
+		if (a->type == DN_PIPE && s->sch.sched_nr <= DN_MAX_ID)
+			return 0;	/* not valid pipe */
 		if (a->flags & DN_C_PIPE) {
-			printf("copy pipe %d\n", s->sch.sched_nr);
-			if (copy_obj(a->start, a->end, &s->pipe))
+			if (copy_obj(a->start, a->end, &s->pipe, "pipe", s->sch.sched_nr))
 				return DNHT_SCAN_END;
-			printf("copy int-fs for pipe %d %p\n",
-				s->sch.sched_nr, s->fs);
 			if (copy_flowset(a, s->fs, 0))
 				return DNHT_SCAN_END;
-			printf("copy pipe %d done\n", s->sch.sched_nr);
 		}
 		if (a->flags & DN_C_SCH) {
-			printf("copy sched %d\n", s->sch.sched_nr);
-			if (copy_obj(a->start, a->end, &s->sch))
+			if (copy_obj(a->start, a->end, &s->sch, "sched", s->sch.sched_nr))
 				return DNHT_SCAN_END;
-			printf("copy sched %d done\n", s->sch.sched_nr);
 		}
 		if (a->flags & DN_C_SCH_INST) {
-			printf("XXX todo: scan sched instances\n");
+			copy_si(a, s, 0);
 		}
 	}
-	if (a->type == DN_FS) {	/* scanning flowsets */
+	if (a->type == DN_FS) {	/* queue show, skip internal flowsets */
 		struct new_fsk *fs = _o;
+		if (fs->fs.fs_nr >= DN_MAX_ID)
+			return 0;
 		/* if extra is set, only copy unlinked ones */
 		if (a->extra == 0 || fs->sched == NULL) {
-			printf("copy fs %d to sched %d\n", fs->fs.fs_nr,
-				fs->sched ? fs->sched->sch.sched_nr : -1);
 			if (copy_flowset(a, fs, 0))
 				return DNHT_SCAN_END;
-			printf("copy fs %d done\n",fs->fs.fs_nr);
 		}
 	}
 	return 0;
@@ -927,7 +964,7 @@ config_fs(struct new_fs *nfs, struct dn_
 		return NULL;
 	// printf("%s flowset %d\n", __FUNCTION__, i);
 	/* XXX other sanity checks */
-        if (nfs->flags & DN_QSIZE_IS_BYTES) {
+        if (nfs->flags & DN_QSIZE_BYTES) {
                 if (nfs->qsize > dn_cfg.pipe_byte_limit)
                         nfs->qsize = dn_cfg.pipe_byte_limit;
         } else {
@@ -938,15 +975,8 @@ config_fs(struct new_fs *nfs, struct dn_
         }
 	if (nfs->flags & DN_HAVE_MASK) {
 		/* make sure we have some buckets */
-		if (nfs->buckets < 1) {
-			nfs->buckets = dn_cfg.hash_size;
-			printf("%s force buckets to %d\n",
-				__FUNCTION__, nfs->buckets);
- 		} else if (nfs->buckets > dn_cfg.max_hash_size) {
-			nfs->buckets = dn_cfg.max_hash_size;
-			printf("%s clamp buckets to %d\n",
-				__FUNCTION__, nfs->buckets);
-		}
+		bound_var(&nfs->buckets, dn_cfg.hash_size,
+			1, dn_cfg.max_hash_size, "flowset buckets");
 	} else {
 		nfs->buckets = 1;	/* we only need 1 */
 	}
@@ -1018,6 +1048,10 @@ config_sched(struct new_sch *_nsch, stru
 	i = a.sch->sched_nr;
 	if (i <= 0 || i >= DN_MAX_ID)
 		return EINVAL;
+	/* make sure we have some buckets */
+	if (a.sch->flags & DN_HAVE_MASK)
+		bound_var(&a.sch->buckets, dn_cfg.hash_size,
+			1, dn_cfg.max_hash_size, "sched buckets");
 	/* XXX other sanity checks */
 	bzero(&p, sizeof(p));
 	DN_BH_WLOCK();
@@ -1288,9 +1322,11 @@ compute_space(struct dn_id *cmd, int *to
 	switch (cmd->subtype) {
 	default:
 		return -1;
-	case DN_SCH:	/* pipe show */
-		x = DN_C_SCH | DN_C_PIPE | DN_C_FS |
-			DN_C_SCH_INST | DN_C_QUEUE;
+	case DN_PIPE:	/* pipe show */
+		x = DN_C_PIPE | DN_C_FS | DN_SCH | DN_C_SCH_INST;
+		break;
+	case DN_SCH:	/* sched show */
+		x = DN_C_SCH | DN_C_PIPE | DN_C_SCH_INST;
 		break;
 	case DN_FS:	/* queue show */
 		x = DN_C_FS | DN_C_QUEUE;
@@ -1371,18 +1407,11 @@ dummynet_get(struct sockopt *sopt)
 		a.start = &buf;
 		a.end = end;
 		a.flags = to_copy;
-		a.extra = 0;
-		printf("copy schedulers (%d : %d)\n",
-			dn_cfg.schk_count,
-			dn_ht_entries(dn_cfg.schedhash));
-		a.type = DN_SCH;
-		dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a);
-		printf("copy unlinked flowsets (%d : %d)\n",
-			dn_cfg.fsk_count,
-			dn_ht_entries(dn_cfg.fshash));
-		a.type = DN_FS;
-		a.extra = 1;
-		dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a);
+		a.type = cmd.subtype;
+		if (a.type == DN_FS)
+			dn_ht_scan(dn_cfg.fshash, copy_data_helper, &a);
+		else
+			dn_ht_scan(dn_cfg.schedhash, copy_data_helper, &a);
 	}
 	DN_BH_WUNLOCK();
 	error = sooptcopyout(sopt, start, buf - start);
@@ -1435,8 +1464,7 @@ ip_dn_ctl(struct sockopt *sopt)
 			printf("argument len %d invalid\n", l);
 			break;
 		}
-		printf("%s size %d\n", __FUNCTION__, l);
-		p = malloc(l, M_TEMP, M_WAITOK);
+		p = malloc(l, M_TEMP, M_WAITOK); // XXX can it fail ?
 		error = sooptcopyin(sopt, p, l, l);
 		if (error)
 			break ;


More information about the svn-src-user mailing list