Nikhil Cheerla
Committed by Gerrit Code Review

OECF removed working

Change-Id: I178a227fedacb4efc8669c839042d952f4efd670
1 -<?xml version="1.0" encoding="UTF-8"?>
2 -<!--
3 - ~ Copyright 2014 Open Networking Laboratory
4 - ~
5 - ~ Licensed under the Apache License, Version 2.0 (the "License");
6 - ~ you may not use this file except in compliance with the License.
7 - ~ You may obtain a copy of the License at
8 - ~
9 - ~ http://www.apache.org/licenses/LICENSE-2.0
10 - ~
11 - ~ Unless required by applicable law or agreed to in writing, software
12 - ~ distributed under the License is distributed on an "AS IS" BASIS,
13 - ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 - ~ See the License for the specific language governing permissions and
15 - ~ limitations under the License.
16 - -->
17 -<project xmlns="http://maven.apache.org/POM/4.0.0"
18 - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19 - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
20 - <modelVersion>4.0.0</modelVersion>
21 -
22 - <parent>
23 - <groupId>org.onosproject</groupId>
24 - <artifactId>onos-apps</artifactId>
25 - <version>1.3.0-SNAPSHOT</version>
26 - <relativePath>../pom.xml</relativePath>
27 - </parent>
28 -
29 - <artifactId>onos-app-oecfg</artifactId>
30 - <packaging>jar</packaging>
31 -
32 - <description>Standalone utility for converting ONOS JSON config to OE-Linc JSON config</description>
33 -
34 - <dependencies>
35 - <dependency>
36 - <groupId>com.fasterxml.jackson.core</groupId>
37 - <artifactId>jackson-databind</artifactId>
38 - <scope>compile</scope>
39 - </dependency>
40 - <dependency>
41 - <groupId>com.fasterxml.jackson.core</groupId>
42 - <artifactId>jackson-annotations</artifactId>
43 - <scope>compile</scope>
44 - </dependency>
45 - </dependencies>
46 -
47 - <build>
48 - <plugins>
49 - <plugin>
50 - <groupId>org.apache.maven.plugins</groupId>
51 - <artifactId>maven-shade-plugin</artifactId>
52 - <executions>
53 - <execution>
54 - <phase>package</phase>
55 - <goals>
56 - <goal>shade</goal>
57 - </goals>
58 - <configuration>
59 - <transformers>
60 - <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
61 - <manifestEntries>
62 - <Main-Class>org.onosproject.oecfg.OELinkConfig</Main-Class>
63 - </manifestEntries>
64 - </transformer>
65 - </transformers>
66 - </configuration>
67 - </execution>
68 - </executions>
69 - </plugin>
70 - </plugins>
71 - </build>
72 -
73 -</project>
1 -/*
2 - * Copyright 2014 Open Networking Laboratory
3 - *
4 - * Licensed under the Apache License, Version 2.0 (the "License");
5 - * you may not use this file except in compliance with the License.
6 - * You may obtain a copy of the License at
7 - *
8 - * http://www.apache.org/licenses/LICENSE-2.0
9 - *
10 - * Unless required by applicable law or agreed to in writing, software
11 - * distributed under the License is distributed on an "AS IS" BASIS,
12 - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 - * See the License for the specific language governing permissions and
14 - * limitations under the License.
15 - */
16 -package org.onosproject.oecfg;
17 -
18 -import com.fasterxml.jackson.databind.JsonNode;
19 -import com.fasterxml.jackson.databind.ObjectMapper;
20 -import com.fasterxml.jackson.databind.node.ArrayNode;
21 -import com.fasterxml.jackson.databind.node.ObjectNode;
22 -
23 -import java.io.IOException;
24 -import java.io.InputStream;
25 -import java.util.HashMap;
26 -import java.util.Map;
27 -
28 -/**
29 - * Utility program to convert standard ONOS config JSON to format expected
30 - * by the OE Link switch.
31 - */
32 -public final class OELinkConfig {
33 -
34 - private ObjectMapper mapper = new ObjectMapper();
35 - private Map<String, String> dpidToName = new HashMap<>();
36 -
37 - public static void main(String[] args) {
38 - try {
39 - OELinkConfig config = new OELinkConfig();
40 - JsonNode json = config.convert(System.in);
41 - System.out.println(json.toString());
42 - } catch (IOException e) {
43 - System.err.println("Unable to convert JSON due to: " + e.getMessage());
44 - e.printStackTrace();
45 - }
46 - }
47 -
48 - private OELinkConfig() {
49 - }
50 -
51 - private JsonNode convert(InputStream input) throws IOException {
52 - JsonNode json = mapper.readTree(input);
53 - ObjectNode result = mapper.createObjectNode();
54 - result.set("switchConfig", opticalSwitches(json));
55 - result.set("linkConfig", opticalLinks(json));
56 - return result;
57 - }
58 -
59 - private JsonNode opticalSwitches(JsonNode json) {
60 - ArrayNode result = mapper.createArrayNode();
61 - for (JsonNode node : json.get("devices")) {
62 - String dpid = dpid(node.path("uri"));
63 - String name = node.path("name").asText("none");
64 - dpidToName.put(dpid, name);
65 - if (node.path("type").asText("none").equals("ROADM")) {
66 - result.add(opticalSwitch(dpid, name, (ObjectNode) node));
67 - }
68 - }
69 - return result;
70 - }
71 -
72 - private ObjectNode opticalSwitch(String dpid, String name, ObjectNode node) {
73 - ObjectNode result = mapper.createObjectNode();
74 - ObjectNode annot = (ObjectNode) node.path("annotations");
75 - result.put("allowed", true).put("type", "Roadm")
76 - .put("name", name).put("nodeDpid", dpid)
77 - .put("latitude", annot.path("latitude").asDouble(0.0))
78 - .put("longitude", annot.path("longitude").asDouble(0.0))
79 - .set("params", switchParams(annot));
80 - return result;
81 - }
82 -
83 - private ObjectNode switchParams(ObjectNode annot) {
84 - return mapper.createObjectNode()
85 - .put("numRegen", annot.path("optical.regens").asInt(0));
86 - }
87 -
88 - private JsonNode opticalLinks(JsonNode json) {
89 - ArrayNode result = mapper.createArrayNode();
90 - for (JsonNode node : json.get("links")) {
91 - if (node.path("type").asText("none").equals("OPTICAL")) {
92 - result.add(opticalLink((ObjectNode) node));
93 - }
94 - }
95 - return result;
96 - }
97 -
98 - private ObjectNode opticalLink(ObjectNode node) {
99 - ObjectNode result = mapper.createObjectNode();
100 - ObjectNode annot = (ObjectNode) node.path("annotations");
101 - String src = dpid(node.path("src"));
102 - String dst = dpid(node.path("dst"));
103 - result.put("allowed", true).put("type", linkType(annot))
104 - .put("nodeDpid1", src).put("nodeDpid2", dst)
105 - .set("params", linkParams(src, dst, node, annot));
106 - return result;
107 - }
108 -
109 - private String linkType(ObjectNode annot) {
110 - return annot.path("optical.type").asText("cross-connect").equals("WDM") ?
111 - "wdmLink" : "pktOptLink";
112 - }
113 -
114 - private ObjectNode linkParams(String src, String dst,
115 - ObjectNode node, ObjectNode annot) {
116 - ObjectNode result = mapper.createObjectNode()
117 - .put("nodeName1", dpidToName.get(src))
118 - .put("nodeName2", dpidToName.get(dst))
119 - .put("port1", port(node.path("src")))
120 - .put("port2", port(node.path("dst")));
121 - if (annot.has("bandwidth")) {
122 - result.put("bandwidth", annot.path("bandwidth").asInt());
123 - }
124 - if (annot.has("optical.waves")) {
125 - result.put("numWaves", annot.path("optical.waves").asInt());
126 - }
127 - return result;
128 - }
129 -
130 - private String dpid(JsonNode node) {
131 - String s = node.asText("of:0000000000000000").substring(3);
132 - return s.substring(0, 2) + ":" + s.substring(2, 4) + ":" +
133 - s.substring(4, 6) + ":" + s.substring(6, 8) + ":" +
134 - s.substring(8, 10) + ":" + s.substring(10, 12) + ":" +
135 - s.substring(12, 14) + ":" + s.substring(14, 16);
136 - }
137 -
138 - private int port(JsonNode node) {
139 - return Integer.parseInt(node.asText("of:0000000000000000/0").substring(20));
140 - }
141 -
142 -}
...@@ -40,7 +40,6 @@ ...@@ -40,7 +40,6 @@
40 <module>sdnip</module> 40 <module>sdnip</module>
41 <module>optical</module> 41 <module>optical</module>
42 <module>metrics</module> 42 <module>metrics</module>
43 - <module>oecfg</module>
44 <module>routing</module> 43 <module>routing</module>
45 <module>routing-api</module> 44 <module>routing-api</module>
46 <module>reactive-routing</module> 45 <module>reactive-routing</module>
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
4 Notes: 4 Notes:
5 5
6 This file contains classes and methods useful for integrating LincOE with Mininet, 6 This file contains classes and methods useful for integrating LincOE with Mininet,
7 -such as startOE, stopOE, LINCLink, and OpticalSwitch 7 +such as startOE, stopOE, OpticalLink, and OpticalSwitch
8 8
9 - $ONOS_ROOT ust be set 9 - $ONOS_ROOT ust be set
10 - Need to run with sudo -E to preserve ONOS_ROOT env var 10 - Need to run with sudo -E to preserve ONOS_ROOT env var
...@@ -22,10 +22,10 @@ such as startOE, stopOE, LINCLink, and OpticalSwitch ...@@ -22,10 +22,10 @@ such as startOE, stopOE, LINCLink, and OpticalSwitch
22 22
23 Usage: 23 Usage:
24 ------------ 24 ------------
25 - - import LINCLink and OpticalSwitch from this module 25 + - import OpticalLink and OpticalSwitch from this module
26 - import startOE and stopOE from this module 26 - import startOE and stopOE from this module
27 - create topology as you would a normal topology. when 27 - create topology as you would a normal topology. when
28 - to an optical switch with topo.addLink, always specify cls=LINCLink 28 + to an optical switch with topo.addLink, always specify cls=OpticalLink
29 - when creating an optical switch, use cls=OpticalSwitch in topo.addSwitch 29 - when creating an optical switch, use cls=OpticalSwitch in topo.addSwitch
30 - for annotations on links and switches, a dictionary must be passed in as 30 - for annotations on links and switches, a dictionary must be passed in as
31 the annotations argument 31 the annotations argument
...@@ -51,12 +51,11 @@ switches have been started, the new Mininet start() method should also push the ...@@ -51,12 +51,11 @@ switches have been started, the new Mininet start() method should also push the
51 Topology configuration file to ONOS. 51 Topology configuration file to ONOS.
52 52
53 ''' 53 '''
54 -import sys 54 +
55 import re 55 import re
56 import json 56 import json
57 import os 57 import os
58 from time import sleep 58 from time import sleep
59 -import urllib2
60 59
61 from mininet.node import Switch, RemoteController 60 from mininet.node import Switch, RemoteController
62 from mininet.topo import Topo 61 from mininet.topo import Topo
...@@ -66,127 +65,25 @@ from mininet.log import setLogLevel, info, error, warn ...@@ -66,127 +65,25 @@ from mininet.log import setLogLevel, info, error, warn
66 from mininet.link import Link, Intf 65 from mininet.link import Link, Intf
67 from mininet.cli import CLI 66 from mininet.cli import CLI
68 67
69 -# Sleep time and timeout values in seconds 68 +class OpticalSwitch( Switch ):
70 -SLEEP_TIME = 2 69 +
71 -TIMEOUT = 60 70 + def __init__( self, name, dpid=None, allowed=True,
72 - 71 + switchType='ROADM', annotations={}, **params ):
73 -class OpticalSwitch(Switch):
74 - """
75 - For now, same as Switch class.
76 - """
77 - pass
78 -
79 -class OpticalIntf(Intf):
80 - """
81 - For now,same as Intf class.
82 - """
83 - pass
84 -
85 -class OpticalLink(Link):
86 - """
87 - For now, same as Link.
88 - """
89 - pass
90 -
91 -class LINCSwitch(OpticalSwitch):
92 - """
93 - LINCSwitch class
94 - """
95 - # FIXME:Sometimes LINC doesn't remove pipes and on restart increase the pipe
96 - # number from erlang.pipe.1.* to erlang.pipe.2.*, so should read and write
97 - # from latest pipe files. For now we are removing all the pipes before
98 - # starting LINC.
99 - ### User Name ###
100 - user = os.getlogin()
101 - ### pipes ###
102 - readPipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.r".format(user)
103 - writePipe = "/tmp/home/{}/linc-oe/rel/linc/erlang.pipe.1.w".format(user)
104 - ### sys.config path ###
105 - sysConfig = "/home/{}/linc-oe/rel/linc/releases/1.0/sys.config".format(user)
106 - ### method, mapping dpid to LINC switchId ###
107 - @staticmethod
108 - def dpids_to_ids(sysConfig):
109 - '''
110 - return the dict containing switch dpids as key and LINC switch id as values
111 - '''
112 - dpids_to_ids = {}
113 - fd = None
114 - try:
115 - with open(sysConfig, 'r', 0) as fd:
116 - switch_id = 1
117 - for line in fd:
118 - dpid = re.search(r'([0-9A-Fa-f]{2}[:-]){7}([0-9A-Fa-f]{2})+', line, re.I)
119 - if dpid:
120 - dpids_to_ids[dpid.group().replace(':', '')] = switch_id
121 - switch_id += 1
122 - return dpids_to_ids
123 - except:
124 - print "Error working with {}\nError: {}\n".format(sysConfig, sys.exc_info())
125 - fd.close()
126 - return None
127 - ### dict of containing dpids as key and corresponding LINC switchId as values ###
128 - dpidsToLINCSwitchId = dpids_to_ids.__func__(sysConfig)
129 - @staticmethod
130 - def findDir(directory, userName):
131 - "finds and returns the path of any directory in the user's home directory"
132 - homeDir = '/home/' + userName
133 - Dir = quietRun('find %s -maxdepth 1 -name %s -type d' % (homeDir, directory)).strip('\n')
134 - DirList = Dir.split('\n')
135 - if not Dir:
136 - return None
137 - elif len(DirList) > 1 :
138 - warn('***WARNING: Found multiple instances of %s; using %s\n'
139 - % (directory, DirList[ 0 ]))
140 - return DirList[ 0 ]
141 - else:
142 - return Dir
143 - ### ONOS Directory ###
144 - try:
145 - onosDir = os.environ[ 'ONOS_ROOT' ]
146 - except:
147 - onosDir = findDir('onos', user)
148 - if not onosDir:
149 - error('Please set ONOS_ROOT environment variable!\n')
150 - else:
151 - os.environ[ 'ONOS_ROOT' ] = onosDir
152 - ### LINC-directory
153 - lincDir = findDir.__func__('linc-oe', user)
154 - if not lincDir:
155 - error("***ERROR: Could not find linc-oe in user's home directory\n")
156 - ### LINC config generator directory###
157 - configGen = findDir.__func__('LINC-config-generator', user)
158 - if not configGen:
159 - error("***ERROR: Could not find LINC-config-generator in user's home directory\n")
160 - # list of all the controllers
161 - controllers = None
162 - def __init__(self, name, dpid=None, allowed=True,
163 - switchType='ROADM', topo=None, annotations={}, controller=None, **params):
164 params[ 'inNamespace' ] = False 72 params[ 'inNamespace' ] = False
165 - Switch.__init__(self, name, dpid=dpid, **params) 73 + Switch.__init__( self, name, dpid=dpid, **params )
166 self.name = name 74 self.name = name
167 self.annotations = annotations 75 self.annotations = annotations
168 self.allowed = allowed 76 self.allowed = allowed
169 self.switchType = switchType 77 self.switchType = switchType
170 - self.configDict = {} # dictionary that holds all of the JSON configuration data 78 + self.configDict = {} # dictionary that holds all of the JSON configuration data
171 - self.crossConnects = [] 79 +
172 - self.deletedCrossConnects = [] 80 + def start( self, *opts, **params ):
173 - self.controller = controller
174 - self.lincId = self._get_linc_id() # use to communicate with LINC
175 - self.lincStarted = False
176 -
177 - def start(self, *opts, **params):
178 '''Instead of starting a virtual switch, we build the JSON 81 '''Instead of starting a virtual switch, we build the JSON
179 dictionary for the emulated optical switch''' 82 dictionary for the emulated optical switch'''
180 - # TODO:Once LINC has the ability to spawn network element dynamically
181 - # we need to use this method to spawn new logical LINC switch rather then
182 - # bulding JSON.
183 - # if LINC is started then we can start and stop logical switches else create JSON
184 - if self.lincStarted:
185 - return self.start_oe()
186 self.configDict[ 'uri' ] = 'of:' + self.dpid 83 self.configDict[ 'uri' ] = 'of:' + self.dpid
187 self.configDict[ 'annotations' ] = self.annotations 84 self.configDict[ 'annotations' ] = self.annotations
188 - self.configDict[ 'annotations' ].setdefault('name', self.name) 85 + self.configDict[ 'annotations' ].setdefault( 'name', self.name )
189 - self.configDict[ 'hw' ] = 'LINC-OE' 86 + self.configDict[ 'hw' ] = 'OE'
190 self.configDict[ 'mfr' ] = 'Linc' 87 self.configDict[ 'mfr' ] = 'Linc'
191 self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1] 88 self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1]
192 self.configDict[ 'type' ] = self.switchType 89 self.configDict[ 'type' ] = self.switchType
...@@ -195,441 +92,74 @@ class LINCSwitch(OpticalSwitch): ...@@ -195,441 +92,74 @@ class LINCSwitch(OpticalSwitch):
195 if intf.name == 'lo': 92 if intf.name == 'lo':
196 continue 93 continue
197 else: 94 else:
198 - self.configDict[ 'ports' ].append(intf.json()) 95 + self.configDict[ 'ports' ].append( intf.json() )
199 - self.lincStarted = True
200 -
201 - def stop(self, deleteIntfs=False):
202 - '''
203 - stop the existing switch
204 - '''
205 - # TODO:Add support for deleteIntf
206 - self.stop_oe()
207 -
208 - def dpctl( self, *args ):
209 - "Run dpctl command: ignore for now"
210 - pass
211 -
212 - def write_to_cli(self, command):
213 - '''
214 - send command to LINC
215 - '''
216 - fd = None
217 - try:
218 - fd = open(self.writePipe, 'w', 0)
219 - fd.write(command)
220 - fd.close()
221 - except:
222 - print "Error working with {}\nError: {}\n".format(self.writePipe, sys.exc_info())
223 - if fd:
224 - fd.close()
225 -
226 - def read_from_cli(self):
227 - '''
228 - read the output from the LINC CLI
229 - '''
230 - response = None
231 - fd = None
232 - try:
233 - fd = open(self.readPipe, 'r', 0)
234 - fcntl.fcntl(fd, fcntl.F_SETFL, os.O_NONBLOCK) # for non-blocking read
235 - # FIXME:Due to non-blocking read most for the time we read nothing
236 - response = fd.read()
237 - fd.close()
238 - except :
239 - # print "Error working with {}\nError: {}\n".format(self.readPipe, sys.exc_info())
240 - if fd:
241 - fd.close()
242 - return response
243 -
244 - def _get_linc_id(self):
245 - '''
246 - return the corresponding LINC switchId.
247 - '''
248 - return LINCSwitch.dpidsToLINCSwitchId.get(self.dpid)
249 - #--------------------------------------------------------------------------
250 - # LINC CLI commands
251 - #--------------------------------------------------------------------------
252 - def start_oe(self):
253 - '''
254 - start the existing LINC switch
255 - '''
256 - #starting Switch
257 - cmd = "linc:start_switch({}).\r\n".format(self.lincId)
258 - self.write_to_cli(cmd)
259 - #hanlding taps interfaces related to the switch
260 - crossConnectJSON = {}
261 - linkConfig = []
262 - for i in range(0,len(self.deletedCrossConnects)):
263 - crossConnect = self.deletedCrossConnects.pop()
264 - tap = None
265 - if isinstance(crossConnect.intf1.node, LINCSwitch):
266 - intf = crossConnect.intf2
267 - tapPort = crossConnect.intf1.port
268 - else:
269 - intf = crossConnect.intf1
270 - tapPort = crossConnect.intf2.port
271 - tap = LINCSwitch.findTap(self, tapPort)
272 - if tap:
273 - LINCSwitch.setupInts([tap])
274 - intf.node.attach(tap)
275 - self.crossConnects.append(crossConnect)
276 - linkConfig.append(crossConnect.json())
277 - #Sending crossConnect info to the ONOS.
278 - crossConnectJSON['links'] = linkConfig
279 - with open("crossConnect.json", 'w') as fd:
280 - json.dump(crossConnectJSON, fd, indent=4, separators=(',', ': '))
281 - info('*** Pushing crossConnect.json to ONOS\n')
282 - output = quietRun('%s/tools/test/bin/onos-topo-cfg %s\
283 - Topology.json' % (self.onosDir, self.controllers[ 0 ].ip), shell=True)
284 -
285 - def stop_oe(self):
286 - '''
287 - stop the existing LINC switch
288 - '''
289 - cmd = "linc:stop_switch({}).\r\n".format(self.lincId)
290 - self.write_to_cli(cmd)
291 - #handling taps if any
292 - for i in range(0, len(self.crossConnects)):
293 - crossConnect = self.crossConnects.pop()
294 - if isinstance(crossConnect.intf1.node, LINCSwitch):
295 - intf = crossConnect.intf2
296 - tapPort = crossConnect.intf1.port
297 - else:
298 - intf = crossConnect.intf1
299 - tapPort = crossConnect.intf2.port
300 - intf.node.detach(LINCSwitch.findTap(self, tapPort))
301 - self.deletedCrossConnects.append(crossConnect)
302 -
303 - def w_port_up(self, port):
304 - '''
305 - port_up
306 - '''
307 - cmd = "linc:port_up({},{}).\r\n".format(self.lincId, port)
308 - self.write_to_cli(cmd)
309 -
310 - def w_port_down(self, port):
311 - '''
312 - port_down
313 - '''
314 - cmd = "linc:port_down({},{}).\r\n".format(self.lincId, port)
315 - self.write_to_cli(cmd)
316 -
317 - # helper functions
318 - @staticmethod
319 - def switchJSON(switch):
320 - "Returns the json configuration for a packet switch"
321 - configDict = {}
322 - configDict[ 'uri' ] = 'of:' + switch.dpid
323 - configDict[ 'mac' ] = quietRun('cat /sys/class/net/%s/address' % switch.name).strip('\n').translate(None, ':')
324 - configDict[ 'hw' ] = 'PK' # FIXME what about OVS?
325 - configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS?
326 - configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS?
327 - annotations = switch.params.get('annotations', {})
328 - annotations.setdefault('name', switch.name)
329 - configDict[ 'annotations' ] = annotations
330 - ports = []
331 - for port, intf in switch.intfs.items():
332 - if intf.name == 'lo':
333 - continue
334 - portDict = {}
335 - portDict[ 'port' ] = port
336 - portDict[ 'type' ] = 'FIBER' if isinstance(intf.link, LINCLink) else 'COPPER'
337 - intfList = [ intf.link.intf1, intf.link.intf2 ]
338 - intfList.remove(intf)
339 - portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance(intf.link, LINCLink) else 0
340 - ports.append(portDict)
341 - configDict[ 'ports' ] = ports
342 - return configDict
343 -
344 - @staticmethod
345 - def bootOE(net):
346 - "Start the LINC optical emulator within a mininet instance"
347 - opticalJSON = {}
348 - linkConfig = []
349 - devices = []
350 - #setting up the controllers for LINCSwitch class
351 - LINCSwitch.controllers = net.controllers
352 -
353 - for switch in net.switches:
354 - if isinstance(switch, OpticalSwitch):
355 - devices.append(switch.json())
356 - else:
357 - devices.append(LINCSwitch.switchJSON(switch))
358 - opticalJSON[ 'devices' ] = devices
359 -
360 - for link in net.links:
361 - if isinstance(link, LINCLink) :
362 - linkConfig.append(link.json())
363 - opticalJSON[ 'links' ] = linkConfig
364 -
365 - info('*** Writing Topology.json file\n')
366 - with open('Topology.json', 'w') as outfile:
367 - json.dump(opticalJSON, outfile, indent=4, separators=(',', ': '))
368 -
369 - info('*** Converting Topology.json to linc-oe format (TopoConfig.json) file\n')
370 - output = quietRun('%s/tools/test/bin/onos-oecfg ./Topology.json > TopoConfig.json' % LINCSwitch.onosDir, shell=True)
371 - if output:
372 - error('***ERROR: Error creating topology file: %s ' % output + '\n')
373 - return False
374 -
375 - info('*** Creating sys.config...\n')
376 - output = quietRun('%s/config_generator TopoConfig.json %s/sys.config.template %s %s'
377 - % (LINCSwitch.configGen, LINCSwitch.configGen, LINCSwitch.controllers[ 0 ].ip, LINCSwitch.controllers[ 0 ].port), shell=True)
378 - if output:
379 - error('***ERROR: Error creating sys.config file: %s\n' % output)
380 - return False
381 -
382 - info ('*** Setting multiple controllers in sys.config...\n')
383 - searchStr = '\[{"Switch.*$'
384 - ctrlStr = ''
385 - for index in range(len(LINCSwitch.controllers)):
386 - ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (index, net.controllers[index].ip, net.controllers[index].port)
387 - replaceStr = '[%s]},' % ctrlStr[:-1] # Cut off last comma
388 - sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr)
389 - output = quietRun(sedCmd, shell=True)
390 -
391 - info('*** Copying sys.config to linc-oe directory: ', output + '\n')
392 - output = quietRun('cp -v sys.config %s/rel/linc/releases/1.0/' % LINCSwitch.lincDir, shell=True).strip('\n')
393 - info(output + '\n')
394 -
395 - info('*** Adding taps and bringing them up...\n')
396 - LINCSwitch.setupInts(LINCSwitch.getTaps())
397 -
398 - info('*** removing pipes if any \n')
399 - quietRun('rm /tmp/home/%s/linc-oe/rel/linc/*' % LINCSwitch.user, shell=True)
400 -
401 - info('*** Starting linc OE...\n')
402 - output = quietRun('%s/rel/linc/bin/linc start' % LINCSwitch.lincDir, shell=True)
403 - if output:
404 - error('***ERROR: LINC-OE: %s' % output + '\n')
405 - quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
406 - return False
407 -
408 - info('*** Waiting for linc-oe to start...\n')
409 - LINCSwitch.waitStarted(net)
410 -
411 - info('*** Adding cross-connect (tap) interfaces to packet switches...\n')
412 - for link in net.links:
413 - if isinstance(link, LINCLink):
414 - if link.annotations[ 'optical.type' ] == 'cross-connect':
415 - for intf in [ link.intf1, link.intf2 ]:
416 - if not isinstance(intf, LINCIntf):
417 - intfList = [ intf.link.intf1, intf.link.intf2 ]
418 - intfList.remove(intf)
419 - intf2 = intfList[ 0 ]
420 - intf.node.attach(LINCSwitch.findTap(intf2.node, intf2.node.ports[ intf2 ]))
421 -
422 - info('*** Waiting for all devices to be available in ONOS...\n')
423 - url = 'http://%s:8181/onos/v1/devices' % LINCSwitch.controllers[0].ip
424 - time = 0
425 - while True:
426 - response = json.load(urllib2.urlopen(url))
427 - devs = response.get('devices')
428 -
429 - # Wait for all devices to be registered
430 - if (len(devices) != len(devs)):
431 - continue
432 96
433 - # Wait for all devices to available
434 - available = True
435 - for d in devs:
436 - available &= d['available']
437 - if available:
438 - break
439 -
440 - if (time >= TIMEOUT):
441 - error('***ERROR: ONOS did not register devices within %s seconds\n' % TIMEOUT)
442 - break
443 -
444 - time += SLEEP_TIME
445 - sleep(SLEEP_TIME)
446 -
447 - info('*** Pushing Topology.json to ONOS\n')
448 - for index in range(len(LINCSwitch.controllers)):
449 - output = quietRun('%s/tools/test/bin/onos-topo-cfg %s Topology.json &' % (LINCSwitch.onosDir, LINCSwitch.controllers[ index ].ip), shell=True)
450 - # successful output contains the two characters '{}'
451 - # if there is more output than this, there is an issue
452 - if output.strip('{}'):
453 - warn('***WARNING: Could not push topology file to ONOS: %s\n' % output)
454 -
455 - @staticmethod
456 - def waitStarted(net, timeout=TIMEOUT):
457 - "wait until all tap interfaces are available"
458 - tapCount = 0
459 - time = 0
460 - for link in net.links:
461 - if isinstance(link, LINCLink):
462 - if link.annotations[ 'optical.type' ] == 'cross-connect':
463 - tapCount += 1
464 -
465 - while True:
466 - if str(tapCount) == quietRun('ip addr | grep tap | wc -l', shell=True).strip('\n'):
467 - return True
468 - if timeout:
469 - if time >= TIMEOUT:
470 - error('***ERROR: LINC OE did not start within %s seconds\n' % TIMEOUT)
471 - return False
472 - time += SLEEP_TIME
473 - sleep(SLEEP_TIME)
474 -
475 - @staticmethod
476 - def shutdownOE():
477 - "stop the optical emulator"
478 - info('*** Stopping linc OE...\n')
479 - quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
480 -
481 - @staticmethod
482 - def setupInts(intfs):
483 - '''
484 - add taps and bring them up.
485 - '''
486 - for i in intfs:
487 - quietRun('ip tuntap add dev %s mode tap' % i)
488 - quietRun('ip link set dev %s up' % i)
489 - info('*** Intf %s set\n' % i)
490 -
491 - @staticmethod
492 - def getTaps(path=None):
493 - '''
494 - return list of all the tops in sys.config
495 - '''
496 - if path is None:
497 - path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
498 - fd = open(path, 'r', 0)
499 - sys_data = fd.read()
500 - taps = re.findall('tap\d+', sys_data)
501 - fd.close()
502 - return taps
503 -
504 - @staticmethod
505 - def findUser():
506 - "Try to return logged-in (usually non-root) user"
507 - try:
508 - # If we're running sudo
509 - return os.environ[ 'SUDO_USER' ]
510 - except:
511 - try:
512 - # Logged-in user (if we have a tty)
513 - return quietRun('who am i').split()[ 0 ]
514 - except:
515 - # Give up and return effective user
516 - return quietRun('whoami')
517 -
518 -
519 - @staticmethod
520 - def findTap(node, port, path=None):
521 - '''utility function to parse through a sys.config
522 - file to find tap interfaces for a switch'''
523 - switch = False
524 - portLine = ''
525 - intfLines = []
526 -
527 - if path is None:
528 - path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
529 -
530 - with open(path) as f:
531 - for line in f:
532 - if 'tap' in line:
533 - intfLines.append(line)
534 - if node.dpid in line.translate(None, ':'):
535 - switch = True
536 - continue
537 - if switch:
538 - if 'switch' in line:
539 - switch = False
540 - if 'port_no,%s}' % port in line:
541 - portLine = line
542 - break
543 -
544 - if portLine:
545 - m = re.search('port,\d+', portLine)
546 - port = m.group(0).split(',')[ 1 ]
547 - else:
548 - error('***ERROR: Could not find any ports in sys.config\n')
549 - return
550 97
551 - for intfLine in intfLines: 98 + def json( self ):
552 - if 'port,%s' % port in intfLine:
553 - return re.findall('tap\d+', intfLine)[ 0 ]
554 -
555 - def json(self):
556 "return json configuration dictionary for switch" 99 "return json configuration dictionary for switch"
557 return self.configDict 100 return self.configDict
558 - 101 +
559 - def terminate(self): 102 + def terminate( self ):
560 pass 103 pass
561 104
562 -class LINCLink(Link): 105 +class OpticalLink( Link ):
563 - """ 106 +
564 - LINC link class 107 + def __init__( self, node1, node2, port1=None, port2=None, allowed=True,
565 - """
566 - def __init__(self, node1, node2, port1=None, port2=None, allowed=True,
567 intfName1=None, intfName2=None, linkType='OPTICAL', 108 intfName1=None, intfName2=None, linkType='OPTICAL',
568 - annotations={}, speed1=0, speed2=0, **params): 109 + annotations={}, speed1=0, speed2=0, **params ):
569 "Creates a dummy link without a virtual ethernet pair." 110 "Creates a dummy link without a virtual ethernet pair."
570 self.allowed = allowed 111 self.allowed = allowed
571 self.annotations = annotations 112 self.annotations = annotations
572 self.linkType = linkType 113 self.linkType = linkType
573 - self.port1 = port1
574 - self.port2 = port2
575 params1 = { 'speed': speed1 } 114 params1 = { 'speed': speed1 }
576 params2 = { 'speed': speed2 } 115 params2 = { 'speed': speed2 }
577 - # self.isCrossConnect = True if self.annotations.get('optical.type') == 'cross-connect' else False 116 +
578 - if isinstance(node1, LINCSwitch) and isinstance(node2, LINCSwitch): 117 + if isinstance( node1, OpticalSwitch ):
579 - self.isCrossConnect = False 118 + cls1 = OpticalIntf
580 - else:
581 - self.isCrossConnect = True
582 - if isinstance(node1, LINCSwitch):
583 - cls1 = LINCIntf
584 - if self.isCrossConnect:
585 - node1.crossConnects.append(self)
586 else: 119 else:
587 cls1 = Intf 120 cls1 = Intf
588 # bad hack to stop error message from appearing when we try to set up intf in a packet switch, 121 # bad hack to stop error message from appearing when we try to set up intf in a packet switch,
589 # and there is no interface there( because we do not run makeIntfPair ). This way, we just set lo up 122 # and there is no interface there( because we do not run makeIntfPair ). This way, we just set lo up
590 intfName1 = 'lo' 123 intfName1 = 'lo'
591 - if isinstance(node2, LINCSwitch): 124 + if isinstance( node2, OpticalSwitch ):
592 - cls2 = LINCIntf 125 + cls2 = OpticalIntf
593 - if self.isCrossConnect:
594 - node2.crossConnects.append(self)
595 else: 126 else:
596 cls2 = Intf 127 cls2 = Intf
597 intfName2 = 'lo' 128 intfName2 = 'lo'
598 - Link.__init__(self, node1, node2, port1=port1, port2=port2, 129 + Link.__init__( self, node1, node2, port1=port1, port2=port2,
599 intfName1=intfName1, intfName2=intfName2, cls1=cls1, 130 intfName1=intfName1, intfName2=intfName2, cls1=cls1,
600 - cls2=cls2, params1=params1, params2=params2) 131 + cls2=cls2, params1=params1, params2=params2 )
132 +
601 133
602 @classmethod 134 @classmethod
603 - def makeIntfPair(_cls, intfName1, intfName2, *args, **kwargs): 135 + def makeIntfPair( _cls, intfName1, intfName2, *args, **kwargs ):
604 pass 136 pass
605 137
606 - def json(self): 138 + def json( self ):
607 "build and return the json configuration dictionary for this link" 139 "build and return the json configuration dictionary for this link"
608 configData = {} 140 configData = {}
609 - configData[ 'src' ] = ('of:' + self.intf1.node.dpid + 141 + configData[ 'src' ] = ( 'of:' + self.intf1.node.dpid +
610 - '/%s' % self.intf1.node.ports[ self.intf1 ]) 142 + '/%s' % self.intf1.node.ports[ self.intf1 ] )
611 - configData[ 'dst' ] = ('of:' + self.intf2.node.dpid + 143 + configData[ 'dst' ] = ( 'of:' + self.intf2.node.dpid +
612 - '/%s' % self.intf2.node.ports[ self.intf2 ]) 144 + '/%s' % self.intf2.node.ports[ self.intf2 ] )
613 configData[ 'type' ] = self.linkType 145 configData[ 'type' ] = self.linkType
614 configData[ 'annotations' ] = self.annotations 146 configData[ 'annotations' ] = self.annotations
615 return configData 147 return configData
616 148
617 -class LINCIntf(OpticalIntf): 149 +class OpticalIntf( Intf ):
618 - """ 150 +
619 - LINC interface class 151 + def __init__( self, name=None, node=None, speed=0,
620 - """ 152 + port=None, link=None, **params ):
621 - def __init__(self, name=None, node=None, speed=0,
622 - port=None, link=None, **params):
623 self.node = node 153 self.node = node
624 self.speed = speed 154 self.speed = speed
625 self.port = port 155 self.port = port
626 self.link = link 156 self.link = link
627 self.name = name 157 self.name = name
628 - node.addIntf(self, port=port) 158 + node.addIntf( self, port=port )
629 self.params = params 159 self.params = params
630 self.ip = None 160 self.ip = None
631 161
632 - def json(self): 162 + def json( self ):
633 "build and return the JSON information for this interface( not used right now )" 163 "build and return the JSON information for this interface( not used right now )"
634 configDict = {} 164 configDict = {}
635 configDict[ 'port' ] = self.port 165 configDict[ 'port' ] = self.port
...@@ -637,34 +167,356 @@ class LINCIntf(OpticalIntf): ...@@ -637,34 +167,356 @@ class LINCIntf(OpticalIntf):
637 configDict[ 'type' ] = 'FIBER' 167 configDict[ 'type' ] = 'FIBER'
638 return configDict 168 return configDict
639 169
640 - def config(self, *args, **kwargs): 170 + def config( self, *args, **kwargs ):
641 "dont configure a dummy interface" 171 "dont configure a dummy interface"
642 pass 172 pass
643 173
644 - def ifconfig(self, status): 174 +def switchJSON( switch ):
645 - "configure the status" 175 + "Returns the json configuration for a packet switch"
646 - if status == "up": 176 + configDict = {}
647 - return self.node.w_port_up(self.port) 177 + configDict[ 'uri' ] = 'of:' + switch.dpid
648 - elif status == "down": 178 + configDict[ 'mac' ] = quietRun( 'cat /sys/class/net/%s/address' % switch.name ).strip( '\n' ).translate( None, ':' )
649 - return self.node.w_port_down(self.port) 179 + configDict[ 'hw' ] = 'PK' # FIXME what about OVS?
180 + configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS?
181 + configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS?
182 + annotations = switch.params.get( 'annotations', {} )
183 + annotations.setdefault( 'name', switch.name )
184 + configDict[ 'annotations' ] = annotations
185 + ports = []
186 + for port, intf in switch.intfs.items():
187 + if intf.name == 'lo':
188 + continue
189 + portDict = {}
190 + portDict[ 'port' ] = port
191 + portDict[ 'type' ] = 'FIBER' if isinstance( intf.link, OpticalLink ) else 'COPPER'
192 + intfList = [ intf.link.intf1, intf.link.intf2 ]
193 + intfList.remove( intf )
194 + portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance( intf.link, OpticalLink ) else 0
195 + ports.append( portDict )
196 + configDict[ 'ports' ] = ports
197 + return configDict
198 +
199 +
200 +def startOE( net ):
201 + "Start the LINC optical emulator within a mininet instance"
202 + opticalJSON = {}
203 + linkConfig = []
204 + devices = []
205 +
206 + for switch in net.switches:
207 + if isinstance( switch, OpticalSwitch ):
208 + devices.append( switch.json() )
209 + else:
210 + devices.append( switchJSON( switch ) )
211 + opticalJSON[ 'devices' ] = devices
212 +
213 + for link in net.links:
214 + if isinstance( link, OpticalLink ) :
215 + linkConfig.append( link.json() )
216 +
217 + opticalJSON[ 'links' ] = linkConfig
218 +
219 + try:
220 + onosDir = os.environ[ 'ONOS_ROOT' ]
221 + except:
222 + onosDir = findDir( 'onos' )
223 + if not onosDir:
224 + error( 'Please set ONOS_ROOT environment variable!\n' )
225 + return False
226 + else:
227 + os.environ[ 'ONOS_ROOT' ] = onosDir
228 +
229 + info( '*** Writing Topology.json file\n' )
230 + with open( 'Topology.json', 'w' ) as outfile:
231 + json.dump( opticalJSON, outfile, indent=4, separators=(',', ': ') )
232 +
233 + info( '*** Converting Topology.json to linc-oe format (TopoConfig.json) file (not using oecfg) \n' )
234 +
235 + topoConfigJson = {};
236 + newLinkConfig = [];
237 + switchConfig = [];
238 + dpIdToName = {};
239 +
240 + #Iterate through all switches and convert the ROADM switches to linc-oe format
241 + for switch in opticalJSON["devices"]:
242 + if switch["type"] == "ROADM":
243 + builtSwitch = {}
244 +
245 + #set basic switch params based on annotations
246 + builtSwitch["allowed"] = True;
247 + builtSwitch["latitude"] = switch["annotations"]["latitude"];
248 + builtSwitch["longitude"] = switch["annotations"]["longitude"];
249 +
250 + nodeId = switch["uri"]
251 +
252 + #convert the nodeId to linc-oe format
253 + nodeDpid = dpId(nodeId);
254 +
255 + if "name" in switch:
256 + builtSwitch["name"] = switch["name"]
257 + else:
258 + builtSwitch["name"] = "none"
259 +
260 + #keep track of the name corresponding to each switch dpid
261 + dpIdToName[nodeDpid] = builtSwitch["name"];
262 +
263 + builtSwitch["nodeDpid"] = nodeDpid
264 +
265 + #set switch params and type
266 + builtSwitch["params"] = {};
267 + builtSwitch["params"]["numregens"] = switch["annotations"]["optical.regens"];
268 + builtSwitch["type"] = "Roadm"
650 269
270 + #append to list of switches
271 + switchConfig.append(builtSwitch);
651 272
652 -class MininetOE(Mininet): 273 + topoConfigJson["switchConfig"] = switchConfig;
274 +
275 + #Iterate through all optical links and convert them to linc-oe format
276 + for link in opticalJSON["links"]:
277 + if link["type"] == "OPTICAL":
278 + builtLink = {}
279 +
280 + #set basic link params for src and dst
281 + builtLink["allowed"] = True;
282 + builtLink["nodeDpid1"] = dpId(link["src"])
283 + builtLink["nodeDpid2"] = dpId(link["dst"])
284 +
285 + #set more params such as name/bandwidth/port/waves if they exist
286 + params = {}
287 + params["nodeName1"] = dpIdToName.get(builtLink["nodeDpid1"], "none")
288 + params["nodeName2"] = dpIdToName.get(builtLink["nodeDpid2"], "none")
289 + if "bandwidth" in link["annotations"]:
290 + params["bandwidth"] = link["annotations"]["bandwidth"]
291 + params["port1"] = int(link["src"].split("/")[1])
292 + params["port2"] = int(link["dst"].split("/")[1])
293 +
294 + if "optical.waves" in link["annotations"]:
295 + params["numWaves"] = link["annotations"]["optical.waves"]
296 + builtLink["params"] = params
297 +
298 + #set type of link (WDM or pktOpt)
299 + if link["annotations"]["optical.type"] == "WDM":
300 + builtLink["type"] = "wdmLink"
301 + else:
302 + builtLink["type"] = "pktOptLink"
303 +
304 + newLinkConfig.append(builtLink);
305 +
306 + topoConfigJson["linkConfig"] = newLinkConfig;
307 +
308 + #Writing to TopoConfig.json
309 + with open( 'TopoConfig.json', 'w' ) as outfile:
310 + json.dump( topoConfigJson, outfile, indent=4, separators=(',', ': ') )
311 +
312 + info( '*** Creating sys.config...\n' )
313 + configGen = findDir( 'LINC-config-generator' )
314 + if not configGen:
315 + error( "***ERROR: Could not find LINC-config-generator in user's home directory\n" )
316 + return False
317 + output = quietRun( '%s/config_generator TopoConfig.json %s/sys.config.template %s %s'
318 + % ( configGen, configGen, net.controllers[ 0 ].ip, net.controllers[ 0 ].port ), shell=True )
319 + if output:
320 + error( '***ERROR: Error creating sys.config file: %s\n' % output )
321 + return False
322 +
323 + info ('*** Setting multiple controllers in sys.config...\n' )
324 + searchStr = '{controllers,.*$'
325 + ctrlStr = ''
326 + for index in range(len(net.controllers)):
327 + ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (index, net.controllers[index].ip, net.controllers[index].port)
328 + replaceStr = '{controllers,[%s]},' % ctrlStr[:-1] # Cut off last comma
329 + sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr)
330 + output = quietRun( sedCmd, shell=True )
331 +
332 + info( '*** Copying sys.config to linc-oe directory: ', output + '\n' )
333 + lincDir = findDir( 'linc-oe' )
334 + if not lincDir:
335 + error( "***ERROR: Could not find linc-oe in user's home directory\n" )
336 + return False
337 + output = quietRun( 'cp -v sys.config %s/rel/linc/releases/1.0/' % lincDir, shell=True ).strip( '\n' )
338 + info( output + '\n' )
339 +
340 + info( '*** Starting linc OE...\n' )
341 + output = quietRun( '%s/rel/linc/bin/linc start' % lincDir, shell=True )
342 + if output:
343 + error( '***ERROR: LINC-OE: %s' % output + '\n' )
344 + quietRun( '%s/rel/linc/bin/linc stop' % lincDir, shell=True )
345 + return False
346 +
347 + info( '*** Waiting for linc-oe to start...\n' )
348 + waitStarted( net )
349 +
350 + info( '*** Adding cross-connect (tap) interfaces to packet switches...\n' )
351 + for link in net.links:
352 + if isinstance( link, OpticalLink ):
353 + if link.annotations[ 'optical.type' ] == 'cross-connect':
354 + for intf in [ link.intf1, link.intf2 ]:
355 + if not isinstance( intf, OpticalIntf ):
356 + intfList = [ intf.link.intf1, intf.link.intf2 ]
357 + intfList.remove( intf )
358 + intf2 = intfList[ 0 ]
359 + intf.node.attach( findTap( intf2.node, intf2.node.ports[ intf2 ] ) )
360 +
361 + info( '*** Press ENTER to push Topology.json to onos...\n' )
362 + raw_input() # FIXME... we should eventually remove this
363 + info( '*** Pushing Topology.json to ONOS\n' )
364 + output = quietRun( '%s/tools/test/bin/onos-topo-cfg %s Topology.json' % ( onosDir, net.controllers[ 0 ].ip ), shell=True )
365 + # successful output contains the two characters '{}'
366 + # if there is more output than this, there is an issue
367 + if output.strip( '{}' ):
368 + warn( '***WARNING: Could not push topology file to ONOS: %s' % output )
369 +
370 +#converts node ids to linc-oe format, with colons every two chars
371 +def dpId(id):
372 + nodeDpid = ""
373 + id = id.split("/", 1)[0]
374 + for i in range(3, len(id) - 1, 2):
375 + nodeDpid += (id[i:(i + 2):]) + ":"
376 + return nodeDpid[0:(len(nodeDpid) - 1)];
377 +
378 +def waitStarted( net, timeout=None ):
379 + "wait until all tap interfaces are available"
380 + tapCount = 0
381 + time = 0
382 + for link in net.links:
383 + if isinstance( link, OpticalLink ):
384 + if link.annotations[ 'optical.type' ] == 'cross-connect':
385 + tapCount += 1
386 +
387 + while True:
388 + if str( tapCount ) == quietRun( 'ip addr | grep tap | wc -l', shell=True ).strip( '\n' ):
389 + return True
390 + if timeout:
391 + if time >= timeout:
392 + error( '***ERROR: Linc OE did not start within %s seconds' % timeout )
393 + return False
394 + time += .5
395 + sleep( .5 )
396 +
397 +def stopOE():
398 + "stop the optical emulator"
399 + info( '*** Stopping linc OE...\n' )
400 + lincDir = findDir( 'linc-oe' )
401 + quietRun( '%s/rel/linc/bin/linc stop' % lincDir, shell=True )
402 +
403 +def findDir( directory ):
404 + "finds and returns the path of any directory in the user's home directory"
405 + user = findUser()
406 + homeDir = '/home/' + user
407 + Dir = quietRun( 'find %s -maxdepth 1 -name %s -type d' % ( homeDir, directory ) ).strip( '\n' )
408 + DirList = Dir.split( '\n' )
409 + if not Dir:
410 + return None
411 + elif len( DirList ) > 1 :
412 + warn( '***WARNING: Found multiple instances of %s; using %s\n'
413 + % ( directory, DirList[ 0 ] ) )
414 + return DirList[ 0 ]
415 + else:
416 + return Dir
417 +
418 +def findUser():
419 + "Try to return logged-in (usually non-root) user"
420 + try:
421 + # If we're running sudo
422 + return os.environ[ 'SUDO_USER' ]
423 + except:
424 + try:
425 + # Logged-in user (if we have a tty)
426 + return quietRun( 'who am i' ).split()[ 0 ]
427 + except:
428 + # Give up and return effective user
429 + return quietRun( 'whoami' )
430 +
431 +
432 +def findTap( node, port, path=None ):
433 + '''utility function to parse through a sys.config
434 + file to find tap interfaces for a switch'''
435 + switch=False
436 + portLine = ''
437 + intfLines = []
438 +
439 + if path is None:
440 + lincDir = findDir( 'linc-oe' )
441 + if not lincDir:
442 + error( '***ERROR: Could not find linc-oe in users home directory\n' )
443 + return None
444 + path = '%s/rel/linc/releases/1.0/sys.config' % lincDir
445 +
446 + with open( path ) as f:
447 + for line in f:
448 + if 'tap' in line:
449 + intfLines.append( line )
450 + if node.dpid in line.translate( None, ':' ):
451 + switch=True
452 + continue
453 + if switch:
454 + if 'switch' in line:
455 + switch = False
456 + if 'port_no,%s}' % port in line:
457 + portLine = line
458 + break
459 +
460 + if portLine:
461 + m = re.search( 'port,\d+', portLine )
462 + port = m.group( 0 ).split( ',' )[ 1 ]
463 + else:
464 + error( '***ERROR: Could not find any ports in sys.config\n' )
465 + return
466 +
467 + for intfLine in intfLines:
468 + if 'port,%s' % port in intfLine:
469 + return re.findall( 'tap\d+', intfLine )[ 0 ]
470 +
471 +
472 +class MininetOE( Mininet ):
653 "Mininet with Linc-OE support (starts and stops linc-oe)" 473 "Mininet with Linc-OE support (starts and stops linc-oe)"
654 474
655 - def start(self): 475 + def start( self ):
656 - Mininet.start(self) 476 + Mininet.start( self )
657 - LINCSwitch.bootOE(self) 477 + startOE( self )
658 478
659 - def stop(self): 479 + def stop( self ):
660 - Mininet.stop(self) 480 + Mininet.stop( self )
661 - LINCSwitch.shutdownOE() 481 + stopOE()
662 482
663 - def addControllers(self, controllers): 483 + def addControllers( self, controllers ):
664 i = 0 484 i = 0
665 for ctrl in controllers: 485 for ctrl in controllers:
666 - self.addController(RemoteController('c%d' % i, ip=ctrl)) 486 + self.addController( RemoteController( 'c%d' % i, ip=ctrl ) )
667 - i += 1 487 +
488 +
489 +class OpticalTestTopo( Topo ):
490 +
491 + def build( self ):
492 + opticalAnn = { 'optical.waves': 80, 'optical.type': "WDM", 'durable': True }
493 + switchAnn = { 'bandwidth': 100000, 'optical.type': 'cross-connect', 'durable': True }
494 + h1 = self.addHost( 'h1' )
495 + h2 = self.addHost( 'h2' )
496 + s1 = self.addSwitch( 's1' )
497 + s2 = self.addSwitch( 's2' )
498 + O4 = self.addSwitch( 'O4', cls=OpticalSwitch )
499 + O5 = self.addSwitch( 'O5', cls=OpticalSwitch )
500 + O6 = self.addSwitch( 'O6', cls=OpticalSwitch )
501 + self.addLink( O4, O5, cls=OpticalLink, annotations=opticalAnn )
502 + self.addLink( O5, O6, cls=OpticalLink, annotations=opticalAnn )
503 + self.addLink( s1, O4, cls=OpticalLink, annotations=switchAnn )
504 + self.addLink( s2, O6, cls=OpticalLink, annotations=switchAnn )
505 + self.addLink( h1, s1 )
506 + self.addLink( h2, s2 )
668 507
669 if __name__ == '__main__': 508 if __name__ == '__main__':
670 - pass 509 + import sys
510 + if len( sys.argv ) >= 2:
511 + controllers = sys.argv[1:]
512 + else:
513 + print 'Usage: ./opticalUtils.py (<Controller IP>)+'
514 + print 'Using localhost...\n'
515 + controllers = [ '127.0.0.1' ]
516 +
517 + setLogLevel( 'info' )
518 + net = MininetOE( topo=OpticalTestTopo(), controller=None, autoSetMacs=True )
519 + net.addControllers( controllers )
520 + net.start()
521 + CLI( net )
522 + net.stop()
......