Allow injection of routes to Ipv4GlobalRouting
authorAntti Makela <zarhan@cc.hut.fi>
Mon, 31 Aug 2009 23:05:26 -0700
changeset 4745 a0e27af57c8d
parent 4744 cd473a5cf99c
child 4746 bfec2b0fa57d
Allow injection of routes to Ipv4GlobalRouting
CHANGES.html
examples/global-injection-slash32.cc
examples/wscript
src/routing/global-routing/global-route-manager-impl.cc
src/routing/global-routing/global-route-manager-impl.h
src/routing/global-routing/global-router-interface.cc
src/routing/global-routing/global-router-interface.h
src/routing/global-routing/ipv4-global-routing.cc
src/routing/global-routing/ipv4-global-routing.h
--- a/CHANGES.html	Mon Aug 31 15:29:20 2009 +0200
+++ b/CHANGES.html	Mon Aug 31 23:05:26 2009 -0700
@@ -52,6 +52,12 @@
 
 <h2>New API:</h2>
 <ul>
+<li><b>Route injection for global routing</b>
+<p>Add ability to inject and withdraw routes to Ipv4GlobalRouting.  This
+allows a user to insert a route and have it redistributed like an OSPF
+external LSA to the rest of the topology.
+</p>
+</li>
 <li><b>Athstats</b>
 <p>New classes AthstatsWifiTraceSink and AthstatsHelper.
 </p>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/global-injection-slash32.cc	Mon Aug 31 23:05:26 2009 -0700
