Committed by
Jonathan Hart
Varius updates to BMv2 mininet scripts
Most notably: - Added support for onos.py's ONOSCluster controller (it works with "mn --custom onos.py,bmv2.py --switch onosbmv2 ...") - Randomly select an open port for the Thrift RPC server Change-Id: Ifa974741dc4a3693777f01866b1f6203d0e7e75e
Showing
2 changed files
with
44 additions
and
23 deletions
1 | +import socket | ||
2 | + | ||
1 | from mininet.log import error, info | 3 | from mininet.log import error, info |
2 | from mininet.node import Switch | 4 | from mininet.node import Switch |
3 | from os import environ | 5 | from os import environ |
... | @@ -7,20 +9,18 @@ from os.path import isfile | ... | @@ -7,20 +9,18 @@ from os.path import isfile |
7 | class ONOSBmv2Switch(Switch): | 9 | class ONOSBmv2Switch(Switch): |
8 | """BMv2 software switch """ | 10 | """BMv2 software switch """ |
9 | 11 | ||
10 | - thriftPort = 9090 | ||
11 | deviceId = 0 | 12 | deviceId = 0 |
13 | + instanceCount = 0 | ||
12 | 14 | ||
13 | def __init__(self, name, thriftPort=None, deviceId=None, debugger=False, | 15 | def __init__(self, name, thriftPort=None, deviceId=None, debugger=False, |
14 | loglevel="warn", elogger=False, persistent=True, **kwargs): | 16 | loglevel="warn", elogger=False, persistent=True, **kwargs): |
15 | Switch.__init__(self, name, **kwargs) | 17 | Switch.__init__(self, name, **kwargs) |
16 | self.swPath = environ['BMV2_EXE'] | 18 | self.swPath = environ['BMV2_EXE'] |
17 | self.jsonPath = environ['BMV2_JSON'] | 19 | self.jsonPath = environ['BMV2_JSON'] |
18 | - if not thriftPort: | 20 | + if thriftPort: |
19 | - self.thriftPort = ONOSBmv2Switch.thriftPort | ||
20 | - ONOSBmv2Switch.thriftPort += 1 | ||
21 | - else: | ||
22 | self.thriftPort = thriftPort | 21 | self.thriftPort = thriftPort |
23 | - ONOSBmv2Switch.thriftPort = max(thriftPort, ONOSBmv2Switch.thriftPort) | 22 | + else: |
23 | + self.thriftPort = ONOSBmv2Switch.pickUnusedPort() | ||
24 | if not deviceId: | 24 | if not deviceId: |
25 | if self.dpid: | 25 | if self.dpid: |
26 | self.deviceId = int(self.dpid, 0 if 'x' in self.dpid else 16) | 26 | self.deviceId = int(self.dpid, 0 if 'x' in self.dpid else 16) |
... | @@ -39,25 +39,32 @@ class ONOSBmv2Switch(Switch): | ... | @@ -39,25 +39,32 @@ class ONOSBmv2Switch(Switch): |
39 | if persistent: | 39 | if persistent: |
40 | self.exectoken = "/tmp/bmv2-%d-exec-token" % self.deviceId | 40 | self.exectoken = "/tmp/bmv2-%d-exec-token" % self.deviceId |
41 | self.cmd("touch %s" % self.exectoken) | 41 | self.cmd("touch %s" % self.exectoken) |
42 | + # Store thrift port for future uses. | ||
43 | + self.cmd("echo %d > /tmp/bmv2-%d-thrift-port" % (self.thriftPort, self.deviceId)) | ||
44 | + | ||
45 | + @classmethod | ||
46 | + def pickUnusedPort(cls): | ||
47 | + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | ||
48 | + s.bind(('localhost', 0)) | ||
49 | + addr, port = s.getsockname() | ||
50 | + s.close() | ||
51 | + return port | ||
42 | 52 | ||
43 | @classmethod | 53 | @classmethod |
44 | def setup(cls): | 54 | def setup(cls): |
45 | err = False | 55 | err = False |
46 | - | ||
47 | if 'BMV2_EXE' not in environ: | 56 | if 'BMV2_EXE' not in environ: |
48 | error("ERROR! environment var $BMV2_EXE not set\n") | 57 | error("ERROR! environment var $BMV2_EXE not set\n") |
49 | err = True | 58 | err = True |
50 | elif not isfile(environ['BMV2_EXE']): | 59 | elif not isfile(environ['BMV2_EXE']): |
51 | error("ERROR! BMV2_EXE=%s: no such file\n" % environ['BMV2_EXE']) | 60 | error("ERROR! BMV2_EXE=%s: no such file\n" % environ['BMV2_EXE']) |
52 | err = True | 61 | err = True |
53 | - | ||
54 | if 'BMV2_JSON' not in environ: | 62 | if 'BMV2_JSON' not in environ: |
55 | error("ERROR! environment var $BMV2_JSON not set\n") | 63 | error("ERROR! environment var $BMV2_JSON not set\n") |
56 | err = True | 64 | err = True |
57 | elif not isfile(environ['BMV2_JSON']): | 65 | elif not isfile(environ['BMV2_JSON']): |
58 | error("ERROR! BMV2_JSON=%s: no such file\n" % environ['BMV2_JSON']) | 66 | error("ERROR! BMV2_JSON=%s: no such file\n" % environ['BMV2_JSON']) |
59 | err = True | 67 | err = True |
60 | - | ||
61 | if err: | 68 | if err: |
62 | exit(1) | 69 | exit(1) |
63 | 70 | ||
... | @@ -75,17 +82,23 @@ class ONOSBmv2Switch(Switch): | ... | @@ -75,17 +82,23 @@ class ONOSBmv2Switch(Switch): |
75 | args.append('--debugger') | 82 | args.append('--debugger') |
76 | args.append('--log-console -L%s' % self.loglevel) | 83 | args.append('--log-console -L%s' % self.loglevel) |
77 | args.append(self.jsonPath) | 84 | args.append(self.jsonPath) |
78 | - | 85 | + try: # onos.py |
79 | - assert controllers[0] | 86 | + clist = controllers[0].nodes() |
80 | - c = controllers[0] | 87 | + except AttributeError: |
88 | + clist = controllers | ||
89 | + assert len(clist) > 0 | ||
90 | + # BMv2 can't connect to multiple controllers. | ||
91 | + # Uniformly balance connections among available ones. | ||
92 | + cip = clist[ONOSBmv2Switch.instanceCount % len(clist)].IP() | ||
93 | + ONOSBmv2Switch.instanceCount += 1 | ||
94 | + # BMv2 controler port is hardcoded here as it is hardcoded also in ONOS. | ||
95 | + cport = 40123 | ||
81 | args.append('--') | 96 | args.append('--') |
82 | - args.append('--controller-ip %s' % c.IP()) | 97 | + args.append('--controller-ip %s' % cip) |
83 | - args.append('--controller-port %d' % c.port) | 98 | + args.append('--controller-port %d' % cport) |
84 | 99 | ||
85 | bmv2cmd = " ".join(args) | 100 | bmv2cmd = " ".join(args) |
86 | - | ||
87 | info("\nStarting BMv2 target: %s\n" % bmv2cmd) | 101 | info("\nStarting BMv2 target: %s\n" % bmv2cmd) |
88 | - | ||
89 | if self.persistent: | 102 | if self.persistent: |
90 | # Re-exec the switch if it crashes. | 103 | # Re-exec the switch if it crashes. |
91 | cmdStr = "(while [ -e {} ]; " \ | 104 | cmdStr = "(while [ -e {} ]; " \ |
... | @@ -94,18 +107,16 @@ class ONOSBmv2Switch(Switch): | ... | @@ -94,18 +107,16 @@ class ONOSBmv2Switch(Switch): |
94 | "done;) > {} 2>&1 &".format(self.exectoken, bmv2cmd, self.logfile) | 107 | "done;) > {} 2>&1 &".format(self.exectoken, bmv2cmd, self.logfile) |
95 | else: | 108 | else: |
96 | cmdStr = "{} > {} 2>&1 &".format(bmv2cmd, self.logfile) | 109 | cmdStr = "{} > {} 2>&1 &".format(bmv2cmd, self.logfile) |
97 | - | ||
98 | self.cmd(cmdStr) | 110 | self.cmd(cmdStr) |
99 | 111 | ||
100 | def stop(self): | 112 | def stop(self): |
101 | "Terminate switch." | 113 | "Terminate switch." |
102 | self.output.flush() | 114 | self.output.flush() |
103 | - if self.persistent: | 115 | + self.cmd("rm -f /tmp/bmv2-%d-*" % self.deviceId) |
104 | - self.cmd("rm -f %s" % self.exectoken) | 116 | + self.cmd("rm -f /tmp/bmv2-%d.log" % self.deviceId) |
105 | self.cmd('kill %' + self.swPath) | 117 | self.cmd('kill %' + self.swPath) |
106 | self.deleteIntfs() | 118 | self.deleteIntfs() |
107 | 119 | ||
108 | 120 | ||
109 | ### Exports for bin/mn | 121 | ### Exports for bin/mn |
110 | - | ||
111 | switches = {'onosbmv2': ONOSBmv2Switch} | 122 | switches = {'onosbmv2': ONOSBmv2Switch} | ... | ... |
1 | #!/usr/bin/python | 1 | #!/usr/bin/python |
2 | 2 | ||
3 | +import os | ||
4 | +import sys | ||
3 | import argparse | 5 | import argparse |
6 | + | ||
7 | +# Find and import bmv2.py | ||
8 | +if 'ONOS_ROOT' not in os.environ: | ||
9 | + print "Environment var $ONOS_ROOT not set" | ||
10 | + exit() | ||
11 | +else: | ||
12 | + sys.path.append(os.environ["ONOS_ROOT"] + "/tools/dev/mininet") | ||
13 | + from bmv2 import ONOSBmv2Switch | ||
14 | + | ||
4 | from itertools import combinations | 15 | from itertools import combinations |
5 | from time import sleep | 16 | from time import sleep |
6 | 17 | ||
7 | -from bmv2 import ONOSBmv2Switch | ||
8 | from mininet.cli import CLI | 18 | from mininet.cli import CLI |
9 | from mininet.link import TCLink | 19 | from mininet.link import TCLink |
10 | from mininet.log import setLogLevel | 20 | from mininet.log import setLogLevel |
... | @@ -29,8 +39,8 @@ class ClosTopo(Topo): | ... | @@ -29,8 +39,8 @@ class ClosTopo(Topo): |
29 | bmv2Switches[switchId] = self.addSwitch(switchId, | 39 | bmv2Switches[switchId] = self.addSwitch(switchId, |
30 | cls=ONOSBmv2Switch, | 40 | cls=ONOSBmv2Switch, |
31 | loglevel="warn", | 41 | loglevel="warn", |
32 | - device_id=int(switchId[1:]), | 42 | + deviceId=int(switchId[1:]), |
33 | - thrift_port=tport) | 43 | + thriftPort=tport) |
34 | tport += 1 | 44 | tport += 1 |
35 | 45 | ||
36 | for i in (1, 2, 3): | 46 | for i in (1, 2, 3): | ... | ... |
-
Please register or login to post a comment