Subject: Re: BPF support for writing raw IEEE 802.11 frames
To: Vivek raghunathan <vivek.raghunathan@gmail.com>
From: Pavel Cahyna <pavel@netbsd.org>
List: tech-net
Date: 08/01/2006 20:42:31
On Tue, Aug 01, 2006 at 02:19:15PM -0400, Vivek raghunathan wrote:
> Hello all,
> 
> (Long email)
> 
> I am currently working at BBN Technologies with Greg Troxel on a project to
> virtualize an IEEE 802.11 interface over a network. The broad
> architecture is as follows: (real/virtual host refers to the host on which
> the real/virtual interface is attached.)
> 
> 1. Frames arriving on the real interface are read by a userspace
> daemon using BPF, encapsulated in UDP packets and passed off to a
> userspace daemon running on the virtual host. This daemon decapsulates
> the UDP packets and injects the extracted 802.11 frames into the
> kernel stack at the virtual host. This injection is done by extending
> the tap(4) interface to support 802.11 in addition to Ethernet.
> 
> 2. When a packet is to be transmitted out the virtual interface, it is
> encapsulated in 802.11 headers and passed to userspace using the
> extended tap(4) interface mentioned above. The userspace daemon at the
> virtual host encapsulates the frames in UDP, and sends them to the
> userspace daemon at the real host, where they are injected into the
> real interface using BPF.
> 
> (There are a lot of additional details here on what it means to
> virtualize an IEEE 802.11 interface over a network - that is the
> subject of another email.)
> 
> As part of this project, we need the ability to inject raw IEEE 802.11
> frames from userspace using BPF. It seems like the current NetBSD
> bpf_write path does not support DLT_IEEE802_11, or
> DLT_IEEE802_11_RADIO. This is because:
> 
> 1. (minor) net/bpf.c: bpf_write calls bpf_movein, which does not
> recognize the dlt DLT_IEEE802_11/DLT_IEEE802_11_RADIO and returns EIO.
> This is easily fixable.
> 
> 2. net/bpf.c: bpf_write passes an mbuf to ifp->if_output. All 802.11
> drivers invoke ether_ifattach via ieee80211_ifattach, and
> ether_ifattach sets ifp->if_output = ether_output. Thus, bpf_write
> ends up passing raw DLT_IEEE802_11 mbufs to ether_output. This causes
> DLT_IEEE80211 raw frame writes on a BPF to break:
> 
> a. ether_output expects raw frames with an attached Ethernet header.
> DLT_IEEE80211 raw frames do not have an Ethernet header.
> 
> b. ether_output enqueues the frame and calls the driver-provided
> foo_start routine, which typically calls ieee80211_encap to do
> IEEE 802.11 encapsulation. If this worked, it would incorrectly put an
> 802.11 header on the raw 802.11 frame. (In practice, it won't work
>          because ieee80211_encap expects its input to be Ethernet
>          encapsulated; it strips off the
>          Ethernet header and adds an IEEE 802.11 header and a LLC
>          header. Here the raw DLT_IEEE802_11 frame does not have an
>          Ethernet header.)

Why do the 802.11 drivers use ether_output and other Ethernet routines
if the frames are actually in a different format? FDDI and Token Ring also
have their own _output routines. Shouldn't we have a similar
ieee80211_output function which would be used instead of ether_output?

Pavel