svn commit: r185083 - in user/lstewart/dummynet_7.x: sbin/ipfw sys sys/netinet

Lawrence Stewart lstewart at FreeBSD.org
Tue Nov 18 19:57:12 PST 2008


Author: lstewart
Date: Wed Nov 19 03:57:11 2008
New Revision: 185083
URL: http://svn.freebsd.org/changeset/base/185083

Log:
  Merge the dummynet and ipfw man page bits of dummynet_8.x r185051. Couple of
  minor tweaks required to make it compile (namely kthread_* kpi differences).

Modified:
  user/lstewart/dummynet_7.x/sbin/ipfw/   (props changed)
  user/lstewart/dummynet_7.x/sbin/ipfw/ipfw.8
  user/lstewart/dummynet_7.x/sys/   (props changed)
  user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.c
  user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.h

Modified: user/lstewart/dummynet_7.x/sbin/ipfw/ipfw.8
==============================================================================
--- user/lstewart/dummynet_7.x/sbin/ipfw/ipfw.8	Wed Nov 19 03:24:35 2008	(r185082)
+++ user/lstewart/dummynet_7.x/sbin/ipfw/ipfw.8	Wed Nov 19 03:57:11 2008	(r185083)
@@ -1967,12 +1967,13 @@ Packet loss set.
 Argument
 .Ar packet-loss-set
 is a comma-delimited string of the form 10,30-31,1000 identifying the specific
-packets entering a queue/pipe to drop. In the given example, the 10th, 30th,
-31st and 1000th packet to enter the pipe/queue would be dropped. Clearing the
-counters on a pipe will cause the
+packets entering a queue/pipe to drop.
+In the given example, the 10th, 30th, 31st and 1000th packet to enter the
+pipe/queue would be dropped.
+Clearing the counters on a pipe will cause the
 .Ar packet-loss-set
-to be evaluated again from scratch. Use of this option mutually excludes use of
-the
+to be evaluated again from scratch.
+Use of this option mutually excludes use of the
 .Nm plr
 option.
 .Pp

Modified: user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.c
==============================================================================
--- user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.c	Wed Nov 19 03:24:35 2008	(r185082)
+++ user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.c	Wed Nov 19 03:57:11 2008	(r185083)
@@ -64,28 +64,39 @@ __FBSDID("$FreeBSD$");
 #include <sys/kernel.h>
 #include <sys/module.h>
 #include <sys/priv.h>
+#include <sys/kthread.h>
 #include <sys/proc.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/time.h>
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
+#include <sys/alq.h>
+#include <sys/sbuf.h>
+#include <sys/hash.h>
+#include <sys/unistd.h>
+
 #include <net/if.h>
 #include <net/netisr.h>
 #include <net/route.h>
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
+#include <netinet/in_pcb.h>
 #include <netinet/ip.h>
 #include <netinet/ip_fw.h>
 #include <netinet/ip_dummynet.h>
 #include <netinet/ip_var.h>
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
 
 #include <netinet/if_ether.h> /* for struct arpcom */
 
 #include <netinet/ip6.h>       /* for ip6_input, ip6_output prototypes */
 #include <netinet6/ip6_var.h>
 
