Merge NixVector Routing code

This commit is contained in:
Josh Pelkey
2009-09-18 10:32:07 -04:00
parent 81fc7f1bf5
commit 4273c4d1ba
20 changed files with 2401 additions and 3 deletions

View File

@@ -31,3 +31,4 @@ Mauro Tortonesi (mauro.tortonesi@unife.it)
Sebastien Vincent (vincent@clarinet.u-strasbg.fr)
Guillaume Vu-Brugier (gvubrugier@gmail.com)
Florian Westphal (fw@strlen.de)
Josh Pelkey (jpelkey@gatech.edu)

View File

@@ -113,6 +113,17 @@ router solicitation, DAD
</p>
</li>
<li><b> Nix-vector Routing</b>
<p> Add nix-vector routing protocol
<ul>
<li> new helper class Ipv4NixVectorHelper
</ul>
<ul>
<li> examples: nix-simple.cc, nms-p2p-nix.cc
</ul>
</p>
</li>
</ul>
<h2>Changes to existing API:</h2>

View File

@@ -59,6 +59,10 @@ New user-visible features
- IEEE 802.11s (Draft 3.0) model including Peering Management Protocol and HWMP.
- Forwarding Layer for Meshing (FLAME) protocol.
d) Nix-vector routing:
- Ipv4NixVectorHelper
- Examples (nix-simple, nms-p2p-nix)
API changes from ns-3.5
-----------------------
API changes for this release are documented in the file CHANGES.html.

114
examples/nix-simple.cc Normal file
View File

