Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 9 Nov 2001 10:56:30 -0600
From:      "Guy Helmer" <ghelmer@palisadesys.com>
To:        "Edwin Groothuis" <edwin@mavetju.org>, <freebsd-hackers@FreeBSD.ORG>
Subject:   RE: pcap/bpf in a multi-threaded environment
Message-ID:  <HEEHKIJOHDLFOOEBABJIAEJGCAAA.ghelmer@palisadesys.com>
In-Reply-To: <20011109225532.A3919@k7.mavetju.org>

next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format.

------=_NextPart_000_0000_01C1690D.2FC70CF0
Content-Type: text/plain;
	charset="us-ascii"
Content-Transfer-Encoding: 7bit

On Friday, November 09, 2001 5:56 AM Edwin Groothuis edwin@mavetju.org
wrote:

> The past couple of days I've been plagued by a strange behaviour
> of something between libpcap and the bpf-device. As you can read
> in PR bin/31649, the behaviour of libpcap is very different if you
> compile it on gcc with or without -pthread:
>
> Without -pthread, it calls the callback function everytime it has
> received a packet.
> With -pthread, it calls the callback function only when the
> input-buffer (about 32Kb) is nearly full.
>
> I've done some investigation (with my limited knowledge of what
> happens between a call to read() and when it ends up in bpfread())
> and saw the difference between a call with and without the -pthreads
> option:
>
> in /usr/src/contrib/libpcap/pcap-bpf.c, line 81, the function pcap_read():
> 		cc = read(p->fd, (char *)p->buffer, p->bufsize);
>
> at a certain moment, in the read()-code, bpfread() is called:
> /sys/net/bpf.c, line 491
>
> In a non-threaded environment, this if-statement is false
>                 if (ioflag & IO_NDELAY) {
> 			splx(s);
> 			return (EWOULDBLOCK);
> 		}
>
> In a threaded environment, the if-statement is true, splx(s) is
> called and EWOULDBLOCK is returned. Then it's silent for a while,
> while the packets are being collected (somewhere) and at a certain
> moment the buffer is nearly full and the read() in pcap_read() is
> finished.
>
> So yeah, I'm stuck. All I want is in threaded mode to have the same
> behaviour as I have in non-threaded mode. Anybody any ideas on how
> to fix this?

The problem is probably due to the poll system call that the threaded
library does before performing the read().  In the non-threaded case, the
read() returns when the timeout is hit; in the threaded case, the threaded
library's poll() has to succeed before the read system call will be
executed, and poll() won't succeed until the buffer is full.

If you would like to try this patch (relative to FreeBSD 4.3) to
/sys/net/bpf.c and /sys/net/bpfdesc.h and let me know if it helps, I will
add this patch to PR 22063 and perhaps commit it if it passes review.

Guy Helmer

------=_NextPart_000_0000_01C1690D.2FC70CF0
Content-Type: application/octet-stream;
	name="bpf-new.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="bpf-new.diff"

--- bpf.c.ORIG	Mon Aug 27 13:25:57 2001=0A=
+++ bpf.c	Fri Nov  9 10:47:22 2001=0A=
@@ -444,7 +444,8 @@=0A=
 	(d)->bd_hlen =3D (d)->bd_slen; \=0A=
 	(d)->bd_sbuf =3D (d)->bd_fbuf; \=0A=
 	(d)->bd_slen =3D 0; \=0A=
-	(d)->bd_fbuf =3D 0;=0A=
+	(d)->bd_fbuf =3D 0; \=0A=
+	(d)->bd_poll =3D 0;=0A=
 /*=0A=
  *  bpfread - read next chunk of packets from buffers=0A=
  */=0A=
@@ -472,7 +473,7 @@=0A=
 	 * have arrived to fill the store buffer.=0A=
 	 */=0A=
 	while (d->bd_hbuf =3D=3D 0) {=0A=
-		if (d->bd_immediate && d->bd_slen !=3D 0) {=0A=
+		if ((d->bd_immediate || d->bd_poll) && d->bd_slen !=3D 0) {=0A=
 			/*=0A=
 			 * A packet(s) either arrived since the previous=0A=
 			 * read or arrived while we were asleep.=0A=
@@ -559,6 +560,7 @@=0A=
 		pgsigio(d->bd_sigio, d->bd_sig, 0);=0A=
 =0A=
 #if BSD >=3D 199103=0A=
+	/* revents |=3D events & (POLLIN | POLLRDNORM); ??? */=0A=
 	selwakeup(&d->bd_sel);=0A=
 	/* XXX */=0A=
 	d->bd_sel.si_pid =3D 0;=0A=
@@ -1057,10 +1059,12 @@=0A=
 =0A=
 	s =3D splimp();=0A=
 	if (events & (POLLIN | POLLRDNORM)) {=0A=
-		if (d->bd_hlen !=3D 0 || (d->bd_immediate && d->bd_slen !=3D 0))=0A=
+		if (d->bd_hlen !=3D 0 || d->bd_poll || (d->bd_immediate && d->bd_slen =
!=3D 0))=0A=
 			revents |=3D events & (POLLIN | POLLRDNORM);=0A=
-		else=0A=
+		else {=0A=
+			d->bd_poll =3D 1;=0A=
 			selrecord(p, &d->bd_sel);=0A=
+		}=0A=
 	}=0A=
 	splx(s);=0A=
 	return (revents);=0A=
@@ -1199,7 +1203,7 @@=0A=
 		bpf_wakeup(d);=0A=
 		curlen =3D 0;=0A=
 	}=0A=
-	else if (d->bd_immediate)=0A=
+	else if (d->bd_immediate || d->bd_poll)=0A=
 		/*=0A=
 		 * Immediate mode is set.  A packet arrived so any=0A=
 		 * reads should be woken up.=0A=
--- bpfdesc.h.ORIG	Mon Aug 27 13:26:06 2001=0A=
+++ bpfdesc.h	Fri Nov  9 10:47:25 2001=0A=
@@ -76,6 +76,7 @@=0A=
 	u_char		bd_promisc;	/* true if listening promiscuously */=0A=
 	u_char		bd_state;	/* idle, waiting, or timed out */=0A=
 	u_char		bd_immediate;	/* true to return on packet arrival */=0A=
+	u_char		bd_poll;	/* poll waiting for data */=0A=
 	int		bd_hdrcmplt;	/* false to fill in src lladdr automatically */=0A=
 	int		bd_seesent;	/* true if bpf should see sent packets */=0A=
 	int		bd_async;	/* non-zero if packet reception should generate signal =
*/=0A=

------=_NextPart_000_0000_01C1690D.2FC70CF0--


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




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