Setting Up a Network Bridge #
A bridge(4) is a link between two or more separate networks. Unlike a router, packets go through the bridge transparently: the two network segments appear as one to nodes on either side. Bridges will only forward packets that have to pass from one segment to the other and, as a result, an interface in a bridge may or may not have an IP address of its own. If it does, the interface has effectively two modes of operation: one as part of a bridge, the other as a stand-alone NIC. If neither interface has an IP address, the bridge will pass network data, but will not be externally maintainable (which can be a feature).
A Bridge Acting as a DHCP Server #
Let’s say we have a system which has four vr(4) interfaces, vr0 through vr3. We want to bridge vr1, vr2 and vr3 together, leaving out vr0 for the uplink. We also want to serve IP addresses through DHCP over the bridged interfaces. Being a DHCP server and an uplink router, the box needs to have an IP address on the bridged network.
It is not possible to assign an IP address directly to a bridge interface. The IP address should be added to one of the member interfaces, but we cannot use a physical interface as the link might be down, in which case the address would not be reachable. Fortunately, there is the vether(4) (virtual Ethernet) driver that can be used for this purpose. We will add it to the bridge, assign the IP address to it and make dhcpd(8) listen there.
- The DHCP server configuration is not described yet again in this section, but the addressing scheme used here is the same.
- This will also be the uplink router for your bridged network, so we will use IP address 192.168.1.1 to match the DHCP server configuration.
- We will not cover the uplink, routing or firewalling configuration here.
First, mark the vr1, vr2 and vr3 interfaces as up:
# echo up > /etc/hostname.vr1
# echo up > /etc/hostname.vr2
# echo up > /etc/hostname.vr3
Then create the vether0 configuration:
# echo 'inet 192.168.1.1 255.255.255.0 192.168.1.255' > /etc/hostname.vether0
Configure the bridge interface to contain all the above interfaces:
$ cat /etc/hostname.bridge0
add vether0
add vr1
add vr2
add vr3
up
And finally we make the DHCP daemon listen on the vether0 interface:
# rcctl set dhcpd flags vether0
All that’s left now is to reboot!
Filtering on a Bridge #
While there are certainly uses for a simple bridge like this, it is likely you might want to DO something with the packets as they go through your bridge. As you might expect, Packet Filter can be used to restrict what traffic goes through your bridge. Keep in mind, by the nature of a bridge, the same data flows through both interfaces, so you only need to filter on one interface.
Tips on Bridging #
- By using the blocknonip option of ifconfig(8) or in hostname.bridge0, you can prevent non-IP traffic (such as IPX or NETBEUI) from slipping around your filters. This may be important in some situations, but you should be aware that bridges work for all kinds of traffic, not just IP.
- Bridging requires that the NICs be in a promiscuous mode. They listen to all network traffic, not just that directed at the interface. This will put a higher load on the processor and bus than one might expect.
Equal-cost Multipath Routing #
Equal-cost multipath routing refers to having multiple routes in the routing table for the same network, such as the default route, 0.0.0.0/0. When the kernel is doing a route lookup to determine where to send packets destined to that network, it can choose from any of the equal-cost routes. In most scenarios, multipath routing is used to provide redundant uplink connections, e.g., redundant connections to the internet.
The route(8) command is used to add/change/delete routes in the routing table. The -mpath argument is used when adding multipath routes.
# route add -mpath default 10.130.128.1
# route add -mpath default 10.132.0.1
Verify the routes:
# netstat -rnf inet | grep default
default 10.130.128.1 UGS 2 134 - fxp1
default 10.132.0.1 UGS 0 172 - fxp2
In this example we can see that one default route points to 10.130.128.1, which is accessible via the fxp1 interface, and the other points to 10.132.0.1, which is accessible via fxp2.
Since the mygate(5) file does not yet support multipath default routes, the above commands should be added to the bottom of the hostname.if(5) files for the fxp1 and fxp2 interfaces. The /etc/mygate file should then be deleted.
$ tail -1 /etc/hostname.fxp1
!route add -mpath default 10.130.128.1
$ tail -1 /etc/hostname.fxp2
!route add -mpath default 10.132.0.1
Lastly, don’t forget to activate the use of multipath routes by enabling the proper sysctl(8) variable.
# sysctl net.inet.ip.multipath=1
# sysctl net.inet6.ip6.multipath=1
Be sure to edit sysctl.conf(5) to make the changes permanent.
Now try a traceroute to different destinations. The kernel will load balance the traffic over each multipath route.
# traceroute -n 154.11.0.4
traceroute to 154.11.0.4 (154.11.0.4), 64 hops max, 60 byte packets
1 10.130.128.1 19.337 ms 18.194 ms 18.849 ms
2 154.11.95.170 17.642 ms 18.176 ms 17.731 ms
3 154.11.5.33 110.486 ms 19.478 ms 100.949 ms
4 154.11.0.4 32.772 ms 33.534 ms 32.835 ms
# traceroute -n 154.11.0.5
traceroute to 154.11.0.5 (154.11.0.5), 64 hops max, 60 byte packets
1 10.132.0.1 14.175 ms 14.503 ms 14.58 ms
2 154.11.95.38 13.664 ms 13.962 ms 13.445 ms
3 208.38.16.151 13.964 ms 13.347 ms 13.788 ms
4 154.11.0.5 30.177 ms 30.95 ms 30.593 ms
For more information about how the route is chosen, please refer to RFC2992, “Analysis of an Equal-Cost Multi-Path Algorithm”.
It’s worth noting that if an interface used by a multipath route goes down (i.e., loses carrier), the kernel will still try to forward packets using the route that points to that interface. This traffic will of course be blackholed and end up going nowhere. It’s highly recommended to use ifstated(8) to check for unavailable interfaces and adjust the routing table accordingly.