+#include <machine/in_cksum.h>
+
 /*
  * We keep a private variable for the simulation time, but we could
  * probably use an existing one ("softticks" in sys/kern/kern_timeout.c)
@@ -154,6 +165,74 @@ static struct callout dn_timeout;
 
 extern	void (*bridge_dn_p)(struct mbuf *, struct ifnet *);
 
+#define DN_LOG(fs, p, q, m, dropped, dir) \
+	if (dn_log_enable) \
+		dn_log((fs), (p), (q), (m), (dropped), (dir));
+
+#define CAST_PTR_INT(X) (*((int*)(X)))
+
+struct log_node {
+	/* log msg creation timestamp */
+	struct timeval	tval;
+	/*
+	 * direction of packet after dummynet finishes processing it
+	 * (defined in ip_dummynet.h DN_TO_IP_OUT, DN_TO_IP_IN, ...)
+	 */
+	int	direction;
+	/*
+	 * pkt dropped yes/no + reason if dropped (see DN_DROP_X defines in
+	 * ip_dummynet.h)
+	 */
+	uint32_t	dropped;
+	/* hash of the pkt which triggered the log msg */
+	uint32_t	hash;
+	/* IP version log_node relates to; either INP_IPV4 or INP_IPV6 */
+	uint8_t		ipver;
+	/* flow set number */
+	int	fs_num;
+	/* flags set on the flow set */
+	uint16_t	fs_flags;
+	/* pipe number */
+	int	p_num;
+	/* current pipe occupancy */
+	int	p_len;
+	/*
+	 * max queue len in either pkts or bytes (depending on whether
+	 * DN_QSIZE_IS_BYTES is set in fs_flags)
+	 */
+	int	q_max_len;
+	/* current queue occupancy in pkts */
+	int	q_len_pkts;
+	/* current queue occupancy in bytes */
+	int	q_len_bytes;
+
+	STAILQ_ENTRY(log_node) nodes;
+};
+
+/*
+ * in_pcb.h defines INP_IPV4 as 0x1 and INP_IPV6 as 0x2,
+ * which we use as an index into this array
+ */
+static char	ipver[3] = {'\0', '4', '6'};
+static int	dn_sysctl_log_enable_handler(SYSCTL_HANDLER_ARGS);
+static int	dn_sysctl_logfile_name_handler(SYSCTL_HANDLER_ARGS);
+static u_int	dn_log_enable = 0;
+static char	dn_logfile[PATH_MAX] = "/var/log/dummynet.log\0";
+STAILQ_HEAD(loghead, log_node) log_queue = STAILQ_HEAD_INITIALIZER(log_queue);
+static struct	mtx dn_log_queue_mtx;
+static int	wait_for_log;
+static struct alq *dn_alq = NULL;
+static volatile uint32_t dn_exit_log_manager_thread = 0;
+static struct thread *dn_log_manager_thr = NULL;
+static struct proc *dn_log_manager_proc = NULL;
+
+#define DN_LOG_FILE_MODE 0644
+#define DN_ALQ_BUFLEN 200000
+#define DN_MAX_LOG_MSG_LEN 60
+
+#define DN_LOG_DISABLE	0
+#define DN_LOG_ENABLE	1
+
 #ifdef SYSCTL_NODE
 SYSCTL_NODE(_net_inet_ip, OID_AUTO, dummynet, CTLFLAG_RW, 0, "Dummynet");
 SYSCTL_INT(_net_inet_ip_dummynet, OID_AUTO, hash_size,
@@ -206,6 +285,12 @@ SYSCTL_LONG(_net_inet_ip_dummynet, OID_A
     CTLFLAG_RW, &pipe_slot_limit, 0, "Upper limit in slots for pipe queue.");
 SYSCTL_LONG(_net_inet_ip_dummynet, OID_AUTO, pipe_byte_limit,
     CTLFLAG_RW, &pipe_byte_limit, 0, "Upper limit in bytes for pipe queue.");
+SYSCTL_OID(_net_inet_ip_dummynet, OID_AUTO, log_enable, CTLTYPE_UINT|CTLFLAG_RW,
+    &dn_log_enable, 0, &dn_sysctl_log_enable_handler, "IU",
+    "switch dummynet data logging on/off");
+SYSCTL_PROC(_net_inet_ip_dummynet, OID_AUTO, logfile,
+    CTLTYPE_STRING|CTLFLAG_RW, &dn_logfile, sizeof(dn_logfile),
+    &dn_sysctl_logfile_name_handler, "A", "file to save dummynet log data to");
 #endif
 
 #ifdef DUMMYNET_DEBUG
@@ -451,6 +536,363 @@ heap_free(struct dn_heap *h)
  * --- end of heap management functions ---
  */
 
+static __inline void
+dn_process_log_node(struct log_node * log_node)
+{
+	char dn_log_msg[DN_MAX_LOG_MSG_LEN];
+
+	/* construct our log message */
+	snprintf( dn_log_msg,
+		DN_MAX_LOG_MSG_LEN,
+		"%d,0x%08x,%u.%06u,%u,%u,%d,0x%04x,%d,%d,%d,%d,%d\n",
+		log_node->direction,
+		log_node->hash,
+		(unsigned int)log_node->tval.tv_sec,
+		(unsigned int)log_node->tval.tv_usec,
+		ipver[log_node->ipver],
+		log_node->dropped,
+		log_node->fs_num,
+		log_node->fs_flags,
+		log_node->p_num,
+		log_node->p_len,
+		log_node->q_max_len,
+		log_node->q_len_pkts,
+		log_node->q_len_bytes
+	);
+
+	alq_writen(dn_alq, dn_log_msg, strlen(dn_log_msg), ALQ_WAITOK);
+}
+
+static void
+dn_log_manager_thread(void *arg)
+{
+	struct log_node *log_node, *log_node_temp;
+
+	/* loop until thread is signalled to exit */
+	while (!dn_exit_log_manager_thread) {
+		/*
+		 * sleep until we are signalled to wake because thread has
+		 * been told to exit or until 1 tick has passed
+		 */
+		tsleep(&wait_for_log, PWAIT, "logwait", 1);
+
+		/* Process logs until the queue is empty */
+		do {
+			log_node = NULL;
+
+			/* gain exclusive access to the queue */
+			mtx_lock(&dn_log_queue_mtx);
+
+			/* get the element at the head of the list */
+			if ((log_node = STAILQ_FIRST(&log_queue)) != NULL) {
+				/*
+				 * list wasn't empty, so let's remove the first
+				 * element from the list.
+				 * Note that STAILQ_REMOVE_HEAD doesn't delete
+				 * the log_node struct itself. It just
+				 * disentangles it from the list structure.
+				 * We have a copy of the node's ptr stored
+				 * in log_node.
+				 */
+				STAILQ_REMOVE_HEAD(&log_queue, nodes);
+			}
+			/*
+			 * We've finished making changes to the list. Unlock it
+			 * so the pfil hooks can continue queuing pkt_nodes
+			 */
+			mtx_unlock(&dn_log_queue_mtx);
+
+			/* if we successfully get a log_node from the list */
+			if (log_node != NULL) {
+				dn_process_log_node(log_node);
+				/*
+				 * free the memory that was
+				 * malloc'd in dn_log()
+				 */
+				free(log_node, M_DUMMYNET);
+			}
+
+		} while (log_node != NULL);
+	}
+
+	/* Flush all remaining log_nodes to the log file */
+
+	/* Lock the mutex so we gain exclusive access to the queue */
+	mtx_lock(&dn_log_queue_mtx);
+
+	STAILQ_FOREACH_SAFE(log_node, &log_queue, nodes, log_node_temp) {
+		dn_process_log_node(log_node);
+		STAILQ_REMOVE_HEAD(&log_queue, nodes);
+		free(log_node, M_DUMMYNET);
+	}
+
+	/* Reinit the list to mark it as empty and virgin */
+	STAILQ_INIT(&log_queue);
+
+	/* We've finished making changes to the list. Safe to unlock it. */
+	mtx_unlock(&dn_log_queue_mtx);
+
+	/* kthread_exit calls wakeup on our thread's struct pointer */
+	kthread_exit(0);
+}
+
+static int
+dn_sysctl_logfile_name_handler(SYSCTL_HANDLER_ARGS)
+{
+	struct alq *new_alq;
+
+	if (!req->newptr)
+		goto skip;
+
+	/* if old filename and new filename are different */
+	if (strncmp(dn_logfile, (char *)req->newptr, PATH_MAX)) {
+
+		int error = alq_open(	&new_alq,
+					req->newptr,
+					curthread->td_ucred,
+					DN_LOG_FILE_MODE,
+					DN_ALQ_BUFLEN,
+					0
+		);
+
+		/* bail if unable to create new alq */
+		if (error)
+			return 1;
+
+		/*
+		 * If disabled, dn_alq == NULL so we simply close
+		 * the alq as we've proved it can be opened.
+		 * If enabled, close the existing alq and switch the old for the new
+		 */
+		if (dn_alq == NULL)
+			alq_close(new_alq);
+		else {
+			alq_close(dn_alq);
+			dn_alq = new_alq;
+		}
+	}
+
+skip:
+	return sysctl_handle_string(oidp, arg1, arg2, req);
+}
+
+static int
+dn_manage_logging(uint8_t action)
+{
+	int ret, error = 0;
+	struct timeval tval;
+	struct sbuf *s = NULL;
+
+	/* init an autosizing sbuf that initially holds 200 chars */
+	if ((s = sbuf_new(NULL, NULL, 200, SBUF_AUTOEXTEND)) == NULL)
+		return -1;
+
+	if (action == DN_LOG_ENABLE) {
+
+		/* create our alq */
+		alq_open(	&dn_alq,
+				dn_logfile,
+				curthread->td_ucred,
+				DN_LOG_FILE_MODE,
+				DN_ALQ_BUFLEN,
+				0
+		);
+
+		STAILQ_INIT(&log_queue);
+
+		dn_exit_log_manager_thread = 0;
+
+		ret = kthread_create(   &dn_log_manager_thread,
+					NULL,
+					&dn_log_manager_proc,
+					RFNOWAIT,
+					0,
+					"dn_log_manager_thr"
+		);
+		dn_log_manager_thr =
+			FIRST_THREAD_IN_PROC(dn_log_manager_proc);
+
+		microtime(&tval);
+
+		sbuf_printf(s,
+			"enable_time_secs=%ld\tenable_time_usecs=%06ld\thz=%d\tsysname=%s\tsysver=%u\n",
+			tval.tv_sec,
+			tval.tv_usec,
+			hz,
+			"FreeBSD",
+			__FreeBSD_version
+		);
+
+		sbuf_finish(s);
+		alq_writen(dn_alq, sbuf_data(s), sbuf_len(s), ALQ_WAITOK);
+	}
+	else if (action == DN_LOG_DISABLE && dn_log_manager_thr != NULL) {
+
+		/* tell the log manager thread that it should exit now */
+		dn_exit_log_manager_thread = 1;
+
+		/*
+		 * wake the pkt_manager thread so it realises that
+		 * dn_exit_log_manager_thread = 1 and exits gracefully
+		 */
+		wakeup(&wait_for_log);
+
+		/* wait for the pkt_manager thread to exit */
+		tsleep(dn_log_manager_thr, PWAIT, "thrwait", 0);
+
+		dn_log_manager_thr = NULL;
+
+		microtime(&tval);
+
+		sbuf_printf(s,
+			"disable_time_secs=%ld\tdisable_time_usecs=%06ld",
+			tval.tv_sec,
+			tval.tv_usec
+		);
+
+		sbuf_printf(s, "\n");
+		sbuf_finish(s);
+		alq_writen(dn_alq, sbuf_data(s), sbuf_len(s), ALQ_WAITOK);
+		alq_close(dn_alq);
+		dn_alq = NULL;
+	}
+
+	sbuf_delete(s);
+
+	/*
+	 * XXX: Should be using ret to check if any functions fail
+	 * and set error appropriately
+	 */
+	return error;
+}
+
+static int
+dn_sysctl_log_enable_handler(SYSCTL_HANDLER_ARGS)
+{
+	if (!req->newptr)
+		goto skip;
+	
+	/* if the value passed in isn't DISABLE or ENABLE, return an error */
+	if (CAST_PTR_INT(req->newptr) != DN_LOG_DISABLE &&
+		CAST_PTR_INT(req->newptr) != DN_LOG_ENABLE)
+		return 1;
+	
+	/* if we are changing state (DISABLE to ENABLE or vice versa) */
+	if (CAST_PTR_INT(req->newptr) != dn_log_enable )
+		if (dn_manage_logging(CAST_PTR_INT(req->newptr))) {
+			dn_manage_logging(DN_LOG_DISABLE);
+			return 1;
+		}
+
+skip:
+	return sysctl_handle_int(oidp, arg1, arg2, req);
+}
+
+static uint32_t
+hash_pkt(struct mbuf *m, uint32_t offset)
+{
+	register uint32_t hash = 0;
+
+	while ((m != NULL) && (offset > m->m_len)) {
+		/*
+		 * the IP packet payload does not start in this mbuf
+		 * need to figure out which mbuf it starts in and what offset
+		 * into the mbuf's data region the payload starts at
+		 */
+		offset -= m->m_len;
+		m = m->m_next;
+	}
+
+	while (m != NULL) {
+		/* ensure there is data in the mbuf */
+		if ((m->m_len - offset) > 0) {
+			hash = hash32_buf(	m->m_data + offset,
+						m->m_len - offset,
+						hash
+			);
+                }
+
+		m = m->m_next;
+		offset = 0;
+        }
+
+	return hash;
+}
+
+static void
+dn_log(	struct dn_flow_set *fs,
+	struct dn_pipe *p,
+	struct dn_flow_queue *q,
+	struct mbuf *pkt,
+	u_int dropped,
+	int dir)
+{
+	struct log_node *log_node;
+
+	DUMMYNET_LOCK_ASSERT();
+
+	/* M_NOWAIT flag required here */
+	log_node = malloc(sizeof(struct log_node), M_DUMMYNET, M_NOWAIT);
+
+	if (log_node == NULL)
+		return;
+
+	/* set log_node struct members */
+	microtime(&(log_node->tval));
+	log_node->direction = dir;
+	log_node->dropped = dropped;
+	log_node->ipver = INP_IPV4;
+	log_node->fs_num = (dropped == DN_DROP_NOFS) ?
+				-1 : fs->fs_nr;
+	log_node->fs_flags = (dropped == DN_DROP_NOFS) ?
+				0 : fs->flags_fs;
+	log_node->q_max_len = (dropped == DN_DROP_NOFS) ?
+				-1 : fs->qsize;
+	log_node->p_num = (dropped == DN_DROP_NOFS ||
+				dropped == DN_DROP_NOP4Q) ?
+					-1 : p->pipe_nr;
+	log_node->p_len = (dropped == DN_DROP_NOFS ||
+				dropped == DN_DROP_NOP4Q) ?
+					-1 : p->len;
+	log_node->q_len_pkts = (dropped == DN_DROP_NOFS ||
+					dropped == DN_DROP_NOQ) ?
+						-1 : q->len;
+	log_node->q_len_bytes = (dropped == DN_DROP_NOFS ||
+					dropped == DN_DROP_NOQ) ?
+						-1 : q->len_bytes;
+
+	/*
+	 * calc a hash of the pkt which triggered this log message
+	 * hash is calculated over the IP payload (not IP header) so as to
+	 * be invariant to changes in the IP header
+	 * XXX: Handle IPv6
+	 */
+	struct ip *ip = mtod(pkt, struct ip *);
+	uint32_t ip_hl = (ip->ip_hl << 2);
+
+	if (pkt->m_pkthdr.csum_flags & (CSUM_TCP | CSUM_UDP)) {
+		/*
+		 * This is a TCP or UDP packet without its checksum field
+		 * Manually calculate the checksum so that we generate a correct pkt hash
+		 */
+		if (pkt->m_pkthdr.csum_flags & CSUM_TCP) {
+			struct tcphdr *th = (struct tcphdr *)((caddr_t)ip + ip_hl);
+			th->th_sum  = in_cksum_skip(pkt, ip->ip_len, ip_hl);
+			pkt->m_pkthdr.csum_flags &= ~CSUM_TCP;
+		} else {
+			struct udphdr *uh = (struct udphdr *)((caddr_t)ip + ip_hl);
+			uh->uh_sum  = in_cksum_skip(pkt, ip->ip_len, ip_hl);
+			pkt->m_pkthdr.csum_flags &= ~CSUM_UDP;
+		}
+	}
+
+	log_node->hash = hash_pkt(pkt, ip_hl);
+
+	mtx_lock(&dn_log_queue_mtx);
+	STAILQ_INSERT_TAIL(&log_queue, log_node, nodes);
+	mtx_unlock(&dn_log_queue_mtx);
+}
+
 /*
  * Return the mbuf tag holding the dummynet state.  As an optimization
  * this is assumed to be the first tag on the list.  If this turns out
@@ -504,6 +946,7 @@ transmit_event(struct dn_pipe *pipe, str
 		else
 			*head = m;
 		*tail = m;
+		pipe->len--;
 	}
 	if (*tail != NULL)
 		(*tail)->m_nextpkt = NULL;
@@ -550,6 +993,7 @@ move_pkt(struct mbuf *pkt, struct dn_flo
 	p->tail->m_nextpkt = pkt;
     p->tail = pkt;
     p->tail->m_nextpkt = NULL;
+    p->len++;
 }
 
 /*
@@ -1295,34 +1739,43 @@ dummynet_io(struct mbuf **m0, int dir, s
 	} else
 		fs = locate_flowset(fwa->cookie);
 
-	if (fs == NULL)
+	if (fs == NULL) {
+		DN_LOG(NULL, NULL, NULL, m, DN_DROP_NOFS, dir);
 		goto dropit;	/* This queue/pipe does not exist! */
+	}
 	pipe = fs->pipe;
 	if (pipe == NULL) {	/* Must be a queue, try find a matching pipe. */
 		pipe = locate_pipe(fs->parent_nr);
 		if (pipe != NULL)
 			fs->pipe = pipe;
 		else {
+			DN_LOG(fs, NULL, NULL, m, DN_DROP_NOP4Q, dir);
 			printf("dummynet: no pipe %d for queue %d, drop pkt\n",
 			    fs->parent_nr, fs->fs_nr);
 			goto dropit;
 		}
 	}
 	q = find_queue(fs, &(fwa->f_id));
