--- a/AUTHORS Fri Sep 18 12:27:17 2009 +0100
+++ b/AUTHORS Fri Sep 18 10:32:07 2009 -0400
@@ -31,3 +31,4 @@
Sebastien Vincent (vincent@clarinet.u-strasbg.fr)
Guillaume Vu-Brugier (gvubrugier@gmail.com)
Florian Westphal (fw@strlen.de)
+Josh Pelkey (jpelkey@gatech.edu)
--- a/CHANGES.html Fri Sep 18 12:27:17 2009 +0100
+++ b/CHANGES.html Fri Sep 18 10:32:07 2009 -0400
@@ -113,6 +113,17 @@
</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>
--- a/RELEASE_NOTES Fri Sep 18 12:27:17 2009 +0100
+++ b/RELEASE_NOTES Fri Sep 18 10:32:07 2009 -0400
@@ -59,6 +59,10 @@
- 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.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/nix-simple.cc Fri Sep 18 10:32:07 2009 -0400
@@ -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;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/nms-p2p-nix.cc Fri Sep 18 10:32:07 2009 -0400
@@ -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;
+}
--- a/examples/wscript Fri Sep 18 12:27:17 2009 +0100
+++ b/examples/wscript Fri Sep 18 10:32:07 2009 -0400
@@ -96,6 +96,14 @@
['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'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/nix-vector.cc Fri Sep 18 10:32:07 2009 -0400
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/common/nix-vector.h Fri Sep 18 10:32:07 2009 -0400
@@ -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
--- a/src/common/packet.cc Fri Sep 18 12:27:17 2009 +0100
+++ b/src/common/packet.cc Fri Sep 18 10:32:07 2009 -0400
@@ -138,6 +138,7 @@
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, 0),
+ m_nixVector (0),
m_refCount (1)
{
m_globalUid++;
@@ -149,7 +150,10 @@
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 @@
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 @@
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, size),
+ m_nixVector (0),
m_refCount (1)
{
m_globalUid++;
@@ -179,6 +186,7 @@
m_byteTagList (),
m_packetTagList (),
m_metadata (m_globalUid, size),
+ m_nixVector (0),
m_refCount (1)
{
m_globalUid++;
@@ -193,6 +201,7 @@
m_byteTagList (byteTagList),
m_packetTagList (packetTagList),
m_metadata (metadata),
+ m_nixVector (0),
m_refCount (1)
{}
@@ -209,6 +218,18 @@
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 @@
return PacketTagIterator (m_packetTagList.Head ());
}
-
std::ostream& operator<< (std::ostream& os, const Packet &packet)
{
packet.Print (os);
--- a/src/common/packet.h Fri Sep 18 12:27:17 2009 +0100
+++ b/src/common/packet.h Fri Sep 18 10:32:07 2009 -0400
@@ -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 @@
*/
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 @@
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;
};
--- a/src/common/wscript Fri Sep 18 12:27:17 2009 +0100
+++ b/src/common/wscript Fri Sep 18 10:32:07 2009 -0400
@@ -17,6 +17,7 @@
'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 @@
'byte-tag-list.h',
'tag-buffer.h',
'packet-tag-list.h',
+ 'nix-vector.h',
'ascii-writer.h',
'sgi-hashmap.h',
'pcap-file.h',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv4-nix-vector-helper.cc Fri Sep 18 10:32:07 2009 -0400
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/ipv4-nix-vector-helper.h Fri Sep 18 10:32:07 2009 -0400
@@ -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 */
--- a/src/helper/wscript Fri Sep 18 12:27:17 2009 +0100
+++ b/src/helper/wscript Fri Sep 18 10:32:07 2009 -0400
@@ -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 @@
'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 @@
'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',
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc Fri Sep 18 10:32:07 2009 -0400
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/nix-vector-routing/ipv4-nix-vector-routing.h Fri Sep 18 10:32:07 2009 -0400
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/nix-vector-routing/nix-vector-routing.h Fri Sep 18 10:32:07 2009 -0400
@@ -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.
+ * */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/nix-vector-routing/waf Fri Sep 18 10:32:07 2009 -0400
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../waf "$@"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/nix-vector-routing/wscript Fri Sep 18 10:32:07 2009 -0400
@@ -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',
+ ]
+
--- a/src/wscript Fri Sep 18 12:27:17 2009 +0100
+++ b/src/wscript Fri Sep 18 10:32:07 2009 -0400
@@ -27,6 +27,7 @@
'applications/onoff',
'applications/packet-sink',
'applications/udp-echo',
+ 'routing/nix-vector-routing',
'routing/olsr',
'routing/global-routing',
'routing/static-routing',