@@ -0,0 +1,158 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * 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
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+// Test program for this 3-router scenario, using global routing
+//
+// (a.a.a.a/32)A<--x.x.x.0/30-->B<--y.y.y.0/30-->C(c.c.c.c/32)
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/csma-net-device.h"
+#include "ns3/core-module.h"
+#include "ns3/simulator-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/ipv4-static-routing.h"
+#include "ns3/ipv4-global-routing.h"
+#include "ns3/ipv4-list-routing.h"
+#include "ns3/ipv4-routing-table-entry.h"
+#include "ns3/global-router-interface.h"
+
+using namespace ns3;
+using std::cout;
+
+NS_LOG_COMPONENT_DEFINE ("GlobalRouterInjectionTest");
+
+int 
+main (int argc, char *argv[])
+{
+
+  // Allow the user to override any of the defaults and the above
+  // DefaultValue::Bind ()s at run-time, via command-line arguments
+  CommandLine cmd;
+  cmd.Parse (argc, argv);
+
+  Ptr<Node> nA = CreateObject<Node> ();
+  Ptr<Node> nB = CreateObject<Node> ();
+  Ptr<Node> nC = CreateObject<Node> ();
+
+  NodeContainer c = NodeContainer (nA, nB, nC);
+
+  InternetStackHelper internet;
+
+  // Point-to-point links
+  NodeContainer nAnB = NodeContainer (nA, nB);
+  NodeContainer nBnC = NodeContainer (nB, nC);
+
+  internet.Install (nAnB);
+  Ipv4ListRoutingHelper staticonly;
+  Ipv4ListRoutingHelper staticRouting;
+  staticonly.Add(staticRouting, 0);
+  internet.SetRoutingHelper(staticonly);
+  internet.Install(NodeContainer(nC));
+
+  // We create the channels first without any IP addressing information
+  PointToPointHelper p2p;
+  p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
+  p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
+  NetDeviceContainer dAdB = p2p.Install (nAnB);
+
+  NetDeviceContainer dBdC = p2p.Install (nBnC);;
+  
+  Ptr<CsmaNetDevice> deviceA = CreateObject<CsmaNetDevice> ();
+  deviceA->SetAddress (Mac48Address::Allocate ());
+  nA->AddDevice (deviceA);
+
+  Ptr<CsmaNetDevice> deviceC = CreateObject<CsmaNetDevice> ();
+  deviceC->SetAddress (Mac48Address::Allocate ());
+  nC->AddDevice (deviceC);
+
+  // Later, we add IP addresses.  
+  Ipv4AddressHelper ipv4;
+  ipv4.SetBase ("10.1.1.0", "255.255.255.252");
+  Ipv4InterfaceContainer iAiB = ipv4.Assign (dAdB);
+
+  ipv4.SetBase ("10.1.1.4", "255.255.255.252");
+  Ipv4InterfaceContainer iBiC = ipv4.Assign (dBdC);
+
+  Ptr<Ipv4> ipv4A = nA->GetObject<Ipv4> ();
+  Ptr<Ipv4> ipv4B = nB->GetObject<Ipv4> ();
+  Ptr<Ipv4> ipv4C = nC->GetObject<Ipv4> ();
+  
+  int32_t ifIndexA = ipv4A->AddInterface (deviceA);
+  int32_t ifIndexC = ipv4C->AddInterface (deviceC);
+    
+  Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255"));
+  ipv4A->AddAddress (ifIndexA, ifInAddrA);
+  ipv4A->SetMetric (ifIndexA, 1);
+  ipv4A->SetUp (ifIndexA);
+
+  Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("255.255.255.255"));
+  ipv4C->AddAddress (ifIndexC, ifInAddrC);
+  ipv4C->SetMetric (ifIndexC, 1);
+  ipv4C->SetUp (ifIndexC);
+ 
+  // Create router nodes, initialize routing database and set up the routing
+  // tables in the nodes.
+  
+  // Populate routing tables for nodes nA and nB
+  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
+  // Inject global routes from Node B, including transit network...
+  Ptr<GlobalRouter> globalRouterB = nB->GetObject<GlobalRouter> ();
+  globalRouterB->InjectRoute ("10.1.1.4", "255.255.255.252");
+  // ...and the host in network "C"
+  globalRouterB->InjectRoute ("192.168.1.1", "255.255.255.255");
+  
+  Ipv4GlobalRoutingHelper::RecomputeRoutingTables();
+  // In addition, nB needs a static route to nC so it knows what to do with stuff
+  // going to 192.168.1.1
+  Ipv4StaticRoutingHelper ipv4RoutingHelper;
+  Ptr<Ipv4StaticRouting> staticRoutingB = ipv4RoutingHelper.GetStaticRouting(ipv4B);
+  staticRoutingB->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.6"),2);
+  
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  uint16_t port = 9;   // Discard port (RFC 863)
+  OnOffHelper onoff ("ns3::UdpSocketFactory", 
+    Address (InetSocketAddress (ifInAddrC.GetLocal(), port)));
+  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (6000)));
+  ApplicationContainer apps = onoff.Install (nA);
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  // Create a packet sink to receive these packets
+  PacketSinkHelper sink ("ns3::UdpSocketFactory",
+    Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
+  apps = sink.Install (nC);
+  apps.Start (Seconds (1.0));
+  apps.Stop (Seconds (10.0));
+
+  std::ofstream ascii;
+  ascii.open ("global-routing-injection32.tr", std::ios_base::binary | std::ios_base::out);
+  PointToPointHelper::EnablePcapAll ("global-routing-injection32");
+  PointToPointHelper::EnableAsciiAll (ascii);
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  return 0;
+}
--- a/examples/wscript	Mon Aug 31 15:29:20 2009 +0200
+++ b/examples/wscript	Mon Aug 31 23:05:26 2009 -0700
@@ -36,6 +36,10 @@
                                  ['point-to-point', 'internet-stack', 'global-routing'])
     obj.source = 'global-routing-slash32.cc'
 
+    obj = bld.create_ns3_program('global-injection-slash32',
+                                 ['point-to-point', 'internet-stack', 'global-routing'])
+    obj.source = 'global-injection-slash32.cc'
+
     obj = bld.create_ns3_program('simple-global-routing',
                                  ['point-to-point', 'internet-stack', 'global-routing'])
     obj.source = 'simple-global-routing.cc'
--- a/src/routing/global-routing/global-route-manager-impl.cc	Mon Aug 31 15:29:20 2009 +0200
+++ b/src/routing/global-routing/global-route-manager-impl.cc	Mon Aug 31 23:05:26 2009 -0700
@@ -243,6 +243,15 @@
   return m_vertexProcessed;
 }
 
+void
+SPFVertex::ClearVertexProcessed (void)
+{
+  for (uint32_t i = 0; i < this->GetNChildren (); i++)
+    {
+      this->GetChild (i)->ClearVertexProcessed ();
+    }
+  this->SetVertexProcessed (false);
+}
 
 // ---------------------------------------------------------------------------
 //
