Merge NixVector Routing code
authorJosh Pelkey <jpelkey@gatech.edu>
Fri, 18 Sep 2009 10:32:07 -0400
changeset 5224 06f639d05b8f
parent 5223 d6bbde9c6712
child 5225 9c612cb88d6b
Merge NixVector Routing code
AUTHORS
CHANGES.html
RELEASE_NOTES
examples/nix-simple.cc
examples/nms-p2p-nix.cc
examples/wscript
src/common/nix-vector.cc
src/common/nix-vector.h
src/common/packet.cc
src/common/packet.h
src/common/wscript
src/helper/ipv4-nix-vector-helper.cc
src/helper/ipv4-nix-vector-helper.h
src/helper/wscript
src/routing/nix-vector-routing/ipv4-nix-vector-routing.cc
src/routing/nix-vector-routing/ipv4-nix-vector-routing.h
src/routing/nix-vector-routing/nix-vector-routing.h
src/routing/nix-vector-routing/waf
src/routing/nix-vector-routing/wscript
src/wscript
--- 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',