Configuring RIPd

In the guide below, we will demonstrate the use of ripd(8) using virtual machines inside vmm. This guide presumes you have practiced static routing.

In order to save on costs, we will be using the reserved IP address prefix 10/8 and then translate the range to a public IP address. Here is the topology:

    R1 <-----> Internet
 (10.1/16)
 10.2.1.1
    ^
    |
    |
   veb12
    |
    |
    V
 10.2.2.1
    R2  10.3.2.1 <-veb23-> 10.3.2.2 R3 10.5.3.1 <--veb35--> 10.5.5.1 R5
 (10.2/16)                       (10.3/16)      (10.5/16)
 10.4.2.1                        10.3.4.2
     ^                              ^
      \                            /
     veb24                        /
        \                       veb34
         \                      /
          ------>   R4    <-----
       10.4.4.1  (10.4/16)  10.3.4.1

Each R# in the above topology represents a router, which we simulate with a virtual machine with multiple interfaces. We will use veb(4) to link two routers together. Because there are multiple interfaces on each router, no three nodes will ever share the same broadcast domain. This ensures that routing will be required to traverse the network.

In the hypervisor, we configure the proper interfaces:

host# cat /etc/vm.conf
socket owner :vmdusers

switch "switch12" {
    locked lladdr
    interface veb12
}

switch "switch23" {
    locked lladdr
    interface veb23
}

switch "switch24" {
    locked lladdr
    interface veb24
}

switch "switch34" {
    locked lladdr
    interface veb34
}

switch "switch35" {
    locked lladdr
    interface veb35
}

bsdiso="/home/iso/install75.iso"

vm "r2" {
    owner $USER
    memory 1G
    cdrom $bsdiso
    disk /home/$USER/r2.qcow2 format qcow2
    interface tap22 {
        locked lladdr e8:8b:22:22:22:22
        switch "switch12"
    }
    interface tap32 {
        locked lladdr e8:8b:32:32:32:32
        switch "switch23"
    }
    interface tap42 {
        locked lladdr e8:8b:42:42:42:42
        switch "switch24"
    }
}

vm "r3" {
    owner $USER
    memory 1G
    cdrom $bsdiso
    disk /home/$USER/r3.qcow2 format qcow2
    interface tap322 { 
        locked lladdr e8:8b:32:02:32:02
        switch "switch23"
    }
    interface tap342 { 
        locked lladdr e8:8b:34:02:34:02
        switch "switch34"
    }
    interface tap53 {
        locked lladdr e8:8b:53:53:53:53
        switch "switch35"
    }
}

vm "r4" {
    owner $USER
    memory 1G
    cdrom $bsdiso
    disk /home/$USER/r4.qcow2 format qcow2
    interface tap44 { 
        switch "switch24"
        locked lladdr e8:8b:44:44:44:44
    }
    interface tap34 { 
        locked lladdr e8:8b:34:34:34:34
        switch "switch34"
    }
}

vm "r5" {
    owner $USER
    memory 1G
    cdrom $bsdiso
    disk /home/$USER/r5.qcow2 format qcow2
    interface tap55 { 
        switch "switch35"
        locked lladdr e8:8b:55:55:55:55
    }
}

NOTE: You will need to create necessary tap devices:

# cd /dev
# sh MAKEDEV tap{22,32,42,322,342,53,44,34,55}

We also create the qcow2 images and install the system:

$ vmctl create -s 20G $HOME/r2.qcow2
$ vmctl create -s 20G $HOME/r3.qcow2
$ vmctl create -s 20G $HOME/r4.qcow2
$ vmctl create -s 20G $HOME/r5.qcow2

In /etc/pf.conf?, we add a rule similar to the following for performing NAT:

match out on egress from !(egress:network) to any nat-to (egress:0)

Now all IPs from 10/8 will be NAT'd to our host's public IP address.

Then reload the ruleset:

host# pfctl -f /etc/pf.conf

We configure the proper interfaces on the host, sysctl.conf(5), and ripd.conf(5):

host# cat /etc/hostname.veb12
add vport21
up
host# cat /etc/hostname.veb23
up
host# cat /etc/hostname.veb24
up
host# cat /etc/hostname.veb34
up
host# cat /etc/hostname.veb35
up
host# cat /etc/hostname.vport11
inet 10.1.1.1 0xffff0000
up
host# cat /etc/hostname.vport21
inet 10.2.1.1 0xffff0000
up
host# cat /etc/ripd.conf
#       $OpenBSD: ripd.conf,v 1.1 2014/07/11 21:20:10 deraadt Exp $

redistribute static
redistribute connected
redistribute default
triggered-updates yes

interface if0
interface vport11
interface vport21
host# cat /etc/sysctl.conf
net.inet.ip.arpq.maxlen=1024
net.inet.ip.forwarding=1
net.inet6.ip6.forwarding=1
net.inet.ip.multipath=1

Replace if0 with your actual egress interface.

Next, we configure the virtual machines:

r2# cat /etc/hostname.vio0
inet 10.2.2.1 0xffff0000
up
r2# cat /etc/hostname.vio1
inet 10.3.2.1 0xffffff00
up
r2# cat /etc/hostname.vio2
inet 10.4.2.1 0xffff0000
up
r2# cat /etc/sysctl.conf
net.inet.ip.forwarding=1
net.inet.ip.multipath=1
r2# cat /etc/ripd.conf
#       $OpenBSD: ripd.conf,v 1.1 2014/07/11 21:20:10 deraadt Exp $

redistribute static
redistribute connected
redistribute default
triggered-updates yes

interface vio0
interface vio1
interface vio2

r3# cat /etc/hostname.vio0
inet 10.3.2.2 0xffffff00
up
r3# cat /etc/hostname.vio1
inet 10.3.4.2 0xffffff00
up
r3# cat /etc/hostname.vio2
inet 10.5.3.1 0xffff0000
up
r3# cat /etc/ripd.conf
#       $OpenBSD: ripd.conf,v 1.1 2014/07/11 21:20:10 deraadt Exp $

redistribute static
redistribute connected
redistribute default
triggered-updates yes

interface vio0
interface vio1
interface vio2
r3# cat /etc/sysctl.conf
net.inet.ip.forwarding=1
net.inet.ip.multipath=1

r4# cat /etc/hostname.vio0
inet 10.4.4.1 0xffff0000
up
r4# cat /etc/hostname.vio1
inet 10.3.4.1 0xffffff00
up
r4# cat /etc/ripd.conf
#       $OpenBSD: ripd.conf,v 1.1 2014/07/11 21:20:10 deraadt Exp $

redistribute static
redistribute connected
redistribute default
triggered-updates yes

interface vio0
interface vio1
r4# cat /etc/sysctl.conf
net.inet.ip.forwarding=1
net.inet.ip.multipath=1

r5# cat /etc/hostname.vio0
inet 10.5.5.1 0xffff0000
up
r5# cat /etc/ripd.conf
#       $OpenBSD: ripd.conf,v 1.1 2014/07/11 21:20:10 deraadt Exp $

redistribute static
redistribute connected
redistribute default
triggered-updates yes

interface vio0
r5# cat /etc/sysctl.conf
net.inet.ip.forwarding=1
net.inet.ip.multipath=1

Note: Be careful to input the correct subnet masks. Interfaces connecting to 10.3/16 have a longer mask.

When set up correctly, r5 will now be able to reach the Internet:

r5# ping 1.1.1.1 
PING 1.1.1.1 (1.1.1.1): 56 data bytes
64 bytes from 1.1.1.1: icmp_seq=0 ttl=53 time=4.181 ms
64 bytes from 1.1.1.1: icmp_seq=1 ttl=53 time=4.353 ms

Querying ripd

You can show the state of your current interfaces:

r3# ripctl show interfaces
Interface   Address  State      Linkstate  Uptime
vio2        10.5.3.1/16        ACTIVE     active     00:30:18
vio1        10.3.4.2/24        ACTIVE     active     00:30:18
vio0        10.3.2.2/24        ACTIVE     active     00:30:18

You can also show the routing information base:

r3# ripctl show rib
Destination          Nexthop           Cost
0.0.0.0/0            10.3.2.1          3
10.1.0.0/16          10.3.2.1          3
10.2.0.0/16          10.3.2.1          2
10.3.2.0/24          0.0.0.0           1
10.3.4.0/24          0.0.0.0           1
10.4.0.0/16          10.3.4.1          2
10.5.0.0/16          0.0.0.0           1

This shows us the cost (in our case, calculated based on the number of hops) to reach a network. The destination 0.0.0.0/0 represents the entire Internet. As nexthop, 0.0.0.0 represents this current host.

We can also show the forwarding information base (fib), which is what goes into the kernel routing tables:

r3# ripctl show fib 
flags: * = valid, R = RIP, C = Connected, S = Static
Flags  Destination          Nexthop          
*R     0.0.0.0/0            10.3.2.1
*R     10.1.0.0/16          10.3.2.1
*R     10.2.0.0/16          10.3.2.1
*C     10.3.2.0/24          link#1
*C     10.3.4.0/24          link#2
*R     10.4.0.0/16          10.3.4.1
*C     10.5.0.0/16          link#3
*R     104.167.241.48/29    10.3.2.1
*R     104.167.241.192/26   10.3.2.1
*S     127.0.0.0/8          127.0.0.1
*C     127.0.0.1/8          link#0
*      127.0.0.1/32         127.0.0.1
*S     224.0.0.0/4          127.0.0.1

Troubleshooting

Run ripctl to check if it shows neighbors:

# ripctl show neighbor                                                            
ID              State           Address         Iface     Uptime                    

If it does not show any neighbors, run it in debug mode with the verbose flag:

# ripd -dv

Wait 60 seconds. If you see the error message below:

recv_packet: cannot find a matching interface

It may indicate that the IP addresses / subnet masks on the interfaces do not match up correctly.