<p>I previously wrote about building <ahref="2016-03-13-wifi-client-router-setup.html">WiFi client routers</a> instead of bridges; they get you broadcast domain isolation and a degree of conceptual simplicity (no L2 tricks). I finally ran into a requirement on a different project to build an actual bridge; here’s how I did it.</p>
<li>Make use of <ahref="http://madwifi-project.org/wiki/AboutWDS">4-address WDS</a>. Basically, this means “don’t assume that the source MAC address of the ethernet frame and the source MAC address of the WLAN frame are the same”.</li>
<li>Allow frames where the ethernet and WLAN source MAC addresses differ (like above, but a policy decision).</li>
<li>Not assume that the WLAN MAC address is the only MAC at the other end of the link. This assumption is frequently used to reduce the effect of broadcast traffic in a WiFi environment by filtering. There may be settings like “Multicast optimization”, “Broadcast optimization”, or “DHCP optimization” that you need to turn off.</li>
<p>From that point forward, the interface won’t be able to talk normally, and wpa_supplicant is likely to time out in the association phase (run “sudo wpa_cli” to watch its logs).</p>
<p>You should now be able to fetch an IP on br0 via DHCP. Unless, of course, you need wpa_supplicant to work…</p>
<h3>wpa_supplicant</h3>
<p>wpa_supplicant needs to be bridge-aware to work with 4-address mode. Fortunately, it has a flag (-b) to set the bridge interface. Unfortunately, this flag is broken in 2.1, the version in Ubuntu Trusty. I verified that it works in wpa_supplicant 2.5 built from source; I haven’t verified 2.4 from Xenial.</p>
<p>With that working, the interface should get to wpa_state=COMPLETED, and br0 should work normally. Remember that wlan0 will still be unusable directly.</p>
<h3>Ordering</h3>
<p>Bringing up these interfaces is tricky; the ordering is annoying.</p>
<p>Because of the ordering issues, it’s easier to treat this all as one interface that has to come up together. Here’s an example interface stanza that does this:</p>