BPF BIOCSETF



BIOCSETF and BIOCSETWF call reset_d which discards any packets
currently in the hold buffer and resets the packet rx count.

The patch below adds BIOCSETFNR, an ioctl that swaps the BPF filter
without resetting the hold buffer and without resetting the packet rx
counts, which is handy when the application wants to adjust its filter
program but without discarding whatever the system might have
buffered.

I've also changed BIOCSETWF to map to the new function. I don't see
the rationale in having BIOCSETWF mucking with the receive stats and
hold buffer.

Patch below is against RELENG_6. I'll send a PR tomorrow against HEAD
if there aren't any comments or complaints; the main difference will
be the extra cruft to make bpf_jitter work.

Thoughts?

Matthew

--- bpf.c.orig Mon Nov 19 14:23:52 2007
+++ bpf.c Mon Nov 19 15:55:05 2007
@@ -103,7 +103,8 @@
u_int, void (*)(const void *, void *, size_t),
struct timeval *);
static void reset_d(struct bpf_d *);
-static int bpf_setf(struct bpf_d *, struct bpf_program *, u_long cmd);
+static int bpf_setf(struct bpf_d *, struct bpf_program *);
+static int bpf_setfnr(struct bpf_d *, struct bpf_program *, u_long);
static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
static int bpf_setdlt(struct bpf_d *, u_int);
static void filt_bpfdetach(struct knote *);
@@ -755,8 +756,12 @@
* Set link layer read filter.
*/
case BIOCSETF:
+ error = bpf_setf(d, (struct bpf_program *)addr);
+ break;
+
+ case BIOCSETFNR:
case BIOCSETWF:
- error = bpf_setf(d, (struct bpf_program *)addr, cmd);
+ error = bpf_setfnr(d, (struct bpf_program *)addr, cmd);
break;

/*
@@ -976,26 +981,17 @@
* free it and replace it. Returns EINVAL for bogus requests.
*/
static int
-bpf_setf(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
+bpf_setf(struct bpf_d *d, struct bpf_program *fp)
{
struct bpf_insn *fcode, *old;
- u_int wfilter, flen, size;
+ u_int flen, size;

- if (cmd == BIOCSETWF) {
- old = d->bd_wfilter;
- wfilter = 1;
- } else {
- wfilter = 0;
- old = d->bd_rfilter;
- }
if (fp->bf_insns == NULL) {
if (fp->bf_len != 0)
return (EINVAL);
BPFD_LOCK(d);
- if (wfilter)
- d->bd_wfilter = NULL;
- else
- d->bd_rfilter = NULL;
+ old = d->bd_rfilter;
+ d->bd_rfilter = NULL;
reset_d(d);
BPFD_UNLOCK(d);
if (old != NULL)
@@ -1011,10 +1007,8 @@
if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
bpf_validate(fcode, (int)flen)) {
BPFD_LOCK(d);
- if (wfilter)
- d->bd_wfilter = fcode;
- else
- d->bd_rfilter = fcode;
+ old = d->bd_rfilter;
+ d->bd_rfilter = fcode;
reset_d(d);
BPFD_UNLOCK(d);
if (old != NULL)
@@ -1024,6 +1018,50 @@
}
free((caddr_t)fcode, M_BPF);
return (EINVAL);
+}
+
+/*
+ * Set d's packet filter program to fp. If this file already has a filter,
+ * replace it but keep any existing buffered packets.
+ */
+static int
+bpf_setfnr(struct bpf_d *d, struct bpf_program *fp, u_long cmd)
+{
+ struct bpf_insn *fcode, *old;
+ u_int flen, size;
+
+ if (fp->bf_insns != NULL) {
+ flen = fp->bf_len;
+ if (flen > bpf_maxinsns)
+ return (EINVAL);
+
+ size = flen * sizeof(*fp->bf_insns);
+ fcode = (struct bpf_insn *)malloc(size, M_BPF, M_WAITOK);
+ if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) != 0 ||
+ bpf_validate(fcode, (int)flen) == 0) {
+ free((caddr_t)fcode, M_BPF);
+ return (EINVAL);
+ }
+ } else {
+ if (fp->bf_len != 0)
+ return (EINVAL);
+ fcode = NULL;
+ }
+
+ BPFD_LOCK(d);
+ if (cmd == BIOCSETFNR) {
+ old = d->bd_rfilter;
+ d->bd_rfilter = fcode;
+ } else {
+ old = d->bd_wfilter;
+ d->bd_wfilter = fcode;
+ }
+ BPFD_UNLOCK(d);
+
+ if(old != NULL)
+ free((caddr_t)old, M_BPF);
+
+ return (0);
}

/*
--- bpf.h.orig Mon Nov 19 14:24:11 2007
+++ bpf.h Mon Nov 19 14:25:16 2007
@@ -115,6 +115,7 @@
#define BIOCGDLTLIST _IOWR('B',121, struct bpf_dltlist)
#define BIOCLOCK _IO('B', 122)
#define BIOCSETWF _IOW('B',123, struct bpf_program)
+#define BIOCSETFNR _IOW('B',124, struct bpf_program)

/*
* Structure prepended to each packet.
_______________________________________________
freebsd-net@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscribe@xxxxxxxxxxx"



Relevant Pages

  • Re: BPF BIOCSETF
    ... currently in the hold buffer and resets the packet rx count. ... The patch below adds BIOCSETFNR, an ioctl that swaps the BPF filter ...
    (freebsd-net)
  • Re: Interesting TCP behaviour with large sends/small buffers
    ... My current workaround is simply setting the send buffer to a larger ... The server, upon connection, sends a configurable number of bytes to ... packet before sending the next packet. ... ACK, according to the delayed ACK algorithm - 50KB bytes means 34 MSS- ...
    (microsoft.public.win32.programmer.networks)
  • Re: Interesting TCP behaviour with large sends/small buffers
    ... The server, upon connection, sends a configurable number of bytes to ... I set the client's receive buffer size to 1MBps, ... packet before sending the next packet. ... ACK, according to the delayed ACK algorithm - 50KB bytes means 34 MSS- ...
    (microsoft.public.win32.programmer.networks)
  • Re: Fundamentals question, is this how it works?
    ... You maintain a buffer for the last incomplete packet. ... receiving that many bytes i then break and wait for the next set of data ... With a tcp stream socket what happens when it is reading say 4000bytes ...
    (microsoft.public.win32.programmer.networks)
  • Re: Design of a Router
    ... packet forward it and than close the port and move to the next and so ... would ideally like the router as small and as fast as possible. ... size of your buffer (just keep in mind that if you have 4 ports than ...
    (comp.lang.verilog)