Merge NixVector Routing code
This commit is contained in:
1
AUTHORS
1
AUTHORS
@@ -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)
|
||||
|
||||
11
CHANGES.html
11
CHANGES.html
@@ -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>
|
||||
|
||||
@@ -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
114
examples/nix-simple.cc
Normal 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
458
examples/nms-p2p-nix.cc
Normal 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;
|
||||
}
|
||||
@@ -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
419
src/common/nix-vector.cc
Normal 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
166
src/common/nix-vector.h
Normal 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
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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',
|
||||
|
||||
39
src/helper/ipv4-nix-vector-helper.cc
Normal file
39
src/helper/ipv4-nix-vector-helper.cc
Normal 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
|
||||
55
src/helper/ipv4-nix-vector-helper.h
Normal file
55
src/helper/ipv4-nix-vector-helper.h
Normal 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 */
|
||||
@@ -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',
|
||||
|
||||
840
src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc
Normal file
840
src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc
Normal 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
|
||||
157
src/routing/nix-vector-routing/ipv4-nix-vector-routing.h
Normal file
157
src/routing/nix-vector-routing/ipv4-nix-vector-routing.h
Normal 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
|
||||
71
src/routing/nix-vector-routing/nix-vector-routing.h
Normal file
71
src/routing/nix-vector-routing/nix-vector-routing.h
Normal 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
1
src/routing/nix-vector-routing/waf
vendored
Normal file
@@ -0,0 +1 @@
|
||||
exec "`dirname "$0"`"/../../../waf "$@"
|
||||
15
src/routing/nix-vector-routing/wscript
Normal file
15
src/routing/nix-vector-routing/wscript
Normal 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',
|
||||
]
|
||||
|
||||
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user