Hi,

tcpdump feels a bit laggy or slow some times when i use it for live debugging.

The following patch adds a new flag, '-b', to tcpdump. With this flag, tcpdump
sets BIOCIMMEDIATE for the current bpf(4) interface. With BIOCIMMEDIATE set,
the output is fluent.

Index: usr.sbin/tcpdump/privsep.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep.c,v
retrieving revision 1.30
diff -u -p -r1.30 privsep.c
--- usr.sbin/tcpdump/privsep.c  22 Sep 2011 09:12:30 -0000      1.30
+++ usr.sbin/tcpdump/privsep.c  14 Dec 2014 22:40:14 -0000
@@ -318,7 +318,7 @@ priv_init(int argc, char **argv)
 static void
 impl_open_bpf(int fd, int *bpfd)
 {
-       int snaplen, promisc, err;
+       int snaplen, promisc, immediate, err;
        u_int dlt, dirfilt;
        char device[IFNAMSIZ];
        size_t iflen;
@@ -327,12 +327,13 @@ impl_open_bpf(int fd, int *bpfd)
 
        must_read(fd, &snaplen, sizeof(int));
        must_read(fd, &promisc, sizeof(int));
+       must_read(fd, &immediate, sizeof(int));
        must_read(fd, &dlt, sizeof(u_int));
        must_read(fd, &dirfilt, sizeof(u_int));
        iflen = read_string(fd, device, sizeof(device), __func__);
        if (iflen == 0)
                errx(1, "Invalid interface size specified");
-       *bpfd = pcap_live(device, snaplen, promisc, dlt, dirfilt);
+       *bpfd = pcap_live(device, snaplen, promisc, immediate, dlt, dirfilt);
        err = errno;
        if (*bpfd < 0)
                logmsg(LOG_DEBUG,
Index: usr.sbin/tcpdump/privsep.h
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep.h,v
retrieving revision 1.7
diff -u -p -r1.7 privsep.h
--- usr.sbin/tcpdump/privsep.h  25 Aug 2009 06:59:17 -0000      1.7
+++ usr.sbin/tcpdump/privsep.h  14 Dec 2014 22:40:14 -0000
@@ -47,10 +47,10 @@ int priv_init(int, char **);
 void    priv_init_done(void);
 
 int    setfilter(int, int, char *);
-int    pcap_live(const char *, int, int, u_int, u_int);
+int    pcap_live(const char *, int, int, int, u_int, u_int);
 
 struct bpf_program *priv_pcap_setfilter(pcap_t *, int, u_int32_t);
-pcap_t *priv_pcap_live(const char *, int, int, int, char *, u_int,
+pcap_t *priv_pcap_live(const char *, int, int, int, int, char *, u_int,
            u_int);
 pcap_t *priv_pcap_offline(const char *, char *);
 
Index: usr.sbin/tcpdump/privsep_pcap.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/privsep_pcap.c,v
retrieving revision 1.17
diff -u -p -r1.17 privsep_pcap.c
--- usr.sbin/tcpdump/privsep_pcap.c     14 Nov 2012 03:33:04 -0000      1.17
+++ usr.sbin/tcpdump/privsep_pcap.c     14 Dec 2014 22:40:14 -0000
@@ -172,8 +172,8 @@ priv_pcap_setfilter(pcap_t *hpcap, int o
 
 /* privileged part of priv_pcap_live */
 int
-pcap_live(const char *device, int snaplen, int promisc, u_int dlt,
-    u_int dirfilt)
+pcap_live(const char *device, int snaplen, int promisc, int immediate,
+    u_int dlt, u_int dirfilt)
 {
        char            bpf[sizeof "/dev/bpf0000000000"];
        int             fd, n = 0;
@@ -204,6 +204,10 @@ pcap_live(const char *device, int snaple
        if (promisc)
                /* this is allowed to fail */
                ioctl(fd, BIOCPROMISC, NULL);
+
+       if (immediate && ioctl(fd, BIOCIMMEDIATE, &immediate) < 0)
+               goto error;
+
        if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0)
                goto error;
 
@@ -223,7 +227,7 @@ pcap_live(const char *device, int snaple
  * unprivileged part.
  */
 pcap_t *
-priv_pcap_live(const char *dev, int slen, int prom, int to_ms,
+priv_pcap_live(const char *dev, int slen, int prom, int imme, int to_ms,
     char *ebuf, u_int dlt, u_int dirfilt)
 {
        int fd, err;
@@ -251,6 +255,7 @@ priv_pcap_live(const char *dev, int slen
        write_command(priv_fd, PRIV_OPEN_BPF);
        must_write(priv_fd, &slen, sizeof(int));
        must_write(priv_fd, &prom, sizeof(int));
+       must_write(priv_fd, &imme, sizeof(int));
        must_write(priv_fd, &dlt, sizeof(u_int));
        must_write(priv_fd, &dirfilt, sizeof(u_int));
        write_string(priv_fd, dev);
Index: usr.sbin/tcpdump/tcpdump.8
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.8,v
retrieving revision 1.83
diff -u -p -r1.83 tcpdump.8
--- usr.sbin/tcpdump/tcpdump.8  3 Jun 2014 02:57:29 -0000       1.83
+++ usr.sbin/tcpdump/tcpdump.8  14 Dec 2014 22:40:15 -0000
@@ -28,7 +28,7 @@
 .Sh SYNOPSIS
 .Nm tcpdump
 .Bk -words
-.Op Fl AadefILlNnOopqStvXx
+.Op Fl AabdefILlNnOopqStvXx
 .Op Fl c Ar count
 .Op Fl D Ar direction
 .Oo Fl E Oo Ar espalg : Oc Ns
@@ -61,6 +61,9 @@ The smaller of the entire packet or
 bytes will be printed.
 .It Fl a
 Attempt to convert network and broadcast addresses to names.
+.It Fl b
+Disables read blocking on the bpf(4) buffer. With this so called
+``immediate mode'' reads return immediately upon packet reception.
 .It Fl c Ar count
 Exit after receiving
 .Ar count
Index: usr.sbin/tcpdump/tcpdump.c
===================================================================
RCS file: /cvs/src/usr.sbin/tcpdump/tcpdump.c,v
retrieving revision 1.66
diff -u -p -r1.66 tcpdump.c
--- usr.sbin/tcpdump/tcpdump.c  30 Jun 2014 04:25:11 -0000      1.66
+++ usr.sbin/tcpdump/tcpdump.c  14 Dec 2014 22:40:15 -0000
@@ -60,6 +60,7 @@
 
 int Aflag;                     /* dump ascii */
 int aflag;                     /* translate network and broadcast addresses */
+int bflag;                     /* set read on livesession to non-blocking */
 int dflag;                     /* print filter code */
 int eflag;                     /* print ethernet header */
 int fflag;                     /* don't translate "foreign" IP address */
@@ -226,7 +227,7 @@ main(int argc, char **argv)
 
        opterr = 0;
        while ((op = getopt(argc, argv,
-           "Aac:D:deE:fF:i:IlLnNOopqr:s:StT:vw:xXy:Y")) != -1)
+           "Aabc:D:deE:fF:i:IlLnNOopqr:s:StT:vw:xXy:Y")) != -1)
                switch (op) {
 
                case 'A':
@@ -238,6 +239,10 @@ main(int argc, char **argv)
                        ++aflag;
                        break;
 
+               case 'b':
+                       ++bflag;
+                       break;
+
                case 'c':
                        cnt = atoi(optarg);
                        if (cnt <= 0)
@@ -429,8 +434,8 @@ main(int argc, char **argv)
                        if (device == NULL)
                                error("%s", ebuf);
                }
-               pd = priv_pcap_live(device, snaplen, !pflag, 1000, ebuf,
-                   dlt, dirfilt);
+               pd = priv_pcap_live(device, snaplen, !pflag, bflag, 1000,
+                   ebuf, dlt, dirfilt);
                if (pd == NULL)
                        error("%s", ebuf);

Reply via email to