@@ -0,0 +1,114 @@
/* -*- 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
*/
#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
/*
* Simple point to point links:
*
* n0 -- n1 -- n2 -- n3
*
* n0 has UdpEchoClient
* n3 has UdpEchoServer
*
* n0 IP: 10.1.1.1
* n1 IP: 10.1.1.2, 10.1.2.1
* n2 IP: 10.1.2.2, 10.1.3.1
* n3 IP: 10.1.3.2
*
*/
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("FirstScriptExample");
int
main (int argc, char *argv[])
{
LogComponentEnable("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable("UdpEchoServerApplication", LOG_LEVEL_INFO);
NodeContainer nodes12;
nodes12.Create (2);
NodeContainer nodes23;
nodes23.Add (nodes12.Get (1));
nodes23.Create (1);
NodeContainer nodes34;
nodes34.Add(nodes23.Get (1));
nodes34.Create (1);
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
NodeContainer allNodes = NodeContainer (nodes12, nodes23.Get (1), nodes34.Get (1));
// NixHelper to install nix-vector routing
// on all nodes
Ipv4NixVectorHelper nixRouting;
Ipv4StaticRoutingHelper staticRouting;
Ipv4ListRoutingHelper list;
list.Add (staticRouting, 0);
list.Add (nixRouting, 10);
InternetStackHelper stack;
stack.SetRoutingHelper (list);
stack.Install (allNodes);
NetDeviceContainer devices12;
NetDeviceContainer devices23;
NetDeviceContainer devices34;
devices12 = pointToPoint.Install (nodes12);
devices23 = pointToPoint.Install (nodes23);
devices34 = pointToPoint.Install (nodes34);
Ipv4AddressHelper address1;
address1.SetBase ("10.1.1.0", "255.255.255.0");
Ipv4AddressHelper address2;
address2.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4AddressHelper address3;
address3.SetBase ("10.1.3.0", "255.255.255.0");
address1.Assign (devices12);
address2.Assign (devices23);
Ipv4InterfaceContainer interfaces = address3.Assign (devices34);
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (nodes34.Get (1));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (nodes12.Get (0));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}

458
examples/nms-p2p-nix.cc Normal file
View File

@@ -0,0 +1,458 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
// DARPA NMS Campus Network Model
//
// - This topology replicates the original NMS Campus Network model
// with the exception of chord links (which were never utilized in the
// original model)
// - Link Bandwidths and Delays may not be the same as the original
// specifications
//
// (c)2009, GTech Systems, Inc. - Alfred Park <park@gtech-systems.com>
// for timing functions
#include <cstdlib>
#include <sys/time.h>
#include <fstream>
#include "ns3/core-module.h"
#include "ns3/simulator-module.h"
#include "ns3/node-module.h"
#include "ns3/helper-module.h"
#include "ns3/global-routing-module.h"
#include "ns3/onoff-application.h"
#include "ns3/packet-sink.h"
#include "ns3/point-to-point-net-device.h"
#include "ns3/simulator.h"
using namespace std;
using namespace ns3;
typedef struct timeval TIMER_TYPE;
#define TIMER_NOW(_t) gettimeofday(&_t,NULL);
#define TIMER_SECONDS(_t) ((double)(_t).tv_sec + (_t).tv_usec*1e-6)
#define TIMER_DIFF(_t1, _t2) (TIMER_SECONDS(_t1)-TIMER_SECONDS(_t2))
NS_LOG_COMPONENT_DEFINE ("CampusNetworkModel");
void Progress ()
{
Time now = Simulator::Now ();
Simulator::Schedule (Seconds (0.1), Progress);
}
int
main (int argc, char *argv[])
{
//Config::SetDefault ("ns3::Simulator::SchedulerType", StringValue ("ns3::CalendarScheduler"));
TIMER_TYPE t0, t1, t2;
TIMER_NOW(t0);
cout << " ==== DARPA NMS CAMPUS NETWORK SIMULATION ====" << endl;
LogComponentEnable ("OnOffApplication", LOG_LEVEL_INFO);
//RandomVariable::UseGlobalSeed (1, 1, 2, 3, 5, 8);
int nCN = 2, nLANClients = 42;
bool nix = true;
CommandLine cmd;
cmd.AddValue ("CN", "Number of total CNs [2]", nCN);
cmd.AddValue ("LAN", "Number of nodes per LAN [42]", nLANClients);
cmd.AddValue ("NIX", "Toggle nix-vector routing", nix);
cmd.Parse (argc,argv);
if (nCN < 2)
{
cout << "Number of total CNs (" << nCN << ") lower than minimum of 2"
<< endl;
return 1;
}
cout << "Number of CNs: " << nCN << ", LAN nodes: " << nLANClients << endl;
NodeContainer nodes_net0[nCN][3], nodes_net1[nCN][6], nodes_netLR[nCN],
nodes_net2[nCN][14], nodes_net2LAN[nCN][7][nLANClients],
nodes_net3[nCN][9], nodes_net3LAN[nCN][5][nLANClients];
PointToPointHelper p2p_2gb200ms, p2p_1gb5ms, p2p_100mb1ms;
InternetStackHelper stack;
Ipv4InterfaceContainer ifs, ifs0[nCN][3], ifs1[nCN][6], ifs2[nCN][14],
ifs3[nCN][9], ifs2LAN[nCN][7][nLANClients],
ifs3LAN[nCN][5][nLANClients];
Ipv4AddressHelper address;
std::ostringstream oss;
p2p_1gb5ms.SetDeviceAttribute ("DataRate", StringValue ("1Gbps"));
p2p_1gb5ms.SetChannelAttribute ("Delay", StringValue ("5ms"));
p2p_2gb200ms.SetDeviceAttribute ("DataRate", StringValue ("2Gbps"));
p2p_2gb200ms.SetChannelAttribute ("Delay", StringValue ("200ms"));
p2p_100mb1ms.SetDeviceAttribute ("DataRate", StringValue ("100Mbps"));
p2p_100mb1ms.SetChannelAttribute ("Delay", StringValue ("1ms"));
// Setup NixVector Routing
Ipv4NixVectorHelper nixRouting;
Ipv4StaticRoutingHelper staticRouting;
Ipv4ListRoutingHelper list;
list.Add (staticRouting, 0);
list.Add (nixRouting, 10);
if (nix)
{
stack.SetRoutingHelper (list);
}
// Create Campus Networks
for (int z = 0; z < nCN; ++z)
{
cout << "Creating Campus Network " << z << ":" << endl;
// Create Net0
cout << " SubNet [ 0";
for (int i = 0; i < 3; ++i)
{
nodes_net0[z][i].Create (1);
stack.Install (nodes_net0[z][i]);
}
nodes_net0[z][0].Add (nodes_net0[z][1].Get (0));
nodes_net0[z][1].Add (nodes_net0[z][2].Get (0));
nodes_net0[z][2].Add (nodes_net0[z][0].Get (0));
NetDeviceContainer ndc0[3];
for (int i = 0; i < 3; ++i)
{
ndc0[i] = p2p_1gb5ms.Install (nodes_net0[z][i]);
}
// Create Net1
cout << " 1";
for (int i = 0; i < 6; ++i)
{
nodes_net1[z][i].Create (1);
stack.Install (nodes_net1[z][i]);
}
nodes_net1[z][0].Add (nodes_net1[z][1].Get (0));
nodes_net1[z][2].Add (nodes_net1[z][0].Get (0));
nodes_net1[z][3].Add (nodes_net1[z][0].Get (0));
nodes_net1[z][4].Add (nodes_net1[z][1].Get (0));
nodes_net1[z][5].Add (nodes_net1[z][1].Get (0));
NetDeviceContainer ndc1[6];
for (int i = 0; i < 6; ++i)
{
if (i == 1)
{
continue;
}
ndc1[i] = p2p_1gb5ms.Install (nodes_net1[z][i]);
}
// Connect Net0 <-> Net1
NodeContainer net0_1;
net0_1.Add (nodes_net0[z][2].Get (0));
net0_1.Add (nodes_net1[z][0].Get (0));
NetDeviceContainer ndc0_1;
ndc0_1 = p2p_1gb5ms.Install (net0_1);
oss.str("");
oss << 10 + z << ".1.252.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc0_1);
// Create Net2
cout << " 2";
for (int i = 0; i < 14; ++i)
{
nodes_net2[z][i].Create (1);
stack.Install (nodes_net2[z][i]);
}
nodes_net2[z][0].Add (nodes_net2[z][1].Get (0));
nodes_net2[z][2].Add (nodes_net2[z][0].Get (0));
nodes_net2[z][1].Add (nodes_net2[z][3].Get (0));
nodes_net2[z][3].Add (nodes_net2[z][2].Get (0));
nodes_net2[z][4].Add (nodes_net2[z][2].Get (0));
nodes_net2[z][5].Add (nodes_net2[z][3].Get (0));
nodes_net2[z][6].Add (nodes_net2[z][5].Get (0));
nodes_net2[z][7].Add (nodes_net2[z][2].Get (0));
nodes_net2[z][8].Add (nodes_net2[z][3].Get (0));
nodes_net2[z][9].Add (nodes_net2[z][4].Get (0));
nodes_net2[z][10].Add (nodes_net2[z][5].Get (0));
nodes_net2[z][11].Add (nodes_net2[z][6].Get (0));
nodes_net2[z][12].Add (nodes_net2[z][6].Get (0));
nodes_net2[z][13].Add (nodes_net2[z][6].Get (0));
NetDeviceContainer ndc2[14];
for (int i = 0; i < 14; ++i)
{
ndc2[i] = p2p_1gb5ms.Install (nodes_net2[z][i]);
}
NetDeviceContainer ndc2LAN[7][nLANClients];
for (int i = 0; i < 7; ++i)
{
oss.str ("");
oss << 10 + z << ".4." << 15 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
for (int j = 0; j < nLANClients; ++j)
{
nodes_net2LAN[z][i][j].Create (1);
stack.Install (nodes_net2LAN[z][i][j]);
nodes_net2LAN[z][i][j].Add (nodes_net2[z][i+7].Get (0));
ndc2LAN[i][j] = p2p_100mb1ms.Install (nodes_net2LAN[z][i][j]);
ifs2LAN[z][i][j] = address.Assign (ndc2LAN[i][j]);
}
}
// Create Net3
cout << " 3 ]" << endl;
for (int i = 0; i < 9; ++i)
{
nodes_net3[z][i].Create (1);
stack.Install(nodes_net3[z][i]);
}
nodes_net3[z][0].Add (nodes_net3[z][1].Get (0));
nodes_net3[z][1].Add (nodes_net3[z][2].Get (0));
nodes_net3[z][2].Add (nodes_net3[z][3].Get (0));
nodes_net3[z][3].Add (nodes_net3[z][1].Get (0));
nodes_net3[z][4].Add (nodes_net3[z][0].Get (0));
nodes_net3[z][5].Add (nodes_net3[z][0].Get (0));
nodes_net3[z][6].Add (nodes_net3[z][2].Get (0));
nodes_net3[z][7].Add (nodes_net3[z][3].Get (0));
nodes_net3[z][8].Add (nodes_net3[z][3].Get (0));
NetDeviceContainer ndc3[9];
for (int i = 0; i < 9; ++i)
{
ndc3[i] = p2p_1gb5ms.Install (nodes_net3[z][i]);
}
NetDeviceContainer ndc3LAN[5][nLANClients];
for (int i = 0; i < 5; ++i)
{
oss.str ("");
oss << 10 + z << ".5." << 10 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.255");
for (int j = 0; j < nLANClients; ++j)
{
nodes_net3LAN[z][i][j].Create (1);
stack.Install (nodes_net3LAN[z][i][j]);
nodes_net3LAN[z][i][j].Add (nodes_net3[z][i+4].Get (0));
ndc3LAN[i][j] = p2p_100mb1ms.Install (nodes_net3LAN[z][i][j]);
ifs3LAN[z][i][j] = address.Assign (ndc3LAN[i][j]);
}
}
cout << " Connecting Subnets..." << endl;
// Create Lone Routers (Node 4 & 5)
nodes_netLR[z].Create (2);
stack.Install (nodes_netLR[z]);
NetDeviceContainer ndcLR;
ndcLR = p2p_1gb5ms.Install (nodes_netLR[z]);
// Connect Net2/Net3 through Lone Routers to Net0
NodeContainer net0_4, net0_5, net2_4a, net2_4b, net3_5a, net3_5b;
net0_4.Add (nodes_netLR[z].Get (0));
net0_4.Add (nodes_net0[z][0].Get (0));
net0_5.Add (nodes_netLR[z].Get (1));
net0_5.Add (nodes_net0[z][1].Get (0));
net2_4a.Add (nodes_netLR[z].Get (0));
net2_4a.Add (nodes_net2[z][0].Get (0));
net2_4b.Add (nodes_netLR[z].Get (1));
net2_4b.Add (nodes_net2[z][1].Get (0));
net3_5a.Add (nodes_netLR[z].Get (1));
net3_5a.Add (nodes_net3[z][0].Get (0));
net3_5b.Add (nodes_netLR[z].Get (1));
net3_5b.Add (nodes_net3[z][1].Get (0));
NetDeviceContainer ndc0_4, ndc0_5, ndc2_4a, ndc2_4b, ndc3_5a, ndc3_5b;
ndc0_4 = p2p_1gb5ms.Install (net0_4);
oss.str ("");
oss << 10 + z << ".1.253.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc0_4);
ndc0_5 = p2p_1gb5ms.Install (net0_5);
oss.str ("");
oss << 10 + z << ".1.254.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc0_5);
ndc2_4a = p2p_1gb5ms.Install (net2_4a);
oss.str ("");
oss << 10 + z << ".4.253.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc2_4a);
ndc2_4b = p2p_1gb5ms.Install (net2_4b);
oss.str ("");
oss << 10 + z << ".4.254.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc2_4b);
ndc3_5a = p2p_1gb5ms.Install (net3_5a);
oss.str ("");
oss << 10 + z << ".5.253.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc3_5a);
ndc3_5b = p2p_1gb5ms.Install (net3_5b);
oss.str ("");
oss << 10 + z << ".5.254.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc3_5b);
// Assign IP addresses
cout << " Assigning IP addresses..." << endl;
for (int i = 0; i < 3; ++i)
{
oss.str ("");
oss << 10 + z << ".1." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs0[z][i] = address.Assign (ndc0[i]);
}
for (int i = 0; i < 6; ++i)
{
if (i == 1)
{
continue;
}
oss.str ("");
oss << 10 + z << ".2." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs1[z][i] = address.Assign (ndc1[i]);
}
oss.str ("");
oss << 10 + z << ".3.1.0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndcLR);
for (int i = 0; i < 14; ++i)
{
oss.str ("");
oss << 10 + z << ".4." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs2[z][i] = address.Assign (ndc2[i]);
}
for (int i = 0; i < 9; ++i)
{
oss.str ("");
oss << 10 + z << ".5." << 1 + i << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs3[z][i] = address.Assign (ndc3[i]);
}
}
// Create Ring Links
if (nCN > 1)
{
cout << "Forming Ring Topology..." << endl;
NodeContainer nodes_ring[nCN];
for (int z = 0; z < nCN-1; ++z)
{
nodes_ring[z].Add (nodes_net0[z][0].Get (0));
nodes_ring[z].Add (nodes_net0[z+1][0].Get (0));
}
nodes_ring[nCN-1].Add (nodes_net0[nCN-1][0].Get (0));
nodes_ring[nCN-1].Add (nodes_net0[0][0].Get (0));
NetDeviceContainer ndc_ring[nCN];
for (int z = 0; z < nCN; ++z)
{
ndc_ring[z] = p2p_2gb200ms.Install (nodes_ring[z]);
oss.str ("");
oss << "254.1." << z + 1 << ".0";
address.SetBase (oss.str ().c_str (), "255.255.255.0");
ifs = address.Assign (ndc_ring[z]);
}
}
// Create Traffic Flows
cout << "Creating TCP Traffic Flows:" << endl;
Config::SetDefault ("ns3::OnOffApplication::MaxBytes", UintegerValue (500000));
Config::SetDefault ("ns3::OnOffApplication::OnTime",
RandomVariableValue (ConstantVariable (1)));
Config::SetDefault ("ns3::OnOffApplication::OffTime",
RandomVariableValue (ConstantVariable (0)));
Config::SetDefault ("ns3::TcpSocket::SegmentSize", UintegerValue (512));
UniformVariable urng;
int r1;
double r2;
for (int z = 0; z < nCN; ++z)
{
int x = z + 1;
if (z == nCN - 1)
{
x = 0;
}
// Subnet 2 LANs
cout << " Campus Network " << z << " Flows [ Net2 ";
for (int i = 0; i < 7; ++i)
{
for (int j = 0; j < nLANClients; ++j)
{
// Sinks
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), 9999));
ApplicationContainer sinkApp = sinkHelper.Install (
nodes_net2LAN[z][i][j].Get (0));
sinkApp.Start (Seconds (100.0));
// Sources
r1 = 2 + (int)(4 * urng.GetValue ());
r2 = 100 + (10 * urng.GetValue ());;
OnOffHelper client ("ns3::TcpSocketFactory", Address ());
AddressValue remoteAddress(InetSocketAddress (
ifs2LAN[z][i][j].GetAddress (0), 9999));
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
clientApp.Start (Seconds (r2));
}
}
// Subnet 3 LANs
cout << "Net3 ]" << endl;
for (int i = 0; i < 5; ++i)
{
for (int j = 0; j < nLANClients; ++j)
{
// Sinks
PacketSinkHelper sinkHelper ("ns3::TcpSocketFactory",
InetSocketAddress (Ipv4Address::GetAny (), 9999));
ApplicationContainer sinkApp = sinkHelper.Install (
nodes_net3LAN[z][i][j].Get (0));
sinkApp.Start (Seconds (100.0));
// Sources
r1 = 2 + (int)(4 * urng.GetValue ());
r2 = 100 + (10 * urng.GetValue ());;
OnOffHelper client ("ns3::TcpSocketFactory", Address ());
AddressValue remoteAddress (InetSocketAddress (
ifs2LAN[z][i][j].GetAddress (0), 9999));
client.SetAttribute ("Remote", remoteAddress);
ApplicationContainer clientApp;
clientApp.Add (client.Install (nodes_net1[x][r1].Get (0)));
clientApp.Start (Seconds (r2));
}
}
}
cout << "Created " << NodeList::GetNNodes () << " nodes." << endl;
TIMER_TYPE routingStart;
TIMER_NOW (routingStart);
if (nix)
{
// Calculate routing tables
cout << "Using Nix-vectors..." << endl;
}
else
{
// Calculate routing tables
cout << "Populating Global Static Routing Tables..." << endl;
Ipv4GlobalRoutingHelper::PopulateRoutingTables ();
}
TIMER_TYPE routingEnd;
TIMER_NOW (routingEnd);
cout << "Routing tables population took "
<< TIMER_DIFF (routingEnd, routingStart) << endl;
#if 0
std::ofstream ascii;
ascii.open("nms_p2p_nix.tr");
PointToPointHelper::EnableAsciiAll(ascii);
CsmaHelper::EnableAsciiAll(ascii);
#endif
#if 0
PointToPointHelper::EnablePcapAll("nms_p2p");
CsmaHelper::EnablePcapAll("nms_csma");
#endif
Simulator::ScheduleNow (Progress);
cout << "Running simulator..." << endl;
TIMER_NOW (t1);
Simulator::Stop (Seconds (200.0));
Simulator::Run ();
TIMER_NOW (t2);
cout << "Simulator finished." << endl;
Simulator::Destroy ();
double d1 = TIMER_DIFF (t1, t0), d2 = TIMER_DIFF (t2, t1);
cout << "-----" << endl << "Runtime Stats:" << endl;
cout << "Simulator init time: " << d1 << endl;
cout << "Simulator run time: " << d2 << endl;
cout << "Total elapsed time: " << d1+d2 << endl;
return 0;
}

