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 on the bpf(4) device. 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