Finishing with FIB initialization based on IPv4 global routing controller

Example ccnx-routing-simple.cc shows all necessary steps to make it work.
diff --git a/examples/ccnx-routing-simple.cc b/examples/ccnx-routing-simple.cc
index e277cfe..29fd49f 100644
--- a/examples/ccnx-routing-simple.cc
+++ b/examples/ccnx-routing-simple.cc
@@ -25,6 +25,7 @@
 #include "ns3/point-to-point-grid.h"
 #include "ns3/ipv4-global-routing-helper.h"
 #include "ns3/applications-module.h"
+#include "ns3/NDNabstraction-module.h"
 
 using namespace ns3;
 
@@ -34,15 +35,21 @@
 uint32_t nNodes = 2;
 uint32_t stopTime = 60;
 
-void TestDisable (Ptr<Node> node)
-{
-  NS_LOG_FUNCTION (node->GetId ());
+// void TestDisable (Ptr<Node> node)
+// {
+//   NS_LOG_FUNCTION (node->GetId ());
   
-  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
-  NS_ASSERT_MSG (ipv4 != 0, "ipv4 should not be null");
+//   Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+//   NS_ASSERT_MSG (ipv4 != 0, "ipv4 should not be null");
 
-  // The thing I didn't know is that interface status (isUp/isDown) and device status (isLinkUp) are two totally different things.  It is possible to set interface up and down, but there is not an easy way to alter status of device. This similar to reality: it is possible to programmatically disable interface, but to actually disable a link one needs to physically cut the cable
-  ipv4->SetDown (2);
+//   // The thing I didn't know is that interface status (isUp/isDown) and device status (isLinkUp) are two totally different things.  It is possible to set interface up and down, but there is not an easy way to alter status of device. This similar to reality: it is possible to programmatically disable interface, but to actually disable a link one needs to physically cut the cable
+//   ipv4->SetDown (2);
+// }
+
+void PrintCcnxFib (Ptr<Node> node, Ptr<OutputStreamWrapper> wrapper)
+{
+  Ptr<CcnxFib> fib = node->GetObject<CcnxFib> ();
+  *wrapper->GetStream () << *fib;
 }
 
 int main (int argc, char *argv[])
@@ -52,13 +59,15 @@
   cmd.AddValue ("stopTime", "Time to stop(seconds)", stopTime);
   cmd.Parse (argc, argv);
 
-  PointToPointHelper p2p;
   InternetStackHelper stack;
+  CcnxStackHelper ccnxHelper;
 
-  // Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingOrderedNexthops");
-  Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingUnorderedNexthops");
+  Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingOrderedNexthops");
+  // Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingUnorderedNexthops");
   stack.SetRoutingHelper (ipv4RoutingHelper);
 
+  PointToPointHelper p2p;
+
   PointToPointGridHelper grid (nNodes, nNodes, p2p);
   grid.BoundingBox(100,100,270,270);
   grid.InstallStack (stack);
@@ -68,36 +77,20 @@
                             Ipv4AddressHelper("10.2.0.0", "255.255.255.0")
                             );
 
-  for (uint32_t i=0; i<nNodes; i++)
-    for (uint32_t j=0; j<nNodes; j++)
-      grid.GetNode (i,j)->GetObject<GlobalRouter> ()->InjectRoute (Ipv4Address(grid.GetNode (i,j)->GetId ()),
-                                                                   Ipv4Mask("255.255.255.255"));
 
-  // // Create router nodes, initialize routing database and set up the routing
-  // // tables in the nodes.
-  // Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
-  // Ipv4GlobalRoutingHelper::PopulateAllPossibleRoutingTables ();
-  Ipv4GlobalRoutingHelper::PopulateRandomRoutingTables (5);
-  
-  // testing ip routing
-  UdpEchoClientHelper client (Ipv4Address ("10.2.1.1"), 1029);
-  client.SetAttribute ("MaxPackets", UintegerValue (1));
-  client.SetAttribute ("Interval", TimeValue (Seconds(1.0)));
-  client.SetAttribute ("PacketSize", UintegerValue (100));
-  client.Install (grid.GetNode (0,0));
-  // bla
-
-  
-  // apps.Stop (Seconds(150.0));
-
-  Simulator::ScheduleWithContext (grid.GetNode (0,0)->GetId (),
-                                  Seconds (80.0), TestDisable, grid.GetNode (0,0));
+  ccnxHelper.InstallAll ();
+  ccnxHelper.InstallFakeGlobalRoutes ();
+  // ccnxHelper.InstallRouteTo (grid.GetNode (0,0));
+  ccnxHelper.InstallRoutesToAll ();
 
   // Trace routing tables 
   Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("routes.log", std::ios::out);
   *routingStream->GetStream () << "Node (1,1)\n";
   ipv4RoutingHelper.PrintRoutingTableAt (Seconds (20), grid.GetNode (1,1), routingStream);
 