-	if (q == NULL)
+	if (q == NULL) {
+		DN_LOG(fs, pipe, NULL, m, DN_DROP_NOQ, dir);
 		goto dropit;		/* Cannot allocate queue. */
+	}
 
 	/* Update statistics, then check reasons to drop pkt. */
 	q->tot_bytes += len;
 	q->tot_pkts++;
-	if (fs->plr && random() < fs->plr)
+	if (fs->plr && random() < fs->plr) {
+		DN_LOG(fs, pipe, q, m, DN_DROP_PLR, dir);
 		goto dropit;		/* Random pkt drop. */
+	}
 	else {
 		while (fs->pls_index < fs->pls.count) {
 			if (q->tot_pkts >= fs->pls.arr[fs->pls_index].start) {
 				if (q->tot_pkts <=
-					fs->pls.arr[fs->pls_index].end)
+					fs->pls.arr[fs->pls_index].end) {
+					DN_LOG(fs, pipe, q, m, DN_DROP_PLS, dir);
 					goto dropit; /* Controlled pkt drop. */
+				}
 				else
 					fs->pls_index++;
 			}
@@ -1335,20 +1788,28 @@ dummynet_io(struct mbuf **m0, int dir, s
 		}
 	}
 	if (fs->flags_fs & DN_QSIZE_IS_BYTES) {
-		if (q->len_bytes > fs->qsize)
+		if (q->len_bytes > fs->qsize) {
+			DN_LOG(fs, pipe, q, m, DN_DROP_QOVERFLOW, dir);
 			goto dropit;	/* Queue size overflow. */
+		}
 	} else {
-		if (q->len >= fs->qsize)
+		if (q->len >= fs->qsize) {
+			DN_LOG(fs, pipe, q, m, DN_DROP_QOVERFLOW, dir);
 			goto dropit;	/* Queue count overflow. */
+		}
 	}
