Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Dec 2014 12:30:40 +0000 (UTC)
From:      "Alexander V. Chernikov" <melifaro@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r275608 - stable/9/sys/net
Message-ID:  <201412081230.sB8CUe8t079973@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: melifaro
Date: Mon Dec  8 12:30:40 2014
New Revision: 275608
URL: https://svnweb.freebsd.org/changeset/base/275608

Log:
  Merge r267361:
    Improve logic besides net.bpf.optimize_writers.
    Direct bpf(4) consumers should now work fine with this tunable turned on.
    In fact, the only case when optimized_writers can change program
    behavior is direct bpf(4) consumer setting its read filter to
    catch-all one.
  
  Sponsored by:	Yandex LLC

Modified:
  stable/9/sys/net/bpf.c
Directory Properties:
  stable/9/sys/   (props changed)
  stable/9/sys/net/   (props changed)

Modified: stable/9/sys/net/bpf.c
==============================================================================
--- stable/9/sys/net/bpf.c	Mon Dec  8 11:28:08 2014	(r275607)
+++ stable/9/sys/net/bpf.c	Mon Dec  8 12:30:40 2014	(r275608)
@@ -659,6 +659,67 @@ bpf_attachd(struct bpf_d *d, struct bpf_
 }
 
 /*
+ * Check if we need to upgrade our descriptor @d from write-only mode.
+ */
+static int
+bpf_check_upgrade(u_long cmd, struct bpf_d *d, struct bpf_insn *fcode, int flen)
+{
+	int is_snap, need_upgrade;
+
+	/*
+	 * Check if we've already upgraded or new filter is empty.
+	 */
+	if (d->bd_writer == 0 || fcode == NULL)
+		return (0);
+
+	need_upgrade = 0;
+
+	/*
+	 * Check if cmd looks like snaplen setting from
+	 * pcap_bpf.c:pcap_open_live().
+	 * Note we're not checking .k value here:
+	 * while pcap_open_live() definitely sets to to non-zero value,
+	 * we'd prefer to treat k=0 (deny ALL) case the same way: e.g.
+	 * do not consider upgrading immediately
+	 */
+	if (cmd == BIOCSETF && flen == 1 && fcode[0].code == (BPF_RET | BPF_K))
+		is_snap = 1;
+	else
+		is_snap = 0;
+
+	if (is_snap == 0) {
+		/*
+		 * We're setting first filter and it doesn't look like
+		 * setting snaplen.  We're probably using bpf directly.
+		 * Upgrade immediately.
+		 */
+		need_upgrade = 1;
+	} else {
+		/*
+		 * Do not require upgrade by first BIOCSETF
+		 * (used to set snaplen) by pcap_open_live().
+		 */
+
+		if (--d->bd_writer == 0) {
+			/*
+			 * First snaplen filter has already
+			 * been set. This is probably catch-all
+			 * filter
+			 */
+			need_upgrade = 1;
+		}
+	}
+
+	CTR5(KTR_NET,
+	    "%s: filter function set by pid %d, "
+	    "bd_writer counter %d, snap %d upgrade %d",
+	    __func__, d->bd_pid, d->bd_writer,
+	    is_snap, need_upgrade);
+
+	return (need_upgrade);
+}
+
+/*
  * Add d to the list of active bp filters.
  * Reuqires bpf_attachd() to be called before
  */
@@ -1818,17 +1879,7 @@ bpf_setf(struct bpf_d *d, struct bpf_pro
 		if (cmd == BIOCSETF)
 			reset_d(d);
 
-		if (fcode != NULL) {
-			/*
-			 * Do not require upgrade by first BIOCSETF
-			 * (used to set snaplen) by pcap_open_live().
-			 */
-			if (d->bd_writer != 0 && --d->bd_writer == 0)
-				need_upgrade = 1;
-			CTR4(KTR_NET, "%s: filter function set by pid %d, "
-			    "bd_writer counter %d, need_upgrade %d",
-			    __func__, d->bd_pid, d->bd_writer, need_upgrade);
-		}
+		need_upgrade = bpf_check_upgrade(cmd, d, fcode, flen);
 	}
 	BPFD_UNLOCK(d);
 	if (d->bd_bif != NULL)
@@ -1841,7 +1892,7 @@ bpf_setf(struct bpf_d *d, struct bpf_pro
 #endif
 
 	/* Move d to active readers list. */
-	if (need_upgrade)
+	if (need_upgrade != 0)
 		bpf_upgraded(d);
 
 	BPF_UNLOCK();



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