@@ -252,7 +261,8 @@
 
 GlobalRouteManagerLSDB::GlobalRouteManagerLSDB ()
 :
-  m_database ()
+  m_database (),
+  m_extdatabase ()
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
@@ -267,6 +277,12 @@
       GlobalRoutingLSA* temp = i->second;
       delete temp;
     }
+  for (uint32_t j = 0; j < m_extdatabase.size (); j++)
+    {
+      NS_LOG_LOGIC ("free ASexternalLSA");
+      GlobalRoutingLSA* temp = m_extdatabase.at (j);
+      delete temp;
+    }
   NS_LOG_LOGIC ("clear map");
   m_database.clear ();
 }
@@ -287,7 +303,26 @@
 GlobalRouteManagerLSDB::Insert (Ipv4Address addr, GlobalRoutingLSA* lsa)
 {
   NS_LOG_FUNCTION (addr << lsa);
-  m_database.insert (LSDBPair_t (addr, lsa));
+  if (lsa->GetLSType () == GlobalRoutingLSA::ASExternalLSAs) 
+    {
+      m_extdatabase.push_back (lsa);
+    } 
+  else
+    {
+      m_database.insert (LSDBPair_t (addr, lsa));
+    }
+}
+
+  GlobalRoutingLSA*
+GlobalRouteManagerLSDB::GetExtLSA (uint32_t index) const
+{
+  return m_extdatabase.at (index);
+}
+
+  uint32_t
+GlobalRouteManagerLSDB::GetNumExtLSAs () const
+{
+  return m_extdatabase.size ();
 }
 
   GlobalRoutingLSA*
@@ -438,6 +473,7 @@
 // DiscoverLSAs () will get zero as the number since no routes have been 
 // found.
 //
+      Ptr<Ipv4GlobalRouting> grouting = rtr->GetRoutingProtocol ();
       uint32_t numLSAs = rtr->DiscoverLSAs ();
       NS_LOG_LOGIC ("Found " << numLSAs << " LSAs");
 
@@ -1237,6 +1273,14 @@
 
 // Second stage of SPF calculation procedure  
   SPFProcessStubs (m_spfroot);
+  for (uint32_t i = 0; i < m_lsdb->GetNumExtLSAs (); i++)
+    {
+      m_spfroot->ClearVertexProcessed ();
+      GlobalRoutingLSA *extlsa = m_lsdb->GetExtLSA (i);
+      NS_LOG_LOGIC ("Processing External LSA with id " << extlsa->GetLinkStateId ());
+      ProcessASExternals (m_spfroot, extlsa);
+    }
+
 //
 // We're all done setting the routing information for the node at the root of
 // the SPF tree.  Delete all of the vertices and corresponding resources.  Go
@@ -1246,6 +1290,160 @@
   m_spfroot = 0;
 }
 
