Wednesday, December 19, 2012

Quick-n-dirty 'network' statement generator

I recently had a requirement to feed a lab router a bunch of BGP prefixes for some testing. The test required a non-overlapping, random-looking population of prefixes from several different eBGP neighbors.

I decided to bang together a little script to generate the prefixes in a format suitable for quagga's bgpd daemon, but wound up adding features throughout the day as I discovered new requirements. The end result was something that might be useful to somebody else.

Here I'm telling it to give me 5 network statements from within 10.0.0.0/8. The netmask will be 24 bits:
$ ./bgpdgen.pl -c 5 -n 10.0.0.0/8 -m 24
 network 10.160.244.0/24
 network 10.61.69.0/24
 network 10.13.1.0/24
 network 10.13.138.0/24
 network 10.50.109.0/24
Or I can have a range of bitmasks, this time the networks are packed much tighter and they'll be masked with 26 to 30 bits:
$ ./bgpdgen.pl -c 5 -n 10.0.0.0/24 -m 26-30
 network 10.0.0.224/28
 network 10.0.0.112/28
 network 10.0.0.0/26
 network 10.0.0.80/28
 network 10.0.0.24/29
Note however that the output above has a problem. 10.0.0.24/29 falls within 10.0.0.0/26. The -A flag (Avoid collisions) makes sure that doesn't happen:
$ ./bgpdgen.pl -c 5 -n 10.0.0.0/24 -m 26-30 -A
 network 10.0.0.128/26
 network 10.0.0.64/28
 network 10.0.0.224/28
 network 10.0.0.80/29
 network 10.0.0.192/28
In the cases where I'm adding network statements to some prior bgpd config file, I want to be able to avoid collisions with the existing configuration. Enter the -p flag, which reads in a prior bgpd configuration file and avoids collisions with any existing 'network' statements:
$ ./bgpdgen.pl -c 5 -n 10.0.0.0/24 -m 26-30 -A -p /usr/local/etc/bgpd.conf
 network 10.0.0.64/28
 network 10.0.0.176/28
 network 10.0.0.160/28
 network 10.0.0.24/29
 network 10.0.0.32/28
Finally, there's a flag to throw a route-map (or other text) onto the output:
$ ./bgpdgen.pl -c 5 -n 10.0.0.0/24 -m 26-30 -A -s " route-map RM_MYMAP"
 network 10.0.0.8/29 route-map RM_MYMAP
 network 10.0.0.64/28 route-map RM_MYMAP
 network 10.0.0.112/28 route-map RM_MYMAP
 network 10.0.0.128/26 route-map RM_MYMAP
 network 10.0.0.192/26 route-map RM_MYMAP
It's not very elegant, nor fast, but it got me through a problem and seemed worth sharing. Generating 1000 verified unique prefixes takes about 20 seconds on my laptop. The 2nd 1000 prefixes takes 100 seconds. And it gets slower from there. I'm sure I could do something speedier than using NetAddr::IP's within operator (over and over and over), but that will have to wait until I need to simulate a lot more unique addresses.

The script is here.