mirror of
https://github.com/opennetworkinglab/onos.git
synced 2025-10-16 18:02:05 +02:00
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
123 lines
4.4 KiB
Python
123 lines
4.4 KiB
Python
import socket
|
|
|
|
from mininet.log import error, info
|
|
from mininet.node import Switch
|
|
from os import environ
|
|
from os.path import isfile
|
|
|
|
|
|
class ONOSBmv2Switch(Switch):
|
|
"""BMv2 software switch """
|
|
|
|
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 thriftPort:
|
|
self.thriftPort = 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)
|
|
else:
|
|
self.deviceId = ONOSBmv2Switch.deviceId
|
|
ONOSBmv2Switch.deviceId += 1
|
|
else:
|
|
self.deviceId = deviceId
|
|
ONOSBmv2Switch.deviceId = max(deviceId, ONOSBmv2Switch.deviceId)
|
|
self.debugger = debugger
|
|
self.loglevel = loglevel
|
|
self.logfile = '/tmp/bmv2-%d.log' % self.deviceId
|
|
self.output = open(self.logfile, 'w')
|
|
self.elogger = elogger
|
|
self.persistent = persistent
|
|
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)
|
|
|
|
def start(self, controllers):
|
|
args = [self.swPath, '--device-id %s' % str(self.deviceId)]
|
|
for port, intf in self.intfs.items():
|
|
if not intf.IP():
|
|
args.append('-i %d@%s' % (port, intf.name))
|
|
if self.thriftPort:
|
|
args.append('--thrift-port %d' % self.thriftPort)
|
|
if self.elogger:
|
|
nanomsg = 'ipc:///tmp/bmv2-%d-log.ipc' % self.deviceId
|
|
args.append('--nanolog %s' % nanomsg)
|
|
if self.debugger:
|
|
args.append('--debugger')
|
|
args.append('--log-console -L%s' % self.loglevel)
|
|
args.append(self.jsonPath)
|
|
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' % 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 {} ]; " \
|
|
"do {} ; " \
|
|
"sleep 1; " \
|
|
"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()
|
|
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}
|