4. Transferring dynamic routes into a static routing table

4.1. Copying routes into a static table

For the route-based QoS to work, the dynamic routes must be connected to the iproute2 filters. There exists a route filter that classifies packets based on the destination's route realm value. The route-based packet classification would be very easy if Zebra allowed setting a route id, but this feature doesn't exist. The solution is to take the routing table, copy the entries to a separate table, set a realm value for each in the process, then add a lookup rule for the new routing table. The route filter can then see the id of the destination route and classify outbound packets accordingly.

4.2. Example route refresh script

Example 3. refresh-qos-routes.pl


#!/usr/bin/perl -w

use strict;
use Getopt::Long;
Getopt::Long::Configure('bundling', 'no_ignore_case');

my(
$opt_v,$verbose,
$opt_q,$quiet
);

#------------------------------------------------------------#
# read conf file arg
GetOptions (
	"v|verbose"		=> \$opt_v,
	"q|quiet"		=> \$opt_q
);

($opt_v) ? ($verbose = 1) : ($verbose = 0);
($opt_q) ? ($quiet = 1) : ($quiet = 0);

my $ipcmd = "/sbin/ip";
my $table = 99;

#------------------------------------------------------------#

if ($> != 0) {
        print "Only root can modify routes.  Exiting.\n";
        exit 1;
}

#------------------------------------------------------------#

# remove lookup rule
if (!$quiet) {
	print "Removing lookup rule for table $table\n";
}
system("$ipcmd rule del table $table");

# flush the existing routing table
if (!$quiet) {
	print "Flushing entries in table $table\n";
}
system("$ipcmd route flush table $table");

# grab the routes out of the main table
if (!$quiet) {
	print "Reading entries for main routing table\n";
}
my @list = `$ipcmd route show table main | grep 'zebra'`;

# add the I2 routes 
if (!$quiet) {
	print "Adding I2 entries to table $table\n";
}
my $item;
for $item (@list) {
	chomp($item);
	if ($verbose) {
		print "Adding: $item\n";
	}
	system("$ipcmd route add table $table $item realm 5");
}

# add static routes
if (!$quiet) {
	print "Adding static routes\n";
}
system("$ipcmd route add table $table 192.168.2.0/8 via 192.168.254.254 dev eth0 proto zebra realm 2");
system("$ipcmd route add table $table 192.168.3.0/8 via 192.168.254.254 dev eth0 proto zebra realm 2");
system("$ipcmd route add table $table 192.168.4.0/8 via 192.168.254.254 dev eth0 proto zebra realm 2");

# add lookup rule
system("$ipcmd rule add table $table");

      

4.3. Route realm value

This script could be run every few hours via cron. In the example scenario, the Internet2 BGP routes do not change very frequently, so the lack of dynamic updates is not a serious problem. The key task of the script is to take routes added to the main routing table by Zebra and copy them into the routing table 99 with a route realm value of 5. Local network destinations are served by manually adding routes to cover local subnets. These receive a realm value of 2. The realm values are arbitrary, but it's important that the numbers match here and in the packet filter configuration described below.

[ route realm explanation]