Routing and Switching

Lecture slides are here. In this lesson you’ll learn the commands that view and alter the routing and switching functions of Linux.


  • ip route

  • ip neigh

  • brctl


  • /etc/network/interfaces

Know Your Neighbors

In order to communicate with a host on an Ethernet LAN you must know the host’s MAC address. This information is typically not known by the user. Instead the user requests communication with a host by IP address. For example:

$ ping6 2001:db8::1

Linux must determine the MAC address from the IP address automatically. This is the job of two protocols: The Neighbor Discovery Protocol (NDP) for IPv6 addresses and the Address Resolution Protocol (ARP) for IPv4. Though they have the same function the protocols behave differently. That’s beyond the scope of this class. Linux maintains a list of IP address to MAC address mappings. You can access the list with the command:

$ ip neigh

Here’s an example from my computer:

$ ip neigh
fe80::250:56ff:feaf:2a21 dev eth0 lladdr 00:50:56:af:2a:21 STALE
2607:f380:80f:f830:192::1 dev eth0 lladdr 00:50:56:af:2a:21 STALE
fe80::f830:1 dev eth0 lladdr 24:e9:b3:24:fc:80 router STALE dev eth0 lladdr 24:e9:b3:24:fc:80 DELAY

Each line shows an IP address followed by the device that IP address is connected to and the state of the neighbor association. The last word is the reachability state of the host. Those states are defined in Section 7.3.2 of RFC 4861. If a host is in the “DELAY”, “STALE” or “REACHABLE” state Linux will attempt to contact the host directly. If a host is missing or in the “INCOMPLETE” OR “PROBE” states a new ARP request or ND request will be sent before Linux can attempt to contact the host.

Adding and Removing Neighbors

You can add a neighbor by simply attempting to contact them:

$ ping6 2607:f380:80f:f830:192::1

You can manually add them too. You shouldn’t do that unless you really know what you’re doing. You can remove neighbors, that will force Linux to redo ARP or ND with the command:

$ sudo ip neigh del <ip-address> dev <device>

The device must be specified because it’s possible to have the same IP address connected on two devices. This is especially common in IPv6 where link-local addresses are very common.


Every host makes routing decisions. Routing decisions are based on the host’s routing table. On Linux you can inspect the routing table with the command:

$ ip route

Here’s an example from my VM:

$ ip route
default via dev eth0 dev eth1 proto kernel scope link src dev eth0 proto kernel scope link src

The routing table has three routes. The first is the route to the default gateway. If an outgoing packet does not match any locally connected network the packet will be routed there. The next two entries show the directly connected networks. Here’s an example from my home machine that has two physical and several virtual interfaces:

$ ip route
default via dev br0 dev lxcbr0 proto kernel scope link src dev br0 proto kernel scope link src dev virbr3 proto kernel scope link src dev virbr4 proto kernel scope link src dev br0 scope link metric 1000 dev docker0 proto kernel scope link src dev virbr1 proto kernel scope link src dev virbr0 proto kernel scope link src dev virbr2 proto kernel scope link src

The “virbr” and “docker” interfaces are created for virtual machine networking. is an APIPA subnet. It’s primarily used for Windows interoperation. Unlike the ip neigh command the ip route command only shows IPv4 or IPv6, not both. To see your IPv6 routing table you use the command:

$ ip -6 route
2607:f380:80f:f830::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth1 proto kernel metric 256
default via fe80::f830:1 dev eth0 proto ra metric 1024 expires 1741sec hoplimit 64

Notice that in IPv6 there are matching routes to the same interface. Those are for link local addresses. You can manipulate the routing table. This is common if you’re setting up a router that needs static routes. It’s also common to manually set a default route. This is usually required if you setup networking manually (rather than using /etc/network/interfaces). An example of setting the network manually is:

$ sudo ifconfig eth0 netmaksk

Now you have the link up but Linux doesn’t know what your default route is. You tell it like this:

$ sudo ip route add default via dev eth0

After the default gateway is configured you should be able to communicate off of your local network. This page describes how to setup the Ethernet bridging functions of Linux. This makes Linux an Ethernet switch.


In order to configure bridging you need the ‘brctl’ command. The command has several sub-commands. For help run it with no arguments:

$ brctl
Usage: brctl [commands]
	addbr     	<bridge>		add bridge
	delbr     	<bridge>		delete bridge
	addif     	<bridge> <device>	add interface to bridge
	delif     	<bridge> <device>	delete interface from bridge
	hairpin   	<bridge> <port> {on|off}	turn hairpin on/off
	setageing 	<bridge> <time>		set ageing time
	setbridgeprio	<bridge> <prio>		set bridge priority
	setfd     	<bridge> <time>		set bridge forward delay
	sethello  	<bridge> <time>		set hello time
	setmaxage 	<bridge> <time>		set max message age
	setpathcost	<bridge> <port> <cost>	set path cost
	setportprio	<bridge> <port> <prio>	set port priority
	show      	[ <bridge> ]		show a list of bridges
	showmacs  	<bridge>		show a list of mac addrs
	showstp   	<bridge>		show bridge stp info
	stp       	<bridge> {on|off}	turn stp on/off

Most of the sub commands aren’t useful to us, they control the Spanning Tree Protocol (STP). You must leave STP off on our VMs otherwise VMware becomes upset. To see what bridges exist run this:

$ brctl show

By default Linux won’t create any bridges. A bridge interface is special. It’s used to bond one or more interfaces together. Bonded interfaces cannot have IP addresses of their own. Once your switch’s interfaces are bonded into bridge mode you have to set the IP address for the host on the bridge interface. Here’s how to turn your switch VM into a switch. Start by adding a bridge interface:

$ sudo brctl addbr br0

Now you should see the bridge interface in the list of Ethernet interfaces:

$ ifconfig br0

Once the bridge is established you add interfaces to it:

$ sudo brctl addif br0 eth192
$ sudo brctl addif br0 eth224
$ sudo brctl addif br0 ens256

Adding interfaces to the bridge doesn’t automatically bring them up. Make sure that they are up and none have an IP address assigned:

$ sudo ifconfig ens192 up
$ sudo ifconfig ens224 up
$ sudo ifconfig ens256 up

Your bridge doesn’t need an IP address to function but having an IP address is handy if you want to login to the machine remotely.

$ sudo ifconfig br0 netmask up

You don’t have a default route set yet. Set it to your router:

$ sudo ip route add default via br0

This doesn’t really matter yet because your router is not routing yet.

Permanent Bridge Configuration

In Ubuntu it’s easy to make your bridge configuration permanent. Add your bridge to the /etc/network/interfaces file. Here’s an example of how to create a bridge:

auto br0
iface br0 inet static
 dns-nameservers 2607:f380:80f:f425::252 and 2607:f380:80f:f425::253
 bridge_ports ens192 ens224 ens256

iface br0 inet6 auto

Be sure you DELETE the configuration of ens192!