Marc De Leenheer
Committed by Gerrit Code Review

Revert "OECF removed working"

This reverts commit 5f8f8f0c.

Change-Id: I13207976c26fc210994c90e213349790a4227440
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 +}
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
41 <module>sdnip</module> 41 <module>sdnip</module>
42 <module>optical</module> 42 <module>optical</module>
43 <module>metrics</module> 43 <module>metrics</module>
44 + <module>oecfg</module>
44 <module>routing</module> 45 <module>routing</module>
45 <module>routing-api</module> 46 <module>routing-api</module>
46 <module>reactive-routing</module> 47 <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, OpticalLink, and OpticalSwitch 7 +such as startOE, stopOE, LINCLink, 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, OpticalLink, and OpticalSwitch ...@@ -22,10 +22,10 @@ such as startOE, stopOE, OpticalLink, and OpticalSwitch
22 22
23 Usage: 23 Usage:
24 ------------ 24 ------------
25 - - import OpticalLink and OpticalSwitch from this module 25 + - import LINCLink 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=OpticalLink 28 + to an optical switch with topo.addLink, always specify cls=LINCLink
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,11 +51,12 @@ switches have been started, the new Mininet start() method should also push the ...@@ -51,11 +51,12 @@ 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 - 54 +import sys
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
59 60
60 from mininet.node import Switch, RemoteController 61 from mininet.node import Switch, RemoteController
61 from mininet.topo import Topo 62 from mininet.topo import Topo
...@@ -65,25 +66,127 @@ from mininet.log import setLogLevel, info, error, warn ...@@ -65,25 +66,127 @@ from mininet.log import setLogLevel, info, error, warn
65 from mininet.link import Link, Intf 66 from mininet.link import Link, Intf
66 from mininet.cli import CLI 67 from mininet.cli import CLI
67 68
68 -class OpticalSwitch( Switch ): 69 +# Sleep time and timeout values in seconds
70 +SLEEP_TIME = 2
71 +TIMEOUT = 60
72 +
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
69 90
70 - def __init__( self, name, dpid=None, allowed=True, 91 +class LINCSwitch(OpticalSwitch):
71 - switchType='ROADM', annotations={}, **params ): 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):
72 params[ 'inNamespace' ] = False 164 params[ 'inNamespace' ] = False
73 - Switch.__init__( self, name, dpid=dpid, **params ) 165 + Switch.__init__(self, name, dpid=dpid, **params)
74 self.name = name 166 self.name = name
75 self.annotations = annotations 167 self.annotations = annotations
76 self.allowed = allowed 168 self.allowed = allowed
77 self.switchType = switchType 169 self.switchType = switchType
78 self.configDict = {} # dictionary that holds all of the JSON configuration data 170 self.configDict = {} # dictionary that holds all of the JSON configuration data
171 + self.crossConnects = []
172 + self.deletedCrossConnects = []
173 + self.controller = controller
174 + self.lincId = self._get_linc_id() # use to communicate with LINC
175 + self.lincStarted = False
79 176
80 - def start( self, *opts, **params ): 177 + def start(self, *opts, **params):
81 '''Instead of starting a virtual switch, we build the JSON 178 '''Instead of starting a virtual switch, we build the JSON
82 dictionary for the emulated optical switch''' 179 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()
83 self.configDict[ 'uri' ] = 'of:' + self.dpid 186 self.configDict[ 'uri' ] = 'of:' + self.dpid
84 self.configDict[ 'annotations' ] = self.annotations 187 self.configDict[ 'annotations' ] = self.annotations
85 - self.configDict[ 'annotations' ].setdefault( 'name', self.name ) 188 + self.configDict[ 'annotations' ].setdefault('name', self.name)
86 - self.configDict[ 'hw' ] = 'OE' 189 + self.configDict[ 'hw' ] = 'LINC-OE'
87 self.configDict[ 'mfr' ] = 'Linc' 190 self.configDict[ 'mfr' ] = 'Linc'
88 self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1] 191 self.configDict[ 'mac' ] = 'ffffffffffff' + self.dpid[-2] + self.dpid[-1]
89 self.configDict[ 'type' ] = self.switchType 192 self.configDict[ 'type' ] = self.switchType
...@@ -92,95 +195,137 @@ class OpticalSwitch( Switch ): ...@@ -92,95 +195,137 @@ class OpticalSwitch( Switch ):
92 if intf.name == 'lo': 195 if intf.name == 'lo':
93 continue 196 continue
94 else: 197 else:
95 - self.configDict[ 'ports' ].append( intf.json() ) 198 + self.configDict[ 'ports' ].append(intf.json())
96 - 199 + self.lincStarted = True
97 - 200 +
98 - def json( self ): 201 + def stop(self, deleteIntfs=False):
99 - "return json configuration dictionary for switch" 202 + '''
100 - return self.configDict 203 + stop the existing switch
101 - 204 + '''
102 - def terminate( self ): 205 + # TODO:Add support for deleteIntf
206 + self.stop_oe()
207 +
208 + def dpctl( self, *args ):
209 + "Run dpctl command: ignore for now"
103 pass 210 pass
104 211
105 -class OpticalLink( Link ): 212 + def write_to_cli(self, command):
106 - 213 + '''
107 - def __init__( self, node1, node2, port1=None, port2=None, allowed=True, 214 + send command to LINC
108 - intfName1=None, intfName2=None, linkType='OPTICAL', 215 + '''
109 - annotations={}, speed1=0, speed2=0, **params ): 216 + fd = None
110 - "Creates a dummy link without a virtual ethernet pair." 217 + try:
111 - self.allowed = allowed 218 + fd = open(self.writePipe, 'w', 0)
112 - self.annotations = annotations 219 + fd.write(command)
113 - self.linkType = linkType 220 + fd.close()
114 - params1 = { 'speed': speed1 } 221 + except:
115 - params2 = { 'speed': speed2 } 222 + print "Error working with {}\nError: {}\n".format(self.writePipe, sys.exc_info())
116 - 223 + if fd:
117 - if isinstance( node1, OpticalSwitch ): 224 + fd.close()
118 - cls1 = OpticalIntf 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
119 else: 268 else:
120 - cls1 = Intf 269 + intf = crossConnect.intf1
121 - # bad hack to stop error message from appearing when we try to set up intf in a packet switch, 270 + tapPort = crossConnect.intf2.port
122 - # and there is no interface there( because we do not run makeIntfPair ). This way, we just set lo up 271 + tap = LINCSwitch.findTap(self, tapPort)
123 - intfName1 = 'lo' 272 + if tap:
124 - if isinstance( node2, OpticalSwitch ): 273 + LINCSwitch.setupInts([tap])
125 - cls2 = OpticalIntf 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
126 else: 297 else:
127 - cls2 = Intf 298 + intf = crossConnect.intf1
128 - intfName2 = 'lo' 299 + tapPort = crossConnect.intf2.port
129 - Link.__init__( self, node1, node2, port1=port1, port2=port2, 300 + intf.node.detach(LINCSwitch.findTap(self, tapPort))
130 - intfName1=intfName1, intfName2=intfName2, cls1=cls1, 301 + self.deletedCrossConnects.append(crossConnect)
131 - cls2=cls2, params1=params1, params2=params2 ) 302 +
132 - 303 + def w_port_up(self, port):
133 - 304 + '''
134 - @classmethod 305 + port_up
135 - def makeIntfPair( _cls, intfName1, intfName2, *args, **kwargs ): 306 + '''
136 - pass 307 + cmd = "linc:port_up({},{}).\r\n".format(self.lincId, port)
137 - 308 + self.write_to_cli(cmd)
138 - def json( self ): 309 +
139 - "build and return the json configuration dictionary for this link" 310 + def w_port_down(self, port):
140 - configData = {} 311 + '''
141 - configData[ 'src' ] = ( 'of:' + self.intf1.node.dpid + 312 + port_down
142 - '/%s' % self.intf1.node.ports[ self.intf1 ] ) 313 + '''
143 - configData[ 'dst' ] = ( 'of:' + self.intf2.node.dpid + 314 + cmd = "linc:port_down({},{}).\r\n".format(self.lincId, port)
144 - '/%s' % self.intf2.node.ports[ self.intf2 ] ) 315 + self.write_to_cli(cmd)
145 - configData[ 'type' ] = self.linkType 316 +
146 - configData[ 'annotations' ] = self.annotations 317 + # helper functions
147 - return configData 318 + @staticmethod
148 - 319 + def switchJSON(switch):
149 -class OpticalIntf( Intf ):
150 -
151 - def __init__( self, name=None, node=None, speed=0,
152 - port=None, link=None, **params ):
153 - self.node = node
154 - self.speed = speed
155 - self.port = port
156 - self.link = link
157 - self.name = name
158 - node.addIntf( self, port=port )
159 - self.params = params
160 - self.ip = None
161 -
162 - def json( self ):
163 - "build and return the JSON information for this interface( not used right now )"
164 - configDict = {}
165 - configDict[ 'port' ] = self.port
166 - configDict[ 'speed' ] = self.speed
167 - configDict[ 'type' ] = 'FIBER'
168 - return configDict
169 -
170 - def config( self, *args, **kwargs ):
171 - "dont configure a dummy interface"
172 - pass
173 -
174 -def switchJSON( switch ):
175 "Returns the json configuration for a packet switch" 320 "Returns the json configuration for a packet switch"
176 configDict = {} 321 configDict = {}
177 configDict[ 'uri' ] = 'of:' + switch.dpid 322 configDict[ 'uri' ] = 'of:' + switch.dpid
178 - configDict[ 'mac' ] = quietRun( 'cat /sys/class/net/%s/address' % switch.name ).strip( '\n' ).translate( None, ':' ) 323 + configDict[ 'mac' ] = quietRun('cat /sys/class/net/%s/address' % switch.name).strip('\n').translate(None, ':')
179 configDict[ 'hw' ] = 'PK' # FIXME what about OVS? 324 configDict[ 'hw' ] = 'PK' # FIXME what about OVS?
180 configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS? 325 configDict[ 'mfr' ] = 'Linc' # FIXME what about OVS?
181 configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS? 326 configDict[ 'type' ] = 'SWITCH' # FIXME what about OVS?
182 - annotations = switch.params.get( 'annotations', {} ) 327 + annotations = switch.params.get('annotations', {})
183 - annotations.setdefault( 'name', switch.name ) 328 + annotations.setdefault('name', switch.name)
184 configDict[ 'annotations' ] = annotations 329 configDict[ 'annotations' ] = annotations
185 ports = [] 330 ports = []
186 for port, intf in switch.intfs.items(): 331 for port, intf in switch.intfs.items():
...@@ -188,234 +333,176 @@ def switchJSON( switch ): ...@@ -188,234 +333,176 @@ def switchJSON( switch ):
188 continue 333 continue
189 portDict = {} 334 portDict = {}
190 portDict[ 'port' ] = port 335 portDict[ 'port' ] = port
191 - portDict[ 'type' ] = 'FIBER' if isinstance( intf.link, OpticalLink ) else 'COPPER' 336 + portDict[ 'type' ] = 'FIBER' if isinstance(intf.link, LINCLink) else 'COPPER'
192 intfList = [ intf.link.intf1, intf.link.intf2 ] 337 intfList = [ intf.link.intf1, intf.link.intf2 ]
193 - intfList.remove( intf ) 338 + intfList.remove(intf)
194 - portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance( intf.link, OpticalLink ) else 0 339 + portDict[ 'speed' ] = intfList[ 0 ].speed if isinstance(intf.link, LINCLink) else 0
195 - ports.append( portDict ) 340 + ports.append(portDict)
196 configDict[ 'ports' ] = ports 341 configDict[ 'ports' ] = ports
197 return configDict 342 return configDict
198 343
199 - 344 + @staticmethod
200 -def startOE( net ): 345 + def bootOE(net):
201 "Start the LINC optical emulator within a mininet instance" 346 "Start the LINC optical emulator within a mininet instance"
202 opticalJSON = {} 347 opticalJSON = {}
203 linkConfig = [] 348 linkConfig = []
204 devices = [] 349 devices = []
350 + #setting up the controllers for LINCSwitch class
351 + LINCSwitch.controllers = net.controllers
205 352
206 for switch in net.switches: 353 for switch in net.switches:
207 - if isinstance( switch, OpticalSwitch ): 354 + if isinstance(switch, OpticalSwitch):
208 - devices.append( switch.json() ) 355 + devices.append(switch.json())
209 else: 356 else:
210 - devices.append( switchJSON( switch ) ) 357 + devices.append(LINCSwitch.switchJSON(switch))
211 opticalJSON[ 'devices' ] = devices 358 opticalJSON[ 'devices' ] = devices
212 359
213 for link in net.links: 360 for link in net.links:
214 - if isinstance( link, OpticalLink ) : 361 + if isinstance(link, LINCLink) :
215 - linkConfig.append( link.json() ) 362 + linkConfig.append(link.json())
216 -
217 opticalJSON[ 'links' ] = linkConfig 363 opticalJSON[ 'links' ] = linkConfig
218 364
219 - try: 365 + info('*** Writing Topology.json file\n')
220 - onosDir = os.environ[ 'ONOS_ROOT' ] 366 + with open('Topology.json', 'w') as outfile:
221 - except: 367 + json.dump(opticalJSON, outfile, indent=4, separators=(',', ': '))
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"
269 -
270 - #append to list of switches
271 - switchConfig.append(builtSwitch);
272 -
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 368
308 - #Writing to TopoConfig.json 369 + info('*** Converting Topology.json to linc-oe format (TopoConfig.json) file\n')
309 - with open( 'TopoConfig.json', 'w' ) as outfile: 370 + output = quietRun('%s/tools/test/bin/onos-oecfg ./Topology.json > TopoConfig.json' % LINCSwitch.onosDir, shell=True)
310 - json.dump( topoConfigJson, outfile, indent=4, separators=(',', ': ') ) 371 + if output:
311 - 372 + error('***ERROR: Error creating topology file: %s ' % output + '\n')
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 373 return False
317 - output = quietRun( '%s/config_generator TopoConfig.json %s/sys.config.template %s %s' 374 +
318 - % ( configGen, configGen, net.controllers[ 0 ].ip, net.controllers[ 0 ].port ), shell=True ) 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)
319 if output: 378 if output:
320 - error( '***ERROR: Error creating sys.config file: %s\n' % output ) 379 + error('***ERROR: Error creating sys.config file: %s\n' % output)
321 return False 380 return False
322 381
323 - info ('*** Setting multiple controllers in sys.config...\n' ) 382 + info ('*** Setting multiple controllers in sys.config...\n')
324 - searchStr = '{controllers,.*$' 383 + searchStr = '\[{"Switch.*$'
325 ctrlStr = '' 384 ctrlStr = ''
326 - for index in range(len(net.controllers)): 385 + for index in range(len(LINCSwitch.controllers)):
327 ctrlStr += '{"Switch%d-Controller","%s",%d,tcp},' % (index, net.controllers[index].ip, net.controllers[index].port) 386 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 387 + replaceStr = '[%s]},' % ctrlStr[:-1] # Cut off last comma
329 sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr) 388 sedCmd = 'sed -i \'s/%s/%s/\' sys.config' % (searchStr, replaceStr)
330 - output = quietRun( sedCmd, shell=True ) 389 + output = quietRun(sedCmd, shell=True)
331 390
332 - info( '*** Copying sys.config to linc-oe directory: ', output + '\n' ) 391 + info('*** Copying sys.config to linc-oe directory: ', output + '\n')
333 - lincDir = findDir( 'linc-oe' ) 392 + output = quietRun('cp -v sys.config %s/rel/linc/releases/1.0/' % LINCSwitch.lincDir, shell=True).strip('\n')
334 - if not lincDir: 393 + info(output + '\n')
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 394
340 - info( '*** Starting linc OE...\n' ) 395 + info('*** Adding taps and bringing them up...\n')
341 - output = quietRun( '%s/rel/linc/bin/linc start' % lincDir, shell=True ) 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)
342 if output: 403 if output:
343 - error( '***ERROR: LINC-OE: %s' % output + '\n' ) 404 + error('***ERROR: LINC-OE: %s' % output + '\n')
344 - quietRun( '%s/rel/linc/bin/linc stop' % lincDir, shell=True ) 405 + quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
345 return False 406 return False
346 407
347 - info( '*** Waiting for linc-oe to start...\n' ) 408 + info('*** Waiting for linc-oe to start...\n')
348 - waitStarted( net ) 409 + LINCSwitch.waitStarted(net)
349 410
350 - info( '*** Adding cross-connect (tap) interfaces to packet switches...\n' ) 411 + info('*** Adding cross-connect (tap) interfaces to packet switches...\n')
351 for link in net.links: 412 for link in net.links:
352 - if isinstance( link, OpticalLink ): 413 + if isinstance(link, LINCLink):
353 if link.annotations[ 'optical.type' ] == 'cross-connect': 414 if link.annotations[ 'optical.type' ] == 'cross-connect':
354 for intf in [ link.intf1, link.intf2 ]: 415 for intf in [ link.intf1, link.intf2 ]:
355 - if not isinstance( intf, OpticalIntf ): 416 + if not isinstance(intf, LINCIntf):
356 intfList = [ intf.link.intf1, intf.link.intf2 ] 417 intfList = [ intf.link.intf1, intf.link.intf2 ]
357 - intfList.remove( intf ) 418 + intfList.remove(intf)
358 intf2 = intfList[ 0 ] 419 intf2 = intfList[ 0 ]
359 - intf.node.attach( findTap( intf2.node, intf2.node.ports[ intf2 ] ) ) 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')
360 428
361 - info( '*** Press ENTER to push Topology.json to onos...\n' ) 429 + # Wait for all devices to be registered
362 - raw_input() # FIXME... we should eventually remove this 430 + if (len(devices) != len(devs)):
363 - info( '*** Pushing Topology.json to ONOS\n' ) 431 + continue
364 - output = quietRun( '%s/tools/test/bin/onos-topo-cfg %s Topology.json' % ( onosDir, net.controllers[ 0 ].ip ), shell=True ) 432 +
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)
365 # successful output contains the two characters '{}' 450 # successful output contains the two characters '{}'
366 # if there is more output than this, there is an issue 451 # if there is more output than this, there is an issue
367 - if output.strip( '{}' ): 452 + if output.strip('{}'):
368 - warn( '***WARNING: Could not push topology file to ONOS: %s' % output ) 453 + warn('***WARNING: Could not push topology file to ONOS: %s\n' % output)
369 - 454 +
370 -#converts node ids to linc-oe format, with colons every two chars 455 + @staticmethod
371 -def dpId(id): 456 + def waitStarted(net, timeout=TIMEOUT):
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" 457 "wait until all tap interfaces are available"
380 tapCount = 0 458 tapCount = 0
381 time = 0 459 time = 0
382 for link in net.links: 460 for link in net.links:
383 - if isinstance( link, OpticalLink ): 461 + if isinstance(link, LINCLink):
384 if link.annotations[ 'optical.type' ] == 'cross-connect': 462 if link.annotations[ 'optical.type' ] == 'cross-connect':
385 tapCount += 1 463 tapCount += 1
386 464
387 while True: 465 while True:
388 - if str( tapCount ) == quietRun( 'ip addr | grep tap | wc -l', shell=True ).strip( '\n' ): 466 + if str(tapCount) == quietRun('ip addr | grep tap | wc -l', shell=True).strip('\n'):
389 return True 467 return True
390 if timeout: 468 if timeout:
391 - if time >= timeout: 469 + if time >= TIMEOUT:
392 - error( '***ERROR: Linc OE did not start within %s seconds' % timeout ) 470 + error('***ERROR: LINC OE did not start within %s seconds\n' % TIMEOUT)
393 return False 471 return False
394 - time += .5 472 + time += SLEEP_TIME
395 - sleep( .5 ) 473 + sleep(SLEEP_TIME)
396 474
397 -def stopOE(): 475 + @staticmethod
476 + def shutdownOE():
398 "stop the optical emulator" 477 "stop the optical emulator"
399 - info( '*** Stopping linc OE...\n' ) 478 + info('*** Stopping linc OE...\n')
400 - lincDir = findDir( 'linc-oe' ) 479 + quietRun('%s/rel/linc/bin/linc stop' % LINCSwitch.lincDir, shell=True)
401 - quietRun( '%s/rel/linc/bin/linc stop' % lincDir, shell=True ) 480 +
402 - 481 + @staticmethod
403 -def findDir( directory ): 482 + def setupInts(intfs):
404 - "finds and returns the path of any directory in the user's home directory" 483 + '''
405 - user = findUser() 484 + add taps and bring them up.
406 - homeDir = '/home/' + user 485 + '''
407 - Dir = quietRun( 'find %s -maxdepth 1 -name %s -type d' % ( homeDir, directory ) ).strip( '\n' ) 486 + for i in intfs:
408 - DirList = Dir.split( '\n' ) 487 + quietRun('ip tuntap add dev %s mode tap' % i)
409 - if not Dir: 488 + quietRun('ip link set dev %s up' % i)
410 - return None 489 + info('*** Intf %s set\n' % i)
411 - elif len( DirList ) > 1 : 490 +
412 - warn( '***WARNING: Found multiple instances of %s; using %s\n' 491 + @staticmethod
413 - % ( directory, DirList[ 0 ] ) ) 492 + def getTaps(path=None):
414 - return DirList[ 0 ] 493 + '''
415 - else: 494 + return list of all the tops in sys.config
416 - return Dir 495 + '''
417 - 496 + if path is None:
418 -def findUser(): 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():
419 "Try to return logged-in (usually non-root) user" 506 "Try to return logged-in (usually non-root) user"
420 try: 507 try:
421 # If we're running sudo 508 # If we're running sudo
...@@ -423,32 +510,29 @@ def findUser(): ...@@ -423,32 +510,29 @@ def findUser():
423 except: 510 except:
424 try: 511 try:
425 # Logged-in user (if we have a tty) 512 # Logged-in user (if we have a tty)
426 - return quietRun( 'who am i' ).split()[ 0 ] 513 + return quietRun('who am i').split()[ 0 ]
427 except: 514 except:
428 # Give up and return effective user 515 # Give up and return effective user
429 - return quietRun( 'whoami' ) 516 + return quietRun('whoami')
430 517
431 518
432 -def findTap( node, port, path=None ): 519 + @staticmethod
520 + def findTap(node, port, path=None):
433 '''utility function to parse through a sys.config 521 '''utility function to parse through a sys.config
434 file to find tap interfaces for a switch''' 522 file to find tap interfaces for a switch'''
435 - switch=False 523 + switch = False
436 portLine = '' 524 portLine = ''
437 intfLines = [] 525 intfLines = []
438 526
439 if path is None: 527 if path is None:
440 - lincDir = findDir( 'linc-oe' ) 528 + path = '%s/rel/linc/releases/1.0/sys.config' % LINCSwitch.lincDir
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 529
446 - with open( path ) as f: 530 + with open(path) as f:
447 for line in f: 531 for line in f:
448 if 'tap' in line: 532 if 'tap' in line:
449 - intfLines.append( line ) 533 + intfLines.append(line)
450 - if node.dpid in line.translate( None, ':' ): 534 + if node.dpid in line.translate(None, ':'):
451 - switch=True 535 + switch = True
452 continue 536 continue
453 if switch: 537 if switch:
454 if 'switch' in line: 538 if 'switch' in line:
...@@ -458,65 +542,129 @@ def findTap( node, port, path=None ): ...@@ -458,65 +542,129 @@ def findTap( node, port, path=None ):
458 break 542 break
459 543
460 if portLine: 544 if portLine:
461 - m = re.search( 'port,\d+', portLine ) 545 + m = re.search('port,\d+', portLine)
462 - port = m.group( 0 ).split( ',' )[ 1 ] 546 + port = m.group(0).split(',')[ 1 ]
463 else: 547 else:
464 - error( '***ERROR: Could not find any ports in sys.config\n' ) 548 + error('***ERROR: Could not find any ports in sys.config\n')
465 return 549 return
466 550
467 for intfLine in intfLines: 551 for intfLine in intfLines:
468 if 'port,%s' % port in intfLine: 552 if 'port,%s' % port in intfLine:
469 - return re.findall( 'tap\d+', intfLine )[ 0 ] 553 + return re.findall('tap\d+', intfLine)[ 0 ]
554 +
555 + def json(self):
556 + "return json configuration dictionary for switch"
557 + return self.configDict
470 558
559 + def terminate(self):
560 + pass
471 561
472 -class MininetOE( Mininet ): 562 +class LINCLink(Link):
563 + """
564 + LINC link class
565 + """
566 + def __init__(self, node1, node2, port1=None, port2=None, allowed=True,
567 + intfName1=None, intfName2=None, linkType='OPTICAL',
568 + annotations={}, speed1=0, speed2=0, **params):
569 + "Creates a dummy link without a virtual ethernet pair."
570 + self.allowed = allowed
571 + self.annotations = annotations
572 + self.linkType = linkType
573 + self.port1 = port1
574 + self.port2 = port2
575 + params1 = { 'speed': speed1 }
576 + params2 = { 'speed': speed2 }
577 + # self.isCrossConnect = True if self.annotations.get('optical.type') == 'cross-connect' else False
578 + if isinstance(node1, LINCSwitch) and isinstance(node2, LINCSwitch):
579 + self.isCrossConnect = False
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:
587 + cls1 = Intf
588 + # 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
590 + intfName1 = 'lo'
591 + if isinstance(node2, LINCSwitch):
592 + cls2 = LINCIntf
593 + if self.isCrossConnect:
594 + node2.crossConnects.append(self)
595 + else:
596 + cls2 = Intf
597 + intfName2 = 'lo'
598 + Link.__init__(self, node1, node2, port1=port1, port2=port2,
599 + intfName1=intfName1, intfName2=intfName2, cls1=cls1,
600 + cls2=cls2, params1=params1, params2=params2)
601 +
602 + @classmethod
603 + def makeIntfPair(_cls, intfName1, intfName2, *args, **kwargs):
604 + pass
605 +
606 + def json(self):
607 + "build and return the json configuration dictionary for this link"
608 + configData = {}
609 + configData[ 'src' ] = ('of:' + self.intf1.node.dpid +
610 + '/%s' % self.intf1.node.ports[ self.intf1 ])
611 + configData[ 'dst' ] = ('of:' + self.intf2.node.dpid +
612 + '/%s' % self.intf2.node.ports[ self.intf2 ])
613 + configData[ 'type' ] = self.linkType
614 + configData[ 'annotations' ] = self.annotations
615 + return configData
616 +
617 +class LINCIntf(OpticalIntf):
618 + """
619 + LINC interface class
620 + """
621 + def __init__(self, name=None, node=None, speed=0,
622 + port=None, link=None, **params):
623 + self.node = node
624 + self.speed = speed
625 + self.port = port
626 + self.link = link
627 + self.name = name
628 + node.addIntf(self, port=port)
629 + self.params = params
630 + self.ip = None
631 +
632 + def json(self):
633 + "build and return the JSON information for this interface( not used right now )"
634 + configDict = {}
635 + configDict[ 'port' ] = self.port
636 + configDict[ 'speed' ] = self.speed
637 + configDict[ 'type' ] = 'FIBER'
638 + return configDict
639 +
640 + def config(self, *args, **kwargs):
641 + "dont configure a dummy interface"
642 + pass
643 +
644 + def ifconfig(self, status):
645 + "configure the status"
646 + if status == "up":
647 + return self.node.w_port_up(self.port)
648 + elif status == "down":
649 + return self.node.w_port_down(self.port)
650 +
651 +
652 +class MininetOE(Mininet):
473 "Mininet with Linc-OE support (starts and stops linc-oe)" 653 "Mininet with Linc-OE support (starts and stops linc-oe)"
474 654
475 - def start( self ): 655 + def start(self):
476 - Mininet.start( self ) 656 + Mininet.start(self)
477 - startOE( self ) 657 + LINCSwitch.bootOE(self)
478 658
479 - def stop( self ): 659 + def stop(self):
480 - Mininet.stop( self ) 660 + Mininet.stop(self)
481 - stopOE() 661 + LINCSwitch.shutdownOE()
482 662
483 - def addControllers( self, controllers ): 663 + def addControllers(self, controllers):
484 i = 0 664 i = 0
485 for ctrl in controllers: 665 for ctrl in controllers:
486 - self.addController( RemoteController( 'c%d' % i, ip=ctrl ) ) 666 + self.addController(RemoteController('c%d' % i, ip=ctrl))
487 - 667 + i += 1
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 )
507 668
508 if __name__ == '__main__': 669 if __name__ == '__main__':
509 - import sys 670 + pass
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()
......