-	if (fs->flags_fs & DN_IS_RED && red_drops(fs, q, len))
+	if (fs->flags_fs & DN_IS_RED && red_drops(fs, q, len)) {
+		DN_LOG(fs, pipe, q, m, DN_DROP_RED, dir);
 		goto dropit;
+	}
 
 	/* XXX expensive to zero, see if we can remove it. */
 	mtag = m_tag_get(PACKET_TAG_DUMMYNET,
 	    sizeof(struct dn_pkt_tag), M_NOWAIT | M_ZERO);
-	if (mtag == NULL)
+	if (mtag == NULL) {
+		DN_LOG(fs, pipe, q, m, DN_DROP_MALLOC, dir);
 		goto dropit;		/* Cannot allocate packet header. */
+	}
 	m_tag_prepend(m, mtag);		/* Attach to mbuf chain. */
 
 	pkt = (struct dn_pkt_tag *)(mtag + 1);
@@ -1369,6 +1830,8 @@ dummynet_io(struct mbuf **m0, int dir, s
 	q->len++;
 	q->len_bytes += len;
 
+	DN_LOG(fs, pipe, q, m, DN_NO_DROP, dir);
+
 	if (q->head != m)		/* Flow was not idle, we are done. */
 		goto done;
 
@@ -2301,6 +2764,7 @@ ip_dn_init(void)
 		printf("DUMMYNET with IPv6 initialized (040826)\n");
 
 	DUMMYNET_LOCK_INIT();
+	mtx_init(&dn_log_queue_mtx, "dummynet__queue_mtx", NULL, MTX_DEF);
 
 	for (i = 0; i < HASHSIZE; i++) {
 		SLIST_INIT(&pipehash[i]);
@@ -2339,6 +2803,7 @@ ip_dn_destroy(void)
 	ip_dn_io_ptr = NULL;
 	ip_dn_ruledel_ptr = NULL;
 
+	dn_manage_logging(DN_LOG_DISABLE);
 	DUMMYNET_LOCK();
 	callout_stop(&dn_timeout);
 	DUMMYNET_UNLOCK();
@@ -2386,4 +2851,5 @@ static moduledata_t dummynet_mod = {
 };
 DECLARE_MODULE(dummynet, dummynet_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
 MODULE_DEPEND(dummynet, ipfw, 2, 2, 2);
+MODULE_DEPEND(idummynet, alq, 1, 1, 1);
 MODULE_VERSION(dummynet, 1);

Modified: user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.h
==============================================================================
--- user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.h	Wed Nov 19 03:24:35 2008	(r185082)
+++ user/lstewart/dummynet_7.x/sys/netinet/ip_dummynet.h	Wed Nov 19 03:57:11 2008	(r185083)
@@ -30,6 +30,33 @@
 #ifndef _IP_DUMMYNET_H
 #define _IP_DUMMYNET_H
 
+/* Packet was not dropped by dummynet */
+#define DN_NO_DROP		0
+
+/* Packet was dropped because there was no corresponding flow set */
+#define DN_DROP_NOFS		1
+
+/* Packet was dropped because there was no corresponding pipe for the queue */
+#define DN_DROP_NOP4Q		2
+
+/* Packet was dropped because we could not allocate a queue for the packet */
+#define DN_DROP_NOQ		3
+
+/* Packet was dropped because PLR was set and this packet won the lucky dip */
+#define DN_DROP_PLR		4
+
+/* Packet was dropped because PLS was set and this packet was selected */
+#define DN_DROP_PLS		5
+
+/* Packet was dropped because the queue it was destined for is full */
+#define DN_DROP_QOVERFLOW	6
+
+/* Packet was dropped because RED was configured on the queue */
+#define DN_DROP_RED		7
+
+/* Packet was dropped because of a malloc failure */
+#define DN_DROP_MALLOC		8
+
 /*
  * Definition of dummynet data structures. In the structures, I decided
  * not to use the macros in <sys/queue.h> in the hope of making the code
@@ -328,6 +355,7 @@ struct dn_pipe {		/* a pipe */
     int bandwidth;		/* really, bytes/tick.	*/
     int	delay ;			/* really, ticks	*/
 
+    u_int len;			/* number of pkts in delay line */
     struct	mbuf *head, *tail ;	/* packets in delay line */
 
     /* WF2Q+ */


More information about the svn-src-user mailing list