+void
+GlobalRouteManagerImpl::ProcessASExternals (SPFVertex* v, GlobalRoutingLSA* extlsa)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC ("Processing external for destination " << 
+      extlsa->GetLinkStateId () <<
+      ", for router "  << v->GetVertexId () << 
+      ", advertised by " << extlsa->GetAdvertisingRouter ());
+  if (v->GetVertexType () == SPFVertex::VertexRouter)
+    {
+      GlobalRoutingLSA *rlsa = v->GetLSA ();
+      NS_LOG_LOGIC ("Processing router LSA with id " << rlsa->GetLinkStateId ());
+      if ((rlsa->GetLinkStateId ()) == (extlsa->GetAdvertisingRouter ()))
+        {
+          NS_LOG_LOGIC ("Found advertising router to destination");
+          SPFAddASExternal(extlsa,v);
+        }
+    }
+  for (uint32_t i = 0; i < v->GetNChildren (); i++)
+    {
+      if (!v->GetChild (i)->IsVertexProcessed ())
+        {
+          NS_LOG_LOGIC ("Vertex's child " << i << " not yet processed, processing...");
+          ProcessASExternals (v->GetChild (i), extlsa);
+          v->GetChild (i)->SetVertexProcessed (true);
+        }
+    }
+}
+
+//
+// Adding external routes to routing table - modeled after
+// SPFAddIntraAddStub()
+//
+
+void
+GlobalRouteManagerImpl::SPFAddASExternal (GlobalRoutingLSA *extlsa, SPFVertex *v)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  NS_ASSERT_MSG (m_spfroot, "GlobalRouteManagerImpl::SPFAddASExternal (): Root pointer not set");
+// Two cases to consider: We are advertising the external ourselves
+// => No need to add anything
+// OR find best path to the advertising router
+  if (v->GetVertexId () == m_spfroot->GetVertexId ())
+    {
+      NS_LOG_LOGIC ("External is on local host: " 
+        << v->GetVertexId () << "; returning");
+      return;
+    }
+  NS_LOG_LOGIC ("External is on remote host: " 
+    << extlsa->GetAdvertisingRouter () << "; installing");
+  
+  Ipv4Address routerId = m_spfroot->GetVertexId ();
+
+  NS_LOG_LOGIC ("Vertex ID = " << routerId);
+//
+// We need to walk the list of nodes looking for the one that has the router
+// ID corresponding to the root vertex.  This is the one we're going to write
+// the routing information to.
+//
+  NodeList::Iterator i = NodeList::Begin (); 
+  for (; i != NodeList::End (); i++)
+    {
+      Ptr<Node> node = *i;
+//
+// The router ID is accessible through the GlobalRouter interface, so we need
+// to QI for that interface.  If there's no GlobalRouter interface, the node
+// in question cannot be the router we want, so we continue.
+// 
+      Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter> ();
+
+      if (rtr == 0)
+        {
+          NS_LOG_LOGIC ("No GlobalRouter interface on node " << node->GetId ());
+          continue;
+        }
+//
+// If the router ID of the current node is equal to the router ID of the 
+// root of the SPF tree, then this node is the one for which we need to 
+// write the routing tables.
+//
+      NS_LOG_LOGIC ("Considering router " << rtr->GetRouterId ());
+
+      if (rtr->GetRouterId () == routerId)
+        {
+          NS_LOG_LOGIC ("Setting routes for node " << node->GetId ());
+//
+// Routing information is updated using the Ipv4 interface.  We need to QI
+// for that interface.  If the node is acting as an IP version 4 router, it
+// should absolutely have an Ipv4 interface.
+//
+          Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+          NS_ASSERT_MSG (ipv4, 
+                     "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
+                         "QI for <Ipv4> interface failed");
+//
+// Get the Global Router Link State Advertisement from the vertex we're
+// adding the routes to.  The LSA will have a number of attached Global Router
+// Link Records corresponding to links off of that vertex / node.  We're going
+// to be interested in the records corresponding to point-to-point links.
+//
+          NS_ASSERT_MSG (v->GetLSA (), 
+                     "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
+                         "Expected valid LSA in SPFVertex* v");
+          Ipv4Mask tempmask = extlsa->GetNetworkLSANetworkMask ();
+          Ipv4Address tempip = extlsa->GetLinkStateId ();
+          tempip = tempip.CombineMask (tempmask);
+
+          NS_LOG_LOGIC (" Node " << node->GetId () <<
+              " add route to " << tempip <<
+              " with mask " << tempmask <<
+              " using next hop " << v->GetNextHop () <<
+              " via interface " << v->GetOutgoingInterfaceId ());
+//
+// Here's why we did all of that work.  We're going to add a host route to the
+// host address found in the m_linkData field of the point-to-point link
+// record.  In the case of a point-to-point link, this is the local IP address
+// of the node connected to the link.  Each of these point-to-point links
+// will correspond to a local interface that has an IP address to which
+// the node at the root of the SPF tree can send packets.  The vertex <v> 
+// (corresponding to the node that has these links and interfaces) has 
+// an m_nextHop address precalculated for us that is the address to which the
+// root node should send packets to be forwarded to these IP addresses.
+// Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
+// which the packets should be send for forwarding.
+//
+          Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
+          if (router == 0)
+            {
+              continue;
+            }
+          Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
+          NS_ASSERT (gr);
+          if (v->GetOutgoingInterfaceId () >= 0)
+            {
+              gr->AddASExternalRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ());
+              NS_LOG_LOGIC ("Node " << node->GetId () <<
+                  " add network route to " << tempip <<
+                  " using next hop " << v->GetNextHop () <<
+                  " via interface " << v->GetOutgoingInterfaceId ());
+            }
+          else
+            {
+              NS_LOG_LOGIC ("Node " << node->GetId () <<
+                  " NOT able to add network route to " << tempip <<
+                  " using next hop " << v->GetNextHop () <<
+                  " since outgoing interface id is negative");
+            }
+          return;
+        } // if
+    } // for
+}
+
+
 // Processing logic from RFC 2328, page 166 and quagga ospf_spf_process_stubs ()
 // stub link records will exist for point-to-point interfaces and for
 // broadcast interfaces for which no neighboring router can be found