View File

@@ -96,6 +96,14 @@ def build(bld):
['point-to-point', 'internet-stack', 'olsr'])
obj.source = 'simple-point-to-point-olsr.cc'
obj = bld.create_ns3_program('nix-simple',
['point-to-point', 'internet-stack', 'nix-vector-routing'])
obj.source = 'nix-simple.cc'
obj = bld.create_ns3_program('nms-p2p-nix',
['point-to-point', 'internet-stack', 'nix-vector-routing'])
obj.source = 'nms-p2p-nix.cc'
obj = bld.create_ns3_program('tcp-large-transfer',
['point-to-point', 'internet-stack'])
obj.source = 'tcp-large-transfer.cc'

419
src/common/nix-vector.cc Normal file
View File

@@ -0,0 +1,419 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 The Georgia Institute of Technology
*
* 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
*
* Authors: Josh Pelkey <jpelkey@gatech.edu>
*/
#include "ns3/log.h"
#include "nix-vector.h"
NS_LOG_COMPONENT_DEFINE ("NixVector");
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (NixVector);
typedef std::vector<uint32_t> NixBits_t;
NixVector::NixVector ()
: m_nixVector (0),
m_used (0),
m_currentVectorBitSize (0),
m_totalBitSize (0)
{
NS_LOG_FUNCTION_NOARGS ();
m_nixVector.push_back (0);
}
NixVector::~NixVector ()
{
NS_LOG_FUNCTION_NOARGS ();
}
Ptr<NixVector>
NixVector::Copy (void) const
{
// we need to invoke the copy constructor directly
// rather than calling Create because the copy constructor
// is private.
return Ptr<NixVector> (new NixVector (*this), false);
}
NixVector::NixVector (const NixVector &o)
: m_nixVector (o.m_nixVector),
m_used (o.m_used),
m_currentVectorBitSize (o.m_currentVectorBitSize),
m_totalBitSize (o.m_totalBitSize)
{}
NixVector &
NixVector::operator = (const NixVector &o)
{
if (this == &o)
{
return *this;
}
m_nixVector = o.m_nixVector;
m_used = o.m_used;
m_currentVectorBitSize = o.m_currentVectorBitSize;
m_totalBitSize = o.m_totalBitSize;
return *this;
}
TypeId
NixVector::GetTypeId(void)
{
static TypeId tid = TypeId ("ns3::NixVector")
.SetParent<Object> ()
.AddConstructor<NixVector> ()
;
return tid;
}
std::ostream & operator << (std::ostream &os, const NixVector &nix)
{
nix.DumpNixVector (os);
return os;
}
void
NixVector::AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits)
{
NS_LOG_FUNCTION_NOARGS ();
if (numberOfBits > 32)
{
NS_FATAL_ERROR ("Can't add more than 32 bits to a nix-vector at one time");
}
// Check to see if the number
// of new bits forces the creation of
// a new entry into the NixVector vector
// i.e., we will overflow int o.w.
if (m_currentVectorBitSize + numberOfBits > 32)
{
if (m_currentVectorBitSize == 32)
{
// can't add any more to this vector, so
// start a new one
m_nixVector.push_back(newBits);
// also reset number of bits in
// m_currentVectorBitSize
// because we are working with a new
// entry in the vector
m_currentVectorBitSize = numberOfBits;
m_totalBitSize += numberOfBits;
}
else
{
// Put what we can in the remaining portion of the
// vector entry
uint32_t tempBits = newBits;
tempBits = newBits << m_currentVectorBitSize;
tempBits |= m_nixVector.back ();
m_nixVector.back () = tempBits;
// Now start a new vector entry
// and push the remaining bits
// there
newBits = newBits >> (32 - m_currentVectorBitSize);
m_nixVector.push_back (newBits);
// also reset number of bits in
// m_currentVectorBitSize
// because we are working with a new
// entry in the vector
m_currentVectorBitSize = (numberOfBits - (32 - m_currentVectorBitSize));
m_totalBitSize += numberOfBits;
}
}
else
{
// Shift over the newbits by the
// number of current bits. This allows
// us to logically OR with the present
// NixVector, resulting in the new
// NixVector
newBits = newBits << m_currentVectorBitSize;
newBits |= m_nixVector.back ();
// Now insert the new NixVector and
// increment number of bits for
// m_currentVectorBitSize and m_totalBitSize
// accordingly
m_nixVector.back () = newBits;
m_currentVectorBitSize += numberOfBits;
m_totalBitSize += numberOfBits;
}
}
uint32_t
NixVector::ExtractNeighborIndex (uint32_t numberOfBits)
{
NS_LOG_FUNCTION_NOARGS ();
if (numberOfBits > 32)
{
NS_FATAL_ERROR ("Can't extract more than 32 bits to a nix-vector at one time");
}
uint32_t vectorIndex = 0;
uint32_t extractedBits = 0;
uint32_t totalRemainingBits = GetRemainingBits ();
if (numberOfBits > totalRemainingBits)
{
NS_FATAL_ERROR ("You've tried to extract too many bits of the Nix-vector, " << this << ". NumberBits: "
<< numberOfBits << " Remaining: " << totalRemainingBits);
}
if (numberOfBits <= 0)
{
NS_FATAL_ERROR ("You've specified a number of bits for Nix-vector <= 0!");
}
// First determine where in the NixVector
// vector we need to extract which depends
// on the number of used bits and the total
// number of bits
vectorIndex = ((totalRemainingBits-1) / 32);
// Next, determine if this extraction will
// span multiple vector entries
if (vectorIndex > 0) // we could span more than one
{
if ((numberOfBits-1) > ((totalRemainingBits-1) % 32)) // we do span more than one
{
extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
extractedBits = extractedBits >> ((32 - (totalRemainingBits % 32))
- (numberOfBits - (totalRemainingBits % 32)));
extractedBits |= (m_nixVector.at (vectorIndex-1)
>> (32 - (numberOfBits - (totalRemainingBits % 32))));
m_used += numberOfBits;
return extractedBits;
}
}
// we don't span more than one
extractedBits = m_nixVector.at (vectorIndex) << (32 - (totalRemainingBits % 32));
extractedBits = extractedBits >> (32 - (numberOfBits));
m_used += numberOfBits;
return extractedBits;
}
uint32_t
NixVector::GetSerializedSize (void) const
{
uint32_t totalSizeInBytes;
totalSizeInBytes = sizeof (m_used) + sizeof (m_currentVectorBitSize) +
sizeof (m_totalBitSize) + (4 * m_nixVector.size ());
// add four to this to account
// for the nix-vector length
// entry
return totalSizeInBytes+4;
}
void
NixVector::Serialize (Buffer::Iterator i, uint32_t size) const
{
uint32_t bytesWritten = 0;
i.WriteU32 (size);
bytesWritten += 4;
i.WriteU32 (m_used);
bytesWritten += 4;
i.WriteU32 (m_currentVectorBitSize);
bytesWritten += 4;
i.WriteU32 (m_totalBitSize);
bytesWritten += 4;
for (uint32_t j = 0; j < m_nixVector.size (); j++)
{
i.WriteU32 (m_nixVector.at(j));
bytesWritten += 4;
}
NS_ASSERT (bytesWritten == size);
}
uint32_t
NixVector::Deserialize (Buffer::Iterator i)
{
NS_LOG_FUNCTION (this);
uint32_t totalSize = i.ReadU32 ();
uint32_t size = totalSize;
size -= 4;
NS_ASSERT (size >= 4);
m_used = i.ReadU32 ();
size -=4;
NS_ASSERT (size >= 4);
m_currentVectorBitSize = i.ReadU32 ();
size -=4;
NS_ASSERT (size >= 4);
m_totalBitSize = i.ReadU32 ();
size -=4;
// make sure the nix-vector
// is empty
m_nixVector.clear ();
while (size > 0)
{
NS_ASSERT (size >= 4);
m_nixVector.push_back (i.ReadU32 ());
size -=4;
}
NS_ASSERT (size == 0);
return totalSize;
}
void
NixVector::DumpNixVector (std::ostream &os) const
{
NS_LOG_FUNCTION_NOARGS ();
uint32_t i = m_nixVector.size ();
std::vector<uint32_t>::const_reverse_iterator rIter;
for (rIter = m_nixVector.rbegin (); rIter != m_nixVector.rend (); rIter++)
{
uint32_t numBits = BitCount (*rIter);
// all this work just to get the nix
// vector to print out neat
// if it's not the first entry in the vector,
// we may have to add some zeros and fill
// out the vector
if (m_totalBitSize > ((sizeof (uint32_t)*8) * i))
{
PrintDec2BinNixFill (*rIter,numBits,os);
}
else if (m_totalBitSize%32 == 0)
{
PrintDec2BinNix (*rIter,32,os);
}
else
{
PrintDec2BinNix (*rIter,m_totalBitSize%32,os);
}
i--;
if (i > 0)
{
os << "--";
}
}
}
uint32_t
NixVector::GetRemainingBits (void)
{
NS_LOG_FUNCTION_NOARGS ();
return (m_totalBitSize - m_used);
}
uint32_t
NixVector::BitCount (uint32_t numberOfNeighbors) const
{
NS_LOG_FUNCTION_NOARGS ();
// Given the numberOfNeighbors, return the number
// of bits needed (essentially, log2(numberOfNeighbors-1)
uint32_t bitCount = 0;
if (numberOfNeighbors < 2)
{
return 1;
}
else
{
for (numberOfNeighbors -= 1; numberOfNeighbors != 0; numberOfNeighbors >>= 1)
{
bitCount++;
}
return bitCount;
}
}
void
NixVector::PrintDec2BinNix (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
{
if(decimalNum == 0)
{
for (; bitCount > 0; bitCount--)
{
os << 0;
}
return;
}
if(decimalNum == 1)
{
for (; bitCount > 1; bitCount--)
{
os << 0;
}
os << 1;
}
else
{
PrintDec2BinNix (decimalNum / 2,bitCount-1, os);
os << decimalNum % 2;
}
}
void
NixVector::PrintDec2BinNixFill (uint32_t decimalNum, uint32_t bitCount, std::ostream &os) const
{
if(decimalNum == 0)
{
os << 0;
return;
}
if(decimalNum == 1)
{
// check to see if we need to
// print out some zeros at the
// beginning of the nix vector
if ((uint32_t)(sizeof (uint32_t)*8) > bitCount)
{
for (uint32_t i = ((sizeof (uint32_t)*8)-bitCount); i > 0; i--)
{
os << 0;
}
}
os << 1;
}
else
{
PrintDec2BinNixFill (decimalNum / 2, bitCount, os);
os << decimalNum % 2;
}
}
} // namespace ns3

