Linux Bridging Support
Support for bridging has been available in stable Linux kernels from version 2.4.0 onwards. Previously, patches were available for versions 2.2, however these are no longer maintained for newer 2.2.x releases.
Kernel configuration
If you're using a distribution supplied kernel, chances are that you already have support for Ethernet bridges on your system. Most likely it will be compiled as a module, in which case you will need to load it before you can use it:
# modprobe bridge
If you need to recompile your kernel, you will need to set the 'CONFIG_BRIDGE' option to 'y' or 'm' during the configuration stage.
Userspace Tools
All the popular distributions have the bridging userspace tools already packaged for easy installation; under Debian, Ubuntu, Fedora, Redhat Enterprise and SuSE Linux, this package is called 'bridge-utils'. The package provides the 'brctl' command, which is used to control all of the Linux bridging capabilities discussed here.
If your system doesn't have a precompiled package available, you will need to download the source from the
Linux ethernet bridging sourceforge page. At the time of writing, the latest stable version available of the bridge utils package was 1.1.
Compilation and installation is quite straightforward:
# tar xzf bridge-utils-1.1.tar.gz
# cd bridge-utils-1.1
# ./configure --prefix=/usr/local
# make
# su
# make install
Other than the standard GNU autoconf options, there are no special compile time directives to alter the behaviour of the bridge-utils package.
Creating and using bridges
For simplicity's sake, we will assume that we want to bridge together two ethernet networks, interfaces eth0 and eth1. Figure 1 shows a fairly basic network: our bridging linux box (bridge01) with two network segments, which have two Linux machines on each (linux01 and linux02 on the first, and linux03 and linux04 on the second).
Before we create the bridge, we should ensure that both interfaces are down, and have no IP address assigned to them:
# ifconfig eth0 0 down
# ifconfig eth1 0 down
Now, we can create the bridge interface. Here we see the use of the brctl 'addbr' command, which adds a bridge interface named 'br0'.
# brctl addbr br0
There are no restrictions on the interface name used for the bridge; any name can be used, as long as the system does not already have an interface with that name. The convention, however, is to name bridges br0, br1 and so forth.
Once the bridge interface has been created, we can add the real ethernet interfaces to it as ports:
# brctl addif br0 eth0
# brctl addif br0 eth1
That's all there is to it. At this point, we can now treat the bridge interface as we would any other network interface on a Linux box; so the first thing we can do is give it an interface and bring it up on the network:
# ifconfig br0 10.1.9.1 netmask 255.255.255.0 broadcast 10.1.9.255 up
# ifconfig br0
br0 Link encap:Ethernet HWaddr 10:00:01:04:71:06
inet addr:10.1.9.1 Bcast:10.1.9.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:49 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:9442 (9.2 KiB)
The brctl command provides a 'show' function, so that it is possible to see the state of bridges on the machine:
# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.100001047106 yes eth0
eth1
Of note is the "bridge id". This number is used with Spanning Tree Protocol, which will be discussed later on.
At this point, it should be possible to ping the client machines on each of the network segments, from the bridge:
bridge01:/# ping -c 1 -n 10.1.9.2
PING 10.1.9.2 (10.1.9.2) 56(84) bytes of data.
64 bytes from 10.1.9.2: icmp_seq=1 ttl=64 time=20.6 ms
bridge01:/# ping -c 1 -n 10.1.9.4
PING 10.1.9.4 (10.1.9.4) 56(84) bytes of data.
64 bytes from 10.1.9.4: icmp_seq=1 ttl=64 time=20.6 ms
It will also be possible to send traffic from one of the machines on one segment to a machine on the other segment:
linux01:/# ping -c 1 -n 10.1.9.5
PING 10.1.9.5 (10.1.9.5) 56(84) bytes of data.
64 bytes from 10.1.9.5: icmp_seq=1 ttl=64 time=20.6 ms
More importantly, it can be seen that for traffic between two devices on a single network segment, the bridge will confine the traffic to that segment. This can be seen by running tcpdump on, say, linux03, while sending ICMP packets from linux01 to linux02.
linux03:/# tcpdump -n -i eth0 icmp
linux01:/# ping -n 10.1.9.3
PING 10.1.9.3 (10.1.9.3) 56(84) bytes of data.
64 bytes from 10.1.9.3: icmp_seq=1 ttl=64 time=20.6 ms
If the bridge is working correctly, linux03 should not see any of the traffic between linux01 and linux02, even though they are part of the same logical network.
On the other hand, if we were to send an ICMP packet to the broadcast address on the network, the bridge will pass this packet across to the second network segment:
linux01:/# ping -c 1 -b 10.1.9.255
WARNING: pinging broadcast address
PING 10.1.9.255 (10.1.9.255) 56(84) bytes of data.
64 bytes from 10.1.9.2: icmp_seq=1 ttl=64 time=0.251 ms
linux03:/# tcpdump -n -i eth0 icmp
tcpdump: listening on eth0
19:39:48.273806 10.1.9.2 > 10.1.9.255: icmp: echo request (DF)
19:39:48.273965 10.1.9.4 > 10.1.9.2: icmp: echo reply
19:39:48.274582 10.1.9.5 > 10.1.9.2: icmp: echo reply
This tcpdump output shows the broadcast ICMP request from linux01, and two replies, one from linux03 and one from linux04. linux01 and linux02 would also have sent ICMP responses, as indeed would the bridge itself, since we configured it to have a broadcast address on this network.
It is worth mentioning at this point that it is perfectly possible for the bridge to be able to operate without having an IP address assigned to it. If this were the case, it would bridge packets between the two segments as shown above, but would not actually take part in any network exchanges on an IP level.
Using the 'showmacs' command, we can see a list of the devices on the network, along with the port to which they are connected:
bridge01:/# brctl showmacs br0
port no mac addr is local? ageing timer
2 10:00:01:02:24:04 no 0.49
1 10:00:01:02:95:35 no 0.98
1 10:00:01:02:34:56 no 3.84
2 10:00:01:03:26:02 no 9.19
1 10:00:01:03:73:03 yes 0.00
2 10:00:01:04:71:06 yes 0.00
This list displays the MAC addresses of the six ethernet cards connected to our bridged network; firstly the ethernet cards in each of our four client PCs (listed as not local) and then the two ethernet cards in our bridge itself (and hence, local).
The Ageing Time represents the period of time since the bridge last saw a packet from a device with a particular MAC address. After a certain amount of time has passed, the bridge will purge an address from its database. This is done to handle machines that might change ports over a period of time (for example, a laptop computer which is physically moved from one location to another).
The ageing timeout for a bridge can be changed with the 'setageingtime' command:
# brctl setageingtime br0 40
The above command would set a bridge to purge addresses after 40 seconds.
If you found this article helpful, consider making a donation to offset the costs of running this server, to one of these addresses: