Creating a Bridge Interface

From Mage
Jump to: navigation, search

A quick and dirty guide to setting up a bridge interface with a reliable device name.

Find MAC address

Find the MAC address of the NICs you'd like to bridge using ifconfig:

ifconfig -a

Example output is shown below. Make a note of the HWaddr of the interfaces you want to bridge. We'll need these MAC addresses in the next step.

┌(foo@server)─(10:30 PM Tue Jun 24)─(~)
└> ifconfig -a

enp5s0    Link encap:Ethernet  HWaddr 00:1C:C0:AE:B5:E7
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0(0 MiB)  TX bytes:0 (0 MiB)

enp6s0    Link encap:Ethernet  HWaddr 00:1C:C0:AE:B5:E8
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0(0 MiB)  TX bytes:0 (0 MiB)

enp7s0    Link encap:Ethernet  HWaddr 00:1C:C0:AE:B5:E9
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0(0 MiB)  TX bytes:0 (0 MiB)

enp8s0    Link encap:Ethernet  HWaddr 00:1C:C0:AE:B5:EA
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0(0 MiB)  TX bytes:0 (0 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:8 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:480 (480.0 b)  TX bytes:480 (480.0 b)

wan       Link encap:Ethernet  HWaddr 00:1C:C0:AE:B5:E6
          inet addr:192.168.1.1  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:41620 errors:0 dropped:0 overruns:0 frame:0
          TX packets:40231 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:21601203 (20.6 MiB)  TX bytes:6145876 (5.8 MiB)


Set udev rules

We're going to set a udev rule that renames the interfaces upon boot and starts any services that may depend on them. The following rule will look for the MAC addresses we noted in the previous step (make sure the letters are in lowercase in this file). If found, it will rename the interfaces from the kernel generated ones to the names of our choosing. Here we're renaming enp*s0 to lan*. This will help give us reliable names to use when referring to the devices. Avoid using names the kernel may use by default such as eth0.

vi /etc/udev/rules.d/30-br0.rules

SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:e7", NAME="lan0"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:e8", NAME="lan1"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:e9", NAME="lan2"
SUBSYSTEM=="net", ACTION=="add", ATTR{address}=="00:1c:c0:ae:b5:ea", NAME="lan3"
ENV{SYSTEMD_WANTS}="network@br0.service"


Create systemd service

You may have noticed the reference to network@br0.service in the previous step. This lets udev know to start a systemd service named network@br0.service after the interfaces have been renamed to lan0, et al. Systemd can be a true pain in the butt when trying to set services to only come online after a network interface is up, so let's create a framework where services can be specified in the interface's startup service. We can do this using an old school init.d style script. Because this is launched via udev, we don't need to bother with systemd's [Install] section or actually enabling this service.


vi /etc/systemd/system/network\@br0.service

[Unit]
Description=Network Connectivity (br0)

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStart=/etc/network/br0.sh start

ExecStop=/etc/network/br0.sh stop


Create the network init script

Remember to set the script to executable only by root after it's creation by issuing:

touch /etc/network/br0.sh
chown root:root /etc/network/br0.sh
chmod 700 /etc/network/br0.sh


vi /etc/network/br0.sh

#!/bin/bash
#
# Wait for lan port renames and bring the bridge up.

start() {
   if [ -n "`ip link | grep br0`" ]; then
      echo -n "Attempting to bring up br0 : Interface br0 is already up!"
      return
   else
      while [ -z "`ip link | grep br0`" ]
      do
         echo -n "Attempting to bring up br0 : "

         # Test to see if the LAN ports have been assigned yet.
         lan_status=`ip link`
         lan_up=`echo $lan_status | grep lan0 | grep lan1 | grep lan2 | grep lan3`

         if [ "$lan_up" ]; then
            ip link add name br0 type bridge
            # Make sure to give the interface a unique MAC
            ip link set dev br0 address 00:1c:c0:ae:b5:eb
            ip link set br0 up
            ip link set dev lan0 up
            ip link set dev lan1 up
            ip link set dev lan2 up
            ip link set dev lan3 up
            ip link set lan0 master br0
            ip link set lan1 master br0
            ip link set lan2 master br0
            ip link set lan3 master br0
            # Add a separate subnet for the device to route on.
            ip addr add dev br0 192.168.2.1/24 broadcast 192.168.2.255
            # Enhance the send/receive windows on this route
            ip route change 192.168.2.0/24 dev br0 proto kernel scope link src 192.168.2.1 initcwnd 65 initrwnd 65

            # Start any services that depend on this NIC HERE
            #systemctl start sshd
         else
            echo "LAN ports unavailable, waiting 0.1s."
            sleep 0.1
         fi
      done
   fi

   echo -n "Done."
   return
}

stop() {
   echo -n "Bringing down interface br0 : "

   # Stop any services that depend on this NIC HERE
   #systemctl stop sshd

   ip route del 192.168.2.0/24 dev br0 proto kernel scope link src 192.168.2.1
   ip link set lan3 nomaster
   ip link set lan2 nomaster
   ip link set lan1 nomaster
   ip link set lan0 nomaster
   ip link set dev br0 down
   ip link set dev lan3 down
   ip link set dev lan2 down
   ip link set dev lan1 down
   ip link set dev lan0 down
   ip address flush dev lan3
   ip address flush dev lan2
   ip address flush dev lan1
   ip address flush dev lan0
   ip address flush dev br0
   ip link delete br0 type bridge >/dev/null 2>&1

   echo -n "Done."
   return
}

status() {
   if [ "`which ifconfig`" ]; then
      ifconfig br0
      echo
   fi

   ip link show br0
}

restart() {
   stop
   echo
   start
}

case "$1" in
   start)
      start
      ;;
   stop)
      stop
      ;;
   status)
      status
      ;;
   restart)
      restart
      ;;
   *)
      echo -n "   Usage: ./br0.sh (start | stop | status | restart)"
      ;;
esac


Reboot

Reboot your machine to verify the changes have been applied correctly. Make sure the NICs have been renamed and that they have been assigned to the bridge. Verify that any services that depend on the bridge interface have started correctly.