166
src/common/nix-vector.h Normal file
View File

@@ -0,0 +1,166 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 The Georgia Institute of Technology
*
* 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
*
* Authors: Josh Pelkey <jpelkey@gatech.edu>
*/
#ifndef __NIX_VECTOR_H__
#define __NIX_VECTOR_H__
#include "ns3/object.h"
#include "ns3/buffer.h"
namespace ns3 {
/**
* \ingroup packet
*
* \brief Neighbor-index data structure for nix-vector routing
*
* This data structure holds a vector of "neighbor-indexes" for
* a simulation specific routing protocol, nix-vector routing.
* Theses neighbor-indexes correspond to the net-device which a
* node should use to route a packet. A nix-vector is built
* (or fetched from a cache) on-demand. The nix-vector is
* transmitted with the packet, and along each hop of the
* route, the current node extracts the appropriate
* neighbor-index and routes the packet.
*
* \internal
* The implementation of NixVector uses a vector to store
* the neighbor-indexes. Each entry in the vector is 32
* bits long and can store multiple neighbor-indexes. A
* fair amount of bit manipulation is used to store these
* neighbor-indexes efficiently. A vector is used so that
* the nix-vector can grow arbitraily if the topoplogy and
* route requires a large number of neighbor-indexes.
*
* As the nix-vector travels along the route, an internal
* private member variable keeps track of how many bits
* have been used. At a particular node, the nix-vector
* is used to return the next neighbor-index. This
* neighbor-index is used to determine which net-device
* to use. The number of bits used would then be
* incremented accordingly, and the packet would be
* routed.
*/
class NixVector : public Object
{
public:
NixVector ();
NixVector (const NixVector &o);
~NixVector ();
Ptr<NixVector> Copy (void) const;
NixVector &operator = (const NixVector &o);
static TypeId GetTypeId (void);
/**
* \param newBits the neighbor-index to be added to the vector
* \param numberOfBits the number of bits that newBits contains
*
* Adds the neighbor index to the vector using a fair amount of
* bit manipulation to pack everything in efficiently.
*
* Note: This function assumes that the number of bits to be added
* is always less than or equal to 32, ie., you can only span one
* entry of a nix-vector at a time. This is reasonable, since 32
* bits gives you 2^32 possible neighbors.
*/
void AddNeighborIndex (uint32_t newBits, uint32_t numberOfBits);
/**
* \return the neighbor index
*
* \param numberOfBits the number of bits to extract from the vector
*
* Extracts the number of bits specified from
* the vector and returns the value extracted
*
* Note: This function assumes that the number of bits to be extracted
* is always less than or equal to 32, ie., you can only span one
* entry of a nix-vector at a time. This is reasonable, since 32
* bits gives you 2^32 possible neighbors.
*/
uint32_t ExtractNeighborIndex (uint32_t numberOfBits);
/**
* \return number of bits remaining in the
* nix-vector (ie m_total - m_used)
*/
uint32_t GetRemainingBits (void);
/**
* \return the number of bytes required for serialization
*/
uint32_t GetSerializedSize (void) const;
/**
* \param i Buffer iterator for writing
*
* \param size number of bytes to write
*/
void Serialize (Buffer::Iterator i, uint32_t size) const;
/**
* \return the number of bytes deserialized
*
* \param i Buffer iterator for reading
*/
uint32_t Deserialize (Buffer::Iterator i);
/**
* \return number of bits of numberOfNeighbors
*
* \param numberOfNeighbors the total number of neighbors
*
* This function is used to determine the number of bits of
* numberOfNeighbors so that this value can be passed in to
* AddNeighborIndex or ExtractNeighborIndex.
*/
uint32_t BitCount (uint32_t numberOfNeighbors) const;
/* for printing of nix-vector */
void DumpNixVector (std::ostream &os) const;
/* for printing of nix-vector */
friend std::ostream & operator <<( std::ostream &outs, const NixVector &nix);
private:
typedef std::vector<uint32_t> NixBits_t;
/* the actual nix-vector */
NixBits_t m_nixVector;
/* for tracking where we are
* in the nix-vector
*/
uint32_t m_used;
/* for tracking how many bits we
* have used in the current vector
* entry. need this in order to
* expand the vector passed 32bits
*/
uint32_t m_currentVectorBitSize;
/* a counter of how total bits are in
* the nix-vector
*/
uint32_t m_totalBitSize;
/* internal for pretty printing of nix-vector */
void PrintDec2BinNixFill (uint32_t, uint32_t, std::ostream &os) const;
/* internal for pretty printing of nix-vector */
void PrintDec2BinNix (uint32_t, uint32_t, std::ostream &os) const;
};
} // namespace ns3
#endif

View File