--- a/src/routing/global-routing/global-route-manager-impl.h	Mon Aug 31 15:29:20 2009 +0200
+++ b/src/routing/global-routing/global-route-manager-impl.h	Mon Aug 31 23:05:26 2009 -0700
@@ -26,6 +26,7 @@
 #include <list>
 #include <queue>
 #include <map>
+#include <vector>
 #include "ns3/object.h"
 #include "ns3/ptr.h"
 #include "ns3/ipv4-address.h"
@@ -563,6 +564,9 @@
    * @returns value of underlying flag
    */ 
   bool IsVertexProcessed (void) const;
+  
+  void ClearVertexProcessed (void);
+      
 private:
   VertexType m_vertexType;
   Ipv4Address m_vertexId;
@@ -683,12 +687,18 @@
  * @see SPFVertex
  */
   void Initialize ();
+  
+  GlobalRoutingLSA* GetExtLSA (uint32_t index) const;
+  uint32_t GetNumExtLSAs () const;
+      
 
 private:
   typedef std::map<Ipv4Address, GlobalRoutingLSA*> LSDBMap_t;
   typedef std::pair<Ipv4Address, GlobalRoutingLSA*> LSDBPair_t;
 
   LSDBMap_t m_database;
+  std::vector<GlobalRoutingLSA*> m_extdatabase;
+  
 /**
  * @brief GlobalRouteManagerLSDB copy construction is disallowed.  There's no 
  * need for it and a compiler provided shallow copy would be wrong.
@@ -775,6 +785,7 @@
   bool CheckForStubNode (Ipv4Address root);
   void SPFCalculate (Ipv4Address root);
   void SPFProcessStubs (SPFVertex* v);
+  void ProcessASExternals (SPFVertex* v, GlobalRoutingLSA* extlsa);
   void SPFNext (SPFVertex*, CandidateQueue&);
   int SPFNexthopCalculation (SPFVertex* v, SPFVertex* w, 
     GlobalRoutingLinkRecord* l, uint32_t distance);
@@ -784,6 +795,7 @@
   void SPFIntraAddRouter (SPFVertex* v);
   void SPFIntraAddTransit (SPFVertex* v);
   void SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v);
+  void SPFAddASExternal (GlobalRoutingLSA *extlsa, SPFVertex *v);
   int32_t FindOutgoingInterfaceId (Ipv4Address a, 
     Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
 };
--- a/src/routing/global-routing/global-router-interface.cc	Mon Aug 31 15:29:20 2009 +0200
+++ b/src/routing/global-routing/global-router-interface.cc	Mon Aug 31 23:05:26 2009 -0700
@@ -413,6 +413,10 @@
     {
       os << " (GlobalRoutingLSA::NetworkLSA)";
     }
+  else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
+    {
+      os << " (GlobalRoutingLSA::ASExternalLSA)";
+    }
   else
     {
       os << "(Unknown LSType)";
@@ -474,6 +478,12 @@
         }
       os << "---------- End NetworkLSA Link Record ----------" << std::endl;
     }
+  else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
+    {
+      os << "---------- ASExternalLSA Link Record --------" << std::endl;
+      os << "m_linkStateId = " << m_linkStateId << std::endl;
+      os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
+    }
   else 
     {
       NS_ASSERT_MSG(0, "Illegal LSA LSType: " << m_lsType);
@@ -532,6 +542,12 @@
 {
   NS_LOG_FUNCTION_NOARGS ();
   m_routingProtocol = 0;
+  for (InjectedRoutesI k = m_injectedRoutes.begin ();
+         k != m_injectedRoutes.end ();
+         k = m_injectedRoutes.erase (k))
+    {
+      delete (*k);
+    }
   Object::DoDispose ();
 }
 
@@ -568,8 +584,8 @@
 // and build the Link State Advertisements that reflect them and their associated
 // networks.
 // 
-  uint32_t 
-GlobalRouter::DiscoverLSAs (void)
+uint32_t 
+GlobalRouter::DiscoverLSAs ()
 {
   NS_LOG_FUNCTION_NOARGS ();
   Ptr<Node> node = GetObject<Node> ();
@@ -696,6 +712,22 @@
       BuildNetworkLSAs (c);
     }
 
+  //
+  // Build injected route LSAs as external routes
+  // RFC 2328, section 12.4.4
+  //
+  for (InjectedRoutesCI i = m_injectedRoutes.begin();
+       i != m_injectedRoutes.end();
+       i++)
+    {
+      GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
+      pLSA->SetLSType (GlobalRoutingLSA::ASExternalLSAs);
+      pLSA->SetLinkStateId ((*i)->GetDestNetwork ());
+      pLSA->SetAdvertisingRouter (m_routerId);
+      pLSA->SetNetworkLSANetworkMask ((*i)->GetDestNetworkMask ());
+      pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
+      m_LSAs.push_back (pLSA); 
+    }
   return m_LSAs.size ();
 }
 
@@ -1467,6 +1499,86 @@
   return false;
 }
 
+void
+GlobalRouter::InjectRoute (Ipv4Address network, Ipv4Mask networkMask)
+{
+  NS_LOG_FUNCTION (network << networkMask);
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+//
+// Interface number does not matter here, using 1.
+//
+  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
+      networkMask,
+      1);
+  m_injectedRoutes.push_back (route);
+}
+
+Ipv4RoutingTableEntry *
+GlobalRouter::GetInjectedRoute (uint32_t index)
+{
+  NS_LOG_FUNCTION (index);
+  if (index < m_injectedRoutes.size ())
+    {
+      uint32_t tmp = 0;
+      for (InjectedRoutesCI i = m_injectedRoutes.begin ();
+           i != m_injectedRoutes.end ();
+           i++)
+        {
+          if (tmp  == index)
+            {
+              return *i;
+            }
+          tmp++;
+        }
+     }
+  NS_ASSERT (false);
+  // quiet compiler.
+  return 0;
+}
+
+uint32_t
+GlobalRouter::GetNInjectedRoutes ()
+{
+  return m_injectedRoutes.size ();
+}
+
+void
+GlobalRouter::RemoveInjectedRoute (uint32_t index)
+{
+  NS_LOG_FUNCTION (index);
+  NS_ASSERT (index < m_injectedRoutes.size ());
+  uint32_t tmp = 0;
+  for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
+    {
+      if (tmp  == index)
+        {
+          NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_injectedRoutes.size());
+          delete *i;
+          m_injectedRoutes.erase (i);
+          return;
+        }
+      tmp++;
+    }
+}
+
+bool
+GlobalRouter::WithdrawRoute (Ipv4Address network, Ipv4Mask networkMask)
+{
+  NS_LOG_FUNCTION (index);
+  for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
+    {
+      if ((*i)->GetDestNetwork () == network && (*i)->GetDestNetworkMask () == networkMask)
+        {
+          NS_LOG_LOGIC ("Withdrawing route to network/mask " << network << "/" << networkMask);
+          delete *i;
+          m_injectedRoutes.erase (i);
+          return true;
+        }
+    }
+  return false;
+}
+
+
 //
 // Link through the given channel and find the net device that's on the
 // other end.  This only makes sense with a point-to-point channel.
--- a/src/routing/global-routing/global-router-interface.h	Mon Aug 31 15:29:20 2009 +0200
+++ b/src/routing/global-routing/global-router-interface.h	Mon Aug 31 23:05:26 2009 -0700
@@ -32,6 +32,7 @@
 #include "ns3/net-device-container.h"
 #include "ns3/bridge-net-device.h"
 #include "ns3/global-route-manager.h"
+#include "ns3/ipv4-routing-table-entry.h"
 
 namespace ns3 {
 
@@ -614,6 +615,8 @@
  * advertisements after a network topology change by calling DiscoverLSAs 
  * and then by reading those advertisements.
  *
+ * \param List of routing table entries of external routes to be injected.
+ *
  * @see GlobalRoutingLSA
  * @see GlobalRouter::GetLSA ()
  * @returns The number of Global Routing Link State Advertisements.
@@ -657,6 +660,59 @@
  */
   bool GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const;
 