+  Simulator::ScheduleWithContext (grid.GetNode (1,1)->GetId (),
+                                  Seconds (20.0), PrintCcnxFib, grid.GetNode (1,1), routingStream);
+  
   Simulator::Stop (Seconds(160.0));
   Simulator::Run ();
   Simulator::Destroy ();
diff --git a/helper/ccnx-stack-helper.cc b/helper/ccnx-stack-helper.cc
index 0a39a80..33951c5 100644
--- a/helper/ccnx-stack-helper.cc
+++ b/helper/ccnx-stack-helper.cc
@@ -70,6 +70,12 @@
 #include "ns3/ccnx-net-device-face.h"
 #include "ns3/ccnx-l3-protocol.h"
 #include "ns3/ccnx-fib.h"
+#include "ns3/node-list.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-routing-helper.h"
+#include "ns3/ipv4-global-routing-ordered-nexthops.h"
+#include "ns3/global-router-interface.h"
+#include "ns3/ipv4-global-routing-helper.h"
 
 #include "ccnx-face-container.h"
 #include "ccnx-stack-helper.h"
@@ -77,6 +83,7 @@
 
 #include <limits>
 #include <map>
+#include <boost/foreach.hpp>
 
 NS_LOG_COMPONENT_DEFINE ("CcnxStackHelper");
 
@@ -238,21 +245,30 @@
 
 
 void
