Fix #126 Routes configuration
authorAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 17 Feb 2014 12:53:09 +0000 (13:53 +0100)
committerAlina Quereilhac <alina.quereilhac@inria.fr>
Mon, 17 Feb 2014 12:53:09 +0000 (13:53 +0100)
src/nepi/resources/ns3/ns3base.py
src/nepi/resources/ns3/ns3ipv4l3protocol.py
src/nepi/resources/ns3/ns3netdevice.py
src/nepi/resources/ns3/ns3node.py
src/nepi/resources/ns3/ns3wrapper.py
test/resources/linux/ns3/ns3simulation.py

index b007059..e6816bf 100644 (file)
@@ -23,7 +23,7 @@ from nepi.execution.resource import ResourceManager, clsinit_copy, \
 from nepi.execution.attribute import Flags
 from nepi.execution.trace import TraceAttr
 
-reschedule_delay = "2s"
+reschedule_delay = "1s"
 
 @clsinit_copy
 class NS3Base(ResourceManager):
index 5dd0827..5eb3f45 100644 (file)
@@ -24,6 +24,11 @@ from nepi.resources.ns3.ns3base import NS3Base
 class NS3BaseIpv4L3Protocol(NS3Base):
     _rtype = "abstract::ns3::Ipv4L3Protocol"
 
+    def __init__(self, ec, guid):
+        super(NS3BaseIpv4L3Protocol, self).__init__(ec, guid)
+        self.list_routing_uuid = None
+        self.static_routing_uuid = None
+
     @property
     def node(self):
         from nepi.resources.ns3.ns3node import NS3BaseNode
@@ -45,11 +50,12 @@ class NS3BaseIpv4L3Protocol(NS3Base):
     def _configure_object(self):
         simulation = self.simulation
 
-        uuid_list_routing = simulation.create("Ipv4ListRouting")
-        simulation.invoke(self.uuid, "SetRoutingProtocol", uuid_list_routing)
+        self.list_routing_uuid = simulation.create("Ipv4ListRouting")
+        simulation.invoke(self.uuid, "SetRoutingProtocol", self.list_routing_uuid)
 
-        uuid_static_routing = simulation.create("Ipv4StaticRouting")
-        simulation.invoke(uuid_list_routing, "AddRoutingProtocol", uuid_static_routing, 1)
+        self.static_routing_uuid = simulation.create("Ipv4StaticRouting")
+        simulation.invoke(self.list_routing_uuid, "AddRoutingProtocol", 
+                self.static_routing_uuid, 1)
 
     def _connect_object(self):
         pass
index 074f075..f136dd8 100644 (file)
@@ -24,8 +24,6 @@ from nepi.resources.ns3.ns3base import NS3Base
 
 import ipaddr
 
-# TODO: Validate that device must be connected to queue!! If not a segmentation fault occurs
-
 @clsinit_copy
 class NS3BaseNetDevice(NS3Base):
     _rtype = "abstract::ns3::NetDevice"
@@ -84,6 +82,18 @@ class NS3BaseNetDevice(NS3Base):
 
         return channels[0]
 
+    @property
+    def queue(self):
+        from nepi.resources.ns3.ns3queue import NS3BaseQueue
+        queue = self.get_connected(NS3BaseQueue.get_rtype())
+
+        if not queue: 
+            msg = "Device not connected to queue"
+            self.error(msg)
+            raise RuntimeError, msg
+
+        return queue[0]
+
     @property
     def ascii_helper_uuid(self):
         if not self._ascii_helper_uuid:
@@ -213,4 +223,9 @@ class NS3BaseNetDevice(NS3Base):
         if channel and channel.uuid not in self.connected:
             self.simulation.invoke(self.uuid, "Attach", channel.uuid)
             self._connected.add(channel.uuid)
-
+        
+        queue = self.queue
+        # Verify that the device has a queue. If no queue is added a segfault 
+        # error occurs
+        if queue and queue.uuid not in self.connected:
+            self._connected.add(queue.uuid)
index b0e5dcf..0d6f691 100644 (file)
@@ -50,6 +50,18 @@ class NS3BaseNode(NS3Base):
         if mobility: return mobility[0]
         return None
 
+    @property
+    def devices(self):
+        from nepi.resources.ns3.ns3netdevice import NS3BaseNetDevice
+        devices = self.get_connected(NS3BaseNetDevice.get_rtype())
+
+        if not devices: 
+            msg = "Node not connected to devices"
+            self.error(msg)
+            raise RuntimeError, msg
+
+        return devices
+
     @property
     def _rms_to_wait(self):
         rms = set()
index 4c2063a..69e2b86 100644 (file)
@@ -210,6 +210,8 @@ class NS3Wrapper(object):
     def invoke(self, uuid, operation, *args, **kwargs):
         if operation == "isAppRunning":
             return self._is_app_running(uuid)
+        if operation == "addStaticRoute":
+            return self._add_static_route(uuid, *args)
 
         if uuid.startswith(SINGLETON):
             obj = self._singleton(uuid)
@@ -459,3 +461,52 @@ class NS3Wrapper(object):
 
         return False
 
