#!/usr/bin/env python

from mininet.cli import CLI
from mininet.node import Link, Host
from mininet.net import Mininet
from mininet.node import RemoteController
from mininet.term import makeTerm
from functools import partial

class VLANHost( Host ):
    "Host connected to VLAN interface"

    def config( self, vlan=10, **params ):
        """Configure VLANHost according to (optional) parameters:
           vlan: VLAN ID for default interface"""

        r = super( VLANHost, self ).config( **params )

        intf = self.defaultIntf()
        # remove IP from default, "physical" interface
        self.cmd( 'ifconfig %s inet 0' % intf )
        # create VLAN interface
        self.cmd( 'vconfig add %s %d' % ( intf, vlan ) )
        # assign the host's IP to the VLAN interface
        self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) )
        # update the intf name and host's intf map
        newName = '%s.%d' % ( intf, vlan )
        # update the (Mininet) interface to refer to VLAN interface name
        intf.name = newName
        # add VLAN interface to host's name to intf map
        self.nameToIntf[ newName ] = intf

        return r

if '__main__' == __name__:
    net = Mininet(autoSetMacs=True)

    s1 = net.addSwitch('s1')
    s2 = net.addSwitch('s2')
    s3 = net.addSwitch('s3')
    s4 = net.addSwitch('s4')

    vpls1h1 = net.addHost('vpls1h1', cls=VLANHost, vlan=10)
    vpls1h2 = net.addHost('vpls1h2', cls=VLANHost, vlan=10)
    vpls1h3 = net.addHost('vpls1h3', cls=VLANHost, vlan=20)
    vpls2h1 = net.addHost('vpls2h1', cls=VLANHost, vlan=30)
    vpls2h2 = net.addHost('vpls2h2', cls=VLANHost, vlan=40)

    net.addLink(s1, vpls1h1)
    net.addLink(s4, vpls1h2)
    net.addLink(s3, vpls1h3)
    net.addLink(s4, vpls2h1)
    net.addLink(s2, vpls2h2)
    net.addLink(s1, s4)
    net.addLink(s1, s2)
    net.addLink(s2, s4)
    net.addLink(s2, s3)
    net.addLink(s3, s4)
    c1 = RemoteController('c1', '10.0.2.15', 6653)
    net.build()
    c1.start()

    s1.start([c1])
    s2.start([c1])
    s3.start([c1])
    s4.start([c1])

    CLI(net)

    net.stop()