Carmelo Cascone
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
import socket
from mininet.log import error, info
from mininet.node import Switch
from os import environ
......@@ -7,20 +9,18 @@ from os.path import isfile
class ONOSBmv2Switch(Switch):
"""BMv2 software switch """
thriftPort = 9090
deviceId = 0
instanceCount = 0
def __init__(self, name, thriftPort=None, deviceId=None, debugger=False,
loglevel="warn", elogger=False, persistent=True, **kwargs):
Switch.__init__(self, name, **kwargs)
self.swPath = environ['BMV2_EXE']
self.jsonPath = environ['BMV2_JSON']
if not thriftPort:
self.thriftPort = ONOSBmv2Switch.thriftPort
ONOSBmv2Switch.thriftPort += 1
else:
if thriftPort:
self.thriftPort = thriftPort
ONOSBmv2Switch.thriftPort = max(thriftPort, ONOSBmv2Switch.thriftPort)
else:
self.thriftPort = ONOSBmv2Switch.pickUnusedPort()
if not deviceId:
if self.dpid:
self.deviceId = int(self.dpid, 0 if 'x' in self.dpid else 16)
......@@ -39,25 +39,32 @@ class ONOSBmv2Switch(Switch):
if persistent:
self.exectoken = "/tmp/bmv2-%d-exec-token" % self.deviceId
self.cmd("touch %s" % self.exectoken)
# Store thrift port for future uses.
self.cmd("echo %d > /tmp/bmv2-%d-thrift-port" % (self.thriftPort, self.deviceId))
@classmethod
def pickUnusedPort(cls):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('localhost', 0))
addr, port = s.getsockname()
s.close()
return port
@classmethod
def setup(cls):
err = False
if 'BMV2_EXE' not in environ:
error("ERROR! environment var $BMV2_EXE not set\n")
err = True
elif not isfile(environ['BMV2_EXE']):
error("ERROR! BMV2_EXE=%s: no such file\n" % environ['BMV2_EXE'])
err = True
if 'BMV2_JSON' not in environ:
error("ERROR! environment var $BMV2_JSON not set\n")
err = True
elif not isfile(environ['BMV2_JSON']):
error("ERROR! BMV2_JSON=%s: no such file\n" % environ['BMV2_JSON'])
err = True
if err:
exit(1)
......@@ -75,17 +82,23 @@ class ONOSBmv2Switch(Switch):
args.append('--debugger')
args.append('--log-console -L%s' % self.loglevel)
args.append(self.jsonPath)
assert controllers[0]
c = controllers[0]
try: # onos.py
clist = controllers[0].nodes()
except AttributeError:
clist = controllers
assert len(clist) > 0
# BMv2 can't connect to multiple controllers.
# Uniformly balance connections among available ones.
cip = clist[ONOSBmv2Switch.instanceCount % len(clist)].IP()
ONOSBmv2Switch.instanceCount += 1
# BMv2 controler port is hardcoded here as it is hardcoded also in ONOS.
cport = 40123
args.append('--')
args.append('--controller-ip %s' % c.IP())
args.append('--controller-port %d' % c.port)
args.append('--controller-ip %s' % cip)
args.append('--controller-port %d' % cport)
bmv2cmd = " ".join(args)
info("\nStarting BMv2 target: %s\n" % bmv2cmd)
if self.persistent:
# Re-exec the switch if it crashes.
cmdStr = "(while [ -e {} ]; " \
......@@ -94,18 +107,16 @@ class ONOSBmv2Switch(Switch):
"done;) > {} 2>&1 &".format(self.exectoken, bmv2cmd, self.logfile)
else:
cmdStr = "{} > {} 2>&1 &".format(bmv2cmd, self.logfile)
self.cmd(cmdStr)
def stop(self):
"Terminate switch."
self.output.flush()
if self.persistent:
self.cmd("rm -f %s" % self.exectoken)
self.cmd("rm -f /tmp/bmv2-%d-*" % self.deviceId)
self.cmd("rm -f /tmp/bmv2-%d.log" % self.deviceId)
self.cmd('kill %' + self.swPath)
self.deleteIntfs()
### Exports for bin/mn
switches = {'onosbmv2': ONOSBmv2Switch}
......
#!/usr/bin/python
import os
import sys
import argparse
# Find and import bmv2.py
if 'ONOS_ROOT' not in os.environ:
print "Environment var $ONOS_ROOT not set"
exit()
else:
sys.path.append(os.environ["ONOS_ROOT"] + "/tools/dev/mininet")
from bmv2 import ONOSBmv2Switch
from itertools import combinations
from time import sleep
from bmv2 import ONOSBmv2Switch
from mininet.cli import CLI
from mininet.link import TCLink
from mininet.log import setLogLevel
......@@ -29,8 +39,8 @@ class ClosTopo(Topo):
bmv2Switches[switchId] = self.addSwitch(switchId,
cls=ONOSBmv2Switch,
loglevel="warn",
device_id=int(switchId[1:]),
thrift_port=tport)
deviceId=int(switchId[1:]),
thriftPort=tport)
tport += 1
for i in (1, 2, 3):
......