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
     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
 
     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)
 
         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
+
 
 
         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()