Added option to run Bmv2 with valgrind in bmv2.py
Helpful to debug Bmv2 memory leaks.
Change-Id: I404914201c00203ab3050c439fd7af8a608774d2
diff --git a/tools/dev/mininet/bmv2.py b/tools/dev/mininet/bmv2.py
index 5a4de21..e942646 100644
--- a/tools/dev/mininet/bmv2.py
+++ b/tools/dev/mininet/bmv2.py
@@ -4,6 +4,8 @@
import json
import urllib2
+import time
+
from mininet.log import info, warn, error
from mininet.node import Switch, Host
@@ -15,6 +17,15 @@
ONOS_ROOT = os.environ["ONOS_ROOT"]
CPU_PORT = 255
PKT_BYTES_TO_DUMP = 80
+VALGRIND_PREFIX = 'valgrind --leak-check=yes'
+VALGRIND_SLEEP = 10 # seconds
+
+
+def parseBoolean(value):
+ if value in ['1', 1, 'true', 'True']:
+ return True
+ else:
+ return False
class ONOSHost(Host):
@@ -40,8 +51,8 @@
instanceCount = 0
def __init__(self, name, json=None, debugger=False, loglevel="warn", elogger=False,
- persistent=False, grpcPort=None, thriftPort=None, netcfg=True,
- pipeconfId="", pktdump=False, **kwargs):
+ persistent=False, grpcPort=None, thriftPort=None, netcfg=True, dryrun=False,
+ pipeconfId="", pktdump=False, valgrind=False, **kwargs):
Switch.__init__(self, name, **kwargs)
self.grpcPort = ONOSBmv2Switch.pickUnusedPort() if not grpcPort else grpcPort
self.thriftPort = ONOSBmv2Switch.pickUnusedPort() if not thriftPort else thriftPort
@@ -51,13 +62,15 @@
self.deviceId = ONOSBmv2Switch.deviceId
ONOSBmv2Switch.deviceId += 1
self.json = json
- self.debugger = debugger
+ self.debugger = parseBoolean(debugger)
self.loglevel = loglevel
self.logfile = '/tmp/bmv2-%d.log' % self.deviceId
- self.elogger = elogger
- self.pktdump = pktdump
- self.persistent = persistent
- self.netcfg = netcfg
+ self.elogger = parseBoolean(elogger)
+ self.pktdump = parseBoolean(pktdump)
+ self.persistent = parseBoolean(persistent)
+ self.netcfg = parseBoolean(netcfg)
+ self.dryrun = parseBoolean(dryrun)
+ self.valgrind = parseBoolean(valgrind)
self.netcfgfile = '/tmp/bmv2-%d-netcfg.json' % self.deviceId
self.pipeconfId = pipeconfId
if persistent:
@@ -153,6 +166,11 @@
}
with open(self.netcfgfile, 'w') as fp:
json.dump(cfgData, fp, indent=4)
+
+ if not self.netcfg:
+ # Do not push config to ONOS.
+ return
+
# Build netcfg URL
url = 'http://%s:8181/onos/v1/network/configuration/' % controllerIP
# Instantiate password manager for HTTP auth
@@ -194,7 +212,11 @@
args.append('--grpc-server-addr 0.0.0.0:%d' % self.grpcPort)
bmv2cmd = " ".join(args)
- info("\nStarting BMv2 target: %s\n" % bmv2cmd)
+ if self.valgrind:
+ bmv2cmd = "%s %s" % (VALGRIND_PREFIX, bmv2cmd)
+ if self.dryrun:
+ info("\n*** DRY RUN (not executing bmv2)")
+ info("\nStarting BMv2 target: %s" % bmv2cmd)
if self.persistent:
# Bash loop to re-exec the switch if it crashes.
@@ -203,18 +225,23 @@
cmdStr = "{} > {} 2>&1 &".format(bmv2cmd, self.logfile)
# Starts the switch.
- out = self.cmd(cmdStr)
- if out:
- print out
+ if not self.dryrun:
+ out = self.cmd(cmdStr)
+ if out:
+ print out
+ if self.valgrind:
+ # With valgrind, it takes some time before the gRPC server is available.
+ # Wait before pushing the netcfg.
+ info("\n*** Waiting %d seconds before pushing the config to ONOS...\n" % VALGRIND_SLEEP)
+ time.sleep(VALGRIND_SLEEP)
- if self.netcfg:
- try: # onos.py
- clist = controllers[0].nodes()
- except AttributeError:
- clist = controllers
- assert len(clist) > 0
- cip = clist[0].IP()
- self.doOnosNetcfg(cip)
+ try: # onos.py
+ clist = controllers[0].nodes()
+ except AttributeError:
+ clist = controllers
+ assert len(clist) > 0
+ cip = clist[0].IP()
+ self.doOnosNetcfg(cip)
def stop(self, deleteIntfs=True):
"""Terminate switch."""