@@ -138,6 +138,7 @@ Packet::Packet ()
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, 0),
m_nixVector (0),
m_refCount (1)
{
m_globalUid++;
@@ -149,7 +150,10 @@ Packet::Packet (const Packet &o)
m_packetTagList (o.m_packetTagList),
m_metadata (o.m_metadata),
m_refCount (1)
{}
{
o.m_nixVector ? m_nixVector = o.m_nixVector->Copy ()
: m_nixVector = 0;
}
Packet &
Packet::operator = (const Packet &o)
@@ -162,6 +166,8 @@ Packet::operator = (const Packet &o)
m_byteTagList = o.m_byteTagList;
m_packetTagList = o.m_packetTagList;
m_metadata = o.m_metadata;
o.m_nixVector ? m_nixVector = o.m_nixVector->Copy ()
: m_nixVector = 0;
return *this;
}
@@ -170,6 +176,7 @@ Packet::Packet (uint32_t size)
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, size),
m_nixVector (0),
m_refCount (1)
{
m_globalUid++;
@@ -179,6 +186,7 @@ Packet::Packet (uint8_t const*buffer, uint32_t size)
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, size),
m_nixVector (0),
m_refCount (1)
{
m_globalUid++;
@@ -193,6 +201,7 @@ Packet::Packet (const Buffer &buffer, const ByteTagList &byteTagList,
m_byteTagList (byteTagList),
m_packetTagList (packetTagList),
m_metadata (metadata),
m_nixVector (0),
m_refCount (1)
{}
@@ -209,6 +218,18 @@ Packet::CreateFragment (uint32_t start, uint32_t length) const
return Ptr<Packet> (new Packet (buffer, m_byteTagList, m_packetTagList, metadata), false);
}
void
Packet::SetNixVector (Ptr<NixVector> nixVector)
{
m_nixVector = nixVector;
}
Ptr<NixVector>
Packet::GetNixVector (void) const
{
return m_nixVector;
}
uint32_t
Packet::GetSize (void) const
{
@@ -677,7 +698,6 @@ Packet::GetPacketTagIterator (void) const
return PacketTagIterator (m_packetTagList.Head ());
}
std::ostream& operator<< (std::ostream& os, const Packet &packet)
{
packet.Print (os);

View File

@@ -28,6 +28,7 @@
#include "tag.h"
#include "byte-tag-list.h"
#include "packet-tag-list.h"
#include "nix-vector.h"
#include "ns3/callback.h"
#include "ns3/assert.h"
#include "ns3/ptr.h"
@@ -520,6 +521,15 @@ public:
*/
PacketTagIterator GetPacketTagIterator (void) const;
/* Note: These function support a temporary solution
* to a specific problem in this generic class, i.e.
* how to associate something specific like nix-vector
* with a packet. This design methodology
* should _not_ be followed, and is only here as an
* impetus to fix this general issue. */
void SetNixVector (Ptr<NixVector>);
Ptr<NixVector> GetNixVector (void) const;
private:
Packet (const Buffer &buffer, const ByteTagList &byteTagList,
const PacketTagList &packetTagList, const PacketMetadata &metadata);
@@ -527,6 +537,10 @@ private:
ByteTagList m_byteTagList;
PacketTagList m_packetTagList;
PacketMetadata m_metadata;
/* Please see comments above about nix-vector */
Ptr<NixVector> m_nixVector;
mutable uint32_t m_refCount;
static uint32_t m_globalUid;
};

View File

@@ -17,6 +17,7 @@ def build(bld):
'byte-tag-list.cc',
'tag-buffer.cc',
'packet-tag-list.cc',
'nix-vector.cc',
'ascii-writer.cc',
'pcap-file.cc',
'pcap-file-test-suite.cc',
@@ -38,6 +39,7 @@ def build(bld):
'byte-tag-list.h',
'tag-buffer.h',
'packet-tag-list.h',
'nix-vector.h',
'ascii-writer.h',
'sgi-hashmap.h',
'pcap-file.h',

View File

@@ -0,0 +1,39 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 The Georgia Institute of Technology
*
* 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
*
* Authors: Josh Pelkey <jpelkey@gatech.edu>
*/
#include "ipv4-nix-vector-helper.h"
#include "ns3/ipv4-nix-vector-routing.h"
namespace ns3 {
Ipv4NixVectorHelper::Ipv4NixVectorHelper ()
{
m_agentFactory.SetTypeId ("ns3::Ipv4NixVectorRouting");
}
Ptr<Ipv4RoutingProtocol>
Ipv4NixVectorHelper::Create (Ptr<Node> node) const
{
Ptr<Ipv4NixVectorRouting> agent = m_agentFactory.Create<Ipv4NixVectorRouting> ();
agent->SetNode(node);
node->AggregateObject (agent);
return agent;
}
} // namespace ns3

View File

@@ -0,0 +1,55 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 The Georgia Institute of Technology
*
* 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
*
* Authors: Josh Pelkey <jpelkey@gatech.edu>
*/
#ifndef IPV4_NIX_VECTOR_HELPER_H
#define IPV4_NIX_VECTOR_HELPER_H
#include "ns3/object-factory.h"
#include "ns3/ipv4-routing-helper.h"
namespace ns3 {
/**
* \brief Helper class that adds Nix-vector routing to nodes.
*
* This class is expected to be used in conjunction with
* ns3::InternetStackHelper::SetRoutingHelper
*
*/
class Ipv4NixVectorHelper : public Ipv4RoutingHelper
{
public:
Ipv4NixVectorHelper ();
/**
* \param node the node on which the routing protocol will run
* \returns a newly-created routing protocol
*
* This method will be called by ns3::InternetStackHelper::Install
*/
virtual Ptr<Ipv4RoutingProtocol> Create (Ptr<Node>) const;
private:
ObjectFactory m_agentFactory;
};
} // namespace ns3
#endif /* IPV4_NIX_VECTOR_HELPER_H */

View File

@@ -1,7 +1,7 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'nix-vector-routing', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
helper.source = [
'node-container.cc',
'net-device-container.cc',
@@ -25,6 +25,7 @@ def build(bld):
'v4ping-helper.cc',
'nqos-wifi-mac-helper.cc',
'qos-wifi-mac-helper.cc',
'ipv4-nix-vector-helper.cc',
'ipv4-global-routing-helper.cc',
'ipv4-list-routing-helper.cc',
'ipv4-routing-helper.cc',
@@ -66,6 +67,7 @@ def build(bld):
'v4ping-helper.h',
'nqos-wifi-mac-helper.h',
'qos-wifi-mac-helper.h',
'ipv4-nix-vector-helper.h',
'ipv4-global-routing-helper.h',
'ipv4-list-routing-helper.h',
'ipv4-routing-helper.h',

View File

@@ -0,0 +1,840 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 The Georgia Institute of Technology
*
* 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
*
* Authors: Josh Pelkey <jpelkey@gatech.edu>
*/
#include <queue>
#include "ns3/log.h"
#include "ns3/abort.h"
#include "ns3/ipv4-list-routing.h"
#include "ipv4-nix-vector-routing.h"
NS_LOG_COMPONENT_DEFINE ("Ipv4NixVectorRouting");
namespace ns3 {
NS_OBJECT_ENSURE_REGISTERED (Ipv4NixVectorRouting);
TypeId
Ipv4NixVectorRouting::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::Ipv4NixVectorRouting")
.SetParent<Ipv4RoutingProtocol> ()
.AddConstructor<Ipv4NixVectorRouting> ()
;
return tid;
}
Ipv4NixVectorRouting::Ipv4NixVectorRouting ()
:m_totalNeighbors (0)
{
NS_LOG_FUNCTION_NOARGS ();
}
Ipv4NixVectorRouting::~Ipv4NixVectorRouting ()
{
NS_LOG_FUNCTION_NOARGS ();
}
void
Ipv4NixVectorRouting::SetIpv4 (Ptr<Ipv4> ipv4)
{
NS_ASSERT (ipv4 != 0);
NS_ASSERT (m_ipv4 == 0);
NS_LOG_DEBUG ("Created Ipv4NixVectorProtocol");
m_ipv4 = ipv4;
}
void
Ipv4NixVectorRouting::DoDispose ()
{
NS_LOG_FUNCTION_NOARGS ();
m_node = 0;
m_ipv4 = 0;
Ipv4RoutingProtocol::DoDispose ();
}
void
Ipv4NixVectorRouting::SetNode (Ptr<Node> node)
{
NS_LOG_FUNCTION_NOARGS ();
m_node = node;
}
void
Ipv4NixVectorRouting::FlushGlobalNixRoutingCache ()
{
NS_LOG_FUNCTION_NOARGS ();
NodeList::Iterator listEnd = NodeList::End ();
for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
{
Ptr<Node> node = *i;
Ptr<Ipv4NixVectorRouting> rp = node->GetObject<Ipv4NixVectorRouting> ();
if (!rp)
{
continue;
}
NS_LOG_LOGIC ("Flushing Nix caches.");
rp->FlushNixCache ();
rp->FlushIpv4RouteCache ();
}
}
void
Ipv4NixVectorRouting::FlushNixCache ()
{
NS_LOG_FUNCTION_NOARGS ();
m_nixCache.clear ();
}
void
Ipv4NixVectorRouting::FlushIpv4RouteCache ()
{
NS_LOG_FUNCTION_NOARGS ();
m_ipv4RouteCache.clear ();
}
Ptr<NixVector>
Ipv4NixVectorRouting::GetNixVector (Ptr<Node> source, Ipv4Address dest)
{
NS_LOG_FUNCTION_NOARGS ();
Ptr<NixVector> nixVector = CreateObject<NixVector> ();
// not in cache, must build the nix vector
// First, we have to figure out the nodes
// associated with these IPs
Ptr<Node> destNode = GetNodeByIp (dest);
if (destNode == 0)
{
NS_LOG_ERROR ("No routing path exists");
return 0;
}
// if source == dest, then we have a special case
// because the node is sending to itself. have to
// build the nix vector a little differently
if (source == destNode)
{
BuildNixVectorLocal(nixVector);
return nixVector;
}
else
{
// otherwise proceed as normal
// and build the nix vector
std::vector< Ptr<Node> > parentVector;
BFS (NodeList::GetNNodes (), source, destNode, parentVector);
if (BuildNixVector (parentVector, source->GetId (), destNode->GetId (), nixVector))
{
return nixVector;
}
else
{
NS_LOG_ERROR ("No routing path exists");
return 0;
}
}
}
Ptr<NixVector>
Ipv4NixVectorRouting::GetNixVectorInCache (Ipv4Address address)
{
NS_LOG_FUNCTION_NOARGS ();
NixMap_t::iterator iter = m_nixCache.find (address);
if (iter != m_nixCache.end ())
{
NS_LOG_LOGIC ("Found Nix-vector in cache.");
return iter->second;
}
// not in cache
return 0;
}
Ptr<Ipv4Route>
Ipv4NixVectorRouting::GetIpv4RouteInCache (Ipv4Address address)
{
NS_LOG_FUNCTION_NOARGS ();
Ipv4RouteMap_t::iterator iter = m_ipv4RouteCache.find (address);
if (iter != m_ipv4RouteCache.end ())
{
NS_LOG_LOGIC ("Found Ipv4Route in cache.");
return iter->second;
}
// not in cache
return 0;
}
bool
Ipv4NixVectorRouting::BuildNixVectorLocal (Ptr<NixVector> nixVector)
{
NS_LOG_FUNCTION_NOARGS ();
uint32_t numberOfDevices = m_node->GetNDevices ();
// here we are building a nix vector to
// ourself, so we need to find the loopback
// interface and add that to the nix vector
Ipv4Address loopback ("127.0.0.1");
for (uint32_t i = 0; i < numberOfDevices; i++)
{
uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(i));
Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0);
if (ifAddr.GetLocal() == loopback)
{
NS_LOG_LOGIC ("Adding loopback to nix.");
NS_LOG_LOGIC ("Adding Nix: " << i << " with " << nixVector->BitCount (numberOfDevices)
<< " bits, for node " << m_node->GetId());
nixVector->AddNeighborIndex (i, nixVector->BitCount (numberOfDevices));
return true;
}
}
return false;
}
bool
Ipv4NixVectorRouting::BuildNixVector (const std::vector< Ptr<Node> > & parentVector, uint32_t source, uint32_t dest, Ptr<NixVector> nixVector)
{
NS_LOG_FUNCTION_NOARGS ();
if (source == dest)
{
return true;
}
if (parentVector.at (dest) == 0)
{
return false;
}
Ptr<Node> parentNode = parentVector.at (dest);
uint32_t numberOfDevices = parentNode->GetNDevices ();
uint32_t destId = 0;
uint32_t totalNeighbors = 0;
// scan through the net devices on the parent node
// and then look at the nodes adjacent to them
for (uint32_t i = 0; i < numberOfDevices; i++)
{
// Get a net device from the node
// as well as the channel, and figure
// out the adjacent net devices
Ptr<NetDevice> localNetDevice = parentNode->GetDevice (i);
if (localNetDevice->IsBridge ())
{
continue;
}
Ptr<Channel> channel = localNetDevice->GetChannel ();
if (channel == 0)
{
continue;
}
// this function takes in the local net dev, and channnel, and
// writes to the netDeviceContainer the adjacent net devs
NetDeviceContainer netDeviceContainer;
GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
// Finally we can get the adjacent nodes
// and scan through them. If we find the
// node that matches "dest" then we can add
// the index to the nix vector.
// the index corresponds to the neighbor index
uint32_t offset = 0;
for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin (); iter != netDeviceContainer.End (); iter++)
{
Ptr<Node> remoteNode = (*iter)->GetNode ();
if (remoteNode->GetId () == dest)
{
destId = totalNeighbors + offset;
}
offset += 1;
}
totalNeighbors += netDeviceContainer.GetN ();
}
NS_LOG_LOGIC ("Adding Nix: " << destId << " with "
<< nixVector->BitCount (totalNeighbors) << " bits, for node " << parentNode->GetId());
nixVector->AddNeighborIndex (destId, nixVector->BitCount (totalNeighbors));
// recurse through parent vector, grabbing the path
// and building the nix vector
BuildNixVector (parentVector, source, (parentVector.at (dest))->GetId (), nixVector);
return true;
}
void
Ipv4NixVectorRouting::GetAdjacentNetDevices (Ptr<NetDevice> netDevice, Ptr<Channel> channel, NetDeviceContainer & netDeviceContainer)
{
NS_LOG_FUNCTION_NOARGS ();
for (uint32_t i = 0; i < channel->GetNDevices (); i++)
{
Ptr<NetDevice> remoteDevice = channel->GetDevice (i);
if (remoteDevice != netDevice)
{
Ptr<BridgeNetDevice> bd = NetDeviceIsBridged (remoteDevice);
// we have a bridged device, we need to add all
// bridged devices
if (bd)
{
NS_LOG_LOGIC ("Looking through bridge ports of bridge net device " << bd);
for (uint32_t j = 0; j < bd->GetNBridgePorts (); ++j)
{
Ptr<NetDevice> ndBridged = bd->GetBridgePort (j);
if (ndBridged == remoteDevice)
{
NS_LOG_LOGIC ("That bridge port is me, don't walk backward");
continue;
}
Ptr<Channel> chBridged = ndBridged->GetChannel ();
if (channel == 0)
{
continue;
}
GetAdjacentNetDevices (ndBridged, chBridged, netDeviceContainer);
}
}
else
{
netDeviceContainer.Add (channel->GetDevice (i));
}
}
}
}
Ptr<Node>
Ipv4NixVectorRouting::GetNodeByIp (Ipv4Address dest)
{
NS_LOG_FUNCTION_NOARGS ();
NodeContainer allNodes = NodeContainer::GetGlobal ();
Ptr<Node> destNode;
for (NodeContainer::Iterator i = allNodes.Begin (); i != allNodes.End (); ++i)
{
Ptr<Node> node = *i;
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
if (ipv4->GetInterfaceForAddress (dest) != -1)
{
destNode = node;
break;
}
}
if (!destNode)
{
NS_LOG_ERROR ("Couldn't find dest node given the IP" << dest);
return 0;
}
return destNode;
}
uint32_t
Ipv4NixVectorRouting::FindTotalNeighbors ()
{
uint32_t numberOfDevices = m_node->GetNDevices ();
uint32_t totalNeighbors = 0;
// scan through the net devices on the parent node
// and then look at the nodes adjacent to them
for (uint32_t i = 0; i < numberOfDevices; i++)
{
// Get a net device from the node
// as well as the channel, and figure
// out the adjacent net devices
Ptr<NetDevice> localNetDevice = m_node->GetDevice (i);
Ptr<Channel> channel = localNetDevice->GetChannel ();
if (channel == 0)
{
continue;
}
// this function takes in the local net dev, and channnel, and
// writes to the netDeviceContainer the adjacent net devs
NetDeviceContainer netDeviceContainer;
GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
totalNeighbors += netDeviceContainer.GetN ();
}
return totalNeighbors;
}
Ptr<BridgeNetDevice>
Ipv4NixVectorRouting::NetDeviceIsBridged (Ptr<NetDevice> nd) const
{
NS_LOG_FUNCTION (nd);
Ptr<Node> node = nd->GetNode ();
uint32_t nDevices = node->GetNDevices();
//
// There is no bit on a net device that says it is being bridged, so we have
// to look for bridges on the node to which the device is attached. If we
// find a bridge, we need to look through its bridge ports (the devices it
// bridges) to see if we find the device in question.
//
for (uint32_t i = 0; i < nDevices; ++i)
{
Ptr<NetDevice> ndTest = node->GetDevice(i);
NS_LOG_LOGIC ("Examine device " << i << " " << ndTest);
if (ndTest->IsBridge ())
{
NS_LOG_LOGIC ("device " << i << " is a bridge net device");
Ptr<BridgeNetDevice> bnd = ndTest->GetObject<BridgeNetDevice> ();
NS_ABORT_MSG_UNLESS (bnd, "Ipv4NixVectorRouting::NetDeviceIsBridged (): GetObject for <BridgeNetDevice> failed");
for (uint32_t j = 0; j < bnd->GetNBridgePorts (); ++j)
{
NS_LOG_LOGIC ("Examine bridge port " << j << " " << bnd->GetBridgePort (j));
if (bnd->GetBridgePort (j) == nd)
{
NS_LOG_LOGIC ("Net device " << nd << " is bridged by " << bnd);
return bnd;
}
}
}
}
NS_LOG_LOGIC ("Net device " << nd << " is not bridged");
return 0;
}
uint32_t
Ipv4NixVectorRouting::FindNetDeviceForNixIndex (uint32_t nodeIndex, Ipv4Address & gatewayIp)
{
uint32_t numberOfDevices = m_node->GetNDevices ();
uint32_t index = 0;
uint32_t totalNeighbors = 0;
// scan through the net devices on the parent node
// and then look at the nodes adjacent to them
for (uint32_t i = 0; i < numberOfDevices; i++)
{
// Get a net device from the node
// as well as the channel, and figure
// out the adjacent net devices
Ptr<NetDevice> localNetDevice = m_node->GetDevice (i);
Ptr<Channel> channel = localNetDevice->GetChannel ();
if (channel == 0)
{
continue;
}
// this function takes in the local net dev, and channnel, and
// writes to the netDeviceContainer the adjacent net devs
NetDeviceContainer netDeviceContainer;
GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
// check how many neighbors we have
if (nodeIndex < (totalNeighbors + netDeviceContainer.GetN ()))
{
// found the proper net device
index = i;
Ptr<NetDevice> gatewayDevice = netDeviceContainer.Get (nodeIndex-totalNeighbors);
Ptr<Node> gatewayNode = gatewayDevice->GetNode ();
Ptr<Ipv4> ipv4 = gatewayNode->GetObject<Ipv4> ();
uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice(gatewayDevice);
Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (interfaceIndex, 0);
gatewayIp = ifAddr.GetLocal ();
break;
}
totalNeighbors += netDeviceContainer.GetN ();
}
return index;
}
Ptr<Ipv4Route>
Ipv4NixVectorRouting::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr)
{
NS_LOG_FUNCTION_NOARGS ();
Ptr<Ipv4Route> rtentry;
Ptr<NixVector> nixVectorInCache;
Ptr<NixVector> nixVectorForPacket;
NS_LOG_DEBUG ("Dest IP from header: " << header.GetDestination ());
// check if cache
nixVectorInCache = GetNixVectorInCache(header.GetDestination ());
// not in cache
if (!nixVectorInCache)
{
NS_LOG_LOGIC ("Nix-vector not in cache, build: ");
// Build the nix-vector, given this node and the
// dest IP address
nixVectorInCache = GetNixVector (m_node, header.GetDestination ());
// cache it
m_nixCache.insert (NixMap_t::value_type (header.GetDestination (), nixVectorInCache));
}
// path exists
if (nixVectorInCache)
{
NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache);
// create a new nix vector to be used,
// we want to keep the cached version clean
nixVectorForPacket = CreateObject<NixVector> ();
nixVectorForPacket = nixVectorInCache->Copy();
// Get the interface number that we go out of, by extracting
// from the nix-vector
if (m_totalNeighbors == 0)
{
m_totalNeighbors = FindTotalNeighbors ();
}
// Get the interface number that we go out of, by extracting
// from the nix-vector
uint32_t numberOfBits = nixVectorForPacket->BitCount (m_totalNeighbors);
uint32_t nodeIndex = nixVectorForPacket->ExtractNeighborIndex (numberOfBits);
// Possibly search here in a cache for this node index
// and look for a Ipv4Route. If we have it, don't
// need to do the next 3 lines.
rtentry = GetIpv4RouteInCache (header.GetDestination ());
// not in cache
if (!rtentry)
{
NS_LOG_LOGIC ("Ipv4Route not in cache, build: ");
Ipv4Address gatewayIp;
uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp);
uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index));
Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0);
// start filling in the Ipv4Route info
rtentry = Create<Ipv4Route> ();
rtentry->SetSource (ifAddr.GetLocal ());
rtentry->SetGateway (gatewayIp);
rtentry->SetDestination (header.GetDestination ());
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex));
sockerr = Socket::ERROR_NOTERROR;
// add rtentry to cache
m_ipv4RouteCache.insert(Ipv4RouteMap_t::value_type(header.GetDestination (), rtentry));
}
NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache << " : Remaining bits: " << nixVectorForPacket->GetRemainingBits());
// Add nix-vector in the packet class
// make sure the packet exists first
if (p)
{
NS_LOG_LOGIC ("Adding Nix-vector to packet: " << *nixVectorForPacket);
p->SetNixVector (nixVectorForPacket);
}
}
else // path doesn't exist
{
NS_LOG_ERROR ("No path to the dest: " << header.GetDestination ());
sockerr = Socket::ERROR_NOROUTETOHOST;
}
return rtentry;
}
bool
Ipv4NixVectorRouting::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
LocalDeliverCallback lcb, ErrorCallback ecb)
{
NS_LOG_FUNCTION_NOARGS ();
Ptr<Ipv4Route> rtentry;
// Get the nix-vector from the packet
Ptr<NixVector> nixVector = p->GetNixVector();
// make sure it exists, if not something
// went wrong
if (!nixVector)
{
NS_LOG_ERROR ("Nix-vector wasn't in the packet! Rebuild.");
Ptr<NixVector> nixVectorInCache;
NS_LOG_DEBUG ("Dest IP from header: " << header.GetDestination ());
// check if cache
nixVectorInCache = GetNixVectorInCache(header.GetDestination ());
// not in cache
if (!nixVectorInCache)
{
NS_LOG_LOGIC ("RouteInput(): Nix-vector not in cache, build: ");
// Build the nix-vector, given this node and the
// dest IP address
nixVectorInCache = GetNixVector (m_node, header.GetDestination ());
}
// path exists
if (nixVectorInCache)
{
NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache);
// cache it
m_nixCache.insert(NixMap_t::value_type(header.GetDestination (), nixVectorInCache));
// create a new nix vector to be used,
// we want to keep the cached version clean
Ptr<NixVector> nixVectorForPacket;
nixVectorForPacket = CreateObject<NixVector> ();
nixVectorForPacket = nixVectorInCache->Copy();
// Get the interface number that we go out of, by extracting
// from the nix-vector
if (m_totalNeighbors == 0)
{
m_totalNeighbors = FindTotalNeighbors ();
}
uint32_t numberOfBits = nixVectorForPacket->BitCount (m_totalNeighbors);
uint32_t nodeIndex = nixVectorForPacket->ExtractNeighborIndex (numberOfBits);
rtentry = GetIpv4RouteInCache (header.GetDestination ());
// not in cache
if (!rtentry)
{
NS_LOG_LOGIC ("Ipv4Route not in cache, build: ");
Ipv4Address gatewayIp;
uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp);
uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index));
Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0);
// start filling in the Ipv4Route info
rtentry = Create<Ipv4Route> ();
rtentry->SetSource (ifAddr.GetLocal ());
rtentry->SetGateway (Ipv4Address(gatewayIp));
rtentry->SetDestination (header.GetDestination ());
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex));
// add rtentry to cache
m_ipv4RouteCache.insert(Ipv4RouteMap_t::value_type(header.GetDestination (), rtentry));
}
NS_LOG_LOGIC ("Nix-vector contents: " << *nixVectorInCache << " : Remaining bits: " << nixVectorForPacket->GetRemainingBits());
// Add nix-vector in the packet class
// have to copy the packet first b/c
// it is const
Ptr<Packet> newPacket = Create<Packet> ();
newPacket = p->Copy();
NS_LOG_LOGIC ("Adding Nix-vector to packet: " << *nixVectorForPacket);
newPacket->SetNixVector(nixVectorForPacket);
// call the unicast callback
// local deliver is handled by Ipv4StaticRoutingImpl
// so this code is never even called if the packet is
// destined for this node.
ucb (rtentry, newPacket, header);
return true;
}
else // path doesn't exist
{
NS_LOG_ERROR ("No path to the dest: " << header.GetDestination ());
return false;
}
}
else
{
// Get the interface number that we go out of, by extracting
// from the nix-vector
if (m_totalNeighbors == 0)
{
m_totalNeighbors = FindTotalNeighbors ();
}
uint32_t numberOfBits = nixVector->BitCount (m_totalNeighbors);
uint32_t nodeIndex = nixVector->ExtractNeighborIndex (numberOfBits);
rtentry = GetIpv4RouteInCache (header.GetDestination ());
// not in cache
if (!rtentry)
{
NS_LOG_LOGIC ("Ipv4Route not in cache, build: ");
Ipv4Address gatewayIp;
uint32_t index = FindNetDeviceForNixIndex (nodeIndex, gatewayIp);
uint32_t interfaceIndex = (m_ipv4)->GetInterfaceForDevice(m_node->GetDevice(index));
Ipv4InterfaceAddress ifAddr = m_ipv4->GetAddress (interfaceIndex, 0);
// start filling in the Ipv4Route info
rtentry = Create<Ipv4Route> ();
rtentry->SetSource (ifAddr.GetLocal ());
rtentry->SetGateway (gatewayIp);
rtentry->SetDestination (header.GetDestination ());
rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIndex));
// add rtentry to cache
m_ipv4RouteCache.insert(Ipv4RouteMap_t::value_type(header.GetDestination (), rtentry));
}
NS_LOG_LOGIC ("At Node " << m_node->GetId() << ", Extracting " << numberOfBits <<
" bits from Nix-vector: " << nixVector << " : " << *nixVector);
// call the unicast callback
// local deliver is handled by Ipv4StaticRoutingImpl
// so this code is never even called if the packet is
// destined for this node.
ucb (rtentry, p, header);
return true;
}
}
// virtual functions from Ipv4RoutingProtocol
void
Ipv4NixVectorRouting::NotifyInterfaceUp (uint32_t i)
{
FlushGlobalNixRoutingCache ();
}
void
Ipv4NixVectorRouting::NotifyInterfaceDown (uint32_t i)
{
FlushGlobalNixRoutingCache ();
}
void
Ipv4NixVectorRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
{
FlushGlobalNixRoutingCache ();
}
void
Ipv4NixVectorRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
{
FlushGlobalNixRoutingCache ();
}
bool
Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr<Node> source, Ptr<Node> dest, std::vector< Ptr<Node> > & parentVector)
{
NS_LOG_FUNCTION_NOARGS ();
NS_LOG_LOGIC ("Going from Node " << source->GetId() << " to Node " << dest->GetId());
std::queue< Ptr<Node> > greyNodeList; // discovered nodes with unexplored children
// reset the parent vector
parentVector.clear ();
parentVector.reserve (sizeof (Ptr<Node>)*numberOfNodes);
parentVector.insert (parentVector.begin (), sizeof (Ptr<Node>)*numberOfNodes, 0); // initialize to 0
// Add the source node to the queue, set its parent to itself
greyNodeList.push (source);
parentVector.at (source->GetId()) = source;
// BFS loop
while (greyNodeList.size () != 0)
{
Ptr<Node> currNode = greyNodeList.front ();
Ptr<Ipv4> ipv4 = currNode->GetObject<Ipv4> ();
if (currNode == dest)
{
NS_LOG_LOGIC ("Made it to Node " << currNode->GetId());
return true;
}
// Iterate over the current node's adjacent vertices
// and push them into the queue
for (uint32_t i = 0; i < (currNode->GetNDevices ()); i++)
{
// Get a net device from the node
// as well as the channel, and figure
// out the adjacent net device
Ptr<NetDevice> localNetDevice = currNode->GetDevice (i);
// make sure that we can go this way
if (ipv4)
{
uint32_t interfaceIndex = (ipv4)->GetInterfaceForDevice(currNode->GetDevice(i));
if (!(ipv4->IsUp (interfaceIndex)))
{
NS_LOG_LOGIC ("Ipv4Interface is down");
continue;
}
}
if (!(localNetDevice->IsLinkUp ()))
{
NS_LOG_LOGIC ("Link is down.");
continue;
}
Ptr<Channel> channel = localNetDevice->GetChannel ();
if (channel == 0)
{
continue;
}
// this function takes in the local net dev, and channnel, and
// writes to the netDeviceContainer the adjacent net devs
NetDeviceContainer netDeviceContainer;
GetAdjacentNetDevices (localNetDevice, channel, netDeviceContainer);
// Finally we can get the adjacent nodes
// and scan through them. We push them
// to the greyNode queue, if they aren't
// already there.
for (NetDeviceContainer::Iterator iter = netDeviceContainer.Begin (); iter != netDeviceContainer.End (); iter++)
{
Ptr<Node> remoteNode = (*iter)->GetNode ();
// check to see if this node has been pushed before
// by checking to see if it has a parent
// if it doesn't (null or 0), then set its parent and
// push to the queue
if (parentVector.at (remoteNode->GetId ()) == 0)
{
parentVector.at (remoteNode->GetId ()) = currNode;
greyNodeList.push (remoteNode);
}
}
}
// Pop off the head grey node. We have all its children.
// It is now black.
greyNodeList.pop ();
}
// Didn't find the dest...
return false;
}
} // namespace ns3

