From nobody@FreeBSD.org  Mon Sep 13 20:38:46 2004
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id ACCFE16A4CF
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 13 Sep 2004 20:38:46 +0000 (GMT)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 9852243D64
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 13 Sep 2004 20:38:46 +0000 (GMT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.12.11/8.12.11) with ESMTP id i8DKckDP002102
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 13 Sep 2004 20:38:46 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.12.11/8.12.11/Submit) id i8DKcjaa002101;
	Mon, 13 Sep 2004 20:38:45 GMT
	(envelope-from nobody)
Message-Id: <200409132038.i8DKcjaa002101@www.freebsd.org>
Date: Mon, 13 Sep 2004 20:38:45 GMT
From: Matthew Luckie <mjl@luckie.org.nz>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [PATCH] generate a single bpf timestamp for each packet
X-Send-Pr-Version: www-2.3

>Number:         71711
>Category:       kern
>Synopsis:       [bpf] [patch] generate a single bpf timestamp for each packet
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    dwmalone
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Mon Sep 13 20:40:29 GMT 2004
>Closed-Date:    Wed Jan 17 09:37:05 GMT 2007
>Last-Modified:  Wed Jan 17 09:37:05 GMT 2007
>Originator:     Matthew Luckie
>Release:        FreeBSD 4.10
>Organization:
University of Waikato
>Environment:
FreeBSD neoprene.luckie.org.nz 4.10-RELEASE FreeBSD 4.10-RELEASE #8: Tue Sep 14 08:14:46 NZST 2004     root@neoprene.luckie.org.nz:/usr/src/sys/compile/neoprene  i386
>Description:
      I'm using BPF to obtain the transmit timestamp of packets I send.  I noticed that the timestamps differed slightly between what I was seeing and what tcpdump saw.  The cause of this is that timestamps are generated for each bpf fd if the packet passes the filter.  The bpf(4) documentation is accurate for this case, but I'm wondering if it makes more sense to generate the timestamp once for each packet, as it allows a more accurate estimation of when the packet might have hit the wire.
>How-To-Repeat:
      Open two tcpdump sessions that capture the same packets.  You'll notice the timestamps differ slightly.
>Fix:
      I took the liberty of optimising bpf_mtap a little while generating the patch.  I also removed code for generating timestamps based on the kernel being run, as the code would be duplicated in two places.  I'm happy to generate a macro and stick it in bpf_compat.h

--- net/bpf.c.orig	Tue Sep 14 07:40:02 2004
+++ net/bpf.c	Tue Sep 14 08:14:38 2004
@@ -126,7 +126,8 @@
 static inline void
 		bpf_wakeup __P((struct bpf_d *));
 static void	catchpacket __P((struct bpf_d *, u_char *, u_int,
-		    u_int, void (*)(const void *, void *, size_t)));
+		    u_int, void (*)(const void *, void *, size_t),
+		    struct timeval *));
 static void	reset_d __P((struct bpf_d *));
 static int	 bpf_setf __P((struct bpf_d *, struct bpf_program *));
 
@@ -1188,17 +1189,22 @@
 	struct bpf_if *bp;
 	register struct bpf_d *d;
 	register u_int slen;
+	struct timeval tv;
+	
+	bp = ifp->if_bpf;
+	if (bp->bif_dlist != NULL)
+		microtime(&tv);
+
 	/*
 	 * Note that the ipl does not have to be raised at this point.
 	 * The only problem that could arise here is that if two different
 	 * interfaces shared any data.  This is not the case.
 	 */
-	bp = ifp->if_bpf;
 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
 		++d->bd_rcount;
 		slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
 		if (slen != 0)
-			catchpacket(d, pkt, pktlen, slen, bcopy);
+			catchpacket(d, pkt, pktlen, slen, bcopy, &tv);
 	}
 }
 
@@ -1241,18 +1247,27 @@
 	struct bpf_d *d;
 	u_int pktlen, slen;
 	struct mbuf *m0;
+	struct timeval tv;
 
-	pktlen = 0;
-	for (m0 = m; m0 != 0; m0 = m0->m_next)
-		pktlen += m0->m_len;
-
-	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
-		if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
-			continue;
-		++d->bd_rcount;
-		slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
-		if (slen != 0)
-			catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
+	d = bp->bif_dlist;
+	if (d != NULL) {
+		microtime(&tv);
+
+		pktlen = 0;
+		for (m0 = m; m0 != 0; m0 = m0->m_next)
+			pktlen += m0->m_len;
+
+		do {
+			if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
+				continue;
+			++d->bd_rcount;
+			slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
+			if (slen != 0)
+				catchpacket(d, (u_char *)m, pktlen, slen,
+				            bpf_mcopy, &tv);
+			d = d->bd_next;
+		}
+		while (d != NULL);
 	}
 }
 
@@ -1265,11 +1280,12 @@
  * pkt is really an mbuf.
  */
 static void
-catchpacket(d, pkt, pktlen, snaplen, cpfn)
+catchpacket(d, pkt, pktlen, snaplen, cpfn, tv)
 	register struct bpf_d *d;
 	register u_char *pkt;
 	register u_int pktlen, snaplen;
 	register void (*cpfn) __P((const void *, void *, size_t));
+	register struct timeval *tv;
 {
 	register struct bpf_hdr *hp;
 	register int totlen, curlen;
@@ -1318,13 +1334,7 @@
 	 * Append the bpf header.
 	 */
 	hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
-#if BSD >= 199103
-	microtime(&hp->bh_tstamp);
-#elif defined(sun)
-	uniqtime(&hp->bh_tstamp);
-#else
-	hp->bh_tstamp = time;
-#endif
+	bcopy(tv, &hp->bh_tstamp, sizeof(hp->bh_tstamp));
 	hp->bh_datalen = pktlen;
 	hp->bh_hdrlen = hdrlen;
 	/*

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->dwmalone 
Responsible-Changed-By: dwmalone 
Responsible-Changed-When: Mon Jul 24 15:42:09 UTC 2006 
Responsible-Changed-Why:  
I've committed a patch to -current. I will MFC in about a month. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=71711 
State-Changed-From-To: open->closed 
State-Changed-By: dwmalone 
State-Changed-When: Wed Jan 17 09:36:43 UTC 2007 
State-Changed-Why:  
I merged this some time ago, but forgot to close the PR. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=71711 
>Unformatted:
