Fun with Linux – Quagga Routing

Standard

In this post I’ll be looking at using CumulusVX to doing some routing with a Cisco router, why Cumulus? It is a great Linux distribution / virtual switch that has a strong Quagga implementation.
This lab will have a single CumulusVX VM and a Cisco CSR since we are just kicking the tires.

The first thing to do in Cumulus is to edit the interfaces and add some IPs.

cumulus@cumulus:~$ sudo vi /etc/network/interfaces
 [sudo] password for cumulus:
 # This file describes the network interfaces available on your system
 # and how to activate them. For more information, see interfaces(5).
 
 source /etc/network/interfaces.d/*.intf
 
 # The loopback network interface
 auto lo
 iface lo inet loopback
 
 # The primary network interface
 auto eth0
 iface eth0 inet static
 address 10.10.2.181/24
 gateway 10.10.2.1
 
 auto swp1
 iface swp1 inet static
 address 10.100.1.254/24
 
 auto swp2
 iface swp2 inet static
 address 10.100.2.254/24
 
 auto swp3
 iface swp3 inet static
 address 10.100.3.254/24

Once the file is changed Cumulus has a nice ifreload -a command to immediately implement the changes.

cumulus@cumulus:~$ sudo ifreload -a 
 cumulus@cumulus:~$ ip addr show | grep inet | grep -v inet6
 inet 127.0.0.1/8 scope host lo
 inet 10.10.2.181/24 scope global eth0
 inet 10.100.1.254/24 scope global swp1
 inet 10.100.2.254/24 scope global swp2
 inet 10.100.3.254/24 scope global swp3

Quagga is Linux’s primary routing daemon (though a new fork is picking up steam), it is preinstalled in Cumulus which is nice but you can install it on any linux system. By default all routing is disabled when Quagga is first installed.

cumulus@cumulus:~$ cat /etc/quagga/daemons 
 # This file tells the quagga package which daemons to start.
 #
 # Entries are in the format: <daemon>=(no|no|priority)
 # 0, "no" = disabled
 # 1, "no" = highest priority
 # 2 .. 10 = lower priorities
 # Read /usr/share/doc/quagga/README.Debian for details.
 #
 # Sample configurations for these daemons can be found in
 # /usr/share/doc/quagga/examples/.
 #
 # ATTENTION:
 #
 # When activation a daemon at the first time, a config file, even if it is
 # empty, has to be present *and* be owned by the user and group "quagga", else
 # the daemon will not be started by /etc/init.d/quagga. The permissions should
 # be u=rw,g=r,o=.
 # When using "vtysh" such a config file is also needed. It should be owned by
 # group "quaggavty" and set to ug=rw,o= though. Check /etc/pam.d/quagga, too.
 #
 # The watchquagga daemon is always started. Per default in monitoring-only but
 # that can be changed via /etc/quagga/debian.conf.
 #
 zebra=no
 bgpd=no
 ospfd=no
 ospf6d=no
 ripd=no
 ripngd=no
 isisd=no
 pimd=no
 ldpd=no
I'll use the ​sed command to enable all processes though you can selectively say yes to what you want if you need to.
 
 cumulus@cumulus:~$ sudo sed -i 's/no/yes/g' /etc/quagga/daemons 
 cumulus@cumulus:~$ cat /etc/quagga/daemons 
 # This file tells the quagga package which daemons to start.
 #
 # Entries are in the format: <daemon>=(yes|yes|priority)
 # 0, "yes" = disabled
 # 1, "yes" = highest priority
 # 2 .. 10 = lower priorities
 # Read /usr/share/doc/quagga/README.Debian for details.
 #
 # Sample configurations for these daemons can be found in
 # /usr/share/doc/quagga/examples/.
 #
 # ATTENTION:
 #
 # When activation a daemon at the first time, a config file, even if it is
 # empty, has to be present *and* be owned by the user and group "quagga", else
 # the daemon will yest be started by /etc/init.d/quagga. The permissions should
 # be u=rw,g=r,o=.
 # When using "vtysh" such a config file is also needed. It should be owned by
 # group "quaggavty" and set to ug=rw,o= though. Check /etc/pam.d/quagga, too.
 #
 # The watchquagga daemon is always started. Per default in monitoring-only but
 # that can be changed via /etc/quagga/debian.conf.
 #
 zebra=yes
 bgpd=yes
 ospfd=yes
 ospf6d=yes
 ripd=yes
 ripngd=yes
 isisd=yes
 pimd=yes
 ldpd=yes

Once that is done we can start the Quagga process.

cumulus@cumulus:~$ sudo service quagga start

We can access the Quagga shell with the vtysh command, once we are in the CLI is very Cisco like so you can change the Quagga hostname etc as you would on a router.

cumulus@cumulus:~$ sudo vtysh
 
 Hello, this is Quagga (version 1.0.0+cl3u11).
 Copyright 1996-2005 Kunihiro Ishiguro, et al.
 
 cumulus# 
 cumulus# conf t
 cumulus(config)# hostname CSW01

Routing wise Quagga supports everything except for EIGRP (for now) which makes Quagga a decent option for labs to complement your Cisco training.

CSW01(config)# router ?
 bgp BGP information
 isis ISO IS-IS
 ospf Start OSPF configuration
 ospf6 Open Shortest Path First (OSPF) for IPv6
 rip RIP
 ripng RIPng

Setting up OSPF is similar to Cisco except that you don’t need to specify a process id and you can use slash notation for your network statements.

CSW01(config)# router ospf 
 CSW01(config-router)# network 10.10.2.0/24 
 area Set the OSPF area ID
 CSW01(config-router)# network 10.10.2.0/24 area 
 <0-4294967295> OSPF area ID as a decimal value
 A.B.C.D OSPF area ID in IP address format
 CSW01(config-router)# network 10.10.2.0/24 area 0
 CSW01(config-router)# exit

We still have our trusty do command if we want to run some verification commands.

CSW01(config)# do show run
 Building configuration...
 
 Current configuration:
 !
 hostname CSW01
 username cumulus nopassword
 !
 service integrated-vtysh-config
 !
 log file /var/log/quagga/quagga.log
 !
 log timestamp precision 6
 !
 router ospf
 network 10.10.2.0/24 area 0.0.0.0
 !
 line vty
 !

Show commands are largely the same

CSW01(config)# do show ip ospf neighbor 
 
 Neighbor ID Pri State Dead Time Address Interface RXmtL RqstL DBsmL
 10.10.2.249 1 Full/DR 37.350s 10.10.2.249 eth0:10.10.2.181 0 0 0

Let’s configure BGP on the CSR side

 CSR01(config)#interface Loopback0
 CSR01(config-if)# ip address 192.168.0.1 255.255.255.0
 CSR01(config-if)#interface Loopback1
 CSR01(config-if)# ip address 192.168.1.1 255.255.255.0
 CSR01(config-if)#interface Loopback2
 CSR01(config-if)# ip address 192.168.2.1 255.255.255.0
 CSR01(config-if)#interface Loopback3
 CSR01(config-if)# ip address 192.168.3.1 255.255.255.0
 
 CSR01(config)#router bgp 200
 CSR01(config-router)# bgp log-neighbor-changes
 CSR01(config-router)# redistribute connected
 CSR01(config-router)# neighbor 10.10.2.181 remote-as 100
 CSR01(config-router)# neighbor 10.10.2.181 ebgp-multihop 255

The BGP output is pretty much the same as on a Cisco.

CSW01(config-router)# do show ip bgp
 BGP table version is 7, local router ID is 10.100.3.254
 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
 i internal, r RIB-failure, S Stale, R Removed
 Origin codes: i - IGP, e - EGP, ? - incomplete
 
 Network Next Hop Metric LocPrf Weight Path
 *> 10.0.123.0/24 10.10.13.171 0 0 200 ?
 *> 10.10.13.0/24 10.10.13.171 0 0 200 ?
 *> 192.168.0.0 10.10.13.171 0 0 200 ?
 *> 192.168.1.0 10.10.13.171 0 0 200 ?
 *> 192.168.2.0 10.10.13.171 0 0 200 ?
 *> 192.168.3.0 10.10.13.171 0 0 200 ?
 *> 200.0.1.0 10.10.13.171 0 0 200 ?
 
 Displayed 7 out of 7 total prefixes

CSW01(config-router)# do show bgp ipv4 unicast 
 BGP table version is 7, local router ID is 10.100.3.254
 Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
 i internal, r RIB-failure, S Stale, R Removed
 Origin codes: i - IGP, e - EGP, ? - incomplete
 
 Network Next Hop Metric LocPrf Weight Path
 *> 10.0.123.0/24 10.10.13.171 0 0 200 ?
 *> 10.10.13.0/24 10.10.13.171 0 0 200 ?
 *> 192.168.0.0 10.10.13.171 0 0 200 ?
 *> 192.168.1.0 10.10.13.171 0 0 200 ?
 *> 192.168.2.0 10.10.13.171 0 0 200 ?
 *> 192.168.3.0 10.10.13.171 0 0 200 ?
 *> 200.0.1.0 10.10.13.171 0 0 200 ?

Lastly the routing table is the same except for it has a couple of linux specific route types and is missing some of Cisco’s more advanced types.

CSW01(config-router)# do show ip route
 Codes: K - kernel route, C - connected, S - static, R - RIP,
 O - OSPF, I - IS-IS, B - BGP, P - PIM, T - Table, v - VNC,
 V - VPN,
 > - selected route, * - FIB route
 
 K>* 0.0.0.0/0 via 10.10.2.1, eth0
 B> 10.0.123.0/24 [20/0] via 10.10.13.171 (recursive), 00:04:26
 * via 10.10.2.249, eth0, 00:04:26
 O 10.0.123.0/24 [110/1011] via 10.10.2.249, eth0, 00:06:28
 O>* 10.1.2.0/24 [110/12] via 10.10.2.249, eth0, 00:06:28
 O 10.10.2.0/24 [110/10] is directly connected, eth0, 00:06:33
 C>* 10.10.2.0/24 is directly connected, eth0
 O>* 10.10.11.0/24 [110/11] via 10.10.2.249, eth0, 00:06:28
 B 10.10.13.0/24 [20/0] via 10.10.13.171 inactive, 00:04:26
 O>* 10.10.13.0/24 [110/11] via 10.10.2.249, eth0, 00:06:28
 O>* 10.10.14.0/24 [110/11] via 10.10.2.249, eth0, 00:06:28
 O>* 10.10.255.254/32 [110/12] via 10.10.2.249, eth0, 00:06:28
 C>* 10.100.1.0/24 is directly connected, swp1
 C>* 10.100.2.0/24 is directly connected, swp2
 C>* 10.100.3.0/24 is directly connected, swp3
 B> 192.168.0.0/24 [20/0] via 10.10.13.171 (recursive), 00:04:26
 * via 10.10.2.249, eth0, 00:04:26
 B> 192.168.1.0/24 [20/0] via 10.10.13.171 (recursive), 00:04:26
 * via 10.10.2.249, eth0, 00:04:26
 B> 192.168.2.0/24 [20/0] via 10.10.13.171 (recursive), 00:04:26
 * via 10.10.2.249, eth0, 00:04:26
 B> 192.168.3.0/24 [20/0] via 10.10.13.171 (recursive), 00:04:26
 * via 10.10.2.249, eth0, 00:04:26
 B> 200.0.1.0/24 [20/0] via 10.10.13.171 (recursive), 00:04:26
 * via 10.10.2.249, eth0, 00:04:2
We can also filter by protocol as well. 
 
 CSW01(config)# do show ip route ospf
 Codes: K - kernel route, C - connected, S - static, R - RIP,
 O - OSPF, I - IS-IS, B - BGP, P - PIM, T - Table, v - VNC,
 V - VPN,
 > - selected route, * - FIB route
 
 O>* 10.0.123.0/24 [110/1011] via 10.10.2.249, eth0, 00:01:03
 O>* 10.1.2.0/24 [110/12] via 10.10.2.249, eth0, 00:01:03
 O 10.10.2.0/24 [110/10] is directly connected, eth0, 00:01:08
 O>* 10.10.11.0/24 [110/11] via 10.10.2.249, eth0, 00:01:03
 O>* 10.10.13.0/24 [110/11] via 10.10.2.249, eth0, 00:01:03
 O>* 10.10.14.0/24 [110/11] via 10.10.2.249, eth0, 00:01:03
 O>* 10.10.255.254/32 [110/12] via 10.10.2.249, eth0, 00:01:03

Exiting out of Cumulus (don’t forget to save!) we can see linux OS learns the routes so it can use them.

cumulus@cumulus:~$ ip route show
 default via 10.10.2.1 dev eth0 
 10.0.123.0/24 via 10.10.2.249 dev eth0 proto bgp metric 20 
 10.1.2.0/24 via 10.10.2.249 dev eth0 proto ospf metric 20 
 10.10.2.0/24 dev eth0 proto kernel scope link src 10.10.2.181 
 10.10.11.0/24 via 10.10.2.249 dev eth0 proto ospf metric 20 
 10.10.13.0/24 via 10.10.2.249 dev eth0 proto ospf metric 20 
 10.10.14.0/24 via 10.10.2.249 dev eth0 proto ospf metric 20 
 10.10.255.254 via 10.10.2.249 dev eth0 proto ospf metric 20 
 10.100.1.0/24 dev swp1 proto kernel scope link src 10.100.1.254 
 10.100.2.0/24 dev swp2 proto kernel scope link src 10.100.2.254 
 10.100.3.0/24 dev swp3 proto kernel scope link src 10.100.3.254 
 192.168.0.0/24 via 10.10.2.249 dev eth0 proto bgp metric 20 
 192.168.1.0/24 via 10.10.2.249 dev eth0 proto bgp metric 20 
 192.168.2.0/24 via 10.10.2.249 dev eth0 proto bgp metric 20 
 192.168.3.0/24 via 10.10.2.249 dev eth0 proto bgp metric 20 
 200.0.1.0/24 via 10.10.2.249 dev eth0 proto bgp metric 20

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.