Migrating from Quagga to Bird

For example, I will give a simple example of migrating from Quagga to Bird, that is, how can you install Quagga and Bird at the same time on the same server, and switch between them.

Let’s say Quagga (BGP) is installed on the Ubuntu server with one uplink from which only the default route comes.

First, let’s look at Quagga statistics, what neighbors are, what routes are exported/imported from them, to make sure that the current Quagga configuration is correct, since based on it, you will need to write configurations in Bird:

telnet localhost 2605
sh ip bgp neighbors
sh ip bgp
sh ip bgp neighbors advertised-routes
sh ip bgp neighbors received-routes

Suppose that only the default route comes from the uplink, and we only announce our network X.X.X.0/23 to the uplink.

Let’s look at the configuration files in the /etc/quagga/ directory, let’s say the zebra.conf file says:

! Zebra configuration saved from vty
!   2017/07/21 13:13:02
hostname XXX
password XXX
enable password XXX
log file /var/log/zebra.log errors
interface lo
interface ens2
 ipv6 nd suppress-ra
interface ens4
 ipv6 nd suppress-ra
ip route X.X.X.128/25 Null0 254
ip forwarding
line vty

From the main one, this is the ip route X.X.X.128/25 Null0 254 command, which I added to the blackhole network for NAT so as not to assign IP addresses for NAT on the network interface. In bird, I added the entire network to the blackhole, which should be announced by uplink.

Let’s look at the main BGP configuration file /etc/quagga/bgpd.conf

! Zebra configuration saved from vty
!   2017/07/21 13:13:02
password XXX
enable password XXX
log file /var/log/quagga/bgpd.log
service advanced-vty
bgp multiple-instance
bgp config-type cisco
router bgp XXXXX
 no synchronization
 bgp router-id X.X.X.X
 bgp log-neighbor-changes
 network X.X.X.0 mask
 aggregate-address X.X.X.0 summary-only
 redistribute connected
 timers bgp 20 60
 neighbor X.X.X.X remote-as XXXXX
 neighbor X.X.X.X description ixnfo.com
 neighbor X.X.X.X soft-reconfiguration inbound
 neighbor X.X.X.X route-map IXNFO-OUT out
 no auto-summary
access-list 10 permit
access-list 10 deny any
access-list all permit any
ip prefix-list DEFAULT-ONLY seq 10 deny ge 1 le 31
ip prefix-list DEFAULT-ONLY seq 20 permit
ip prefix-list DEFAULT-STRIP seq 10 deny
ip prefix-list DEFAULT-STRIP seq 20 permit ge 1 le 31
ip prefix-list TO-IXNFO seq 10 permit X.X.X.0/23
ip prefix-list TO-IXNFO seq 100 deny le 32
route-map IXNFO-IN permit 10
 match ip address prefix-list all
route-map IXNFO-OUT permit 10
 match ip address prefix-list TO-IXNFO
line vty
 access-class 10
 no login

Install bird, temporarily stop its processes and create a directory for logs:

apt install bird
systemctl stop bird.service
systemctl stop bird6.service
mkdir /var/log/bird/
touch /var/log/bird/bird.log
chown -R bird:bird /var/log/bird/

Let’s create a configuration file:

mv /etc/bird/bird.conf /etc/bird/bird.conf.original
nano /etc/bird/bird.conf

Here is a simple content example:

router id X.X.X.1;
define my_as=XXXXX;

log "/var/log/bird/bird.log" { trace, info, remote, warning, error, auth, fatal, bug };
timeformat base     iso long;
timeformat log      iso long;
timeformat protocol iso long;
timeformat route    iso long;

protocol direct {
        interface "ens2";

protocol kernel {
        persist off;
        scan time 20;
        import all;
        export none;

protocol device {
        scan time 60;

protocol static {
preference 254;
route X.X.X.0/23 blackhole;

filter PROVIDER1_IN {
if net ~ [ ] then {
   else reject;

protocol bgp IXNFO_COM {
    debug { states, events };
    router id X.X.X.X;
    description "IXNFO_COM";
    local as my_as;
    neighbor X.X.X.X as XXXXX;

    hold time 60;
    startup hold time 60;
    connect retry time 120;
    keepalive time 20;
    start delay time 5;
    error wait time 60, 300;
    error forget time 300;
    next hop self;
    path metric 1;
    default bgp_med 0;

    source address X.X.X.X;
    export where net = X.X.X.0/23;
    import filter PROVIDER1_IN;

When the BIRD configuration is ready, stop Quagga:

service zebra stop
service zebra status
service bgpd stop
service bgpd status

And run BIRD:

service bird start
service bird status

Let’s connect to the BIRD console, make sure that the BGP session is established and see the statistics:

show protocols
show protocols all
show route
show route all
show static
show route export IXNFO.COM

Activate BIRD IPv4 autostart at operating system startup:

systemctl is-enabled bird.service
systemctl is-enabled bird6.service
systemctl enable bird.service
systemctl disable bird6.service

Deactivate Quagga autorun:

systemctl is-enabled zebra.service
systemctl is-enabled bgpd.service
systemctl disable zebra.service
systemctl disable bgpd.service

systemctl is-enabled ospfd
systemctl is-enabled ospf6d
systemctl is-enabled ripd
systemctl is-enabled ripngd
systemctl is-enabled isisd

Let’s review and comment out the extra stuff in /etc/quagga/zebra.conf, because bird will run zebra.

See also my articles:
Installing and configuring BIRD (BGP)
Installing Quagga on Ubuntu Server 18

Join the Conversation

1 Comment

Leave a Reply

  1. The lack of proper route aggregation management in BIRD, as well as the lack of complete protocol implementation for other protocols, is what pushed us to abandon BIRD and move towards FRR. In the example you give, you replace aggregate-address X.X.X.0 summary-only with blackholing X.X.X.0/23. Note that blackholing a prefix to generate a route in the routing table has nothing to do with what the real route aggregation protocol does. The real route aggregation protocol provides a level of automation. That automation creates an aggregated prefix in the route table only if at least one sub-prefix is available. For instance, if you want to create route aggregation for, you need at least to be available in the routing table.