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>