diff --git a/routinglib.py b/routinglib.py
new file mode 100644
index 0000000..b2e8245
--- /dev/null
+++ b/routinglib.py
@@ -0,0 +1,638 @@
+#!/usr/bin/python
+
+"""
+Libraries for creating L3 topologies with routing protocols.
+"""
+
+from mininet.node import Host, OVSBridge
+from mininet.nodelib import NAT
+from mininet.log import info, debug, error
+from mininet.cli import CLI
+from ipaddress import ip_network, ip_address, ip_interface
+
+class RoutedHost(Host):
+    """Host that can be configured with multiple IP addresses."""
+    def __init__(self, name, ips, gateway, *args, **kwargs):
+        super(RoutedHost, self).__init__(name, *args, **kwargs)
+
+        self.ips = ips
+        self.gateway = gateway
+
+    def config(self, **kwargs):
+        Host.config(self, **kwargs)
+
+        self.cmd('ip addr flush dev %s' % self.defaultIntf())
+        for ip in self.ips:
+            self.cmd('ip addr add %s dev %s' % (ip, self.defaultIntf()))
+
+        self.cmd('ip route add default via %s' % self.gateway)
+
+class Router(Host):
+    
+    """An L3 router.
+    Configures the Linux kernel for L3 forwarding and supports rich interface
+    configuration of IP addresses, MAC addresses and VLANs."""
+    
+    def __init__(self, name, interfaces, *args, **kwargs):
+        super(Router, self).__init__(name, **kwargs)
+
+        self.interfaces = interfaces
+        
+    def config(self, **kwargs):
+        super(Host, self).config(**kwargs)
+        
+        self.cmd('sysctl net.ipv4.ip_forward=1')
+        self.cmd('sysctl net.ipv4.conf.all.rp_filter=0')
+
+        for intf, configs in self.interfaces.items():
+            self.cmd('ip addr flush dev %s' % intf)
+            self.cmd( 'sysctl net.ipv4.conf.%s.rp_filter=0' % intf )
+            
+            if not isinstance(configs, list):
+                configs = [configs]
+                
+            for attrs in configs:
+                # Configure the vlan if there is one    
+                if 'vlan' in attrs:
+                    vlanName = '%s.%s' % (intf, attrs['vlan'])
+                    self.cmd('ip link add link %s name %s type vlan id %s' % 
+                             (intf, vlanName, attrs['vlan']))
+                    self.cmd('ip link set %s up' % vlanName)
+                    addrIntf = vlanName
+                else:
+                    addrIntf = intf
+                    
+                # Now configure the addresses on the vlan/native interface
+                if 'mac' in attrs:
+                    self.cmd('ip link set %s down' % addrIntf)
+                    self.cmd('ip link set %s address %s' % (addrIntf, attrs['mac']))
+                    self.cmd('ip link set %s up' % addrIntf)
+                for addr in attrs['ipAddrs']:
+                    self.cmd('ip addr add %s dev %s' % (addr, addrIntf))
+
+class QuaggaRouter(Router):
+    
+    """Runs Quagga to create a router that can speak routing protocols."""
+    
+    binDir = '/usr/lib/quagga'
+    
+    def __init__(self, name, interfaces,
+                 defaultRoute=None,
+                 zebraConfFile=None,
+                 protocols=[],
+                 fpm=None,
+                 runDir='/var/run/quagga', *args, **kwargs):
+        super(QuaggaRouter, self).__init__(name, interfaces, **kwargs)
+        
+        self.protocols = protocols
+        self.fpm = fpm
+        
+        for p in self.protocols:
+            p.setQuaggaRouter(self)
+        
+        self.runDir = runDir
+        self.defaultRoute = defaultRoute
+        
+        self.zebraConfFile = zebraConfFile
+        if (self.zebraConfFile is None):
+            self.zebraConfFile = '%s/zebrad%s.conf' % (self.runDir, self.name)
+            self.generateZebra()
+            
+        self.socket = '%s/zebra%s.api' % (self.runDir, self.name)
+        
+        self.zebraPidFile = '%s/zebra%s.pid' % (self.runDir, self.name)
+
+    def generateZebra(self):
+        configFile = open(self.zebraConfFile, 'w+')
+        configFile.write('hostname zebra-%s\n' % self.name)
+        configFile.write('password %s\n' % 'hello')
+        if (self.fpm is not None):
+            configFile.write('fpm connection ip %s port 2620' % self.fpm)
+        configFile.close()
+
+    def config(self, **kwargs):
+        super(QuaggaRouter, self).config(**kwargs)
+
+        self.cmd('%s/zebra -d -f %s -z %s -i %s'
+                 % (QuaggaRouter.binDir, self.zebraConfFile, self.socket, self.zebraPidFile))
+        
+        for p in self.protocols:
+            p.config(**kwargs)
+        
+        if self.defaultRoute:
+            self.cmd('ip route add default via %s' % self.defaultRoute)
+        
+    def terminate(self, **kwargs):
+        self.cmd("ps ax | grep '%s' | awk '{print $1}' | xargs kill" 
+                 % (self.socket))
+        
+        for p in self.protocols:
+            p.terminate(**kwargs)
+
+        super(QuaggaRouter, self).terminate()
+        
+class Protocol(object):
+    
+    """Base abstraction of a protocol that the QuaggaRouter can run."""
+        
+    def setQuaggaRouter(self, qr):
+        self.qr = qr
+        
+    def config(self, **kwargs):
+        pass
+    
+    def terminate(self, **kwargs):
+        pass
+        
+class BgpProtocol(Protocol):
+    
+    """Configures and runs the BGP protocol in Quagga."""
+    
+    def __init__(self, configFile=None, asNum=None, neighbors=[], routes=[], *args, **kwargs):
+        self.configFile = configFile
+        
+        self.asNum = asNum
+        self.neighbors = neighbors
+        self.routes = routes
+            
+    def config(self, **kwargs):
+        if self.configFile is None:
+            self.configFile = '%s/bgpd%s.conf' % (self.qr.runDir, self.qr.name)
+            self.generateConfig()
+        
+        bgpdPidFile = '%s/bgpd%s.pid' % (self.qr.runDir, self.qr.name)
+        
+        self.qr.cmd('%s/bgpd -d -f %s -z %s -i %s'
+                     % (QuaggaRouter.binDir, self.configFile, self.qr.socket, bgpdPidFile))
+        
+    def generateConfig(self):
+        conf = ConfigurationWriter(self.configFile)
+                    
+        def getRouterId(interfaces):
+            intfAttributes = interfaces.itervalues().next()
+            print intfAttributes
+            if isinstance(intfAttributes, list):
+                # Try use the first set of attributes, but if using vlans they might not have addresses
+                intfAttributes = intfAttributes[1] if not intfAttributes[0]['ipAddrs'] else intfAttributes[0]
+            return intfAttributes['ipAddrs'][0].split('/')[0]
+        
+        conf.writeLine('hostname bgp-%s' % self.qr.name);
+        conf.writeLine('password %s' % 'sdnip')
+        conf.writeLine('!')
+        conf.writeLine('router bgp %s' % self.asNum)
+        
+        conf.indent()
+        
+        conf.writeLine('bgp router-id %s' % getRouterId(self.qr.interfaces))
+        conf.writeLine('timers bgp %s' % '3 9')
+        conf.writeLine('!')
+        
+        for neighbor in self.neighbors:
+            conf.writeLine('neighbor %s remote-as %s' % (neighbor['address'], neighbor['as']))
+            conf.writeLine('neighbor %s ebgp-multihop' % neighbor['address'])
+            conf.writeLine('neighbor %s timers connect %s' % (neighbor['address'], '5'))
+            conf.writeLine('neighbor %s advertisement-interval %s' % (neighbor['address'], '5'))
+            if 'port' in neighbor:
+                conf.writeLine('neighbor %s port %s' % (neighbor['address'], neighbor['port']))
+            conf.writeLine('!')
+            
+        for route in self.routes:
+            conf.writeLine('network %s' % route)
+        
+        conf.close()
+    
+class OspfProtocol(Protocol):
+    
+    """Configures and runs the OSPF protocol in Quagga."""
+    
+    def __init__(self, configFile=None, *args, **kwargs):
+        self.configFile = configFile
+            
+    def config(self, **kwargs):
+        if self.configFile is None:
+            self.configFile = '%s/ospfd%s.conf' % (self.qr.runDir, self.qr.name)
+            self.generateConfig()
+        
+        ospfPidFile = '%s/ospf%s.pid' % (self.qr.runDir, self.qr.name)
+        
+        self.qr.cmd('%s/ospfd -d -f %s -z %s -i %s'
+                     % (QuaggaRouter.binDir, self.configFile, self.qr.socket, ospfPidFile))
+        
+    def generateConfig(self):
+        conf = ConfigurationWriter(self.configFile)
+            
+        def getRouterId(interfaces):
+            intfAttributes = interfaces.itervalues().next()
+            print intfAttributes
+            if isinstance(intfAttributes, list):
+                # Try use the first set of attributes, but if using vlans they might not have addresses
+                intfAttributes = intfAttributes[1] if not intfAttributes[0]['ipAddrs'] else intfAttributes[0]
+            return intfAttributes['ipAddrs'][0].split('/')[0]
+        
+        conf.writeLine('hostname ospf-%s' % self.qr.name);
+        conf.writeLine('password %s' % 'hello')
+        conf.writeLine('!')
+        conf.writeLine('router ospf')
+        
+        conf.indent()
+        
+        conf.writeLine('ospf router-id %s' % getRouterId(self.qr.interfaces))
+        conf.writeLine('!')
+        
+        for name, intf in self.qr.interfaces.items():
+            for ip in intf['ipAddrs']:
+                conf.writeLine('network %s area 0' % ip)
+            #if intf['ipAddrs'][0].startswith('192.168'):
+            #    writeLine(1, 'passive-interface %s' % name)
+            
+        conf.close()
+        
+class PimProtocol(Protocol):
+    
+    """Configures and runs the PIM protcol in Quagga."""
+    
+    def __init__(self, configFile=None, *args, **kwargs):
+        self.configFile = configFile
+        
+    def config(self, **kwargs):
+        pimPidFile = '%s/pim%s.pid' % (self.qr.runDir, self.qr.name)
+        
+        self.qr.cmd('%s/pimd -d -f %s -z %s -i %s'
+                     % (QuaggaRouter.binDir, self.configFile, self.qr.socket, pimPidFile))
+        
+class ConfigurationWriter(object):
+    
+    """Utility class for writing a configuration file."""
+    
+    def __init__(self, filename):
+        self.filename = filename
+        self.indentValue = 0;
+        
+        self.configFile = open(self.filename, 'w+')
+    
+    def indent(self):
+        self.indentValue += 1
+        
+    def unindent(self):
+        if (self.indentValue > 0):
+            self.indentValue -= 1
+            
+    def write(self, string):
+        self.configFile.write(string)
+    
+    def writeLine(self, string):
+        intentStr = ''
+        for _ in range(0, self.indentValue):
+            intentStr += '  '
+        self.write('%s%s\n' % (intentStr, string))
+        
+    def close(self):
+        self.configFile.close()
+
+#Backward compatibility for BGP-only use case
+class BgpRouter(QuaggaRouter):
+    
+    """Quagga router running the BGP protocol."""
+    
+    def __init__(self, name, interfaces,
+                 asNum, neighbors, routes=[],
+                 defaultRoute=None,
+                 quaggaConfFile=None,
+                 zebraConfFile=None,
+                 *args, **kwargs):
+        bgp = BgpProtocol(configFile=quaggaConfFile, asNum=asNum, neighbors=neighbors, routes=routes)
+        
+        super(BgpRouter, self).__init__(name, interfaces, 
+                                        zebraConfFile=zebraConfFile,
+                                        defaultRoute=defaultRoute,
+                                        protocols=[bgp],
+                                        *args, **kwargs)
+        
+class RouterData(object):
+    
+    """Internal data structure storing information about a router."""
+    
+    def __init__(self, index):
+        self.index = index;
+        self.neighbors = []
+        self.interfaces = {}
+        self.switches = []
+        
+    def addNeighbor(self, theirAddress, theirAsNum):
+        self.neighbors.append({'address':theirAddress.ip, 'as':theirAsNum})
+    
+    def addInterface(self, intf, vlan, address):
+        if not intf in self.interfaces:
+            self.interfaces[intf] = InterfaceData(intf)
+            
+        self.interfaces[intf].addAddress(vlan, address)
+        
+    def setSwitch(self, switch):
+        self.switches.append(switch)
+        
+class InterfaceData(object):
+    
+    """Internal data structure storing information about an interface."""
+    
+    def __init__(self, number):
+        self.number = number
+        self.addressesByVlan = {}
+        
+    def addAddress(self, vlan, address):
+        if not vlan in self.addressesByVlan:
+            self.addressesByVlan[vlan] = []
+            
+        self.addressesByVlan[vlan].append(address.with_prefixlen)
+        
+class RoutedNetwork(object):
+    
+    """Creates a host behind a router. This is common boilerplate topology
+    segment in routed networks."""
+    
+    @staticmethod
+    def build(topology, router, hostName, networks):
+        # There's a convention that the router's addresses are already set up,
+        # and it has the last address in the network.
+        
+        def getFirstAddress(network):
+            return '%s/%s' % (network[1], network.prefixlen)
+        
+        defaultRoute = AutonomousSystem.getLastAddress(networks[0]).ip
+        
+        host = topology.addHost(hostName, cls=RoutedHost,
+                                ips=[getFirstAddress(network) for network in networks],
+                                gateway=defaultRoute)
+
+        topology.addLink(router, host)
+
+class AutonomousSystem(object):
+    
+    """Base abstraction of an autonomous system, which implies some internal
+    topology and connections to other topology elements (switches/other ASes)."""
+    
+    psIdx = 1
+    
+    def __init__(self, asNum, numRouters):
+        self.asNum = asNum
+        self.numRouters = numRouters
+        self.routers = {}
+        for i in range(1, numRouters + 1):
+            self.routers[i] = RouterData(i)
+            
+        self.routerNodes={}
+            
+        self.neighbors=[]
+        self.vlanAddresses={}
+        
+    def peerWith(self, myRouter, myAddress, theirAddress, theirAsNum, intf=1, vlan=None):
+        router = self.routers[myRouter]
+        
+        router.addInterface(intf, vlan, myAddress)
+        router.addNeighbor(theirAddress, theirAsNum)
+
+    def getRouter(self, i):
+        return self.routerNodes[i]
+
+    @staticmethod
+    def generatePeeringAddresses():
+        network = ip_network(u'10.0.%s.0/24' % AutonomousSystem.psIdx)
+        AutonomousSystem.psIdx += 1
+        
+        return ip_interface('%s/%s' % (network[1], network.prefixlen)), \
+            ip_interface('%s/%s' % (network[2], network.prefixlen))
+        
+    @staticmethod
+    def addPeering(as1, as2, router1=1, router2=1, intf1=1, intf2=1, address1=None, address2=None, useVlans=False):
+        vlan = AutonomousSystem.psIdx if useVlans else None
+        
+        if address1 is None or address2 is None:
+            (address1, address2) = AutonomousSystem.generatePeeringAddresses()
+            
+        as1.peerWith(router1, address1, address2, as2.asNum, intf=intf1, vlan=vlan)
+        as2.peerWith(router2, address2, address1, as1.asNum, intf=intf2, vlan=vlan)
+    
+    @staticmethod
+    def getLastAddress(network):
+        return ip_interface(network.network_address + network.num_addresses - 2)
+    
+    @staticmethod
+    def getIthAddress(network, i):
+        return ip_interface('%s/%s' % (network[i], network.prefixlen))
+
+class BasicAutonomousSystem(AutonomousSystem):
+
+    """Basic autonomous system containing one host and one or more routers
+    which peer with other ASes."""
+
+    def __init__(self, num, routes, numRouters=1):
+        super(BasicAutonomousSystem, self).__init__(65000+num, numRouters)
+        self.num = num
+        self.routes = routes
+        
+    def addLink(self, switch, router=1):
+        self.routers[router].setSwitch(switch)
+
+    def build(self, topology):
+        self.addRouterAndHost(topology)
+
+    def addRouterAndHost(self, topology):
+        
+        # TODO implementation is messy and needs to be cleaned up
+        
+        intfs = {}
+        
+        router = self.routers[1]
+        for i, router in self.routers.items():
+        
+            #routerName = 'r%i%i' % (self.num, i)
+            routerName = 'r%i' % self.num
+            if not i==1:
+                routerName += ('%i' % i)
+                
+            hostName = 'h%i' % self.num
+        
+            for j, interface in router.interfaces.items():
+                nativeAddresses = interface.addressesByVlan.pop(None, [])
+                peeringIntf = [{'mac' : '00:00:%02x:00:%02x:%02x' % (self.num, i, j),
+                               'ipAddrs' : nativeAddresses}]
+                
+                for vlan, addresses in interface.addressesByVlan.items():
+                    peeringIntf.append({'vlan':vlan,
+                                        'mac':'00:00:%02x:%02x:%02x:%02x' % (self.num, vlan, i, j),
+                                        'ipAddrs':addresses})
+                    
+                intfs.update({'%s-eth%s' % (routerName, j-1) : peeringIntf})
+            
+            # Only add the host to the first router for now
+            if i==1:
+                internalAddresses=[]
+                for route in self.routes:
+                    internalAddresses.append('%s/%s' % (AutonomousSystem.getLastAddress(route).ip, route.prefixlen))
+        
+                internalIntf = {'ipAddrs' : internalAddresses}
+        
+                # This is the configuration of the next interface after all the peering interfaces
+                intfs.update({'%s-eth%s' % (routerName, len(router.interfaces.keys())) : internalIntf})
+    
+            routerNode = topology.addHost(routerName,  
+                                  asNum=self.asNum, neighbors=router.neighbors,
+                                  routes=self.routes,
+                                  cls=BgpRouter, interfaces=intfs)
+            
+            self.routerNodes[i] = routerNode
+
+            for switch in router.switches:
+                topology.addLink(switch, routerNode)
+
+            # Only add the host to the first router for now
+            if i==1:
+                defaultRoute = internalAddresses[0].split('/')[0]
+        
+                host = topology.addHost(hostName, cls=RoutedHost,
+                                        ips=[self.getFirstAddress(route) for route in self.routes],
+                                        gateway=defaultRoute)
+        
+                topology.addLink(routerNode, host)
+
+    #def getLastAddress(self, network):
+    #    return ip_address(network.network_address + network.num_addresses - 2)
+    
+    def getFirstAddress(self, network):
+        return '%s/%s' % (network[1], network.prefixlen)
+
+# TODO fix this AS - doesn't currently work
+class RouteServerAutonomousSystem(BasicAutonomousSystem):
+
+    def __init__(self, routerAddress, *args, **kwargs):
+        BasicAutonomousSystem.__init__(self, *args, **kwargs)
+
+        self.routerAddress = routerAddress
+
+    def build(self, topology, connectAtSwitch):
+
+        switch = topology.addSwitch('as%isw' % self.num, cls=OVSBridge)
+
+        self.addRouterAndHost(topology, self.routerAddress, switch)
+
+        rsName = 'rs%i' % self.num
+        routeServer = topology.addHost(rsName,
+                                       self.asnum, self.neighbors,
+                                       cls=BgpRouter,
+                                       interfaces={'%s-eth0' % rsName : {'ipAddrs':[self.peeringAddress]}})
+
+        topology.addLink(routeServer, switch)
+        topology.addLink(switch, connectAtSwitch)
+        
+class SdnAutonomousSystem(AutonomousSystem):
+    
+    """Runs the internal BGP speakers needed for ONOS routing apps like
+    SDN-IP."""
+    
+    def __init__(self, onosIps, numBgpSpeakers=1, asNum=65000, externalOnos=True, peerIntfConfig=None):
+        super(SdnAutonomousSystem, self).__init__(asNum, numBgpSpeakers)
+        self.onosIps = onosIps
+        self.numBgpSpeakers = numBgpSpeakers
+        self.peerIntfConfig = peerIntfConfig
+        self.externalOnos= externalOnos
+        self.internalPeeringSubnet = ip_network(u'1.1.1.0/24')
+        
+        for router in self.routers.values():
+            # Add iBGP sessions to ONOS nodes
+            for onosIp in onosIps:
+                router.neighbors.append({'address':onosIp, 'as':asNum, 'port':2000})
+                
+            # Add iBGP sessions to other BGP speakers
+            for i, router2 in self.routers.items():
+                if router == router2:
+                    continue
+                ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, 10+i)
+                router.neighbors.append({'address':ip.ip, 'as':asNum})
+        
+    def build(self, topology, connectAtSwitch, controlSwitch):
+        
+        natIp = AutonomousSystem.getLastAddress(self.internalPeeringSubnet)
+        
+        for i, router in self.routers.items():
+            name = 'bgp%s' % i
+            
+            ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, 10+i)
+            eth0 = { 'ipAddrs' : [ str(ip) ] }
+            if self.peerIntfConfig is not None:
+                eth1 = self.peerIntfConfig
+            else:
+                nativeAddresses = router.interfaces[1].addressesByVlan.pop(None, [])
+                eth1 = [{ 'mac':'00:00:00:00:00:%02x' % i, 
+                         'ipAddrs' : nativeAddresses }]
+                
+                for vlan, addresses in router.interfaces[1].addressesByVlan.items():
+                    eth1.append({'vlan':vlan,
+                                'mac':'00:00:00:%02x:%02x:00' % (i, vlan),
+                                'ipAddrs':addresses})
+            
+            
+            intfs = { '%s-eth0' % name : eth0,
+                      '%s-eth1' % name : eth1 }
+            
+            bgp = topology.addHost( name, cls=BgpRouter, asNum=self.asNum, 
+                                    neighbors=router.neighbors,
+                                    interfaces=intfs, 
+                                    defaultRoute=str(natIp.ip),
+                                    fpm=self.onosIps[0] )
+            
+            topology.addLink( bgp, controlSwitch )
+            topology.addLink( bgp, connectAtSwitch )
+            
+            
+        if self.externalOnos:
+            nat = topology.addHost('nat', cls=NAT, 
+                                   ip='%s/%s' % (natIp.ip, self.internalPeeringSubnet.prefixlen), 
+                                   subnet=str(self.internalPeeringSubnet), inNamespace=False);
+            topology.addLink(controlSwitch, nat)
+
+        
+def generateRoutes(baseRange, numRoutes, subnetSize=None):
+    baseNetwork = ip_network(baseRange)
+    
+    # We need to get at least 2 addresses out of each subnet, so the biggest
+    # prefix length we can have is /30
+    maxPrefixLength = baseNetwork.max_prefixlen - 2
+    
+    if subnetSize is not None:
+        return list(baseNetwork.subnets(new_prefix=subnetSize))
+    
+    trySubnetSize = baseNetwork.prefixlen + 1
+    while trySubnetSize <= maxPrefixLength and \
+            len(list(baseNetwork.subnets(new_prefix=trySubnetSize))) < numRoutes:
+        trySubnetSize += 1
+        
+    if trySubnetSize > maxPrefixLength:
+        raise Exception("Can't get enough routes from input parameters")
+    
+    return list(baseNetwork.subnets(new_prefix=trySubnetSize))[:numRoutes]
+    
+class RoutingCli( CLI ):
+    
+    """CLI command that can bring a host up or down. Useful for simulating router failure."""
+    
+    def do_host( self, line ):
+        args = line.split()
+        if len(args) != 2:
+            error( 'invalid number of args: host <host name> {up, down}\n' )
+            return
+        
+        host = args[ 0 ]
+        command = args[ 1 ]
+        if host not in self.mn or self.mn.get( host ) not in self.mn.hosts:
+            error( 'invalid host: %s\n' % args[ 1 ] )
+        else:
+            if command == 'up':
+                op = 'up'
+            elif command == 'down':
+                op = 'down'
+            else:
+                error( 'invalid command: host <host name> {up, down}\n' )
+                return
+
+            for intf in self.mn.get( host ).intfList( ):
+                intf.link.intf1.ifconfig( op )
+                intf.link.intf2.ifconfig( op )
