Allow injection of routes to Ipv4GlobalRouting

This commit is contained in:
Antti Makela
2009-08-31 23:05:26 -07:00
parent 8c6d52b1f1
commit c19fc78377
9 changed files with 653 additions and 11 deletions
+6
View File
@@ -52,6 +52,12 @@ us a note on ns-developers mailing list. </p>
<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>
+158
View File
@@ -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;
}
+4
View File
@@ -36,6 +36,10 @@ def build(bld):
['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'
@@ -243,6 +243,15 @@ SPFVertex::IsVertexProcessed (void) const
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 @@ SPFVertex::IsVertexProcessed (void) const
GlobalRouteManagerLSDB::GlobalRouteManagerLSDB ()
:
m_database ()
m_database (),
m_extdatabase ()
{
NS_LOG_FUNCTION_NOARGS ();
}
@@ -267,6 +277,12 @@ GlobalRouteManagerLSDB::~GlobalRouteManagerLSDB ()
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::Initialize ()
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 @@ GlobalRouteManagerImpl::BuildGlobalRoutingDatabase ()
// 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 @@ GlobalRouteManagerImpl::SPFCalculate (Ipv4Address root)
// 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 @@ GlobalRouteManagerImpl::SPFCalculate (Ipv4Address root)
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
@@ -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 @@ public:
* @returns value of underlying flag
*/
bool IsVertexProcessed (void) const;
void ClearVertexProcessed (void);
private:
VertexType m_vertexType;
Ipv4Address m_vertexId;
@@ -683,12 +687,18 @@ public:
* @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 @@ private:
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 @@ private:
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"));
};
@@ -413,6 +413,10 @@ GlobalRoutingLSA::Print (std::ostream &os) const
{
os << " (GlobalRoutingLSA::NetworkLSA)";
}
else if (m_lsType == GlobalRoutingLSA::ASExternalLSAs)
{
os << " (GlobalRoutingLSA::ASExternalLSA)";
}
else
{
os << "(Unknown LSType)";
@@ -474,6 +478,12 @@ GlobalRoutingLSA::Print (std::ostream &os) const
}
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 @@ GlobalRouter::DoDispose ()
{
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 @@ GlobalRouter::GetRouterId (void) const
// 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 @@ GlobalRouter::DiscoverLSAs (void)
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 @@ GlobalRouter::GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const
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.
@@ -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 @@ public:
* 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 @@ public:
*/
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 @@ private:
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);
@@ -98,10 +98,27 @@ Ipv4GlobalRouting::AddNetworkRouteTo (Ipv4Address network,
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 @@ Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest)
}
}
}
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 @@ Ipv4GlobalRouting::GetNRoutes (void)
uint32_t n = 0;
n += m_hostRoutes.size ();
n += m_networkRoutes.size ();
n += m_ASexternalRoutes.size ();
return n;
}
@@ -184,16 +219,31 @@ Ipv4GlobalRouting::GetRoute (uint32_t index)
}
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 @@ Ipv4GlobalRouting::RemoveRoute (uint32_t index)
}
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 @@ Ipv4GlobalRouting::DoDispose (void)
{
delete (*j);
}
for (ASExternalRoutesI l = m_ASexternalRoutes.begin ();
l != m_ASexternalRoutes.end ();
l = m_ASexternalRoutes.erase (l))
{
delete (*l);
}
Ipv4RoutingProtocol::DoDispose ();
}
@@ -146,6 +146,20 @@ public:
Ipv4Mask networkMask,
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 @@ private:
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;
};