+/**
+ * @brief Inject a route to be circulated to other routers as an external
+ * route
+ *
+ * @param network The Network to inject
+ * @param networkMask The Network Mask to inject
+ */
+  void InjectRoute (Ipv4Address network, Ipv4Mask networkMask);
+
+/**
+ * @brief Get the number of injected routes that have been added
+ * to the routing table.
+ * @return number of injected routes
+ */
+  uint32_t GetNInjectedRoutes (void);
+
+/**
+ * @brief Return the injected route indexed by i
+ * @param i the index of the route
+ * @return a pointer to that Ipv4RoutingTableEntry is returned
+ *
+ */
+  Ipv4RoutingTableEntry *GetInjectedRoute (uint32_t i);
+
+/**
+ * @brief Withdraw a route from the global unicast routing table.
+ *
+ * Calling this function will cause all indexed routes numbered above
+ * index i to have their index decremented.  For instance, it is possible to
+ * remove N injected routes by calling RemoveInjectedRoute (0) N times.
+ *
+ * @param i The index (into the injected routing list) of the route to remove.  
+ *
+ * @see GlobalRouter::WithdrawRoute ()
+ */
+  void RemoveInjectedRoute (uint32_t i);
+
+/**
+ * @brief Withdraw a route from the global unicast routing table.
+ *
+ * Calling this function will cause all indexed routes numbered above
+ * index i to have their index decremented.  For instance, it is possible to
+ * remove N injected routes by calling RemoveInjectedRoute (0) N times.
+ *
+ * @param i The index (into the injected routing list) of the route to remove.  
+ * @param network The Network to inject
+ * @param networkMask The Network Mask to inject
+ * @return whether the operation succeeded (will return false if no such route)
+ *
+ * @see GlobalRouter::RemoveInjectedRoute ()
+ */
+  bool WithdrawRoute (Ipv4Address network, Ipv4Mask networkMask);
+
 private:
   virtual ~GlobalRouter ();
   void ClearLSAs (void);
