#!/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
import os

class UserNAT(NAT):
    """Disable NIC offloading such that this NAT can be used with user space OVS."""
    def __init(self, name, *args, **kwargs):
        super(UserNAT, self).__init__(name, *args, **kwargs)

    def config(self, **kwargs):
        super(UserNAT, self).config(**kwargs)
        disable_offload(self, self.localIntf)
        disable_offload(self, self.defaultIntf)

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 -4 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 RoutedHost6(Host):
    """Host that can be configured with multiple IP addresses."""
    def __init__(self, name, ips, gateway, *args, **kwargs):
        super(RoutedHost6, self).__init__(name, *args, **kwargs)

        self.ips = ips
        self.gateway = gateway

    def config(self, **kwargs):
        Host.config(self, **kwargs)

        self.cmd('ip -6 addr flush dev %s' % self.defaultIntf())
        for ip in self.ips:
            self.cmd('ip -6 addr add %s dev %s' % (ip, self.defaultIntf()))

        self.cmd('ip -6 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')
        self.cmd('sysctl net.ipv6.conf.all.forwarding=1')

        for intf, configs in self.interfaces.items():
            self.cmd('ip -4 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'
    logDir = '/var/log/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

        # Ensure required directories exist
        try:
            original_umask = os.umask(0)
            if (not os.path.isdir(QuaggaRouter.logDir)):
                os.makedirs(QuaggaRouter.logDir, 0777)
            if (not os.path.isdir(self.runDir)):
                os.makedirs(self.runDir, 0777)
        finally:
            os.umask(original_umask)

        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('log file %s/zebrad%s.log\n' % (QuaggaRouter.logDir, self.name))
        configFile.write('hostname zebra-%s\n' % self.name)
        configFile.write('password %s\n' % 'quagga')
        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)

        for interface in self.interfaces:
            disable_offload(self, interface)

    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('log file %s/bgpd%s.log' % (QuaggaRouter.logDir, self.qr.name))
        conf.writeLine('hostname bgp-%s' % self.qr.name);
        conf.writeLine('password %s' % 'quagga')
        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 -Z -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=0, 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)
    def config(self, **kwargs):
        super(BgpRouter, self).config(**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."""

    routerIdx = 1

    def __init__(self, onosIps, num=1, numBgpSpeakers=1, asNum=65000, externalOnos=True,
                 peerIntfConfig=None, withFpm=False):
        super(SdnAutonomousSystem, self).__init__(asNum, numBgpSpeakers)
        self.onosIps = onosIps
        self.num = num
        self.numBgpSpeakers = numBgpSpeakers
        self.peerIntfConfig = peerIntfConfig
        self.withFpm = withFpm
        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
                cpIpBase = self.num*10
                ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, cpIpBase+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():
            num = SdnAutonomousSystem.routerIdx
            SdnAutonomousSystem.routerIdx += 1
            name = 'bgp%s' % num

            cpIpBase = self.num*10
            ip = AutonomousSystem.getIthAddress(self.internalPeeringSubnet, cpIpBase+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' % num,
                         'ipAddrs' : nativeAddresses }]

                for vlan, addresses in router.interfaces[1].addressesByVlan.items():
                    eth1.append({'vlan':vlan,
                                'mac':'00:00:00:%02x:%02x:00' % (num, 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] if self.withFpm else None )

            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 )

# Disable NIC offloading
def disable_offload(host, intf):
    for attr in ["rx", "tx", "sg"]:
        cmd = "/sbin/ethtool --offload %s %s off" % (intf, attr)
        host.cmd(cmd)