+CcnxStackHelper::AddRoute (Ptr<Node> node, std::string prefix, Ptr<CcnxFace> face, int32_t metric)
+{
+  Ptr<CcnxFib>  fib  = node->GetObject<CcnxFib> ();
+
+  CcnxNameComponentsValue prefixValue;
+  prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
+  fib->Add (prefixValue.Get (), face, metric);
+}
+
+void
 CcnxStackHelper::AddRoute (std::string nodeName, std::string prefix, uint32_t faceId, int32_t metric)
 {
   NS_LOG_LOGIC ("[" << nodeName << "]$ route add " << prefix << " via " << faceId << " metric " << metric);
   
   Ptr<Node> node = Names::Find<Node> (nodeName);
   NS_ASSERT_MSG (node != 0, "Node [" << nodeName << "] does not exist");
-  
-  Ptr<Ccnx>     ccnx = node->GetObject<Ccnx> ();
-  Ptr<CcnxFib>  fib  = node->GetObject<CcnxFib> ();
-  Ptr<CcnxFace> face = ccnx->GetFace (faceId);
-  NS_ASSERT_MSG (node != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
 
-  CcnxNameComponentsValue prefixValue;
-  prefixValue.DeserializeFromString (prefix, MakeCcnxNameComponentsChecker ());
-  fib->Add (prefixValue.Get (), face, metric);
+  Ptr<Ccnx>     ccnx = node->GetObject<Ccnx> ();
+  NS_ASSERT_MSG (ccnx != 0, "Ccnx stack should be installed on the node");
+
+  Ptr<CcnxFace> face = ccnx->GetFace (faceId);
+  NS_ASSERT_MSG (face != 0, "Face with ID [" << faceId << "] does not exist on node [" << nodeName << "]");
+
+  AddRoute (node, prefix, face, metric);
 }
 /*
 void
@@ -524,4 +540,89 @@
   g_faceStreamMapCcnx[std::make_pair (ccnx, face)] = stream;
 }
 
+void
+CcnxStackHelper::InstallFakeGlobalRoutes ()
+{
+  for (NodeList::Iterator node = NodeList::Begin ();
+       node != NodeList::End ();
+       node ++)
+    {
+      NS_ASSERT_MSG ((*node)->GetObject<Ipv4> () != 0,
+                     "InternetStack should be installed on all nodes");
+
+      NS_ASSERT_MSG (Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops>
+                     (
+                      (*node)->GetObject<Ipv4> ()->GetRoutingProtocol ()
+                     ),
+                     "InternetStack should have Ipv4GlobalRoutingOrderedNexthops as routing protocol");
+      // Example:
+      //
+      // Ipv4GlobalRoutingHelper ipv4RoutingHelper ("ns3::Ipv4GlobalRoutingUnorderedNexthops");
+      // stack.SetRoutingHelper (ipv4RoutingHelper);
+      //
+      
+      Ptr<GlobalRouter> globalRouter = (*node)->GetObject<GlobalRouter> ();
+      if (globalRouter == 0) continue;
+
+      globalRouter->InjectRoute (Ipv4Address((*node)->GetId ()), Ipv4Mask("255.255.255.255"));
+    }
+
+  Ipv4GlobalRoutingHelper::PopulateAllPossibleRoutingTables ();
+}
+
+void
+CcnxStackHelper::InstallRouteTo (Ptr<Node> destNode)
+{
+  std::ostringstream destPrefix;
+  destPrefix << "/" << destNode->GetId ();
+
+  Ipv4Address destIpv4 = Ipv4Address(destNode->GetId ());
+  
+  for (NodeList::Iterator node = NodeList::Begin ();
+       node != NodeList::End ();
+       node ++)
+    {
+      if (destNode == *node) continue;
+      
+      Ptr<Ccnx> ccnx = (*node)->GetObject<Ccnx> ();
+      NS_ASSERT_MSG (ccnx != 0, "CCNx stack should be installed on all nodes");
+
+      Ptr<Ipv4> ipv4 = (*node)->GetObject<Ipv4> ();
+      NS_ASSERT_MSG (ipv4 != 0,
+                     "InternetStack should be installed on all nodes");
+      
+      Ptr<Ipv4GlobalRoutingOrderedNexthops> routing =
+        Ipv4RoutingHelper::GetRouting<Ipv4GlobalRoutingOrderedNexthops> (ipv4->GetRoutingProtocol ());
+      NS_ASSERT_MSG (routing != 0, "Ipv4GlobalRoutingOrderedNexthops should be used in InternetStack");
+
+      Ptr<Ipv4GlobalRoutingOrderedNexthops::EntryContainer>
+        routes = routing->Lookup (destIpv4);
+
+      NS_ASSERT_MSG (routes != 0, "Should not happen... Call the developer");
+
+      BOOST_FOREACH (const Ipv4RoutingTableEntry &entry, *routes)
+        {
+          Ptr<NetDevice> netDevice = ipv4->GetNetDevice (entry.GetInterface ());
+          NS_ASSERT_MSG (netDevice != 0, "Should never happen. Call the popos");
+          
+          Ptr<CcnxFace> face = ccnx->GetFaceByNetDevice (netDevice);
+          NS_ASSERT_MSG (face != 0, "Definitely should never happen. Call the president");
+            
+          AddRoute (*node, destPrefix.str(), face, entry.GetMetric ());
+        }
+    }
+}
+
+void
+CcnxStackHelper::InstallRoutesToAll ()
+{
+  for (NodeList::Iterator node = NodeList::Begin ();
+       node != NodeList::End ();
+       node ++)
+    {
+      InstallRouteTo (*node);
+    }
+}
+
+
 } // namespace ns3
diff --git a/helper/ccnx-stack-helper.h b/helper/ccnx-stack-helper.h
index eebbf0b..1a76201 100644
--- a/helper/ccnx-stack-helper.h
+++ b/helper/ccnx-stack-helper.h
@@ -153,10 +153,46 @@
    */
   void
   AddRoute (std::string nodeName, std::string prefix, uint32_t faceId, int32_t metric);
-/*
+
+  /**
+   * \brief Add forwarding entry in FIB
+   *
+   * \param node   Node
+   * \param prefix Routing prefix
+   * \param face   Face
+   * \param metric Routing metric
+   */
   void
-  AddRoute (Ptr<Node> node, std::string prefix, uint32_t faceId, int32_t metric);
-  */  
+  AddRoute (Ptr<Node> node, std::string prefix, Ptr<CcnxFace> face, int32_t metric);
+  
+
+  /**
+   * \brief Install fake IPv4 routes that could be used to find nexthops for CCNx routes
+   *
+   * This method adds fake routes to all nodes, where each route is /32 and IPv4 address equal to node number.
+   * For example, node 5 will have direct route to 0.0.0.5.
+   */
+  void
+  InstallFakeGlobalRoutes ();
+
+  /**
+   * \brief Installs CCNx route to `node` based on fake IPv4 routes
+   *
+   * Actual route is "/<nodeId>"
+   *
+   * \param node Pointer to a node, which should be reached from all other nodes
+   */
+  void
+  InstallRouteTo (Ptr<Node> node);
+
+  /**
+   * \brief Installs CCNx route to all nodes based on fake IPv4 routes
+   *
+   * \see InstallRouteTo
+   */
+  void
+  InstallRoutesToAll ();
+  
 private:
    CcnxForwardingHelper m_forwardingHelper;
     
diff --git a/model/ccnx-l3-protocol.cc b/model/ccnx-l3-protocol.cc
index 4b832a4..d045339 100644
--- a/model/ccnx-l3-protocol.cc
+++ b/model/ccnx-l3-protocol.cc
@@ -38,6 +38,8 @@
 #include "ccnx-interest-header.h"
 #include "ccnx-content-object-header.h"
 
+#include "ccnx-net-device-face.h"
+
 #include <boost/foreach.hpp>
 
 NS_LOG_COMPONENT_DEFINE ("CcnxL3Protocol");
@@ -184,6 +186,20 @@
   return 0;
 }
 
