Subject: Conditionalize expensive BPF operation
To: None <tech-net@NetBSD.ORG>
From: Martin Husemann <firstname.lastname@example.org>
Date: 04/30/2001 21:57:26
I would like add a test function to the in-kernel bpf routines,
int bpf_haslisteners(caddr_t arg);
which would return 0 if there are no listeners attached to the struct bpf_if
(that hides behind "arg"); i.e. would do something like this:
int bpf_haslisteners(caddr_t arg)
struct bpf_if *bp = (struct bpf_if *)arg;
return (bp->bif_dlist != NULL);
This would be usefull for interface where the bpf_mtap call needs some
special, maybe expensive work.
The concrete example I'm thinking about (and maybe I'm completely on the
wrong track here already), is the pppoe pseudo device (see
sys/net/if_pppoe.c). Doing the right bpf_mtap for this on output is not easy:
it is passed a mbuf chain, prepends some headers, and then passes the whole
chain down to an ethernet interface, which ends up in a call to ether_output.
There is a bpf_mtap happening there, but with the wrong DLT_* type.
Actually I would like to pass to BPF something slightly different from the
packet send by the ethernet interface by prepending additional meta-BPF
information (PPP encapsulation type, so a generic PPP module can interpret
this data in libpcap and/or tcpdump or other applications).
What I would do for a packet passed down to this interface is:
- M_PREPEND() some space, or copyup all contents to a buffer
- fill in a faked ethernet header (hopefully identical to the one
later added in ether_output
- add the encapsulation info in front of the ethernet header
- pass this to bpf
All this only needs to happen if someone is listening. I'd like to avoid it
for the standard path without listeners.
I have no idea whether just copying the whole mbuf chain and modifying the
copy, or copying up to memory buffer allocated once for the softc and doing
bpf_tap instead of bpf_mtap would be preferable.
This all looks ugly and does not feel like the right way to do it, so I'll
gladly take any better suggestions.