HIGUCHI Yuta
Committed by Yuta HIGUCHI

ONOS-3422 inter-domain cross connect

- Add network configuration about cross connect port for CO-ONOS
- revised metro.py requires ecord.co app after
  (Change-Id: I3892e780bc6550f8a8d8be622b9fee5322c1dab5)
  to be loaded.
- stop using onos-topo-cfg to send netcfg

Change-Id: Ie90e69c4134d1f71893bf43ee6c290bdbd273aeb
...@@ -83,6 +83,7 @@ public class BasicNetworkConfigs { ...@@ -83,6 +83,7 @@ public class BasicNetworkConfigs {
83 return new BasicLinkConfig(); 83 return new BasicLinkConfig();
84 } 84 }
85 }, 85 },
86 + // TODO move this optical specific configuration out to optical app
86 new ConfigFactory<ConnectPoint, OpticalPortConfig>(CONNECT_POINT_SUBJECT_FACTORY, 87 new ConfigFactory<ConnectPoint, OpticalPortConfig>(CONNECT_POINT_SUBJECT_FACTORY,
87 OpticalPortConfig.class, 88 OpticalPortConfig.class,
88 "optical") { 89 "optical") {
......
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 2
3 +import json
4 +
3 from mininet.net import Mininet 5 from mininet.net import Mininet
4 from mininet.node import UserSwitch, DefaultController, RemoteController, Host 6 from mininet.node import UserSwitch, DefaultController, RemoteController, Host
5 from mininet.topo import Topo 7 from mininet.topo import Topo
6 -from mininet.log import setLogLevel, info 8 +from mininet.log import setLogLevel, info, error, warn
7 from mininet.cli import CLI 9 from mininet.cli import CLI
8 from mininet.link import OVSIntf 10 from mininet.link import OVSIntf
11 +from mininet.util import quietRun
9 12
10 from opticalUtils import LINCSwitch, LINCLink 13 from opticalUtils import LINCSwitch, LINCLink
11 14
...@@ -33,6 +36,7 @@ class Domain(object): ...@@ -33,6 +36,7 @@ class Domain(object):
33 self.__ctrls[name] = args if args else {} 36 self.__ctrls[name] = args if args else {}
34 return name 37 return name
35 38
39 + # Note: This method will return the name of the swich, not the switch object
36 def addSwitch(self, name, **args): 40 def addSwitch(self, name, **args):
37 self.__switches[name] = args if args else {} 41 self.__switches[name] = args if args else {}
38 return name 42 return name
...@@ -90,10 +94,12 @@ class OpticalDomain(Domain): ...@@ -90,10 +94,12 @@ class OpticalDomain(Domain):
90 oean = { "optical.regens": 0 } 94 oean = { "optical.regens": 0 }
91 self.addSwitch('OE%s' % i, dpid='0000ffffffffff0%s' % i, annotations=oean, cls=LINCSwitch) 95 self.addSwitch('OE%s' % i, dpid='0000ffffffffff0%s' % i, annotations=oean, cls=LINCSwitch)
92 96
97 + # ROADM port number OE"1" -> OE'2' = "1"'2'00
98 + # leaving port number up to 100 open for use by Och port
93 an = { "durable": "true" } 99 an = { "durable": "true" }
94 - self.addLink('OE1', 'OE2', port1=50, port2=30, annotations=an, cls=LINCLink) 100 + self.addLink('OE1', 'OE2', port1=1200, port2=2100, annotations=an, cls=LINCLink)
95 - self.addLink('OE2', 'OE3', port1=50, port2=30, annotations=an, cls=LINCLink) 101 + self.addLink('OE2', 'OE3', port1=2300, port2=3200, annotations=an, cls=LINCLink)
96 - self.addLink('OE3', 'OE1', port1=50, port2=30, annotations=an, cls=LINCLink) 102 + self.addLink('OE3', 'OE1', port1=3100, port2=1300, annotations=an, cls=LINCLink)
97 103
98 class FabricDomain(Domain): 104 class FabricDomain(Domain):
99 """ 105 """
...@@ -139,10 +145,11 @@ class FabricDomain(Domain): ...@@ -139,10 +145,11 @@ class FabricDomain(Domain):
139 domains to the core. name: the UserSwitch to connect the OVS to. 145 domains to the core. name: the UserSwitch to connect the OVS to.
140 """ 146 """
141 self.__tether = self.addSwitch(tname, dpid=tdpid) 147 self.__tether = self.addSwitch(tname, dpid=tdpid)
148 + # Note: OVS port number '1' reserved for port facing the fabric
142 self.addLink(tname, name, port1=1) 149 self.addLink(tname, name, port1=1)
143 150
144 def getTether(self): 151 def getTether(self):
145 - """ get connection point of this fabric to the core """ 152 + """ get the switch name of this fabric facing the core """
146 return self.__tether 153 return self.__tether
147 154
148 155
...@@ -157,10 +164,6 @@ class IpHost(Host): ...@@ -157,10 +164,6 @@ class IpHost(Host):
157 self.cmd(mtu) 164 self.cmd(mtu)
158 self.cmd('ip route add default via %s' % self.gateway) 165 self.cmd('ip route add default via %s' % self.gateway)
159 166
160 -# fixed port numbers for attachment points (APs) between CORD and metro domains
161 -OVS_AP=2
162 -OE_AP=10
163 -
164 def setup(argv): 167 def setup(argv):
165 domains = [] 168 domains = []
166 ctlsets = sys.argv[1:] 169 ctlsets = sys.argv[1:]
...@@ -180,6 +183,16 @@ def setup(argv): ...@@ -180,6 +183,16 @@ def setup(argv):
180 for j in range (len(ctls)): 183 for j in range (len(ctls)):
181 f.addController('c%s%s' % (i,j), controller=RemoteController, ip=ctls[j]) 184 f.addController('c%s%s' % (i,j), controller=RemoteController, ip=ctls[j])
182 185
186 + # netcfg for each domains
187 + # Note: Separate netcfg for domain0 is created in opticalUtils
188 + domainCfgs = []
189 + for i in range (0,len(ctlsets)):
190 + cfg = {}
191 + cfg['devices'] = {}
192 + cfg['ports'] = {}
193 + cfg['links'] = {}
194 + domainCfgs.append(cfg)
195 +
183 # make/setup Mininet object 196 # make/setup Mininet object
184 net = Mininet() 197 net = Mininet()
185 for d in domains: 198 for d in domains:
...@@ -187,10 +200,19 @@ def setup(argv): ...@@ -187,10 +200,19 @@ def setup(argv):
187 d.injectInto(net) 200 d.injectInto(net)
188 201
189 # connect COs to core - sort of hard-wired at this moment 202 # connect COs to core - sort of hard-wired at this moment
203 + # adding cross-connect links
190 for i in range(1,len(domains)): 204 for i in range(1,len(domains)):
191 - an = { "bandwidth": 100000, "durable": "true" } 205 + # add 10 cross-connect links between domains
206 + xcPortNo=2
207 + ochPortNo=10
208 + for j in range(0, 10):
209 + an = { "bandwidth": 10, "durable": "true" }
192 net.addLink(domains[i].getTether(), d0.getSwitches('OE%s' % i), 210 net.addLink(domains[i].getTether(), d0.getSwitches('OE%s' % i),
193 - port1=OVS_AP, port2=OE_AP, speed=10000, annotations=an, cls=LINCLink) 211 + port1=xcPortNo+j, port2=ochPortNo+j, speed=10000, annotations=an, cls=LINCLink)
212 +
213 + xcId = 'of:' + domains[i].getSwitches(name=domains[i].getTether()).dpid + '/' + str(xcPortNo+j)
214 + ochId = 'of:' + d0.getSwitches('OE%s' % i).dpid + '/' + str(ochPortNo+j)
215 + domainCfgs[i]['ports'][xcId] = {'cross-connect': {'remote': ochId}}
194 216
195 # fire everything up 217 # fire everything up
196 net.build() 218 net.build()
...@@ -203,6 +225,22 @@ def setup(argv): ...@@ -203,6 +225,22 @@ def setup(argv):
203 cfgnet.controllers = d0.getControllers() 225 cfgnet.controllers = d0.getControllers()
204 LINCSwitch.bootOE(cfgnet, d0.getSwitches()) 226 LINCSwitch.bootOE(cfgnet, d0.getSwitches())
205 227
228 + # send netcfg json to each CO-ONOS
229 + for i in range(1,len(domains)):
230 + info('*** Pushing Topology.json to CO-ONOS %d\n' % i)
231 + filename = 'Topology%d.json' % i
232 + with open(filename, 'w') as outfile:
233 + json.dump(domainCfgs[i], outfile, indent=4, separators=(',', ': '))
234 +
235 + output = quietRun('%s/tools/test/bin/onos-netcfg %s %s &'\
236 + % (LINCSwitch.onosDir,
237 + domains[i].getControllers()[0].ip,
238 + filename), shell=True)
239 + # successful output contains the two characters '{}'
240 + # if there is more output than this, there is an issue
241 + if output.strip('{}'):
242 + warn('***WARNING: Could not push topology file to ONOS: %s\n' % output)
243 +
206 CLI(net) 244 CLI(net)
207 net.stop() 245 net.stop()
208 LINCSwitch.shutdownOE() 246 LINCSwitch.shutdownOE()
......
...@@ -287,8 +287,8 @@ class LINCSwitch(OpticalSwitch): ...@@ -287,8 +287,8 @@ class LINCSwitch(OpticalSwitch):
287 with open("crossConnect.json", 'w') as fd: 287 with open("crossConnect.json", 'w') as fd:
288 json.dump(crossConnectJSON, fd, indent=4, separators=(',', ': ')) 288 json.dump(crossConnectJSON, fd, indent=4, separators=(',', ': '))
289 info('*** Pushing crossConnect.json to ONOS\n') 289 info('*** Pushing crossConnect.json to ONOS\n')
290 - output = quietRun('%s/tools/test/bin/onos-topo-cfg %s\ 290 + output = quietRun('%s/tools/test/bin/onos-netcfg %s\
291 - Topology.json network/configuration/' % (self.onosDir, self.controllers[ 0 ].ip), shell=True) 291 + Topology.json' % (self.onosDir, self.controllers[ 0 ].ip), shell=True)
292 292
293 def stop_oe(self): 293 def stop_oe(self):
294 ''' 294 '''
...@@ -455,21 +455,20 @@ class LINCSwitch(OpticalSwitch): ...@@ -455,21 +455,20 @@ class LINCSwitch(OpticalSwitch):
455 opener.open(url) 455 opener.open(url)
456 urllib2.install_opener(opener) 456 urllib2.install_opener(opener)
457 # focus on just checking the state of devices we're interested in 457 # focus on just checking the state of devices we're interested in
458 - devlist = map( lambda x: x['uri'], devices ) 458 + # expected devices availability map
459 + devMap = dict.fromkeys(map( lambda x: x['uri'], devices ), False)
459 while True: 460 while True:
460 response = json.load(urllib2.urlopen(url)) 461 response = json.load(urllib2.urlopen(url))
461 devs = response.get('devices') 462 devs = response.get('devices')
462 463
463 - # Wait for all devices to be registered. There is a chance that this is only a subgraph. 464 + # update availability map
464 - if (len(devices) == len(devs)):
465 -
466 - # Wait for all devices to available
467 - available = True
468 for d in devs: 465 for d in devs:
469 - if d['id'] in devlist: 466 + if devMap.has_key(d['id']):
470 - available &= d['available'] 467 + devMap[d['id']] = d['available']
471 - if available: 468 +
472 - break 469 + # Check if all devices we're interested became available
470 + if all(devMap.viewvalues()):
471 + break;
473 472
474 if (time >= TIMEOUT): 473 if (time >= TIMEOUT):
475 error('***ERROR: ONOS did not register devices within %s seconds\n' % TIMEOUT) 474 error('***ERROR: ONOS did not register devices within %s seconds\n' % TIMEOUT)
...@@ -480,7 +479,7 @@ class LINCSwitch(OpticalSwitch): ...@@ -480,7 +479,7 @@ class LINCSwitch(OpticalSwitch):
480 479
481 info('*** Pushing Topology.json to ONOS\n') 480 info('*** Pushing Topology.json to ONOS\n')
482 for index in range(len(LINCSwitch.controllers)): 481 for index in range(len(LINCSwitch.controllers)):
483 - output = quietRun('%s/tools/test/bin/onos-topo-cfg %s Topology.json network/configuration/ &'\ 482 + output = quietRun('%s/tools/test/bin/onos-netcfg %s Topology.json &'\
484 % (LINCSwitch.onosDir, LINCSwitch.controllers[ index ].ip), shell=True) 483 % (LINCSwitch.onosDir, LINCSwitch.controllers[ index ].ip), shell=True)
485 # successful output contains the two characters '{}' 484 # successful output contains the two characters '{}'
486 # if there is more output than this, there is an issue 485 # if there is more output than this, there is an issue
......