- def _load_ns3_module(self):
- if self.ns3:
- return
-
- import ctypes
- import imp
- import re
- import pkgutil
-
- bindings = os.environ.get("NS3BINDINGS")
- libdir = os.environ.get("NS3LIBRARIES")
-
- # Load the ns-3 modules shared libraries
- if libdir:
- files = os.listdir(libdir)
- regex = re.compile("(.*\.so)$")
- libs = [m.group(1) for filename in files for m in [regex.search(filename)] if m]
-
- libscp = list(libs)
- while len(libs) > 0:
- for lib in libs:
- libfile = os.path.join(libdir, lib)
- try:
- ctypes.CDLL(libfile, ctypes.RTLD_GLOBAL)
- libs.remove(lib)
- except:
- pass
-
- # if did not load any libraries in the last iteration break
- # to prevent infinit loop
- if len(libscp) == len(libs):
- raise RuntimeError("Imposible to load shared libraries %s" % str(libs))
- libscp = list(libs)
-
- # import the python bindings for the ns-3 modules
- if bindings:
- sys.path.append(bindings)
-
- # create a module to add all ns3 classes
- ns3mod = imp.new_module("ns3")
- sys.modules["ns3"] = ns3mod
-
- # retrieve all ns3 classes and add them to the ns3 module
- import ns
- for importer, modname, ispkg in pkgutil.iter_modules(ns.__path__):
- fullmodname = "ns.%s" % modname
- module = __import__(fullmodname, globals(), locals(), ['*'])
-
- # netanim.Config singleton overrides ns3::Config
- if modname in ['netanim']:
- continue
+ # singletons are identified as "ns3::ClassName"
+ def _singleton(self, ident):
+ if not ident.startswith(SINGLETON):
+ return None
+
+ clazzname = ident[ident.find("::")+2:]
+ if not hasattr(self.ns3, clazzname):
+ msg = "Type %s not supported" % (clazzname)
+ self.logger.error(msg)
+
+ return getattr(self.ns3, clazzname)
+
+ # replace uuids and singleton references for the real objects
+ def replace_args(self, args):
+ realargs = [self.get_object(arg) if \
+ str(arg).startswith("uuid") else arg for arg in args]
+
+ realargs = [self._singleton(arg) if \
+ str(arg).startswith(SINGLETON) else arg for arg in realargs]
+
+ return realargs
+
+ # replace uuids and singleton references for the real objects
+ def replace_kwargs(self, kwargs):
+ realkwargs = dict([(k, self.get_object(v) \
+ if str(v).startswith("uuid") else v) \
+ for k,v in kwargs.items()])
+
+ realkwargs = dict([(k, self._singleton(v) \
+ if str(v).startswith(SINGLETON) else v )\
+ for k, v in realkwargs.items()])
+
+ return realkwargs
+
+ 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)
+ stop_time = stop_time_value.Get()
+
+ start_time_value = self.ns3.TimeValue()
+ app.GetAttribute("StartTime", start_time_value)
+ start_time = start_time_value.Get()
+
+ 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)
+
+ list_routing = ipv4.GetRoutingProtocol()
+ (static_routing, priority) = list_routing.GetRoutingProtocol(0)
+
+ ifindex = self._find_ifindex(ipv4, nexthop)
+ if ifindex == -1:
+ return False
+
+ nexthop = self.ns3.Ipv4Address(nexthop)
+
+ if network in ["0.0.0.0", "0", None]:
+ # Default route: 0.0.0.0/0
+ static_routing.SetDefaultRoute(nexthop, ifindex)
+ else:
+ mask = self.ns3.Ipv4Mask("/%s" % prefix)
+ network = self.ns3.Ipv4Address(network)
+
+ if prefix == 32:
+ # Host route: x.y.z.w/32
+ static_routing.AddHostRouteTo(network, nexthop, ifindex)
+ else:
+ # Network route: x.y.z.w/n
+ static_routing.AddNetworkRouteTo(network, mask, nexthop,
+ ifindex)
+ return True
+
+ def _find_ifindex(self, ipv4, nexthop):
+ ifindex = -1
+
+ nexthop = self.ns3.Ipv4Address(nexthop)
+
+ # 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 range(nifaces):
+ iface = ipv4.GetInterface(ifidx)
+ naddress = iface.GetNAddresses()
+ for addridx in range(naddress):
+ ifaddr = iface.GetAddress(addridx)
+ ifmask = ifaddr.GetMask()
+
+ ifindex = ipv4.GetInterfaceForPrefix(nexthop, ifmask)
+
+ if ifindex == ifidx:
+ 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()