blob: 6348632a65c562d04709f83bd1e91c3c89ad01d6 [file] [log] [blame]
Flavio Castrocc38a542016-03-03 13:15:46 -08001#!/usr/bin/python
2
3import os
Flavio Castroab163ca2016-07-07 14:05:00 -07004import re
Flavio Castrocc38a542016-03-03 13:15:46 -08005from optparse import OptionParser
6
7from mininet.net import Mininet
8from mininet.topo import Topo
Flavio Castroe168f7f2016-06-24 15:53:12 -07009from mininet.node import RemoteController, UserSwitch, Host, OVSBridge
Flavio Castrocc38a542016-03-03 13:15:46 -080010from mininet.link import TCLink
11from mininet.log import setLogLevel
12from mininet.cli import CLI
13
Flavio Castrocc38a542016-03-03 13:15:46 -080014
Flavio Castro5608a392016-06-22 17:02:35 -070015# Parse command line options and dump results
16def parseOptions( ):
17 """Parse command line options"""
18 parser = OptionParser( )
19 parser.add_option( '--spine', dest='spine', type='int', default=2,
20 help='number of spine switches, default=2' )
21 parser.add_option( '--leaf', dest='leaf', type='int', default=2,
22 help='number of leaf switches, default=2' )
23 parser.add_option( '--fanout', dest='fanout', type='int', default=2,
24 help='number of hosts per leaf switch, default=2' )
25 parser.add_option( '--onos', dest='onos', type='int', default=0,
26 help='number of ONOS Instances, default=0, 0 means localhost, 1 will use OC1 and so on' )
Flavio Castroab163ca2016-07-07 14:05:00 -070027 parser.add_option( '--vlan', dest='vlan', type='int', default=-1,
28 help='vid of cross connect, default=-1, -1 means utilize default value' )
Flavio Castro5608a392016-06-22 17:02:35 -070029 (options, args) = parser.parse_args( )
Flavio Castrocc38a542016-03-03 13:15:46 -080030 return options, args
31
Flavio Castrocc38a542016-03-03 13:15:46 -080032
Flavio Castro5608a392016-06-22 17:02:35 -070033opts, args = parseOptions( )
34
35
36class LeafAndSpine( Topo ):
37 def __init__( self, spine=2, leaf=2, fanout=2, **opts ):
Flavio Castrocc38a542016-03-03 13:15:46 -080038 "Create Leaf and Spine Topo."
Flavio Castro5608a392016-06-22 17:02:35 -070039 Topo.__init__( self, **opts )
Flavio Castrocc38a542016-03-03 13:15:46 -080040 # Add spine switches
Flavio Castro5608a392016-06-22 17:02:35 -070041 spines = { }
Flavio Castroe168f7f2016-06-24 15:53:12 -070042 leafs = { }
Flavio Castro5608a392016-06-22 17:02:35 -070043 for s in range( spine ):
44 spines[ s ] = self.addSwitch( 'spine10%s' % (s + 1),
45 dpid="00000000010%s" % (s + 1) )
Flavio Castrocc38a542016-03-03 13:15:46 -080046 # Set link speeds to 100Mb/s
Flavio Castro5608a392016-06-22 17:02:35 -070047 linkopts = dict( bw=100 )
Flavio Castrocc38a542016-03-03 13:15:46 -080048 # Add Leaf switches
Flavio Castro5608a392016-06-22 17:02:35 -070049 for ls in range( leaf ):
Flavio Castroe168f7f2016-06-24 15:53:12 -070050 leafs[ ls ] = self.addSwitch( 'leaf%s' % (ls + 1),
51 dpid="00000000000%s" % (1 + ls) )
Flavio Castrocc38a542016-03-03 13:15:46 -080052 # Add hosts under a leaf, fanout hosts per leaf switch
Flavio Castro5608a392016-06-22 17:02:35 -070053 for f in range( fanout ):
54 host = self.addHost( 'h%s' % (ls * fanout + f + 1),
55 cls=IpHost,
56 ip='10.0.%s.%s/24' % ((ls + 1), (f + 1)),
57 gateway='10.0.%s.254' % (ls + 1) )
Flavio Castroe168f7f2016-06-24 15:53:12 -070058 self.addLink( host, leafs[ ls ], **linkopts )
59 # Add Xconnect simulation
Flavio Castroab163ca2016-07-07 14:05:00 -070060 if ls is 0:
61 in1 = self.addHost( 'in1', cls=IpHost, ip='10.0.1.9/24', mac="00:00:00:00:00:09" )
62 self.addLink( in1, leafs[0], **linkopts )
63 out1 = self.addHost( 'out1', cls=IpHost, ip='10.0.9.1/24', mac="00:00:00:00:09:01" )
64 self.addLink( out1, leafs[0], **linkopts )
65 br1 = self.addSwitch( 'br1', cls=OVSBridge )
66 self.addLink( br1, leafs[ 0 ], **linkopts )
67 vlans = [ 1, 5, 10 ]
68 for vid in vlans:
69 olt = self.addHost( 'olt%s' % vid, cls=VLANHost, vlan=vid,
70 ip="10.%s.0.1/24" % vid
71 , mac="00:00:%02d:00:00:01" % vid )
72 vsg = self.addHost( 'vsg%s' % vid, cls=VLANHost, vlan=vid,
73 ip="10.%s.0.2/24" % vid
74 , mac="00:00:%02d:00:00:02" % vid )
75 self.addLink( olt, leafs[ 0 ], **linkopts )
76 self.addLink( vsg, br1, **linkopts )
77 # Connect leaf to all spines
78 for s in range( spine ):
79 switch = spines[ s ]
80 self.addLink( leafs[ ls ], switch, **linkopts )
Flavio Castro5608a392016-06-22 17:02:35 -070081
82class IpHost( Host ):
Flavio Castroab163ca2016-07-07 14:05:00 -070083 def __init__( self, name, *args, **kwargs ):
Flavio Castro5608a392016-06-22 17:02:35 -070084 super( IpHost, self ).__init__( name, *args, **kwargs )
Flavio Castroab163ca2016-07-07 14:05:00 -070085 gateway = re.split('\.|/', kwargs['ip'])
86 gateway[3] = '254'
87 self.gateway = '.'.join(gateway[0:4])
Flavio Castrocc38a542016-03-03 13:15:46 -080088
Flavio Castro5608a392016-06-22 17:02:35 -070089 def config( self, **kwargs ):
90 Host.config( self, **kwargs )
91 mtu = "ifconfig " + self.name + "-eth0 mtu 1490"
92 self.cmd( mtu )
93 self.cmd( 'ip route add default via %s' % self.gateway )
Flavio Castrocc38a542016-03-03 13:15:46 -080094
Flavio Castro5608a392016-06-22 17:02:35 -070095
Flavio Castroe168f7f2016-06-24 15:53:12 -070096class VLANHost( Host ):
97 "Host connected to VLAN interface"
98
99 def config( self, vlan=100, **params ):
100 """Configure VLANHost according to (optional) parameters:
101 vlan: VLAN ID for default interface"""
102 r = super( VLANHost, self ).config( **params )
103 intf = self.defaultIntf( )
104 # remove IP from default, "physical" interface
105 self.cmd( 'ifconfig %s inet 0' % intf )
106 intf = self.defaultIntf( )
107 # create VLAN interface
108 self.cmd( 'vconfig add %s %d' % (intf, vlan) )
109 self.cmd( 'ifconfig %s.%d %s' % (intf, vlan, params[ 'ip' ]) )
110 # update the intf name and host's intf map
111 self.cmd( 'ifconfig %s.%d mtu 1480' % (intf, vlan) )
112 newName = '%s.%d' % (intf, vlan)
113 # update the (Mininet) interface to refer to VLAN interface name
114 intf.name = newName
115 # add VLAN interface to host's name to intf map
116 self.nameToIntf[ newName ] = intf
117
Flavio Castroab163ca2016-07-07 14:05:00 -0700118class ExtendedCLI( CLI ):
119 """
120 Extends mininet CLI with the following commands:
121 addvlanhost
122 addiphost
123 """
124 def do_addhost( self, line ):
125 #Parsing args from CLI
126 args = line.split( )
127 if len( args ) < 3 or len( args ) :
128 "usage: addhost hostname switch **params"
129 hostname, switch = args[0], args[1]
130 params = eval(line.split( ' ', 3 )[2])
131 if 'cls' in params:
132 params['cls'] = eval( params[ 'cls' ] )
133 if hostname in self.mn:
134 #error( '%s already exists!\n' % hostname )
135 return
136 if switch not in self.mn:
137 #error( '%s does not exist!\n' % switch )
138 return
139 print params
140 host = self.mn.addHostCfg( hostname, **params )
141 #switch.attach( link.intf2 )
142 #host.config()
143 link = self.mn.addLink( host, switch )
144 host.config(**params)
Flavio Castroe168f7f2016-06-24 15:53:12 -0700145
Flavio Castro5608a392016-06-22 17:02:35 -0700146def config( opts ):
Flavio Castrocc38a542016-03-03 13:15:46 -0800147 spine = opts.spine
148 leaf = opts.leaf
Flavio Castro5608a392016-06-22 17:02:35 -0700149 fanout = opts.fanout
Flavio Castroab163ca2016-07-07 14:05:00 -0700150 vlan = opts.vlan
Flavio Castro5608a392016-06-22 17:02:35 -0700151 controllers = [ os.environ[ 'OC%s' % i ] for i in
152 range( 1, opts.onos + 1 ) ] if (opts.onos) else [
153 '127.0.0.1' ]
Flavio Castroab163ca2016-07-07 14:05:00 -0700154 topo = LeafAndSpine( spine=spine, leaf=leaf, fanout=fanout, vlan=vlan )
Flavio Castro5608a392016-06-22 17:02:35 -0700155 net = Mininet( topo=topo, link=TCLink, build=False,
Flavio Castroe168f7f2016-06-24 15:53:12 -0700156 switch=UserSwitch, controller=None, autoSetMacs=True )
Flavio Castrocc38a542016-03-03 13:15:46 -0800157 i = 0
158 for ip in controllers:
Flavio Castro5608a392016-06-22 17:02:35 -0700159 net.addController( "c%s" % (i), controller=RemoteController, ip=ip )
Flavio Castrocc38a542016-03-03 13:15:46 -0800160 i += 1;
Flavio Castro5608a392016-06-22 17:02:35 -0700161 net.build( )
162 net.start( )
Flavio Castroab163ca2016-07-07 14:05:00 -0700163 out1 = net.get( 'out1' )
164 out1.cmd( "arp -s 10.0.9.254 10:00:00:00:00:01 -i %s " % (out1.intf()) )
165 CLI(net)
Flavio Castro5608a392016-06-22 17:02:35 -0700166 net.stop( )
167
Flavio Castrocc38a542016-03-03 13:15:46 -0800168
169if __name__ == '__main__':
Flavio Castro5608a392016-06-22 17:02:35 -0700170 setLogLevel( 'info' )
171 config( opts )
172 os.system( 'sudo mn -c' )