+Ptr<CcnxFace>
+CcnxL3Protocol::GetFaceByNetDevice (Ptr<NetDevice> netDevice) const
+{
+  BOOST_FOREACH (const Ptr<CcnxFace> &face, m_faces) // this function is not supposed to be called often, so linear search is fine
+    {
+      Ptr<CcnxNetDeviceFace> netDeviceFace = DynamicCast<CcnxNetDeviceFace> (face);
+      if (netDeviceFace == 0) continue;
+
+      if (netDeviceFace->GetNetDevice () == netDevice)
+        return face;
+    }
+  return 0;
+}
+
 uint32_t 
 CcnxL3Protocol::GetNFaces (void) const
 {
diff --git a/model/ccnx-l3-protocol.h b/model/ccnx-l3-protocol.h
index c4d4f29..5b57ee0 100644
--- a/model/ccnx-l3-protocol.h
+++ b/model/ccnx-l3-protocol.h
@@ -144,6 +144,9 @@
 
   virtual void
   RemoveFace (Ptr<CcnxFace> face);
+
+  virtual Ptr<CcnxFace>
+  GetFaceByNetDevice (Ptr<NetDevice> netDevice) const;
   
   Ptr<CcnxPit> GetPit();
 protected:
diff --git a/model/ccnx.h b/model/ccnx.h
index 7fc9217..cafa354 100644
--- a/model/ccnx.h
+++ b/model/ccnx.h
@@ -192,6 +192,12 @@
    */
   virtual void
   RemoveFace (Ptr<CcnxFace> face) = 0;
+
+  /**
+   * Get face for NetDevice
+   */
+  virtual Ptr<CcnxFace>
+  GetFaceByNetDevice (Ptr<NetDevice> netDevice) const = 0;
 };
 
 } // namespace ns3 
diff --git a/model/ipv4-global-routing-ordered-nexthops.cc b/model/ipv4-global-routing-ordered-nexthops.cc
index 9ed2b60..a01c044 100644
--- a/model/ipv4-global-routing-ordered-nexthops.cc
+++ b/model/ipv4-global-routing-ordered-nexthops.cc
@@ -108,8 +108,7 @@
 Ptr<Ipv4Route>
 Ipv4GlobalRoutingOrderedNexthops::LookupGlobal (Ipv4Address dest, Ptr<NetDevice> oif)
 {
-  NS_LOG_FUNCTION_NOARGS ();
-  NS_LOG_LOGIC ("Looking for route for destination " << dest);
+  NS_LOG_FUNCTION (this << dest << oif);
 
   Ipv4AddressTrieMap::const_iterator longest_prefix_map = m_routes.longest_prefix_match (dest);
   if (longest_prefix_map == m_routes.end ())
@@ -134,6 +133,21 @@
   return rtentry;
 }
 
+const Ptr<Ipv4GlobalRoutingOrderedNexthops::EntryContainer>
+Ipv4GlobalRoutingOrderedNexthops::Lookup (Ipv4Address dest)
+{
+  NS_LOG_FUNCTION (this << dest);
+  
+  Ipv4AddressTrieMap::const_iterator longest_prefix_map = m_routes.longest_prefix_match (dest);
+  if (longest_prefix_map == m_routes.end ())
+    {
+      return 0;
+    }
+
+  return longest_prefix_map->second;
+}
+
+
 void
 Ipv4GlobalRoutingOrderedNexthops::DeleteRoutes ()
 {
diff --git a/model/ipv4-global-routing-ordered-nexthops.h b/model/ipv4-global-routing-ordered-nexthops.h
index b52779e..1ae8713 100644
--- a/model/ipv4-global-routing-ordered-nexthops.h
+++ b/model/ipv4-global-routing-ordered-nexthops.h
@@ -47,7 +47,7 @@
  */
 class Ipv4GlobalRoutingOrderedNexthops : public Ipv4GlobalRouting
 {
-private:
+public:
   class i_iface {};
   class i_metric {};
   class i_index {};
@@ -109,6 +109,9 @@
 
   virtual void DeleteRoutes ();
 
+  const Ptr<EntryContainer>
+  Lookup (Ipv4Address dest);
+
 protected:
   virtual Ptr<Ipv4Route> LookupGlobal (Ipv4Address dest, Ptr<NetDevice> oif = 0);