in flexsai/p4/backend/json_stage/bmv2stf.py [0:0]
def run(self):
if self.options.verbose:
print("Running model")
wait = 0 # Time to wait before model starts running
concurrent = ConcurrentInteger(os.getcwd(), 1000)
rand = concurrent.generate()
if rand is None:
reportError("Could not find a free port for Thrift")
return FAILURE
thriftPort = str(9090 + rand)
rv = SUCCESS
try:
os.remove("/tmp/bmv2-%d-notifications.ipc" % rand)
except OSError:
pass
try:
runswitch = [FindExe("behavioral-model", "simple_switch"),
"--log-file", self.switchLogFile, "--log-flush",
"--use-files", str(wait), "--thrift-port", thriftPort,
"--device-id", str(rand)] + self.interfaceArgs() + ["../" + self.jsonfile]
if self.options.verbose:
print("Running", " ".join(runswitch))
sw = subprocess.Popen(runswitch, cwd=self.folder)
def openInterface(ifname):
fp = self.interfaces[interface] = RawPcapWriter(ifname, linktype=0)
fp._write_header(None)
# Try to open input interfaces. Each time, we set a 2 second
# timeout. If the timeout expires we check if the bmv2 process is
# not running anymore. If it is, we check if we have exceeded the
# one minute timeout (exceeding this timeout is very unlikely and
# could mean the system is very slow for some reason). If one of the
# 2 conditions above is met, the test is considered a FAILURE.
start = time.time()
sw_timeout = 60
# open input interfaces
# DANGER -- it is critical that we open these fifos in the same
# order as bmv2, as otherwise we'll deadlock. Would be nice if we
# could open nonblocking.
for interface in sorted(self.interfaces):
ifname = self.interfaces[interface]
while True:
try:
signal.alarm(2)
openInterface(ifname)
signal.alarm(0)
except TimeoutException:
if time.time() - start > sw_timeout:
return FAILURE
if sw.poll() is not None:
return FAILURE
else:
break
# at this point we wait until the Thrift server is ready
# also useful if there are no interfaces
try:
signal.alarm(int(sw_timeout + start - time.time()))
self.check_switch_server_ready(sw, int(thriftPort))
signal.alarm(0)
except TimeoutException:
return FAILURE
time.sleep(0.1)
runcli = [FindExe("behavioral-model", "simple_switch_CLI"), "--thrift-port", thriftPort]
if self.options.verbose:
print("Running", " ".join(runcli))
cli = subprocess.Popen(runcli, cwd=self.folder, stdin=subprocess.PIPE)
self.cli_stdin = cli.stdin
with open(self.stffile) as i:
for line in i:
line, comment = nextWord(line, "#")
self.do_command(line)
cli.stdin.close()
for interface, fp in self.interfaces.iteritems():
fp.close()
# Give time to the model to execute
time.sleep(2)
cli.terminate()
sw.terminate()
sw.wait()
# This only works on Unix: negative returncode is
# minus the signal number that killed the process.
if sw.returncode != 0 and sw.returncode != -15: # 15 is SIGTERM
reportError("simple_switch died with return code", sw.returncode);
rv = FAILURE
elif self.options.verbose:
print("simple_switch exit code", sw.returncode)
cli.wait()
if cli.returncode != 0 and cli.returncode != -15:
reportError("CLI process failed with exit code", cli.returncode)
rv = FAILURE
finally:
try:
os.remove("/tmp/bmv2-%d-notifications.ipc" % rand)
except OSError:
pass
concurrent.release(rand)
if self.options.verbose:
print("Execution completed")
return rv