Allow injection of routes to Ipv4GlobalRouting
authorAntti Makela <zarhan@cc.hut.fi>
Mon Aug 31 23:05:26 2009 -0700 (5 months ago)
changeset 4745a0e27af57c8d
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
     1.1 --- a/CHANGES.html	Mon Aug 31 15:29:20 2009 +0200
     1.2 +++ b/CHANGES.html	Mon Aug 31 23:05:26 2009 -0700
     1.3 @@ -52,6 +52,12 @@
     1.4  
     1.5  <h2>New API:</h2>
     1.6  <ul>
     1.7 +<li><b>Route injection for global routing</b>
     1.8 +<p>Add ability to inject and withdraw routes to Ipv4GlobalRouting.  This
     1.9 +allows a user to insert a route and have it redistributed like an OSPF
    1.10 +external LSA to the rest of the topology.
    1.11 +</p>
    1.12 +</li>
    1.13  <li><b>Athstats</b>
    1.14  <p>New classes AthstatsWifiTraceSink and AthstatsHelper.
    1.15  </p>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/examples/global-injection-slash32.cc	Mon Aug 31 23:05:26 2009 -0700
     2.3 @@ -0,0 +1,158 @@
     2.4 +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2.5 +/*
     2.6 + * This program is free software; you can redistribute it and/or modify
     2.7 + * it under the terms of the GNU General Public License version 2 as
     2.8 + * published by the Free Software Foundation;
     2.9 + *
    2.10 + * This program is distributed in the hope that it will be useful,
    2.11 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.12 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.13 + * GNU General Public License for more details.
    2.14 + *
    2.15 + * You should have received a copy of the GNU General Public License
    2.16 + * along with this program; if not, write to the Free Software
    2.17 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.18 + *
    2.19 + */
    2.20 +
    2.21 +// Test program for this 3-router scenario, using global routing
    2.22 +//
    2.23 +// (a.a.a.a/32)A<--x.x.x.0/30-->B<--y.y.y.0/30-->C(c.c.c.c/32)
    2.24 +
    2.25 +#include <iostream>
    2.26 +#include <fstream>
    2.27 +#include <string>
    2.28 +#include <cassert>
    2.29 +
    2.30 +#include "ns3/csma-net-device.h"
    2.31 +#include "ns3/core-module.h"
    2.32 +#include "ns3/simulator-module.h"
    2.33 +#include "ns3/node-module.h"
    2.34 +#include "ns3/helper-module.h"
    2.35 +#include "ns3/ipv4-static-routing.h"
    2.36 +#include "ns3/ipv4-global-routing.h"
    2.37 +#include "ns3/ipv4-list-routing.h"
    2.38 +#include "ns3/ipv4-routing-table-entry.h"
    2.39 +#include "ns3/global-router-interface.h"
    2.40 +
    2.41 +using namespace ns3;
    2.42 +using std::cout;
    2.43 +
    2.44 +NS_LOG_COMPONENT_DEFINE ("GlobalRouterInjectionTest");
    2.45 +
    2.46 +int 
    2.47 +main (int argc, char *argv[])
    2.48 +{
    2.49 +
    2.50 +  // Allow the user to override any of the defaults and the above
    2.51 +  // DefaultValue::Bind ()s at run-time, via command-line arguments
    2.52 +  CommandLine cmd;
    2.53 +  cmd.Parse (argc, argv);
    2.54 +
    2.55 +  Ptr<Node> nA = CreateObject<Node> ();
    2.56 +  Ptr<Node> nB = CreateObject<Node> ();
    2.57 +  Ptr<Node> nC = CreateObject<Node> ();
    2.58 +
    2.59 +  NodeContainer c = NodeContainer (nA, nB, nC);
    2.60 +
    2.61 +  InternetStackHelper internet;
    2.62 +
    2.63 +  // Point-to-point links
    2.64 +  NodeContainer nAnB = NodeContainer (nA, nB);
    2.65 +  NodeContainer nBnC = NodeContainer (nB, nC);
    2.66 +
    2.67 +  internet.Install (nAnB);
    2.68 +  Ipv4ListRoutingHelper staticonly;
    2.69 +  Ipv4ListRoutingHelper staticRouting;
    2.70 +  staticonly.Add(staticRouting, 0);
    2.71 +  internet.SetRoutingHelper(staticonly);
    2.72 +  internet.Install(NodeContainer(nC));
    2.73 +
    2.74 +  // We create the channels first without any IP addressing information
    2.75 +  PointToPointHelper p2p;
    2.76 +  p2p.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
    2.77 +  p2p.SetChannelAttribute ("Delay", StringValue ("2ms"));
    2.78 +  NetDeviceContainer dAdB = p2p.Install (nAnB);
    2.79 +
    2.80 +  NetDeviceContainer dBdC = p2p.Install (nBnC);;
    2.81 +  
    2.82 +  Ptr<CsmaNetDevice> deviceA = CreateObject<CsmaNetDevice> ();
    2.83 +  deviceA->SetAddress (Mac48Address::Allocate ());
    2.84 +  nA->AddDevice (deviceA);
    2.85 +
    2.86 +  Ptr<CsmaNetDevice> deviceC = CreateObject<CsmaNetDevice> ();
    2.87 +  deviceC->SetAddress (Mac48Address::Allocate ());
    2.88 +  nC->AddDevice (deviceC);
    2.89 +
    2.90 +  // Later, we add IP addresses.  
    2.91 +  Ipv4AddressHelper ipv4;
    2.92 +  ipv4.SetBase ("10.1.1.0", "255.255.255.252");
    2.93 +  Ipv4InterfaceContainer iAiB = ipv4.Assign (dAdB);
    2.94 +
    2.95 +  ipv4.SetBase ("10.1.1.4", "255.255.255.252");
    2.96 +  Ipv4InterfaceContainer iBiC = ipv4.Assign (dBdC);
    2.97 +
    2.98 +  Ptr<Ipv4> ipv4A = nA->GetObject<Ipv4> ();
    2.99 +  Ptr<Ipv4> ipv4B = nB->GetObject<Ipv4> ();
   2.100 +  Ptr<Ipv4> ipv4C = nC->GetObject<Ipv4> ();
   2.101 +  
   2.102 +  int32_t ifIndexA = ipv4A->AddInterface (deviceA);
   2.103 +  int32_t ifIndexC = ipv4C->AddInterface (deviceC);
   2.104 +    
   2.105 +  Ipv4InterfaceAddress ifInAddrA = Ipv4InterfaceAddress (Ipv4Address ("172.16.1.1"), Ipv4Mask ("255.255.255.255"));
   2.106 +  ipv4A->AddAddress (ifIndexA, ifInAddrA);
   2.107 +  ipv4A->SetMetric (ifIndexA, 1);
   2.108 +  ipv4A->SetUp (ifIndexA);
   2.109 +
   2.110 +  Ipv4InterfaceAddress ifInAddrC = Ipv4InterfaceAddress (Ipv4Address ("192.168.1.1"), Ipv4Mask ("255.255.255.255"));
   2.111 +  ipv4C->AddAddress (ifIndexC, ifInAddrC);
   2.112 +  ipv4C->SetMetric (ifIndexC, 1);
   2.113 +  ipv4C->SetUp (ifIndexC);
   2.114 + 
   2.115 +  // Create router nodes, initialize routing database and set up the routing
   2.116 +  // tables in the nodes.
   2.117 +  
   2.118 +  // Populate routing tables for nodes nA and nB
   2.119 +  Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
   2.120 +  // Inject global routes from Node B, including transit network...
   2.121 +  Ptr<GlobalRouter> globalRouterB = nB->GetObject<GlobalRouter> ();
   2.122 +  globalRouterB->InjectRoute ("10.1.1.4", "255.255.255.252");
   2.123 +  // ...and the host in network "C"
   2.124 +  globalRouterB->InjectRoute ("192.168.1.1", "255.255.255.255");
   2.125 +  
   2.126 +  Ipv4GlobalRoutingHelper::RecomputeRoutingTables();
   2.127 +  // In addition, nB needs a static route to nC so it knows what to do with stuff
   2.128 +  // going to 192.168.1.1
   2.129 +  Ipv4StaticRoutingHelper ipv4RoutingHelper;
   2.130 +  Ptr<Ipv4StaticRouting> staticRoutingB = ipv4RoutingHelper.GetStaticRouting(ipv4B);
   2.131 +  staticRoutingB->AddHostRouteTo (Ipv4Address ("192.168.1.1"), Ipv4Address ("10.1.1.6"),2);
   2.132 +  
   2.133 +  // Create the OnOff application to send UDP datagrams of size
   2.134 +  // 210 bytes at a rate of 448 Kb/s
   2.135 +  uint16_t port = 9;   // Discard port (RFC 863)
   2.136 +  OnOffHelper onoff ("ns3::UdpSocketFactory", 
   2.137 +    Address (InetSocketAddress (ifInAddrC.GetLocal(), port)));
   2.138 +  onoff.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
   2.139 +  onoff.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
   2.140 +  onoff.SetAttribute ("DataRate", DataRateValue (DataRate (6000)));
   2.141 +  ApplicationContainer apps = onoff.Install (nA);
   2.142 +  apps.Start (Seconds (1.0));
   2.143 +  apps.Stop (Seconds (10.0));
   2.144 +
   2.145 +  // Create a packet sink to receive these packets
   2.146 +  PacketSinkHelper sink ("ns3::UdpSocketFactory",
   2.147 +    Address (InetSocketAddress (Ipv4Address::GetAny (), port)));
   2.148 +  apps = sink.Install (nC);
   2.149 +  apps.Start (Seconds (1.0));
   2.150 +  apps.Stop (Seconds (10.0));
   2.151 +
   2.152 +  std::ofstream ascii;
   2.153 +  ascii.open ("global-routing-injection32.tr", std::ios_base::binary | std::ios_base::out);
   2.154 +  PointToPointHelper::EnablePcapAll ("global-routing-injection32");
   2.155 +  PointToPointHelper::EnableAsciiAll (ascii);
   2.156 +
   2.157 +  Simulator::Run ();
   2.158 +  Simulator::Destroy ();
   2.159 +
   2.160 +  return 0;
   2.161 +}
     3.1 --- a/examples/wscript	Mon Aug 31 15:29:20 2009 +0200
     3.2 +++ b/examples/wscript	Mon Aug 31 23:05:26 2009 -0700
     3.3 @@ -36,6 +36,10 @@
     3.4                                   ['point-to-point', 'internet-stack', 'global-routing'])
     3.5      obj.source = 'global-routing-slash32.cc'
     3.6  
     3.7 +    obj = bld.create_ns3_program('global-injection-slash32',
     3.8 +                                 ['point-to-point', 'internet-stack', 'global-routing'])
     3.9 +    obj.source = 'global-injection-slash32.cc'
    3.10 +
    3.11      obj = bld.create_ns3_program('simple-global-routing',
    3.12                                   ['point-to-point', 'internet-stack', 'global-routing'])
    3.13      obj.source = 'simple-global-routing.cc'
     4.1 --- a/src/routing/global-routing/global-route-manager-impl.cc	Mon Aug 31 15:29:20 2009 +0200
     4.2 +++ b/src/routing/global-routing/global-route-manager-impl.cc	Mon Aug 31 23:05:26 2009 -0700
     4.3 @@ -243,6 +243,15 @@
     4.4    return m_vertexProcessed;
     4.5  }
     4.6  
     4.7 +void
     4.8 +SPFVertex::ClearVertexProcessed (void)
     4.9 +{
    4.10 +  for (uint32_t i = 0; i < this->GetNChildren (); i++)
    4.11 +    {
    4.12 +      this->GetChild (i)->ClearVertexProcessed ();
    4.13 +    }
    4.14 +  this->SetVertexProcessed (false);
    4.15 +}
    4.16  
    4.17  // ---------------------------------------------------------------------------
    4.18  //
    4.19 @@ -252,7 +261,8 @@
    4.20  
    4.21  GlobalRouteManagerLSDB::GlobalRouteManagerLSDB ()
    4.22  :
    4.23 -  m_database ()
    4.24 +  m_database (),
    4.25 +  m_extdatabase ()
    4.26  {
    4.27    NS_LOG_FUNCTION_NOARGS ();
    4.28  }
    4.29 @@ -267,6 +277,12 @@
    4.30        GlobalRoutingLSA* temp = i->second;
    4.31        delete temp;
    4.32      }
    4.33 +  for (uint32_t j = 0; j < m_extdatabase.size (); j++)
    4.34 +    {
    4.35 +      NS_LOG_LOGIC ("free ASexternalLSA");
    4.36 +      GlobalRoutingLSA* temp = m_extdatabase.at (j);
    4.37 +      delete temp;
    4.38 +    }
    4.39    NS_LOG_LOGIC ("clear map");
    4.40    m_database.clear ();
    4.41  }
    4.42 @@ -287,7 +303,26 @@
    4.43  GlobalRouteManagerLSDB::Insert (Ipv4Address addr, GlobalRoutingLSA* lsa)
    4.44  {
    4.45    NS_LOG_FUNCTION (addr << lsa);
    4.46 -  m_database.insert (LSDBPair_t (addr, lsa));
    4.47 +  if (lsa->GetLSType () == GlobalRoutingLSA::ASExternalLSAs) 
    4.48 +    {
    4.49 +      m_extdatabase.push_back (lsa);
    4.50 +    } 
    4.51 +  else
    4.52 +    {
    4.53 +      m_database.insert (LSDBPair_t (addr, lsa));
    4.54 +    }
    4.55 +}
    4.56 +
    4.57 +  GlobalRoutingLSA*
    4.58 +GlobalRouteManagerLSDB::GetExtLSA (uint32_t index) const
    4.59 +{
    4.60 +  return m_extdatabase.at (index);
    4.61 +}
    4.62 +
    4.63 +  uint32_t
    4.64 +GlobalRouteManagerLSDB::GetNumExtLSAs () const
    4.65 +{
    4.66 +  return m_extdatabase.size ();
    4.67  }
    4.68  
    4.69    GlobalRoutingLSA*
    4.70 @@ -438,6 +473,7 @@
    4.71  // DiscoverLSAs () will get zero as the number since no routes have been 
    4.72  // found.
    4.73  //
    4.74 +      Ptr<Ipv4GlobalRouting> grouting = rtr->GetRoutingProtocol ();
    4.75        uint32_t numLSAs = rtr->DiscoverLSAs ();
    4.76        NS_LOG_LOGIC ("Found " << numLSAs << " LSAs");
    4.77  
    4.78 @@ -1237,6 +1273,14 @@
    4.79  
    4.80  // Second stage of SPF calculation procedure  
    4.81    SPFProcessStubs (m_spfroot);
    4.82 +  for (uint32_t i = 0; i < m_lsdb->GetNumExtLSAs (); i++)
    4.83 +    {
    4.84 +      m_spfroot->ClearVertexProcessed ();
    4.85 +      GlobalRoutingLSA *extlsa = m_lsdb->GetExtLSA (i);
    4.86 +      NS_LOG_LOGIC ("Processing External LSA with id " << extlsa->GetLinkStateId ());
    4.87 +      ProcessASExternals (m_spfroot, extlsa);
    4.88 +    }
    4.89 +
    4.90  //
    4.91  // We're all done setting the routing information for the node at the root of
    4.92  // the SPF tree.  Delete all of the vertices and corresponding resources.  Go
    4.93 @@ -1246,6 +1290,160 @@
    4.94    m_spfroot = 0;
    4.95  }
    4.96  
    4.97 +void
    4.98 +GlobalRouteManagerImpl::ProcessASExternals (SPFVertex* v, GlobalRoutingLSA* extlsa)
    4.99 +{
   4.100 +  NS_LOG_FUNCTION_NOARGS ();
   4.101 +  NS_LOG_LOGIC ("Processing external for destination " << 
   4.102 +      extlsa->GetLinkStateId () <<
   4.103 +      ", for router "  << v->GetVertexId () << 
   4.104 +      ", advertised by " << extlsa->GetAdvertisingRouter ());
   4.105 +  if (v->GetVertexType () == SPFVertex::VertexRouter)
   4.106 +    {
   4.107 +      GlobalRoutingLSA *rlsa = v->GetLSA ();
   4.108 +      NS_LOG_LOGIC ("Processing router LSA with id " << rlsa->GetLinkStateId ());
   4.109 +      if ((rlsa->GetLinkStateId ()) == (extlsa->GetAdvertisingRouter ()))
   4.110 +        {
   4.111 +          NS_LOG_LOGIC ("Found advertising router to destination");
   4.112 +          SPFAddASExternal(extlsa,v);
   4.113 +        }
   4.114 +    }
   4.115 +  for (uint32_t i = 0; i < v->GetNChildren (); i++)
   4.116 +    {
   4.117 +      if (!v->GetChild (i)->IsVertexProcessed ())
   4.118 +        {
   4.119 +          NS_LOG_LOGIC ("Vertex's child " << i << " not yet processed, processing...");
   4.120 +          ProcessASExternals (v->GetChild (i), extlsa);
   4.121 +          v->GetChild (i)->SetVertexProcessed (true);
   4.122 +        }
   4.123 +    }
   4.124 +}
   4.125 +
   4.126 +//
   4.127 +// Adding external routes to routing table - modeled after
   4.128 +// SPFAddIntraAddStub()
   4.129 +//
   4.130 +
   4.131 +void
   4.132 +GlobalRouteManagerImpl::SPFAddASExternal (GlobalRoutingLSA *extlsa, SPFVertex *v)
   4.133 +{
   4.134 +  NS_LOG_FUNCTION_NOARGS ();
   4.135 +
   4.136 +  NS_ASSERT_MSG (m_spfroot, "GlobalRouteManagerImpl::SPFAddASExternal (): Root pointer not set");
   4.137 +// Two cases to consider: We are advertising the external ourselves
   4.138 +// => No need to add anything
   4.139 +// OR find best path to the advertising router
   4.140 +  if (v->GetVertexId () == m_spfroot->GetVertexId ())
   4.141 +    {
   4.142 +      NS_LOG_LOGIC ("External is on local host: " 
   4.143 +        << v->GetVertexId () << "; returning");
   4.144 +      return;
   4.145 +    }
   4.146 +  NS_LOG_LOGIC ("External is on remote host: " 
   4.147 +    << extlsa->GetAdvertisingRouter () << "; installing");
   4.148 +  
   4.149 +  Ipv4Address routerId = m_spfroot->GetVertexId ();
   4.150 +
   4.151 +  NS_LOG_LOGIC ("Vertex ID = " << routerId);
   4.152 +//
   4.153 +// We need to walk the list of nodes looking for the one that has the router
   4.154 +// ID corresponding to the root vertex.  This is the one we're going to write
   4.155 +// the routing information to.
   4.156 +//
   4.157 +  NodeList::Iterator i = NodeList::Begin (); 
   4.158 +  for (; i != NodeList::End (); i++)
   4.159 +    {
   4.160 +      Ptr<Node> node = *i;
   4.161 +//
   4.162 +// The router ID is accessible through the GlobalRouter interface, so we need
   4.163 +// to QI for that interface.  If there's no GlobalRouter interface, the node
   4.164 +// in question cannot be the router we want, so we continue.
   4.165 +// 
   4.166 +      Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter> ();
   4.167 +
   4.168 +      if (rtr == 0)
   4.169 +        {
   4.170 +          NS_LOG_LOGIC ("No GlobalRouter interface on node " << node->GetId ());
   4.171 +          continue;
   4.172 +        }
   4.173 +//
   4.174 +// If the router ID of the current node is equal to the router ID of the 
   4.175 +// root of the SPF tree, then this node is the one for which we need to 
   4.176 +// write the routing tables.
   4.177 +//
   4.178 +      NS_LOG_LOGIC ("Considering router " << rtr->GetRouterId ());
   4.179 +
   4.180 +      if (rtr->GetRouterId () == routerId)
   4.181 +        {
   4.182 +          NS_LOG_LOGIC ("Setting routes for node " << node->GetId ());
   4.183 +//
   4.184 +// Routing information is updated using the Ipv4 interface.  We need to QI
   4.185 +// for that interface.  If the node is acting as an IP version 4 router, it
   4.186 +// should absolutely have an Ipv4 interface.
   4.187 +//
   4.188 +          Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
   4.189 +          NS_ASSERT_MSG (ipv4, 
   4.190 +                     "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
   4.191 +                         "QI for <Ipv4> interface failed");
   4.192 +//
   4.193 +// Get the Global Router Link State Advertisement from the vertex we're
   4.194 +// adding the routes to.  The LSA will have a number of attached Global Router
   4.195 +// Link Records corresponding to links off of that vertex / node.  We're going
   4.196 +// to be interested in the records corresponding to point-to-point links.
   4.197 +//
   4.198 +          NS_ASSERT_MSG (v->GetLSA (), 
   4.199 +                     "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
   4.200 +                         "Expected valid LSA in SPFVertex* v");
   4.201 +          Ipv4Mask tempmask = extlsa->GetNetworkLSANetworkMask ();
   4.202 +          Ipv4Address tempip = extlsa->GetLinkStateId ();
   4.203 +          tempip = tempip.CombineMask (tempmask);
   4.204 +
   4.205 +          NS_LOG_LOGIC (" Node " << node->GetId () <<
   4.206 +              " add route to " << tempip <<
   4.207 +              " with mask " << tempmask <<
   4.208 +              " using next hop " << v->GetNextHop () <<
   4.209 +              " via interface " << v->GetOutgoingInterfaceId ());
   4.210 +//
   4.211 +// Here's why we did all of that work.  We're going to add a host route to the
   4.212 +// host address found in the m_linkData field of the point-to-point link
   4.213 +// record.  In the case of a point-to-point link, this is the local IP address
   4.214 +// of the node connected to the link.  Each of these point-to-point links
   4.215 +// will correspond to a local interface that has an IP address to which
   4.216 +// the node at the root of the SPF tree can send packets.  The vertex <v> 
   4.217 +// (corresponding to the node that has these links and interfaces) has 
   4.218 +// an m_nextHop address precalculated for us that is the address to which the
   4.219 +// root node should send packets to be forwarded to these IP addresses.
   4.220 +// Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
   4.221 +// which the packets should be send for forwarding.
   4.222 +//
   4.223 +          Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
   4.224 +          if (router == 0)
   4.225 +            {
   4.226 +              continue;
   4.227 +            }
   4.228 +          Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
   4.229 +          NS_ASSERT (gr);
   4.230 +          if (v->GetOutgoingInterfaceId () >= 0)
   4.231 +            {
   4.232 +              gr->AddASExternalRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingInterfaceId ());
   4.233 +              NS_LOG_LOGIC ("Node " << node->GetId () <<
   4.234 +                  " add network route to " << tempip <<
   4.235 +                  " using next hop " << v->GetNextHop () <<
   4.236 +                  " via interface " << v->GetOutgoingInterfaceId ());
   4.237 +            }
   4.238 +          else
   4.239 +            {
   4.240 +              NS_LOG_LOGIC ("Node " << node->GetId () <<
   4.241 +                  " NOT able to add network route to " << tempip <<
   4.242 +                  " using next hop " << v->GetNextHop () <<
   4.243 +                  " since outgoing interface id is negative");
   4.244 +            }
   4.245 +          return;
   4.246 +        } // if
   4.247 +    } // for
   4.248 +}
   4.249 +
   4.250 +
   4.251  // Processing logic from RFC 2328, page 166 and quagga ospf_spf_process_stubs ()
   4.252  // stub link records will exist for point-to-point interfaces and for
   4.253  // broadcast interfaces for which no neighboring router can be found
     5.1 --- a/src/routing/global-routing/global-route-manager-impl.h	Mon Aug 31 15:29:20 2009 +0200
     5.2 +++ b/src/routing/global-routing/global-route-manager-impl.h	Mon Aug 31 23:05:26 2009 -0700
     5.3 @@ -26,6 +26,7 @@
     5.4  #include <list>
     5.5  #include <queue>
     5.6  #include <map>
     5.7 +#include <vector>
     5.8  #include "ns3/object.h"
     5.9  #include "ns3/ptr.h"
    5.10  #include "ns3/ipv4-address.h"
    5.11 @@ -563,6 +564,9 @@
    5.12     * @returns value of underlying flag
    5.13     */ 
    5.14    bool IsVertexProcessed (void) const;
    5.15 +  
    5.16 +  void ClearVertexProcessed (void);
    5.17 +      
    5.18  private:
    5.19    VertexType m_vertexType;
    5.20    Ipv4Address m_vertexId;
    5.21 @@ -683,12 +687,18 @@
    5.22   * @see SPFVertex
    5.23   */
    5.24    void Initialize ();
    5.25 +  
    5.26 +  GlobalRoutingLSA* GetExtLSA (uint32_t index) const;
    5.27 +  uint32_t GetNumExtLSAs () const;
    5.28 +      
    5.29  
    5.30  private:
    5.31    typedef std::map<Ipv4Address, GlobalRoutingLSA*> LSDBMap_t;
    5.32    typedef std::pair<Ipv4Address, GlobalRoutingLSA*> LSDBPair_t;
    5.33  
    5.34    LSDBMap_t m_database;
    5.35 +  std::vector<GlobalRoutingLSA*> m_extdatabase;
    5.36 +  
    5.37  /**
    5.38   * @brief GlobalRouteManagerLSDB copy construction is disallowed.  There's no 
    5.39   * need for it and a compiler provided shallow copy would be wrong.
    5.40 @@ -775,6 +785,7 @@
    5.41    bool CheckForStubNode (Ipv4Address root);
    5.42    void SPFCalculate (Ipv4Address root);
    5.43    void SPFProcessStubs (SPFVertex* v);
    5.44 +  void ProcessASExternals (SPFVertex* v, GlobalRoutingLSA* extlsa);
    5.45    void SPFNext (SPFVertex*, CandidateQueue&);
    5.46    int SPFNexthopCalculation (SPFVertex* v, SPFVertex* w, 
    5.47      GlobalRoutingLinkRecord* l, uint32_t distance);
    5.48 @@ -784,6 +795,7 @@
    5.49    void SPFIntraAddRouter (SPFVertex* v);
    5.50    void SPFIntraAddTransit (SPFVertex* v);
    5.51    void SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v);
    5.52 +  void SPFAddASExternal (GlobalRoutingLSA *extlsa, SPFVertex *v);
    5.53    int32_t FindOutgoingInterfaceId (Ipv4Address a, 
    5.54      Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
    5.55  };
     6.1 --- a/src/routing/global-routing/global-router-interface.cc	Mon Aug 31 15:29:20 2009 +0200
     6.2 +++ b/src/routing/global-routing/global-router-interface.cc	Mon Aug 31 23:05:26 2009 -0700
     6.3 @@ -413,6 +413,10 @@
     6.4      {
     6.5        os << " (GlobalRoutingLSA::NetworkLSA)";
     6.6      }
     6.7 +  else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
     6.8 +    {
     6.9 +      os << " (GlobalRoutingLSA::ASExternalLSA)";
    6.10 +    }
    6.11    else
    6.12      {
    6.13        os << "(Unknown LSType)";
    6.14 @@ -474,6 +478,12 @@
    6.15          }
    6.16        os << "---------- End NetworkLSA Link Record ----------" << std::endl;
    6.17      }
    6.18 +  else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
    6.19 +    {
    6.20 +      os << "---------- ASExternalLSA Link Record --------" << std::endl;
    6.21 +      os << "m_linkStateId = " << m_linkStateId << std::endl;
    6.22 +      os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask << std::endl;
    6.23 +    }
    6.24    else 
    6.25      {
    6.26        NS_ASSERT_MSG(0, "Illegal LSA LSType: " << m_lsType);
    6.27 @@ -532,6 +542,12 @@
    6.28  {
    6.29    NS_LOG_FUNCTION_NOARGS ();
    6.30    m_routingProtocol = 0;
    6.31 +  for (InjectedRoutesI k = m_injectedRoutes.begin ();
    6.32 +         k != m_injectedRoutes.end ();
    6.33 +         k = m_injectedRoutes.erase (k))
    6.34 +    {
    6.35 +      delete (*k);
    6.36 +    }
    6.37    Object::DoDispose ();
    6.38  }
    6.39  
    6.40 @@ -568,8 +584,8 @@
    6.41  // and build the Link State Advertisements that reflect them and their associated
    6.42  // networks.
    6.43  // 
    6.44 -  uint32_t 
    6.45 -GlobalRouter::DiscoverLSAs (void)
    6.46 +uint32_t 
    6.47 +GlobalRouter::DiscoverLSAs ()
    6.48  {
    6.49    NS_LOG_FUNCTION_NOARGS ();
    6.50    Ptr<Node> node = GetObject<Node> ();
    6.51 @@ -696,6 +712,22 @@
    6.52        BuildNetworkLSAs (c);
    6.53      }
    6.54  
    6.55 +  //
    6.56 +  // Build injected route LSAs as external routes
    6.57 +  // RFC 2328, section 12.4.4
    6.58 +  //
    6.59 +  for (InjectedRoutesCI i = m_injectedRoutes.begin();
    6.60 +       i != m_injectedRoutes.end();
    6.61 +       i++)
    6.62 +    {
    6.63 +      GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
    6.64 +      pLSA->SetLSType (GlobalRoutingLSA::ASExternalLSAs);
    6.65 +      pLSA->SetLinkStateId ((*i)->GetDestNetwork ());
    6.66 +      pLSA->SetAdvertisingRouter (m_routerId);
    6.67 +      pLSA->SetNetworkLSANetworkMask ((*i)->GetDestNetworkMask ());
    6.68 +      pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
    6.69 +      m_LSAs.push_back (pLSA); 
    6.70 +    }
    6.71    return m_LSAs.size ();
    6.72  }
    6.73  
    6.74 @@ -1467,6 +1499,86 @@
    6.75    return false;
    6.76  }
    6.77  
    6.78 +void
    6.79 +GlobalRouter::InjectRoute (Ipv4Address network, Ipv4Mask networkMask)
    6.80 +{
    6.81 +  NS_LOG_FUNCTION (network << networkMask);
    6.82 +  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
    6.83 +//
    6.84 +// Interface number does not matter here, using 1.
    6.85 +//
    6.86 +  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
    6.87 +      networkMask,
    6.88 +      1);
    6.89 +  m_injectedRoutes.push_back (route);
    6.90 +}
    6.91 +
    6.92 +Ipv4RoutingTableEntry *
    6.93 +GlobalRouter::GetInjectedRoute (uint32_t index)
    6.94 +{
    6.95 +  NS_LOG_FUNCTION (index);
    6.96 +  if (index < m_injectedRoutes.size ())
    6.97 +    {
    6.98 +      uint32_t tmp = 0;
    6.99 +      for (InjectedRoutesCI i = m_injectedRoutes.begin ();
   6.100 +           i != m_injectedRoutes.end ();
   6.101 +           i++)
   6.102 +        {
   6.103 +          if (tmp  == index)
   6.104 +            {
   6.105 +              return *i;
   6.106 +            }
   6.107 +          tmp++;
   6.108 +        }
   6.109 +     }
   6.110 +  NS_ASSERT (false);
   6.111 +  // quiet compiler.
   6.112 +  return 0;
   6.113 +}
   6.114 +
   6.115 +uint32_t
   6.116 +GlobalRouter::GetNInjectedRoutes ()
   6.117 +{
   6.118 +  return m_injectedRoutes.size ();
   6.119 +}
   6.120 +
   6.121 +void
   6.122 +GlobalRouter::RemoveInjectedRoute (uint32_t index)
   6.123 +{
   6.124 +  NS_LOG_FUNCTION (index);
   6.125 +  NS_ASSERT (index < m_injectedRoutes.size ());
   6.126 +  uint32_t tmp = 0;
   6.127 +  for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
   6.128 +    {
   6.129 +      if (tmp  == index)
   6.130 +        {
   6.131 +          NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_injectedRoutes.size());
   6.132 +          delete *i;
   6.133 +          m_injectedRoutes.erase (i);
   6.134 +          return;
   6.135 +        }
   6.136 +      tmp++;
   6.137 +    }
   6.138 +}
   6.139 +
   6.140 +bool
   6.141 +GlobalRouter::WithdrawRoute (Ipv4Address network, Ipv4Mask networkMask)
   6.142 +{
   6.143 +  NS_LOG_FUNCTION (index);
   6.144 +  for (InjectedRoutesI i = m_injectedRoutes.begin (); i != m_injectedRoutes.end (); i++)
   6.145 +    {
   6.146 +      if ((*i)->GetDestNetwork () == network && (*i)->GetDestNetworkMask () == networkMask)
   6.147 +        {
   6.148 +          NS_LOG_LOGIC ("Withdrawing route to network/mask " << network << "/" << networkMask);
   6.149 +          delete *i;
   6.150 +          m_injectedRoutes.erase (i);
   6.151 +          return true;
   6.152 +        }
   6.153 +    }
   6.154 +  return false;
   6.155 +}
   6.156 +
   6.157 +
   6.158  //
   6.159  // Link through the given channel and find the net device that's on the
   6.160  // other end.  This only makes sense with a point-to-point channel.
     7.1 --- a/src/routing/global-routing/global-router-interface.h	Mon Aug 31 15:29:20 2009 +0200
     7.2 +++ b/src/routing/global-routing/global-router-interface.h	Mon Aug 31 23:05:26 2009 -0700
     7.3 @@ -32,6 +32,7 @@
     7.4  #include "ns3/net-device-container.h"
     7.5  #include "ns3/bridge-net-device.h"
     7.6  #include "ns3/global-route-manager.h"
     7.7 +#include "ns3/ipv4-routing-table-entry.h"
     7.8  
     7.9  namespace ns3 {
    7.10  
    7.11 @@ -614,6 +615,8 @@
    7.12   * advertisements after a network topology change by calling DiscoverLSAs 
    7.13   * and then by reading those advertisements.
    7.14   *
    7.15 + * \param List of routing table entries of external routes to be injected.
    7.16 + *
    7.17   * @see GlobalRoutingLSA
    7.18   * @see GlobalRouter::GetLSA ()
    7.19   * @returns The number of Global Routing Link State Advertisements.
    7.20 @@ -657,6 +660,59 @@
    7.21   */
    7.22    bool GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const;
    7.23  
    7.24 +/**
    7.25 + * @brief Inject a route to be circulated to other routers as an external
    7.26 + * route
    7.27 + *
    7.28 + * @param network The Network to inject
    7.29 + * @param networkMask The Network Mask to inject
    7.30 + */
    7.31 +  void InjectRoute (Ipv4Address network, Ipv4Mask networkMask);
    7.32 +
    7.33 +/**
    7.34 + * @brief Get the number of injected routes that have been added
    7.35 + * to the routing table.
    7.36 + * @return number of injected routes
    7.37 + */
    7.38 +  uint32_t GetNInjectedRoutes (void);
    7.39 +
    7.40 +/**
    7.41 + * @brief Return the injected route indexed by i
    7.42 + * @param i the index of the route
    7.43 + * @return a pointer to that Ipv4RoutingTableEntry is returned
    7.44 + *
    7.45 + */
    7.46 +  Ipv4RoutingTableEntry *GetInjectedRoute (uint32_t i);
    7.47 +
    7.48 +/**
    7.49 + * @brief Withdraw a route from the global unicast routing table.
    7.50 + *
    7.51 + * Calling this function will cause all indexed routes numbered above
    7.52 + * index i to have their index decremented.  For instance, it is possible to
    7.53 + * remove N injected routes by calling RemoveInjectedRoute (0) N times.
    7.54 + *
    7.55 + * @param i The index (into the injected routing list) of the route to remove.  
    7.56 + *
    7.57 + * @see GlobalRouter::WithdrawRoute ()
    7.58 + */
    7.59 +  void RemoveInjectedRoute (uint32_t i);
    7.60 +
    7.61 +/**
    7.62 + * @brief Withdraw a route from the global unicast routing table.
    7.63 + *
    7.64 + * Calling this function will cause all indexed routes numbered above
    7.65 + * index i to have their index decremented.  For instance, it is possible to
    7.66 + * remove N injected routes by calling RemoveInjectedRoute (0) N times.
    7.67 + *
    7.68 + * @param i The index (into the injected routing list) of the route to remove.  
    7.69 + * @param network The Network to inject
    7.70 + * @param networkMask The Network Mask to inject
    7.71 + * @return whether the operation succeeded (will return false if no such route)
    7.72 + *
    7.73 + * @see GlobalRouter::RemoveInjectedRoute ()
    7.74 + */
    7.75 +  bool WithdrawRoute (Ipv4Address network, Ipv4Mask networkMask);
    7.76 +
    7.77  private:
    7.78    virtual ~GlobalRouter ();
    7.79    void ClearLSAs (void);
    7.80 @@ -680,6 +736,11 @@
    7.81    Ipv4Address m_routerId;
    7.82    Ptr<Ipv4GlobalRouting> m_routingProtocol;
    7.83  
    7.84 +  typedef std::list<Ipv4RoutingTableEntry *> InjectedRoutes;
    7.85 +  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator InjectedRoutesCI;
    7.86 +  typedef std::list<Ipv4RoutingTableEntry *>::iterator InjectedRoutesI;
    7.87 +  InjectedRoutes m_injectedRoutes; // Routes we are exporting
    7.88 +
    7.89    // inherited from Object
    7.90    virtual void DoDispose (void);
    7.91  
     8.1 --- a/src/routing/global-routing/ipv4-global-routing.cc	Mon Aug 31 15:29:20 2009 +0200
     8.2 +++ b/src/routing/global-routing/ipv4-global-routing.cc	Mon Aug 31 23:05:26 2009 -0700
     8.3 @@ -98,10 +98,27 @@
     8.4    m_networkRoutes.push_back (route);
     8.5  }
     8.6  
     8.7 +void 
     8.8 +Ipv4GlobalRouting::AddASExternalRouteTo (Ipv4Address network, 
     8.9 +                                         Ipv4Mask networkMask,
    8.10 +                                         Ipv4Address nextHop,
    8.11 +                                         uint32_t interface)
    8.12 +{
    8.13 +  NS_LOG_FUNCTION (network << networkMask << nextHop);
    8.14 +  Ipv4RoutingTableEntry *route = new Ipv4RoutingTableEntry ();
    8.15 +  *route = Ipv4RoutingTableEntry::CreateNetworkRouteTo (network,
    8.16 +      networkMask,
    8.17 +      nextHop,
    8.18 +      interface);
    8.19 +  m_ASexternalRoutes.push_back (route);
    8.20 +}
    8.21 +
    8.22 +
    8.23  Ptr<Ipv4Route>
    8.24  Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest)
    8.25  {
    8.26    NS_LOG_FUNCTION_NOARGS ();
    8.27 +  NS_LOG_LOGIC ("Looking for route for destination " << dest);
    8.28    Ptr<Ipv4Route> rtentry = 0;
    8.29    bool found = false;
    8.30    Ipv4RoutingTableEntry* route = 0;
    8.31 @@ -137,6 +154,23 @@
    8.32              }
    8.33          }
    8.34      }
    8.35 +  if (found == false)
    8.36 +    {
    8.37 +      for (ASExternalRoutesI k = m_ASexternalRoutes.begin ();
    8.38 +           k != m_ASexternalRoutes.end ();
    8.39 +           k++)
    8.40 +        {
    8.41 +          Ipv4Mask mask = (*k)->GetDestNetworkMask ();
    8.42 +          Ipv4Address entry = (*k)->GetDestNetwork ();
    8.43 +          if (mask.IsMatch (dest, entry))
    8.44 +            {
    8.45 +              NS_LOG_LOGIC ("Found external route" << *k);
    8.46 +              route = (*k);
    8.47 +              found = true;
    8.48 +              break;
    8.49 +            }
    8.50 +        }
    8.51 +    }
    8.52    if (found == true)
    8.53      {
    8.54        rtentry = Create<Ipv4Route> ();
    8.55 @@ -161,6 +195,7 @@
    8.56    uint32_t n = 0;
    8.57    n += m_hostRoutes.size ();
    8.58    n += m_networkRoutes.size ();
    8.59 +  n += m_ASexternalRoutes.size ();
    8.60    return n;
    8.61  }
    8.62  
    8.63 @@ -184,16 +219,31 @@
    8.64      }
    8.65    index -= m_hostRoutes.size ();
    8.66    uint32_t tmp = 0;
    8.67 -  for (NetworkRoutesI j = m_networkRoutes.begin (); 
    8.68 -       j != m_networkRoutes.end (); 
    8.69 -       j++) 
    8.70 +  if (index < m_networkRoutes.size())
    8.71      {
    8.72 -      if (tmp == index)
    8.73 +      for (NetworkRoutesI j = m_networkRoutes.begin (); 
    8.74 +          j != m_networkRoutes.end (); 
    8.75 +          j++) 
    8.76          {
    8.77 -          return *j;
    8.78 +          if (tmp == index)
    8.79 +            {
    8.80 +              return *j;
    8.81 +            }
    8.82 +          tmp++;
    8.83          }
    8.84 -      tmp++;
    8.85      }
    8.86 +  index -= m_networkRoutes.size();
    8.87 +  tmp = 0;
    8.88 +  for (ASExternalRoutesI k = m_ASexternalRoutes.begin (); 
    8.89 +       k != m_ASexternalRoutes.end (); 
    8.90 +       k++) 
    8.91 +  {
    8.92 +    if (tmp == index)
    8.93 +    {
    8.94 +      return *k;
    8.95 +    }
    8.96 +    tmp++;
    8.97 +  }
    8.98    NS_ASSERT (false);
    8.99    // quiet compiler.
   8.100    return 0;
   8.101 @@ -236,6 +286,22 @@
   8.102          }
   8.103        tmp++;
   8.104      }
   8.105 +  index -= m_networkRoutes.size ();
   8.106 +  tmp = 0;
   8.107 +  for (ASExternalRoutesI k = m_ASexternalRoutes.begin (); 
   8.108 +         k != m_ASexternalRoutes.end (); 
   8.109 +         k++) 
   8.110 +    {
   8.111 +      if (tmp == index)
   8.112 +      {
   8.113 +        NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_ASexternalRoutes.size());
   8.114 +        delete *k;
   8.115 +        m_ASexternalRoutes.erase (k);
   8.116 +        NS_LOG_LOGIC ("Done removing network route " << index << "; network route remaining size = " << m_networkRoutes.size());
   8.117 +        return;
   8.118 +      }
   8.119 +      tmp++;
   8.120 +    }
   8.121    NS_ASSERT (false);
   8.122  }
   8.123  
   8.124 @@ -255,6 +321,13 @@
   8.125      {
   8.126        delete (*j);
   8.127      }
   8.128 +  for (ASExternalRoutesI l = m_ASexternalRoutes.begin (); 
   8.129 +         l != m_ASexternalRoutes.end (); 
   8.130 +         l = m_ASexternalRoutes.erase (l)) 
   8.131 +    {
   8.132 +      delete (*l);
   8.133 +    }
   8.134 +
   8.135    Ipv4RoutingProtocol::DoDispose ();
   8.136  }
   8.137  
     9.1 --- a/src/routing/global-routing/ipv4-global-routing.h	Mon Aug 31 15:29:20 2009 +0200
     9.2 +++ b/src/routing/global-routing/ipv4-global-routing.h	Mon Aug 31 23:05:26 2009 -0700
     9.3 @@ -147,6 +147,20 @@
     9.4                            uint32_t interface);
     9.5  
     9.6  /**
     9.7 + * \brief Add an external route to the global routing table.
     9.8 + *
     9.9 + * \param network The Ipv4Address network for this route.
    9.10 + * \param networkMask The Ipv4Mask to extract the network.
    9.11 + * \param nextHop The next hop Ipv4Address
    9.12 + * \param interface The network interface index used to send packets to the
    9.13 + * destination.
    9.14 + */
    9.15 +  void AddASExternalRouteTo (Ipv4Address network,
    9.16 +                             Ipv4Mask networkMask,
    9.17 +                             Ipv4Address nextHop,
    9.18 +                             uint32_t interface);
    9.19 +
    9.20 +/**
    9.21   * \brief Get the number of individual unicast routes that have been added
    9.22   * to the routing table.
    9.23   *
    9.24 @@ -204,12 +218,16 @@
    9.25    typedef std::list<Ipv4RoutingTableEntry *> NetworkRoutes;
    9.26    typedef std::list<Ipv4RoutingTableEntry *>::const_iterator NetworkRoutesCI;
    9.27    typedef std::list<Ipv4RoutingTableEntry *>::iterator NetworkRoutesI;
    9.28 +  typedef std::list<Ipv4RoutingTableEntry *> ASExternalRoutes;
    9.29 +  typedef std::list<Ipv4RoutingTableEntry *>::const_iterator ASExternalRoutesCI;
    9.30 +  typedef std::list<Ipv4RoutingTableEntry *>::iterator ASExternalRoutesI;
    9.31  
    9.32    Ptr<Ipv4Route> LookupGlobal (Ipv4Address dest);
    9.33  
    9.34    HostRoutes m_hostRoutes;
    9.35    NetworkRoutes m_networkRoutes;
    9.36 -
    9.37 +  ASExternalRoutes m_ASexternalRoutes; // External routes imported
    9.38 +  
    9.39    Ptr<Ipv4> m_ipv4;
    9.40  };
    9.41