# Copyright (C) 2013 INRIA
#
# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation;
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
self._allowed_types = None
# Object to dump instructions to reproduce and debug experiment
- from ns3wrapper_debug import NS3WrapperDebuger
+ from nepi.resources.ns3.ns3wrapper_debug import NS3WrapperDebuger
self._debuger = NS3WrapperDebuger(enabled = enable_dump)
@property
tid_count = type_id.GetRegisteredN()
base = type_id.LookupByName("ns3::Object")
- for i in xrange(tid_count):
+ for i in range(tid_count):
tid = type_id.GetRegistered(i)
if tid.MustHideFromDocumentation() or \
@property
def is_running(self):
- return self._started and self.ns3.Simulator.IsFinished()
+ return self.is_started and not self.ns3.Simulator.IsFinished()
+
+ @property
+ def is_started(self):
+ if not self._started:
+ now = self.ns3.Simulator.Now()
+ if not now.IsZero():
+ self._started = True
+
+ return self._started
+
+ @property
+ def is_finished(self):
+ return self.ns3.Simulator.IsFinished()
def make_uuid(self):
return "uuid%s" % uuid.uuid4()
### DEBUG
self.logger.debug("FACTORY %s( %s )" % (type_name, str(kwargs)))
+ ### DUMP
self.debuger.dump_factory(uuid, type_name, kwargs)
- ########
factory = self.ns3.ObjectFactory()
factory.SetTypeId(type_name)
- for name, value in kwargs.iteritems():
+ for name, value in kwargs.items():
ns3_value = self._attr_from_string_to_ns3_value(type_name, name, value)
factory.Set(name, ns3_value)
### DEBUG
self.logger.debug("RET FACTORY ( uuid %s ) %s = %s( %s )" % (
str(uuid), str(obj), type_name, str(kwargs)))
- ########
return uuid
### DEBUG
self.logger.debug("CREATE %s( %s )" % (clazzname, str(args)))
+ ### DUMP
self.debuger.dump_create(uuid, clazzname, args)
- ########
clazz = getattr(self.ns3, clazzname)
### DEBUG
self.logger.debug("RET CREATE ( uuid %s ) %s = %s( %s )" % (str(uuid),
str(obj), clazzname, str(args)))
- ########
return uuid
if operation == "isRunning":
result = self.is_running
+
+ elif operation == "isStarted":
+ result = self.is_started
+
+ elif operation == "isFinished":
+ result = self.is_finished
+
elif operation == "isAppRunning":
result = self._is_app_running(uuid)
- elif operation == "addStaticRoute":
- ### DEBUG
- self.debuger.dump_add_static_route(uuid, args)
- ########
+ elif operation == "isAppStarted":
+ result = self._is_app_started(uuid)
+
+ elif operation == "recvFD":
+ ### passFD operation binds to a different random socket
+ ### en every execution, so the socket name that could be
+ ### dumped to the debug script using dump_invoke is
+ ### not be valid accross debug executions.
+ result = self._recv_fd(uuid, *args, **kwargs)
+
+ elif operation == "addStaticRoute":
result = self._add_static_route(uuid, *args)
+
+ ### DUMP - result is static, so will be dumped as plain text
+ self.debuger.dump_invoke(result, uuid, operation, args, kwargs)
+
+ elif operation == "retrieveObject":
+ result = self._retrieve_object(uuid, *args, **kwargs)
+
+ ### DUMP - result is static, so will be dumped as plain text
+ self.debuger.dump_invoke(result, uuid, operation, args, kwargs)
+
else:
newuuid = self.make_uuid()
- ### DEBUG
+ ### DUMP - result is a uuid that encoded an dynamically generated
+ ### object
self.debuger.dump_invoke(newuuid, uuid, operation, args, kwargs)
- ########
if uuid.startswith(SINGLETON):
obj = self._singleton(uuid)
### DEBUG
self.logger.debug("SET %s %s %s" % (uuid, name, str(value)))
+ ### DUMP
self.debuger.dump_set(uuid, name, value)
- ########
obj = self.get_object(uuid)
type_name = obj.GetInstanceTypeId().GetName()
### DEBUG
self.logger.debug("RET SET %s = %s -> set(%s, %s)" % (str(value), uuid, name,
str(value)))
- ########
return value
### DEBUG
self.logger.debug("GET %s %s" % (uuid, name))
+ ### DUMP
self.debuger.dump_get(uuid, name)
- ########
obj = self.get_object(uuid)
type_name = obj.GetInstanceTypeId().GetName()
### DEBUG
self.logger.debug("RET GET %s = %s -> get(%s)" % (str(result), uuid, name))
- ########
return result
def start(self):
- ### DEBUG
+ ### DUMP
self.debuger.dump_start()
- ########
# Launch the simulator thread and Start the
# simulator in that thread
args = [self._condition])
self._simulator_thread.setDaemon(True)
self._simulator_thread.start()
- self._started = True
-
+
### DEBUG
self.logger.debug("START")
- ########
def stop(self, time = None):
- ### DEBUG
+ ### DUMP
self.debuger.dump_stop(time=time)
- ########
if time is None:
self.ns3.Simulator.Stop()
### DEBUG
self.logger.debug("STOP time=%s" % str(time))
- ########
def shutdown(self):
- ### DEBUG
+ ### DUMP
self.debuger.dump_shutdown()
- ########
while not self.ns3.Simulator.IsFinished():
#self.logger.debug("Waiting for simulation to finish")
### DEBUG
self.logger.debug("SHUTDOWN")
- ########
def _simulator_run(self, condition):
# Run simulation
def replace_kwargs(self, kwargs):
realkwargs = dict([(k, self.get_object(v) \
if str(v).startswith("uuid") else v) \
- for k,v in kwargs.iteritems()])
+ for k,v in kwargs.items()])
realkwargs = dict([(k, self._singleton(v) \
if str(v).startswith(SINGLETON) else v )\
- for k, v in realkwargs.iteritems()])
+ for k, v in realkwargs.items()])
return realkwargs
- def _is_app_running(self, uuid):
+ def _is_app_running(self, uuid):
now = self.ns3.Simulator.Now()
if now.IsZero():
return False
+ if self.ns3.Simulator.IsFinished():
+ return False
+
app = self.get_object(uuid)
stop_time_value = self.ns3.TimeValue()
app.GetAttribute("StopTime", stop_time_value)
app.GetAttribute("StartTime", start_time_value)
start_time = start_time_value.Get()
- if now.Compare(start_time) >= 0 and now.Compare(stop_time) < 0:
- return True
+ if now.Compare(start_time) >= 0:
+ if stop_time.IsZero() or now.Compare(stop_time) < 0:
+ return True
return False
+
+ def _is_app_started(self, uuid):
+ return self._is_app_running(uuid) or self.is_finished
def _add_static_route(self, ipv4_uuid, network, prefix, nexthop):
ipv4 = self.get_object(ipv4_uuid)
# For all the interfaces registered with the ipv4 object, find
# the one that matches the network of the nexthop
nifaces = ipv4.GetNInterfaces()
- for ifidx in xrange(nifaces):
+ for ifidx in range(nifaces):
iface = ipv4.GetInterface(ifidx)
naddress = iface.GetNAddresses()
- for addridx in xrange(naddress):
+ for addridx in range(naddress):
ifaddr = iface.GetAddress(addridx)
ifmask = ifaddr.GetMask()
return ifindex
return ifindex
+ def _retrieve_object(self, uuid, typeid, search = False):
+ obj = self.get_object(uuid)
+
+ type_id = self.ns3.TypeId()
+ tid = type_id.LookupByName(typeid)
+ nobj = obj.GetObject(tid)
+
+ newuuid = None
+ if search:
+ # search object
+ for ouuid, oobj in self._objects.items():
+ if nobj == oobj:
+ newuuid = ouuid
+ break
+ else:
+ newuuid = self.make_uuid()
+ self._objects[newuuid] = nobj
+
+ return newuuid
+
+ def _recv_fd(self, uuid):
+ """ Waits on a local address to receive a file descriptor
+ from a local process. The file descriptor is associated
+ to a FdNetDevice to stablish communication between the
+ simulation and what ever process writes on that file descriptor
+ """
+
+ def recvfd(sock, fdnd):
+ (fd, msg) = passfd.recvfd(sock)
+ # Store a reference to the endpoint to keep the socket alive
+ fdnd.SetFileDescriptor(fd)
+
+ import passfd
+ import socket
+ sock = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+ sock.bind("")
+ address = sock.getsockname()
+
+ fdnd = self.get_object(uuid)
+ t = threading.Thread(target=recvfd, args=(sock,fdnd))
+ t.start()
+
+ return address
+
+