View File

@@ -0,0 +1,157 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 The Georgia Institute of Technology
*
* 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
*
* Authors: Josh Pelkey <jpelkey@gatech.edu>
*/
#ifndef __IPV4_NIX_VECTOR_ROUTING_H__
#define __IPV4_NIX_VECTOR_ROUTING_H__
#include <map>
#include "ns3/channel.h"
#include "ns3/node-container.h"
#include "ns3/node-list.h"
#include "ns3/net-device-container.h"
#include "ns3/ipv4-routing-protocol.h"
#include "ns3/ipv4-route.h"
#include "ns3/bridge-net-device.h"
namespace ns3 {
typedef std::map<Ipv4Address, Ptr<NixVector> > NixMap_t;
typedef std::map<Ipv4Address, Ptr<Ipv4Route> > Ipv4RouteMap_t;
class Ipv4NixVectorRouting : public Ipv4RoutingProtocol
{
public:
Ipv4NixVectorRouting ();
~Ipv4NixVectorRouting ();
/**
* @brief The Interface ID of the Global Router interface.
*
* @see Object::GetObject ()
*/
static TypeId GetTypeId (void);
/**
* @brief Set the Node pointer of the node for which this
* routing protocol is to be placed
*
* @param node Node pointer
*/
void SetNode (Ptr<Node>);
/**
* @brief Called when run-time link topology change occurs
* which iterates through the node list and flushes any
* nix vector caches
*
*/
void FlushGlobalNixRoutingCache (void);
private:
/* flushes the cache which stores nix-vector based on
* destination IP */
void FlushNixCache (void);
/* flushes the cache which stores the Ipv4 route
* based on the destination IP */
void FlushIpv4RouteCache (void);
/* upon a run-time topology change caches are
* flushed and the total number of neighbors is
* reset to zero */
void ResetTotalNeighbors (void);
/* takes in the source node and dest IP and calls GetNodeByIp,
* BFS, and BuildNixVector to finally return the built
* nix-vector */
Ptr<NixVector> GetNixVector (Ptr<Node>, Ipv4Address);
/* checks the cache based on dest IP for the nix-vector */
Ptr<NixVector> GetNixVectorInCache (Ipv4Address);
/* checks the cache based on dest IP for the Ipv4Route */
Ptr<Ipv4Route> GetIpv4RouteInCache (Ipv4Address);
/* given a net-device returns all the adjacent net-devices,
* essentially getting the neighbors on that channel */
void GetAdjacentNetDevices (Ptr<NetDevice>, Ptr<Channel>, NetDeviceContainer &);
/* iterates through the node list and finds the one
* corresponding to the given Ipv4Address */
Ptr<Node> GetNodeByIp (Ipv4Address);
/* Recurses the parent vector, created by BFS and actually builds the nixvector */
bool BuildNixVector (const std::vector< Ptr<Node> > & parentVector, uint32_t source, uint32_t dest, Ptr<NixVector> nixVector);
/* special variation of BuildNixVector for when a node is sending to itself */
bool BuildNixVectorLocal (Ptr<NixVector> nixVector);
/* simple iterates through the nodes net-devices and determines
* how many neighbors it has */
uint32_t FindTotalNeighbors (void);
/* determine if the netdevice is bridged */
Ptr<BridgeNetDevice> NetDeviceIsBridged (Ptr<NetDevice> nd) const;
/* Nix index is with respect to the neighbors. The net-device index must be
* derived from this */
uint32_t FindNetDeviceForNixIndex (uint32_t nodeIndex, Ipv4Address & gatewayIp);
/* Breadth first search algorithm
* Param1: Vector containing all nodes in the graph
* Param2: Source Node
* Param3: Dest Node
* Param4: (returned) Parent vector for retracing routes
* Returns: false if dest not found, true o.w.
*/
bool BFS (uint32_t numberOfNodes,
Ptr<Node> source,
Ptr<Node> dest,
std::vector< Ptr<Node> > & parentVector);
void DoDispose (void);
/* From Ipv4RoutingProtocol */
virtual Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
virtual bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
LocalDeliverCallback lcb, ErrorCallback ecb);
virtual void NotifyInterfaceUp (uint32_t interface);
virtual void NotifyInterfaceDown (uint32_t interface);
virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
virtual void SetIpv4 (Ptr<Ipv4> ipv4);
/* cache stores nix-vectors based on destination ip */
NixMap_t m_nixCache;
/* cache stores Ipv4Routes based on destination ip */
Ipv4RouteMap_t m_ipv4RouteCache;
Ptr<Ipv4> m_ipv4;
Ptr<Node> m_node;
/* total neighbors used for nix-vector to determine
* number of bits */
uint32_t m_totalNeighbors;
};
} // namepace ns3
#endif