+    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 xrange(nifaces):
+            iface = ipv4.GetInterface(ifidx)
+            naddress = iface.GetNAddresses()
+            for addridx in xrange(naddress):
+                ifaddr = iface.GetAddress(addridx)
+                ifmask = ifaddr.GetMask()
+                
+                ifindex = ipv4.GetInterfaceForPrefix(nexthop, ifmask)
+
+                if ifindex == ifidx:
+                    return ifindex
+        return ifindex
+
index f289ca4..030422f 100644 (file)
@@ -511,6 +511,119 @@ class LinuxNS3ClientTest(unittest.TestCase):
 
         ec.shutdown()
 
+    def test_routing(self):
+        """ 
+        network topology:
+                                n4
+                                |
+           n1 -- p2p -- n2 -- csma -- n5 -- p2p -- n6
+           |                    | 
+           ping n6              n3
+           
+
+        """
+        ec = ExperimentController(exp_id = "test-ns3-routes")
+        
+        node = ec.register_resource("LinuxNode")
+        ec.set(node, "hostname", self.fedora_host)
+        ec.set(node, "username", self.fedora_user)
+        ec.set(node, "identity", self.fedora_identity)
+        ec.set(node, "cleanProcesses", True)
+        #ec.set(node, "cleanHome", True)
+
+        simu = ec.register_resource("LinuxNS3Simulation")
+        ec.set(simu, "verbose", True)
+        ec.register_connection(simu, node)
+
+        nsnode1 = add_ns3_node(ec, simu)
+        p2p12 = add_point2point_device(ec, nsnode1, "10.0.0.1", "30")
+
+        nsnode2 = add_ns3_node(ec, simu)
+        p2p21 = add_point2point_device(ec, nsnode2, "10.0.0.2", "30")
+        csma2 = add_csma_device(ec, nsnode2, "10.0.1.1", "24")
+
+        nsnode3 = add_ns3_node(ec, simu)
+        csma3 = add_csma_device(ec, nsnode3, "10.0.1.2", "24")
+
+        nsnode4 = add_ns3_node(ec, simu)
+        csma4 = add_csma_device(ec, nsnode4, "10.0.1.3", "24")
+
+        nsnode5 = add_ns3_node(ec, simu)
+        p2p56 = add_point2point_device(ec, nsnode5, "10.0.2.1", "30")
+        csma5 = add_csma_device(ec, nsnode5, "10.0.1.4", "24")
+
+        nsnode6 = add_ns3_node(ec, simu)
+        p2p65 = add_point2point_device(ec, nsnode6, "10.0.2.2", "30")
+
+        # P2P chan1
+        p2p_chan1 = ec.register_resource("ns3::PointToPointChannel")
+        ec.set(p2p_chan1, "Delay", "0s")
+        ec.register_connection(p2p_chan1, p2p12)
+        ec.register_connection(p2p_chan1, p2p21)
+
+        # CSMA chan
+        csma_chan = ec.register_resource("ns3::CsmaChannel")
+        ec.set(csma_chan, "Delay", "0s")
+        ec.register_connection(csma_chan, csma2)
+        ec.register_connection(csma_chan, csma3)
+        ec.register_connection(csma_chan, csma4)
+        ec.register_connection(csma_chan, csma5)
+
+        # P2P chan2
+        p2p_chan2 = ec.register_resource("ns3::PointToPointChannel")
+        ec.set(p2p_chan2, "Delay", "0s")
+        ec.register_connection(p2p_chan2, p2p56)
+        ec.register_connection(p2p_chan2, p2p65)
+
+        # Add routes - n1 - n6
+        r1 = ec.register_resource("ns3::Route")
+        ec.set(r1, "Network", "10.0.2.0")
+        ec.set(r1, "Prefix", "30")
+        ec.set(r1, "Nexthop", "10.0.0.2")
+        ec.register_connection(r1, nsnode1)
+
+        # Add routes - n2 - n6
+        r2 = ec.register_resource("ns3::Route")
+        ec.set(r2, "Network", "10.0.2.0")
+        ec.set(r2, "Prefix", "30")
+        ec.set(r2, "Nexthop", "10.0.1.4")
+        ec.register_connection(r2, nsnode2)
+
+        # Add routes - n5 - n1
+        r5 = ec.register_resource("ns3::Route")
+        ec.set(r5, "Network", "10.0.0.0")
+        ec.set(r5, "Prefix", "30")
+        ec.set(r5, "Nexthop", "10.0.1.1")
+        ec.register_connection(r5, nsnode5)
+
+        # Add routes - n6 - n1
+        r6 = ec.register_resource("ns3::Route")
+        ec.set(r6, "Network", "10.0.0.0")
+        ec.set(r6, "Prefix", "30")
+        ec.set(r6, "Nexthop", "10.0.2.1")
+        ec.register_connection(r6, nsnode6)
+
+        ### create pinger
+        ping = ec.register_resource("ns3::V4Ping")
+        ec.set (ping, "Remote", "10.0.2.2")
+        ec.set (ping, "Interval", "1s")
+        ec.set (ping, "Verbose", True)
+        ec.set (ping, "StartTime", "1s")
+        ec.set (ping, "StopTime", "21s")
+        ec.register_connection(ping, nsnode1)
+
+        ec.deploy()
+
+        ec.wait_finished([ping])
+        
+        stdout = ec.trace(simu, "stdout")
+
+        expected = "20 packets transmitted, 20 received, 0% packet loss"
+        self.assertTrue(stdout.find(expected) > -1)
+
+        ec.shutdown()
+
+
 if __name__ == '__main__':
     unittest.main()