@@ -680,6 +736,11 @@
   Ipv4Address m_routerId;
   Ptr<Ipv4GlobalRouting> m_routingProtocol;
 
+  typedef std::list<Ipv4RoutingTableEntry *> InjectedRoutes;
+  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator InjectedRoutesCI;
+  typedef std::list<Ipv4RoutingTableEntry *>::iterator InjectedRoutesI;
+  InjectedRoutes m_injectedRoutes; // Routes we are exporting
+
   // inherited from Object
   virtual void DoDispose (void);
 
--- a/src/routing/global-routing/ipv4-global-routing.cc	Mon Aug 31 15:29:20 2009 +0200
+++ b/src/routing/global-routing/ipv4-global-routing.cc	Mon Aug 31 23:05:26 2009 -0700
@@ -98,10 +98,27 @@
   m_networkRoutes.push_back (route);
 }
 
+void 
+Ipv4GlobalRouting::AddASExternalRouteTo (Ipv4Address network, 
+                                         Ipv4Mask networkMask,
+                                         Ipv4Address nextHop,
+                                         uint32_t interface)
+{
+  NS_LOG_FUNCTION (network << networkMask << nextHop);
+  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
+  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
+      networkMask,
+      nextHop,
+      interface);
+  m_ASexternalRoutes.push_back (route);
+}
+
+
 Ptr<Ipv4Route>
 Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest)
 {
   NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC ("Looking for route for destination " << dest);
   Ptr<Ipv4Route> rtentry = 0;
   bool found = false;
   Ipv4RoutingTableEntry* route = 0;
@@ -137,6 +154,23 @@
             }
         }
     }
+  if (found == false)
+    {
+      for (ASExternalRoutesI k = m_ASexternalRoutes.begin ();
+           k != m_ASexternalRoutes.end ();
+           k++)
+        {
+          Ipv4Mask mask = (*k)->GetDestNetworkMask ();
+          Ipv4Address entry = (*k)->GetDestNetwork ();
+          if (mask.IsMatch (dest, entry))
+            {
+              NS_LOG_LOGIC ("Found external route" << *k);
+              route = (*k);
+              found = true;
+              break;
+            }
+        }
+    }
   if (found == true)
     {
       rtentry = Create<Ipv4Route> ();
@@ -161,6 +195,7 @@
   uint32_t n = 0;
   n += m_hostRoutes.size ();
   n += m_networkRoutes.size ();
+  n += m_ASexternalRoutes.size ();
   return n;
 }
 