View File

@@ -0,0 +1,71 @@
/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2009 The Georgia Institute of Technology
*
* 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
*
* Authors: Josh Pelkey <jpelkey@gatech.edu>
*/
/**
* \ingroup routing
* \defgroup nixvectorrouting Nix-vector Routing
*
* \section model Model
*
* Nix-vector routing is a simulation specific routing protocol and is
* intended for large network topologies. The on-demand nature of this
* protocol as well as the low-memory footprint of the nix-vector provides
* improved performance in terms of memory usage and simulation run time
* when dealing with a large number of nodes.
*
* Currently, the ns-3 model of nix-vector routing supports IPv4 p2p links
* as well as CSMA links. It does not (yet) provide support for
* efficient adaptation to link failures. It simply flushes all nix-vector
* routing caches. Finally, IPv6 is not supported.
*
* \section api API and Usage
*
* Nix-vector routing has been rolled into a helper class. In order to
* utilize these helper functions, users must include ns3/helper-module.h.
* The Nix-vector routing protocol must be added to a list of routing
* protocols. It is important that list routing is utilized.
*
* Example:
*
* Ipv4NixVectorHelper nixRouting;
* Ipv4StaticRoutingHelper staticRouting;
*
* Ipv4ListRoutingHelper list;
* list.Add (staticRouting, 0);
* list.Add (nixRouting, 10);
*
* InternetStackHelper stack;
* stack.SetRoutingHelper (list);
* stack.Install (allNodes);
*
* \section impl Implementation
*
* ns-3 nix-vector-routing performs on-demand route computation using
* a breadth-first search and an efficient route-storage data structure
* known as a nix-vector. When a packet is generated at a node for
* transmission, the route is calculated, and the nix-vector is built.
* The nix-vector stores an index for each hop along the path, which
* corresponds to the neighbor-index. This index is used to determine
* which net-device and gateway should be used. To route a packet, the
* nix-vector must be transmitted with the packet (in the metadata).
* At each hop, the current node extracts the appropriate neighbor-index
* from the nix-vector and transmits the packet through the corresponding
* net-device. This continues until the packet reaches the destination.
* */

1
src/routing/nix-vector-routing/waf vendored Normal file
View File

@@ -0,0 +1 @@
exec "`dirname "$0"`"/../../../waf "$@"

View File

@@ -0,0 +1,15 @@
## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
module = bld.create_ns3_module('nix-vector-routing', ['internet-stack', 'contrib'])
module.includes = '.'
module.source = [
'ipv4-nix-vector-routing.cc',
]
headers = bld.new_task_gen('ns3header')
headers.module = 'nix-vector-routing'
headers.source = [
'ipv4-nix-vector-routing.h',
]

View File

@@ -27,6 +27,7 @@ all_modules = (
'applications/onoff',
'applications/packet-sink',
'applications/udp-echo',
'routing/nix-vector-routing',
'routing/olsr',
'routing/global-routing',
'routing/static-routing',