@@ -184,16 +219,31 @@
     }
   index -= m_hostRoutes.size ();
   uint32_t tmp = 0;
-  for (NetworkRoutesI j = m_networkRoutes.begin (); 
-       j != m_networkRoutes.end (); 
-       j++) 
+  if (index < m_networkRoutes.size())
     {
-      if (tmp == index)
+      for (NetworkRoutesI j = m_networkRoutes.begin (); 
+          j != m_networkRoutes.end (); 
+          j++) 
         {
-          return *j;
+          if (tmp == index)
+            {
+              return *j;
+            }
+          tmp++;
         }
-      tmp++;
     }
+  index -= m_networkRoutes.size();
+  tmp = 0;
+  for (ASExternalRoutesI k = m_ASexternalRoutes.begin (); 
+       k != m_ASexternalRoutes.end (); 
+       k++) 
+  {
+    if (tmp == index)
+    {
+      return *k;
+    }
+    tmp++;
+  }
   NS_ASSERT (false);
   // quiet compiler.
   return 0;
@@ -236,6 +286,22 @@
         }
       tmp++;
     }
+  index -= m_networkRoutes.size ();
+  tmp = 0;
+  for (ASExternalRoutesI k = m_ASexternalRoutes.begin (); 
+         k != m_ASexternalRoutes.end (); 
+         k++) 
+    {
+      if (tmp == index)
+      {
+        NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_ASexternalRoutes.size());
+        delete *k;
+        m_ASexternalRoutes.erase (k);
+        NS_LOG_LOGIC ("Done removing network route " << index << "; network route remaining size = " << m_networkRoutes.size());
+        return;
+      }
+      tmp++;
+    }
   NS_ASSERT (false);
 }
 
@@ -255,6 +321,13 @@
     {
       delete (*j);
     }
+  for (ASExternalRoutesI l = m_ASexternalRoutes.begin (); 
+         l != m_ASexternalRoutes.end (); 
+         l = m_ASexternalRoutes.erase (l)) 
+    {
+      delete (*l);
+    }
+
   Ipv4RoutingProtocol::DoDispose ();
 }
 
--- a/src/routing/global-routing/ipv4-global-routing.h	Mon Aug 31 15:29:20 2009 +0200
+++ b/src/routing/global-routing/ipv4-global-routing.h	Mon Aug 31 23:05:26 2009 -0700
@@ -147,6 +147,20 @@
                           uint32_t interface);
 
 /**
+ * \brief Add an external route to the global routing table.
+ *
+ * \param network The Ipv4Address network for this route.
+ * \param networkMask The Ipv4Mask to extract the network.
+ * \param nextHop The next hop Ipv4Address
+ * \param interface The network interface index used to send packets to the
+ * destination.
+ */
+  void AddASExternalRouteTo (Ipv4Address network,
+                             Ipv4Mask networkMask,
+                             Ipv4Address nextHop,
+                             uint32_t interface);
+
+/**
  * \brief Get the number of individual unicast routes that have been added
  * to the routing table.
  *
@@ -204,12 +218,16 @@
   typedef std::list<Ipv4RoutingTableEntry *> NetworkRoutes;
   typedef std::list<Ipv4RoutingTableEntry *>::const_iterator NetworkRoutesCI;
   typedef std::list<Ipv4RoutingTableEntry *>::iterator NetworkRoutesI;
+  typedef std::list<Ipv4RoutingTableEntry *> ASExternalRoutes;
+  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator ASExternalRoutesCI;
+  typedef std::list<Ipv4RoutingTableEntry *>::iterator ASExternalRoutesI;
 
   Ptr<Ipv4Route> LookupGlobal (Ipv4Address dest);
 
   HostRoutes m_hostRoutes;
   NetworkRoutes m_networkRoutes;
-
+  ASExternalRoutes m_ASexternalRoutes; // External routes imported
+  
   Ptr<Ipv4> m_ipv4;
 };