Add IPv4 DSR routing
authorYufei Cheng <yfcheng@ittc.ku.edu>
Fri, 27 Jan 2012 15:15:48 -0800
changeset 8751 efad81f3cb47
parent 8750 b3db7d51f260
child 8752 2da1fab73114
Add IPv4 DSR routing
doc/models/Makefile
doc/models/source/index.rst
examples/routing/manet-routing-compare.cc
examples/routing/wscript
manet-routing.output.csv.dsr
manet-routing.output.csv.olsr
src/dsr/doc/dsr.h
src/dsr/doc/dsr.rst
src/dsr/examples/dsr.cc
src/dsr/examples/wscript
src/dsr/helper/dsr-helper.cc
src/dsr/helper/dsr-helper.h
src/dsr/helper/dsr-main-helper.cc
src/dsr/helper/dsr-main-helper.h
src/dsr/model/dsr-fs-header.cc
src/dsr/model/dsr-fs-header.h
src/dsr/model/dsr-gratuitous-reply-table.cc
src/dsr/model/dsr-gratuitous-reply-table.h
src/dsr/model/dsr-maintain-buff.cc
src/dsr/model/dsr-maintain-buff.h
src/dsr/model/dsr-option-header.cc
src/dsr/model/dsr-option-header.h
src/dsr/model/dsr-options.cc
src/dsr/model/dsr-options.h
src/dsr/model/dsr-rcache.cc
src/dsr/model/dsr-rcache.h
src/dsr/model/dsr-routing.cc
src/dsr/model/dsr-routing.h
src/dsr/model/dsr-rreq-table.cc
src/dsr/model/dsr-rreq-table.h
src/dsr/model/dsr-rsendbuff.cc
src/dsr/model/dsr-rsendbuff.h
src/dsr/test/dsr-test-suite.cc
src/dsr/wscript
--- a/doc/models/Makefile	Sat May 12 21:14:01 2012 -0700
+++ b/doc/models/Makefile	Fri Jan 27 15:15:48 2012 -0800
@@ -32,6 +32,7 @@
 	$(SRC)/click/doc/click.rst \
 	$(SRC)/csma/doc/csma.rst \
 	$(SRC)/dsdv/doc/dsdv.rst \
+	$(SRC)/dsr/doc/dsr.rst \
 	$(SRC)/mpi/doc/distributed.rst \
 	$(SRC)/energy/doc/energy.rst \
 	$(SRC)/emu/doc/emu.rst \
--- a/doc/models/source/index.rst	Sat May 12 21:14:01 2012 -0700
+++ b/doc/models/source/index.rst	Fri Jan 27 15:15:48 2012 -0800
@@ -26,6 +26,7 @@
    click
    csma
    dsdv
+   dsr
    emulation-overview
    energy
    flow-monitor
--- a/examples/routing/manet-routing-compare.cc	Sat May 12 21:14:01 2012 -0700
+++ b/examples/routing/manet-routing-compare.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -75,9 +75,11 @@
 #include "ns3/aodv-module.h"
 #include "ns3/olsr-module.h"
 #include "ns3/dsdv-module.h"
+#include "ns3/dsr-module.h"
 #include "ns3/applications-module.h"
 
 using namespace ns3;
+using namespace dsr;
 
 NS_LOG_COMPONENT_DEFINE ("manet-routing-compare");
 
@@ -190,7 +192,7 @@
   CommandLine cmd;
   cmd.AddValue ("CSVfileName", "The name of the CSV output file name", m_CSVfileName);
   cmd.AddValue ("traceMobility", "Enable mobility tracing", m_traceMobility);
-  cmd.AddValue ("protocol", "1=OLSR;2=AODV;3=DSDV", m_protocol);
+  cmd.AddValue ("protocol", "1=OLSR;2=AODV;3=DSDV;4=DSR", m_protocol);
   cmd.Parse (argc, argv);
   return m_CSVfileName;
 }
@@ -270,7 +272,10 @@
   AodvHelper aodv;
   OlsrHelper olsr;
   DsdvHelper dsdv;
+  DsrHelper dsr;
+  DsrMainHelper dsrMain;
   Ipv4ListRoutingHelper list;
+  InternetStackHelper internet;
 
   switch (m_protocol)
     {
@@ -286,13 +291,23 @@
       list.Add (dsdv, 100);
       m_protocolName = "DSDV";
       break;
+    case 4:
+      m_protocolName = "DSR";
+      break;
     default:
       NS_FATAL_ERROR ("No such protocol:" << m_protocol);
     }
 
-  InternetStackHelper internet;
-  internet.SetRoutingHelper (list);
-  internet.Install (adhocNodes);
+  if (m_protocol < 4)
+    {
+      internet.SetRoutingHelper (list);
+      internet.Install (adhocNodes);
+    }
+  else if (m_protocol == 4)
+    {
+      internet.Install (adhocNodes);
+      dsrMain.Install (dsr, adhocNodes);
+    }
 
   NS_LOG_INFO ("assigning ip address");
 
@@ -356,7 +371,7 @@
   //Ptr<OutputStreamWrapper> osw = ascii.CreateFileStream ( (tr_name + ".tr").c_str());
   //wifiPhy.EnableAsciiAll (osw);
   std::ofstream os;
-  os.open ((tr_name + ".mob").c_str());
+  os.open ((tr_name + ".mob").c_str ());
   MobilityHelper::EnableAsciiAll (os);
 
   //Ptr<FlowMonitor> flowmon;
--- a/examples/routing/wscript	Sat May 12 21:14:01 2012 -0700
+++ b/examples/routing/wscript	Fri Jan 27 15:15:48 2012 -0800
@@ -34,7 +34,7 @@
     obj.source = 'simple-routing-ping6.cc'
 
     obj = bld.create_ns3_program('manet-routing-compare',
-                                 ['wifi', 'dsdv', 'aodv', 'olsr', 'internet', 'applications'])
+                                 ['wifi', 'dsr', 'dsdv', 'aodv', 'olsr', 'internet', 'applications'])
     obj.source = 'manet-routing-compare.cc'
 
     bld.register_ns3_script('simple-routing-ping6.py', ['csma', 'internet', 'applications'])
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/manet-routing.output.csv.dsr	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,201 @@
+SimulationSecond,ReceiveRate,PacketsReceived,NumberOfSinks,RoutingProtocol,TransmissionPower
+0,0,0,10,DSR,7.5
+1,0,0,10,DSR,7.5
+2,0,0,10,DSR,7.5
+3,0,0,10,DSR,7.5
+4,0,0,10,DSR,7.5
+5,0,0,10,DSR,7.5
+6,0,0,10,DSR,7.5
+7,0,0,10,DSR,7.5
+8,0,0,10,DSR,7.5
+9,0,0,10,DSR,7.5
+10,0,0,10,DSR,7.5
+11,0,0,10,DSR,7.5
+12,0,0,10,DSR,7.5
+13,0,0,10,DSR,7.5
+14,0,0,10,DSR,7.5
+15,0,0,10,DSR,7.5
+16,0,0,10,DSR,7.5
+17,0,0,10,DSR,7.5
+18,0,0,10,DSR,7.5
+19,0,0,10,DSR,7.5
+20,0,0,10,DSR,7.5
+21,0,0,10,DSR,7.5
+22,0,0,10,DSR,7.5
+23,0,0,10,DSR,7.5
+24,0,0,10,DSR,7.5
+25,0,0,10,DSR,7.5
+26,0,0,10,DSR,7.5
+27,0,0,10,DSR,7.5
+28,0,0,10,DSR,7.5
+29,0,0,10,DSR,7.5
+30,0,0,10,DSR,7.5
+31,0,0,10,DSR,7.5
+32,0,0,10,DSR,7.5
+33,0,0,10,DSR,7.5
+34,0,0,10,DSR,7.5
+35,0,0,10,DSR,7.5
+36,0,0,10,DSR,7.5
+37,0,0,10,DSR,7.5
+38,0,0,10,DSR,7.5
+39,0,0,10,DSR,7.5
+40,0,0,10,DSR,7.5
+41,0,0,10,DSR,7.5
+42,0,0,10,DSR,7.5
+43,0,0,10,DSR,7.5
+44,0,0,10,DSR,7.5
+45,0,0,10,DSR,7.5
+46,0,0,10,DSR,7.5
+47,0,0,10,DSR,7.5
+48,0,0,10,DSR,7.5
+49,0,0,10,DSR,7.5
+50,0,0,10,DSR,7.5
+51,0,0,10,DSR,7.5
+52,0,0,10,DSR,7.5
+53,1.536,3,10,DSR,7.5
+54,71.168,139,10,DSR,7.5
+55,29.184,57,10,DSR,7.5
+56,0,0,10,DSR,7.5
+57,0,0,10,DSR,7.5
+58,0,0,10,DSR,7.5
+59,3.584,7,10,DSR,7.5
+60,12.288,24,10,DSR,7.5
+61,7.168,14,10,DSR,7.5
+62,5.12,10,10,DSR,7.5
+63,0,0,10,DSR,7.5
+64,0,0,10,DSR,7.5
+65,0,0,10,DSR,7.5
+66,0,0,10,DSR,7.5
+67,1.536,3,10,DSR,7.5
+68,0,0,10,DSR,7.5
+69,0,0,10,DSR,7.5
+70,0,0,10,DSR,7.5
+71,0,0,10,DSR,7.5
+72,0,0,10,DSR,7.5
+73,0,0,10,DSR,7.5
+74,0,0,10,DSR,7.5
+75,0,0,10,DSR,7.5
+76,0,0,10,DSR,7.5
+77,3.584,7,10,DSR,7.5
+78,14.336,28,10,DSR,7.5
+79,12.288,24,10,DSR,7.5
+80,0.512,1,10,DSR,7.5
+81,0,0,10,DSR,7.5
+82,1.024,2,10,DSR,7.5
+83,4.096,8,10,DSR,7.5
+84,4.096,8,10,DSR,7.5
+85,2.048,4,10,DSR,7.5
+86,1.536,3,10,DSR,7.5
+87,7.68,15,10,DSR,7.5
+88,4.608,9,10,DSR,7.5
+89,5.632,11,10,DSR,7.5
+90,0.512,1,10,DSR,7.5
+91,5.632,11,10,DSR,7.5
+92,8.192,16,10,DSR,7.5
+93,14.848,29,10,DSR,7.5
+94,10.752,21,10,DSR,7.5
+95,14.336,28,10,DSR,7.5
+96,2.048,4,10,DSR,7.5
+97,6.144,12,10,DSR,7.5
+98,11.776,23,10,DSR,7.5
+99,8.704,17,10,DSR,7.5
+100,5.632,11,10,DSR,7.5
+101,6.144,12,10,DSR,7.5
+102,9.216,18,10,DSR,7.5
+103,5.12,10,10,DSR,7.5
+104,10.24,20,10,DSR,7.5
+105,5.12,10,10,DSR,7.5
+106,7.68,15,10,DSR,7.5
+107,8.192,16,10,DSR,7.5
+108,3.072,6,10,DSR,7.5
+109,1.536,3,10,DSR,7.5
+110,7.168,14,10,DSR,7.5
+111,7.68,15,10,DSR,7.5
+112,7.168,14,10,DSR,7.5
+113,5.632,11,10,DSR,7.5
+114,4.608,9,10,DSR,7.5
+115,8.704,17,10,DSR,7.5
+116,21.504,42,10,DSR,7.5
+117,4.608,9,10,DSR,7.5
+118,18.944,37,10,DSR,7.5
+119,23.552,46,10,DSR,7.5
+120,46.592,91,10,DSR,7.5
+121,38.4,75,10,DSR,7.5
+122,11.264,22,10,DSR,7.5
+123,44.544,87,10,DSR,7.5
+124,33.28,65,10,DSR,7.5
+125,13.312,26,10,DSR,7.5
+126,18.432,36,10,DSR,7.5
+127,31.744,62,10,DSR,7.5
+128,47.616,93,10,DSR,7.5
+129,48.128,94,10,DSR,7.5
+130,28.672,56,10,DSR,7.5
+131,71.68,140,10,DSR,7.5
+132,50.688,99,10,DSR,7.5
+133,9.728,19,10,DSR,7.5
+134,34.304,67,10,DSR,7.5
+135,12.288,24,10,DSR,7.5
+136,14.848,29,10,DSR,7.5
+137,3.584,7,10,DSR,7.5
+138,10.752,21,10,DSR,7.5
+139,17.92,35,10,DSR,7.5
+140,7.68,15,10,DSR,7.5
+141,29.184,57,10,DSR,7.5
+142,5.12,10,10,DSR,7.5
+143,55.808,109,10,DSR,7.5
+144,28.672,56,10,DSR,7.5
+145,21.504,42,10,DSR,7.5
+146,20.48,40,10,DSR,7.5
+147,46.592,91,10,DSR,7.5
+148,3.072,6,10,DSR,7.5
+149,18.944,37,10,DSR,7.5
+150,48.128,94,10,DSR,7.5
+151,33.792,66,10,DSR,7.5
+152,0,0,10,DSR,7.5
+153,20.48,40,10,DSR,7.5
+154,30.208,59,10,DSR,7.5
+155,17.92,35,10,DSR,7.5
+156,3.072,6,10,DSR,7.5
+157,12.288,24,10,DSR,7.5
+158,23.04,45,10,DSR,7.5
+159,27.648,54,10,DSR,7.5
+160,16.384,32,10,DSR,7.5
+161,9.728,19,10,DSR,7.5
+162,17.92,35,10,DSR,7.5
+163,10.24,20,10,DSR,7.5
+164,20.992,41,10,DSR,7.5
+165,14.336,28,10,DSR,7.5
+166,5.632,11,10,DSR,7.5
+167,11.776,23,10,DSR,7.5
+168,25.6,50,10,DSR,7.5
+169,13.312,26,10,DSR,7.5
+170,3.072,6,10,DSR,7.5
+171,13.824,27,10,DSR,7.5
+172,11.776,23,10,DSR,7.5
+173,8.192,16,10,DSR,7.5
+174,3.072,6,10,DSR,7.5
+175,0.512,1,10,DSR,7.5
+176,3.584,7,10,DSR,7.5
+177,13.824,27,10,DSR,7.5
+178,16.896,33,10,DSR,7.5
+179,5.632,11,10,DSR,7.5
+180,16.896,33,10,DSR,7.5
+181,14.336,28,10,DSR,7.5
+182,6.656,13,10,DSR,7.5
+183,18.432,36,10,DSR,7.5
+184,24.576,48,10,DSR,7.5
+185,13.312,26,10,DSR,7.5
+186,14.848,29,10,DSR,7.5
+187,9.728,19,10,DSR,7.5
+188,6.144,12,10,DSR,7.5
+189,6.656,13,10,DSR,7.5
+190,86.528,169,10,DSR,7.5
+191,13.824,27,10,DSR,7.5
+192,37.888,74,10,DSR,7.5
+193,12.8,25,10,DSR,7.5
+194,2.048,4,10,DSR,7.5
+195,9.728,19,10,DSR,7.5
+196,17.92,35,10,DSR,7.5
+197,2.56,5,10,DSR,7.5
+198,10.24,20,10,DSR,7.5
+199,2.56,5,10,DSR,7.5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/manet-routing.output.csv.olsr	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,201 @@
+SimulationSecond,ReceiveRate,PacketsReceived,NumberOfSinks,RoutingProtocol,TransmissionPower
+0,0,0,10,OLSR,7.5
+1,0,0,10,OLSR,7.5
+2,0,0,10,OLSR,7.5
+3,0,0,10,OLSR,7.5
+4,0,0,10,OLSR,7.5
+5,0,0,10,OLSR,7.5
+6,0,0,10,OLSR,7.5
+7,0,0,10,OLSR,7.5
+8,0,0,10,OLSR,7.5
+9,0,0,10,OLSR,7.5
+10,0,0,10,OLSR,7.5
+11,0,0,10,OLSR,7.5
+12,0,0,10,OLSR,7.5
+13,0,0,10,OLSR,7.5
+14,0,0,10,OLSR,7.5
+15,0,0,10,OLSR,7.5
+16,0,0,10,OLSR,7.5
+17,0,0,10,OLSR,7.5
+18,0,0,10,OLSR,7.5
+19,0,0,10,OLSR,7.5
+20,0,0,10,OLSR,7.5
+21,0,0,10,OLSR,7.5
+22,0,0,10,OLSR,7.5
+23,0,0,10,OLSR,7.5
+24,0,0,10,OLSR,7.5
+25,0,0,10,OLSR,7.5
+26,0,0,10,OLSR,7.5
+27,0,0,10,OLSR,7.5
+28,0,0,10,OLSR,7.5
+29,0,0,10,OLSR,7.5
+30,0,0,10,OLSR,7.5
+31,0,0,10,OLSR,7.5
+32,0,0,10,OLSR,7.5
+33,0,0,10,OLSR,7.5
+34,0,0,10,OLSR,7.5
+35,0,0,10,OLSR,7.5
+36,0,0,10,OLSR,7.5
+37,0,0,10,OLSR,7.5
+38,0,0,10,OLSR,7.5
+39,0,0,10,OLSR,7.5
+40,0,0,10,OLSR,7.5
+41,0,0,10,OLSR,7.5
+42,0,0,10,OLSR,7.5
+43,0,0,10,OLSR,7.5
+44,0,0,10,OLSR,7.5
+45,0,0,10,OLSR,7.5
+46,0,0,10,OLSR,7.5
+47,0,0,10,OLSR,7.5
+48,0,0,10,OLSR,7.5
+49,0,0,10,OLSR,7.5
+50,0,0,10,OLSR,7.5
+51,5.632,11,10,OLSR,7.5
+52,16.384,32,10,OLSR,7.5
+53,18.432,36,10,OLSR,7.5
+54,20.48,40,10,OLSR,7.5
+55,18.944,37,10,OLSR,7.5
+56,16.384,32,10,OLSR,7.5
+57,18.944,37,10,OLSR,7.5
+58,18.432,36,10,OLSR,7.5
+59,17.92,35,10,OLSR,7.5
+60,18.432,36,10,OLSR,7.5
+61,18.432,36,10,OLSR,7.5
+62,17.408,34,10,OLSR,7.5
+63,17.92,35,10,OLSR,7.5
+64,17.92,35,10,OLSR,7.5
+65,18.432,36,10,OLSR,7.5
+66,18.432,36,10,OLSR,7.5
+67,17.92,35,10,OLSR,7.5
+68,17.92,35,10,OLSR,7.5
+69,14.848,29,10,OLSR,7.5
+70,18.432,36,10,OLSR,7.5
+71,15.872,31,10,OLSR,7.5
+72,14.848,29,10,OLSR,7.5
+73,14.336,28,10,OLSR,7.5
+74,12.8,25,10,OLSR,7.5
+75,18.432,36,10,OLSR,7.5
+76,18.432,36,10,OLSR,7.5
+77,17.92,35,10,OLSR,7.5
+78,18.432,36,10,OLSR,7.5
+79,18.432,36,10,OLSR,7.5
+80,17.408,34,10,OLSR,7.5
+81,16.896,33,10,OLSR,7.5
+82,20.48,40,10,OLSR,7.5
+83,17.92,35,10,OLSR,7.5
+84,22.016,43,10,OLSR,7.5
+85,16.384,32,10,OLSR,7.5
+86,16.896,33,10,OLSR,7.5
+87,17.92,35,10,OLSR,7.5
+88,19.456,38,10,OLSR,7.5
+89,17.92,35,10,OLSR,7.5
+90,18.432,36,10,OLSR,7.5
+91,17.408,34,10,OLSR,7.5
+92,15.872,31,10,OLSR,7.5
+93,16.384,32,10,OLSR,7.5
+94,16.384,32,10,OLSR,7.5
+95,16.896,33,10,OLSR,7.5
+96,17.408,34,10,OLSR,7.5
+97,18.944,37,10,OLSR,7.5
+98,16.384,32,10,OLSR,7.5
+99,19.456,38,10,OLSR,7.5
+100,20.48,40,10,OLSR,7.5
+101,20.48,40,10,OLSR,7.5
+102,20.48,40,10,OLSR,7.5
+103,19.968,39,10,OLSR,7.5
+104,19.456,38,10,OLSR,7.5
+105,17.92,35,10,OLSR,7.5
+106,17.92,35,10,OLSR,7.5
+107,18.432,36,10,OLSR,7.5
+108,18.432,36,10,OLSR,7.5
+109,18.432,36,10,OLSR,7.5
+110,19.968,39,10,OLSR,7.5
+111,18.944,37,10,OLSR,7.5
+112,18.432,36,10,OLSR,7.5
+113,18.432,36,10,OLSR,7.5
+114,18.432,36,10,OLSR,7.5
+115,20.48,40,10,OLSR,7.5
+116,20.48,40,10,OLSR,7.5
+117,20.48,40,10,OLSR,7.5
+118,20.48,40,10,OLSR,7.5
+119,20.48,40,10,OLSR,7.5
+120,18.944,37,10,OLSR,7.5
+121,17.92,35,10,OLSR,7.5
+122,18.432,36,10,OLSR,7.5
+123,19.968,39,10,OLSR,7.5
+124,20.48,40,10,OLSR,7.5
+125,19.968,39,10,OLSR,7.5
+126,16.384,32,10,OLSR,7.5
+127,16.896,33,10,OLSR,7.5
+128,16.384,32,10,OLSR,7.5
+129,17.92,35,10,OLSR,7.5
+130,18.432,36,10,OLSR,7.5
+131,17.92,35,10,OLSR,7.5
+132,17.92,35,10,OLSR,7.5
+133,20.48,40,10,OLSR,7.5
+134,20.48,40,10,OLSR,7.5
+135,18.432,36,10,OLSR,7.5
+136,17.92,35,10,OLSR,7.5
+137,16.896,33,10,OLSR,7.5
+138,16.384,32,10,OLSR,7.5
+139,17.92,35,10,OLSR,7.5
+140,18.432,36,10,OLSR,7.5
+141,17.408,34,10,OLSR,7.5
+142,16.384,32,10,OLSR,7.5
+143,16.384,32,10,OLSR,7.5
+144,16.384,32,10,OLSR,7.5
+145,18.432,36,10,OLSR,7.5
+146,19.456,38,10,OLSR,7.5
+147,18.944,37,10,OLSR,7.5
+148,18.432,36,10,OLSR,7.5
+149,19.968,39,10,OLSR,7.5
+150,19.968,39,10,OLSR,7.5
+151,18.944,37,10,OLSR,7.5
+152,20.992,41,10,OLSR,7.5
+153,18.944,37,10,OLSR,7.5
+154,18.432,36,10,OLSR,7.5
+155,17.408,34,10,OLSR,7.5
+156,20.48,40,10,OLSR,7.5
+157,18.944,37,10,OLSR,7.5
+158,17.92,35,10,OLSR,7.5
+159,18.944,37,10,OLSR,7.5
+160,18.432,36,10,OLSR,7.5
+161,19.456,38,10,OLSR,7.5
+162,19.968,39,10,OLSR,7.5
+163,19.456,38,10,OLSR,7.5
+164,19.968,39,10,OLSR,7.5
+165,20.48,40,10,OLSR,7.5
+166,20.48,40,10,OLSR,7.5
+167,19.968,39,10,OLSR,7.5
+168,20.48,40,10,OLSR,7.5
+169,18.944,37,10,OLSR,7.5
+170,19.456,38,10,OLSR,7.5
+171,18.944,37,10,OLSR,7.5
+172,21.504,42,10,OLSR,7.5
+173,20.48,40,10,OLSR,7.5
+174,19.968,39,10,OLSR,7.5
+175,18.432,36,10,OLSR,7.5
+176,18.432,36,10,OLSR,7.5
+177,19.456,38,10,OLSR,7.5
+178,20.48,40,10,OLSR,7.5
+179,17.92,35,10,OLSR,7.5
+180,18.944,37,10,OLSR,7.5
+181,19.968,39,10,OLSR,7.5
+182,20.48,40,10,OLSR,7.5
+183,18.944,37,10,OLSR,7.5
+184,18.432,36,10,OLSR,7.5
+185,19.968,39,10,OLSR,7.5
+186,20.48,40,10,OLSR,7.5
+187,20.48,40,10,OLSR,7.5
+188,20.48,40,10,OLSR,7.5
+189,18.432,36,10,OLSR,7.5
+190,18.432,36,10,OLSR,7.5
+191,17.408,34,10,OLSR,7.5
+192,19.456,38,10,OLSR,7.5
+193,17.92,35,10,OLSR,7.5
+194,18.432,36,10,OLSR,7.5
+195,19.968,39,10,OLSR,7.5
+196,20.48,40,10,OLSR,7.5
+197,19.968,39,10,OLSR,7.5
+198,20.992,41,10,OLSR,7.5
+199,20.48,40,10,OLSR,7.5
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/doc/dsr.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,43 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_H
+#define DSR_H
+
+/**
+ * \defgroup dsr DSR Routing
+ *
+ * This section documents the API of the ns-3 DSR module. For a
+ * generic functional description, please refer to the ns-3 model
+ * library document.
+ */
+
+#endif /* DSR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/doc/dsr.rst	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,142 @@
+.. include:: replace.txt
+
+DSR Routing
+-----------
+
+Dynamic Source Routing (DSR) protocol is a reactive routing protocol designed specifically for use in multi-hop 
+wireless ad hoc networks of mobile nodes.
+
+This model was developed by 
+`the ResiliNets research group <http://www.ittc.ku.edu/resilinets>`_
+at the University of Kansas.  
+
+DSR Routing Overview
+********************
+ 
+ This model implements the base specification of the Dynamic Source Routing (DSR)
+ protocol. Implementation is based on RFC4728.
+
+ Class dsr::DsrRouting implements all functionality of service packet exchange and inherits Ipv4L4Protocol.
+
+ Class dsr::DsrOptions implements functionality of packet processing and talk to DsrRouting to send/receive packets
+
+ Class dsr::DsrFsHeader defines the fixed-size header and identify the up-layer protocol
+
+ Class dsr::DsrOptionHeader takes care of different dsr options and process different header according to specification from rfc
+
+ Class dsr::DsrSendBuffer is a buffer to save data packet as well as route error packet when there is no route to forward the packet
+
+ Class dsr::DsrMaintainBuffer is a buffer to save data packet for next-hop notification when the data packet has already sent out of send buffer
+
+ Class dsr::RouteCache is the essential part to save routes found for data packet, dsr responds to several routes for a single destination
+
+ Class dsr::RreqTable implements the functionalities to avoid duplicate route requests and control route request rate for a single destination
+
+ Protocol operation depends on the many adjustable parameters. We support parameters, with their default values, from
+ RFC and parameters that enable/disable protocol features or tune for specific simulation scenarios, such as the max size
+ of send buffer and its timeout value. The full parameter list is in DsrRouting.cc file.
+
+ DSR discovers routes totally on demand. Therefore, our DSR model buffers all packets, while a route request packet (RREQ)
+ is disseminated. We implement a packet buffer in dsr-rsendbuff.cc. The packet queue implements garbage collection of old
+ packets and a queue size limit. When the packet is sent out from the send buffer, it will be queued in maintenance buffer for
+ next hop acknowledgment
+
+ Route Cache implementation support garbage collection of old entries and state machine, defined in standard.
+ It implements as a STL map container. The key is the destination IP address.
+
+ Protocol operation strongly depends on broken link detection mechanism. We implement all the three heuristics.
+    First, we use layer 2 feedback when possible. Link considered to be broken, if frame transmission results in a transmission
+    failure for all retries. This mechanism meant for active links and work much more faster, than first method.
+    Layer 2 feedback implementation relies on TxErrHeader trace source, currently it is supported in AdhocWifiMac only.
+
+    Second, passive acknowledgment should be used whenever possible. The node turns on "promiscuous" receive mode, in which it can receive
+    packet not destined for itself, and when the node assures the delivery of that data packet to its destination, it cancels the passive
+    acknowledgment timer.
+
+    Last, we use network layer acknowledge scheme to notify the receipt of a packet. Route request packet will not
+    be acknowledge or retransmitted.
+
+ Following optional protocol optimizations aren't implemented:
+  - Flow state
+  - First Hop External (F), Last Hop External (L) flags
+  - Handling unknown DSR options
+  - Two types of error headers:
+     1. flow state not supported option
+     2. unsupported option (not going to happen in simulation)
+
+ DSR operates with direct access to IP header, and operates between network and transport layer.
+
+ Implementation changes
+  - The DsrFsHeader has added 3 fields: message type, source id, destination id, and these changes only for post-processing
+      - message type is used to identify the data packet from control packet
+      - source id is used to identify the real source of the data packet since we have to deliver the packet hop-by-hop and the ipv4header
+        is not carrying the real source and destination ip address as needed
+      - destination id is for same reason of above
+
+ Changes:
+   - Route Reply header is not word-aligned in DSR rfc, change it to word-aligned in implementation
+   - DSR works as a shim header between transport and network protocol, it needs its own forwarding mechanism,
+     we are changing the packet transmission to hop-by-hop delivery, so we added two fields in dsr fixed header
+     to notify packet delivery
+     1. message type to notify the type of this packet: data packet or control one
+     2. source id to identify the real source address of this packet
+     3. destination id to identify the real destination
+
+ Current Route Cache implementation:
+   - This implementation used "path cache", which is simple to implement and ensures loop-free
+      - the path cache has automatic expire policy
+      - the cache saves multiple route entries for a certain destination and sort the entries based on hop counts
+      - the MaxEntriesEachDst can be tuned to change the maximum entries saved for a single destination
+      - when adding mulitiple routes for one destination, the route is compared based on hop-count and expire time, the one with less hop count
+        or relatively new route is favored
+   - Future implementation may include "link cache" as another possibility
+
+DSR Instructions
+****************
+
+The following should be kept in mind when running DSR as routing protocol:
+
+* NodeTraversalTime is the time it takes to traverse two neighboring nodes and should be chosen to fit the transmission range
+* PassiveAckTimeout is the time a packet in maintenance buffer wait for passive acknowledgment, normally set as two times of NodeTraversalTime
+* RouteCacheTimeout should be set smaller value when the nodes' velocity become higher. The default value is 300s.
+   
+Helper
+******
+
+To have a node run DSR, the easiest way would be to use the ClickInternetStackHelper
+class in your simulation script. For instance::
+
+  DsrHelper dsr;
+  DsrMainHelper dsrMain;
+  dsrMain.Install (dsr, adhocNodes);
+
+The example scripts inside ``src/dsr/examples/`` demonstrate the use of DSR based nodes
+in different scenarios. The helper source can be found inside ``src/dsr/helper/dsr-main-helper.{h,cc}`` 
+and ``src/dsr/helper/dsr-helper.{h,cc}``
+
+Examples
+********
+
+The example can be found in ``src/dsr/examples/``:
+
+* dsr.cc use DSR as routing protocol within a traditional MANETs environment[3]. 
+
+DSR is also built in the routing comparison case in ``examples/routing/``:
+
+* manet-routing-compare.cc is a comparison case with built in MANET routing protocols and can generate its own results.
+
+Validation
+**********
+
+This model has been tested as follows:
+
+* Unit tests have been written to verify the internals of DSR. This can be found in ``src/dsr/test/dsr-test-suite.cc``. These tests verify whether the methods inside DSR module which deal with packet buffer, headers work correctly.
+* Simulation cases similar to [3] have been tested and have comparable results.
+* manet-routing-compare.cc has been used to compare DSR with three of other routing protocols.
+  
+References
+**********
+
+[1] Link for the original paper: www.monarch.cs.rice.edu/monarch-papers/dsr-chapter00.pdf
+[2] Link for RFC 4728: http://www6.ietf.org/rfc/rfc4728.txt
+[3] Link for the broch's comparison paper: http://www.monarch.cs.rice.edu/monarch-papers/mobicom98.ps
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/examples/dsr.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,221 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+
+#include "ns3/core-module.h"
+#include "ns3/network-module.h"
+#include "ns3/applications-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/config-store-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/internet-module.h"
+#include "ns3/ipv4-list-routing-helper.h"
+#include "ns3/dsr-module.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsrExample");
+
+using namespace ns3;
+
+int main (int argc, char *argv[])
+{
+  //
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+  //
+#if 0
+  LogComponentEnable ("Ipv4L3Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv4L4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("UdpL4Protocol", LOG_LEVEL_ALL);
+  LogComponentEnable ("NetDevice", LOG_LEVEL_ALL);
+  LogComponentEnable ("Ipv4EndPointDemux", LOG_LEVEL_ALL);
+#endif
+
+#if 0
+  LogComponentEnable ("DsrOptions", LOG_LEVEL_ALL);
+  LogComponentEnable ("DsrRouting", LOG_LEVEL_ALL);
+  LogComponentEnable ("DsrOptionHeader", LOG_LEVEL_ALL);
+  LogComponentEnable ("DsrFsHeader", LOG_LEVEL_ALL);
+  LogComponentEnable ("DsrGraReplyTable", LOG_LEVEL_ALL);
+  LogComponentEnable ("DsrSendBuffer", LOG_LEVEL_ALL);
+  LogComponentEnable ("RouteCache", LOG_LEVEL_ALL);
+  LogComponentEnable ("DsrMaintainBuffer", LOG_LEVEL_ALL);
+  LogComponentEnable ("RreqTable", LOG_LEVEL_ALL);
+#endif
+
+  SeedManager::SetSeed (99);
+  SeedManager::SetRun (1);
+
+  double totalTime = 1000.0;
+  double dataStart = 50.0;
+  uint32_t nWifis = 50;
+  uint32_t nSinks = 10;
+  double txp = 8.9048;
+  double pauseTime = 0.0;
+  double nodeSpeed = 20.0;
+  uint32_t packetSize = 64;
+  std::string phyModeControl ("DsssRate11Mbps");
+  std::string phyModeData ("DsssRate11Mbps");
+  std::string rate = "0.512kbps";
+  double ppers = 1.0;
+  /*
+   * Define the DSR parameters
+   */
+  uint32_t m_maxCacheLen = 64;
+  Time m_maxCacheTime = Seconds (30);
+  Time m_nodeTraversalTime = MicroSeconds (2);
+  Time m_passiveAckTimeout = MicroSeconds (4);
+  uint32_t m_maxSendBuffLen = 64;
+  Time m_sendBufferTimeout = Seconds (30);
+  uint32_t m_maxMaintainLen = 50;
+  Time m_maxMaintainTime = Seconds (30);
+  uint32_t m_maintenanceRetries = 2;
+  std::string cacheType ("PathCache");            // PathCache
+  bool enableSubRoute = false;
+
+  //Allow users to override the default parameters and set it to new ones from CommandLine.
+  CommandLine cmd;
+  cmd.AddValue ("MaxCacheLen", "Max route cache length.", m_maxCacheLen);
+  cmd.AddValue ("RouteCacheTimeout", "Max route cache timeout.", m_maxCacheTime);
+  cmd.AddValue ("NodeTraversalTime", "The time it takes to travel to neighboring nodes.", m_nodeTraversalTime);
+  cmd.AddValue ("PassiveAckTimeout", "The time for ack to traversal the two neighboring nodes.", m_passiveAckTimeout);
+  cmd.AddValue ("MaxSendBuffLen", "Maximum number of packets that can be stored.", m_maxSendBuffLen);
+  cmd.AddValue ("MaxSendBuffTime", "Maximum time packets can be queued.", m_sendBufferTimeout);
+  cmd.AddValue ("MaxMaintLen", "Maximum number of packets that can be stored.", m_maxMaintainLen);
+  cmd.AddValue ("MaxMaintTime", "Maximum time packets can be queued.", m_maxMaintainTime);
+  cmd.AddValue ("MaintenanceRetries", "Maximum retransmission retries for maintenance data packet.", m_maintenanceRetries);
+  cmd.AddValue ("CacheType", "route cache type, Default:PathCache", cacheType);
+  cmd.AddValue ("EnableSubRoute", "whether to enable the sub route mechanism, Default:false", enableSubRoute);
+  cmd.Parse (argc, argv);
+
+  NS_LOG_INFO ("Create nodes.");
+  NodeContainer nodes;
+  nodes.Create (nWifis);
+  NetDeviceContainer devices;
+
+  // Fix non-unicast data rate to be the same as that of unicast
+  Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode", StringValue (phyModeData));
+  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2200"));
+  // disable fragmentation
+  Config::SetDefault ("ns3::WifiRemoteStationManager::FragmentationThreshold", StringValue ("2200"));
+
+  NS_LOG_INFO ("Create channels.");
+  WifiHelper wifi;
+  wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
+  YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+  YansWifiChannelHelper wifiChannel;
+  wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
+  wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
+  wifiPhy.SetChannel (wifiChannel.Create ());
+
+  // Add a non-QoS upper mac, and disable rate control
+  NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue (phyModeData),
+                                "ControlMode", StringValue (phyModeControl));
+  wifiPhy.Set ("TxPowerStart", DoubleValue (txp));
+  wifiPhy.Set ("TxPowerEnd", DoubleValue (txp));
+  // Set it to adhoc mode
+  wifiMac.SetType ("ns3::AdhocWifiMac");
+  devices = wifi.Install (wifiPhy, wifiMac, nodes);
+
+  InternetStackHelper internet;
+  DsrMainHelper dsrMain;
+  DsrHelper dsr;
+  dsr.Set ("MaxCacheLen", UintegerValue (m_maxCacheLen));
+  dsr.Set ("RouteCacheTimeout", TimeValue (m_maxCacheTime));
+  dsr.Set ("NodeTraversalTime", TimeValue (m_nodeTraversalTime));
+  dsr.Set ("PassiveAckTimeout", TimeValue (m_passiveAckTimeout));
+  dsr.Set ("MaxSendBuffLen", UintegerValue (m_maxSendBuffLen));
+  dsr.Set ("MaxSendBuffTime", TimeValue (m_sendBufferTimeout));
+  dsr.Set ("MaxMaintLen", UintegerValue (m_maxMaintainLen));
+  dsr.Set ("MaxMaintTime", TimeValue (m_maxMaintainTime));
+  dsr.Set ("MaintenanceRetries", UintegerValue (m_maintenanceRetries));
+  dsr.Set ("EnableSubRoute", BooleanValue (false));
+  dsr.Set ("CacheType", StringValue (cacheType));
+  dsr.Set ("SendBuffInterval", TimeValue (Seconds (50)));
+  internet.Install (nodes);
+  dsrMain.Install (dsr, nodes);
+
+  NS_LOG_INFO ("assigning ip address");
+  Ipv4AddressHelper addressAdhoc;
+  addressAdhoc.SetBase ("10.1.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer adhocInterfaces;
+  adhocInterfaces = addressAdhoc.Assign (devices);
+
+  MobilityHelper mobility;
+
+  ObjectFactory pos;
+  pos.SetTypeId ("ns3::RandomRectanglePositionAllocator");
+  pos.Set ("X", RandomVariableValue (UniformVariable (0.0, 300.0)));
+  pos.Set ("Y", RandomVariableValue (UniformVariable (0.0, 1500.0)));
+  Ptr<PositionAllocator> positionAlloc = pos.Create ()->GetObject<PositionAllocator> ();
+  mobility.SetPositionAllocator (positionAlloc);
+
+  mobility.SetMobilityModel ("ns3::RandomWaypointMobilityModel",
+                             "Speed", RandomVariableValue (ConstantVariable (nodeSpeed)),
+                             "Pause", RandomVariableValue (ConstantVariable (pauseTime)),
+                             "PositionAllocator", PointerValue (positionAlloc));
+  mobility.Install (nodes);
+
+  // many to many application
+  uint16_t port = 9;
+  double randomStartTime = (1 / ppers) / nSinks;     //distributed btw 1s evenly as we are sending 1pkt/s
+
+  for (uint32_t i = 0; i < nSinks; i++)
+    {
+      PacketSinkHelper sink ("ns3::UdpSocketFactory", InetSocketAddress (Ipv4Address::GetAny (), port));
+      ApplicationContainer apps_sink = sink.Install (nodes.Get (i));
+      apps_sink.Start (Seconds (0.0));
+      apps_sink.Stop (Seconds (totalTime));
+
+      OnOffHelper onoff1 ("ns3::UdpSocketFactory", Address (InetSocketAddress (adhocInterfaces.GetAddress (i), port)));
+      onoff1.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+      onoff1.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+      onoff1.SetAttribute ("PacketSize", UintegerValue (packetSize));
+      onoff1.SetAttribute ("DataRate", DataRateValue (DataRate (rate)));
+
+      ApplicationContainer apps1 = onoff1.Install (nodes.Get (i + nSinks));
+      apps1.Start (Seconds (dataStart + i * randomStartTime));
+      apps1.Stop (Seconds (totalTime));
+    }
+
+  AsciiTraceHelper ascii;
+  Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream ("dsrtest.tr");
+  wifiPhy.EnableAsciiAll (stream);
+
+  NS_LOG_INFO ("Run Simulation.");
+  Simulator::Stop (Seconds (totalTime));
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/examples/wscript	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,6 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    obj = bld.create_ns3_program('dsr', ['core', 'network', 'internet', 'wifi', 'dsr'])
+    obj.source = 'dsr.cc'
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/helper/dsr-helper.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,97 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsr-helper.h"
+#include "ns3/node-container.h"
+#include "ns3/node.h"
+#include "ns3/callback.h"
+#include "ns3/ptr.h"
+#include "ns3/log.h"
+#include "ns3/tcp-l4-protocol.h"
+#include "ns3/udp-l4-protocol.h"
+#include "ns3/dsr-options.h"
+#include "ns3/dsr-routing.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/node-list.h"
+#include "ns3/names.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsrHelper");
+
+namespace ns3 {
+
+DsrHelper::DsrHelper ()
+{
+  NS_LOG_FUNCTION (this);
+  m_agentFactory.SetTypeId ("ns3::dsr::DsrRouting");
+}
+
+DsrHelper::DsrHelper (const DsrHelper &o)
+  : m_agentFactory (o.m_agentFactory)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+DsrHelper::~DsrHelper ()
+{
+  NS_LOG_FUNCTION (this);
+}
+
+DsrHelper*
+DsrHelper::Copy (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return new DsrHelper (*this);
+}
+
+Ptr<ns3::dsr::DsrRouting>
+DsrHelper::Create (Ptr<Node> node) const
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<ns3::dsr::DsrRouting> agent = m_agentFactory.Create<ns3::dsr::DsrRouting> ();
+  // deal with the downtargets, install UdpL4Protocol, TcpL4Protocol, Icmpv4L4Protocol
+  Ptr<UdpL4Protocol> udp = node->GetObject<UdpL4Protocol> ();
+  agent->SetDownTarget (udp->GetDownTarget ());
+  udp->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent));
+  Ptr<TcpL4Protocol> tcp = node->GetObject<TcpL4Protocol> ();
+  tcp->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent));
+  Ptr<Icmpv4L4Protocol> icmp = node->GetObject<Icmpv4L4Protocol> ();
+  icmp->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent));
+  node->AggregateObject (agent);
+  return agent;
+}
+
+void
+DsrHelper::Set (std::string name, const AttributeValue &value)
+{
+  m_agentFactory.Set (name, value);
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/helper/dsr-helper.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,85 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_HELPER_H
+#define DSR_HELPER_H
+
+#include "ns3/node-container.h"
+#include "ns3/object-factory.h"
+#include "ns3/dsr-routing.h"
+#include "ns3/node.h"
+#include "ns3/udp-l4-protocol.h"
+#include "ns3/tcp-l4-protocol.h"
+#include "ns3/icmpv4-l4-protocol.h"
+
+namespace ns3 {
+class DsrHelper
+{
+public:
+  /**
+   * Create an DsrHelper that makes life easier for people who want to install
+   * Dsr routing to nodes.
+   */
+  DsrHelper ();
+  ~DsrHelper ();
+  /**
+   * \brief Construct an DsrHelper from another previously initialized instance
+   * (Copy Constructor).
+   */
+  DsrHelper (const DsrHelper &);
+  /**
+   * \internal
+   * \returns pointer to clone of this DsrHelper
+   *
+   * This method is mainly for internal use by the other helpers;
+   * clients are expected to free the dynamic memory allocated by this method
+   */
+  DsrHelper* Copy (void) const;
+  /**
+   * \param node the node on which the routing protocol will run
+   * \returns a newly-created L4 protocol
+   */
+  Ptr<ns3::dsr::DsrRouting> Create (Ptr<Node> node) const;
+  void Set (std::string name, const AttributeValue &value);
+private:
+  /**
+   * \internal
+   * \brief Assignment operator declared private and not implemented to disallow
+   * assignment and prevent the compiler from happily inserting its own.
+   */
+  DsrHelper & operator = (const DsrHelper &o);
+  ObjectFactory m_agentFactory;
+  NodeContainer m_nodes;
+};
+
+} // namespace ns3
+
+#endif // DSR_HELPER_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/helper/dsr-main-helper.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,110 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsr-main-helper.h"
+#include "ns3/dsr-helper.h"
+#include "ns3/dsr-routing.h"
+#include "ns3/dsr-rcache.h"
+#include "ns3/dsr-rreq-table.h"
+#include "ns3/node-list.h"
+#include "ns3/names.h"
+#include "ns3/log.h"
+#include "ns3/ptr.h"
+#include "ns3/node.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsrMainHelper");
+
+namespace ns3 {
+
+DsrMainHelper::DsrMainHelper ()
+  : m_dsrHelper (0)
+{
+  NS_LOG_FUNCTION (this);
+}
+
+DsrMainHelper::DsrMainHelper (const DsrMainHelper &o)
+{
+  NS_LOG_FUNCTION (this);
+  m_dsrHelper = o.m_dsrHelper->Copy ();
+}
+
+DsrMainHelper::~DsrMainHelper ()
+{
+  NS_LOG_FUNCTION (this);
+  delete m_dsrHelper;
+}
+
+DsrMainHelper &
+DsrMainHelper::operator = (const DsrMainHelper &o)
+{
+  if (this == &o)
+    {
+      return *this;
+    }
+  m_dsrHelper = o.m_dsrHelper->Copy ();
+  return *this;
+}
+
+void
+DsrMainHelper::Install (DsrHelper &dsrHelper, NodeContainer nodes)
+{
+  NS_LOG_DEBUG ("Passed node container");
+  delete m_dsrHelper;
+  m_dsrHelper = dsrHelper.Copy ();
+  for (NodeContainer::Iterator i = nodes.Begin (); i != nodes.End (); ++i)
+    {
+      Install (*i);
+    }
+}
+
+void
+DsrMainHelper::Install (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (node);
+  Ptr<ns3::dsr::DsrRouting> dsr = m_dsrHelper->Create (node);
+  Ptr<ns3::dsr::RouteCache> routeCache = CreateObject<ns3::dsr::RouteCache> ();
+  Ptr<ns3::dsr::RreqTable> rreqTable = CreateObject<ns3::dsr::RreqTable> ();
+  dsr->SetRouteCache (routeCache);
+  dsr->SetRequestTable (rreqTable);
+  dsr->SetNode (node);
+  node->AggregateObject (routeCache);
+  node->AggregateObject (rreqTable);
+}
+
+void
+DsrMainHelper::SetDsrHelper (DsrHelper &dsrHelper)
+{
+  NS_LOG_FUNCTION (this);
+  delete m_dsrHelper;
+  m_dsrHelper = dsrHelper.Copy ();
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/helper/dsr-main-helper.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,77 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_MAIN_HELPER_H
+#define DSR_MAIN_HELPER_H
+
+#include "ns3/object-factory.h"
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/dsr-routing.h"
+#include "ns3/dsr-helper.h"
+
+namespace ns3 {
+/**
+ * \brief Helper class that adds DSR routing to nodes.
+ */
+class DsrMainHelper
+{
+public:
+  /**
+   * Create an DsrMainHelper that makes life easier for people who want to install
+   * DSR routing to nodes.
+   */
+  DsrMainHelper ();
+  ~DsrMainHelper ();
+  /**
+   * \brief Construct an DsrMainHelper from another previously initialized instance
+   * (Copy Constructor).
+   */
+  DsrMainHelper (const DsrMainHelper &);
+  void Install (DsrHelper &dsrHelper, NodeContainer nodes);
+  void SetDsrHelper (DsrHelper &dsrHelper);
+  void SetRouteCache (Ptr<dsr::RouteCache> routeCache);
+  void SetRreqTable (Ptr<dsr::RreqTable> rreqTable);
+
+private:
+  void Install (Ptr<Node> node);
+  /**
+   * \internal
+   * \brief Assignment operator declared private and not implemented to disallow
+   * assignment and prevent the compiler from happily inserting its own.
+   */
+  DsrMainHelper &operator = (const DsrMainHelper &o);
+  const DsrHelper *m_dsrHelper;
+};
+
+} // namespace ns3
+
+#endif /* DSR_MAIN_HELPER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-fs-header.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,329 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/header.h"
+#include "dsr-fs-header.h"
+
+namespace ns3 {
+namespace dsr {
+
+NS_LOG_COMPONENT_DEFINE ("DsrFsHeader");
+
+NS_OBJECT_ENSURE_REGISTERED (DsrFsHeader);
+
+TypeId DsrFsHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrFsHeader")
+    .AddConstructor<DsrFsHeader> ()
+    .SetParent<Header> ()
+  ;
+  return tid;
+}
+
+TypeId DsrFsHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrFsHeader::DsrFsHeader ()
+  : m_nextHeader (0),
+    m_messageType (0),
+    m_payloadLen (0),
+    m_sourceId (0),
+    m_destId (0),
+    m_data (0)
+{
+}
+
+DsrFsHeader::~DsrFsHeader ()
+{
+}
+
+void DsrFsHeader::SetNextHeader (uint8_t protocol)
+{
+  m_nextHeader = protocol;
+}
+
+uint8_t DsrFsHeader::GetNextHeader () const
+{
+  return m_nextHeader;
+}
+
+void DsrFsHeader::SetMessageType (uint8_t messageType)
+{
+  m_messageType = messageType;
+}
+
+uint8_t DsrFsHeader::GetMessageType () const
+{
+  return m_messageType;
+}
+
+void DsrFsHeader::SetPayloadLength (uint16_t length)
+{
+  m_payloadLen = length;
+}
+
+uint16_t DsrFsHeader::GetPayloadLength () const
+{
+  return m_payloadLen;
+}
+
+void DsrFsHeader::SetSourceId (uint16_t sourceId)
+{
+  m_sourceId = sourceId;
+}
+
+uint16_t DsrFsHeader::GetSourceId () const
+{
+  return m_sourceId;
+}
+
+void DsrFsHeader::SetDestId (uint16_t destId)
+{
+  m_destId = destId;
+}
+
+uint16_t DsrFsHeader::GetDestId () const
+{
+  return m_destId;
+}
+
+void DsrFsHeader::Print (std::ostream &os) const
+{
+  os
+  << " nextHeader: " << (uint32_t)GetNextHeader () << " messageType: " << (uint32_t)GetMessageType ()
+  << " sourceId: " << (uint32_t)GetSourceId () << " destinationId: " << (uint32_t)GetDestId ()
+  << " length: " << (uint32_t)GetPayloadLength ();
+}
+
+uint32_t DsrFsHeader::GetSerializedSize () const
+{
+  return 8;
+}
+
+void DsrFsHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (m_nextHeader);
+  i.WriteU8 (m_messageType);
+  i.WriteU16 (m_sourceId);
+  i.WriteU16 (m_destId);
+  i.WriteU16 (m_payloadLen);
+
+  i.Write (m_data.PeekData (), m_data.GetSize ());
+}
+
+uint32_t DsrFsHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  m_nextHeader = i.ReadU8 ();
+  m_messageType = i.ReadU8 ();
+  m_sourceId = i.ReadU16 ();
+  m_destId = i.ReadU16 ();
+  m_payloadLen = i.ReadU16 ();
+
+  uint32_t dataLength = GetPayloadLength ();
+  uint8_t data[dataLength];
+  i.Read (data, dataLength);
+
+  if (dataLength > m_data.GetSize ())
+    {
+      m_data.AddAtEnd (dataLength - m_data.GetSize ());
+    }
+  else
+    {
+      m_data.RemoveAtEnd (m_data.GetSize () - dataLength);
+    }
+
+  i = m_data.Begin ();
+  i.Write (data, dataLength);
+
+  return GetSerializedSize ();
+}
+
+DsrOptionField::DsrOptionField (uint32_t optionsOffset)
+  : m_optionData (0),
+    m_optionsOffset (optionsOffset)
+{
+}
+
+DsrOptionField::~DsrOptionField ()
+{
+}
+
+uint32_t DsrOptionField::GetSerializedSize () const
+{
+  DsrOptionHeader::Alignment align = {4,0};
+  return m_optionData.GetSize () + CalculatePad (align);
+}
+
+void DsrOptionField::Serialize (Buffer::Iterator start) const
+{
+  start.Write (m_optionData.Begin (), m_optionData.End ());
+  DsrOptionHeader::Alignment align = {4,0};
+  uint32_t fill = CalculatePad (align);
+  NS_LOG_LOGIC ("fill with " << fill << " bytes padding");
+  switch (fill)
+    {
+    case 0:
+      return;
+    case 1:
+      DsrOptionPad1Header ().Serialize (start);
+      return;
+    default:
+      DsrOptionPadnHeader (fill).Serialize (start);
+      return;
+    }
+}
+
+uint32_t DsrOptionField::Deserialize (Buffer::Iterator start, uint32_t length)
+{
+  uint8_t buf[length];
+  start.Read (buf, length);
+  m_optionData = Buffer ();
+  m_optionData.AddAtEnd (length);
+  m_optionData.Begin ().Write (buf, length);
+  return length;
+}
+
+void DsrOptionField::AddDsrOption (DsrOptionHeader const& option)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  uint32_t pad = CalculatePad (option.GetAlignment ());
+  NS_LOG_LOGIC ("need " << pad << " bytes padding");
+  switch (pad)
+    {
+    case 0:
+      break;       // no padding needed
+    case 1:
+      AddDsrOption (DsrOptionPad1Header ());
+      break;
+    default:
+      AddDsrOption (DsrOptionPadnHeader (pad));
+      break;
+    }
+
+  m_optionData.AddAtEnd (option.GetSerializedSize ());
+  Buffer::Iterator it = m_optionData.End ();
+  it.Prev (option.GetSerializedSize ());
+  option.Serialize (it);
+}
+
+uint32_t DsrOptionField::CalculatePad (DsrOptionHeader::Alignment alignment) const
+{
+  return (alignment.offset - (m_optionData.GetSize () + m_optionsOffset)) % alignment.factor;
+}
+
+uint32_t DsrOptionField::GetDsrOptionsOffset ()
+{
+  return m_optionsOffset;
+}
+
+Buffer DsrOptionField::GetDsrOptionBuffer ()
+{
+  return m_optionData;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrRoutingHeader);
+
+TypeId DsrRoutingHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::DsrRoutingHeader")
+    .AddConstructor<DsrRoutingHeader> ()
+    .SetParent<DsrFsHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrRoutingHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrRoutingHeader::DsrRoutingHeader ()
+  : DsrOptionField (8)
+{
+}
+
+DsrRoutingHeader::~DsrRoutingHeader ()
+{
+}
+
+void DsrRoutingHeader::Print (std::ostream &os) const
+{
+  os
+  << " nextHeader: " << (uint32_t)GetNextHeader () << " messageType: " << (uint32_t)GetMessageType ()
+  << " sourceId: " << (uint32_t)GetSourceId () << " destinationId: " << (uint32_t)GetDestId ()
+  << " length: " << (uint32_t)GetPayloadLength ();
+}
+
+uint32_t DsrRoutingHeader::GetSerializedSize () const
+{
+  // 8 bytes is the DsrFsHeader length
+  return 8 + DsrOptionField::GetSerializedSize ();
+}
+
+void DsrRoutingHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetNextHeader ());
+  i.WriteU8 (GetMessageType ());
+  i.WriteU16 (GetSourceId ());
+  i.WriteU16 (GetDestId ());
+  i.WriteU16 (GetPayloadLength ());
+
+  DsrOptionField::Serialize (i);
+}
+
+uint32_t DsrRoutingHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetNextHeader (i.ReadU8 ());
+  SetMessageType (i.ReadU8 ());
+  SetSourceId (i.ReadU16 ());
+  SetDestId (i.ReadU16 ());
+  SetPayloadLength (i.ReadU16 ());
+
+  DsrOptionField::Deserialize (i, GetPayloadLength ());
+
+  return GetSerializedSize ();
+}
+
+}  /* namespace dsr */
+}  /* namespace ns3 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-fs-header.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,339 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_FS_HEADER_H
+#define DSR_FS_HEADER_H
+
+#include <vector>
+#include <list>
+#include <ostream>
+
+#include "ns3/header.h"
+#include "ns3/ipv4-address.h"
+#include "dsr-option-header.h"
+
+namespace ns3 {
+namespace dsr {
+/**
+ * \class DsrHeader
+ * \brief Header for Dsr Routing.
+ */
+
+/**
+* \ingroup dsr
+* \brief Dsr fixed size header Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Next Header |F|     Reservd    |       Payload Length       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Options                           |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+/**
+* \ingroup dsr
+* \brief The modified version of Dsr fixed size header Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Next Header |F|  Message Type  |       Payload Length       |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |             Source Id           |            Dest Id         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Options                           |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+enum DsrMessageType
+{
+  DSR_CONTROL_PACKET = 1,
+  DSR_DATA_PACKET = 2
+};
+
+class DsrFsHeader : public Header
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrFsHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrFsHeader ();
+  /**
+   * \brief Set the "Next header" field.
+   * \param nextHeader the next header number
+   */
+  void SetNextHeader (uint8_t protocol);
+  /**
+   * \brief Get the next header.
+   * \return the next header number
+   */
+  uint8_t GetNextHeader () const;
+  /**
+   * brief Set the message type of the header.
+   * \param message type the message type of the header
+   */
+  void SetMessageType (uint8_t messageType);
+  /**
+   * brief Get the message type of the header.
+   * \return message type the message type of the header
+   */
+  uint8_t GetMessageType () const;
+  /**
+   * brief Set the source id of the header.
+   * \param source id the source id of the header
+   */
+  void SetSourceId (uint16_t sourceId);
+  /**
+   * brief Get the source id of the header.
+   * \return source id the source id of the header
+   */
+  uint16_t GetSourceId () const;
+  /**
+   * brief Set the dest id of the header.
+   * \param dest id the dest id of the header
+   */
+  void SetDestId (uint16_t destId);
+  /**
+   * brief Get the dest id of the header.
+   * \return dest id the dest id of the header
+   */
+  uint16_t GetDestId () const;
+  /**
+   * brief Set the payload length of the header.
+   * \param length the payload length of the header in bytes
+   */
+  void SetPayloadLength (uint16_t length);
+  /**
+   * \brief Get the payload length of the header.
+   * \return the payload length of the header
+   */
+  uint16_t GetPayloadLength () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+
+private:
+  /**
+   * \brief The "next header" field.
+   */
+  uint8_t m_nextHeader;
+  /**
+   * \brief The type of the message.
+   */
+  uint8_t m_messageType;
+  /**
+   * \brief The "payload length" field.
+   */
+  uint16_t m_payloadLen;
+  /**
+   * \brief The source node id
+   */
+  uint16_t m_sourceId;
+  /**
+   * \brief The destination node id
+   */
+  uint16_t m_destId;
+  /**
+   * \brief The data of the extension.
+   */
+  Buffer m_data;
+};
+
+/**
+ * \class OptionField
+ * \brief Option field for an DsrFsHeader
+ * Enables adding options to an DsrFsHeader
+ *
+ * Implementor's note: Make sure to add the result of
+ * OptionField::GetSerializedSize () to your DsrFsHeader::GetSerializedSize ()
+ * return value. Call OptionField::Serialize and OptionField::Deserialize at the
+ * end of your corresponding DsrFsHeader methods.
+ */
+class DsrOptionField
+{
+public:
+  /**
+   * \brief Constructor.
+   * \param optionsOffset option offset
+   */
+  DsrOptionField (uint32_t optionsOffset);
+  /**
+   * \brief Destructor.
+   */
+  ~DsrOptionField ();
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize all added options.
+   * \param start Buffer iterator
+   */
+  void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \param length length
+   * \return size of the packet
+   */
+  uint32_t Deserialize (Buffer::Iterator start, uint32_t length);
+  /**
+   * \brief Serialize the option, prepending pad1 or padn option as necessary
+   * \param option the option header to serialize
+   */
+  void AddDsrOption (DsrOptionHeader const& option);
+  /**
+   * \brief Get the offset where the options begin, measured from the start of
+   * the extension header.
+   * \return the offset from the start of the extension header
+   */
+  uint32_t GetDsrOptionsOffset ();
+  /**
+   * \brief Get the buffer.
+   * \return buffer
+   */
+  Buffer GetDsrOptionBuffer ();
+
+private:
+  /**
+   * \brief Calculate padding.
+   * \param alignment alignment
+   */
+  uint32_t CalculatePad (DsrOptionHeader::Alignment alignment) const;
+  /**
+   * \brief Data payload.
+   */
+  Buffer m_optionData;
+  /**
+   * \brief Offset.
+   */
+  uint32_t m_optionsOffset;
+};
+
+/**
+ * \class DsrRoutingHeader
+ * \brief Header of Dsr Routing
+ */
+class DsrRoutingHeader : public DsrFsHeader,
+                         public DsrOptionField
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrRoutingHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrRoutingHeader ();
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+};
+
+static inline std::ostream & operator<< (std::ostream& os, const DsrRoutingHeader & dsr)
+{
+  dsr.Print (os);
+  return os;
+}
+
+}  // namespace dsr
+}  // namespace ns3
+
+#endif /* DSR_FS_HEADER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-gratuitous-reply-table.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,96 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsr-gratuitous-reply-table.h"
+#include "ns3/log.h"
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("DsrGraReplyTable");
+
+namespace ns3 {
+namespace dsr {
+
+NS_OBJECT_ENSURE_REGISTERED (GraReply);
+
+TypeId GraReply::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::GraReply")
+    .SetParent<Object> ()
+    .AddConstructor<GraReply> ()
+  ;
+  return tid;
+}
+
+GraReply::GraReply ()
+{
+}
+
+GraReply::~GraReply ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+bool
+GraReply::FindAndUpdate (Ipv4Address replyTo, Ipv4Address replyFrom, Time gratReplyHoldoff)
+{
+  Purge ();  // purge the gratuitous reply table
+  for (std::vector<GraReplyEntry>::iterator i = m_graReply.begin ();
+       i != m_graReply.end (); ++i)
+    {
+      if ((i->m_replyTo == replyTo) && (i->m_hearFrom == replyFrom))
+        {
+          NS_LOG_DEBUG ("Update the reply to ip address if found the gratuitous reply entry");
+          i->m_gratReplyHoldoff = std::max (gratReplyHoldoff + Simulator::Now (), i->m_gratReplyHoldoff);
+          return true;
+        }
+    }
+  return false;
+}
+
+bool
+GraReply::AddEntry (GraReplyEntry & graTableEntry)
+{
+  m_graReply.push_back (graTableEntry);
+  return true;
+}
+
+void
+GraReply::Purge ()
+{
+  /*
+   * Purge the expired gratuitous reply entries
+   */
+  m_graReply.erase (remove_if (m_graReply.begin (), m_graReply.end (),
+                               IsExpired ()), m_graReply.end ());
+}
+
+} // namespace dsr
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-gratuitous-reply-table.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,122 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_GRATUITOUS_REPLY_TABLE_H
+#define DSR_GRATUITOUS_REPLY_TABLE_H
+
+#include "ns3/simulator.h"
+#include "ns3/timer.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/callback.h"
+#include <vector>
+
+namespace ns3 {
+namespace dsr {
+/*
+ * The gratuitous table entries, it maintains the already sent gratuitous route reply entries.
+ * When the node "promiscuously" received a packet destined for other nodes, and inferred a shorter
+ * route for the data packet, it will construct a route reply and send back to the source
+ */
+struct GraReplyEntry
+{
+  Ipv4Address m_replyTo;
+  Ipv4Address m_hearFrom;
+  Time m_gratReplyHoldoff;
+
+  GraReplyEntry (Ipv4Address t, Ipv4Address f, Time h)
+    : m_replyTo (t),
+      m_hearFrom (f),
+      m_gratReplyHoldoff (h)
+  {
+  }
+};
+/**
+ * \ingroup dsr
+ * \brief maintain the gratuitous reply
+ */
+class GraReply  : public Object
+{
+public:
+  // / c-tor
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Constructor.
+   */
+  GraReply ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~GraReply ();
+  // / Set the gratuitous reply table size
+  void SetGraTableSize (uint32_t g)
+  {
+    GraReplyTableSize = g;
+  }
+  // / Get the gratuitous reply table size
+  uint32_t GetGraTableSize () const
+  {
+    return GraReplyTableSize;
+  }
+  // / Add a new gratuitous reply entry
+  bool AddEntry (GraReplyEntry & graTableEntry);
+  // / Update the route entry if found, create a new one if not
+  bool FindAndUpdate (Ipv4Address replyTo, Ipv4Address replyFrom, Time gratReplyHoldoff);
+  // / Remove all expired entries
+  void Purge ();
+  // / Remove all entries
+  void Clear ()
+  {
+    m_graReply.clear ();
+  }
+
+private:
+  // / Vector of entries
+  std::vector<GraReplyEntry> m_graReply;
+  // / The max # of gratuitous reply entries to hold
+  uint32_t GraReplyTableSize;
+
+  // / Check if the entry is expired or not
+  struct IsExpired
+  {
+    bool operator() (const struct GraReplyEntry & b) const
+    {
+      return (b.m_gratReplyHoldoff < Simulator::Now ());
+    }
+  };
+};
+}  // namespace dsr
+}  // namespace ns3
+
+#endif /* DSR_GRATUITOUS_REPLY_TABLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-maintain-buff.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,189 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsr-maintain-buff.h"
+#include <algorithm>
+#include <functional>
+#include "ns3/ipv4-route.h"
+#include "ns3/socket.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsrMaintainBuffer");
+
+namespace ns3 {
+namespace dsr {
+
+uint32_t
+MaintainBuffer::GetSize ()
+{
+  Purge ();
+  return m_maintainBuffer.size ();
+}
+
+bool
+MaintainBuffer::Enqueue (MaintainBuffEntry & entry)
+{
+  Purge ();
+  for (std::vector<MaintainBuffEntry>::const_iterator i = m_maintainBuffer.begin (); i
+       != m_maintainBuffer.end (); ++i)
+    {
+      NS_LOG_INFO ("nexthop " << i->GetNextHop () << " " << entry.GetNextHop () << " our add " << i->GetOurAdd () << " " << entry.GetOurAdd ()
+                              << " src " << i->GetSrc () << " " << entry.GetSrc () << " dst " << i->GetDst () << " " << entry.GetDst ()
+                              << " ackId " << i->GetAckId () << " " << entry.GetAckId () << " SegsLeft " << (uint32_t)i->GetSegsLeft () << " " << (uint32_t)entry.GetSegsLeft ()
+                   );
+
+      if ((i->GetNextHop () == entry.GetNextHop ()) && (i->GetOurAdd () == entry.GetOurAdd ()) && (i->GetSrc () == entry.GetSrc ())
+          && (i->GetDst () == entry.GetDst ()) && (i->GetAckId () == entry.GetAckId ()) && (i->GetSegsLeft () == entry.GetSegsLeft ()))
+        {
+          NS_LOG_DEBUG ("Same maintenance entry found");
+          return false;
+        }
+    }
+
+  entry.SetExpireTime (m_maintainBufferTimeout);
+  if (m_maintainBuffer.size () >= m_maxLen)
+    {
+      NS_LOG_DEBUG ("Drop the most aged packet");
+      m_maintainBuffer.erase (m_maintainBuffer.begin ());        // Drop the most aged packet
+    }
+  m_maintainBuffer.push_back (entry);
+  return true;
+}
+
+void
+MaintainBuffer::DropPacketWithNextHop (Ipv4Address nextHop)
+{
+  NS_LOG_FUNCTION (this << nextHop);
+  Purge ();
+  NS_LOG_DEBUG ("Drop Packet With next hop " << nextHop);
+  m_maintainBuffer.erase (std::remove_if (m_maintainBuffer.begin (), m_maintainBuffer.end (),
+                                          std::bind2nd (std::ptr_fun (MaintainBuffer::IsEqual), nextHop)), m_maintainBuffer.end ());
+}
+
+bool
+MaintainBuffer::Dequeue (Ipv4Address nextHop, MaintainBuffEntry & entry)
+{
+  Purge ();
+  for (std::vector<MaintainBuffEntry>::iterator i = m_maintainBuffer.begin (); i != m_maintainBuffer.end (); ++i)
+    {
+      if (i->GetNextHop () == nextHop)
+        {
+          entry = *i;
+          m_maintainBuffer.erase (i);
+          NS_LOG_DEBUG ("Packet size while dequeuing " << entry.GetPacket ()->GetSize ());
+          return true;
+        }
+    }
+  return false;
+}
+
+bool
+MaintainBuffer::Find (Ipv4Address nextHop)
+{
+  for (std::vector<MaintainBuffEntry>::const_iterator i = m_maintainBuffer.begin (); i
+       != m_maintainBuffer.end (); ++i)
+    {
+      if (i->GetNextHop () == nextHop)
+        {
+          NS_LOG_DEBUG ("Found the packet in maintenance buffer");
+          return true;
+        }
+    }
+  return false;
+}
+
+bool
+MaintainBuffer::AllEqual (MaintainBuffEntry & entry)
+{
+  for (std::vector<MaintainBuffEntry>::iterator i = m_maintainBuffer.begin (); i
+       != m_maintainBuffer.end (); ++i)
+    {
+
+      NS_LOG_DEBUG ("nexthop " << i->GetNextHop () << " " << entry.GetNextHop () << " our address " << i->GetOurAdd () << " " << entry.GetOurAdd ()
+                               << " src " << i->GetSrc () << " " << entry.GetSrc () << " dst " << i->GetDst () << " " << entry.GetDst ()
+                               << " ackId " << i->GetAckId () << " " << entry.GetAckId ());
+
+      if ((i->GetOurAdd () == entry.GetOurAdd ()) && (i->GetNextHop () == entry.GetNextHop ())
+          && (i->GetSrc () == entry.GetSrc ()) && (i->GetDst () == entry.GetDst ())
+          && (i->GetAckId () == entry.GetAckId ()))
+        {
+          m_maintainBuffer.erase (i);   // Erase the same maintain buffer entry for the received packet
+          return true;
+        }
+    }
+  return false;
+}
+
+bool
+MaintainBuffer::PromiscEqual (MaintainBuffEntry & entry)
+{
+  for (std::vector<MaintainBuffEntry>::iterator i = m_maintainBuffer.begin (); i
+       != m_maintainBuffer.end (); ++i)
+    {
+
+      NS_LOG_DEBUG ("nexthop " << i->GetNextHop () << " " << entry.GetNextHop () << " our address " << i->GetOurAdd () << " " << entry.GetOurAdd ()
+                               << " src " << i->GetSrc () << " " << entry.GetSrc () << " dst " << i->GetDst () << " " << entry.GetDst ()
+                               << " SegsLeft " << (uint32_t)i->GetSegsLeft () << " " << (uint32_t)entry.GetSegsLeft ()
+                    );
+
+      if ((i->GetOurAdd () == entry.GetOurAdd ()) && (i->GetNextHop () == entry.GetNextHop ())
+          && (i->GetSrc () == entry.GetSrc ()) && (i->GetDst () == entry.GetDst ())
+          && (i->GetSegsLeft () == entry.GetSegsLeft ())
+          )
+        {
+          m_maintainBuffer.erase (i);   // Erase the same maintain buffer entry for the promisc received packet
+          return true;
+        }
+    }
+  return false;
+}
+
+struct IsExpired
+{
+  bool
+  operator() (MaintainBuffEntry const & e) const
+  {
+    // NS_LOG_DEBUG("Expire time for packet in req queue: "<<e.GetExpireTime ());
+    return (e.GetExpireTime () < Seconds (0));
+  }
+};
+
+void
+MaintainBuffer::Purge ()
+{
+  NS_LOG_DEBUG ("Purging Maintenance Buffer");
+  IsExpired pred;
+  m_maintainBuffer.erase (std::remove_if (m_maintainBuffer.begin (), m_maintainBuffer.end (), pred),
+                          m_maintainBuffer.end ());
+}
+
+}  // namespace dsr
+}  // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-maintain-buff.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,258 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_MAINTAIN_BUFF_H
+#define DSR_MAINTAIN_BUFF_H
+
+#include <vector>
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/simulator.h"
+#include "ns3/ipv4-header.h"
+#include "dsr-option-header.h"
+
+
+namespace ns3 {
+namespace dsr {
+/*
+ * The maintenance buffer is responsible for maintaining packet next hop delivery
+ * The data packet is saved in maintenance buffer whenever the data packet is sent out of send buffer
+ */
+
+/*
+ * The packet timer key for controlling data packet retransmission
+ */
+struct PacketKey
+{
+  uint16_t m_ackId;
+  Ipv4Address m_ourAdd;
+  Ipv4Address m_nextHop;
+  Ipv4Address m_source;
+  Ipv4Address m_destination;
+  uint8_t m_segsLeft;
+
+  /**
+   * Compare maintain Buffer entries
+   * \return true if equal
+   */
+  bool operator < (PacketKey const & o) const
+  {
+    return ((m_ackId < o.m_ackId) && (m_ourAdd < o.m_ourAdd) && (m_nextHop < o.m_nextHop) && (m_source < o.m_source)
+            && (m_destination < o.m_destination) && (m_segsLeft < o.m_segsLeft)
+            );
+  }
+};
+/**
+ * \ingroup dsr
+ * \brief DSR Maintain Buffer Entry
+ */
+class MaintainBuffEntry
+{
+public:
+  // / c-tor
+  MaintainBuffEntry (Ptr<const Packet> pa = 0, Ipv4Address us = Ipv4Address (),
+                     Ipv4Address n = Ipv4Address (), Ipv4Address s = Ipv4Address (), Ipv4Address dst = Ipv4Address (),
+                     uint16_t ackId = 0, uint8_t segs = 0, Time exp = Simulator::Now ())
+    : m_packet (pa),
+      m_ourAdd (us),
+      m_nextHop (n),
+      m_src (s),
+      m_dst (dst),
+      m_ackId (ackId),
+      m_segsLeft (segs),
+      m_isPassive (true),
+      m_expire (exp + Simulator::Now ())
+  {
+  }
+
+  // /\name Fields
+  // \{
+  Ptr<const Packet> GetPacket () const
+  {
+    return m_packet;
+  }
+  void SetPacket (Ptr<const Packet> p)
+  {
+    m_packet = p;
+  }
+  Ipv4Address GetOurAdd () const
+  {
+    return m_ourAdd;
+  }
+  void SetOurAdd (Ipv4Address us)
+  {
+    m_ourAdd = us;
+  }
+  Ipv4Address GetNextHop () const
+  {
+    return m_nextHop;
+  }
+  void SetNextHop (Ipv4Address n)
+  {
+    m_nextHop = n;
+  }
+  Ipv4Address GetDst () const
+  {
+    return m_dst;
+  }
+  void SetDst (Ipv4Address n)
+  {
+    m_dst = n;
+  }
+  Ipv4Address GetSrc () const
+  {
+    return m_src;
+  }
+  void SetSrc (Ipv4Address s)
+  {
+    m_src = s;
+  }
+  uint16_t GetAckId () const
+  {
+    return m_ackId;
+  }
+  void SetAckId (uint16_t ackId)
+  {
+    m_ackId = ackId;
+  }
+  uint8_t GetSegsLeft () const
+  {
+    return m_segsLeft;
+  }
+  void SetSegsLeft (uint8_t segs)
+  {
+    m_segsLeft = segs;
+  }
+  bool GetPassive () const
+  {
+    return m_isPassive;
+  }
+  void SetPassive (bool pa)
+  {
+    m_isPassive = pa;
+  }
+  void SetExpireTime (Time exp)
+  {
+    m_expire = exp + Simulator::Now ();
+  }
+  Time GetExpireTime () const
+  {
+    return m_expire - Simulator::Now ();
+  }
+  // \}
+private:
+  // / Data packet
+  Ptr<const Packet> m_packet;
+  // / our own ip address
+  Ipv4Address m_ourAdd;
+  // / Next hop Ip address
+  Ipv4Address m_nextHop;
+  // / The source address
+  Ipv4Address m_src;
+  // / The destination address
+  Ipv4Address m_dst;
+  // / The data ack id
+  uint16_t m_ackId;
+  // / The ipv4 id
+  uint16_t m_id;
+  // / The segments left field
+  uint8_t m_segsLeft;
+  // / The fragment offset of ipv4 header
+  uint16_t m_fragment;
+  // / if the ack metric is passive ack or not
+  bool m_isPassive;
+  // / Expire time for queue entry
+  Time m_expire;
+};
+/**
+ * \ingroup dsr
+ * \brief DSR maintain buffer
+ */
+/************************************************************************************************************************/
+class MaintainBuffer
+{
+public:
+  // / Default c-tor
+  MaintainBuffer ()
+  {
+  }
+  // / Push entry in queue, if there is no entry with the same packet and destination address in queue.
+  bool Enqueue (MaintainBuffEntry & entry);
+  // / Return first found (the earliest) entry for given destination
+  bool Dequeue (Ipv4Address dst, MaintainBuffEntry & entry);
+  // / Remove all packets with destination IP address dst
+  void DropPacketWithNextHop (Ipv4Address nextHop);
+  // / Finds whether a packet with destination dst exists in the queue
+  bool Find (Ipv4Address nextHop);
+  // / Number of entries
+  uint32_t GetSize ();
+  // /\name Fields
+  // \{
+  uint32_t GetMaxQueueLen () const
+  {
+    return m_maxLen;
+  }
+  void SetMaxQueueLen (uint32_t len)
+  {
+    m_maxLen = len;
+  }
+  Time GetMaintainBufferTimeout () const
+  {
+    return m_maintainBufferTimeout;
+  }
+  void SetMaintainBufferTimeout (Time t)
+  {
+    m_maintainBufferTimeout = t;
+  }
+  // / Verify if the maintain buffer entry is the same in every field for network ack
+  bool AllEqual (MaintainBuffEntry & entry);
+  // / Verify if the maintain buffer entry is the same in every field for promiscuous ack
+  bool PromiscEqual (MaintainBuffEntry & entry);
+  // \}
+
+private:
+  // / The vector of maintain buffer entries
+  std::vector<MaintainBuffEntry> m_maintainBuffer;
+  // / Remove all expired entries
+  void Purge ();
+  // / The maximum number of packets that we allow a routing protocol to buffer.
+  uint32_t m_maxLen;
+  // / The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
+  Time m_maintainBufferTimeout;
+  // / Verify if the maintain buffer is equal or not
+  static bool IsEqual (MaintainBuffEntry en, const Ipv4Address nextHop)
+  {
+    return (en.GetNextHop () == nextHop);
+  }
+};
+/*******************************************************************************************************************************/
+} // namespace dsr
+} // namespace ns3
+#endif /* DSR_MAINTAIN_BUFF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-option-header.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,1194 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "ns3/assert.h"
+#include "ns3/log.h"
+#include "ns3/header.h"
+#include "dsr-option-header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/address-utils.h"
+#include "ns3/packet.h"
+#include "ns3/enum.h"
+
+
+namespace ns3 {
+namespace dsr {
+NS_LOG_COMPONENT_DEFINE ("DsrOptionHeader");
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionHeader);
+
+TypeId DsrOptionHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionHeader")
+    .AddConstructor<DsrOptionHeader> ()
+    .SetParent<Header> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionHeader::DsrOptionHeader ()
+  : m_type (0),
+    m_length (0)
+{
+}
+
+DsrOptionHeader::~DsrOptionHeader ()
+{
+}
+
+void DsrOptionHeader::SetType (uint8_t type)
+{
+  m_type = type;
+}
+
+uint8_t DsrOptionHeader::GetType () const
+{
+  return m_type;
+}
+
+void DsrOptionHeader::SetLength (uint8_t length)
+{
+  m_length = length;
+}
+
+uint8_t DsrOptionHeader::GetLength () const
+{
+  return m_length;
+}
+
+void DsrOptionHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)m_type << " length = " << (uint32_t)m_length << " )";
+}
+
+uint32_t DsrOptionHeader::GetSerializedSize () const
+{
+  return m_length + 2;
+}
+
+void DsrOptionHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (m_type);
+  i.WriteU8 (m_length);
+  i.Write (m_data.Begin (), m_data.End ());
+}
+
+uint32_t DsrOptionHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  m_type = i.ReadU8 ();
+  m_length = i.ReadU8 ();
+
+  m_data = Buffer ();
+  m_data.AddAtEnd (m_length);
+  Buffer::Iterator dataStart = i;
+  i.Next (m_length);
+  Buffer::Iterator dataEnd = i;
+  m_data.Begin ().Write (dataStart, dataEnd);
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionHeader::GetAlignment () const
+{
+  Alignment retVal = { 1, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionPad1Header);
+
+TypeId DsrOptionPad1Header::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionPad1Header")
+    .AddConstructor<DsrOptionPad1Header> ()
+    .SetParent<DsrOptionHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionPad1Header::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionPad1Header::DsrOptionPad1Header ()
+{
+  SetType (224);
+}
+
+DsrOptionPad1Header::~DsrOptionPad1Header ()
+{
+}
+
+void DsrOptionPad1Header::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " )";
+}
+
+uint32_t DsrOptionPad1Header::GetSerializedSize () const
+{
+  return 1;
+}
+
+void DsrOptionPad1Header::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+}
+
+uint32_t DsrOptionPad1Header::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionPadnHeader);
+
+TypeId DsrOptionPadnHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionPadnHeader")
+    .AddConstructor<DsrOptionPadnHeader> ()
+    .SetParent<DsrOptionHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionPadnHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionPadnHeader::DsrOptionPadnHeader (uint32_t pad)
+{
+  SetType (0);
+  NS_ASSERT_MSG (pad >= 2, "PadN must be at least 2 bytes long");
+  SetLength (pad - 2);
+}
+
+DsrOptionPadnHeader::~DsrOptionPadnHeader ()
+{
+}
+
+void DsrOptionPadnHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << " )";
+}
+
+uint32_t DsrOptionPadnHeader::GetSerializedSize () const
+{
+  return GetLength () + 2;
+}
+
+void DsrOptionPadnHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+
+  for (int padding = 0; padding < GetLength (); padding++)
+    {
+      i.WriteU8 (0);
+    }
+}
+
+uint32_t DsrOptionPadnHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+
+  return GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRreqHeader);
+
+TypeId DsrOptionRreqHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRreqHeader")
+    .AddConstructor<DsrOptionRreqHeader> ()
+    .SetParent<DsrOptionHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionRreqHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionRreqHeader::DsrOptionRreqHeader ()
+  : m_ipv4Address (0)
+{
+  SetType (1);
+  SetLength (6 + m_ipv4Address.size () * 4);
+}
+
+DsrOptionRreqHeader::~DsrOptionRreqHeader ()
+{
+}
+
+void DsrOptionRreqHeader::SetNumberAddress (uint8_t n)
+{
+  m_ipv4Address.clear ();
+  m_ipv4Address.assign (n, Ipv4Address (""));
+}
+
+Ipv4Address DsrOptionRreqHeader::GetTarget ()
+{
+  return m_target;
+}
+
+void DsrOptionRreqHeader::SetTarget (Ipv4Address target)
+{
+  m_target = target;
+}
+
+void DsrOptionRreqHeader::AddNodeAddress (Ipv4Address ipv4)
+{
+  m_ipv4Address.push_back (ipv4);
+  SetLength (6 + m_ipv4Address.size () * 4);
+}
+
+void DsrOptionRreqHeader::SetNodesAddress (std::vector<Ipv4Address> ipv4Address)
+{
+  m_ipv4Address = ipv4Address;
+  SetLength (6 + m_ipv4Address.size () * 4);
+}
+
+std::vector<Ipv4Address> DsrOptionRreqHeader::GetNodesAddresses () const
+{
+  return m_ipv4Address;
+}
+
+uint32_t DsrOptionRreqHeader::GetNodesNumber () const
+{
+  return m_ipv4Address.size ();
+}
+
+void DsrOptionRreqHeader::SetNodeAddress (uint8_t index, Ipv4Address addr)
+{
+  m_ipv4Address.at (index) = addr;
+}
+
+Ipv4Address DsrOptionRreqHeader::GetNodeAddress (uint8_t index) const
+{
+  return m_ipv4Address.at (index);
+}
+
+void DsrOptionRreqHeader::SetId (uint16_t identification)
+{
+  m_identification = identification;
+}
+
+uint16_t DsrOptionRreqHeader::GetId () const
+{
+  return m_identification;
+}
+
+void DsrOptionRreqHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << "";
+
+  for (std::vector<Ipv4Address>::const_iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      os << *it << " ";
+    }
+
+  os << ")";
+}
+
+uint32_t DsrOptionRreqHeader::GetSerializedSize () const
+{
+  return 8 + m_ipv4Address.size () * 4;
+}
+
+void DsrOptionRreqHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  uint8_t buff[4];
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteHtonU16 (m_identification);
+  WriteTo (i, m_target);
+
+  for (VectorIpv4Address_t::const_iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      it->Serialize (buff);
+      i.Write (buff, 4);
+    }
+}
+
+uint32_t DsrOptionRreqHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t buff[4];
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  m_identification = i.ReadNtohU16 ();
+  ReadFrom (i, m_target);
+
+  uint8_t index = 0;
+  for (std::vector<Ipv4Address>::iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      i.Read (buff, 4);
+      m_address = it->Deserialize (buff);
+      SetNodeAddress (index, m_address);
+      ++index;
+    }
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionRreqHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRrepHeader);
+
+TypeId DsrOptionRrepHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRrepHeader")
+    .AddConstructor<DsrOptionRrepHeader> ()
+    .SetParent<DsrOptionHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionRrepHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionRrepHeader::DsrOptionRrepHeader ()
+  : m_ipv4Address (0)
+{
+  SetType (2);
+  SetLength (2 + m_ipv4Address.size () * 4);
+}
+
+DsrOptionRrepHeader::~DsrOptionRrepHeader ()
+{
+}
+
+void DsrOptionRrepHeader::SetNumberAddress (uint8_t n)
+{
+  m_ipv4Address.clear ();
+  m_ipv4Address.assign (n, Ipv4Address (""));
+}
+
+void DsrOptionRrepHeader::SetNodesAddress (std::vector<Ipv4Address> ipv4Address)
+{
+  m_ipv4Address = ipv4Address;
+  SetLength (2 + m_ipv4Address.size () * 4);
+}
+
+std::vector<Ipv4Address> DsrOptionRrepHeader::GetNodesAddress () const
+{
+  return m_ipv4Address;
+}
+
+void DsrOptionRrepHeader::SetNodeAddress (uint8_t index, Ipv4Address addr)
+{
+  m_ipv4Address.at (index) = addr;
+}
+
+Ipv4Address DsrOptionRrepHeader::GetNodeAddress (uint8_t index) const
+{
+  return m_ipv4Address.at (index);
+}
+
+Ipv4Address DsrOptionRrepHeader::GetTargetAddress (std::vector<Ipv4Address> ipv4Address) const
+{
+  return m_ipv4Address.at (ipv4Address.size () - 1);
+}
+
+void DsrOptionRrepHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << "";
+
+  for (std::vector<Ipv4Address>::const_iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      os << *it << " ";
+    }
+
+  os << ")";
+}
+
+uint32_t DsrOptionRrepHeader::GetSerializedSize () const
+{
+  return 4 + m_ipv4Address.size () * 4;
+}
+
+void DsrOptionRrepHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  uint8_t buff[4];
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU8 (0);
+  i.WriteU8 (0);
+
+  for (VectorIpv4Address_t::const_iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      it->Serialize (buff);
+      i.Write (buff, 4);
+    }
+}
+
+uint32_t DsrOptionRrepHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t buff[4];
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  i.ReadU8 ();
+  i.ReadU8 ();
+
+  uint8_t index = 0;
+  for (std::vector<Ipv4Address>::iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      i.Read (buff, 4);
+      m_address = it->Deserialize (buff);
+      SetNodeAddress (index, m_address);
+      ++index;
+    }
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionRrepHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionSRHeader);
+
+TypeId DsrOptionSRHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionSRHeader")
+    .AddConstructor<DsrOptionSRHeader> ()
+    .SetParent<DsrOptionHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionSRHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionSRHeader::DsrOptionSRHeader ()
+  : m_segmentsLeft (0),
+    m_ipv4Address (0)
+{
+  SetType (96);
+  SetLength (2 + m_ipv4Address.size () * 4);
+}
+
+DsrOptionSRHeader::~DsrOptionSRHeader ()
+{
+}
+
+void DsrOptionSRHeader::SetSegmentsLeft (uint8_t segmentsLeft)
+{
+  m_segmentsLeft = segmentsLeft;
+}
+
+uint8_t DsrOptionSRHeader::GetSegmentsLeft () const
+{
+  return m_segmentsLeft;
+}
+
+void DsrOptionSRHeader::SetSalvage (uint8_t salvage)
+{
+  m_salvage = salvage;
+}
+
+uint8_t DsrOptionSRHeader::GetSalvage () const
+{
+  return m_salvage;
+}
+
+void DsrOptionSRHeader::SetNumberAddress (uint8_t n)
+{
+  m_ipv4Address.clear ();
+  m_ipv4Address.assign (n, Ipv4Address (""));
+}
+
+void DsrOptionSRHeader::SetNodesAddress (std::vector<Ipv4Address> ipv4Address)
+{
+  m_ipv4Address = ipv4Address;
+  SetLength (2 + m_ipv4Address.size () * 4);
+}
+
+std::vector<Ipv4Address> DsrOptionSRHeader::GetNodesAddress () const
+{
+  return m_ipv4Address;
+}
+
+void DsrOptionSRHeader::SetNodeAddress (uint8_t index, Ipv4Address addr)
+{
+  m_ipv4Address.at (index) = addr;
+}
+
+Ipv4Address DsrOptionSRHeader::GetNodeAddress (uint8_t index) const
+{
+  return m_ipv4Address.at (index);
+}
+
+uint8_t DsrOptionSRHeader::GetNodeListSize () const
+{
+  return m_ipv4Address.size ();
+}
+
+void DsrOptionSRHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength () << "";
+
+  for (std::vector<Ipv4Address>::const_iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      os << *it << " ";
+    }
+
+  os << ")";
+}
+
+uint32_t DsrOptionSRHeader::GetSerializedSize () const
+{
+  return 4 + m_ipv4Address.size () * 4;
+}
+
+void DsrOptionSRHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+  uint8_t buff[4];
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU8 (m_salvage);
+  i.WriteU8 (m_segmentsLeft);
+
+  for (VectorIpv4Address_t::const_iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      it->Serialize (buff);
+      i.Write (buff, 4);
+    }
+}
+
+uint32_t DsrOptionSRHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t buff[4];
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  m_salvage = i.ReadU8 ();
+  m_segmentsLeft = i.ReadU8 ();
+
+  uint8_t index = 0;
+  for (std::vector<Ipv4Address>::iterator it = m_ipv4Address.begin (); it != m_ipv4Address.end (); it++)
+    {
+      i.Read (buff, 4);
+      m_address = it->Deserialize (buff);
+      SetNodeAddress (index, m_address);
+      ++index;
+    }
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionSRHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRerrHeader);
+
+TypeId DsrOptionRerrHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRerrHeader")
+    .AddConstructor<DsrOptionRerrHeader> ()
+    .SetParent<DsrOptionHeader> ()
+    .AddAttribute ("ErrorType","Type of route errors",
+                   EnumValue (NODE_UNREACHABLE),
+                   MakeEnumAccessor (&DsrOptionRerrHeader::m_errorType),
+                   MakeEnumChecker (NODE_UNREACHABLE, "Node unreachable",
+                                    FLOW_STATE_NOT_SUPPORTED, "Flow state not supported",
+                                    OPTION_NOT_SUPPORTED, "Option not supported"))
+  ;
+  return tid;
+}
+
+TypeId DsrOptionRerrHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionRerrHeader::DsrOptionRerrHeader ()
+  : m_errorType (0),
+    m_reserved (0),
+    m_salvage (0),
+    m_errorLength (4)
+{
+  SetType (3);
+  SetLength (14);
+}
+
+DsrOptionRerrHeader::~DsrOptionRerrHeader ()
+{
+}
+
+void DsrOptionRerrHeader::SetErrorType (uint8_t errorType)
+{
+  m_errorType = errorType;
+}
+
+uint8_t DsrOptionRerrHeader::GetErrorType () const
+{
+  return m_errorType;
+}
+
+void DsrOptionRerrHeader::SetSalvage (uint8_t salvage)
+{
+  m_salvage = salvage;
+}
+
+uint8_t DsrOptionRerrHeader::GetSalvage () const
+{
+  return m_salvage;
+}
+
+void DsrOptionRerrHeader::SetErrorSrc (Ipv4Address errorSrcAddress)
+{
+  m_errorSrcAddress = errorSrcAddress;
+}
+
+Ipv4Address DsrOptionRerrHeader::GetErrorSrc () const
+{
+  return m_errorSrcAddress;
+}
+
+void DsrOptionRerrHeader::SetErrorDst (Ipv4Address errorDstAddress)
+{
+  m_errorDstAddress = errorDstAddress;
+}
+
+Ipv4Address DsrOptionRerrHeader::GetErrorDst () const
+{
+  return m_errorDstAddress;
+}
+
+void DsrOptionRerrHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength ()
+     << " errorType = " << (uint32_t)m_errorType << " salvage = " << (uint32_t)m_salvage
+     << " error source = " << m_errorSrcAddress << " error dst = " << m_errorDstAddress << " )";
+
+}
+
+uint32_t DsrOptionRerrHeader::GetSerializedSize () const
+{
+  return 16;
+}
+
+void DsrOptionRerrHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU8 (m_errorType);
+  i.WriteU8 (m_salvage);
+  WriteTo (i, m_errorSrcAddress);
+  WriteTo (i, m_errorDstAddress);
+  i.Write (m_errorData.Begin (), m_errorData.End ());
+}
+
+uint32_t DsrOptionRerrHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  m_errorType = i.ReadU8 ();
+  m_salvage = i.ReadU8 ();
+  ReadFrom (i, m_errorSrcAddress);
+  ReadFrom (i, m_errorDstAddress);
+
+  m_errorData = Buffer ();
+  m_errorData.AddAtEnd (m_errorLength);
+  Buffer::Iterator dataStart = i;
+  i.Next (m_errorLength);
+  Buffer::Iterator dataEnd = i;
+  m_errorData.Begin ().Write (dataStart, dataEnd);
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionRerrHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRerrUnreachHeader);
+
+TypeId DsrOptionRerrUnreachHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRerrUnreachHeader")
+    .AddConstructor<DsrOptionRerrUnreachHeader> ()
+    .SetParent<DsrOptionRerrHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionRerrUnreachHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionRerrUnreachHeader::DsrOptionRerrUnreachHeader ()
+  :    m_reserved (0),
+    m_salvage (0)
+{
+  SetType (3);
+  SetLength (14);
+  SetErrorType (1);
+}
+
+DsrOptionRerrUnreachHeader::~DsrOptionRerrUnreachHeader ()
+{
+}
+
+void DsrOptionRerrUnreachHeader::SetSalvage (uint8_t salvage)
+{
+  m_salvage = salvage;
+}
+
+uint8_t DsrOptionRerrUnreachHeader::GetSalvage () const
+{
+  return m_salvage;
+}
+
+void DsrOptionRerrUnreachHeader::SetErrorSrc (Ipv4Address errorSrcAddress)
+{
+  m_errorSrcAddress = errorSrcAddress;
+}
+
+Ipv4Address DsrOptionRerrUnreachHeader::GetErrorSrc () const
+{
+  return m_errorSrcAddress;
+}
+
+void DsrOptionRerrUnreachHeader::SetErrorDst (Ipv4Address errorDstAddress)
+{
+  m_errorDstAddress = errorDstAddress;
+}
+
+Ipv4Address DsrOptionRerrUnreachHeader::GetErrorDst () const
+{
+  return m_errorDstAddress;
+}
+
+void DsrOptionRerrUnreachHeader::SetUnreachNode (Ipv4Address unreachNode)
+{
+  m_unreachNode = unreachNode;
+}
+
+Ipv4Address DsrOptionRerrUnreachHeader::GetUnreachNode () const
+{
+  return m_unreachNode;
+}
+
+void DsrOptionRerrUnreachHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength ()
+     << " errorType = " << (uint32_t)m_errorType << " salvage = " << (uint32_t)m_salvage
+     << " error source = " << m_errorSrcAddress << " error dst = " << m_errorDstAddress
+     << " unreach node = " <<  m_unreachNode << " )";
+}
+
+uint32_t DsrOptionRerrUnreachHeader::GetSerializedSize () const
+{
+  return 16;
+}
+
+void DsrOptionRerrUnreachHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU8 (GetErrorType ());
+  i.WriteU8 (m_salvage);
+  WriteTo (i, m_errorSrcAddress);
+  WriteTo (i, m_errorDstAddress);
+  WriteTo (i, m_unreachNode);
+
+}
+
+uint32_t DsrOptionRerrUnreachHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  SetErrorType (i.ReadU8 ());
+  m_salvage = i.ReadU8 ();
+  ReadFrom (i, m_errorSrcAddress);
+  ReadFrom (i, m_errorDstAddress);
+  ReadFrom (i, m_unreachNode);
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionRerrUnreachHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRerrUnsupportHeader);
+
+TypeId DsrOptionRerrUnsupportHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRerrUnsupportHeader")
+    .AddConstructor<DsrOptionRerrUnsupportHeader> ()
+    .SetParent<DsrOptionRerrHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionRerrUnsupportHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionRerrUnsupportHeader::DsrOptionRerrUnsupportHeader ()
+  :    m_reserved (0),
+    m_salvage (0)
+{
+  SetType (3);
+  SetLength (14);
+  SetErrorType (3);
+}
+
+DsrOptionRerrUnsupportHeader::~DsrOptionRerrUnsupportHeader ()
+{
+}
+
+void DsrOptionRerrUnsupportHeader::SetSalvage (uint8_t salvage)
+{
+  m_salvage = salvage;
+}
+
+uint8_t DsrOptionRerrUnsupportHeader::GetSalvage () const
+{
+  return m_salvage;
+}
+
+void DsrOptionRerrUnsupportHeader::SetErrorSrc (Ipv4Address errorSrcAddress)
+{
+  m_errorSrcAddress = errorSrcAddress;
+}
+
+Ipv4Address DsrOptionRerrUnsupportHeader::GetErrorSrc () const
+{
+  return m_errorSrcAddress;
+}
+
+void DsrOptionRerrUnsupportHeader::SetErrorDst (Ipv4Address errorDstAddress)
+{
+  m_errorDstAddress = errorDstAddress;
+}
+
+Ipv4Address DsrOptionRerrUnsupportHeader::GetErrorDst () const
+{
+  return m_errorDstAddress;
+}
+
+void DsrOptionRerrUnsupportHeader::SetUnsupported (uint16_t unsupport)
+{
+  m_unsupport = unsupport;
+}
+
+uint16_t DsrOptionRerrUnsupportHeader::GetUnsupported () const
+{
+  return m_unsupport;
+}
+
+void DsrOptionRerrUnsupportHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength ()
+     << " errorType = " << (uint32_t)m_errorType << " salvage = " << (uint32_t)m_salvage
+     << " error source = " << m_errorSrcAddress << " error dst = " << m_errorDstAddress
+     << " unsupported option = " <<  m_unsupport << " )";
+
+}
+
+uint32_t DsrOptionRerrUnsupportHeader::GetSerializedSize () const
+{
+  return 16;
+}
+
+void DsrOptionRerrUnsupportHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU8 (GetErrorType ());
+  i.WriteU8 (m_salvage);
+  WriteTo (i, m_errorSrcAddress);
+  WriteTo (i, m_errorDstAddress);
+  i.WriteU16 (m_unsupport);
+
+}
+
+uint32_t DsrOptionRerrUnsupportHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  SetErrorType (i.ReadU8 ());
+  m_salvage = i.ReadU8 ();
+  ReadFrom (i, m_errorSrcAddress);
+  ReadFrom (i, m_errorDstAddress);
+  m_unsupport = i.ReadU16 ();
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionRerrUnsupportHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionAckReqHeader);
+
+TypeId DsrOptionAckReqHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionAckReqHeader")
+    .AddConstructor<DsrOptionAckReqHeader> ()
+    .SetParent<DsrOptionHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionAckReqHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionAckReqHeader::DsrOptionAckReqHeader ()
+  : m_identification (0)
+
+{
+  SetType (160);
+  SetLength (2);
+}
+
+DsrOptionAckReqHeader::~DsrOptionAckReqHeader ()
+{
+}
+
+void DsrOptionAckReqHeader::SetAckId (uint16_t identification)
+{
+  m_identification = identification;
+}
+
+uint16_t DsrOptionAckReqHeader::GetAckId () const
+{
+  return m_identification;
+}
+
+void DsrOptionAckReqHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength ()
+     << " id = " << m_identification << " )";
+}
+
+uint32_t DsrOptionAckReqHeader::GetSerializedSize () const
+{
+  return 4;
+}
+
+void DsrOptionAckReqHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU16 (m_identification);
+}
+
+uint32_t DsrOptionAckReqHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  m_identification = i.ReadU16 ();
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionAckReqHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionAckHeader);
+
+TypeId DsrOptionAckHeader::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionAckHeader")
+    .AddConstructor<DsrOptionAckHeader> ()
+    .SetParent<DsrOptionHeader> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionAckHeader::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionAckHeader::DsrOptionAckHeader ()
+  :    m_identification (0)
+{
+  SetType (32);
+  SetLength (10);
+}
+
+DsrOptionAckHeader::~DsrOptionAckHeader ()
+{
+}
+
+void DsrOptionAckHeader::SetAckId (uint16_t identification)
+{
+  m_identification = identification;
+}
+
+uint16_t DsrOptionAckHeader::GetAckId () const
+{
+  return m_identification;
+}
+
+void DsrOptionAckHeader::SetRealSrc (Ipv4Address realSrcAddress)
+{
+  m_realSrcAddress = realSrcAddress;
+}
+
+Ipv4Address DsrOptionAckHeader::GetRealSrc () const
+{
+  return m_realSrcAddress;
+}
+
+void DsrOptionAckHeader::SetRealDst (Ipv4Address realDstAddress)
+{
+  m_realDstAddress = realDstAddress;
+}
+
+Ipv4Address DsrOptionAckHeader::GetRealDst () const
+{
+  return m_realDstAddress;
+}
+
+void DsrOptionAckHeader::Print (std::ostream &os) const
+{
+  os << "( type = " << (uint32_t)GetType () << " length = " << (uint32_t)GetLength ()
+     << " id = " << m_identification << " real src = " << m_realSrcAddress
+     << " real dst = " << m_realDstAddress << " )";
+
+}
+
+uint32_t DsrOptionAckHeader::GetSerializedSize () const
+{
+  return 12;
+}
+
+void DsrOptionAckHeader::Serialize (Buffer::Iterator start) const
+{
+  Buffer::Iterator i = start;
+
+  i.WriteU8 (GetType ());
+  i.WriteU8 (GetLength ());
+  i.WriteU16 (m_identification);
+  WriteTo (i, m_realSrcAddress);
+  WriteTo (i, m_realDstAddress);
+}
+
+uint32_t DsrOptionAckHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  SetType (i.ReadU8 ());
+  SetLength (i.ReadU8 ());
+  m_identification = i.ReadU16 ();
+  ReadFrom (i, m_realSrcAddress);
+  ReadFrom (i, m_realDstAddress);
+
+  return GetSerializedSize ();
+}
+
+DsrOptionHeader::Alignment DsrOptionAckHeader::GetAlignment () const
+{
+  Alignment retVal = { 4, 0 };
+  return retVal;
+}
+} /* namespace dsr */
+} /* namespace ns3 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-option-header.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,1387 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_OPTION_HEADER_H
+#define DSR_OPTION_HEADER_H
+
+#include <ostream>
+#include <algorithm>
+
+#include "ns3/header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+
+class Time;
+namespace dsr {
+/**
+ * \class DsrOptionHeader
+ * \brief Header for Dsr Options.
+ */
+class DsrOptionHeader : public Header
+{
+public:
+  /**
+   * \struct Alignment
+   * \brief represents the alignment requirements of an option header
+   */
+  struct Alignment
+  {
+    uint8_t factor;   /**< Factor */
+    uint8_t offset;   /**< Offset */
+  };
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionHeader ();
+  /**
+   * \brief Set the type of the option.
+   * \param type the type of the option
+   */
+  void SetType (uint8_t type);
+  /**
+   * \brief Get the type of the option.
+   * \return the type of the option
+   */
+  uint8_t GetType () const;
+  /**
+   * \brief Set the option length.
+   * \param length the option length
+   */
+  void SetLength (uint8_t length);
+  /**
+   * \brief Get the option length.
+   * \return the option length
+   */
+  uint8_t GetLength () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   *
+   * Subclasses should only implement this method, if special alignment is
+   * required. Default is no alignment (1n+0).
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /**
+   * \brief The type of the option.
+   */
+  uint8_t m_type;
+  /**
+   * \brief The option length.
+   */
+  uint8_t m_length;
+  /**
+   * \brief The anonymous data of this option
+   */
+  Buffer m_data;
+};
+
+/**
+ * \class DsrOptionPad1Header
+ * \brief Header of Dsr Option Pad1
+ */
+class DsrOptionPad1Header : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionPad1Header ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionPad1Header ();
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+};
+
+/**
+ * \class DsrOptionPadnHeader
+ * \brief Header of Dsr Option Padn
+ */
+class DsrOptionPadnHeader : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   * \param pad Number of bytes to pad (>=2)
+   */
+  DsrOptionPadnHeader (uint32_t pad = 2);
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionPadnHeader ();
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+};
+
+/**
+ * \class DsrOptionRouteRequestHeader
+ * \brief Header of Dsr Option Route Request
+ */
+
+/**
+* \ingroup dsr
+* \brief   Route Request (RREQ) Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type |  Opt Data Len |         Identification         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                         Target Address                        |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[1]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[2]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                               ...                             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[n]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+class DsrOptionRreqHeader : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRreqHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRreqHeader ();
+  /**
+   * \brief Set the number of ipv4 address.
+   * \param n the number of ipv4 address
+   */
+  void SetNumberAddress (uint8_t n);
+  /**
+   * \brief Get the target ipv4 address.
+   * \return target the target packet
+   */
+  Ipv4Address GetTarget ();
+  /**
+   * \brief Set the target ipv4 address.
+   * \param target the target packet
+   */
+  void SetTarget (Ipv4Address target);
+  /**
+   * \brief Set the vector of ipv4 address
+   * \param ipv4Address the vector of ipv4 address
+   */
+  void SetNodesAddress (std::vector<Ipv4Address> ipv4Address);
+  /**
+   * \brief Get the vector of ipv4 address
+   * \return the vector of ipv4 address
+   */
+  std::vector<Ipv4Address> GetNodesAddresses () const;
+  /**
+   * \brief Get the number of nodes
+   * \return the number of nodes
+   */
+  uint32_t GetNodesNumber () const;
+  /**
+   * \brief Add one node address
+   * \param ipv4 The ip address to add
+   */
+  void AddNodeAddress (Ipv4Address ipv4);
+  /**
+   * \brief Set a Node IPv4 Address.
+   * \param index the index of the IPv4 Address
+   * \param addr the new IPv4 Address
+   */
+  void SetNodeAddress (uint8_t index, Ipv4Address addr);
+  /**
+   * \brief Get a Node IPv4 Address.
+   * \param index the index of the IPv4 Address
+   * \return the router IPv4 Address
+   */
+  Ipv4Address GetNodeAddress (uint8_t index) const;
+  /**
+   * \brief Set the data length.
+   * \param dataLength the data length
+   */
+  void SetDataLength (uint32_t dataLength);
+  /**
+   * \brief Get the data length.
+   * \return the data length
+   */
+  uint32_t GetDataLength () const;
+  /**
+   * \brief Set the request id number.
+   * \param the identification number
+   */
+  void SetId (uint16_t identification);
+  /**
+   * \brief Set the request id number.
+   * \return request id number
+   */
+  uint16_t GetId () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /**
+   * \brief The data length.
+   */
+  uint32_t m_dataLength;
+  /**
+   * \brief Identifier of the packet.
+   */
+  uint16_t m_identification;
+  /*
+   * Ipv4 address of target node
+   */
+  Ipv4Address m_target;
+  /*
+   * Ipv4 address to write when desearizing the packet
+   */
+  Ipv4Address m_address;
+  /**
+   * \brief A vector of IPv4 Address.
+   */
+  typedef std::vector<Ipv4Address> VectorIpv4Address_t;
+  /**
+   * \brief The vector of Nodes' IPv4 Address.
+   */
+  VectorIpv4Address_t m_ipv4Address;
+};
+
+/**
+ * \class DsrOptionRrepHeader
+ * \brief Header of Dsr Option Route Reply
+ */
+
+/**
+* \ingroup dsr
+* \brief Route Reply (RREP) Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+                  -+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+                  |  Option Type  |  Opt Data Len |L|   Reserved   |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[1]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[2]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                               ...                             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[n]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+// The Route Reply header modified for ns-3 implementation
+/**
+* \ingroup dsr
+* \brief Route Reply (RREP) Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type  |  Opt Data Len |L|   Reserved   |   Reserved   |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[1]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[2]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                               ...                             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[n]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+
+class DsrOptionRrepHeader : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRrepHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRrepHeader ();
+  /**
+   * \brief Set the number of ipv4 address.
+   * \param n the number of ipv4 address
+   */
+  void SetNumberAddress (uint8_t n);
+  /**
+   * \brief Set the vector of ipv4 address
+   * \param ipv4Address the vector of ipv4 address
+   */
+  void SetNodesAddress (std::vector<Ipv4Address> ipv4Address);
+  /**
+   * \brief Get the vector of ipv4 address
+   * \return the vector of ipv4 address
+   */
+  std::vector<Ipv4Address> GetNodesAddress () const;
+  /*
+   * \brief Get the target node Ip address
+   * \return the target address
+   */
+  Ipv4Address GetTargetAddress (std::vector<Ipv4Address> ipv4Address) const;
+  /**
+   * \brief Set a Node IPv4 Address.
+   * \param index the index of the IPv4 Address
+   * \param addr the new IPv4 Address
+   */
+  void SetNodeAddress (uint8_t index, Ipv4Address addr);
+  /**
+   * \brief Get a Node IPv4 Address.
+   * \param index the index of the IPv4 Address
+   * \return the router IPv4 Address
+   */
+  Ipv4Address GetNodeAddress (uint8_t index) const;
+  /*
+   * \brief Search the next hop Ipv4 address
+   * \param Our own IP address
+   * \return The next hop address of the route
+   */
+  Ipv4Address SearchNextHop (Ipv4Address ipv4Address);
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /*
+   * The Ip address to write to when deserialize the packet
+   */
+  Ipv4Address m_address;
+  /**
+    * \brief type def A vector of IPv4 Address.
+    */
+  typedef std::vector<Ipv4Address> VectorIpv4Address_t;
+  /**
+   * \brief The vector of Nodes' IPv4 Address.
+   */
+  VectorIpv4Address_t m_ipv4Address;
+};
+
+/**
+ * \class DsrOptionSRHeader
+ * \brief Header of Dsr Option Source Route
+ */
+
+/**
+* \ingroup dsr
+* \brief Source Route (SR) Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type |  Opt Data Len |F|L|Reservd|Salvage|  Segs Left |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[1]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[2]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                               ...                             |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                            Address[n]                         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+class DsrOptionSRHeader : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionSRHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionSRHeader ();
+  /*
+   * \brief Set the number of segments left to send
+   * \param The segments left
+   */
+  void SetSegmentsLeft (uint8_t segmentsLeft);
+  /*
+   * \brief Get the number of segments left to send
+   * \return The segments left
+   */
+  uint8_t GetSegmentsLeft () const;
+  /**
+   * \brief Set the number of ipv4 address.
+   * \param n the number of ipv4' address
+   */
+  void SetNumberAddress (uint8_t n);
+  /**
+   * \brief Set the vector of ipv4 address
+   * \param ipv4Address the vector of ipv4 address
+   */
+  void SetNodesAddress (std::vector<Ipv4Address> ipv4Address);
+  /**
+   * \brief Get the vector of ipv4 address
+   * \return the vector of ipv4 address
+   */
+  std::vector<Ipv4Address> GetNodesAddress () const;
+  /*
+   * \brief Get the node list size which is the number of ip address of the route
+   * \return the node list size
+   */
+  uint8_t GetNodeListSize () const;
+  /**
+   * \brief Set a Node IPv4 Address.
+   * \param index the index of the IPv4 Address
+   * \param addr the new IPv4 Address
+   */
+  void SetNodeAddress (uint8_t index, Ipv4Address addr);
+  /**
+   * \brief Get a Node IPv4 Address.
+   * \param index the index of the IPv4 Address
+   * \return the router IPv4 Address
+   */
+  Ipv4Address GetNodeAddress (uint8_t index) const;
+  /*
+   * \brief Set the salvage value for a packet
+   * \param The salvage value of the packet
+   */
+  void SetSalvage (uint8_t salvage);
+  /*
+   * \brief Get the salvage value for a packet
+   * \return The salvage value of the packet
+   */
+  uint8_t GetSalvage () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /**
+   * \brief The ip address header deserilize to
+   */
+  Ipv4Address m_address;
+  /**
+   * \brief Number of left segments.
+   */
+  uint8_t m_segmentsLeft;
+  /**
+   * \brief Number of savlage times for a packet.
+   */
+  uint8_t m_salvage;
+  /**
+    * \brief A vector of IPv4 Address.
+    */
+  typedef std::vector<Ipv4Address> VectorIpv4Address_t;
+  /**
+   * \brief The vector of Nodes' IPv4 Address.
+   */
+  VectorIpv4Address_t m_ipv4Address;
+};
+
+/**
+ * \class DsrOptionRerrHeader
+ * \brief Header of Dsr Option Route Error
+ */
+
+/**
+* \ingroup dsr
+* \brief Route Error (RERR) Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type |  Opt Data Len |   Error Type  |Reservd| Salvage|
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                      Error Source Address                     |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                    Error Destination Address                  |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   .                                                               .
+   .                    Type-Specific Information                  .
+   .                                                               .
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+// / Error type
+enum ErrorType
+{
+  NODE_UNREACHABLE  = 1,   // !< NODE_UNREACHABLE
+  FLOW_STATE_NOT_SUPPORTED  = 2,   // !< FLOW_STATE_NOT_SUPPORTED
+  OPTION_NOT_SUPPORTED  = 3,   // !< OPTION_NOT_SUPPORTED
+};
+
+class DsrOptionRerrHeader : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRerrHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRerrHeader ();
+  /**
+   * \brief Set the route error type
+   * \param The error type
+   */
+  void SetErrorType (uint8_t errorType);
+  /**
+   * \brief Get the route error type
+   * \return The error type
+   */
+  uint8_t GetErrorType () const;
+  /**
+   * \brief Set the route error source address
+   * \param The error source address
+   */
+  virtual void SetErrorSrc (Ipv4Address errorSrcAddress);
+  /**
+   * \brief Get the route error source address
+   * \return The error source address
+   */
+  virtual Ipv4Address GetErrorSrc () const;
+  /**
+   * \brief Set the salvage value of the packet
+   */
+  virtual void SetSalvage (uint8_t salvage);
+  /**
+   * \brief Get the salvage value of the packet
+   * \param The salvage value of the packet
+   */
+  virtual uint8_t GetSalvage () const;
+  /**
+   * \brief Set the error destination ip address
+   * \param The error destination address
+   */
+  virtual void SetErrorDst (Ipv4Address errorDstAddress);
+  /**
+   * \brief Get the error destination ip address
+   * \return The error destination address
+   */
+  virtual Ipv4Address GetErrorDst () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /**
+   * \brief option data length
+   */
+  uint8_t        m_optDataLen;
+  /**
+   * \brief The error type or route error option
+   */
+  uint8_t        m_errorType;
+  /**
+   * \brief The reserved field
+   */
+  uint8_t        m_reserved;
+  /**
+   * \brief The salavage field
+   */
+  uint8_t        m_salvage;
+  /**
+   * \brief The specific error message length
+   */
+  uint16_t       m_errorLength;
+  /**
+   * \brief The error source address
+   */
+  Ipv4Address    m_errorSrcAddress;
+  /**
+   * \brief The error destination address
+   */
+  Ipv4Address    m_errorDstAddress;
+  /**
+   * \brief The anonymous data of this option
+   */
+  Buffer m_errorData;
+};
+
+/**
+* \ingroup dsr
+* \brief Route Error (RERR) Unreachable node address option Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type |  Opt Data Len |   Error Type  |Reservd| Salvage|
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                      Error Source Address                     |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                    Error Destination Address                  |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   .                                                               .
+   .                    Type-Specific Information                  .
+   .                                                               .
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+/*
+ * \brief The type-specific info field
+ * \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                    Unreachable Node Address                   |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   \endverbatim
+ */
+
+class DsrOptionRerrUnreachHeader : public DsrOptionRerrHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRerrUnreachHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRerrUnreachHeader ();
+  /**
+   * \brief Set the route error source address
+   * \param The error source address
+   */
+  virtual void SetErrorSrc (Ipv4Address errorSrcAddress);
+  /**
+   * \brief Get the route error source address
+   * \return The error source address
+   */
+  virtual Ipv4Address GetErrorSrc () const;
+  /**
+   * \brief Set the salvage value of the packet
+   */
+  virtual void SetSalvage (uint8_t salvage);
+  /**
+   * \brief Get the salvage value of the packet
+   * \param The salvage value of the packet
+   */
+  virtual uint8_t GetSalvage () const;
+  /**
+   * \brief Set the error destination ip address
+   * \param The error destination address
+   */
+  virtual void SetErrorDst (Ipv4Address errorDstAddress);
+  /**
+   * \brief Get the error destination ip address
+   * \return The error destination address
+   */
+  virtual Ipv4Address GetErrorDst () const;
+  /**
+   * \brief Set the unreachable node ip address
+   * \param The unreachable ip address
+   */
+  void SetUnreachNode (Ipv4Address unreachNode);
+  /**
+   * \brief Get the unreachable node ip address
+   * \return The unreachable ip address
+   */
+  Ipv4Address GetUnreachNode () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /**
+   * \brief option data length
+   */
+  uint8_t        m_optDataLen;
+  /**
+   * \brief The error type or route error option
+   */
+  uint8_t        m_errorType;
+  /**
+   * \brief The reserved field
+   */
+  uint8_t        m_reserved;
+  /**
+   * \brief The salavage field
+   */
+  uint8_t        m_salvage;
+  /**
+   * \brief The error source address
+   */
+  Ipv4Address    m_errorSrcAddress;
+  /**
+   * \brief The error destination address
+   */
+  Ipv4Address    m_errorDstAddress;
+  /**
+   * \brief The unreachable node address
+   */
+  Ipv4Address    m_unreachNode;
+  /**
+   * \brief The specific error type
+   */
+  uint16_t       m_typeSpecific;
+};
+
+/**
+* \ingroup dsr
+* \brief Route Error (RERR) Unsupported option Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type |  Opt Data Len |   Error Type  |Reservd| Salvage|
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                      Error Source Address                     |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                    Error Destination Address                  |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   .                                                               .
+   .                    Type-Specific Information                  .
+   .                                                               .
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+/*
+ * \brief The type-specific info field
+ * \unsupported option
+ * \verbatim
+   |      0        |
+   0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+
+   |Unsupported Opt|
+   +-+-+-+-+-+-+-+-+
+   \endverbatim
+ */
+
+class DsrOptionRerrUnsupportHeader : public DsrOptionRerrHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRerrUnsupportHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRerrUnsupportHeader ();
+  /**
+   * \brief Set the route error source address
+   * \param The error source address
+   */
+  virtual void SetErrorSrc (Ipv4Address errorSrcAddress);
+  /**
+   * \brief Get the route error source address
+   * \return The error source address
+   */
+  virtual Ipv4Address GetErrorSrc () const;
+  /**
+   * \brief Set the salvage value of the packet
+   */
+  virtual void SetSalvage (uint8_t salvage);
+  /**
+   * \brief Get the salvage value of the packet
+   * \param The salvage value of the packet
+   */
+  virtual uint8_t GetSalvage () const;
+  /**
+   * \brief Set the error destination ip address
+   * \param The error destination address
+   */
+  virtual void SetErrorDst (Ipv4Address errorDstAddress);
+  /**
+   * \brief Get the error destination ip address
+   * \return The error destination address
+   */
+  virtual Ipv4Address GetErrorDst () const;
+  /**
+   * \brief Set the unsupported option type value
+   * \param The unsupported option type value
+   */
+  void SetUnsupported (uint16_t optionType);
+  /**
+   * \brief Get the unsupported option type value
+   * \return The unsupported option type value
+   */
+  uint16_t GetUnsupported () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /**
+   * \brief option data length
+   */
+  uint8_t        m_optDataLen;
+  /**
+   * \brief The error type or route error option
+   */
+  uint8_t        m_errorType;
+  /**
+   * \brief The reserved field
+   */
+  uint8_t        m_reserved;
+  /**
+   * \brief The salavage field
+   */
+  uint8_t        m_salvage;
+  /**
+   * \brief The error source address
+   */
+  Ipv4Address    m_errorSrcAddress;
+  /**
+   * \brief The error destination address
+   */
+  Ipv4Address    m_errorDstAddress;
+  /**
+   * \brief The unsupported option
+   */
+  uint16_t       m_unsupport;
+};
+
+/**
+ * \class DsrOptionAckReqHeader
+ * \brief Header of Dsr Option ack request
+ */
+
+/**
+* \ingroup dsr
+* \brief   Acknowledgement Request (ACK_RREQ) Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type |  Opt Data Len |         Identification         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+class DsrOptionAckReqHeader : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionAckReqHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionAckReqHeader ();
+  /**
+   * \brief Set the Ack request id number.
+   * \param the identification number
+   */
+  void SetAckId (uint16_t identification);
+  /**
+   * \brief Set the Ack request id number.
+   * \return request id number
+   */
+  uint16_t GetAckId () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /*
+   * The option data length
+   */
+  uint8_t  m_optDataLen;
+  /*
+   * The identification field
+   */
+  uint16_t m_identification;
+};
+
+/**
+ * \class DsrOptionAckHeader
+ * \brief Header of Dsr Option ack
+ */
+
+/**
+* \ingroup dsr
+* \brief   Acknowledgement (ACK) Message Format
+  \verbatim
+   |      0        |      1        |      2        |      3        |
+   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |  Option Type |  Opt Data Len |         Identification         |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                        ACK Source Address                     |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+   |                     ACK Destination Address                   |
+   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+
+class DsrOptionAckHeader : public DsrOptionHeader
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionAckHeader ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionAckHeader ();
+  /**
+   * \brief Set the Ack id number.
+   * \param the identification number
+   */
+  void SetAckId (uint16_t identification);
+  /**
+   * \brief Set the Ack id number.
+   * \return request id number
+   */
+  uint16_t GetAckId () const;
+  /**
+   * \brief Set Error source ip address.
+   * \param The real source address
+   */
+  void SetRealSrc (Ipv4Address realSrcAddress);
+  /**
+   * \brief Get Error source ip address.
+   * \return The real source address
+   */
+  Ipv4Address GetRealSrc () const;
+  /**
+   * \brief Set Error source ip address.
+   * \param The real dst address
+   */
+  void SetRealDst (Ipv4Address realDstAddress);
+  /**
+   * \brief Get Error source ip address.
+   * \return The real dst address
+   */
+  Ipv4Address GetRealDst () const;
+  /**
+   * \brief Print some informations about the packet.
+   * \param os output stream
+   * \return info about this packet
+   */
+  virtual void Print (std::ostream &os) const;
+  /**
+   * \brief Get the serialized size of the packet.
+   * \return size
+   */
+  virtual uint32_t GetSerializedSize () const;
+  /**
+   * \brief Serialize the packet.
+   * \param start Buffer iterator
+   */
+  virtual void Serialize (Buffer::Iterator start) const;
+  /**
+   * \brief Deserialize the packet.
+   * \param start Buffer iterator
+   * \return size of the packet
+   */
+  virtual uint32_t Deserialize (Buffer::Iterator start);
+  /**
+   * \brief Get the Alignment requirement of this option header
+   * \return The required alignment
+   */
+  virtual Alignment GetAlignment () const;
+
+private:
+  /**
+   * \brief option data length
+   */
+  uint8_t m_optDataLen;
+  /**
+   * \brief identification field
+   */
+  uint16_t m_identification;
+  /**
+   * \brief ack source address
+   */
+  Ipv4Address m_realSrcAddress;
+  /**
+   * \brief ack destination address
+   */
+  Ipv4Address m_realDstAddress;
+};
+
+static inline std::ostream & operator<< (std::ostream& os, const DsrOptionSRHeader & sr)
+{
+  sr.Print (os);
+  return os;
+}
+
+} // namespace dsr
+} // namespace ns3
+
+#endif /* DSR_OPTION_HEADER_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-options.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,1596 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#define NS_LOG_APPEND_CONTEXT                                   \
+  if (GetObject<Node> ()) { std::clog << "[node " << GetObject<Node> ()->GetId () << "] "; }
+
+#include <list>
+#include <ctime>
+#include <map>
+
+#include "ns3/ptr.h"
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ns3/fatal-error.h"
+#include "ns3/node.h"
+#include "ns3/uinteger.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/random-variable.h"
+#include "ns3/udp-header.h"
+#include "ns3/pointer.h"
+#include "ns3/node-list.h"
+#include "ns3/uinteger.h"
+#include "ns3/object-vector.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/ipv4-interface.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/icmpv4-l4-protocol.h"
+#include "ns3/ipv4-l4-protocol.h"
+
+#include "dsr-option-header.h"
+#include "dsr-options.h"
+#include "dsr-rcache.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsrOptions");
+
+namespace ns3 {
+namespace dsr {
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptions);
+
+TypeId DsrOptions::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptions")
+    .SetParent<Object> ()
+    .AddAttribute ("OptionNumber", "The Dsr option number.",
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&DsrOptions::GetOptionNumber),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddTraceSource ("Rx", "Receive DSR packet.",
+                     MakeTraceSourceAccessor (&DsrOptions::m_rxPacketTrace))
+  ;
+  return tid;
+}
+
+DsrOptions::DsrOptions ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptions::~DsrOptions ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void DsrOptions::SetNode (Ptr<Node> node)
+{
+  NS_LOG_FUNCTION (this << node);
+  m_node = node;
+}
+
+Ptr<Node> DsrOptions::GetNode () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node;
+}
+
+bool DsrOptions::ContainAddressAfter (Ipv4Address ipv4Address, Ipv4Address destAddress, std::vector<Ipv4Address> &nodeList)
+{
+  std::vector<Ipv4Address>::iterator it = find (nodeList.begin (), nodeList.end (), destAddress);
+
+  for (std::vector<Ipv4Address>::iterator i = it; i != nodeList.end (); ++i)
+    {
+      if ((ipv4Address == (*i)) && ((*i) != nodeList.back ()))
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+std::vector<Ipv4Address>
+DsrOptions::CutRoute (Ipv4Address ipv4Address, std::vector<Ipv4Address> &nodeList)
+{
+  std::vector<Ipv4Address>::iterator it = find (nodeList.begin (), nodeList.end (), ipv4Address);
+  std::vector<Ipv4Address> cutRoute;
+  for (std::vector<Ipv4Address>::iterator i = it; i != nodeList.end (); ++i)
+    {
+      cutRoute.push_back (*i);
+    }
+  return cutRoute;
+}
+
+Ptr<Ipv4Route> DsrOptions::SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress)
+{
+  NS_LOG_FUNCTION (this << nextHop << srcAddress);
+  m_ipv4Route = Create<Ipv4Route> ();
+  m_ipv4Route->SetDestination (nextHop);
+  m_ipv4Route->SetGateway (nextHop);
+  m_ipv4Route->SetSource (srcAddress);
+  return m_ipv4Route;
+}
+
+bool DsrOptions::ReverseRoutes (std::vector<Ipv4Address> & vec)
+{
+  std::vector<Ipv4Address> vec2 (vec);
+  vec.clear ();    // To ensure vec is empty before start
+  for (std::vector<Ipv4Address>::reverse_iterator ri = vec2.rbegin (); ri
+       != vec2.rend (); ++ri)
+    {
+      vec.push_back (*ri);
+    }
+
+  if ((vec.size () == vec2.size ()) && (vec.front () == vec2.back ()))
+    {
+      return true;
+    }
+  return false;
+}
+
+Ipv4Address DsrOptions::SearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec)
+{
+  Ipv4Address nextHop;
+  if (vec.size () == 2)
+    {
+      NS_LOG_DEBUG ("The two nodes are neighbors");
+      nextHop = vec[1];
+      return nextHop;
+    }
+  else
+    {
+      if (ipv4Address == vec.back ())
+        {
+          NS_LOG_DEBUG ("We have reached to the final destination " << ipv4Address << " " << vec.back ());
+          return ipv4Address;
+        }
+      for (std::vector<Ipv4Address>::iterator i = vec.begin (); i != vec.end (); ++i)
+        {
+          if (ipv4Address == (*i))
+            {
+              nextHop = *(++i);
+              return nextHop;
+            }
+        }
+    }
+  NS_LOG_DEBUG ("next hop address not found, route corrupted");
+  Ipv4Address none = "0.0.0.0";
+  return none;
+}
+
+Ipv4Address DsrOptions::ReverseSearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec)
+{
+  Ipv4Address nextHop;
+  if (vec.size () == 2)
+    {
+      NS_LOG_DEBUG ("The two nodes are neighbors");
+      nextHop = vec[0];
+      return nextHop;
+    }
+  else
+    {
+      for (std::vector<Ipv4Address>::reverse_iterator ri = vec.rbegin (); ri != vec.rend (); ++ri)
+        {
+          if (ipv4Address == (*ri))
+            {
+              nextHop = *(++ri);
+              return nextHop;
+            }
+        }
+    }
+  NS_LOG_DEBUG ("next hop address not found, route corrupted");
+  Ipv4Address none = "0.0.0.0";
+  return none;
+}
+
+void DsrOptions::PrintVector (std::vector<Ipv4Address>& vec)
+{
+  /*
+   * Check elements in a route vector
+   */
+  if (!vec.size ())
+    {
+      NS_LOG_DEBUG ("The vector is empty");
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Print all the elements in a vector");
+      for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
+        {
+          NS_LOG_DEBUG ("The ip address " << *i);
+        }
+    }
+}
+
+bool DsrOptions::IfDuplicates (std::vector<Ipv4Address>& vec, std::vector<Ipv4Address>& vec2)
+{
+  for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
+    {
+      for (std::vector<Ipv4Address>::const_iterator j = vec2.begin (); j != vec2.end (); ++j)
+        {
+          if ((*i) == (*j))
+            {
+              return true;
+            }
+          else
+            {
+              continue;
+            }
+        }
+    }
+  return false;
+}
+
+bool DsrOptions::CheckDuplicates (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec)
+{
+  for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
+    {
+      if ((*i) == ipv4Address)
+        {
+          return true;
+        }
+      else
+        {
+          continue;
+        }
+    }
+  return false;
+}
+
+void DsrOptions::RemoveDuplicates (std::vector<Ipv4Address>& vec)
+{
+  //Remove duplicate ip address from the route if any, should not happen with normal behavior nodes
+  std::vector<Ipv4Address> vec2 (vec); // declare vec2 as a copy of the vec
+  PrintVector (vec2); // Print all the ip address in the route
+  vec.clear (); // clear vec
+  for (std::vector<Ipv4Address>::const_iterator i = vec2.begin (); i != vec2.end (); ++i)
+    {
+      if (vec.empty ())
+        {
+          vec.push_back (*i);
+          continue;
+        }
+      else
+        {
+          for (std::vector<Ipv4Address>::iterator j = vec.begin (); j != vec.end (); ++j)
+            {
+              if ((*i) == (*j))
+                {
+                  if ((j + 1) != vec.end ())
+                    {
+                      vec.erase (j + 1, vec.end ());   // Automatic shorten the route
+                      break;
+                    }
+                  else
+                    {
+                      break;
+                    }
+                }
+              else if (j == (vec.end () - 1))
+                {
+                  vec.push_back (*i);
+                  break;
+                }
+              else
+                {
+                  continue;
+                }
+            }
+        }
+    }
+}
+
+uint32_t
+DsrOptions::GetIDfromIP (Ipv4Address address)
+{
+  int32_t nNodes = NodeList::GetNNodes ();
+  for (int32_t i = 0; i < nNodes; ++i)
+    {
+      Ptr<Node> node = NodeList::GetNode (i);
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      if (ipv4->GetAddress (1, 0).GetLocal () == address)
+        {
+          return i;
+        }
+    }
+  return 255;
+}
+
+Ptr<Node> DsrOptions::GetNodeWithAddress (Ipv4Address ipv4Address)
+{
+  int32_t nNodes = NodeList::GetNNodes ();
+  for (int32_t i = 0; i < nNodes; ++i)
+    {
+      Ptr<Node> node = NodeList::GetNode (i);
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      int32_t ifIndex = ipv4->GetInterfaceForAddress (ipv4Address);
+      if (ifIndex != -1)
+        {
+          return node;
+        }
+    }
+  return 0;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionPad1);
+
+TypeId DsrOptionPad1::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionPad1")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionPad1> ()
+  ;
+  return tid;
+}
+
+DsrOptionPad1::DsrOptionPad1 ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionPad1::~DsrOptionPad1 ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+uint8_t DsrOptionPad1::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionPad1::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
+
+  Ptr<Packet> p = packet->Copy ();
+  DsrOptionPad1Header pad1Header;
+  p->RemoveHeader (pad1Header);
+
+  isPromisc = false;
+
+  return pad1Header.GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionPadn);
+
+TypeId DsrOptionPadn::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionPadn")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionPadn> ()
+  ;
+  return tid;
+}
+
+DsrOptionPadn::DsrOptionPadn ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionPadn::~DsrOptionPadn ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+uint8_t DsrOptionPadn::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionPadn::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
+
+  Ptr<Packet> p = packet->Copy ();
+
+  DsrOptionPadnHeader padnHeader;
+  p->RemoveHeader (padnHeader);
+
+  isPromisc = false;
+
+  return padnHeader.GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRreq);
+
+TypeId DsrOptionRreq::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRreq")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionRreq> ()
+  ;
+  return tid;
+}
+
+TypeId DsrOptionRreq::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+DsrOptionRreq::DsrOptionRreq ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionRreq::~DsrOptionRreq ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+uint8_t DsrOptionRreq::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionRreq::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
+  /*
+   * Get the node associated with the ipv4 address and get several objects from the node and leave for further use
+   */
+  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+  Ptr<dsr::RouteCache> m_routeCache = node->GetObject<dsr::RouteCache> ();
+  Ptr<dsr::RreqTable>  m_rreqTable = node->GetObject<dsr::RreqTable> ();
+  ActiveRouteTimeout = m_routeCache->GetCacheTimeout ();
+
+  // Set the isError boolean value as false
+  bool isError = false;
+  Ptr<Packet> p = packet->Copy (); // The packet here doesn't contain the fixed size dsr header
+  /*
+   * \brief Get the number of routers' address field before removing the header
+   * \peek the packet and get the value
+   */
+  uint8_t buf[2];
+  p->CopyData (buf, sizeof(buf));
+  uint8_t numberAddress = (buf[1] - 6) / 4;
+
+  if (numberAddress >= 255)
+    {
+      NS_LOG_DEBUG ("Discard the packet, malformed header since two many ip addresses in route");
+      m_dropTrace (packet); // call the drop trace to show in the tracing
+      return 0;
+    }
+
+  NS_LOG_DEBUG ("The number of Ip addresses " << (uint32_t)numberAddress);
+  /*
+   * Create the dsr rreq header
+   */
+  DsrOptionRreqHeader rreq;
+
+  // Fields from IP header
+  Ipv4Address srcAddress = ipv4Header.GetSource ();
+  Ipv4Address destAddress = ipv4Header.GetDestination ();
+  /*
+   * Set the number of addresses with the value from peek data and remove the rreq header
+   */
+  rreq.SetNumberAddress (numberAddress);
+
+  /*
+   * \ when the ip source address is equal to the address of our own, this is request packet originated
+   * \ by the node itself, discard it
+   */
+  if (srcAddress == ipv4Address)
+    {
+      NS_LOG_DEBUG ("Discard the packet");
+      m_dropTrace (packet); // call the drop trace to show in the tracing
+      return 0;
+    }
+
+  p->RemoveHeader (rreq);
+  Ptr<Packet> errP = p->Copy ();
+
+  // The target address is where we want to send the data packets
+  Ipv4Address targetAddress = rreq.GetTarget ();
+  uint16_t id = rreq.GetId ();
+  // Get the node list and source address from the route request header
+  std::vector<Ipv4Address> nodeList = rreq.GetNodesAddresses ();
+  PrintVector (nodeList);
+
+  // Get the TTL value
+  uint8_t ttl = ipv4Header.GetTtl ();
+  NS_LOG_DEBUG ("The TTL " << (uint32_t) ttl);
+  /*
+   *  Node checks to determine whether it has received a RREQ with the same Originator IP Address and RREQ ID.
+   *  If such a RREQ has been received, the node silently discards the newly received RREQ.
+   */
+  if (ttl)
+    {
+      // if the TTL value is not 0, save the route request entry
+      if (m_rreqTable->FindSrc (source, targetAddress, id))
+        {
+          NS_LOG_DEBUG ("Received the same route request recently, not processing it further");
+          return 0;
+        }
+    }
+
+  if (CheckDuplicates (ipv4Address, nodeList))
+    {
+      /*
+       * if the route contains the node address already, drop the request packet
+       */
+      m_dropTrace (packet);    // call drop trace
+      NS_LOG_DEBUG ("Our node address is already seen in the route, drop the request");
+      return 0;
+    }
+  else
+    {
+      // Verify the option length
+      uint8_t length = rreq.GetLength ();
+      if (length % 2 != 0)
+        {
+          NS_LOG_LOGIC ("Malformed header. Drop!");
+          m_dropTrace (packet); // call drop trace
+          return 0;
+        }
+
+      // A node ignores all RREQs received from any node in its blacklist
+      RouteCacheEntry toPrev;
+      /*
+       *  When the reverse route is created or updated, the following actions on the route are also carried out:
+       *  3. the next hop in the routing table becomes the node from which the  RREQ was received
+       *  4. the hop count is copied from the Hop Count in the RREQ message;
+       */
+
+      //  A node generates a RREP if either:
+      //  (i)  it is itself the destination,
+      /*
+       * The target address equal to our own ip address
+       */
+      if (targetAddress == ipv4Address)
+        {
+          Ipv4Address nextHop; // Declare the next hop address to use
+          if (nodeList.size () == 1)
+            {
+              NS_LOG_DEBUG ("These two nodes are neighbors");
+              m_finalRoute.clear ();
+              m_finalRoute.push_back (srcAddress);     // push back the request originator's address
+              m_finalRoute.push_back (ipv4Address);    // push back our own address
+              nextHop = srcAddress;
+            }
+          else
+            {
+              nodeList.push_back (ipv4Address);    // push back our own address
+              m_finalRoute.clear ();              // get a clear route vector
+              for (std::vector<Ipv4Address>::iterator i = nodeList.begin (); i != nodeList.end (); ++i)
+                {
+                  m_finalRoute.push_back (*i);  // Get the full route from source to destination
+                }
+              PrintVector (m_finalRoute);
+              nextHop = ReverseSearchNextHop (ipv4Address, m_finalRoute); // get the next hop
+            }
+
+          DsrOptionRrepHeader rrep;
+          rrep.SetNodesAddress (m_finalRoute);     // Set the node addresses in the route reply header
+          NS_LOG_DEBUG ("The nextHop address " << nextHop);
+          Ipv4Address replyDst = m_finalRoute.front ();
+          /*
+           * This part add dsr header to the packet and send reply
+           */
+          DsrRoutingHeader dsrRoutingHeader;
+          dsrRoutingHeader.SetNextHeader (protocol);
+          dsrRoutingHeader.SetMessageType (1);
+          dsrRoutingHeader.SetSourceId (GetIDfromIP (ipv4Address));
+          dsrRoutingHeader.SetDestId (GetIDfromIP (replyDst));
+          // Set the route for route reply
+          SetRoute (nextHop, ipv4Address);
+
+          uint8_t length = rrep.GetLength ();  // Get the length of the rrep header excluding the type header
+          dsrRoutingHeader.SetPayloadLength (length + 2);
+          dsrRoutingHeader.AddDsrOption (rrep);
+          Ptr<Packet> newPacket = Create<Packet> ();
+          newPacket->AddHeader (dsrRoutingHeader);
+          dsr->ScheduleInitialReply (newPacket, ipv4Address, nextHop, m_ipv4Route);
+          /*
+           * Create the route entry to the rreq originator and save it to route cache, also need to reverse the route
+           */
+          PrintVector (m_finalRoute);
+          if (ReverseRoutes (m_finalRoute))
+            {
+              PrintVector (m_finalRoute);
+              Ipv4Address dst = m_finalRoute.back ();
+              bool addRoute = false;
+              if (numberAddress > 0)
+                {
+                  RouteCacheEntry toSource (/*IP_VECTOR=*/ m_finalRoute, /*dst=*/
+                                                           dst, /*expire time=*/ ActiveRouteTimeout);
+                  if (m_routeCache->IsLinkCache ())
+                    {
+                      addRoute = m_routeCache->AddRoute_Link (m_finalRoute, ipv4Address);
+                    }
+                  else
+                    {
+                      addRoute = m_routeCache->AddRoute (toSource);
+                    }
+                }
+              else
+                {
+                  NS_LOG_DEBUG ("Abnormal RouteRequest");
+                  return 0;
+                }
+
+              if (addRoute)
+                {
+                  NS_LOG_DEBUG ("The route is failed to add in cache");
+                  return 0;
+                }
+              else
+                {
+                  /*
+                   * Found a route to the dst, construct the source route option header
+                   */
+                  DsrOptionSRHeader sourceRoute;
+                  NS_LOG_DEBUG ("The route length " << m_finalRoute.size ());
+                  sourceRoute.SetNodesAddress (m_finalRoute);
+                  if (m_routeCache->IsLinkCache ())
+                    {
+                      m_routeCache->UseExtends (m_finalRoute);
+                    }
+                  sourceRoute.SetSegmentsLeft ((m_finalRoute.size () - 2));
+                  uint8_t salvage = 0;
+                  sourceRoute.SetSalvage (salvage);
+                  Ipv4Address nextHop = SearchNextHop (ipv4Address, m_finalRoute); // Get the next hop address
+                  NS_LOG_DEBUG ("The nextHop address " << nextHop);
+
+                  if (nextHop == "0.0.0.0")
+                    {
+                      dsr->PacketNewRoute (dsrP, ipv4Address, dst, protocol);
+                      return 0;
+                    }
+                  SetRoute (nextHop, ipv4Address);
+                  /*
+                   * Schedule the packet retry
+                   */
+                  dsr->SendPacket (sourceRoute, nextHop, protocol);
+                  // Cancel the route request timer for destination
+                  dsr->CancelRreqTimer (dst);
+                }
+            }
+          else
+            {
+              NS_LOG_DEBUG ("Unable to reverse route");
+              return 0;
+            }
+          isPromisc = false;
+          return rreq.GetSerializedSize ();
+        }
+
+      /*
+       * (ii) or it has an active route to the destination, send reply based on request header and route cache,
+       *      need to delay based on a random value from d = H * (h - 1 + r), which can avoid possible route
+       *      reply storm.
+       */
+      else if (m_routeCache->LookupRoute (targetAddress, toPrev))
+        {
+
+          RouteCacheEntry::IP_VECTOR ip = toPrev.GetVector (); // The route from our own route cache to dst
+
+          PrintVector (ip);
+          std::vector<Ipv4Address> nodeList = rreq.GetNodesAddresses (); // Route from rreq header
+          std::vector<Ipv4Address> saveRoute (nodeList);
+          PrintVector (saveRoute);
+          // Verify if the two vector contains duplicates, if so, do not use
+          // the route found and forward the route request
+          if (!(IfDuplicates (ip, nodeList)))
+            {
+              m_finalRoute.clear (); // Clear the final route vector
+              /**
+               * push back the intermediate node address from the source to this node
+               */
+              for (std::vector<Ipv4Address>::iterator i = nodeList.begin (); i != nodeList.end (); ++i)
+                {
+                  m_finalRoute.push_back (*i);
+                }
+              /**
+               * push back the route vector we found in our route cache to destination, including this node's address
+               */
+              for (std::vector<Ipv4Address>::iterator j = ip.begin (); j != ip.end (); ++j)
+                {
+                  m_finalRoute.push_back (*j);
+                }
+              /*
+               * Create the route entry to the rreq originator and save it to route cache, also need to reverse the route
+               */
+              bool addRoute = false;
+              std::vector<Ipv4Address> reverseRoute (m_finalRoute);
+
+              if (ReverseRoutes (reverseRoute))
+                {
+                  Ipv4Address dst = reverseRoute.back ();
+                  saveRoute.push_back (ipv4Address);
+                  ReverseRoutes (saveRoute);
+                  PrintVector (saveRoute);
+                  RouteCacheEntry toSource (/*IP_VECTOR=*/ saveRoute, /*dst=*/ dst, /*expire time=*/ ActiveRouteTimeout);
+                  NS_ASSERT (saveRoute.front () == ipv4Address);
+                  // Add the route entry in the route cache
+                  if (m_routeCache->IsLinkCache ())
+                    {
+                      addRoute = m_routeCache->AddRoute_Link (saveRoute, ipv4Address);
+                    }
+                  else
+                    {
+                      addRoute = m_routeCache->AddRoute (toSource);
+                    }
+                  if (addRoute)
+                    {
+                      NS_LOG_DEBUG ("The route is failed to add in cache");
+                      return 0;
+                    }
+                  else
+                    {
+                      NS_LOG_DEBUG ("We have added the route and search send buffer for packet with destination " << dst);
+                      /*
+                       * Found a route the dst, construct the source route option header
+                       */
+                      DsrOptionSRHeader sourceRoute;
+                      NS_LOG_DEBUG ("The route length " << reverseRoute.size ());
+                      sourceRoute.SetNodesAddress (reverseRoute);
+                      if (m_routeCache->IsLinkCache ())
+                        {
+                          m_routeCache->UseExtends (reverseRoute);
+                        }
+                      sourceRoute.SetSegmentsLeft ((saveRoute.size () - 2));
+                      uint8_t salvage = 0;
+                      sourceRoute.SetSalvage (salvage);
+                      Ipv4Address nextHop = SearchNextHop (ipv4Address, reverseRoute); // Get the next hop address
+                      NS_LOG_DEBUG ("The nextHop address " << nextHop);
+
+                      if (nextHop == "0.0.0.0")
+                        {
+                          dsr->PacketNewRoute (dsrP, ipv4Address, dst, protocol);
+                          return 0;
+                        }
+                      SetRoute (nextHop, ipv4Address);
+                      /*
+                       * Schedule the packet retry
+                       */
+                      dsr->SendPacket (sourceRoute, nextHop, protocol);
+                      // Cancel the route request timer for destination
+                      dsr->CancelRreqTimer (dst);
+                    }
+                }
+              else
+                {
+                  NS_LOG_DEBUG ("Unable to reverse the route");
+                }
+
+              /*
+               * Need to first pin down the next hop address before removing duplicates
+               */
+              Ipv4Address nextHop = ReverseSearchNextHop (ipv4Address, m_finalRoute);
+              /*
+               * First remove the duplicate ip address to automatically shorten the route, and then reversely
+               * search the next hop address
+               */
+              PrintVector (m_finalRoute);
+              // Set the route
+              SetRoute (nextHop, ipv4Address);
+
+              uint16_t hops = m_finalRoute.size ();
+              DsrOptionRrepHeader rrep;
+              rrep.SetNodesAddress (m_finalRoute);     // Set the node addresses in the route reply header
+              NS_LOG_DEBUG ("The nextHop address " << nextHop);
+              // Get the real source of the reply
+              Ipv4Address realSource = m_finalRoute.back ();
+              /*
+               * This part add dsr header to the packet and send reply
+               */
+              DsrRoutingHeader dsrRoutingHeader;
+              dsrRoutingHeader.SetNextHeader (protocol);
+              dsrRoutingHeader.SetMessageType (1);
+              dsrRoutingHeader.SetSourceId (GetIDfromIP (realSource));
+              dsrRoutingHeader.SetDestId (255);
+
+              uint8_t length = rrep.GetLength ();  // Get the length of the rrep header excluding the type header
+              dsrRoutingHeader.SetPayloadLength (length + 2);
+              dsrRoutingHeader.AddDsrOption (rrep);
+              Ptr<Packet> newPacket = Create<Packet> ();
+              newPacket->AddHeader (dsrRoutingHeader);
+              dsr->ScheduleCachedReply (newPacket, ipv4Address, nextHop, m_ipv4Route, hops);
+              isPromisc = false;
+            }
+        }
+      /*
+       * (iii) no route in any type has been found
+       */
+      else
+        {
+          std::vector<Ipv4Address> nodeList = rreq.GetNodesAddresses (); // route from rreq header
+          PrintVector (nodeList);
+          /*
+           * Otherwise, forward the route request packet
+           */
+          PrintVector (nodeList);
+          nodeList.push_back (ipv4Address);
+          PrintVector (nodeList);
+          NS_ASSERT (nodeList.front () == source);
+          rreq.SetNodesAddress (nodeList);
+          /*
+          * Decrease the TTL value in the packet tag by one, this tag will go to ip layer 3 send function
+          * and drop packet when TTL value equals to 0
+          */
+          if (ttl)
+            {
+              Ptr<Packet> interP = Create<Packet> ();
+              SocketIpTtlTag tag;
+              tag.SetTtl (ttl - 1);
+              interP->AddPacketTag (tag);
+              /*
+               * Construct the route request header to forward the route requests
+               */
+              DsrRoutingHeader dsrRoutingHeader;
+              dsrRoutingHeader.SetNextHeader (protocol);
+              dsrRoutingHeader.SetMessageType (1);
+              dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+              dsrRoutingHeader.SetDestId (255);
+              dsrRoutingHeader.AddDsrOption (rreq);
+
+              // if the errP packet is not 0, then there is an error header after it
+              if (errP->GetSize ())
+                {
+                  NS_LOG_DEBUG ("Error header included");
+                  DsrOptionRerrUnreachHeader rerr;
+                  p->RemoveHeader (rerr);
+                  Ipv4Address errorSrc = rerr.GetErrorSrc ();
+                  Ipv4Address unreachNode = rerr.GetUnreachNode ();
+                  isError = true;
+                  m_routeCache->DeleteAllRoutesIncludeLink (errorSrc, unreachNode, ipv4Address);
+
+                  DsrOptionRerrUnreachHeader newUnreach;
+                  newUnreach.SetErrorType (1);
+                  newUnreach.SetErrorSrc (rerr.GetErrorSrc ());
+                  newUnreach.SetUnreachNode (rerr.GetUnreachNode ());
+                  newUnreach.SetErrorDst (rerr.GetErrorDst ());
+                  newUnreach.SetSalvage (rerr.GetSalvage ()); // Set the value about whether to salvage a packet or not
+                  dsrRoutingHeader.AddDsrOption (newUnreach);
+                  uint16_t length = rreq.GetLength () + newUnreach.GetLength ();
+                  NS_LOG_DEBUG ("The RREQ and newUnreach header length " <<  length);
+                  dsrRoutingHeader.SetPayloadLength (length + 4);
+                  interP->AddHeader (dsrRoutingHeader);
+                }
+              else
+                {
+                  uint16_t length = rreq.GetLength ();
+                  NS_LOG_DEBUG ("The RREQ header length " <<  length);
+                  dsrRoutingHeader.SetPayloadLength (length + 2);
+                  interP->AddHeader (dsrRoutingHeader);
+                }
+
+              dsr->ScheduleInterRequest (interP);
+              isPromisc = false;
+            }
+        }
+    }
+
+  return rreq.GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRrep);
+
+TypeId DsrOptionRrep::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRrep")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionRrep> ()
+  ;
+  return tid;
+}
+
+DsrOptionRrep::DsrOptionRrep ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionRrep::~DsrOptionRrep ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+TypeId DsrOptionRrep::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+uint8_t DsrOptionRrep::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionRrep::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
+
+  Ptr<Packet> p = packet->Copy ();
+
+  // Get the number of routers' address field
+  uint8_t buf[2];
+  p->CopyData (buf, sizeof(buf));
+  uint8_t numberAddress = (buf[1] - 2) / 4;
+
+  DsrOptionRrepHeader rrep;
+  rrep.SetNumberAddress (numberAddress);  // Set the number of ip address in the header to reserver space for deserialize header
+  p->RemoveHeader (rrep);
+
+  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+  Ptr<dsr::RouteCache> m_routeCache = node->GetObject<dsr::RouteCache> ();
+  Ptr<dsr::RreqTable>  m_rreqTable = node->GetObject<dsr::RreqTable> ();
+  ActiveRouteTimeout = m_routeCache->GetCacheTimeout ();
+
+  NS_LOG_DEBUG ("The next header value " << (uint32_t)protocol);
+
+  std::vector<Ipv4Address> nodeList = rrep.GetNodesAddress ();
+  /*
+   * Get the destination address, which is the last element in the nodeList
+   */
+  Ipv4Address targetAddress = nodeList.front ();
+  // If the RREP option has reached to the destination
+  if (targetAddress == ipv4Address)
+    {
+      RemoveDuplicates (nodeList); // This is for the route reply from intermediate node since we didn't remove
+                                   // duplicate there
+      if (nodeList.size () == 0)
+        {
+          NS_LOG_DEBUG ("The route we have contains 0 entries");
+          return 0;
+        }
+      /*
+       * Get the destination address for the data packet, which is the last element in the nodeList
+       */
+      Ipv4Address dst = nodeList.back ();
+      /*
+       * Add the newly found route to the route cache
+       * The route looks like:
+       * \\ "srcAddress" + "intermediate node address" + "targetAddress"
+       */
+      RouteCacheEntry toDestination (/*IP_VECTOR=*/ nodeList, /*dst=*/ dst, /*expire time=*/ ActiveRouteTimeout);
+      NS_ASSERT (nodeList.front () == ipv4Address);
+      bool addRoute = false;
+      if (m_routeCache->IsLinkCache ())
+        {
+          m_routeCache->AddRoute_Link (nodeList, ipv4Address);
+        }
+      else
+        {
+          m_routeCache->AddRoute (toDestination);
+        }
+      if (addRoute)
+        {
+          NS_LOG_DEBUG ("Failed to add the route");
+          return 0;
+        }
+      else
+        {
+          NS_LOG_DEBUG ("We have added the route and search send buffer for packet with destination " << dst);
+          /*
+           * Found a route the dst, construct the source route option header
+           */
+          DsrOptionSRHeader sourceRoute;
+          NS_LOG_DEBUG ("The route length " << nodeList.size ());
+          sourceRoute.SetNodesAddress (nodeList);
+          sourceRoute.SetSegmentsLeft ((nodeList.size () - 2));
+          uint8_t salvage = 0;
+          sourceRoute.SetSalvage (salvage);
+          Ipv4Address nextHop = SearchNextHop (ipv4Address, nodeList); // Get the next hop address
+          NS_LOG_DEBUG ("The nextHop address " << nextHop);
+          if (nextHop == "0.0.0.0")
+            {
+              dsr->PacketNewRoute (dsrP, ipv4Address, dst, protocol);
+              return 0;
+            }
+          PrintVector (nodeList);
+          SetRoute (nextHop, ipv4Address);
+          /*
+           * Schedule the packet retry
+           */
+          dsr->SendPacket (sourceRoute, nextHop, protocol);
+          // Cancel the route request timer for destination
+          dsr->CancelRreqTimer (dst);
+        }
+    }
+  else
+    {
+      uint8_t length = rrep.GetLength () - 2; // The get length - 2 is to get aligned for the malformed header check
+      NS_LOG_DEBUG ("The length of rrep option " << (uint32_t)length);
+
+      if (length % 2 != 0)
+        {
+          NS_LOG_LOGIC ("Malformed header. Drop!");
+          m_dropTrace (packet);
+          return 0;
+        }
+      PrintVector (nodeList);
+      /*
+       * This node is only an intermediate node, but it needs to save the possible route to the destination when cutting the route
+       */
+      std::vector<Ipv4Address> routeCopy = nodeList;
+      std::vector<Ipv4Address> cutRoute = CutRoute (ipv4Address, nodeList);
+      PrintVector (cutRoute);
+      if (cutRoute.size () >= 2)
+        {
+          Ipv4Address dst = cutRoute.back ();
+          NS_LOG_DEBUG ("The route destination after cut " << dst);
+          RouteCacheEntry toDestination (/*IP_VECTOR=*/ cutRoute, /*dst=*/ dst, /*expire time=*/ ActiveRouteTimeout);
+          NS_ASSERT (cutRoute.front () == ipv4Address);
+          bool addRoute = false;
+          if (m_routeCache->IsLinkCache ())
+            {
+              m_routeCache->AddRoute_Link (nodeList, ipv4Address);
+            }
+          else
+            {
+              m_routeCache->AddRoute (toDestination);
+            }
+          if (addRoute)
+            {
+              dsr->CancelRreqTimer (dst);
+            }
+          else
+            {
+              NS_LOG_DEBUG ("The route not added");
+            }
+        }
+      else
+        {
+          NS_LOG_DEBUG ("The route is corrupted");
+        }
+      /*
+       * Reverse search the vector for next hop address
+       */
+      Ipv4Address nextHop = ReverseSearchNextHop (ipv4Address, routeCopy);
+      NS_ASSERT (routeCopy.back () == source);
+      PrintVector (routeCopy);
+      NS_LOG_DEBUG ("The nextHop address " << nextHop << " and the source in the route reply " << source);
+      /*
+       * Set the route entry we will use to send reply
+       */
+      SetRoute (nextHop, ipv4Address);
+      /*
+       * This part add dsr routing header to the packet and send reply
+       */
+      DsrRoutingHeader dsrRoutingHeader;
+      dsrRoutingHeader.SetNextHeader (protocol);
+
+      length = rrep.GetLength ();    // Get the length of the rrep header excluding the type header
+      NS_LOG_DEBUG ("The reply header length " << (uint32_t)length);
+      dsrRoutingHeader.SetPayloadLength (length + 2);
+      dsrRoutingHeader.SetMessageType (1);
+      dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+      dsrRoutingHeader.SetDestId (GetIDfromIP (targetAddress));
+      dsrRoutingHeader.AddDsrOption (rrep);
+      Ptr<Packet> newPacket = Create<Packet> ();
+      newPacket->AddHeader (dsrRoutingHeader);
+      dsr->SendReply (newPacket, ipv4Address, nextHop, m_ipv4Route);
+      isPromisc = false;
+    }
+  return rrep.GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionSR);
+
+TypeId DsrOptionSR::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionSR")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionSR> ()
+  ;
+  return tid;
+}
+
+DsrOptionSR::DsrOptionSR ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionSR::~DsrOptionSR ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+TypeId DsrOptionSR::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+uint8_t DsrOptionSR::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionSR::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Address << ipv4Header << (uint32_t)protocol << isPromisc);
+  Ptr<Packet> p = packet->Copy ();
+  // Get the number of routers' address field
+  uint8_t buf[2];
+  p->CopyData (buf, sizeof(buf));
+  uint8_t numberAddress = (buf[1] - 2) / 4;
+  DsrOptionSRHeader sourceRoute;
+  sourceRoute.SetNumberAddress (numberAddress);
+  p->RemoveHeader (sourceRoute);
+
+  // The route size saved in the source route
+  std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
+
+  uint8_t segsLeft = sourceRoute.GetSegmentsLeft ();
+  uint8_t salvage = sourceRoute.GetSalvage ();
+
+  // Here we remove the ack packet to the previous hop
+  DsrOptionAckReqHeader ackReq;
+  p->RemoveHeader (ackReq);
+  uint16_t ackId = ackReq.GetAckId ();
+  /*
+   * Get the node from IP address and get the DSR extension object
+   */
+  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+  /*
+   * Get the source and destination address from ipv4 header
+   */
+  Ipv4Address srcAddress = ipv4Header.GetSource ();
+  Ipv4Address destAddress = ipv4Header.GetDestination ();
+  // Get the node list destination
+  Ipv4Address destination = nodeList.back ();
+  /*
+   * If it's a promiscuous receive data packet,
+   * 1. see if automatic route shortening possible or not
+   * 2. see if it is a passive acknowledgment
+   */
+  if (isPromisc)
+    {
+      /*
+       * Get the node from Ip address and get the dsr routing object
+       */
+      Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+      Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+
+      bool findSame = dsr->FindSamePackets (packet, ipv4Header, source, destination, segsLeft);
+
+      if (findSame)
+        {
+          NS_LOG_DEBUG ("Received one passive acknowledgment for data packet");
+        }
+      if (ContainAddressAfter (ipv4Address, destAddress, nodeList))
+        {
+          NS_LOG_DEBUG ("Send back the gratuitous reply");
+          dsr->SendGratuitousReply (source, srcAddress, nodeList, protocol);
+        }
+      else
+        {
+          return 0;
+        }
+    }
+  else
+    {
+      /*
+       * Get the number of address from the source route header
+       */
+      uint8_t length = sourceRoute.GetLength ();
+      uint8_t nextAddressIndex;
+      Ipv4Address nextAddress;
+      /*
+       * Send back acknowledgment packet to the earlier hop
+       */
+      m_ipv4Route = SetRoute (srcAddress, ipv4Address);
+      NS_LOG_DEBUG ("Send back ACK to the earlier hop " << srcAddress << " from us " << ipv4Address);
+      dsr->SendAck (ackId, srcAddress, source, destination, protocol, m_ipv4Route);
+      /*
+       * After send back ACK, check if the segments left value has turned to 0 or not, if yes, update the route entry
+       * and return header length
+       */
+      if (segsLeft == 0)
+        {
+          isPromisc = false;
+          return sourceRoute.GetSerializedSize ();
+        }
+
+      if (length % 2 != 0)
+        {
+          NS_LOG_LOGIC ("Malformed header. Drop!");
+          m_dropTrace (packet);
+          return 0;
+        }
+
+      if (segsLeft > numberAddress) // The segmentsLeft field should not be larger than the total number of ip addresses
+        {
+          NS_LOG_LOGIC ("Malformed header. Drop!");
+          m_dropTrace (packet);
+          return 0;
+        }
+
+      DsrOptionSRHeader newSourceRoute;
+      newSourceRoute.SetSegmentsLeft (segsLeft - 1);
+      newSourceRoute.SetSalvage (salvage);
+      newSourceRoute.SetNodesAddress (nodeList);
+      nextAddressIndex = numberAddress - segsLeft;
+      nextAddress = newSourceRoute.GetNodeAddress (nextAddressIndex);
+      NS_LOG_DEBUG ("The next address of source route option " << nextAddress << " and the nextAddressIndex: " << (uint32_t)nextAddressIndex << " and the segments left : " << (uint32_t)segsLeft);
+      /*
+       * Get the target Address in the node list
+       */
+      Ipv4Address targetAddress = nodeList.back ();
+      Ipv4Address realSource = nodeList.front ();
+      /*
+       * Search the vector for next hop address
+       */
+      Ipv4Address nextHop = SearchNextHop (ipv4Address, nodeList);
+      PrintVector (nodeList);
+
+      if (nextHop == "0.0.0.0")
+        {
+          NS_LOG_DEBUG ("Before new packet " << *dsrP);
+          dsr->PacketNewRoute (dsrP, realSource, targetAddress, protocol);
+          return 0;
+        }
+
+      if (ipv4Address == nextHop)
+        {
+          NS_LOG_DEBUG ("We have reached the destination");
+          newSourceRoute.SetSegmentsLeft (0);
+          return newSourceRoute.GetSerializedSize ();
+        }
+      // Verify the multicast address, leave it here for now
+      if (nextAddress.IsMulticast () || destAddress.IsMulticast ())
+        {
+          m_dropTrace (packet);
+          return 0;
+        }
+      // Set the route and forward the data packet
+      SetRoute (nextAddress, ipv4Address);
+      dsr->ForwardPacket (dsrP, newSourceRoute, ipv4Header, realSource, nextAddress, targetAddress, protocol, m_ipv4Route);
+    }
+  return sourceRoute.GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionRerr);
+
+TypeId DsrOptionRerr::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionRerr")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionRerr> ()
+  ;
+  return tid;
+}
+
+DsrOptionRerr::DsrOptionRerr ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionRerr::~DsrOptionRerr ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+TypeId DsrOptionRerr::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+uint8_t DsrOptionRerr::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionRerr::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
+
+  Ptr<Packet> p = packet->Copy ();
+  uint32_t size = p->GetSize ();
+  uint8_t *data = new uint8_t[size];
+  p->CopyData (data, size);
+  uint8_t errorType = *(data + 2);
+  /*
+   * Get the node from Ip address and get the dsr extension object
+   */
+  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+
+  Ipv4Address srcAddress = ipv4Header.GetSource ();
+  Ipv4Address destAddress = ipv4Header.GetDestination ();
+  /*
+   * The error serialized size
+   */
+  uint32_t rerrSize;
+  if (errorType == 1) // unreachable ip address
+    {
+      /*
+       * Remove the route error header from the packet, and get the error type
+       */
+      DsrOptionRerrUnreachHeader rerrUnreach;
+      p->RemoveHeader (rerrUnreach);
+      /*
+       * Get the error destination address
+       */
+      Ipv4Address targetAddress = rerrUnreach.GetErrorDst ();
+      Ipv4Address unreachAddress = rerrUnreach.GetUnreachNode ();
+      Ipv4Address errorSource = rerrUnreach.GetErrorSrc ();
+
+      NS_LOG_DEBUG ("The destination address and the unreachable node " << targetAddress << " " << unreachAddress);
+      /*
+       * Get the serialized size of the rerr header
+       */
+      rerrSize = rerrUnreach.GetSerializedSize ();
+      /*
+       * Delete all the routes including the unreachable node address from the route cache
+       */
+      Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+      Ptr<dsr::RouteCache> m_routeCache = node->GetObject<dsr::RouteCache> ();
+      m_routeCache->DeleteAllRoutesIncludeLink (errorSource, unreachAddress, ipv4Address);
+
+      Ptr<Packet> newP = p->Copy ();
+      uint32_t serialized = DoSendError (newP, rerrUnreach, rerrSize, ipv4Address, protocol);
+      return serialized;
+    }
+  else
+    {
+      /*
+       * Two other type of error headers:
+       * 1. flow state not supported type-specific information
+       * 2. unsupported option with option number
+       */
+      /*
+       * Remove the route error header from the packet, and get the error type
+       */
+      DsrOptionRerrUnsupportHeader rerrUnsupport;
+      p->RemoveHeader (rerrUnsupport);
+      rerrSize = rerrUnsupport.GetSerializedSize ();
+
+      // This is for the other two error options TODO
+//      uint32_t serialized = DoSendError (p, rerrUnsupport, rerrSize, ipv4Address, protocol);
+      uint32_t serialized = 0;
+      return serialized;
+    }
+}
+
+uint8_t DsrOptionRerr::DoSendError (Ptr<Packet> p, DsrOptionRerrUnreachHeader &rerr, uint32_t rerrSize, Ipv4Address ipv4Address, uint8_t protocol)
+{
+  // Get the number of routers' address field
+  uint8_t buf[2];
+  p->CopyData (buf, sizeof(buf));
+  uint8_t numberAddress = (buf[1] - 2) / 4;
+
+  // Here remove the source route header and schedule next hop error transmission
+  NS_LOG_DEBUG ("The number of addresses " << (uint32_t)numberAddress);
+  DsrOptionSRHeader sourceRoute;
+  sourceRoute.SetNumberAddress (numberAddress);
+  p->RemoveHeader (sourceRoute);
+  NS_ASSERT (p->GetSize () == 0);
+  /*
+   * Get the node from ip address and the dsr extension object
+   */
+  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+  /*
+   * Get the segments left field and the next address
+   */
+  uint8_t segmentsLeft = sourceRoute.GetSegmentsLeft ();
+  NS_LOG_DEBUG ("The segments left " << (uint32_t)segmentsLeft);
+  uint8_t length = sourceRoute.GetLength ();
+  NS_LOG_DEBUG ("The number of addresses we have " << (uint32_t)numberAddress);
+  uint8_t nextAddressIndex;
+  Ipv4Address nextAddress;
+  /*
+   * Get the route size and the error target address
+   */
+  std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
+  Ipv4Address targetAddress = nodeList.back ();
+  /*
+   * The total serialized size for both the rerr and source route headers
+   */
+  uint32_t serializedSize = rerrSize + sourceRoute.GetSerializedSize ();
+
+  if (length % 2 != 0)
+    {
+      NS_LOG_LOGIC ("Malformed header. Drop!");
+      m_dropTrace (p);
+      return 0;
+    }
+
+  if (segmentsLeft > numberAddress)
+    {
+      NS_LOG_LOGIC ("Malformed header. Drop!");
+      m_dropTrace (p);
+      return 0;
+    }
+  /*
+   * When the error packet has reached to the destination
+   */
+  if (segmentsLeft == 0 && targetAddress == ipv4Address)
+    {
+      NS_LOG_DEBUG ("This is the destination of the error");
+      dsr->SendErrorRequest (rerr, protocol);
+      return serializedSize;
+    }
+
+  DsrOptionRerrUnreachHeader newUnreach;
+  newUnreach.SetErrorType (1);
+  newUnreach.SetErrorSrc (rerr.GetErrorSrc ());
+  newUnreach.SetUnreachNode (rerr.GetUnreachNode ());
+  newUnreach.SetErrorDst (rerr.GetErrorDst ());
+  newUnreach.SetSalvage (rerr.GetSalvage ()); // Set the value about whether to salvage a packet or not
+
+  // Get the next Router Address
+  DsrOptionSRHeader newSourceRoute;
+  newSourceRoute.SetSegmentsLeft (segmentsLeft - 1);
+  nextAddressIndex = numberAddress - segmentsLeft;
+  nextAddress = sourceRoute.GetNodeAddress (nextAddressIndex);
+  newSourceRoute.SetSalvage (sourceRoute.GetSalvage ());
+  newSourceRoute.SetNodesAddress (nodeList);
+  nextAddress = newSourceRoute.GetNodeAddress (nextAddressIndex);
+
+  // / to test if the next address is multicast or not
+  if (nextAddress.IsMulticast () || targetAddress.IsMulticast ())
+    {
+      m_dropTrace (p);
+      return serializedSize;
+    }
+
+  // Set the route entry
+  SetRoute (nextAddress, ipv4Address);
+  dsr->ForwardErrPacket (newUnreach, newSourceRoute, nextAddress, protocol, m_ipv4Route);
+  return serializedSize;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionAckReq);
+
+TypeId DsrOptionAckReq::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionAckReq")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionAckReq> ()
+  ;
+  return tid;
+}
+
+DsrOptionAckReq::DsrOptionAckReq ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionAckReq::~DsrOptionAckReq ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+TypeId DsrOptionAckReq::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+uint8_t DsrOptionAckReq::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionAckReq::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
+  /*
+   * Current implementation of the ack request header processing is coded in source route header processing
+   */
+  /*
+   * Remove the ack request header
+   */
+  Ptr<Packet> p = packet->Copy ();
+  DsrOptionAckReqHeader ackReq;
+  p->RemoveHeader (ackReq);
+  /*
+   * Get the node with ip address and get the dsr extension and reoute cache objects
+   */
+  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+  Ptr<dsr::RouteCache> m_routeCache = node->GetObject<dsr::RouteCache> ();
+
+  NS_LOG_DEBUG ("The next header value " << (uint32_t)protocol);
+
+  Ipv4Address srcAddress = ipv4Header.GetSource ();
+  SetRoute (srcAddress, ipv4Address);
+
+  return ackReq.GetSerializedSize ();
+}
+
+NS_OBJECT_ENSURE_REGISTERED (DsrOptionAck);
+
+TypeId DsrOptionAck::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrOptionAck")
+    .SetParent<DsrOptions> ()
+    .AddConstructor<DsrOptionAck> ()
+  ;
+  return tid;
+}
+
+DsrOptionAck::DsrOptionAck ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+DsrOptionAck::~DsrOptionAck ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+TypeId DsrOptionAck::GetInstanceTypeId () const
+{
+  return GetTypeId ();
+}
+
+uint8_t DsrOptionAck::GetOptionNumber () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return OPT_NUMBER;
+}
+
+uint8_t DsrOptionAck::Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc)
+{
+  NS_LOG_FUNCTION (this << packet << dsrP << ipv4Address << source << ipv4Header << (uint32_t)protocol << isPromisc);
+  /*
+   * Remove the ACK header
+   */
+  Ptr<Packet> p = packet->Copy ();
+  DsrOptionAckHeader ack;
+  p->RemoveHeader (ack);
+  /*
+   * Get the ACK source and destination address
+   */
+  Ipv4Address realSrc = ack.GetRealSrc ();
+  Ipv4Address realDst = ack.GetRealDst ();
+  uint16_t ackId = ack.GetAckId ();
+  /*
+   * Get the node with ip address and get the dsr extension and route cache objects
+   */
+  Ptr<Node> node = GetNodeWithAddress (ipv4Address);
+  Ptr<dsr::DsrRouting> dsr = node->GetObject<dsr::DsrRouting> ();
+  Ptr<dsr::RouteCache> srcRouteCache = node->GetObject<dsr::RouteCache> ();
+  srcRouteCache->UpdateRouteEntry (realDst);
+  /*
+   * Cancel the packet retransmit timer when receiving the ack packet
+   */
+  dsr->CallCancelPacketTimer (ackId, ipv4Header, realSrc, realDst);
+  return ack.GetSerializedSize ();
+}
+
+} // namespace dsr
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-options.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,696 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_OPTION_H
+#define DSR_OPTION_H
+
+#include <map>
+#include <list>
+
+#include "ns3/buffer.h"
+#include "ns3/packet.h"
+#include "ns3/callback.h"
+#include "ns3/ptr.h"
+#include "ns3/ipv4-l4-protocol.h"
+#include "ns3/udp-l4-protocol.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/object.h"
+#include "ns3/node.h"
+#include "ns3/ipv4-interface.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/traced-callback.h"
+#include "ns3/output-stream-wrapper.h"
+#include "ns3/timer.h"
+
+#include "dsr-rsendbuff.h"
+#include "dsr-maintain-buff.h"
+#include "dsr-option-header.h"
+#include "dsr-rcache.h"
+#include "dsr-routing.h"
+#include "dsr-gratuitous-reply-table.h"
+
+namespace ns3 {
+
+class Packet;
+class NetDevice;
+class Node;
+class Ipv4Address;
+class Ipv4Interface;
+class Ipv4Route;
+class Ipv4;
+class Time;
+
+namespace dsr {
+
+class DsrOptions : public Object
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId (void);
+  /**
+   * \brief Constructor.
+   */
+  DsrOptions ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptions ();
+  /**
+    * \brief Get the option number.
+    * \return option number
+    */
+  virtual uint8_t GetOptionNumber () const = 0;
+  /**
+   * \brief Set the node.
+   * \param node the node to set
+   */
+  void SetNode (Ptr<Node> node);
+  /**
+   * \brief Get the node.
+   * \return the node
+   */
+  Ptr<Node> GetNode () const;
+  /**
+   * \brief Search for the ipv4 address in the node list.
+   * \return true if contain ip address
+   */
+  bool ContainAddressAfter (Ipv4Address ipv4Address, Ipv4Address destAddress, std::vector<Ipv4Address> &nodeList);
+  /**
+   * \brief Cut the route from ipv4Address to the end of the route vector
+   * \return the vector after the route cut
+   */
+  std::vector<Ipv4Address> CutRoute (Ipv4Address ipv4Address, std::vector<Ipv4Address> &nodeList);
+  /*
+   * \brief Set the route to use for data packets
+   * \return the route
+   * \used by the option headers when sending data/control packets
+   */
+  virtual Ptr<Ipv4Route> SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress);
+  /**
+   * \brief Reverse the routes.
+   * \return true if successfully reversed
+   */
+  bool ReverseRoutes  (std::vector<Ipv4Address>& vec);
+  /*
+   * \brief Search for the next hop in the route
+   * \return the next hop address if found
+   */
+  Ipv4Address SearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec);
+  /*
+   * \brief Reverse search for the next hop in the route
+   * \return the next hop address if found
+   */
+  Ipv4Address ReverseSearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec);
+  /*
+   * \brief Print out the elements in the route vector
+   */
+  void PrintVector (std::vector<Ipv4Address>& vec);
+  /*
+   * \brief Check if the two vectors contain duplicate or not
+   * \return true if contains duplicate
+   */
+  bool IfDuplicates (std::vector<Ipv4Address>& vec, std::vector<Ipv4Address>& vec2);
+  /*
+   * \brief Check if the route already contains the node ip address
+   * \return true if it already exists
+   */
+  bool CheckDuplicates (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec);
+  /*
+   * \brief Remove the duplicates from the route
+   * \return the route after route shorten
+   */
+  void RemoveDuplicates (std::vector<Ipv4Address>& vec);
+  /*
+   * \brief Schedule the intermediate node route request broadcast
+   * \param the original packet
+   * \param rrepHeader The rrep header
+   * \param source address
+   * \param destination address
+   */
+  void ScheduleReply (Ptr<Packet> &packet, std::vector<Ipv4Address> &nodeList, Ipv4Address &source, Ipv4Address &destination);
+  /*
+   * \brief Get the node id with Ipv4Address
+   * \return the id of the node
+   */
+  uint32_t GetIDfromIP (Ipv4Address address);
+  /*
+   * \brief Get the node object with Ipv4Address
+   * \return the object of the node
+   */
+  Ptr<Node> GetNodeWithAddress (Ipv4Address ipv4Address);
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc) = 0;
+
+protected:
+  /**
+   * \brief Drop trace callback.
+   */
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
+  /**
+   * \brief The broadcast IP address.
+   */
+  Ipv4Address Broadcast;
+  /**
+   * \brief The route request table.
+   */
+  Ptr<dsr::RreqTable> m_rreqTable;
+  /**
+   * \brief The route cache table.
+   */
+  Ptr<dsr::RouteCache> m_routeCache;
+  /**
+   * \brief The ipv4 route.
+   */
+  Ptr<Ipv4Route> m_ipv4Route;
+  /**
+   * \brief The ipv4.
+   */
+  Ptr<Ipv4> m_ipv4;
+  /**
+   * \brief The vector of Ipv4 address.
+   */
+  std::vector<Ipv4Address> m_ipv4Address;
+  /**
+   * \brief The vector of final Ipv4 address.
+   */
+  std::vector<Ipv4Address> m_finalRoute;
+  /**
+   * \brief The active route timeout value.
+   */
+  Time ActiveRouteTimeout;
+  /*
+   * The receive trace back, only triggered when final destination receive data packet
+   */
+  TracedCallback <const DsrOptionSRHeader &> m_rxPacketTrace;
+
+private:
+  Ptr<Node> m_node;
+};
+
+/**
+ * \class DsrOptionPad1
+ * \brief Dsr Option Pad1
+ */
+class DsrOptionPad1 : public DsrOptions
+{
+public:
+  /**
+   * \brief Pad1 option number.
+   */
+  static const uint8_t OPT_NUMBER = 224;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionPad1 ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionPad1 ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+};
+
+/**
+ * \class DsrOptionPadn
+ * \brief IPv4 Option Padn
+ */
+class DsrOptionPadn : public DsrOptions
+{
+public:
+  /**
+   * \brief PadN option number.
+   */
+  static const uint8_t OPT_NUMBER = 0;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionPadn ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionPadn ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+};
+
+/**
+ * \class DsrOptionRreq
+ * \brief Dsr Option Rreq
+ */
+class DsrOptionRreq : public DsrOptions
+{
+public:
+  /**
+   * \brief Rreq option number.
+   */
+  static const uint8_t OPT_NUMBER = 1;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRreq ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRreq ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+
+private:
+  /**
+   * \brief The route cache.
+   */
+  Ptr<dsr::RouteCache> m_routeCache;
+  /**
+   * \brief The ipv4.
+   */
+  Ptr<Ipv4> m_ipv4;
+};
+
+/**
+ * \class DsrOptionRrep
+ * \brief Dsr Option Route Reply
+ */
+class DsrOptionRrep : public DsrOptions
+{
+public:
+  /**
+   * \brief Router alert option number.
+   */
+  static const uint8_t OPT_NUMBER = 2;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRrep ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRrep ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+
+private:
+  /**
+   * \brief The route cache.
+   */
+  Ptr<dsr::RouteCache> m_routeCache;
+  /**
+   * \brief The length of the packet.
+   */
+  uint32_t m_length;
+  /**
+   * \brief The ip layer 3.
+   */
+  Ptr<Ipv4> m_ipv4;
+};
+
+/**
+ * \class DsrOptionSR
+ * \brief Dsr Option Source Route
+ */
+class DsrOptionSR : public DsrOptions
+{
+public:
+  /**
+   * \brief Source Route option number.
+   */
+  static const uint8_t OPT_NUMBER = 96;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionSR ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionSR ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+
+private:
+  /**
+   * \brief The length of the packet.
+   */
+  uint32_t m_length;
+  /**
+   * \brief The ip layer 3.
+   */
+  Ptr<Ipv4> m_ipv4;
+};
+
+/**
+ * \class DsrOptionRerr
+ * \brief Dsr Option Route Error
+ */
+class DsrOptionRerr : public DsrOptions
+{
+public:
+  /**
+   * \brief Dsr Route Error option number.
+   */
+  static const uint8_t OPT_NUMBER = 3;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionRerr ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionRerr ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+  /**
+   * \brief Do Send error message
+   *
+   * \param p the packet
+   * \param rerr  the DsrOptionRerrUnreachHeader header
+   * \param rerrSize the route error header size
+   * \param ipv4Address ipv4 address of our own
+   * \param protocol the protocol number of the up layer
+   * \return the processed size
+   */
+  uint8_t DoSendError (Ptr<Packet> p, DsrOptionRerrUnreachHeader &rerr, uint32_t rerrSize, Ipv4Address ipv4Address, uint8_t protocol);
+
+private:
+  /**
+   * \brief The route cache.
+   */
+  Ptr<dsr::RouteCache> m_routeCache;
+  /**
+   * \brief The length of the packet.
+   */
+  uint32_t m_length;
+  /**
+   * \brief The ipv4 layer 3.
+   */
+  Ptr<Ipv4> m_ipv4;
+};
+
+/**
+ * \class DsrOptionAckReq
+ * \brief Dsr Option
+ */
+class DsrOptionAckReq : public DsrOptions
+{
+public:
+  /**
+   * \brief Dsr ack request option number.
+   */
+  static const uint8_t OPT_NUMBER = 160;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionAckReq ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionAckReq ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+
+private:
+  /**
+   * \brief The route cache.
+   */
+  Ptr<dsr::RouteCache> m_routeCache;
+  /**
+   * \brief The length of the packet.
+   */
+  uint32_t m_length;
+  /**
+   * \brief The ipv4 layer 3.
+   */
+  Ptr<Ipv4> m_ipv4;
+};
+
+/**
+ * \class DsrOptionAck
+ * \brief Dsr Option Ack
+ */
+class DsrOptionAck : public DsrOptions
+{
+public:
+  /**
+   * \brief The Dsr Ack option number.
+   */
+  static const uint8_t OPT_NUMBER = 32;
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Get the instance type ID.
+   * \return instance type ID
+   */
+  virtual TypeId GetInstanceTypeId () const;
+  /**
+   * \brief Constructor.
+   */
+  DsrOptionAck ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrOptionAck ();
+  /**
+   * \brief Get the option number.
+   * \return option number
+   */
+  virtual uint8_t GetOptionNumber () const;
+  /**
+   * \brief Process method
+   *
+   * Called from DsrRouting::Receive.
+   * \param packet the packet
+   * \param dsrP  the clean packet with payload
+   * \param ipv4Header the IPv4 header of packet received
+   * \param protocol the protocol number of the up layer
+   * \param isPromisc if the packet must be dropped
+   * \return the processed size
+   */
+  virtual uint8_t Process (Ptr<Packet> packet, Ptr<Packet> dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc);
+
+private:
+  /**
+   * \brief The route cache.
+   */
+  Ptr<dsr::RouteCache> m_routeCache;
+  /**
+   * \brief The length of the packet.
+   */
+  uint32_t m_length;
+  /**
+   * \brief The ipv4 layer 3.
+   */
+  Ptr<Ipv4> m_ipv4;
+};
+} // namespace dsr
+} // Namespace ns3
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-rcache.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,1175 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *              Song Luan <lsuper@mail.ustc.edu.cn> (Implemented Link Cache using Dijsktra algorithm)
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsr-rcache.h"
+#include <map>
+#include <cmath>
+#include <algorithm>
+#include <iostream>
+#include <list>
+#include <vector>
+#include <functional>
+#include <iomanip>
+
+#include "ns3/simulator.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/socket.h"
+#include "ns3/log.h"
+#include "ns3/address-utils.h"
+#include "ns3/packet.h"
+
+NS_LOG_COMPONENT_DEFINE ("RouteCache");
+
+namespace ns3 {
+namespace dsr {
+
+void Link::Print () const
+{
+  NS_LOG_DEBUG (m_low << "----" << m_high);
+}
+
+NodeStab::NodeStab ()
+{
+}
+
+NodeStab::~NodeStab ()
+{
+}
+
+void
+NodeStab::IncStability ()
+{
+  m_nodeStability = Time (GetNodeStability () * m_stabilityIncrFactor);
+}
+
+void
+NodeStab::DecStability ()
+{
+  m_nodeStability = Time (GetNodeStability () / m_stabilityDecrFactor);
+}
+
+LinkStab::LinkStab ()
+{
+}
+
+LinkStab::~LinkStab ()
+{
+}
+
+void LinkStab::Print ( ) const
+{
+  NS_LOG_DEBUG ("LifeTime: " << GetLinkStability ().GetSeconds ());
+}
+
+typedef std::list<RouteCacheEntry>::value_type route_pair;
+
+RouteCacheEntry::RouteCacheEntry (IP_VECTOR const  & ip, Ipv4Address dst, Time exp)
+  : m_ackTimer (Timer::CANCEL_ON_DESTROY),
+    m_dst (dst),
+    m_path (ip),
+    m_expire (exp + Simulator::Now ()),
+    m_reqCount (0),
+    m_blackListState (false),
+    m_blackListTimeout (Simulator::Now ())
+{
+}
+
+RouteCacheEntry::~RouteCacheEntry ()
+{
+}
+
+void
+RouteCacheEntry::Invalidate (Time badLinkLifetime)
+{
+  m_reqCount = 0;
+  m_expire = badLinkLifetime + Simulator::Now ();
+}
+
+void
+RouteCacheEntry::Print (std::ostream & os) const
+{
+  os << m_dst << "\t" << (m_expire - Simulator::Now ()).GetSeconds ()
+     << "\t";
+}
+
+bool CompareRoutesExpire (const RouteCacheEntry &a, const RouteCacheEntry &b)
+{
+  return a.GetExpireTime () > b.GetExpireTime ();
+}
+
+bool CompareRoutesHop (const RouteCacheEntry &a, const RouteCacheEntry &b)
+{
+  return a.GetVector ().size () < b.GetVector ().size ();
+}
+
+bool CompareRoutes (const RouteCacheEntry &a, const RouteCacheEntry &b)
+{
+  return (a.GetVector ().size () < b.GetVector ().size ())
+         || ((a.GetVector ().size () == b.GetVector ().size ()) && (a.GetExpireTime () > b.GetExpireTime ()))
+  ;
+}
+
+NS_OBJECT_ENSURE_REGISTERED (RouteCache);
+
+TypeId RouteCache::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::RouteCache")
+    .SetParent<Object> ()
+    .AddConstructor<RouteCache> ()
+  ;
+  return tid;
+}
+
+RouteCache::RouteCache ()
+  : m_vector (0),
+    m_ntimer (Timer::CANCEL_ON_DESTROY),
+    m_delay (MilliSeconds (100))
+{
+  /*
+   * The timer to set layer 2 notification, not fully supported by ns3 yet
+   */
+  m_ntimer.SetDelay (m_delay);
+  m_ntimer.SetFunction (&RouteCache::PurgeMac, this);
+  m_txErrorCallback = MakeCallback (&RouteCache::ProcessTxError, this);
+}
+
+RouteCache::~RouteCache ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  // clear the route cache when done
+  m_sortedRoutes.clear ();
+}
+
+void
+RouteCache::RemoveLastEntry (std::list<RouteCacheEntry> & rtVector)
+{
+  NS_LOG_FUNCTION (this);
+  // release the last entry of route list
+  rtVector.pop_back ();
+}
+
+bool
+RouteCache::UpdateRouteEntry (Ipv4Address dst)
+{
+  NS_LOG_FUNCTION (this << dst);
+  std::map<Ipv4Address, std::list<RouteCacheEntry> >::const_iterator i =
+    m_sortedRoutes.find (dst);
+  if (i == m_sortedRoutes.end ())
+    {
+      NS_LOG_DEBUG ("Failed to find the route entry for the destination " << dst);
+      return false;
+    }
+  else
+    {
+      std::list<RouteCacheEntry> rtVector = i->second;
+      RouteCacheEntry successEntry = rtVector.front ();
+      successEntry.SetExpireTime (RouteCacheTimeout);
+      rtVector.pop_front ();
+      rtVector.push_back (successEntry);
+      rtVector.sort (CompareRoutesExpire);  // sort the route vector first
+      m_sortedRoutes.erase (dst);  // erase the entry first
+      /*
+       * Save the new route cache along with the destination address in map
+       */
+      std::pair<std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator, bool> result =
+        m_sortedRoutes.insert (std::make_pair (dst, rtVector));
+      return result.second;
+    }
+  return false;
+}
+
+bool
+RouteCache::LookupRoute (Ipv4Address id, RouteCacheEntry & rt)
+{
+  NS_LOG_FUNCTION (this << id);
+  if (IsLinkCache ())
+    {
+      return LookupRoute_Link (id, rt);
+    }
+  else
+    {
+      Purge ();  // Purge first to remove expired entries
+      if (m_sortedRoutes.empty ())
+        {
+          NS_LOG_LOGIC ("Route to " << id << " not found; m_sortedRoutes is empty");
+          return false;
+        }
+      std::map<Ipv4Address, std::list<RouteCacheEntry> >::const_iterator i = m_sortedRoutes.find (id);
+      if (i == m_sortedRoutes.end ())
+        {
+          NS_LOG_LOGIC ("No Direct Route to " << id << " found");
+          for (std::map<Ipv4Address, std::list<RouteCacheEntry> >::const_iterator j =
+                 m_sortedRoutes.begin (); j != m_sortedRoutes.end (); ++j)
+            {
+              std::list<RouteCacheEntry> rtVector = j->second; // The route cache vector linked with destination address
+              /*
+               * Loop through the possibly multiple routes within the route vector
+               */
+              for (std::list<RouteCacheEntry>::const_iterator k = rtVector.begin (); k != rtVector.end (); ++k)
+                {
+                  // return the first route in the route vector
+                  RouteCacheEntry::IP_VECTOR routeVector = k->GetVector ();
+                  RouteCacheEntry::IP_VECTOR changeVector;
+
+                  for (RouteCacheEntry::IP_VECTOR::iterator l = routeVector.begin (); l != routeVector.end (); ++l)
+                    {
+                      if (*l != id)
+                        {
+                          changeVector.push_back (*l);
+                        }
+                      else
+                        {
+                          changeVector.push_back (*l);
+                          break;
+                        }
+                    }
+                  /*
+                   * When the changed vector is smaller in size and larger than 1, which means we have found a route with the destination
+                   * address we are looking for
+                   */
+                  if ((changeVector.size () < routeVector.size ())  && (changeVector.size () > 1))
+                    {
+                      RouteCacheEntry changeEntry; // Create the route entry
+                      changeEntry.SetVector (changeVector);
+                      changeEntry.SetDestination (id);
+                      // use the expire time from original route entry
+                      changeEntry.SetExpireTime (k->GetExpireTime ());
+                      // We need to add new route entry here
+                      std::list<RouteCacheEntry> newVector;
+                      newVector.push_back (changeEntry);
+                      newVector.sort (CompareRoutesExpire);  // sort the route vector first
+                      m_sortedRoutes[id] = newVector;   // Only get the first sub route and add it in route cache
+                      NS_LOG_INFO ("We have a sub-route to " << id << " add it in route cache");
+                    }
+                }
+            }
+        }
+      NS_LOG_INFO ("Here we check the route cache again after updated the sub routes");
+      std::map<Ipv4Address, std::list<RouteCacheEntry> >::const_iterator m = m_sortedRoutes.find (id);
+      if (m == m_sortedRoutes.end ())
+        {
+          NS_LOG_DEBUG ("No updated route till last time");
+          return false;
+        }
+      /*
+       * We have a direct route to the destination address
+       */
+      std::list<RouteCacheEntry> rtVector = m->second;
+      rt = rtVector.front ();  // use the first entry in the route vector
+      NS_LOG_DEBUG ("Route to " << id << " with route size " << rtVector.size ());
+      return true;
+    }
+}
+
+void
+RouteCache::SetCacheType (std::string type)
+{
+  NS_LOG_FUNCTION (this << type);
+  if (type == std::string ("LinkCache"))
+    {
+      m_isLinkCache = true;
+    }
+  else if (type == std::string ("PathCache"))
+    {
+      m_isLinkCache = false;
+    }
+  else
+    {
+      m_isLinkCache = false;             // use path cache as default
+      NS_LOG_DEBUG ("Error Cache Type");
+    }
+}
+
+bool
+RouteCache::IsLinkCache ()
+{
+  return m_isLinkCache;
+}
+
+void
+RouteCache::RebuildBestRouteTable (Ipv4Address source)
+{
+  NS_LOG_FUNCTION (this << source);
+  /*
+   * the followings are initialize-single-source
+   */
+  // @d shortest-path estimate
+  std::map<Ipv4Address, uint32_t> d;
+  // @pre preceeding node
+  std::map<Ipv4Address, Ipv4Address> pre;
+  NS_LOG_FUNCTION (this << source);
+  for (std::map<Ipv4Address, std::map<Ipv4Address, uint32_t> >::iterator i = m_netGraph.begin (); i != m_netGraph.end (); ++i)
+    {
+      if (i->second.find (source) != i->second.end ())
+        {
+          d[i->first] = i->second[source];
+          pre[i->first] = source;
+        }
+      else
+        {
+          d[i->first] = MAXWEIGHT;
+          pre[i->first] = Ipv4Address ("255.255.255.255");
+        }
+    }
+  d[source] = 0;
+  /**
+   * the followings are core of dijskra algorithm
+   *
+   */
+  // the node set which shortest distance has been calculated, if true calculated
+  std::map<Ipv4Address, bool> s;
+  double temp = MAXWEIGHT;
+  Ipv4Address tempip = Ipv4Address ("255.255.255.255");
+  for (uint32_t i = 0; i < m_netGraph.size (); i++)
+    {
+      temp = MAXWEIGHT;
+      for (std::map<Ipv4Address,uint32_t>::iterator j = d.begin (); j != d.end (); ++j)
+        {
+          Ipv4Address ip = j->first;
+          if (s.find (ip) == s.end ())
+            {
+              /*
+               * the followings are for comparison
+               */
+              if (j->second <= temp)
+                {
+                  temp = j->second;
+                  tempip = ip;
+                }
+            }
+        }
+      if (!tempip.IsBroadcast ())
+        {
+          s[tempip] = true;
+          for (std::map<Ipv4Address, uint32_t>::iterator k = m_netGraph[tempip].begin (); k != m_netGraph[tempip].end (); ++k)
+            {
+              if (s.find (k->first) == s.end () && d[k->first] > d[tempip] + k->second)
+                {
+                  d[k->first] = d[tempip] + k->second;
+                  pre[k->first] = tempip;
+                }
+              /**
+               *  Selects the shortest-length route that has the longest expected lifetime
+               *  (highest minimum timeout of any link in the route)
+               *  For the computation overhead and complexity
+               *  Here I just implement kind of greedy strategy to select link with the longest expected lifetime when there is two options
+               */
+              else if (d[k->first] == d[tempip] + k->second)
+                {
+                  std::map<Link, LinkStab>::iterator oldlink = m_linkCache.find (Link (k->first, pre[k->first]));
+                  std::map<Link, LinkStab>::iterator newlink = m_linkCache.find (Link (k->first, tempip));
+                  if (oldlink != m_linkCache.end () && newlink != m_linkCache.end ())
+                    {
+                      if (oldlink->second.GetLinkStability () < newlink->second.GetLinkStability ())
+                        {
+                          NS_LOG_DEBUG ("Select the link with longest expected lifetime");
+                          d[k->first] = d[tempip] + k->second;
+                          pre[k->first] = tempip;
+                        }
+                    }
+                  else
+                    {
+                      NS_LOG_DEBUG ("Link Stability Info Corrupt");
+                    }
+                }
+            }
+        }
+    }
+  // clean the best route table
+  m_bestRoutesTable_link.clear ();
+  for (std::map<Ipv4Address, Ipv4Address>::iterator i = pre.begin (); i != pre.end (); ++i)
+    { // loop for all vertexes
+      RouteCacheEntry::IP_VECTOR route;
+      Ipv4Address iptemp = i->first;
+
+      if (!i->second.IsBroadcast () && iptemp != source)
+        {
+          while (iptemp != source)
+            {
+              route.push_back (iptemp);
+              iptemp = pre[iptemp];
+            }
+          route.push_back (source);
+          /*
+           * reverse the route
+           */
+          RouteCacheEntry::IP_VECTOR reverseroute;
+          for (RouteCacheEntry::IP_VECTOR::reverse_iterator j = route.rbegin (); j != route.rend (); ++j)
+            {
+              reverseroute.push_back (*j);
+            }
+          NS_LOG_DEBUG ("Add Route: ");
+          PrintVector (reverseroute);
+          m_bestRoutesTable_link[i->first] = reverseroute;
+        }
+    }
+}
+
+bool
+RouteCache::LookupRoute_Link (Ipv4Address id, RouteCacheEntry & rt)
+{
+  NS_LOG_FUNCTION (this << id);
+  NS_LOG_DEBUG ("Use Link Cache");
+  std::map<Ipv4Address, RouteCacheEntry::IP_VECTOR>::iterator i = m_bestRoutesTable_link.find (id);
+  if (i == m_bestRoutesTable_link.end ())
+    {
+      NS_LOG_DEBUG ("No Route To " << id);
+      return false;
+    }
+  else
+    {
+      if (i->second.size () < 2)
+        {
+          NS_LOG_DEBUG ("Route To " << id << " Error");
+          return false;
+        }
+      RouteCacheEntry toSource (/*IP_VECTOR=*/ i->second, /*dst=*/ id, /*expire time=*/ Time (0));
+      rt = toSource;
+      NS_LOG_DEBUG ("The route length " << i->second.size ());
+      NS_LOG_LOGIC ("Route to " << id << " found");
+      std::vector<Ipv4Address> path = rt.GetVector ();
+      PrintVector (path);
+      return true;
+    }
+}
+
+void
+RouteCache::PurgeLinkNode ()
+{
+  NS_LOG_FUNCTION (this);
+  for (std::map<Link, LinkStab>::iterator i = m_linkCache.begin (); i != m_linkCache.end (); )
+    {
+      if (i->second.GetLinkStability () <= Seconds (0))
+        {
+          m_linkCache.erase (i++);
+        }
+      else
+        {
+          i++;
+        }
+    }
+  for (std::map<Ipv4Address, NodeStab>::iterator i = m_nodeCache.begin (); i != m_nodeCache.end (); )
+    {
+      if (i->second.GetNodeStability () <= Seconds (0))
+        {
+          m_nodeCache.erase (i++);
+        }
+      else
+        {
+          i++;
+        }
+    }
+}
+
+void
+RouteCache::UpdateNetGraph ()
+{
+  NS_LOG_FUNCTION (this);
+  m_netGraph.clear ();
+  for (std::map<Link, LinkStab>::iterator i = m_linkCache.begin (); i != m_linkCache.end (); ++i)
+    {
+      uint32_t weight = 1;
+      m_netGraph[i->first.m_low][i->first.m_high] = weight;
+      m_netGraph[i->first.m_high][i->first.m_low] = weight;
+    }
+}
+
+bool
+RouteCache::AddRoute_Link (RouteCacheEntry::IP_VECTOR nodelist, Ipv4Address source)
+{
+  NS_LOG_FUNCTION (this << source);
+  NS_LOG_DEBUG ("Use Link Cache");
+  for (uint32_t i = 0; i < nodelist.size () - 1; i++)
+    {
+      NodeStab ns;
+      ns.SetNodeStability (Seconds (m_initStability));
+      ns.SetStabilityIncrFactor (m_stabilityIncrFactor);
+      ns.SetStabilityDecrFactor (m_stabilityDecrFactor);
+
+      if (m_nodeCache.find (nodelist[i]) == m_nodeCache.end ())
+        {
+          m_nodeCache[nodelist[i]] = ns;
+        }
+      if (m_nodeCache.find (nodelist[i + 1]) == m_nodeCache.end ())
+        {
+          m_nodeCache[nodelist[i + 1]] = ns;
+        }
+      Link link (nodelist[i], nodelist[i + 1]);
+      LinkStab stab;
+      stab.SetLinkStability (Seconds (m_initStability));
+      if (m_nodeCache[nodelist[i]].GetNodeStability () < m_nodeCache[nodelist[i + 1]].GetNodeStability ())
+        {
+          stab.SetLinkStability (m_nodeCache[nodelist[i]].GetNodeStability ());
+        }
+      else
+        {
+          stab.SetLinkStability (m_nodeCache[nodelist[i + 1]].GetNodeStability ());
+        }
+
+      if (stab.GetLinkStability () < (Seconds (m_minLifeTime)))
+        {
+          NS_LOG_DEBUG ("stability: " << stab.GetLinkStability ());
+          stab.SetLinkStability (Seconds (m_minLifeTime));
+        }
+      m_linkCache[link] = stab;
+      NS_LOG_DEBUG ("Add a new link");
+      link.Print ();
+      NS_LOG_DEBUG ("Link Info");
+      stab.Print ();
+    }
+  PurgeLinkNode ();
+  UpdateNetGraph ();
+  RebuildBestRouteTable (source);
+  return true;
+}
+
+void
+RouteCache::UseExtends (RouteCacheEntry::IP_VECTOR rt)
+{
+  if (rt.size () < 2)
+    {
+      NS_LOG_DEBUG ("The route is too short");
+    }
+  for (RouteCacheEntry::IP_VECTOR::iterator i = rt.begin (); i != rt.end () - 1; ++i)
+    {
+      Link link (*i, *(i + 1));
+      if (m_linkCache.find (link) != m_linkCache.end ())
+        {
+          if (m_linkCache[link].GetLinkStability () < Time (Seconds (m_useExtends)))
+            {
+              m_linkCache[link].SetLinkStability (Time (Seconds (m_useExtends)));
+            }
+          NS_LOG_DEBUG ("The time of the link " << m_linkCache[link].GetLinkStability ().GetSeconds ());
+        }
+      else
+        {
+          NS_LOG_DEBUG ("we cannot find a link in cache");
+        }
+    }
+  // Increase the stability of the node cache
+  for (RouteCacheEntry::IP_VECTOR::iterator i = rt.begin (); i != rt.end (); ++i)
+    {
+      if (m_nodeCache.find (*i) != m_nodeCache.end ())
+        {
+          NS_LOG_DEBUG ("increase the stability");
+          if (m_nodeCache[*i].GetNodeStability () <= m_initStability)
+            {
+              m_nodeCache[*i].IncStability ();
+            }
+          else
+            {
+              NS_LOG_DEBUG ("The node stability has already been increased");
+            }
+        }
+    }
+}
+
+bool
+RouteCache::AddRoute (RouteCacheEntry & rt)
+{
+  NS_LOG_FUNCTION (this);
+  Purge ();
+  std::list<RouteCacheEntry> rtVector;   // Declare the route cache entry vector
+  Ipv4Address dst = rt.GetDestination ();
+  std::vector<Ipv4Address> route = rt.GetVector ();
+
+  NS_LOG_DEBUG ("The route destination we have " << dst);
+  std::map<Ipv4Address, std::list<RouteCacheEntry> >::const_iterator i =
+    m_sortedRoutes.find (dst);
+
+  if (i == m_sortedRoutes.end ())
+    {
+      rtVector.push_back (rt);
+      m_sortedRoutes.erase (dst);   // erase the route entries for dst first
+      /*
+       * Save the new route cache along with the destination address in map
+       */
+      std::pair<std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator, bool> result =
+        m_sortedRoutes.insert (std::make_pair (dst, rtVector));
+      return result.second;
+    }
+  else
+    {
+      rtVector = i->second;
+      NS_LOG_DEBUG ("The existing route size " << rtVector.size () << " for destination address " << dst);
+      /*
+       * Drop the most aged packet when buffer reaches to max
+       */
+      if (rtVector.size () >= m_maxEntriesEachDst)
+        {
+          RemoveLastEntry (rtVector);         // Drop the last entry for the sorted route cache, the route has already been sorted
+        }
+
+      if (FindSameRoute (rt, rtVector))
+        {
+          NS_LOG_DEBUG ("Find same vector, the FindSameRoute function will update the route expire time");
+          return true;
+        }
+      else
+        {
+          // Check if the expire time for the new route has expired or not
+          if (rt.GetExpireTime () > 0)
+            {
+              rtVector.push_back (rt);
+              // This sort function will sort the route cache entries based on the size of route in each of the
+              // route entries
+              rtVector.sort (CompareRoutesExpire);
+              NS_LOG_DEBUG ("The first time" << rtVector.front ().GetExpireTime ().GetSeconds () << " The second time "
+                                             << rtVector.back ().GetExpireTime ().GetSeconds ());
+              NS_LOG_DEBUG ("The first hop" << rtVector.front ().GetVector ().size () << " The second hop "
+                                            << rtVector.back ().GetVector ().size ());
+              m_sortedRoutes.erase (dst);               // erase the route entries for dst first
+              /*
+               * Save the new route cache along with the destination address in map
+               */
+              std::pair<std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator, bool> result =
+                m_sortedRoutes.insert (std::make_pair (dst, rtVector));
+              return result.second;
+            }
+          else
+            {
+              NS_LOG_DEBUG ("The newly found route is expired");
+            }
+        }
+    }
+  return false;
+}
+
+bool RouteCache::FindSameRoute (RouteCacheEntry & rt, std::list<RouteCacheEntry> & rtVector)
+{
+  NS_LOG_FUNCTION (this);
+  for (std::list<RouteCacheEntry>::iterator i = rtVector.begin (); i != rtVector.end (); ++i)
+    {
+      // return the first route in the route vector
+      RouteCacheEntry::IP_VECTOR routeVector = i->GetVector ();
+      RouteCacheEntry::IP_VECTOR newVector = rt.GetVector ();
+
+      if (routeVector == newVector)
+        {
+          NS_LOG_DEBUG ("Found same routes in the route cache with the vector size "
+                        << rt.GetDestination () << " " << rtVector.size ());
+          NS_LOG_DEBUG ("The new route expire time " << rt.GetExpireTime ().GetSeconds ()
+                                                     << " the original expire time " << i->GetExpireTime ().GetSeconds ());
+          if (rt.GetExpireTime () > i->GetExpireTime ())
+            {
+              i->SetExpireTime (rt.GetExpireTime ());
+            }
+          m_sortedRoutes.erase (rt.GetDestination ()); // erase the entry first
+          rtVector.sort (CompareRoutesExpire);  // sort the route vector first
+          /*
+           * Save the new route cache along with the destination address in map
+           */
+          std::pair<std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator, bool> result =
+            m_sortedRoutes.insert (std::make_pair (rt.GetDestination (), rtVector));
+          return result.second;
+        }
+    }
+  return false;
+}
+
+bool
+RouteCache::DeleteRoute (Ipv4Address dst)
+{
+  Purge (); // purge the route cache first to remove timeout entries
+  if (m_sortedRoutes.erase (dst) != 0)
+    {
+      NS_LOG_LOGIC ("Route deletion to " << dst << " successful");
+      return true;
+    }
+  NS_LOG_LOGIC ("Route deletion to " << dst << " not successful");
+  return false;
+}
+
+void
+RouteCache::DeleteAllRoutesIncludeLink (Ipv4Address errorSrc, Ipv4Address unreachNode, Ipv4Address node)
+{
+  NS_LOG_FUNCTION (this << errorSrc << unreachNode << node);
+  if (IsLinkCache ())
+    {
+      /*
+       * the followings are for cleaning the broken link in linkcache
+       *
+       */
+      Link link (errorSrc, unreachNode);
+      if (m_linkCache.erase (link) == 0)
+        {
+          NS_LOG_LOGIC ("Cut route unsuccessful and erase the route");
+        }
+      else
+        {
+          std::map<Ipv4Address, NodeStab>::iterator i = m_nodeCache.find (errorSrc);
+          if (i == m_nodeCache.end ())
+            {
+              NS_LOG_LOGIC ("Update the node stability unsuccessfully");
+            }
+          else
+            {
+              i->second.DecStability ();
+            }
+          i = m_nodeCache.find (unreachNode);
+          if (i == m_nodeCache.end ())
+            {
+              NS_LOG_LOGIC ("Update the node stability unsuccessfully");
+            }
+          else
+            {
+              i->second.DecStability ();
+            }
+        }
+      PurgeLinkNode ();
+      UpdateNetGraph ();
+      RebuildBestRouteTable (node);
+    }
+  else
+    {
+      /*
+       * the followings are for cleaning the broken link in pathcache
+       *
+       */
+      Purge ();
+      if (m_sortedRoutes.empty ())
+        {
+          return;
+        }
+      /*
+       * Loop all the routes saved in the route cache
+       */
+      for (std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator j =
+             m_sortedRoutes.begin (); j != m_sortedRoutes.end (); )
+        {
+          std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator jtmp = j;
+          Ipv4Address address = j->first;
+          std::list<RouteCacheEntry> rtVector = j->second;
+          /*
+           * Loop all the routes for a single destination
+           */
+          for (std::list<RouteCacheEntry>::iterator k = rtVector.begin (); k != rtVector.end (); )
+            {
+              // return the first route in the route vector
+              RouteCacheEntry::IP_VECTOR routeVector = k->GetVector ();
+              RouteCacheEntry::IP_VECTOR changeVector;
+              /*
+               * Loop the ip addresses within a single route entry
+               */
+              for (RouteCacheEntry::IP_VECTOR::iterator i = routeVector.begin (); i != routeVector.end (); ++i)
+                {
+                  if (*i != errorSrc)
+                    {
+                      changeVector.push_back (*i);
+                    }
+                  else
+                    {
+                      if (*(i + 1) == unreachNode)
+                        {
+                          changeVector.push_back (*i);
+                          break;
+                        }
+                      else
+                        {
+                          changeVector.push_back (*i);
+                        }
+                    }
+                }
+              /*
+               * Verify if need to remove some affected links
+               */
+              if (changeVector.size () == routeVector.size ())
+                {
+                  NS_LOG_DEBUG ("The route does not contain the broken link");
+                  ++k;
+                }
+              else if ((changeVector.size () < routeVector.size ()) && (changeVector.size () > 1))
+                {
+                  NS_LOG_DEBUG ("sub route " << m_subRoute);
+                  if (m_subRoute)
+                    {
+                      Time expire = k->GetExpireTime ();
+                      /*
+                       * Remove the route first
+                       */
+                      k = rtVector.erase (k);
+                      RouteCacheEntry changeEntry;
+                      changeEntry.SetVector (changeVector);
+                      Ipv4Address destination = changeVector.back ();
+                      NS_LOG_DEBUG ("The destination of the newly formed route " << destination << " and the size of the route " << changeVector.size ());
+                      changeEntry.SetDestination (destination);
+                      changeEntry.SetExpireTime (expire); // Initialize the timeout value to the one it has
+                      rtVector.push_back (changeEntry);  // Add the route entry to the route list
+                      NS_LOG_DEBUG ("We have a sub-route to " << destination);
+                    }
+                  else
+                    {
+                      /*
+                       * Remove the route
+                       */
+                      k = rtVector.erase (k);
+                    }
+                }
+              else
+                {
+                  NS_LOG_LOGIC ("Cut route unsuccessful and erase the route");
+                  /*
+                   * Remove the route
+                   */
+                  k = rtVector.erase (k);
+                }
+            }
+          ++j;
+          if (!IsLinkCache ())
+            {
+              m_sortedRoutes.erase (jtmp);
+            }
+          if (rtVector.size ())
+            {
+              /*
+               * Save the new route cache along with the destination address in map
+               */
+              rtVector.sort (CompareRoutesExpire);
+              m_sortedRoutes[address] = rtVector;
+            }
+          else
+            {
+              NS_LOG_DEBUG ("There is no route left for that destination " << address);
+            }
+        }
+    }
+}
+
+void
+RouteCache::PrintVector (std::vector<Ipv4Address>& vec)
+{
+  /*
+   * Check elements in a route vector, used when one wants to check the IP addresses saved in
+   */
+  if (!vec.size ())
+    {
+      NS_LOG_DEBUG ("The vector is empty");
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Print all the elements in a vector");
+      for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
+        {
+          NS_LOG_DEBUG ("The ip address " << *i);
+        }
+    }
+}
+
+void
+RouteCache::PrintRouteVector (std::list<RouteCacheEntry> route)
+{
+  for (std::list<RouteCacheEntry>::iterator i = route.begin (); i != route.end (); i++)
+    {
+      std::vector<Ipv4Address> path = i->GetVector ();
+      NS_LOG_DEBUG ("Route NO. ");
+      PrintVector (path);
+    }
+}
+
+void
+RouteCache::Purge ()
+{
+  //Trying to purge the route cache
+  if (m_sortedRoutes.empty ())
+    {
+      NS_LOG_DEBUG ("The route cache is empty");
+      return;
+    }
+  for (std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator i =
+         m_sortedRoutes.begin (); i != m_sortedRoutes.end (); )
+    {
+      // Loop of route cache entry with the route size
+      std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator itmp = i;
+      /*
+       * The route cache entry vector
+       */
+      Ipv4Address dst = i->first;
+      std::list<RouteCacheEntry> rtVector = i->second;
+      NS_LOG_DEBUG ("The route vector size of1 " << dst << " " << rtVector.size ());
+      if (rtVector.size ())
+        {
+          for (std::list<RouteCacheEntry>::iterator j = rtVector.begin (); j != rtVector.end (); )
+            {
+              NS_LOG_DEBUG ("The expire time of every entry with expire time " << j->GetExpireTime ());
+              /*
+               * First verify if the route has expired or not
+               */
+              if (j->GetExpireTime () <= Seconds (0))
+                {
+                  /*
+                   * When the expire time has passed, erase the certain route
+                   */
+                  NS_LOG_DEBUG ("Erase the expired route for " << dst << " with expire time " << j->GetExpireTime ());
+                  j = rtVector.erase (j);
+                }
+              else
+                {
+                  ++j;
+                }
+            }
+          NS_LOG_DEBUG ("The route vector size of2 " << dst << " " << rtVector.size ());
+          if (rtVector.size ())
+            {
+              ++i;
+              m_sortedRoutes.erase (itmp); // erase the entry first
+              /*
+               * Save the new route cache along with the destination address in map
+               */
+              std::pair<std::map<Ipv4Address, std::list<RouteCacheEntry> >::iterator, bool> result =
+                m_sortedRoutes.insert (std::make_pair (dst, rtVector));
+            }
+          else
+            {
+              ++i;
+              m_sortedRoutes.erase (itmp);
+            }
+        }
+      else
+        {
+          ++i;
+          m_sortedRoutes.erase (itmp);
+        }
+    }
+  return;
+}
+
+void
+RouteCache::Print (std::ostream &os)
+{
+  Purge ();
+  os << "\nDSR Route Cache\n"
+     << "Destination\tGateway\t\tInterface\tFlag\tExpire\tHops\n";
+  for (std::list<RouteCacheEntry>::const_iterator i =
+         m_routeEntryVector.begin (); i != m_routeEntryVector.end (); ++i)
+    {
+      i->Print (os);
+    }
+  os << "\n";
+}
+
+// ----------------------------------------------------------------------------------------------------------
+/**
+ * This part of code maintains an Acknowledgment id cache for next hop and remove duplicate ids
+ */
+uint16_t
+RouteCache::CheckUniqueAckId (Ipv4Address nextHop)
+{
+  NS_LOG_DEBUG ("The size of ack id cache " << m_ackIdCache.size ());
+  std::map<Ipv4Address, uint16_t>::const_iterator i =
+    m_ackIdCache.find (nextHop);
+  if (i == m_ackIdCache.end ())
+    {
+      NS_LOG_LOGIC ("No Ack id for " << nextHop << " found");
+      m_ackIdCache[nextHop] = 0;
+      return 0;
+    }
+  else
+    {
+      uint16_t ackId = m_ackIdCache[nextHop];
+      NS_LOG_LOGIC ("Ack id for " << nextHop << " found in the cache has value " << ackId);
+      ackId++;
+      m_ackIdCache[nextHop] = ackId;
+      return ackId;
+    }
+}
+
+uint16_t
+RouteCache::GetAckSize ()
+{
+  return m_ackIdCache.size ();
+}
+
+// ----------------------------------------------------------------------------------------------------------
+/**
+ * This part maintains a neighbor list to handle unidirectional links and link-layer acks
+ */
+bool
+RouteCache::IsNeighbor (Ipv4Address addr)
+{
+  PurgeMac ();  // purge the mac cache
+  for (std::vector<Neighbor>::const_iterator i = m_nb.begin ();
+       i != m_nb.end (); ++i)
+    {
+      if (i->m_neighborAddress == addr)
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+Time
+RouteCache::GetExpireTime (Ipv4Address addr)
+{
+  PurgeMac ();
+  for (std::vector<Neighbor>::const_iterator i = m_nb.begin (); i
+       != m_nb.end (); ++i)
+    {
+      if (i->m_neighborAddress == addr)
+        {
+          return (i->m_expireTime - Simulator::Now ());
+        }
+    }
+  return Seconds (0);
+}
+
+void
+RouteCache::UpdateNeighbor (std::vector<Ipv4Address> nodeList, Time expire)
+{
+  for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i)
+    {
+      for (std::vector<Ipv4Address>::iterator j = nodeList.begin (); j != nodeList.end (); ++j)
+        {
+          if (i->m_neighborAddress == (*j))
+            {
+              i->m_expireTime
+                = std::max (expire + Simulator::Now (), i->m_expireTime);
+              if (i->m_hardwareAddress == Mac48Address ())
+                {
+                  i->m_hardwareAddress = LookupMacAddress (i->m_neighborAddress);
+                }
+              return;
+            }
+        }
+    }
+
+  Ipv4Address addr;
+  NS_LOG_LOGIC ("Open link to " << addr);
+  Neighbor neighbor (addr, LookupMacAddress (addr), expire + Simulator::Now ());
+  m_nb.push_back (neighbor);
+  PurgeMac ();
+}
+
+void
+RouteCache::AddNeighbor (std::vector<Ipv4Address> nodeList, Ipv4Address ownAddress, Time expire)
+{
+  NS_LOG_LOGIC ("Add neighbor number " << nodeList.size ());
+  for (std::vector<Ipv4Address>::iterator j = nodeList.begin (); j != nodeList.end (); ++j)
+    {
+      Ipv4Address addr = *j;
+      if (addr == ownAddress)
+        {
+          nodeList.erase (j);
+          NS_LOG_DEBUG ("The node list size " << nodeList.size ());
+        }
+      Neighbor neighbor (addr, LookupMacAddress (addr), expire + Simulator::Now ());
+      m_nb.push_back (neighbor);
+      PurgeMac ();
+    }
+}
+
+struct CloseNeighbor
+{
+  bool operator() (const RouteCache::Neighbor & nb) const
+  {
+    return ((nb.m_expireTime < Simulator::Now ()) || nb.close);
+  }
+};
+
+void
+RouteCache::PurgeMac ()
+{
+  if (m_nb.empty ())
+    {
+      return;
+    }
+
+  CloseNeighbor pred;
+  if (!m_handleLinkFailure.IsNull ())
+    {
+      for (std::vector<Neighbor>::iterator j = m_nb.begin (); j != m_nb.end (); ++j)
+        {
+          if (pred (*j))
+            {
+              NS_LOG_LOGIC ("Close link to " << j->m_neighborAddress);
+              // disable temporarily TODO
+//              m_handleLinkFailure (j->m_neighborAddress);
+            }
+        }
+    }
+  m_nb.erase (std::remove_if (m_nb.begin (), m_nb.end (), pred), m_nb.end ());
+  m_ntimer.Cancel ();
+  m_ntimer.Schedule ();
+}
+
+void
+RouteCache::ScheduleTimer ()
+{
+  m_ntimer.Cancel ();
+  m_ntimer.Schedule ();
+}
+
+void
+RouteCache::AddArpCache (Ptr<ArpCache> a)
+{
+  m_arp.push_back (a);
+}
+
+void
+RouteCache::DelArpCache (Ptr<ArpCache> a)
+{
+  m_arp.erase (std::remove (m_arp.begin (), m_arp.end (), a), m_arp.end ());
+}
+
+Mac48Address
+RouteCache::LookupMacAddress (Ipv4Address addr)
+{
+  Mac48Address hwaddr;
+  for (std::vector<Ptr<ArpCache> >::const_iterator i = m_arp.begin ();
+       i != m_arp.end (); ++i)
+    {
+      ArpCache::Entry * entry = (*i)->Lookup (addr);
+      if (entry != 0 && entry->IsAlive () && !entry->IsExpired ())
+        {
+          hwaddr = Mac48Address::ConvertFrom (entry->GetMacAddress ());
+          break;
+        }
+    }
+  return hwaddr;
+}
+
+void
+RouteCache::ProcessTxError (WifiMacHeader const & hdr)
+{
+  Mac48Address addr = hdr.GetAddr1 ();
+
+  for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i)
+    {
+      if (i->m_hardwareAddress == addr)
+        {
+          i->close = true;
+        }
+    }
+  PurgeMac ();
+}
+} // namespace dsr
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-rcache.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,655 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *              Song Luan <lsuper@mail.ustc.edu.cn> (Implemented Link Cache using dijsktra algorithm to get the best route)
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_RCACHE_H
+#define DSR_RCACHE_H
+
+#include <map>
+#include <stdint.h>
+#include <cassert>
+#include <sys/types.h>
+#include <iostream>
+#include <vector>
+
+#include "ns3/simulator.h"
+#include "ns3/timer.h"
+#include "ns3/simple-ref-count.h"
+#include "ns3/header.h"
+#include "ns3/enum.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/nstime.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/net-device.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/callback.h"
+#include "ns3/wifi-mac-header.h"
+#include "ns3/arp-cache.h"
+#include "dsr-option-header.h"
+
+namespace ns3 {
+class Time;
+namespace dsr {
+
+/*
+ * The route cache structure
+  \verbatim
+  +-+-+-+-+-+-+-+-+-+-+-+-         +-+-+-+-+-+-+-+-+-+-+-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+  |  Destination Address |---------| Route Cache Entry  | ---------- | IP_VECTOR | dst | exp time |
+  +-+-+-+-+-+-+-+-+-+-+-+-   Map   +-+-+-+-+-+-+-+-+-+-+-  Contains  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+                                   +-+-+-+-+-+-+-+-+-+-+-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+                                   | Route Cache Entry  | ---------- | IP_VECTOR | dst | exp time |
+                                   +-+-+-+-+-+-+-+-+-+-+-  Contains  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+                                             .                                       .
+                                             .                                       .
+                                             .                                       .
+                                             .                                       .
+                                   +-+-+-+-+-+-+-+-+-+-+-            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+                                   | Route Cache Entry  | ---------- | IP_VECTOR | dst | exp time |
+                                   +-+-+-+-+-+-+-+-+-+-+-  Contains  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+
+  \endverbatim
+ */
+
+/**
+ * \ingroup dsr
+ * \brief DSR Route Cache Entry
+ */
+struct Link
+{
+  Ipv4Address m_low;
+  Ipv4Address m_high;
+  Link (Ipv4Address ip1, Ipv4Address ip2)
+  {
+    if (ip1 < ip2)
+      {
+        m_low = ip1;
+        m_high = ip2;
+      }
+    else
+      {
+        m_low = ip2;
+        m_high = ip1;
+      }
+  }
+  bool operator < (Link const& L) const
+  {
+    if (m_low < L.m_low)
+      {
+        return true;
+      }
+    else if (m_low == L.m_low)
+      {
+        return (m_high < L.m_high);
+      }
+    else
+      {
+        return false;
+      }
+  }
+  void Print () const;
+};
+
+class NodeStab
+{
+public:
+  /**
+   * \brief Constructor
+   */
+  NodeStab ();
+  /**
+   * \brief Destructor
+   */
+  virtual ~NodeStab ();
+
+  void SetStabilityIncrFactor (double stabilityIncrFactor)
+  {
+    m_stabilityIncrFactor = stabilityIncrFactor;
+  }
+  double GetStabilityIncrFactor () const
+  {
+    return m_stabilityIncrFactor;
+  }
+  void SetStabilityDecrFactor (double stabilityDecrFactor)
+  {
+    m_stabilityDecrFactor = stabilityDecrFactor;
+  }
+  double GetStabilityDecrFactor () const
+  {
+    return m_stabilityDecrFactor;
+  }
+
+  void IncStability ();
+
+  void DecStability ();
+
+  void SetNodeStability (Time nodeStab)
+  {
+    m_nodeStability = nodeStab + Simulator::Now ();
+  }
+  Time GetNodeStability () const
+  {
+    return m_nodeStability - Simulator::Now ();
+  }
+private:
+  Time m_nodeStability;
+  double m_stabilityIncrFactor;
+  double m_stabilityDecrFactor;
+};
+
+class LinkStab
+{
+public:
+  /**
+   * \brief Constructor
+   */
+  LinkStab ();
+  /**
+   * \brief Destructor
+   */
+  virtual ~LinkStab ();
+
+  void SetLinkStability (Time linkStab)
+  {
+    m_linkStability = linkStab + Simulator::Now ();
+  }
+  Time GetLinkStability () const
+  {
+    return m_linkStability - Simulator::Now ();
+  }
+
+  void Print () const;
+private:
+  /*
+   * The link stability lifetime expected, when the time is due, the link expires the expiration happens
+   * when purge the node and link cache before update them when receiving new information
+   */
+  Time m_linkStability;
+};
+
+class RouteCacheEntry
+{
+public:
+  typedef std::vector<Ipv4Address> IP_VECTOR;                // Define the vector to hold Ip address
+  typedef std::vector<Ipv4Address>::iterator Iterator;       // Define the iterator
+  // / c-tor
+  /**
+   * \brief Constructor
+   */
+  RouteCacheEntry (IP_VECTOR const  & ip = IP_VECTOR (), Ipv4Address dst = Ipv4Address (), Time exp = Simulator::Now ());
+  /**
+   * \brief Destructor
+   */
+  virtual ~RouteCacheEntry ();
+  // / Mark entry as "down" (i.e. disable it)
+  void Invalidate (Time badLinkLifetime);
+  // /\name Fields
+  // \{
+  void SetUnidirectional (bool u)
+  {
+    m_blackListState = u;
+  }
+  bool IsUnidirectional () const
+  {
+    return m_blackListState;
+  }
+  void SetBlacklistTimeout (Time t)
+  {
+    m_blackListTimeout = t;
+  }
+  Time GetBlacklistTimeout () const
+  {
+    return m_blackListTimeout;
+  }
+  Ipv4Address GetDestination () const
+  {
+    return m_dst;
+  }
+  void SetDestination (Ipv4Address d)
+  {
+    m_dst = d;
+  }
+  IP_VECTOR GetVector () const
+  {
+    return m_path;
+  }
+  void SetVector (IP_VECTOR v)
+  {
+    m_path = v;
+  }
+  void SetExpireTime (Time exp)
+  {
+    m_expire = exp + Simulator::Now ();
+  }
+  Time GetExpireTime () const
+  {
+    return m_expire - Simulator::Now ();
+  }
+  // \}
+  /**
+   * \brief Print necessary fields
+   */
+  void Print (std::ostream & os) const;
+  /**
+   * \brief Compare the route cache entry
+   * \return true if equal
+   */
+  bool operator== (RouteCacheEntry const & o) const
+  {
+    if (m_path.size () != o.m_path.size ())
+      {
+        NS_ASSERT (false);
+        return false;
+      }
+    IP_VECTOR::const_iterator j = o.m_path.begin ();
+    for (IP_VECTOR::const_iterator i = m_path.begin (); i
+         != m_path.end (); i++, j++)
+      {
+        /*
+         * Verify if neither the entry are not 0 and they equal to each other
+         */
+        if (((*i) == 0) || ((*j) == 0))
+          {
+            return false;
+          }
+        else if (!((*i) == (*j)) )
+          {
+            return false;
+          }
+        else
+          {
+            return true;
+          }
+      }
+    return false;
+  }
+  // \}
+  // / RREP_ACK timer
+  Timer m_ackTimer;
+private:
+  // / The destination Ip address
+  Ipv4Address m_dst;
+  // / brief The IP address constructed route
+  IP_VECTOR m_path;
+  // / Expire time for queue entry
+  Time m_expire;
+  // / Output interface address
+  Ipv4InterfaceAddress m_iface;
+  // / Number of route requests
+  uint8_t m_reqCount;
+  // / Indicate if this entry is in "blacklist"
+  bool m_blackListState;
+  // / Time for which the node is put into the blacklist
+  Time m_blackListTimeout;
+  // / The Ipv4 route
+  Ptr<Ipv4Route> m_ipv4Route;
+  // / The Ipv4 layer 3
+  Ptr<Ipv4> m_ipv4;
+};
+/**
+ * \ingroup dsr
+ * \brief DSR route request queue
+ * Since DSR is an on demand routing we queue requests while looking for route.
+ */
+class RouteCache : public Object
+{
+public:
+  // / Default c-tor
+/**
+ * \ingroup dsr
+ * \brief The Route Cache used by DSR
+ */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Constructor.
+   */
+  RouteCache ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~RouteCache ();
+  // / Remove the aged route cache entries when the route cache is full
+  void RemoveLastEntry (std::list<RouteCacheEntry> & rtVector);
+  // / Define the vector of route entries.
+  typedef std::list<RouteCacheEntry::IP_VECTOR> routeVector;
+  // / Get the destination address of the route.
+  Ipv4Address GetDestination (void) const;
+  // / Remove all packets with destination IP address dst
+  void DropPathWithDst (Ipv4Address dst);
+  // / To know if the two entries are the same
+  bool IsEqual (RouteCacheEntry ca);
+  // /\name Fields
+  // \{
+  bool GetSubRoute () const
+  {
+    return m_subRoute;
+  }
+  void SetSubRoute (bool subRoute)
+  {
+    m_subRoute = subRoute;
+  }
+  uint32_t GetMaxCacheLen () const
+  {
+    return m_maxCacheLen;
+  }
+  void SetMaxCacheLen (uint32_t len)
+  {
+    m_maxCacheLen = len;
+  }
+  Time GetCacheTimeout () const
+  {
+    return RouteCacheTimeout;
+  }
+  void SetCacheTimeout (Time t)
+  {
+    RouteCacheTimeout = t;
+  }
+  uint32_t GetMaxEntriesEachDst () const
+  {
+    return m_maxEntriesEachDst;
+  }
+  void SetMaxEntriesEachDst (uint32_t entries)
+  {
+    m_maxEntriesEachDst = entries;
+  }
+  Time GetBadLinkLifetime () const
+  {
+    return m_badLinkLifetime;
+  }
+  void SetBadLinkLifetime (Time t)
+  {
+    m_badLinkLifetime = t;
+  }
+  double GetStabilityDecrFactor () const
+  {
+    return m_stabilityDecrFactor;
+  }
+  void SetStabilityDecrFactor (double decrFactor)
+  {
+    m_stabilityDecrFactor = decrFactor;
+  }
+  double GetStabilityIncrFactor () const
+  {
+    return m_stabilityIncrFactor;
+  }
+  void SetStabilityIncrFactor (double incrFactor)
+  {
+    m_stabilityIncrFactor = incrFactor;
+  }
+  double GetInitStability () const
+  {
+    return m_initStability;
+  }
+  void SetInitStability (double initStability)
+  {
+    m_initStability = initStability;
+  }
+  double GetMinLifeTime () const
+  {
+    return m_minLifeTime;
+  }
+  void SetMinLifeTime (double minLifeTime)
+  {
+    m_minLifeTime = minLifeTime;
+  }
+  double GetUseExtends () const
+  {
+    return m_useExtends;
+  }
+  void SetUseExtends (double useExtends)
+  {
+    m_useExtends = useExtends;
+  }
+  // \}
+  /**
+   * Update route cache entry if it has been recently used and successfully delivered the data packet
+   * \param dst destination address of the route
+   * \param vec the route vector
+   * \return true in success
+   */
+  bool UpdateRouteEntry (Ipv4Address dst);
+  /**
+   * Add route cache entry if it doesn't yet exist in route cache
+   * \param rt route cache entry
+   * \return true in success
+   */
+  bool AddRoute (RouteCacheEntry & rt);
+  /**
+   * Lookup route cache entry with destination address dst
+   * \param dst destination address
+   * \param rt entry with destination address dst, if exists
+   * \return true on success
+   */
+  bool LookupRoute (Ipv4Address id, RouteCacheEntry & rt);
+  /**
+   * Print the route vector elements
+   * \param vec the route vector
+   */
+  void PrintVector (std::vector<Ipv4Address>& vec);
+  /**
+   * Print all the route vector elements from the route list
+   * \param route the route list
+   */
+  void PrintRouteVector (std::list<RouteCacheEntry> route);
+  /**
+   * Find the same route in the route cache
+   * \param rt entry with destination address dst, if exists
+   * \param rtVector the route vector
+   */
+  bool FindSameRoute (RouteCacheEntry & rt, std::list<RouteCacheEntry> & rtVector);
+  /**
+   * Delete the route with certain destination address
+   * \param dst the destination address of the routes that should be deleted
+   */
+  bool DeleteRoute (Ipv4Address dst);
+  /*
+   * Delete all the routes which includes the link from next hop address that has just been notified
+   * as unreachable
+   */
+  void DeleteAllRoutesIncludeLink (Ipv4Address errorSrc, Ipv4Address unreachNode, Ipv4Address node);
+  // / Delete all entries from routing table
+  void Clear ()
+  {
+    m_routeEntryVector.erase (m_routeEntryVector.begin (), m_routeEntryVector.end ());
+  }
+  // / Delete all outdated entries and invalidate valid entry if Lifetime is expired
+  void Purge ();
+  // / Print route cache
+  void Print (std::ostream &os);
+
+  //------------------------------------------------------------------------------------------
+  /*
+   * The following code deals with duplicate ack ids
+   */
+  // / Check for duplicate ids and save new entries if the id is not present in the table
+  uint16_t CheckUniqueAckId (Ipv4Address nextHop);
+  // / Get the ack table size
+  uint16_t GetAckSize ();
+
+  // --------------------------------------------------------------------------------------------
+  /*
+   * The following code handles link-layer acks
+   */
+  // / Neighbor description
+  struct Neighbor
+  {
+    Ipv4Address m_neighborAddress;
+    Mac48Address m_hardwareAddress;
+    Time m_expireTime;
+    bool close;
+
+    Neighbor (Ipv4Address ip, Mac48Address mac, Time t)
+      : m_neighborAddress (ip),
+        m_hardwareAddress (mac),
+        m_expireTime (t),
+        close (false)
+    {
+    }
+  };
+  // / Return expire time for neighbor node with address addr, if exists, else return 0.
+  Time GetExpireTime (Ipv4Address addr);
+  // / Check that node with address addr  is neighbor
+  bool IsNeighbor (Ipv4Address addr);
+  // / Update expire time for entry with address addr, if it exists, else add new entry
+  void UpdateNeighbor (std::vector<Ipv4Address> nodeList, Time expire);
+  // / Add to the neighbor list
+  void AddNeighbor (std::vector<Ipv4Address> nodeList, Ipv4Address ownAddress, Time expire);
+  // / Remove all expired mac entries
+  void PurgeMac ();
+  // / Schedule m_ntimer.
+  void ScheduleTimer ();
+  // / Remove all entries
+  void ClearMac ()
+  {
+    m_nb.clear ();
+  }
+  // / Add ARP cache to be used to allow layer 2 notifications processing
+  void AddArpCache (Ptr<ArpCache>);
+  // / Don't use given ARP cache any more (interface is down)
+  void DelArpCache (Ptr<ArpCache>);
+  // / Get callback to ProcessTxError
+  /*
+   * This callback is trying to use the wifi mac tx error header to notify a link layer drop event, however,
+   * it is not fully supported yet
+   */
+  Callback<void, WifiMacHeader const &> GetTxErrorCallback () const
+  {
+    return m_txErrorCallback;
+  }
+  // /\name Handle link failure callback
+  // \{
+  void SetCallback (Callback<void, Ipv4Address, uint8_t > cb)
+  {
+    m_handleLinkFailure = cb;
+  }
+  Callback<void, Ipv4Address, uint8_t > GetCallback () const
+  {
+    return m_handleLinkFailure;
+  }
+  // \}
+
+private:
+  RouteCache & operator= (RouteCache const &);
+  RouteCacheEntry::IP_VECTOR m_vector; // /< The route vector to save the ip addresses for intermediate nodes.
+  uint32_t m_maxCacheLen;              // /< The maximum number of packets that we allow a routing protocol to buffer.
+  Time     RouteCacheTimeout;          // /< The maximum period of time that dsr is allowed to for an unused route.
+  Time     m_badLinkLifetime;          // /< The time for which the neighboring node is put into the blacklist.
+  /*
+   * Define the parameters for link cache type
+   */
+  double m_stabilityDecrFactor;
+  double m_stabilityIncrFactor;
+  double m_initStability;
+  double m_minLifeTime;
+  double m_useExtends;
+  /*
+   * Define the route cache data structure
+   */
+  typedef std::list<RouteCacheEntry> routeEntryVector;
+  // / Map the ipv4Address to route entry vector
+  std::map<Ipv4Address, routeEntryVector> m_sortedRoutes;
+  // Define the route vector
+  routeEntryVector m_routeEntryVector;
+  // / number of entries for each destination
+  uint32_t m_maxEntriesEachDst;
+  // / The id cache to ensure all the ids are unique
+  std::map<Ipv4Address, uint16_t> m_ackIdCache;
+  // / Check if the route is using path cache or link cache
+  bool m_isLinkCache;
+  // / Check if save the sub route entries or not
+  bool m_subRoute;
+  /*
+   * The link cache to update all the link status, bi-link is two link for link is a struct
+   * when the weight is calculated we normalized them: 100*weight/max of Weight
+   */
+  #define MAXWEIGHT 0xFFFF;
+  /*
+   * Current network graph state for this node, double is weight, which is calculated by the node information
+   * and link information, any time some changes of link cache and node cache
+   * change the weight and then recompute the best choice for each node
+   */
+  std::map<Ipv4Address, std::map<Ipv4Address, uint32_t> > m_netGraph;
+  // for link route cache
+  std::map<Ipv4Address, RouteCacheEntry::IP_VECTOR> m_bestRoutesTable_link;
+  std::map<Link, LinkStab> m_linkCache;
+  std::map<Ipv4Address, NodeStab> m_nodeCache;
+  //used by LookupRoute when LinkCache
+  bool LookupRoute_Link (Ipv4Address id, RouteCacheEntry & rt);
+public:
+  /**
+   * \brief dijsktra algorithm to get the best route from m_netGraph and update the m_bestRoutesTable_link
+   * \when current graph information has changed
+   *
+   */
+  void SetCacheType (std::string type);
+  bool IsLinkCache ();
+  bool AddRoute_Link (RouteCacheEntry::IP_VECTOR nodelist, Ipv4Address node);
+  /*
+   *  USE MAXWEIGHT TO REPRESENT MAX; USE BROADCAST ADDRESS TO REPRESENT NULL PRECEEDING ADDRESS
+   */
+  void RebuildBestRouteTable (Ipv4Address source);
+  void PurgeLinkNode ();
+  /*
+   * When a link from the Route Cache is used in routing a packet originated or salvaged
+   * by that node, the stability metric for each of the two endpoint nodes of that link is incremented by the
+   * amount of time since that link was last used. When a link is used in a route chosen for a packet originated or
+   * salvaged by this node, the link's lifetime is set to be at least UseExtends into the future
+   */
+  void UseExtends (RouteCacheEntry::IP_VECTOR rt);
+  /**
+   *  \brief Update the Net Graph for the link and node cache has changed
+   */
+  void UpdateNetGraph ();
+  //---------------------------------------------------------------------------------------
+  /*
+   * The following code handles link-layer acks
+   */
+  // / link failure callback
+  Callback<void, Ipv4Address, uint8_t > m_handleLinkFailure;
+  // / TX error callback
+  Callback<void, WifiMacHeader const &> m_txErrorCallback;
+  // / Timer for neighbor's list. Schedule Purge().
+  Timer m_ntimer;
+  // / vector of entries
+  std::vector<Neighbor> m_nb;
+  // / list of ARP cached to be used for layer 2 notifications processing
+  std::vector<Ptr<ArpCache> > m_arp;
+  // This timeout deals with the passive ack
+  Time m_delay;
+  // / Find MAC address by IP using list of ARP caches
+  Mac48Address LookupMacAddress (Ipv4Address);
+  // / Process layer 2 TX error notification
+  void ProcessTxError (WifiMacHeader const &);
+};
+} // namespace dsr
+} // namespace ns3
+#endif /* DSR_RCACHE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-routing.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,2570 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#define NS_LOG_APPEND_CONTEXT                                   \
+  if (GetObject<Node> ()) { std::clog << "[node " << GetObject<Node> ()->GetId () << "] "; }
+
+#include <list>
+#include <ctime>
+#include <map>
+#include <limits>
+#include <algorithm>
+#include <iostream>
+
+#include "ns3/string.h"
+#include "ns3/ptr.h"
+#include "ns3/log.h"
+#include "ns3/assert.h"
+#include "ns3/uinteger.h"
+#include "ns3/object-vector.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/ipv4-l4-protocol.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/random-variable.h"
+#include "ns3/icmpv4-l4-protocol.h"
+#include "ns3/pointer.h"
+#include "ns3/adhoc-wifi-mac.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/packet.h"
+#include "ns3/boolean.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/udp-l4-protocol.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/tcp-socket-factory.h"
+#include "ns3/node-list.h"
+#include "ns3/double.h"
+
+#include "dsr-rreq-table.h"
+#include "dsr-rcache.h"
+#include "dsr-routing.h"
+#include "dsr-fs-header.h"
+#include "dsr-options.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsrRouting");
+
+namespace ns3 {
+namespace dsr {
+
+NS_OBJECT_ENSURE_REGISTERED (DsrRouting);
+
+/* see http://www.iana.org/assignments/protocol-numbers */
+const uint8_t DsrRouting::PROT_NUMBER = 48;
+/*
+ * The extension header is the fixed size dsr header, it is response for recognizing DSR option types
+ * and demux to right options to process the packet.
+ *
+ * The header format with neighboring layers is as follows:
+ *
+ +-+-+-+-+-+-+-+-+-+-+-
+ |  Application Header |
+ +-+-+-+-+-+-+-+-+-+-+-+
+ |   Transport Header  |
+ +-+-+-+-+-+-+-+-+-+-+-+
+ |   Fixed DSR Header  |
+ +---------------------+
+ |     DSR Options     |
+ +-+-+-+-+-+-+-+-+-+-+-+
+ |      IP Header      |
+ +-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+TypeId DsrRouting::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::DsrRouting")
+    .SetParent<Ipv4L4Protocol> ()
+    .AddConstructor<DsrRouting> ()
+    .AddAttribute ("RouteCache", "The route cache for saving routes from route discovery process.",
+                   PointerValue (0),
+                   MakePointerAccessor (&DsrRouting::SetRouteCache,
+                                        &DsrRouting::GetRouteCache),
+                   MakePointerChecker<RouteCache> ())
+    .AddAttribute ("RreqTable", "The request table to manage route requests.",
+                   PointerValue (0),
+                   MakePointerAccessor (&DsrRouting::SetRequestTable,
+                                        &DsrRouting::GetRequestTable),
+                   MakePointerChecker<RreqTable> ())
+    .AddAttribute ("MaxSendBuffLen","Maximum number of packets that can be stored in send buffer.",
+                   UintegerValue (64),
+                   MakeUintegerAccessor (&DsrRouting::m_maxSendBuffLen),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxSendBuffTime","Maximum time packets can be queued in the send buffer .",
+                   TimeValue (Seconds (30)),
+                   MakeTimeAccessor (&DsrRouting::m_sendBufferTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxMaintLen","Maximum number of packets that can be stored in maintenance buffer.",
+                   UintegerValue (50),
+                   MakeUintegerAccessor (&DsrRouting::m_maxMaintainLen),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxMaintTime","Maximum time packets can be queued in maintenance buffer.",
+                   TimeValue (Seconds (30)),
+                   MakeTimeAccessor (&DsrRouting::m_maxMaintainTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxCacheLen","Maximum number of route entries that can be stored in route cache.",
+                   UintegerValue (64),
+                   MakeUintegerAccessor (&DsrRouting::m_maxCacheLen),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RouteCacheTimeout","Maximum time the route cache can be queued in route cache.",
+                   TimeValue (Seconds (300)),
+                   MakeTimeAccessor (&DsrRouting::m_maxCacheTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("RreqEntryTimeout","Maximum time for the route request entry to time out.",
+                   TimeValue (Seconds (30)),
+                   MakeTimeAccessor (&DsrRouting::m_maxRreqTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxEntriesEachDst","Maximum number of route entries for a single destination to respond.",
+                   UintegerValue (20),
+                   MakeUintegerAccessor (&DsrRouting::m_maxEntriesEachDst),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("SendBuffInterval","How often to check send buffer for packet with route.",
+                   TimeValue (Seconds (50)),
+                   MakeTimeAccessor (&DsrRouting::m_sendBuffInterval),
+                   MakeTimeChecker ())
+    .AddAttribute ("NodeTraversalTime","The time it takes to traverse two neighboring nodes.",
+                   TimeValue (MicroSeconds (2)),
+                   MakeTimeAccessor (&DsrRouting::m_nodeTraversalTime),
+                   MakeTimeChecker ())
+    .AddAttribute ("RreqRetries","Maximum number of retransmissions for request discovery of a route.",
+                   UintegerValue (16),
+                   MakeUintegerAccessor (&DsrRouting::m_rreqRetries),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaintenanceRetries","Maximum number of retransmissions for data packets from maintenance buffer.",
+                   UintegerValue (3),
+                   MakeUintegerAccessor (&DsrRouting::m_maxMaintRexmt),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RequestTableSize","Maximum number of request entries in the request table.",
+                   UintegerValue (64),
+                   MakeUintegerAccessor (&DsrRouting::m_requestTableSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RequestIdSize","Maximum number of request source Ids in the request table.",
+                   UintegerValue (16),
+                   MakeUintegerAccessor (&DsrRouting::m_requestTableIds),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("UniqueRequestIdSize","Maximum number of request Ids in the request table for a single destination.",
+                   UintegerValue (256),
+                   MakeUintegerAccessor (&DsrRouting::m_maxRreqId),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("NonPropRequestTimeout","The timeout value for non-propagation request.",
+                   TimeValue (MilliSeconds (30)),
+                   MakeTimeAccessor (&DsrRouting::m_nonpropRequestTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("DiscoveryHopLimit","The max discovery hop limit for route requests.",
+                   UintegerValue (255),
+                   MakeUintegerAccessor (&DsrRouting::m_discoveryHopLimit),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("MaxSalvageCount","The max salvage count for a single data packet.",
+                   UintegerValue (15),
+                   MakeUintegerAccessor (&DsrRouting::m_maxSalvageCount),
+                   MakeUintegerChecker<uint8_t> ())
+    .AddAttribute ("BlacklistTimeout","The time for a neighbor to stay in blacklist.",
+                   TimeValue (Seconds (3)),
+                   MakeTimeAccessor (&DsrRouting::m_blacklistTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("GratReplyHoldoff","The time for gratuitous reply entry to expire.",
+                   TimeValue (Seconds (1)),
+                   MakeTimeAccessor (&DsrRouting::m_gratReplyHoldoff),
+                   MakeTimeChecker ())
+    .AddAttribute ("BroadcastJitter","The jitter time to avoid collision for broadcast packets.",
+                   UintegerValue (10),
+                   MakeUintegerAccessor (&DsrRouting::m_broadcastJitter),
+                   MakeUintegerChecker<uint16_t> ())
+    .AddAttribute ("PassiveAckTimeout","The time a packet in maintenance buffer wait for passive acknowledgment.",
+                   TimeValue (MicroSeconds (4)),
+                   MakeTimeAccessor (&DsrRouting::m_passiveAckTimeout),
+                   MakeTimeChecker ())
+    .AddAttribute ("TryPassiveAcks","The number of passive acknowledgment to use.",
+                   UintegerValue (1),
+                   MakeUintegerAccessor (&DsrRouting::m_tryPassiveAcks),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("RequestPeriod","The base time interval between route requests.",
+                   TimeValue (MilliSeconds (500)),
+                   MakeTimeAccessor (&DsrRouting::m_requestPeriod),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxRequestPeriod","The max time interval between route requests.",
+                   TimeValue (Seconds (10)),
+                   MakeTimeAccessor (&DsrRouting::m_maxRequestPeriod),
+                   MakeTimeChecker ())
+    .AddAttribute ("GraReplyTableSize","The gratuitous reply table size.",
+                   UintegerValue (64),
+                   MakeUintegerAccessor (&DsrRouting::m_graReplyTableSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("CacheType","Use Link Cache or use Path Cache",
+                   StringValue ("LinkCache"),
+                   MakeStringAccessor (&DsrRouting::m_cacheType),
+                   MakeStringChecker ())
+    .AddAttribute ("StabilityDecrFactor","The stability decrease factor for link cache",
+                   DoubleValue (2.0),
+                   MakeDoubleAccessor (&DsrRouting::m_stabilityDecrFactor),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("StabilityIncrFactor","The stability increase factor for link cache",
+                   DoubleValue (4.0),
+                   MakeDoubleAccessor (&DsrRouting::m_stabilityIncrFactor),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("InitStability","The initial stability factor for link cache",
+                   DoubleValue (25.0),
+                   MakeDoubleAccessor (&DsrRouting::m_initStability),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("MinLifeTime","The minimal life time for link cache",
+                   DoubleValue (1.0),
+                   MakeDoubleAccessor (&DsrRouting::m_minLifeTime),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("UseExtends","The extension time for link cache",
+                   DoubleValue (120.0),
+                   MakeDoubleAccessor (&DsrRouting::m_useExtends),
+                   MakeDoubleChecker<double> ())
+    .AddAttribute ("EnableSubRoute","Enables saving of sub route when receiving route error messages, only available when using path route cache",
+                   BooleanValue (true),
+                   MakeBooleanAccessor (&DsrRouting::m_subRoute),
+                   MakeBooleanChecker ())
+    .AddTraceSource ("Tx", "Send DSR packet.",
+                     MakeTraceSourceAccessor (&DsrRouting::m_txPacketTrace))
+    .AddTraceSource ("Drop", "Drop DSR packet",
+                     MakeTraceSourceAccessor (&DsrRouting::m_dropTrace))
+  ;
+  return tid;
+}
+
+DsrRouting::DsrRouting ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  /*
+   * The following Ptr statements created objects for all the options header for DSR, and each of them have
+   * distinct option number assigned, when DSR Routing received a packet from higher layer, it will find
+   * the following options based on the option number, and pass the packet to the appropriate option to
+   * process it. After the option processing, it will pass the packet back to DSR Routing to send down layer.
+   */
+  Ptr<dsr::DsrOptionPad1> pad1Option = CreateObject<dsr::DsrOptionPad1> ();
+  Ptr<dsr::DsrOptionPadn> padnOption = CreateObject<dsr::DsrOptionPadn> ();
+  Ptr<dsr::DsrOptionRreq> rreqOption = CreateObject<dsr::DsrOptionRreq> ();
+  Ptr<dsr::DsrOptionRrep> rrepOption = CreateObject<dsr::DsrOptionRrep> ();
+  Ptr<dsr::DsrOptionSR>   srOption = CreateObject<dsr::DsrOptionSR> ();
+  Ptr<dsr::DsrOptionRerr>   rerrOption = CreateObject<dsr::DsrOptionRerr> ();
+  Ptr<dsr::DsrOptionAckReq> ackReq = CreateObject<dsr::DsrOptionAckReq> ();
+  Ptr<dsr::DsrOptionAck> ack = CreateObject<dsr::DsrOptionAck> ();
+
+  Insert (pad1Option);
+  Insert (padnOption);
+  Insert (rreqOption);
+  Insert (rrepOption);
+  Insert (srOption);
+  Insert (rerrOption);
+  Insert (ackReq);
+  Insert (ack);
+
+  // Check the send buffer for sending packets
+  m_sendBuffTimer.SetFunction (&DsrRouting::SendBuffTimerExpire, this);
+  m_sendBuffTimer.Schedule (Seconds (0));
+}
+
+DsrRouting::~DsrRouting ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+DsrRouting::NotifyNewAggregate ()
+{
+  NS_LOG_FUNCTION (this << "NotifyNewAggregate");
+  if (m_node == 0)
+    {
+      Ptr<Node> node = this->GetObject<Node> ();
+      if (node != 0)
+        {
+          m_ipv4 = this->GetObject<Ipv4L3Protocol> ();
+          if (m_ipv4 != 0)
+            {
+              this->SetNode (node);
+              m_ipv4->Insert (this);
+              this->SetDownTarget (MakeCallback (&Ipv4L3Protocol::Send, m_ipv4));
+            }
+
+          m_ip = node->GetObject<Ipv4> ();
+          if (m_ip != 0)
+            {
+              NS_LOG_DEBUG ("Ipv4 started");
+            }
+        }
+    }
+  Object::NotifyNewAggregate ();
+  Simulator::ScheduleNow (&DsrRouting::Start, this);
+}
+
+void DsrRouting::Start ()
+{
+  NS_LOG_FUNCTION (this << "Start DSR Routing protocol");
+  if (m_mainAddress == Ipv4Address ())
+    {
+      Ipv4Address loopback ("127.0.0.1");
+      for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+        {
+          // Use primary address, if multiple
+          Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
+          m_broadcast = m_ipv4->GetAddress (i, 0).GetBroadcast ();
+          NS_LOG_DEBUG ("The addr " << addr);
+          if (addr != loopback)
+            {
+              m_mainAddress = addr;
+              NS_LOG_DEBUG ("The node Address " << m_mainAddress);
+
+              m_ipv4->GetNetDevice (1)->SetPromiscReceiveCallback (MakeCallback (&DsrRouting::PromiscReceive, this));
+
+              // Allow neighbor manager use this interface for layer 2 feedback if possible
+              Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (addr));
+              Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
+              if (wifi == 0)
+                {
+                  break;
+                }
+              Ptr<WifiMac> mac = wifi->GetMac ();
+              if (mac == 0)
+                {
+                  break;
+                }
+
+              // trace back to link mac drop event to process tx error call back
+              mac->TraceConnectWithoutContext ("TxErrHeader", m_routeCache->GetTxErrorCallback ());
+              m_routeCache->AddArpCache (m_ipv4->GetInterface (i)->GetArpCache ());
+              break;
+            }
+        }
+    }
+
+  // Set the initial hop limit
+  m_rreqTable->SetInitHopLimit (m_discoveryHopLimit);
+  // Configure the request table parameters
+  m_rreqTable->SetRreqTableSize (m_requestTableSize);
+  m_rreqTable->SetRreqIdSize (m_requestTableIds);
+  m_rreqTable->SetUniqueRreqIdSize (m_maxRreqId);
+  m_rreqTable->SetRreqExpire (m_maxRreqTime);
+  // Set the send buffer parameters
+  m_sendBuffer.SetMaxQueueLen (m_maxSendBuffLen);
+  m_sendBuffer.SetSendBufferTimeout (m_sendBufferTimeout);
+  // Set the maintenance buffer parameters
+  m_maintainBuffer.SetMaxQueueLen (m_maxMaintainLen);
+  m_maintainBuffer.SetMaintainBufferTimeout (m_maxMaintainTime);
+  // Set the gratuitous reply table size
+  m_graReply.SetGraTableSize (m_graReplyTableSize);
+  // Configure the path cache parameters
+  m_routeCache->SetCacheType (m_cacheType);
+  m_routeCache->SetSubRoute (m_subRoute);
+  m_routeCache->SetMaxCacheLen (m_maxCacheLen);
+  m_routeCache->SetCacheTimeout (m_maxCacheTime);
+  m_routeCache->SetMaxEntriesEachDst (m_maxEntriesEachDst);
+  // parameters for link cache
+  m_routeCache->SetStabilityDecrFactor (m_stabilityDecrFactor);
+  m_routeCache->SetStabilityIncrFactor (m_stabilityIncrFactor);
+  m_routeCache->SetInitStability (m_initStability);
+  m_routeCache->SetMinLifeTime (m_minLifeTime);
+  m_routeCache->SetUseExtends (m_useExtends);
+  m_routeCache->ScheduleTimer ();
+  // The call back to handle link error and send error message to appropriate nodes
+  m_routeCache->SetCallback (MakeCallback (&DsrRouting::SendRerrWhenBreaksLinkToNextHop, this));
+  NS_LOG_DEBUG ("Starting DSR on node " << m_mainAddress);
+}
+
+void
+DsrRouting::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+Ptr<Node>
+DsrRouting::GetNode () const
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  return m_node;
+}
+
+void DsrRouting::SetRouteCache (Ptr<dsr::RouteCache> r)
+{
+  // / Set the route cache to use
+  m_routeCache = r;
+}
+
+Ptr<dsr::RouteCache>
+DsrRouting::GetRouteCache () const
+{
+  // / Get the route cache to use
+  return m_routeCache;
+}
+
+void DsrRouting::SetRequestTable (Ptr<dsr::RreqTable> q)
+{
+  // / Set the request table to use
+  m_rreqTable = q;
+}
+
+Ptr<dsr::RreqTable>
+DsrRouting::GetRequestTable () const
+{
+  // / Get the request table to use
+  return m_rreqTable;
+}
+
+Ipv4Address
+DsrRouting::GetIPfromMAC (Mac48Address address)
+{
+  int32_t nNodes = NodeList::GetNNodes ();
+  for (int32_t i = 0; i < nNodes; ++i)
+    {
+      Ptr<Node> node = NodeList::GetNode (i);
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      Ptr<NetDevice> netDevice = ipv4->GetNetDevice (1);
+
+      if (netDevice->GetAddress () == address)
+        {
+          return ipv4->GetAddress (1, 0).GetLocal ();
+        }
+    }
+  return 0;
+}
+
+void DsrRouting::PrintVector (std::vector<Ipv4Address>& vec)
+{
+  /*
+   * Check elements in a route vector
+   */
+  if (!vec.size ())
+    {
+      NS_LOG_DEBUG ("The vector is empty");
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Print all the elements in a vector");
+      for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
+        {
+          NS_LOG_DEBUG ("The ip address " << *i);
+        }
+    }
+}
+
+Ipv4Address DsrRouting::SearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec)
+{
+  Ipv4Address nextHop;
+  if (vec.size () == 2)
+    {
+      NS_LOG_DEBUG ("The two nodes are neighbors");
+      nextHop = vec[1];
+      return nextHop;
+    }
+  else
+    {
+      if (ipv4Address == vec.back ())
+        {
+          NS_LOG_DEBUG ("We have reached to the final destination " << ipv4Address << " " << vec.back ());
+          return ipv4Address;
+        }
+      for (std::vector<Ipv4Address>::iterator i = vec.begin (); i != vec.end (); ++i)
+        {
+          if (ipv4Address == (*i))
+            {
+              nextHop = *(++i);
+              return nextHop;
+            }
+        }
+    }
+  NS_LOG_DEBUG ("Next hop address not found");
+  Ipv4Address none = "0.0.0.0";
+  return none;
+}
+
+Ptr<Ipv4Route>
+DsrRouting::SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress)
+{
+  NS_LOG_FUNCTION (this << nextHop << srcAddress);
+  m_ipv4Route = Create<Ipv4Route> ();
+  m_ipv4Route->SetDestination (nextHop);
+  m_ipv4Route->SetGateway (nextHop);
+  m_ipv4Route->SetSource (srcAddress);
+  return m_ipv4Route;
+}
+
+void
+DsrRouting::CutRoute (Ipv4Address ourAdd, std::vector<Ipv4Address>& nodeList)
+{
+  NS_LOG_FUNCTION (this << ourAdd);
+  std::vector<Ipv4Address> newRoute = nodeList;
+  nodeList.clear ();
+
+  std::vector<Ipv4Address>::iterator it = find (newRoute.begin (), newRoute.end (), ourAdd);
+
+  for (std::vector<Ipv4Address>::iterator i = it; i != newRoute.end (); ++i)
+    {
+      nodeList.push_back (*i);
+    }
+}
+
+int
+DsrRouting::GetProtocolNumber (void) const
+{
+  // / This is the protocol number for DSR which is 48
+  return PROT_NUMBER;
+}
+
+void
+DsrRouting::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  Ipv4L4Protocol::DoDispose ();
+}
+
+uint32_t
+DsrRouting::GetIDfromIP (Ipv4Address address)
+{
+  int32_t nNodes = NodeList::GetNNodes ();
+  for (int32_t i = 0; i < nNodes; ++i)
+    {
+      Ptr<Node> node = NodeList::GetNode (i);
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      if (ipv4->GetAddress (1, 0).GetLocal () == address)
+        {
+          return i;
+        }
+    }
+  return 255;
+}
+
+Ipv4Address
+DsrRouting::GetIPfromID (uint32_t id)
+{
+  if (id >= 255)
+    {
+      NS_LOG_DEBUG ("Exceed the node range");
+      return "0.0.0.0";
+    }
+  else
+    {
+      Ptr<Node> node = NodeList::GetNode (id);
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      return ipv4->GetAddress (1, 0).GetLocal ();
+    }
+}
+
+void DsrRouting::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << nextHop << (uint32_t)protocol);
+  MaintainBuffEntry entry;
+  // Find the packet in send buffer
+  if (m_maintainBuffer.Find (nextHop))
+    {
+      NS_LOG_DEBUG ("Trying to dequeue");
+
+      if (m_maintainBuffer.Dequeue (nextHop, entry))
+        {
+          NS_LOG_DEBUG ("creating new packet");
+          /*
+           * Copy the packet and save a copy to the send buffer.
+           * For some reason, when queue the original packet to the buffer,
+           * when dequeue the packet, it turns to be empty.
+           */
+          Ptr<Packet> dequeP = ConstCast<Packet> (entry.GetPacket ());
+          Ptr<Packet> newPacket = dequeP->Copy ();
+          Ptr<Packet> p = dequeP->Copy ();
+
+          Ipv4Address source = entry.GetSrc ();
+          Ipv4Address destination = entry.GetDst ();
+
+          DsrRoutingHeader dsrRoutingHeader;
+          p->RemoveHeader (dsrRoutingHeader);
+          uint8_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
+          newPacket->RemoveAtStart (offset);
+
+          // Get the number of routers' address field
+          uint8_t buf[2];
+          newPacket->CopyData (buf, sizeof(buf));
+          uint8_t numberAddress = (buf[1] - 2) / 4;
+
+          DsrOptionSRHeader sourceRoute;
+          sourceRoute.SetNumberAddress (numberAddress);
+          newPacket->RemoveHeader (sourceRoute);
+          uint8_t salvage = sourceRoute.GetSalvage ();
+
+          DsrOptionAckReqHeader ackReq;
+          newPacket->RemoveHeader (ackReq);
+          /*
+           * Get the node list address
+           */
+          std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
+          Ipv4Address address1 = nodeList.front ();
+          Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);
+          NS_LOG_DEBUG ("The next hop address" << nextHop);
+          if (nextHop == "0.0.0.0")
+            {
+              return;
+            }
+          RouteCacheEntry salvageRoute;
+          bool findRoute = m_routeCache->LookupRoute (destination, salvageRoute);
+          // Check the salvage value in header, if salvage is needed, we should find alternative route
+          if (findRoute && (salvage < m_maxSalvageCount))
+            {
+              // Need to salvage the packet instead of discard it
+              Ipv4Address source = nodeList.front ();
+              std::vector<Ipv4Address> nodeList = salvageRoute.GetVector ();
+              DsrOptionSRHeader newSR;
+              newSR.SetNodesAddress (nodeList);
+              newSR.SetSegmentsLeft ((nodeList.size () - 2));
+              newSR.SetSalvage (salvage + 1);
+              if (m_routeCache->IsLinkCache ())
+                {
+                  m_routeCache->UseExtends (nodeList);
+                }
+              PacketKey packetKey;
+              packetKey.m_ackId = entry.GetAckId ();
+              packetKey.m_ourAdd = entry.GetOurAdd ();
+              packetKey.m_nextHop = entry.GetNextHop ();
+              packetKey.m_source = entry.GetSrc ();
+              packetKey.m_destination = entry.GetDst ();
+              packetKey.m_segsLeft = entry.GetSegsLeft ();
+              SchedulePacketRetry (entry, packetKey, protocol);
+            }
+          else
+            {
+              /*
+               * This code block create a packet and attach a route error option to it
+               */
+              m_routeCache->DeleteAllRoutesIncludeLink (source, nextHop, m_mainAddress);
+
+              /*
+               * If the salvage is not 0, use the first address in the route as the error dst in error header
+               * otherwise use the source of packet as the error destination
+               */
+              if (salvage)
+                {
+                  if (address1 == m_mainAddress)
+                    {
+                      DsrOptionRerrUnreachHeader rerr;
+                      rerr.SetErrorType (1);
+                      rerr.SetErrorSrc (address1);
+                      rerr.SetUnreachNode (nextHop);
+                      rerr.SetErrorDst (address1);
+                      rerr.SetSalvage (salvage);       // Set the value about whether to salvage a packet or not
+                      SendErrorRequest (rerr, protocol);
+                    }
+                  else
+                    {
+                      SendUnreachError (nextHop, address1, salvage, protocol);
+                    }
+                }
+              else
+                {
+                  if (source == m_mainAddress)
+                    {
+                      DsrOptionRerrUnreachHeader rerr;
+                      rerr.SetErrorType (1);
+                      rerr.SetErrorSrc (source);
+                      rerr.SetUnreachNode (nextHop);
+                      rerr.SetErrorDst (source);
+                      rerr.SetSalvage (salvage);     // Set the value about whether to salvage a packet or not
+                      SendErrorRequest (rerr, protocol);
+                    }
+                  else
+                    {
+                      SendUnreachError (nextHop, source, salvage, protocol);
+                    }
+                }
+            }
+          if (m_maintainBuffer.GetSize () != 0 && m_maintainBuffer.Find (nextHop))
+            {
+              Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
+                                   &DsrRouting::SendRerrWhenBreaksLinkToNextHop,this,nextHop,protocol);
+            }
+        }
+    }
+}
+
+void DsrRouting::SendBuffTimerExpire ()
+{
+  if (m_sendBuffTimer.IsRunning ())
+    {
+      m_sendBuffTimer.Cancel ();
+    }
+  m_sendBuffTimer.Schedule (m_sendBuffInterval);
+  CheckSendBuffer ();
+}
+
+void DsrRouting::CheckSendBuffer ()
+{
+  NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+               << " Checking send buffer at " << m_mainAddress << " with size " << m_sendBuffer.GetSize ());
+
+  for (std::vector<SendBuffEntry>::iterator i = m_sendBuffer.GetBuffer ().begin (); i != m_sendBuffer.GetBuffer ().end (); )
+    {
+      NS_LOG_DEBUG ("Here we try to find the data packet in the send buffer");
+      Ipv4Address destination = i->GetDestination ();
+      RouteCacheEntry toDst;
+      bool findRoute = m_routeCache->LookupRoute (destination, toDst);
+      if (findRoute)
+        {
+          NS_LOG_INFO ("We have found a route for the packet");
+          Ptr<const Packet> packet = i->GetPacket ();
+          Ptr<Packet> cleanP = packet->Copy ();
+          uint8_t protocol = i->GetProtocol ();
+
+          m_sendBuffer.GetBuffer ().erase (i);
+
+          DsrRoutingHeader dsrRoutingHeader;
+          Ptr<Packet> copyP = packet->Copy ();
+          uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
+          copyP->RemoveAtStart (offset); // Here the processed size is 8 bytes, which is the fixed sized extension header
+          // The packet to get ipv4 header
+          Ptr<Packet> ipv4P = copyP->Copy ();
+          /*
+           * Peek data to get the option type as well as length and segmentsLeft field
+           */
+          uint32_t size = copyP->GetSize ();
+          uint8_t *data = new uint8_t[size];
+          copyP->CopyData (data, size);
+
+          uint8_t optionType = 0;
+          optionType = *(data);
+
+          if (optionType == 3)
+            {
+              Ptr<dsr::DsrOptions> dsrOption;
+              DsrOptionHeader dsrOptionHeader;
+              uint8_t errorType = *(data + 2);
+
+              if (errorType == 1) // This is the Route Error Option
+                {
+                  DsrOptionRerrUnreachHeader rerr;
+                  copyP->RemoveHeader (rerr);
+                  NS_ASSERT (copyP->GetSize () == 0);
+
+                  DsrOptionRerrUnreachHeader newUnreach;
+                  newUnreach.SetErrorType (1);
+                  newUnreach.SetErrorSrc (rerr.GetErrorSrc ());
+                  newUnreach.SetUnreachNode (rerr.GetUnreachNode ());
+                  newUnreach.SetErrorDst (rerr.GetErrorDst ());
+                  newUnreach.SetSalvage (rerr.GetSalvage ()); // Set the value about whether to salvage a packet or not
+
+                  DsrOptionSRHeader sourceRoute;
+                  std::vector<Ipv4Address> errorRoute = toDst.GetVector ();
+                  sourceRoute.SetNodesAddress (errorRoute);
+                  if (m_routeCache->IsLinkCache ())
+                    {
+                      m_routeCache->UseExtends (errorRoute);
+                    }
+                  sourceRoute.SetSegmentsLeft ((errorRoute.size () - 2));
+                  uint8_t salvage = 0;
+                  sourceRoute.SetSalvage (salvage);
+                  Ipv4Address nextHop = SearchNextHop (m_mainAddress, errorRoute); // Get the next hop address
+
+                  if (nextHop == "0.0.0.0")
+                    {
+                      return;
+                    }
+
+                  SetRoute (nextHop, m_mainAddress);
+                  uint8_t length = (sourceRoute.GetLength () + newUnreach.GetLength ());
+                  dsrRoutingHeader.SetNextHeader (protocol);
+                  dsrRoutingHeader.SetMessageType (1);
+                  dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
+                  dsrRoutingHeader.SetDestId (255);
+                  dsrRoutingHeader.SetPayloadLength (length + 4);
+                  dsrRoutingHeader.AddDsrOption (newUnreach);
+                  dsrRoutingHeader.AddDsrOption (sourceRoute);
+
+                  Ptr<Packet> newPacket = Create<Packet> ();
+                  newPacket->AddHeader (dsrRoutingHeader); // Add the routing header with rerr and sourceRoute attached to it
+                  Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+                  m_ipv4Route->SetOutputDevice (dev);
+                  m_downTarget (newPacket, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route);
+                }
+            }
+          else
+            {
+              dsrRoutingHeader.SetNextHeader (protocol);
+              dsrRoutingHeader.SetMessageType (2);
+              dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
+              dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
+
+              DsrOptionSRHeader sourceRoute;
+              std::vector<Ipv4Address> nodeList = toDst.GetVector (); // Get the route from the route entry we found
+              Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);  // Get the next hop address for the route
+              if (nextHop == "0.0.0.0")
+                {
+                  PacketNewRoute (cleanP, m_mainAddress, destination, protocol);
+                  return;
+                }
+              uint8_t salvage = 0;
+              sourceRoute.SetNodesAddress (nodeList); // Save the whole route in the source route header of the packet
+              sourceRoute.SetSegmentsLeft ((nodeList.size () - 2)); // The segmentsLeft field will indicate the hops to go
+              sourceRoute.SetSalvage (salvage);
+
+              DsrOptionAckReqHeader ackReq;
+              m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+              ackReq.SetAckId (m_ackId);
+
+              uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+              NS_LOG_DEBUG ("the length of source route header " << (uint32_t)(sourceRoute.GetLength ()));
+              NS_LOG_DEBUG ("the length of ack request header " << (uint32_t)(ackReq.GetLength ()));
+
+              dsrRoutingHeader.SetPayloadLength (length + 4);
+              dsrRoutingHeader.AddDsrOption (sourceRoute);
+              dsrRoutingHeader.AddDsrOption (ackReq);
+              cleanP->AddHeader (dsrRoutingHeader);
+              Ptr<const Packet> mtP = cleanP->Copy ();
+              // Put the data packet in the maintenance queue for data packet retransmission
+              MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*Ipv4Address=*/ m_mainAddress, /*nextHop=*/ nextHop,
+                                                      /*source=*/ m_mainAddress, /*destination=*/ destination, /*ackId=*/ m_ackId,
+                                                      /*SegsLeft=*/ nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
+              bool result = m_maintainBuffer.Enqueue (newEntry); // Enqueue the packet the the maintenance buffer
+              if (result)
+                {
+                  Ptr<Packet> newPacket = cleanP->Copy ();
+                  PacketKey packetKey;
+                  packetKey.m_ackId = newEntry.GetAckId ();
+                  packetKey.m_ourAdd = newEntry.GetOurAdd ();
+                  packetKey.m_nextHop = newEntry.GetNextHop ();
+                  packetKey.m_source = newEntry.GetSrc ();
+                  packetKey.m_destination = newEntry.GetDst ();
+                  packetKey.m_segsLeft = newEntry.GetSegsLeft ();
+                  SchedulePacketRetry (newEntry, packetKey, protocol);
+                }
+              //we need to suspend the normal timer that checks the send buffer
+              //until we are done sending packets
+              if (!m_sendBuffTimer.IsSuspended ())
+                {
+                  m_sendBuffTimer.Suspend ();
+                }
+              Simulator::Schedule (m_sendBuffInterval, &DsrRouting::CheckSendBuffer, this);
+              return;
+            }
+        }
+      else
+        {
+          ++i;
+        }
+    }
+  //after going through the entire send buffer and send all packets found route,
+  //we need to resume the timer if it has been suspended
+  if (m_sendBuffTimer.IsSuspended ())
+    {
+      NS_LOG_DEBUG ("Resume the send buffer timer");
+      m_sendBuffTimer.Resume ();
+    }
+}
+
+bool DsrRouting::PromiscReceive (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol, const Address &from,
+                                 const Address &to, NetDevice::PacketType packetType)
+{
+  // Receive only IP packets and packets destined for other hosts
+  if (protocol == Ipv4L3Protocol::PROT_NUMBER && packetType == NetDevice::PACKET_OTHERHOST)
+    {
+      Ptr<Packet> p = packet->Copy ();
+      //pull off IP header
+      Ipv4Header ipv4Header;
+      p->RemoveHeader (ipv4Header);
+
+      // Process only data packets with DSR header
+      if (ipv4Header.GetProtocol () == DsrRouting::PROT_NUMBER)
+        {
+          //just to minimize debug output
+          NS_LOG_INFO (this << from << to << packetType << *p);
+          DsrRoutingHeader dsrRoutingHeader;
+          //pull of DSR header to check option type
+          Ptr<Packet> dsrPacket = p->Copy ();
+          dsrPacket->RemoveHeader (dsrRoutingHeader);
+          uint8_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();        // Get the offset for option header, 4 bytes in this case
+          uint8_t nextHeader = dsrRoutingHeader.GetNextHeader ();
+          uint32_t sourceId = dsrRoutingHeader.GetSourceId ();
+          Ipv4Address source = GetIPfromID (sourceId);
+
+          // This packet is used to peek option type
+          p->RemoveAtStart (offset);
+          /*
+           * Peek data to get the option type as well as length and segmentsLeft field
+           */
+          uint32_t size = p->GetSize ();
+          uint8_t *data = new uint8_t[size];
+          p->CopyData (data, size);
+          uint8_t optionType = 0;
+          uint8_t optionLength = 0;
+
+          optionType = *(data);
+          Ptr<dsr::DsrOptions> dsrOption;
+
+          if (optionType == 96)        // This is the source route option
+            {
+              dsrOption = GetOption (optionType);       // Get the relative DSR option and demux to the process function
+              Ipv4Address fromAddr = GetIPfromMAC (Mac48Address::ConvertFrom (from));
+              Ipv4Address toAddr = GetIPfromMAC (Mac48Address::ConvertFrom (to));
+
+              NS_LOG_DEBUG (Simulator::Now ().GetSeconds ()
+                            << " DSR node " << m_mainAddress <<
+                            " overhearing packet PID: " << p->GetUid () << " from " << fromAddr << " to " << toAddr <<
+                            " with source IP " << ipv4Header.GetSource () <<
+                            " and destination IP " << ipv4Header.GetDestination () <<
+                            " and packet : " << *dsrPacket);
+              bool isPromisc = true;                     // Set the boolean value isPromisc as true
+              optionLength = dsrOption->Process (p, dsrPacket, m_mainAddress, source, ipv4Header, nextHeader, isPromisc);
+              return true;
+            }
+        }
+    }
+  return false;
+}
+
+void
+DsrRouting::PacketNewRoute (Ptr<Packet> packet,
+                            Ipv4Address source,
+                            Ipv4Address destination,
+                            uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol);
+  // Look up routes for the specific destination
+  RouteCacheEntry toDst;
+  bool findRoute = m_routeCache->LookupRoute (destination, toDst);
+  // Queue the packet if there is no route pre-existing
+  if (!findRoute)
+    {
+      NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+                   << "s " << m_mainAddress << " there is no route for this packet, queue the packet");
+
+      Ptr<Packet> p = packet->Copy ();
+      SendBuffEntry newEntry (p, destination, m_sendBufferTimeout, protocol);     // Create a new entry for send buffer
+      bool result = m_sendBuffer.Enqueue (newEntry);     // Enqueue the packet in send buffer
+      if (result)
+        {
+          NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+                       << "s Add packet PID: " << packet->GetUid () << " to queue. Packet: " << *packet);
+
+          NS_LOG_LOGIC ("Send RREQ to" << destination);
+          if ((m_addressReqTimer.find (destination) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (destination) == m_nonPropReqTimer.end ()))
+            {
+              /*
+               * Call the send request function, it will update the request table entry and ttl there
+               */
+              SendInitialRequest (source, destination, protocol);
+            }
+        }
+    }
+  else
+    {
+      Ptr<Packet> cleanP = packet->Copy ();
+      DsrRoutingHeader dsrRoutingHeader;
+      dsrRoutingHeader.SetNextHeader (protocol);
+      dsrRoutingHeader.SetMessageType (2);
+      dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+      dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
+
+      DsrOptionSRHeader sourceRoute;
+      std::vector<Ipv4Address> nodeList = toDst.GetVector ();     // Get the route from the route entry we found
+      Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);      // Get the next hop address for the route
+      if (nextHop == "0.0.0.0")
+        {
+          PacketNewRoute (cleanP, source, destination, protocol);
+          return;
+        }
+      uint8_t salvage = 0;
+      sourceRoute.SetNodesAddress (nodeList);     // Save the whole route in the source route header of the packet
+      if (m_routeCache->IsLinkCache ())
+        {
+          m_routeCache->UseExtends (nodeList);
+        }
+      sourceRoute.SetSegmentsLeft ((nodeList.size () - 2));     // The segmentsLeft field will indicate the hops to go
+      sourceRoute.SetSalvage (salvage);
+
+      DsrOptionAckReqHeader ackReq;
+      m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+      ackReq.SetAckId (m_ackId);
+
+      uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+      dsrRoutingHeader.SetPayloadLength (length + 4);
+      dsrRoutingHeader.AddDsrOption (sourceRoute);
+      dsrRoutingHeader.AddDsrOption (ackReq);
+      cleanP->AddHeader (dsrRoutingHeader);
+      Ptr<const Packet> mtP = cleanP->Copy ();
+      SetRoute (nextHop, m_mainAddress);
+      // Put the data packet in the maintenance queue for data packet retransmission
+      MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*Ipv4Address=*/ m_mainAddress, /*nextHop=*/ nextHop,
+                                              /*source=*/ source, /*destination=*/ destination, /*ackId=*/ m_ackId,
+                                              /*SegsLeft=*/ nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
+      bool result = m_maintainBuffer.Enqueue (newEntry);     // Enqueue the packet the the maintenance buffer
+
+      if (result)
+        {
+          PacketKey packetKey;
+          packetKey.m_ackId = newEntry.GetAckId ();
+          packetKey.m_ourAdd = newEntry.GetOurAdd ();
+          packetKey.m_nextHop = newEntry.GetNextHop ();
+          packetKey.m_source = newEntry.GetSrc ();
+          packetKey.m_destination = newEntry.GetDst ();
+          packetKey.m_segsLeft = newEntry.GetSegsLeft ();
+          SchedulePacketRetry (newEntry, packetKey, protocol);
+        }
+    }
+}
+
+void
+DsrRouting::SendUnreachError (Ipv4Address errorHop, Ipv4Address destination, uint8_t salvage, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << errorHop << destination << (uint32_t)salvage << (uint32_t)protocol);
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrRoutingHeader.SetNextHeader (protocol);
+  dsrRoutingHeader.SetMessageType (1);
+  dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
+  dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
+
+  DsrOptionRerrUnreachHeader rerrUnreachHeader;
+  rerrUnreachHeader.SetErrorType (1);
+  rerrUnreachHeader.SetErrorSrc (m_mainAddress);
+  rerrUnreachHeader.SetUnreachNode (errorHop);
+  rerrUnreachHeader.SetErrorDst (destination);
+  rerrUnreachHeader.SetSalvage (salvage);     // Set the value about whether to salvage a packet or not
+  uint8_t rerrLength = rerrUnreachHeader.GetLength ();
+
+  RouteCacheEntry toDst;
+  bool findRoute = m_routeCache->LookupRoute (destination, toDst);
+  // Queue the packet if there is no route pre-existing
+  if (!findRoute)
+    {
+      NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+                   << "s " << m_mainAddress << " there is no route for this packet, queue the packet");
+
+      dsrRoutingHeader.SetPayloadLength (rerrLength + 2);
+      dsrRoutingHeader.AddDsrOption (rerrUnreachHeader);
+      Ptr<Packet> newPacket = Create<Packet> ();
+      newPacket->AddHeader (dsrRoutingHeader);
+      Ptr<Packet> p = newPacket->Copy ();
+      SendBuffEntry newEntry (p, destination, m_sendBufferTimeout);
+      newEntry.SetErrHeader (true);        // Note it as an error packet
+      bool result = m_sendBuffer.Enqueue (newEntry);     // Enqueue the packet in send buffer
+      if (result)
+        {
+          NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+                       << "s Add packet PID: " << p->GetUid () << " to queue. Packet: " << *p);
+          NS_LOG_LOGIC ("Send RREQ to" << destination);
+          if ((m_addressReqTimer.find (destination) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (destination) == m_nonPropReqTimer.end ()))
+            {
+              NS_LOG_DEBUG ("When there is no existing route request for " << destination << ", initialize one");
+              /*
+               * Call the send request function, it will update the request table entry and ttl there
+               */
+              SendInitialRequest (m_mainAddress, destination, protocol);
+            }
+        }
+    }
+  else
+    {
+      std::vector<Ipv4Address> nodeList = toDst.GetVector ();
+      Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);
+      if (nextHop == "0.0.0.0")
+        {
+          return;
+        }
+      DsrOptionSRHeader sourceRoute;
+      sourceRoute.SetNodesAddress (nodeList);
+      if (m_routeCache->IsLinkCache ())
+        {
+          m_routeCache->UseExtends (nodeList);
+        }
+      sourceRoute.SetSegmentsLeft ((nodeList.size () - 2));
+      uint8_t srLength = sourceRoute.GetLength ();
+      uint8_t length = (srLength + rerrLength);
+
+      dsrRoutingHeader.SetNextHeader (protocol);
+      dsrRoutingHeader.SetPayloadLength (length + 4);
+      dsrRoutingHeader.AddDsrOption (rerrUnreachHeader);
+      dsrRoutingHeader.AddDsrOption (sourceRoute);
+      Ptr<Packet> newPacket = Create<Packet> ();
+      newPacket->AddHeader (dsrRoutingHeader);
+
+      SetRoute (nextHop, m_mainAddress);
+      Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+      m_ipv4Route->SetOutputDevice (dev);
+      m_downTarget (newPacket, m_mainAddress, nextHop, protocol, m_ipv4Route);
+    }
+}
+
+void
+DsrRouting::ForwardErrPacket (DsrOptionRerrUnreachHeader &rerr,
+                              DsrOptionSRHeader &sourceRoute,
+                              Ipv4Address nextHop,
+                              uint8_t protocol,
+                              Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION (this << rerr << sourceRoute << nextHop << (uint32_t)protocol << route);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrRoutingHeader.SetNextHeader (protocol);
+  dsrRoutingHeader.SetMessageType (1);
+  dsrRoutingHeader.SetSourceId (GetIDfromIP (rerr.GetErrorSrc ()));
+  dsrRoutingHeader.SetDestId (GetIDfromIP (rerr.GetErrorDst ()));
+
+  uint8_t length = (sourceRoute.GetLength () + rerr.GetLength ());
+  dsrRoutingHeader.SetPayloadLength (length + 4);
+  dsrRoutingHeader.AddDsrOption (rerr);
+  dsrRoutingHeader.AddDsrOption (sourceRoute);
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (dsrRoutingHeader);
+  Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+  route->SetOutputDevice (dev);
+  m_downTarget (packet, m_mainAddress, nextHop, GetProtocolNumber (), route);
+}
+
+void
+DsrRouting::Send (Ptr<Packet> packet,
+                  Ipv4Address source,
+                  Ipv4Address destination,
+                  uint8_t protocol,
+                  Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)protocol << route);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+
+  if (protocol == 1)
+    {
+      NS_LOG_INFO ("Drop packet. Not handling ICMP packet for now");
+    }
+  else
+    {
+      // Look up routes for the specific destination
+      RouteCacheEntry toDst;
+      bool findRoute = m_routeCache->LookupRoute (destination, toDst);
+      // Queue the packet if there is no route pre-existing
+      if (!findRoute)
+        {
+          NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+                       << "s " << m_mainAddress << " there is no route for this packet, queue the packet");
+
+          Ptr<Packet> p = packet->Copy ();
+          m_newPacketSize = packet->GetSize ();
+          SendBuffEntry newEntry (p, destination, m_sendBufferTimeout, protocol);     // Create a new entry for send buffer
+          bool result = m_sendBuffer.Enqueue (newEntry);     // Enqueue the packet in send buffer
+          if (result)
+            {
+              NS_LOG_INFO (Simulator::Now ().GetSeconds ()
+                           << "s Add packet PID: " << packet->GetUid () << " to queue. Packet: " << *packet);
+              NS_LOG_LOGIC ("Send RREQ to " << destination);
+              // Only when there is no existing route request timer when new route request is scheduled
+              if ((m_addressReqTimer.find (destination) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (destination) == m_nonPropReqTimer.end ()))
+                {
+                  NS_LOG_DEBUG ("When there is no existing route request for " << destination << ", initialize one");
+                  /*
+                   * Call the send request function, it will update the request table entry and ttl there
+                   */
+                  SendInitialRequest (source, destination, protocol);
+                }
+            }
+        }
+      else
+        {
+          Ptr<Packet> cleanP = packet->Copy ();
+          DsrRoutingHeader dsrRoutingHeader;
+          dsrRoutingHeader.SetNextHeader (protocol);
+          dsrRoutingHeader.SetMessageType (2);
+          dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+          dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
+
+          DsrOptionSRHeader sourceRoute;
+          std::vector<Ipv4Address> nodeList = toDst.GetVector ();       // Get the route from the route entry we found
+          Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);        // Get the next hop address for the route
+          if (nextHop == "0.0.0.0")
+            {
+              PacketNewRoute (cleanP, source, destination, protocol);
+              return;
+            }
+          uint8_t salvage = 0;
+          sourceRoute.SetNodesAddress (nodeList);       // Save the whole route in the source route header of the packet
+          if (m_routeCache->IsLinkCache ())
+            {
+              m_routeCache->UseExtends (nodeList);
+            }
+          sourceRoute.SetSegmentsLeft ((nodeList.size () - 2));       // The segmentsLeft field will indicate the hops to go
+          sourceRoute.SetSalvage (salvage);
+
+          DsrOptionAckReqHeader ackReq;
+          m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+          ackReq.SetAckId (m_ackId);
+
+          uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+
+          dsrRoutingHeader.SetPayloadLength (length + 4);
+          dsrRoutingHeader.AddDsrOption (sourceRoute);
+          dsrRoutingHeader.AddDsrOption (ackReq);
+          cleanP->AddHeader (dsrRoutingHeader);
+
+          Ptr<const Packet> mtP = cleanP->Copy ();
+          // Put the data packet in the maintenance queue for data packet retransmission
+          MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
+                                                  /*source=*/ source, /*destination=*/ destination, /*ackId=*/ m_ackId,
+                                                  /*SegsLeft=*/ nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
+          bool result = m_maintainBuffer.Enqueue (newEntry);       // Enqueue the packet the the maintenance buffer
+          if (result)
+            {
+              Ptr<Packet> newPacket = cleanP->Copy ();
+              /*
+               * Schedule the packet retransmission
+               */
+              PacketKey packetKey;
+              packetKey.m_ackId = newEntry.GetAckId ();
+              packetKey.m_ourAdd = newEntry.GetOurAdd ();
+              packetKey.m_nextHop = newEntry.GetNextHop ();
+              packetKey.m_source = newEntry.GetSrc ();
+              packetKey.m_destination = newEntry.GetDst ();
+              packetKey.m_segsLeft = newEntry.GetSegsLeft ();
+              PacketKey networkKey = packetKey;
+              networkKey.m_segsLeft = 0;
+              m_addressForwardCnt[networkKey] = 0;
+              SchedulePacketRetry (newEntry, packetKey, protocol);
+            }
+          // Try to send packet from *previously* queued entries from send buffer if any
+          SendPacket (sourceRoute, nextHop, protocol);
+        }
+    }
+}
+
+void
+DsrRouting::SendPacket (DsrOptionSRHeader const &sourceRoute,
+                        Ipv4Address nextHop,
+                        uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << (uint32_t)protocol);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+
+  // Reconstruct the route and Retransmit the data packet
+  std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
+  Ipv4Address destination = nodeList.back ();
+  Ipv4Address source = nodeList.front ();       // Get the source address
+
+  NS_LOG_INFO ("The nexthop address " << nextHop << " the source " << source << " the destination " << destination);
+
+  if (m_sendBuffer.Find (destination))
+    {
+      SendBuffEntry entry;
+      if (m_sendBuffer.Dequeue (destination, entry))
+        {
+          Ptr<Packet> packet = entry.GetPacket ()->Copy ();
+          NS_LOG_DEBUG ("The queued packet size " << packet->GetSize ());
+
+          DsrRoutingHeader dsrRoutingHeader;
+          Ptr<Packet> copyP = packet->Copy ();
+          uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
+          copyP->RemoveAtStart (offset);       // Here the processed size is 8 bytes, which is the fixed sized extension header
+          /*
+           * Peek data to get the option type as well as length and segmentsLeft field
+           */
+          uint32_t size = copyP->GetSize ();
+          uint8_t *data = new uint8_t[size];
+          copyP->CopyData (data, size);
+
+          uint8_t optionType = 0;
+          optionType = *(data);
+          if (optionType == 3)
+            {
+              Ptr<dsr::DsrOptions> dsrOption;
+              DsrOptionHeader dsrOptionHeader;
+
+              uint8_t errorType = *(data + 2);
+              if (errorType == 1)
+                {
+                  DsrOptionRerrUnreachHeader rerr;
+                  copyP->RemoveHeader (rerr);
+                  NS_ASSERT (copyP->GetSize () == 0);
+                  uint8_t length = (sourceRoute.GetLength () + rerr.GetLength ());
+
+                  DsrOptionRerrUnreachHeader newUnreach;
+                  newUnreach.SetErrorType (1);
+                  newUnreach.SetErrorSrc (rerr.GetErrorSrc ());
+                  newUnreach.SetUnreachNode (rerr.GetUnreachNode ());
+                  newUnreach.SetErrorDst (rerr.GetErrorDst ());
+                  newUnreach.SetSalvage (rerr.GetSalvage ());       // Set the value about whether to salvage a packet or not
+
+                  std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
+                  DsrRoutingHeader newRoutingHeader;
+                  newRoutingHeader.SetNextHeader (protocol);
+                  newRoutingHeader.SetMessageType (1);
+                  newRoutingHeader.SetSourceId (GetIDfromIP (rerr.GetErrorSrc ()));
+                  newRoutingHeader.SetDestId (GetIDfromIP (rerr.GetErrorDst ()));
+                  newRoutingHeader.SetPayloadLength (length + 4);
+                  newRoutingHeader.AddDsrOption (newUnreach);
+                  newRoutingHeader.AddDsrOption (sourceRoute);
+                  if (m_routeCache->IsLinkCache ())
+                    {
+                      m_routeCache->UseExtends (nodeList);
+                    }
+                  SetRoute (nextHop, m_mainAddress);
+                  Ptr<Packet> newPacket = Create<Packet> ();
+                  newPacket->AddHeader (newRoutingHeader);       // Add the extension header with rerr and sourceRoute attached to it
+                  Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+                  m_ipv4Route->SetOutputDevice (dev);
+                  m_downTarget (newPacket, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route);
+                }
+            }
+          else
+            {
+              Ptr<Packet> p = packet->Copy ();      // get a copy of the packet
+              // Set the source route option
+              dsrRoutingHeader.SetNextHeader (protocol);
+              dsrRoutingHeader.SetMessageType (2);
+              dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+              dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
+
+              DsrOptionAckReqHeader ackReq;
+              m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+              ackReq.SetAckId (m_ackId);
+
+              uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+              dsrRoutingHeader.SetPayloadLength (length + 4);
+              dsrRoutingHeader.AddDsrOption (sourceRoute);
+              dsrRoutingHeader.AddDsrOption (ackReq);
+
+              p->AddHeader (dsrRoutingHeader);
+              Ptr<const Packet> mtP = p->Copy ();
+              // Put the data packet in the maintenance queue for data packet retransmission
+              MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
+                                                      /*source=*/ source, /*destination=*/ destination, /*ackId=*/ m_ackId,
+                                                      /*SegsLeft=*/ nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
+              bool result = m_maintainBuffer.Enqueue (newEntry);       // Enqueue the packet the the maintenance buffer
+
+              if (result)
+                {
+                  // Send out data packet
+                  NS_LOG_DEBUG ("Send out packet with ack id " << m_ackId);
+                  // Schedule the packet retry timer
+                  PacketKey packetKey;
+                  packetKey.m_ackId = newEntry.GetAckId ();
+                  packetKey.m_ourAdd = newEntry.GetOurAdd ();
+                  packetKey.m_nextHop = newEntry.GetNextHop ();
+                  packetKey.m_source = newEntry.GetSrc ();
+                  packetKey.m_destination = newEntry.GetDst ();
+                  packetKey.m_segsLeft = newEntry.GetSegsLeft ();
+                  PacketKey networkKey = packetKey;
+                  networkKey.m_segsLeft = 0;
+                  m_addressForwardCnt[networkKey] = 0;
+                  SchedulePacketRetry (newEntry, packetKey, protocol);
+                }
+            }
+
+          if (m_sendBuffer.GetSize () != 0 && m_sendBuffer.Find (destination))
+            {
+              NS_LOG_DEBUG ("Schedule sending the next packet in send buffer");
+              Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
+                                   &DsrRouting::SendPacket,this,sourceRoute,nextHop,protocol);
+            }
+        }
+      else
+        {
+          NS_LOG_DEBUG ("All queued packets are out-dated for the destination");
+        }
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Packet not found in send buffer");
+    }
+}
+
+bool
+DsrRouting::FindSamePackets (Ptr<Packet> packet, Ipv4Header const& ipv4Header, Ipv4Address source, Ipv4Address destination,
+                             uint8_t segsLeft)
+{
+  NS_LOG_FUNCTION (this << packet << ipv4Header << source << destination << (uint32_t)segsLeft);
+  /*
+   * Get the source and destination address from ipv4 header
+   */
+  Ipv4Address ourAdd = ipv4Header.GetSource ();
+  Ipv4Address nextHop = ipv4Header.GetDestination ();
+
+  Ptr<Packet> p = packet->Copy ();
+  MaintainBuffEntry newEntry (/*Packet=*/ p, /*Ipv4Address=*/ ourAdd, /*nextHop=*/ nextHop,
+                                          /*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
+                                          /*SegsLeft=*/ segsLeft, /*expire time=*/ m_maxMaintainTime);
+  // Temporarily disable passive acknowledgment
+//  CancelPassivePacketTimer (newEntry);
+  return true;
+}
+
+void
+DsrRouting::CallCancelPacketTimer (uint16_t ackId, Ipv4Header const& ipv4Header, Ipv4Address realSrc, Ipv4Address realDst)
+{
+  NS_LOG_FUNCTION (this << (uint32_t)ackId << ipv4Header << realSrc << realDst);
+  Ipv4Address sender = ipv4Header.GetDestination ();
+  Ipv4Address receiver = ipv4Header.GetSource ();
+  /*
+   * Create a packet to fill maintenance buffer, not used to compare
+   * The reason is ack header doesn't have the original packet copy
+   */
+  Ptr<Packet> mainP = Create<Packet> ();
+  MaintainBuffEntry newEntry (/*Packet=*/ mainP, /*ourAddress=*/ sender, /*nextHop=*/ receiver,
+                                          /*source=*/ realSrc, /*destination=*/ realDst, /*ackId=*/ ackId,
+                                          /*SegsLeft=*/ 0, /*expire time=*/ Simulator::Now ());
+  CancelNetworkPacketTimer (newEntry);
+}
+
+void
+DsrRouting::CancelNetworkPacketTimer (MaintainBuffEntry & mb)
+{
+  NS_LOG_FUNCTION (this);
+  PacketKey packetKey;
+  packetKey.m_ackId = mb.GetAckId ();
+  packetKey.m_ourAdd = mb.GetOurAdd ();
+  packetKey.m_nextHop = mb.GetNextHop ();
+  packetKey.m_source = mb.GetSrc ();
+  packetKey.m_destination = mb.GetDst ();
+  packetKey.m_segsLeft = 0;
+  /*
+   * Here we have found the entry for send retries, so we get the value and increase it by one
+   */
+  m_addressForwardCnt[packetKey] = 0;
+  m_addressForwardCnt.erase (packetKey);
+
+  NS_LOG_INFO ("ackId " << mb.GetAckId () << " ourAdd " << mb.GetOurAdd () << " nextHop " << mb.GetNextHop ()
+                        << " source " << mb.GetSrc () << " destination " << mb.GetDst ()
+                        << " segsLeft " << (uint32_t)mb.GetSegsLeft ()
+               );
+  // Find the network acknowledgment timer
+  std::map<PacketKey, Timer>::const_iterator i =
+    m_addressForwardTimer.find (packetKey);
+  if (i == m_addressForwardTimer.end ())
+    {
+      NS_LOG_DEBUG ("did not find the packet timer");
+    }
+  else
+    {
+      NS_LOG_DEBUG ("did find the packet timer");
+      /*
+       * Schedule the packet retry
+       * Push back the nextHop, source, destination address
+       */
+      m_addressForwardTimer[packetKey].Cancel ();
+      m_addressForwardTimer[packetKey].Remove ();
+      if (m_addressForwardTimer[packetKey].IsRunning ())
+        {
+          NS_LOG_DEBUG ("Timer not canceled");
+        }
+      m_addressForwardTimer.erase (packetKey);
+    }
+  // Erase the maintenance entry
+  if (m_maintainBuffer.AllEqual (mb))
+    {
+      NS_LOG_DEBUG ("Remove same maintenance buffer entry based on network acknowledgment");
+    }
+}
+
+void
+DsrRouting::CancelPassivePacketTimer (MaintainBuffEntry & mb)
+{
+  NS_LOG_FUNCTION (this);
+  PacketKey passiveKey;
+  passiveKey.m_ackId = 0;
+  passiveKey.m_ourAdd = mb.GetOurAdd ();
+  passiveKey.m_nextHop = mb.GetNextHop ();
+  passiveKey.m_source = mb.GetSrc ();
+  passiveKey.m_destination = mb.GetDst ();
+  passiveKey.m_segsLeft = mb.GetSegsLeft ();
+
+  m_addressForwardCnt[passiveKey] = 0;
+  m_addressForwardCnt.erase (passiveKey);
+
+  // Find the passive acknowledgment timer
+  std::map<PacketKey, Timer>::const_iterator j =
+    m_passiveAckTimer.find (passiveKey);
+  if (j == m_passiveAckTimer.end ())
+    {
+      NS_LOG_DEBUG ("did not find the passive timer");
+    }
+  else
+    {
+      NS_LOG_DEBUG ("find the passive timer");
+      /*
+       * Cancel passive acknowledgment timer
+       */
+      m_passiveAckTimer[passiveKey].Cancel ();
+      m_passiveAckTimer[passiveKey].Remove ();
+      if (m_passiveAckTimer[passiveKey].IsRunning ())
+        {
+          NS_LOG_DEBUG ("Timer not canceled");
+        }
+      m_passiveAckTimer.erase (passiveKey);
+    }
+  // Erase the maintenance entry
+  if (m_maintainBuffer.PromiscEqual (mb))
+    {
+      NS_LOG_DEBUG ("Remove same maintenance buffer entry based on passive acknowledgment");
+    }
+}
+
+void
+DsrRouting::CancelPacketTimerNextHop (Ipv4Address nextHop, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << nextHop << (uint32_t)protocol);
+  MaintainBuffEntry entry;
+  if (m_maintainBuffer.Dequeue (nextHop, entry))
+    {
+      Ptr<const Packet> packet = entry.GetPacket ()->Copy ();
+      Ipv4Address source = entry.GetSrc ();
+      Ipv4Address destination = entry.GetDst ();
+      /*
+       * Cancel the packet timer and then salvage the data packet
+       */
+      CancelNetworkPacketTimer (entry);
+      SalvagePacket (packet, source, destination, protocol);
+
+      if (m_maintainBuffer.GetSize () && m_maintainBuffer.Find (nextHop))
+        {
+          NS_LOG_DEBUG ("Cancel the packet timer for next maintenance entry");
+
+          Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
+                               &DsrRouting::CancelPacketTimerNextHop,this,nextHop,protocol);
+        }
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Maintenance buffer entry not found");
+    }
+}
+
+void
+DsrRouting::SalvagePacket (Ptr<const Packet> packet, Ipv4Address source, Ipv4Address dst, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << packet << source << dst << (uint32_t)protocol);
+  /*
+   * Look in the route cache for other routes for this destination
+   */
+  RouteCacheEntry toDst;
+  // Create two copies of packet
+  Ptr<Packet> p = packet->Copy ();
+  Ptr<Packet> newPacket = packet->Copy ();
+  // Remove the routing header in a whole to get a clean packet
+  DsrRoutingHeader dsrRoutingHeader;
+  p->RemoveHeader (dsrRoutingHeader);
+  // Remove offset of dsr routing header
+  uint8_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
+  newPacket->RemoveAtStart (offset);
+
+  // Get the number of routers' address field
+  uint8_t buf[2];
+  newPacket->CopyData (buf, sizeof(buf));
+  uint8_t numberAddress = (buf[1] - 2) / 4;
+
+  DsrOptionSRHeader sourceRoute;
+  sourceRoute.SetNumberAddress (numberAddress);
+  newPacket->RemoveHeader (sourceRoute);
+  uint8_t salvage = sourceRoute.GetSalvage ();
+
+  NS_LOG_DEBUG ("The salvage value get from remove headers " << (uint32_t)salvage);
+
+  bool findRoute = m_routeCache->LookupRoute (dst, toDst);
+  if (findRoute && (salvage < m_maxSalvageCount))
+    {
+      NS_LOG_DEBUG ("We have found a route for the packet");
+      DsrRoutingHeader newDsrRoutingHeader;
+      newDsrRoutingHeader.SetNextHeader (protocol);
+      newDsrRoutingHeader.SetMessageType (2);
+      newDsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+      newDsrRoutingHeader.SetDestId (GetIDfromIP (dst));
+
+      std::vector<Ipv4Address> nodeList = toDst.GetVector ();     // Get the route from the route entry we found
+      Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);      // Get the next hop address for the route
+      if (nextHop == "0.0.0.0")
+        {
+          PacketNewRoute (p, source, dst, protocol);
+          return;
+        }
+      // Increase the salvage count by 1
+      salvage++;
+      DsrOptionSRHeader sourceRoute;
+      sourceRoute.SetSalvage (salvage);
+      sourceRoute.SetNodesAddress (nodeList);     // Save the whole route in the source route header of the packet
+      if (m_routeCache->IsLinkCache ())
+        {
+          m_routeCache->UseExtends (nodeList);
+        }
+      sourceRoute.SetSegmentsLeft ((nodeList.size () - 2));     // The segmentsLeft field will indicate the hops to go
+      DsrOptionAckReqHeader ackReq;
+      m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+      ackReq.SetAckId (m_ackId);
+
+      uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+      NS_LOG_INFO ("length of source route header " << (uint32_t)(sourceRoute.GetLength ())
+                                                    << " length of ack request header " << (uint32_t)(ackReq.GetLength ()));
+      newDsrRoutingHeader.SetPayloadLength (length + 4);
+      newDsrRoutingHeader.AddDsrOption (sourceRoute);
+      newDsrRoutingHeader.AddDsrOption (ackReq);
+      p->AddHeader (newDsrRoutingHeader);
+
+      SetRoute (nextHop, m_mainAddress);
+      Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+      m_ipv4Route->SetOutputDevice (dev);
+      // Send out the data packet
+      m_downTarget (p, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route);
+      /*
+       * Mark the next hop address in blacklist
+       */
+//      NS_LOG_DEBUG ("Save the next hop node in blacklist");
+//      m_rreqTable->MarkLinkAsUnidirectional (nextHop, m_blacklistTimeout);
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Will not salvage this packet, silently drop");
+    }
+}
+
+void
+DsrRouting::SchedulePacketRetry (MaintainBuffEntry & mb,
+                                 PacketKey const & packetKey,
+                                 uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << (uint32_t)protocol);
+  Ipv4Address nextHop = mb.GetNextHop ();
+  Ipv4Address source = mb.GetSrc ();
+  Ipv4Address dst = mb.GetDst ();
+  bool isPassive = mb.GetPassive ();
+  // Temporarily disable passive acknowledgment option
+  isPassive = false;
+  NS_LOG_DEBUG ("Sending passive packet retry or network one " << isPassive);
+
+  // Make two copies of the packet key
+  PacketKey networkKey = packetKey;
+  PacketKey passiveKey = packetKey;
+
+  if (isPassive && nextHop != dst)
+    {
+      // There is no ack id for passive key, so 0 it
+      passiveKey.m_ackId = 0;
+      if (m_addressForwardTimer.find (passiveKey) == m_addressForwardTimer.end ())
+        {
+          Timer timer (Timer::CANCEL_ON_DESTROY);
+          m_addressForwardTimer[passiveKey] = timer;
+        }
+      m_sendRetries = 0; // initialize the send retry times to 0
+      m_sendRetries++;
+      // decrease the passive acknowledgment count
+      m_tryPassiveAcks = (m_tryPassiveAcks - 1);
+      if (!m_tryPassiveAcks)
+        {
+          NS_LOG_DEBUG ("Passive acknowledgment is over");
+          isPassive = false;
+        }
+      NS_LOG_DEBUG ("The passive acknowledgment option for data packet");
+      m_addressForwardTimer[passiveKey].SetFunction (&DsrRouting::PacketScheduleTimerExpire, this);
+      m_addressForwardTimer[passiveKey].Remove ();
+      m_addressForwardTimer[passiveKey].SetArguments (mb, passiveKey, protocol, isPassive);
+      // forward count
+      m_addressForwardCnt[passiveKey] = m_sendRetries;
+      NS_LOG_DEBUG ("The packet retries time is " << m_sendRetries);
+      m_addressForwardTimer[passiveKey].Schedule (m_passiveAckTimeout);
+      return;
+    }
+  else
+    {
+      // There is no segments left value for network key, so 0 it
+      networkKey.m_segsLeft = 0;
+
+      if (m_addressForwardTimer.find (networkKey) == m_addressForwardTimer.end ())
+        {
+          Timer timer (Timer::CANCEL_ON_DESTROY);
+          m_addressForwardTimer[networkKey] = timer;
+        }
+      /*
+       * Here we have found the entry for send retries, so we get the value and increase it by one
+       */
+      m_sendRetries = m_addressForwardCnt[networkKey];
+      NS_LOG_DEBUG ("The packet retry we have done " << m_sendRetries);
+      /*
+       *  If a data packet has been attempted SendRetries times at the maximum TTL without
+       *  receiving any ACK, all data packets destined for the corresponding destination SHOULD be
+       *  dropped from the send buffer
+       *
+       *  The maxMaintRexmt also needs to decrease one for the passive ack packet
+       */
+      Ptr<Packet> p = mb.GetPacket ()->Copy ();
+      Ptr<Packet> dsrP = p->Copy ();
+      Ptr<Packet> salP = p->Copy ();
+      Ptr<Packet> retransP = p->Copy ();
+      // The packet retries time has exceed the max maintenance retransmission times
+      if (m_sendRetries > m_maxMaintRexmt)
+        {
+          NS_LOG_LOGIC ("Packet transmissions to " << nextHop << " has been attempted SendRetries times for " << networkKey.m_ackId);
+          DsrRoutingHeader dsrRoutingHeader;
+          dsrP->RemoveHeader (dsrRoutingHeader);          // Remove the dsr header in whole
+          uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
+          p->RemoveAtStart (offset);
+
+          // Get the number of routers' address field
+          uint8_t buf[2];
+          p->CopyData (buf, sizeof(buf));
+          uint8_t numberAddress = (buf[1] - 2) / 4;
+          NS_LOG_DEBUG ("The number of addresses " << (uint32_t)numberAddress);
+          DsrOptionSRHeader sourceRoute;
+          sourceRoute.SetNumberAddress (numberAddress);
+          p->RemoveHeader (sourceRoute);
+          std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
+          uint8_t salvage = sourceRoute.GetSalvage ();
+          Ipv4Address address1 = nodeList.front ();
+          NS_LOG_DEBUG ("address1 " << address1);
+
+          CutRoute (m_mainAddress, nodeList);
+          NS_LOG_DEBUG ("The route vector after cut and the route source " << nodeList.front ());
+//          PrintVector (nodeList);
+          // Delete the route cache entry
+          RouteCacheEntry toDst;
+          // Cancel the packet timer for maintenance buffer entry
+          CancelNetworkPacketTimer (mb);
+          /*
+           * Mark the next hop address in blacklist
+           */
+//          NS_LOG_DEBUG ("Save the next hop node in blacklist");
+//          m_rreqTable->MarkLinkAsUnidirectional (nextHop, m_blacklistTimeout);
+          // Delete all the routes including the links
+          m_routeCache->DeleteAllRoutesIncludeLink (m_mainAddress, nextHop, m_mainAddress);
+          // After deleting the broken link from all routes, need to salvage the packet right after dropping it
+          SalvagePacket (salP, source, dst, protocol);
+          /*
+           * If the salvage is not 0, use the first address in the route as the error dst in error header
+           * otherwise use the source of packet as the error destination
+           */
+          if (salvage)
+            {
+              if (address1 == m_mainAddress)
+                {
+                  DsrOptionRerrUnreachHeader rerr;
+                  rerr.SetErrorType (1);
+                  rerr.SetErrorSrc (address1);
+                  rerr.SetUnreachNode (nextHop);
+                  rerr.SetErrorDst (address1);
+                  rerr.SetSalvage (salvage);       // Set the value about whether to salvage a packet or not
+                  SendErrorRequest (rerr, protocol);
+                }
+              else
+                {
+                  SendUnreachError (nextHop, address1, salvage, protocol);
+                }
+            }
+          else
+            {
+              if (source == m_mainAddress)
+                {
+                  DsrOptionRerrUnreachHeader rerr;
+                  rerr.SetErrorType (1);
+                  rerr.SetErrorSrc (source);
+                  rerr.SetUnreachNode (nextHop);
+                  rerr.SetErrorDst (source);
+                  rerr.SetSalvage (salvage);     // Set the value about whether to salvage a packet or not
+                  SendErrorRequest (rerr, protocol);
+                }
+              else
+                {
+                  SendUnreachError (nextHop, source, salvage, protocol);
+                }
+            }
+          CancelPacketTimerNextHop (nextHop, protocol);
+        }
+      else
+        {
+          m_sendRetries++;
+          // Send out the retransmission packet
+          m_ipv4Route = SetRoute (nextHop, m_mainAddress);
+          Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+          m_ipv4Route->SetOutputDevice (dev);
+          m_downTarget (retransP, source, nextHop, GetProtocolNumber (), m_ipv4Route);
+          // After m_tryPassiveAcks, schedule the packet retransmission using network acknowledgment option
+          m_addressForwardTimer[networkKey].SetFunction (&DsrRouting::PacketScheduleTimerExpire, this);
+          m_addressForwardTimer[networkKey].Remove ();
+          m_addressForwardTimer[networkKey].SetArguments (mb, networkKey, protocol, false);
+          // forward count
+          m_addressForwardCnt[networkKey] = m_sendRetries;
+          NS_LOG_DEBUG ("The packet retries time for " << mb.GetAckId () << " is " << m_sendRetries);
+          // Back-off mechanism
+          m_addressForwardTimer[networkKey].Schedule (Time (2 * m_sendRetries *  m_nodeTraversalTime));
+        }
+    }
+  return;
+}
+
+void
+DsrRouting::AddAckReqHeader (Ptr<Packet> packet, DsrOptionSRHeader const &sourceRoute, Ipv4Address nextHop)
+{
+  NS_LOG_FUNCTION (this << packet << nextHop);
+  // This packet is used to peek option type
+  Ptr<Packet> cleanP = packet->Copy ();
+
+  DsrOptionAckReqHeader ackReq;
+  m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+  ackReq.SetAckId (m_ackId);
+
+  uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrRoutingHeader.SetPayloadLength (length + 4);
+  dsrRoutingHeader.AddDsrOption (sourceRoute);
+  dsrRoutingHeader.AddDsrOption (ackReq);
+  cleanP->AddHeader (dsrRoutingHeader);
+}
+
+void
+DsrRouting::PacketScheduleTimerExpire  (MaintainBuffEntry & mb,
+                                        PacketKey const & pk,
+                                        uint8_t protocol,
+                                        bool isPassive)
+{
+  NS_LOG_FUNCTION (this << (uint32_t)protocol << isPassive);
+  Ipv4Address nextHop = mb.GetNextHop ();
+  Ipv4Address source = mb.GetSrc ();
+  Ipv4Address dst = mb.GetDst ();
+  Ptr<const Packet> packet = mb.GetPacket ();
+  SetRoute (nextHop, m_mainAddress);
+  Ptr<Packet> p = packet->Copy ();
+  if (isPassive)
+    {
+      // Cancel passive ack timer
+      m_passiveAckTimer[pk].Cancel ();
+      m_passiveAckTimer[pk].Remove ();
+      if (m_passiveAckTimer[pk].IsRunning ())
+        {
+          NS_LOG_DEBUG ("Timer not canceled");
+        }
+      m_passiveAckTimer.erase (pk);
+      isPassive = false;
+      mb.SetPassive (false);
+      SchedulePacketRetry (mb, pk, protocol);
+    }
+  else
+    {
+      mb.SetPassive (false);
+      SchedulePacketRetry (mb, pk, protocol);
+    }
+  return;
+}
+
+void
+DsrRouting::ForwardPacket (Ptr<const Packet> packet,
+                           DsrOptionSRHeader &sourceRoute,
+                           Ipv4Header const& ipv4Header,
+                           Ipv4Address source,
+                           Ipv4Address nextHop,
+                           Ipv4Address targetAddress,
+                           uint8_t protocol,
+                           Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION (this << packet << sourceRoute << source << nextHop << targetAddress << (uint32_t)protocol << route);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrRoutingHeader.SetNextHeader (protocol);
+  dsrRoutingHeader.SetMessageType (2);
+  dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+  dsrRoutingHeader.SetDestId (GetIDfromIP (targetAddress));
+
+  // We get the salvage value in sourceRoute header and set it to route error header if triggered error
+  Ptr<Packet> p = packet->Copy ();
+  DsrOptionAckReqHeader ackReq;
+  m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+  ackReq.SetAckId (m_ackId);
+
+  uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+  dsrRoutingHeader.SetPayloadLength (length + 4);
+  dsrRoutingHeader.AddDsrOption (sourceRoute);
+  dsrRoutingHeader.AddDsrOption (ackReq);
+  p->AddHeader (dsrRoutingHeader);
+  Ptr<const Packet> mtP = p->Copy ();
+
+  MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
+                                          /*source=*/ source, /*destination=*/ targetAddress,
+                                          /*ackId=*/ m_ackId, /*SegsLeft=*/ sourceRoute.GetSegmentsLeft (), /*expire time=*/ m_maxMaintainTime);
+  bool result = m_maintainBuffer.Enqueue (newEntry);
+
+  if (result)
+    {
+      Ptr<Packet> newPacket = p->Copy ();
+      PacketKey packetKey;
+      packetKey.m_ackId = newEntry.GetAckId ();
+      packetKey.m_ourAdd = newEntry.GetOurAdd ();
+      packetKey.m_nextHop = newEntry.GetNextHop ();
+      packetKey.m_source = newEntry.GetSrc ();
+      packetKey.m_destination = newEntry.GetDst ();
+      packetKey.m_segsLeft = newEntry.GetSegsLeft ();
+      PacketKey networkKey = packetKey;
+      networkKey.m_segsLeft = 0;
+      m_addressForwardCnt[networkKey] = 0;
+      SchedulePacketRetry (newEntry, packetKey, protocol);
+    }
+}
+
+void
+DsrRouting::SendInitialRequest (Ipv4Address source,
+                                Ipv4Address destination,
+                                uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << source << destination << (uint32_t)protocol);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+  Ptr<Packet> packet = Create<Packet> ();
+  // Create an empty Ipv4 route ptr
+  Ptr<Ipv4Route> route;
+  /*
+   * Construct the route request option header
+   */
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrRoutingHeader.SetNextHeader (protocol);
+  dsrRoutingHeader.SetMessageType (1);
+  dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+  dsrRoutingHeader.SetDestId (255);
+
+  DsrOptionRreqHeader rreqHeader;                                // has an alignment of 4n+0
+  rreqHeader.AddNodeAddress (m_mainAddress);                     // Add our own address in the header
+  rreqHeader.SetTarget (destination);
+  m_requestId = m_rreqTable->CheckUniqueRreqId (destination);       // Check the Id cache for duplicate ones
+  rreqHeader.SetId (m_requestId);
+  // Increment the route request count, if entry not found, the function will create a new one
+  m_rreqTable->FindAndUpdate (destination);
+
+  dsrRoutingHeader.AddDsrOption (rreqHeader);         // Add the rreqHeader to the dsr extension header
+  uint8_t length = rreqHeader.GetLength ();
+  dsrRoutingHeader.SetPayloadLength (length + 2);
+  packet->AddHeader (dsrRoutingHeader);
+
+  // This function will increase the request count if found the entry, will create the entry if not found
+  m_rreqTable->FindAndUpdate (destination);
+  // Schedule the route requests retry with non-propagation set true
+  bool nonProp = true;
+  ScheduleRreqRetry (packet, source, destination, nonProp, protocol);
+}
+
+void
+DsrRouting::SendErrorRequest (DsrOptionRerrUnreachHeader &rerr, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << (uint32_t)protocol);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+  Ptr<Packet> packet = Create<Packet> ();
+  Ipv4Address destination = rerr.GetErrorSrc ();
+  Ipv4Address unreachAddress = rerr.GetUnreachNode ();
+  // Create an empty route ptr
+  Ptr<Ipv4Route> route = 0;
+  /*
+   * Construct the route request option header
+   */
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrRoutingHeader.SetNextHeader (protocol);
+  dsrRoutingHeader.SetMessageType (1);
+  dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
+  dsrRoutingHeader.SetDestId (255);
+
+  if (m_mainAddress != destination)
+    {
+      /*
+       * Send error request to the error source
+       */
+      NS_LOG_DEBUG ("Send error packet to the error source");
+      Ptr<Packet> dstP = Create<Packet> ();
+      DsrOptionRreqHeader rreqHeader;                                // has an alignment of 4n+0
+      rreqHeader.AddNodeAddress (m_mainAddress);                     // Add our own address in the header
+      rreqHeader.SetTarget (destination);
+      m_requestId = m_rreqTable->CheckUniqueRreqId (destination);       // Check the Id cache for duplicate ones
+      rreqHeader.SetId (m_requestId);
+      // This function will increase the request count if found the entry, will create the entry if not found
+      m_rreqTable->FindAndUpdate (destination);
+
+      dsrRoutingHeader.AddDsrOption (rreqHeader);         // Add the rreqHeader to the dsr extension header
+      dsrRoutingHeader.AddDsrOption (rerr);
+      uint8_t length = rreqHeader.GetLength () + rerr.GetLength ();
+      dsrRoutingHeader.SetPayloadLength (length + 4);
+      dstP->AddHeader (dsrRoutingHeader);
+      // Schedule the route requests retry, propagate the route request message as it contains error
+      bool nonProp = false;
+      if ((m_addressReqTimer.find (destination) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (destination) == m_nonPropReqTimer.end ()))
+        {
+          NS_LOG_DEBUG ("Only when there is no existing route request time when this one is triggered");
+          ScheduleRreqRetry (dstP, m_mainAddress, destination, nonProp, protocol);
+        }
+    }
+  else
+    {
+      /*
+       * Send error request to the unreachable node
+       */
+      DsrOptionRreqHeader rreqHeader;                                // has an alignment of 4n+0
+      rreqHeader.AddNodeAddress (m_mainAddress);                     // Add our own address in the header
+      rreqHeader.SetTarget (unreachAddress);
+      m_requestId = m_rreqTable->CheckUniqueRreqId (unreachAddress);       // Check the Id cache for duplicate ones
+      rreqHeader.SetId (m_requestId);
+      // This function will increase the request count if found the entry, will create the entry if not found
+      m_rreqTable->FindAndUpdate (unreachAddress);
+
+      dsrRoutingHeader.AddDsrOption (rreqHeader);         // Add the rreqHeader to the dsr extension header
+      dsrRoutingHeader.AddDsrOption (rerr);
+      uint8_t length = rreqHeader.GetLength () + rerr.GetLength ();
+      dsrRoutingHeader.SetPayloadLength (length + 4);
+      packet->AddHeader (dsrRoutingHeader);
+      // Schedule the route requests retry, propagate the route request message as it contains error
+      bool nonProp = false;
+      if ((m_addressReqTimer.find (unreachAddress) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (unreachAddress) == m_nonPropReqTimer.end ()))
+        {
+          NS_LOG_DEBUG ("Only when there is no existing route request time when this one is triggered");
+          ScheduleRreqRetry (packet, m_mainAddress, unreachAddress, nonProp, protocol);
+        }
+    }
+}
+
+void
+DsrRouting::CancelRreqTimer (Ipv4Address dst)
+{
+  NS_LOG_FUNCTION (this << dst);
+  // Cancel the non propagation request timer if found
+  if (m_nonPropReqTimer.find (dst) == m_nonPropReqTimer.end ())
+    {
+      NS_LOG_DEBUG ("Did not find the non-propagation timer");
+    }
+  else
+    {
+      NS_LOG_DEBUG ("did find the non-propagation timer");
+    }
+  m_nonPropReqTimer[dst].Cancel ();
+  m_nonPropReqTimer[dst].Remove ();
+
+  if (m_nonPropReqTimer[dst].IsRunning ())
+    {
+      NS_LOG_DEBUG ("Timer not canceled");
+    }
+  m_nonPropReqTimer.erase (dst);
+
+  // Cancel the address request timer if found
+  if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ())
+    {
+      NS_LOG_DEBUG ("Did not find the propagation timer");
+    }
+  else
+    {
+      NS_LOG_DEBUG ("did find the propagation timer");
+    }
+  m_addressReqTimer[dst].Cancel ();
+  m_addressReqTimer[dst].Remove ();
+  if (m_addressReqTimer[dst].IsRunning ())
+    {
+      NS_LOG_DEBUG ("Timer not canceled");
+    }
+  m_addressReqTimer.erase (dst);
+
+  // remove the route request entry from route request table
+  m_rreqTable->RemoveRreqEntry (dst);
+}
+
+void
+DsrRouting::ScheduleRreqRetry (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dst, bool nonProp, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << packet << source << dst << nonProp << (uint32_t)protocol);
+  if (nonProp)
+    {
+      nonProp = false;
+      if (m_nonPropReqTimer.find (dst) == m_nonPropReqTimer.end ())
+        {
+          Timer timer (Timer::CANCEL_ON_DESTROY);
+          m_nonPropReqTimer[dst] = timer;
+        }
+      /*
+       * Add the socket ip ttl tag to the packet to limit the scope of route requests
+       */
+      SocketIpTtlTag tag;
+      tag.SetTtl (0);
+      Ptr<Packet> nonPropPacket = packet->Copy ();
+      nonPropPacket->AddPacketTag (tag);
+      SendRequest (nonPropPacket, source);
+      NS_LOG_DEBUG ("Check the route request entry3 " << source << " " << dst);
+      m_nonPropReqTimer[dst].SetFunction (&DsrRouting::ScheduleRreqRetry, this);
+      m_nonPropReqTimer[dst].Remove ();
+      m_nonPropReqTimer[dst].SetArguments (packet, source, dst, nonProp, protocol);
+      m_nonPropReqTimer[dst].Schedule (m_nonpropRequestTimeout);
+    }
+  else
+    {
+      // Cancel the non propagation request timer if found
+      m_nonPropReqTimer[dst].Cancel ();
+      m_nonPropReqTimer[dst].Remove ();
+      if (m_nonPropReqTimer[dst].IsRunning ())
+        {
+          NS_LOG_DEBUG ("Timer not canceled");
+        }
+      m_nonPropReqTimer.erase (dst);
+      /*
+       * Add the socket ip ttl tag to the packet to limit the scope of route requests
+       */
+      SocketIpTtlTag tag;
+      tag.SetTtl (m_discoveryHopLimit);
+      packet->AddPacketTag (tag);
+      if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ())
+        {
+          Timer timer (Timer::CANCEL_ON_DESTROY);
+          m_addressReqTimer[dst] = timer;
+        }
+      m_addressReqTimer[dst].SetFunction (&DsrRouting::RouteRequestTimerExpire, this);
+      m_addressReqTimer[dst].Remove ();
+      m_addressReqTimer[dst].SetArguments (packet, source, dst, protocol);
+      // Increase the request count
+      m_rreqTable->FindAndUpdate (dst);
+      // back off mechanism for sending route requests
+      Time rreqDelay = Time (pow (m_rreqTable->GetRreqCnt (dst), 2) * m_requestPeriod);
+      NS_LOG_DEBUG ("The request count for the destination " << dst << " " << m_rreqTable->GetRreqCnt (dst) << " with time value " << rreqDelay);
+      if (rreqDelay > m_maxRequestPeriod)
+        {
+          // use the max request period
+          NS_LOG_DEBUG ("The max request delay time " << m_maxRequestPeriod.GetSeconds ());
+          m_addressReqTimer[dst].Schedule (m_maxRequestPeriod);
+        }
+      else
+        {
+          NS_LOG_DEBUG ("The request delay time " << rreqDelay.GetSeconds ());
+          m_addressReqTimer[dst].Schedule (rreqDelay);
+        }
+    }
+}
+
+void
+DsrRouting::RouteRequestTimerExpire (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dst, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << packet << source << dst << (uint32_t)protocol);
+  RouteCacheEntry toDst;
+  if (m_routeCache->LookupRoute (dst, toDst))
+    {
+      /*
+       * Found a route the dst, construct the source route option header
+       */
+      DsrOptionSRHeader sourceRoute;
+      std::vector<Ipv4Address> ip = toDst.GetVector ();
+//      PrintVector (ip);
+      sourceRoute.SetNodesAddress (ip);
+      if (m_routeCache->IsLinkCache ())
+        {
+          m_routeCache->UseExtends (ip);
+        }
+      sourceRoute.SetSegmentsLeft ((ip.size () - 2));
+      uint8_t salvage = 0;
+      sourceRoute.SetSalvage (salvage);
+      Ipv4Address nextHop = SearchNextHop (m_mainAddress, ip);       // Get the next hop address
+      NS_LOG_DEBUG ("The nextHop address " << nextHop);
+      if (nextHop == "0.0.0.0")
+        {
+          return;
+        }
+      SetRoute (nextHop, m_mainAddress);
+      CancelRreqTimer (dst);
+      SendPacket (sourceRoute, nextHop, protocol);
+      NS_LOG_LOGIC ("Route to " << dst << " found");
+      return;
+    }
+  /*
+   *  If a route discovery has been attempted m_rreqRetries times at the maximum TTL without
+   *  receiving any RREP, all data packets destined for the corresponding destination SHOULD be
+   *  dropped from the buffer and a Destination Unreachable message SHOULD be delivered to the application.
+   */
+  NS_LOG_DEBUG ("The new request count for " << dst << " is " << m_rreqTable->GetRreqCnt (dst) << " the max " << m_rreqRetries);
+  if (m_rreqTable->GetRreqCnt (dst) >= m_rreqRetries)
+    {
+      NS_LOG_LOGIC ("Route discovery to " << dst << " has been attempted " << m_rreqRetries << " times");
+      CancelRreqTimer (dst);
+      NS_LOG_DEBUG ("Route not found. Drop packet with dst " << dst);
+      m_sendBuffer.DropPacketWithDst (dst);
+    }
+  else
+    {
+      SendRequest (packet, source);
+      NS_LOG_DEBUG ("Check the route request entry1 " << source << " " << dst);
+      ScheduleRreqRetry (packet, source, dst, false, protocol);
+    }
+  return;
+}
+
+void
+DsrRouting::SendRequest (Ptr<Packet> packet,
+                         Ipv4Address source)
+{
+  NS_LOG_FUNCTION (this << packet << source);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+  /*
+   * The destination address here is directed broadcast address
+   */
+  m_downTarget (packet, source, m_broadcast, GetProtocolNumber (), 0);
+}
+
+void
+DsrRouting::ScheduleInterRequest (Ptr<Packet> packet)
+{
+  NS_LOG_FUNCTION (this << packet);
+  /*
+   * this is a forwarding case when sending route requests, a random delay time [0, m_broadcastJitter]
+   * used before forwarding as link-layer broadcast
+   */
+  Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0, m_broadcastJitter)), &DsrRouting::SendRequest, this,
+                       packet, m_mainAddress);
+}
+
+void
+DsrRouting::SendGratuitousReply (Ipv4Address source, Ipv4Address srcAddress, std::vector<Ipv4Address> &nodeList, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << source << srcAddress << (uint32_t)protocol);
+  if (!(m_graReply.FindAndUpdate (source, srcAddress, m_gratReplyHoldoff)))     // Find the gratuitous reply entry
+    {
+      NS_LOG_LOGIC ("Update gratuitous reply " << source);
+      GraReplyEntry graReplyEntry (source, srcAddress, m_gratReplyHoldoff + Simulator::Now ());
+      m_graReply.AddEntry (graReplyEntry);
+      /*
+       * Automatic route shortening
+       */
+      m_finalRoute.clear ();      // Clear the final route vector
+      /**
+       * Push back the node addresses other than those between srcAddress and our own ip address
+       */
+//      PrintVector (nodeList);
+      std::vector<Ipv4Address>::iterator before = find (nodeList.begin (), nodeList.end (), srcAddress);
+      for (std::vector<Ipv4Address>::iterator i = nodeList.begin (); i != before; ++i)
+        {
+          m_finalRoute.push_back (*i);
+        }
+      m_finalRoute.push_back (srcAddress);
+      std::vector<Ipv4Address>::iterator after = find (nodeList.begin (), nodeList.end (), m_mainAddress);
+      for (std::vector<Ipv4Address>::iterator j = after; j != nodeList.end (); ++j)
+        {
+          m_finalRoute.push_back (*j);
+        }
+//      PrintVector (m_finalRoute);
+      DsrOptionRrepHeader rrep;
+      rrep.SetNodesAddress (m_finalRoute);           // Set the node addresses in the route reply header
+      // Get the real reply source and destination
+      Ipv4Address replySrc = m_finalRoute.back ();
+      Ipv4Address replyDst = m_finalRoute.front ();
+      /*
+       * Set the route and use it in send back route reply
+       */
+      m_ipv4Route = SetRoute (srcAddress, m_mainAddress);
+      /*
+       * This part adds DSR header to the packet and send reply
+       */
+      DsrRoutingHeader dsrRoutingHeader;
+      dsrRoutingHeader.SetNextHeader (protocol);
+      dsrRoutingHeader.SetMessageType (1);
+      dsrRoutingHeader.SetSourceId (GetIDfromIP (replySrc));
+      dsrRoutingHeader.SetDestId (GetIDfromIP (replyDst));
+
+      uint8_t length = rrep.GetLength ();        // Get the length of the rrep header excluding the type header
+      dsrRoutingHeader.SetPayloadLength (length + 2);
+      dsrRoutingHeader.AddDsrOption (rrep);
+      Ptr<Packet> newPacket = Create<Packet> ();
+      newPacket->AddHeader (dsrRoutingHeader);
+      /*
+       * Send gratuitous reply
+       */
+      NS_LOG_INFO ("Send back gratuitous route reply");
+      SendReply (newPacket, m_mainAddress, srcAddress, m_ipv4Route);
+    }
+  else
+    {
+      NS_LOG_INFO ("The same gratuitous route reply has already sent");
+    }
+}
+
+void
+DsrRouting::SendReply (Ptr<Packet> packet,
+                       Ipv4Address source,
+                       Ipv4Address nextHop,
+                       Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION (this << packet << source << nextHop);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+  Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (m_mainAddress));
+  route->SetOutputDevice (dev);
+  NS_LOG_INFO ("The output device " << dev << " packet is: " << *packet);
+  m_downTarget (packet, source, nextHop, GetProtocolNumber (), route);
+}
+
+void
+DsrRouting::ScheduleInitialReply (Ptr<Packet> packet,
+                                  Ipv4Address source,
+                                  Ipv4Address nextHop,
+                                  Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION (this << packet << source << nextHop);
+  Simulator::ScheduleNow (&DsrRouting::SendReply, this,
+                          packet, source, nextHop, route);
+}
+
+void
+DsrRouting::ScheduleCachedReply (Ptr<Packet> packet,
+                                 Ipv4Address source,
+                                 Ipv4Address destination,
+                                 Ptr<Ipv4Route> route,
+                                 uint16_t hops)
+{
+  NS_LOG_FUNCTION (this << packet << source << destination);
+  Simulator::Schedule (Time (2 * m_nodeTraversalTime * (hops - 1 + UniformVariable ().GetValue (0,1))), &DsrRouting::SendReply, this, packet, source, destination, route);
+}
+
+void
+DsrRouting::SendAck   (uint16_t ackId,
+                       Ipv4Address destination,
+                       Ipv4Address realSrc,
+                       Ipv4Address realDst,
+                       uint8_t protocol,
+                       Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION (this << ackId << destination << realSrc << realDst << (uint32_t)protocol << route);
+  NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
+
+  // This is a route reply option header
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrRoutingHeader.SetNextHeader (protocol);
+  dsrRoutingHeader.SetMessageType (1);
+  dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
+  dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
+
+  DsrOptionAckHeader ack;
+  /*
+   * Set the ack Id and set the ack source address and destination address
+   */
+  ack.SetAckId (ackId);
+  ack.SetRealSrc (realSrc);
+  ack.SetRealDst (realDst);
+
+  uint8_t length = ack.GetLength ();
+  dsrRoutingHeader.SetPayloadLength (length + 2);
+  dsrRoutingHeader.AddDsrOption (ack);
+
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (dsrRoutingHeader);
+  Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+  route->SetOutputDevice (dev);
+  NS_LOG_DEBUG ("Send out the ACK");
+  m_downTarget (packet, m_mainAddress, destination, GetProtocolNumber (), route);
+}
+
+enum Ipv4L4Protocol::RxStatus
+DsrRouting::Receive (Ptr<Packet> p,
+                     Ipv4Header const &ip,
+                     Ptr<Ipv4Interface> incomingInterface)
+{
+  NS_LOG_FUNCTION (this << p << ip << incomingInterface);
+
+  NS_LOG_INFO ("Our own IP address " << m_mainAddress << " The incoming interface address " << incomingInterface);
+  m_node = GetNode ();                        // Get the node
+  Ptr<Packet> packet = p->Copy ();            // Save a copy of the received packet
+  /*
+   * When forwarding or local deliver packets, this one should be used always!!
+   */
+  DsrRoutingHeader dsrRoutingHeader;
+  packet->RemoveHeader (dsrRoutingHeader);          // Remove the DSR header in whole
+  Ptr<Packet> copy = packet->Copy ();
+  uint8_t protocol = dsrRoutingHeader.GetNextHeader ();
+  uint32_t sourceId = dsrRoutingHeader.GetSourceId ();
+  Ipv4Address source = GetIPfromID (sourceId);
+  NS_LOG_DEBUG ("The source address " << source);
+  /*
+   * Get the IP source and destination address
+   */
+  Ipv4Address src = ip.GetSource ();
+  Ipv4Address dst = ip.GetDestination ();
+
+  bool isPromisc = false;
+  uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();        // Get the offset for option header, 8 bytes in this case
+
+  // This packet is used to peek option type
+  p->RemoveAtStart (offset);
+
+  Ptr<dsr::DsrOptions> dsrOption;
+  DsrOptionHeader dsrOptionHeader;
+  /*
+   * Peek data to get the option type as well as length and segmentsLeft field
+   */
+  uint32_t size = p->GetSize ();
+  uint8_t *data = new uint8_t[size];
+  p->CopyData (data, size);
+
+  uint8_t optionType = 0;
+  uint8_t optionLength = 0;
+  uint8_t segmentsLeft = 0;
+
+  optionType = *(data);
+  NS_LOG_LOGIC ("The option type value " << (uint32_t)optionType);
+  dsrOption = GetOption (optionType);       // Get the relative dsr option and demux to the process function
+
+  if (optionType == 1)        // This is the request option
+    {
+      BlackList *blackList = m_rreqTable->FindUnidirectional (src);
+      if (blackList)
+        {
+          NS_LOG_DEBUG ("Discard this packet due to unidirectional link");
+          m_dropTrace (p);
+        }
+
+      dsrOption = GetOption (optionType);
+      optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
+
+      if (optionLength == 0)
+        {
+          NS_LOG_DEBUG ("Discard this packet");
+          m_dropTrace (p);
+        }
+    }
+  else if (optionType == 2)
+    {
+      dsrOption = GetOption (optionType);
+      optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
+
+      if (optionLength == 0)
+        {
+          NS_LOG_DEBUG ("Discard this packet");
+          m_dropTrace (p);
+        }
+    }
+
+  else if (optionType == 32)       // This is the ACK option
+    {
+      NS_LOG_DEBUG ("This is the ack option");
+      dsrOption = GetOption (optionType);
+      optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
+
+      if (optionLength == 0)
+        {
+          NS_LOG_DEBUG ("Discard this packet");
+          m_dropTrace (p);
+        }
+    }
+
+  else if (optionType == 3)       // This is a route error header
+    {
+      // populate this route error
+      NS_LOG_DEBUG ("The option type value " << (uint32_t)optionType);
+
+      dsrOption = GetOption (optionType);
+      optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
+
+      if (optionLength == 0)
+        {
+          NS_LOG_DEBUG ("Discard this packet");
+          m_dropTrace (p);
+        }
+      NS_LOG_DEBUG ("The option Length " << (uint32_t)optionLength);
+    }
+
+  else if (optionType == 96)       // This is the source route option
+    {
+      NS_LOG_DEBUG ("This is the source route option " << (uint32_t)optionType);
+      dsrOption = GetOption (optionType);
+      optionLength = dsrOption->Process (p, packet, m_mainAddress, source, ip, protocol, isPromisc);
+
+      segmentsLeft = *(data + 3);
+      NS_LOG_DEBUG ("The segments left in source route header " << (uint32_t)segmentsLeft);
+      if (optionLength == 0)
+        {
+          NS_LOG_DEBUG ("Discard this packet");
+          m_dropTrace (p);
+        }
+      else
+        {
+          if (segmentsLeft != 0)
+            {
+              // / get the next header
+              uint8_t nextHeader = dsrRoutingHeader.GetNextHeader ();
+              Ptr<Ipv4L3Protocol> l3proto = m_node->GetObject<Ipv4L3Protocol> ();
+              Ptr<Ipv4L4Protocol> nextProto = l3proto->GetProtocol (nextHeader);
+              if (nextProto != 0)
+                {
+                  // we need to make a copy in the unlikely event we hit the
+                  // RX_ENDPOINT_UNREACH code path
+                  // Here we can use the packet that has been get off whole DSR header
+                  NS_LOG_DEBUG ("The packet received " << *copy);
+                  enum Ipv4L4Protocol::RxStatus status =
+                    nextProto->Receive (copy, ip, incomingInterface);
+                  NS_LOG_DEBUG ("The receive status " << status);
+                  switch (status)
+                    {
+                      case Ipv4L4Protocol::RX_OK:
+                      // fall through
+                      case Ipv4L4Protocol::RX_ENDPOINT_CLOSED:
+                      // fall through
+                      case Ipv4L4Protocol::RX_CSUM_FAILED:
+                        break;
+                      case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
+                        if (ip.GetDestination ().IsBroadcast () == true
+                            || ip.GetDestination ().IsMulticast () == true)
+                          {
+                            break;       // Do not reply to broadcast or multicast
+                          }
+                    }
+                  // Another case to suppress ICMP is a subnet-directed broadcast
+                 return status;
+                }
+            }
+        }
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Unknown Option. Drop!");
+      /*
+       * Initialize the salvage value to 0
+       */
+      uint8_t salvage = 0;
+
+      DsrOptionRerrUnsupportHeader rerrUnsupportHeader;
+      rerrUnsupportHeader.SetErrorType (3);               // The error type 3 means Option not supported
+      rerrUnsupportHeader.SetErrorSrc (m_mainAddress);       // The error source address is our own address
+      rerrUnsupportHeader.SetUnsupported (optionType);       // The unsupported option type number
+      rerrUnsupportHeader.SetErrorDst (src);              // Error destination address is the destination of the data packet
+      rerrUnsupportHeader.SetSalvage (salvage);           // Set the value about whether to salvage a packet or not
+
+      /*
+       * The unknow option error is not supported currently in this implementation, and it's also not likely to
+       * happen in simulations
+       */
+//            SendError (rerrUnsupportHeader, 0, protocol); // Send the error packet
+    }
+  return Ipv4L4Protocol::RX_ENDPOINT_UNREACH;
+}
+
+void
+DsrRouting::SetDownTarget (DownTargetCallback callback)
+{
+  m_downTarget = callback;
+}
+
+Ipv4L4Protocol::DownTargetCallback
+DsrRouting::GetDownTarget (void) const
+{
+  return m_downTarget;
+}
+
+void DsrRouting::Insert (Ptr<dsr::DsrOptions> option)
+{
+  m_options.push_back (option);
+}
+
+Ptr<dsr::DsrOptions> DsrRouting::GetOption (int optionNumber)
+{
+  for (DsrOptionList_t::iterator i = m_options.begin (); i != m_options.end (); ++i)
+    {
+      if ((*i)->GetOptionNumber () == optionNumber)
+        {
+          return *i;
+        }
+    }
+  return 0;
+}
+}  /* namespace dsr */
+}  /* namespace ns3 */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-routing.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,563 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_ROUTING_H
+#define DSR_ROUTING_H
+
+#include <map>
+#include <list>
+#include <vector>
+#include <stdint.h>
+#include <cassert>
+#include <sys/types.h>
+
+#include "ns3/callback.h"
+#include "ns3/object.h"
+#include "ns3/node.h"
+#include "ns3/ptr.h"
+#include "ns3/buffer.h"
+#include "ns3/packet.h"
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-l4-protocol.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/icmpv4-l4-protocol.h"
+#include "ns3/ipv4-interface.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/traced-callback.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/timer.h"
+#include "ns3/net-device.h"
+#include "ns3/output-stream-wrapper.h"
+#include "ns3/wifi-mac.h"
+#include "ns3/socket.h"
+#include "ns3/event-garbage-collector.h"
+#include "ns3/test.h"
+
+#include "dsr-rcache.h"
+#include "dsr-rreq-table.h"
+#include "dsr-maintain-buff.h"
+#include "dsr-option-header.h"
+#include "dsr-fs-header.h"
+#include "dsr-rsendbuff.h"
+#include "dsr-gratuitous-reply-table.h"
+
+namespace ns3 {
+
+class Packet;
+class Node;
+class Ipv4;
+class Ipv4Address;
+class Ipv4Header;
+class Ipv4Interface;
+class Ipv4L3Protocol;
+class Time;
+
+namespace dsr {
+
+class DsrOptions;
+/**
+ * \class DsrRouting
+ * \brief Dsr Routing base
+ */
+class DsrRouting : public Ipv4L4Protocol
+{
+public:
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+    * \brief Define the dsr protocol number.
+    */
+  static const uint8_t PROT_NUMBER;
+  /**
+   * \brief Constructor.
+   */
+  DsrRouting ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~DsrRouting ();
+  /**
+   * \brief Get the node.
+   * \return the node
+   */
+  Ptr<Node> GetNode () const;
+  /**
+   * \brief Set the node.
+   * \param node the node to set
+   */
+  void SetNode (Ptr<Node> node);
+  /**
+   * \brief Set the route cache.
+   * \param the route cache to set
+   */
+  void SetRouteCache (Ptr<dsr::RouteCache> r);
+  /**
+   * \brief Get the route cache.
+   * \return the route cache
+   */
+  Ptr<dsr::RouteCache> GetRouteCache () const;
+  /**
+   * \brief Set the node.
+   * \param the request table to set
+   */
+  void SetRequestTable (Ptr<dsr::RreqTable> r);
+  /**
+    * \brief Get the request table.
+    * \return the request table
+    */
+  Ptr<dsr::RreqTable> GetRequestTable () const;
+  /**
+    * \brief Get the node id from ip address.
+    * \return the node id
+    */
+  uint32_t GetIDfromIP (Ipv4Address address);
+  /**
+    * \brief Get the ip address from id.
+    * \return the ip address for the id
+    */
+  Ipv4Address GetIPfromID (uint32_t id);
+  /**
+    * \brief Get the Ip address from mac address.
+    * \return the ip address
+    */
+  Ipv4Address GetIPfromMAC (Mac48Address address);
+  /**
+    * \brief Print the route vector.
+    */
+  void PrintVector (std::vector<Ipv4Address>& vec);
+  /**
+    * \brief Get the next hop of the route.
+    * \return the next hop address of the route
+    */
+  Ipv4Address SearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec);
+  /**
+    * \brief Cut the route before our own ip address
+    */
+  void CutRoute (Ipv4Address ourAdd, std::vector<Ipv4Address>& nodeList);
+  /**
+    * \brief Get the dsr protocol number.
+    * \return protocol number
+    */
+  int GetProtocolNumber (void) const;
+  /**
+    * \brief The send buffer timer expire.
+    */
+  void SendBuffTimerExpire ();
+  /**
+    * \brief Check the send buffer of packets with route when send buffer timer expire.
+    */
+  void CheckSendBuffer ();
+  /**
+    * \brief When route vector corrupted, originate a new packet, normally not happening.
+    */
+  void PacketNewRoute (Ptr<Packet> packet,
+                       Ipv4Address source,
+                       Ipv4Address destination,
+                       uint8_t protocol);
+  /*
+   * \brief Set the route to use for data packets
+   * \return the route
+   * \used by the option headers when sending data/control packets
+   */
+  Ptr<Ipv4Route> SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress);
+  /*
+   * \brief This function is responsible for sending error packets in case of break link to next hop
+   */
+  void SendUnreachError (Ipv4Address errorHop, Ipv4Address destination, uint8_t salvage, uint8_t protocol);
+  /*
+   * \brief This function is responsible for forwarding error packets along the route
+   */
+  void ForwardErrPacket (DsrOptionRerrUnreachHeader &rerr,
+                         DsrOptionSRHeader &sourceRoute,
+                         Ipv4Address nextHop,
+                         uint8_t protocol,
+                         Ptr<Ipv4Route> route);
+  /*
+   * \brief This function is called by higher layer protocol when sending packets
+   */
+  void Send (Ptr<Packet> packet, Ipv4Address source,
+             Ipv4Address destination, uint8_t protocol, Ptr<Ipv4Route> route);
+  /*
+   * This function is responsible for sending out data packets when have route, if no route found, it will
+   * cache the packet and send out route requests
+   */
+  void SendPacket (DsrOptionSRHeader const &sourceRoute,
+                   Ipv4Address nextHop,
+                   uint8_t protocol);
+  /*
+   * \brief Find the similar entries in the maintenance buffer
+   */
+  bool FindSamePackets (Ptr<Packet> packet, Ipv4Header const& ipv4Header, Ipv4Address source, Ipv4Address destination,
+                        uint8_t segsLeft);
+  /*
+   * Call the cancel packet retransmission timer function
+   */
+  void CallCancelPacketTimer (uint16_t ackId, Ipv4Header const& ipv4Header, Ipv4Address realSrc, Ipv4Address realDst);
+  /*
+   * Cancel the network packet retransmission timer for a specific maintenance entry
+   */
+  void CancelNetworkPacketTimer (MaintainBuffEntry & mb);
+  /*
+   * Cancel the passive packet retransmission timer for a specific maintenance entry
+   */
+  void CancelPassivePacketTimer (MaintainBuffEntry & mb);
+  /*
+   * Cancel the packet retransmission timer for a all maintenance entries with nextHop address
+   */
+  void CancelPacketTimerNextHop (Ipv4Address nextHop, uint8_t protocol);
+  /*
+   * Salvage the packet which has been transmitted for 3 times
+   */
+  void SalvagePacket (Ptr<const Packet> packet, Ipv4Address source, Ipv4Address dst, uint8_t protocol);
+  /*
+   * Add ack request header to the data packet when need to use network acknowledgment
+   */
+  void AddAckReqHeader (Ptr<Packet> packet, DsrOptionSRHeader const &sourceRoute, Ipv4Address nextHop);
+  /*
+   * Schedule the packet retransmission when the packet has not reached to the next hop address
+   */
+  void SchedulePacketRetry   (MaintainBuffEntry & mb,
+                              PacketKey const & packetKey,
+                              uint8_t protocol);
+  /*
+   * This function deals with packet retransmission timer expire
+   */
+  void PacketScheduleTimerExpire  (MaintainBuffEntry & mb,
+                                   PacketKey const & pk,
+                                   uint8_t protocol,
+                                   bool isPassive);
+  /*
+   * Forward the packet using the route saved in the source route option header
+   */
+  void ForwardPacket (Ptr<const Packet> packet,
+                      DsrOptionSRHeader &sourceRoute,
+                      Ipv4Header const& ipv4Header,
+                      Ipv4Address source,
+                      Ipv4Address destination,
+                      Ipv4Address targetAddress,
+                      uint8_t protocol,
+                      Ptr<Ipv4Route> route);
+  /*
+   * Broadcast the route request packet in subnet
+   */
+  void SendInitialRequest (Ipv4Address source,
+                           Ipv4Address destination,
+                           uint8_t protocol);
+  /*
+   * \brief Send the error request packet
+   * \param the route error header
+   * \param the protocol number
+   */
+  void SendErrorRequest (DsrOptionRerrUnreachHeader &rerr, uint8_t protocol);
+  /*
+   * \brief Send the route request and increment the request count
+   * \param the original packet
+   * \param source address
+   * \param destination address
+   */
+  void SendRequestAndIncrement (Ptr<Packet> packet,
+                                Ipv4Address source,
+                                Ipv4Address destination);
+  /*
+   * \brief Forward the route request if the node is not the destination
+   * \param the original packet
+   * \param source address
+   */
+  void SendRequest (Ptr<Packet> packet,
+                    Ipv4Address source);
+  /*
+   * \brief Schedule the intermediate route request
+   * \param the original packet
+   * \param source The source address
+   * \param destination The destination address
+   */
+  void ScheduleInterRequest (Ptr<Packet> packet);
+  /*
+   * \brief Send the gratuitous reply
+   * \param replyTo The destination address to send the reply to
+   * \param replyFrom The source address sending the reply
+   */
+  void SendGratuitousReply (Ipv4Address replyTo,
+                            Ipv4Address replyFrom,
+                            std::vector<Ipv4Address> &nodeList,
+                            uint8_t protocol);
+  /*
+   * Send the route reply back to the request originator with the cumulated route
+   */
+  void SendReply (Ptr<Packet> packet,
+                  Ipv4Address source,
+                  Ipv4Address nextHop,
+                  Ptr<Ipv4Route> route);
+  /*
+   * this is a generating the initial route reply from the destination address, a random delay time
+   * [0, m_broadcastJitter] is used before unicasting back the route reply packet
+   */
+  void ScheduleInitialReply (Ptr<Packet> packet,
+                             Ipv4Address source,
+                             Ipv4Address nextHop,
+                             Ptr<Ipv4Route> route);
+  /*
+   * Schedule the cached reply to a random start time to avoid possible route reply storm
+   */
+  void ScheduleCachedReply (Ptr<Packet> packet,
+                            Ipv4Address source,
+                            Ipv4Address destination,
+                            Ptr<Ipv4Route> route,
+                            uint16_t hops);
+  /*
+   * Send network layer acknowledgment back to the earlier hop to notify the receipt of data packet
+   */
+  void SendAck   (uint16_t ackId,
+                  Ipv4Address destination,
+                  Ipv4Address realSrc,
+                  Ipv4Address realDst,
+                  uint8_t protocol,
+                  Ptr<Ipv4Route> route);
+  /*
+   * Get the node using the ip address
+   */
+  Ptr<Node> GetNodeWithAddress (Ipv4Address ipv4Address);
+  /**
+   * \param p packet to forward up
+   * \param header IPv4 Header information
+   * \param incomingInterface the Ipv4Interface on which the packet arrived
+   *
+   * Called from lower-level layers to send the packet up
+   * in the stack.
+   */
+  virtual enum Ipv4L4Protocol::RxStatus Receive (Ptr<Packet> p,
+                                                 Ipv4Header const &header,
+                                                 Ptr<Ipv4Interface> incomingInterface);
+
+  void SetDownTarget (Ipv4L4Protocol::DownTargetCallback callback);
+  Ipv4L4Protocol::DownTargetCallback GetDownTarget (void) const;
+  /**
+   * \brief Get the extension number.
+   * \return extension number
+   */
+  uint8_t GetExtensionNumber () const;
+  /**
+   * \brief Process method
+   * Called from Ipv4L3Protocol::Receive.
+   *
+   * \param packet the packet
+   * \param offset the offset of the extension to process
+   * \param dst destination address of the packet received (i.e. us)
+   * \param nextHeader the next header
+   * \param isDropped if the packet must be dropped
+   * \return the size processed
+   */
+  uint8_t Process (Ptr<Packet>& packet, Ipv4Header const& ipv4Header, Ipv4Address dst, uint8_t *nextHeader, uint8_t protocol, bool& isDropped);
+  /**
+   * \brief Insert a new Dsr Option.
+   * \param option the option to insert
+   */
+  void Insert (Ptr<dsr::DsrOptions> option);
+  /**
+   * \brief Get the option corresponding to optionNumber.
+   * \param optionNumber the option number of the option to retrieve
+   * \return a matching Dsr option
+   */
+  Ptr<dsr::DsrOptions> GetOption (int optionNumber);
+  /**
+   * \brief Cancel the route request timer.
+   * \param dst The dst address of the route request timer
+   */
+  void CancelRreqTimer (Ipv4Address dst);
+  /**
+   * \brief Schedule the route request retry.
+   * \param dst The dst address of the route request
+   */
+  void ScheduleRreqRetry (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dst, bool nonProp, uint8_t protocol);
+  // / Handle route discovery timer
+  void RouteRequestTimerExpire (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dst, uint8_t protocol);
+
+protected:
+  /*
+ *    * This function will notify other components connected to the node that a new stack member is now connected
+ *       * This will be used to notify Layer 3 protocol of layer 4 protocol stack to connect them together.
+ *          */
+  virtual void NotifyNewAggregate ();
+  /**
+   * \brief Drop trace callback.
+   */
+  virtual void DoDispose (void);
+  /*
+   * The trace for drop, receive and send data packets
+   */
+  TracedCallback<Ptr<const Packet> > m_dropTrace;
+  TracedCallback <const DsrOptionSRHeader &> m_txPacketTrace;
+
+private:
+  void Start ();
+  /**
+   * \brief Send the route error message when the link breaks to the next hop.
+   */
+  void SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop, uint8_t protocol);
+  /**
+   * \brief Promiscuous receive data packets destined to some other node.
+   */
+  bool PromiscReceive (Ptr<NetDevice> device, Ptr<const Packet> packet, uint16_t protocol, const Address &from,
+                       const Address &to, NetDevice::PacketType packetType);
+  /**
+   * \brief Define the list to hold DSR options.
+   */
+  typedef std::list<Ptr<DsrOptions> > DsrOptionList_t;
+  /**
+   * \brief List of DSR Options supported.
+   */
+  DsrOptionList_t m_options;
+
+  Ptr<Ipv4L3Protocol> m_ipv4;        // / Ipv4l3Protocol
+
+  Ptr<Ipv4Route> m_ipv4Route;        // / Ipv4 Route
+
+  Ptr<Ipv4> m_ip;                    // / The ip ptr
+
+  Ptr<Node> m_node;                  // / The node ptr
+
+  Ipv4Address m_mainAddress;         // / Our own Ip address
+
+  uint8_t segsLeft;                  // / The segment left value from SR header
+
+  Ipv4L4Protocol::DownTargetCallback m_downTarget;    // The callback for down layer
+
+  uint8_t m_discoveryHopLimit;             // / Maximum hops to go for route request
+
+  uint8_t m_maxSalvageCount;             // / Maximum # times to salvage a packet
+
+  Time  m_requestPeriod;                   // / The base time interval between route requests
+
+  Time m_nonpropRequestTimeout;            // / The non-propagation request timeout
+
+  uint32_t  m_sendRetries;                // / # of retries have been sent for data packet
+
+  uint32_t m_rreqRetries;                  // /< Maximum number of retransmissions of RREQ with TTL = NetDiameter to discover a route
+
+  uint32_t m_maxMaintRexmt;                  // /< Maximum number of retransmissions of data packets
+
+  Time m_nodeTraversalTime;                // / Time estimated for packet to travel between two nodes
+
+  uint32_t m_maxSendBuffLen;             // /< The maximum number of packets that we allow a routing protocol to buffer.
+
+  Time  m_sendBufferTimeout;               // /< The maximum period of time that a routing protocol is allowed to buffer a packet for.
+
+  SendBuffer m_sendBuffer;               // / The send buffer
+
+  uint32_t  m_maxMaintainLen;            // / Max # of entries for maintainance buffer
+
+  Time     m_maxMaintainTime;            // / Time out for maintainance buffer
+
+  uint32_t m_maxCacheLen;                // / Max # of cache entries for route cache
+
+  Time   m_maxCacheTime;                 // / Max time for caching the route cache entry
+
+  Time  m_maxRreqTime;                   // / Max time for caching the route request entry
+
+  uint32_t  m_maxEntriesEachDst;         // / Max number of route entries to save for each destination
+
+  MaintainBuffer m_maintainBuffer;       // / The declaration of maintain buffer
+
+  uint16_t m_requestId;                  // / The id assigned to each route request
+
+  uint16_t m_ackId;                      // / The ack id assigned to each acknowledge
+
+  uint32_t m_requestTableSize;             // / The max size of the request table size
+
+  uint32_t m_requestTableIds;              // / The request table identifiers
+
+  uint32_t m_maxRreqId;                  // / The max number of request ids for a single destination
+
+  Time  m_blacklistTimeout;                // / The black list time out
+
+  Ipv4Address m_broadcast;                 // / The broadcast IP address
+
+  uint16_t m_broadcastJitter;              // / The max time to delay route request broadcast.
+
+  Time  m_passiveAckTimeout;               // / The timeout value for passive acknowledge
+
+  uint32_t m_tryPassiveAcks;               // /< Maximum number of packet transmission using passive acknowledgment
+
+  Timer m_sendBuffTimer;                 // / The send buffer timer
+
+  Time m_sendBuffInterval;               // / how often to check send buffer
+
+  Time  m_gratReplyHoldoff;                // / The max gratuitous reply hold off time
+
+  Time m_maxRequestPeriod;                 // / The max request period
+
+  uint32_t m_graReplyTableSize;            // / Set the gratuitous reply table size
+
+  std::string m_cacheType;                // / The type of route cache
+
+  double m_stabilityDecrFactor;           // / The initial decrease factor for link cache
+
+  double m_stabilityIncrFactor;           // / The initial increase factor for link cache
+
+  double m_initStability;                 // / The initial stability value for link cache
+
+  double m_minLifeTime;                   // / The min life time
+
+  double m_useExtends;                    // / The use extension of the life time for link cache
+
+  bool m_subRoute;                        // / Whether to save sub route or not
+
+  std::vector<Ipv4Address> m_finalRoute; // / The route cache
+
+  std::map<Ipv4Address, Timer> m_addressReqTimer;        // / Map IP address + RREQ timer.
+
+  std::map<Ipv4Address, Timer> m_nonPropReqTimer;        // / Map IP address + RREQ timer.
+
+  std::map<PacketKey, Timer>  m_addressForwardTimer;   // / Map packet key + forward timer.
+
+  std::map<PacketKey, uint32_t> m_addressForwardCnt;    // / Map packet key + forward counts.
+
+  std::map<PacketKey, Timer> m_passiveAckTimer;               // / The timer for passive acknowledgment
+
+  Ptr<dsr::RouteCache> m_routeCache;      // / A "drop-front" queue used by the routing layer to cache routes found.
+
+  Ptr<dsr::RreqTable> m_rreqTable;        // / A "drop-front" queue used by the routing layer to cache route request sent.
+
+  GraReply m_graReply;                    // / The gratuitous route reply.
+
+  std::vector<Ipv4Address> m_clearList;   // / The node that is clear to send packet to
+
+  uint32_t m_newPacketSize;               // / The packet size of a newly created packet
+
+  std::vector<Ipv4Address> m_addresses;   // / The bind ipv4 addresses with next hop, src, destination address in sequence
+};
+}  /* namespace dsr */
+}  /* namespace ns3 */
+#endif /* DSR_ROUTING_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-rreq-table.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,383 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsr-rreq-table.h"
+#include "ns3/log.h"
+#include <algorithm>
+#include <iostream>
+
+NS_LOG_COMPONENT_DEFINE ("RreqTable");
+
+namespace ns3 {
+namespace dsr {
+
+NS_OBJECT_ENSURE_REGISTERED (RreqTable);
+
+TypeId RreqTable::GetTypeId ()
+{
+  static TypeId tid = TypeId ("ns3::dsr::RreqTable")
+    .SetParent<Object> ()
+    .AddConstructor<RreqTable> ()
+  ;
+  return tid;
+}
+
+RreqTable::RreqTable ()
+  : m_linkStates (PROBABLE)
+{
+}
+
+RreqTable::~RreqTable ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+}
+
+void
+RreqTable::RemoveLeastExpire (std::map<Ipv4Address, RreqTableEntry > & rreqDstMap)
+{
+  NS_LOG_FUNCTION (this);
+  Ipv4Address firstExpire;
+  Time max = Seconds (0.0);
+  for (std::map<Ipv4Address, RreqTableEntry >::const_iterator i =
+         rreqDstMap.begin (); i != rreqDstMap.end (); ++i)
+    {
+      Ipv4Address dst = i->first;
+      RreqTableEntry rreqTableEntry = i->second;
+      if (rreqTableEntry.m_expire > max)
+        {
+          max = rreqTableEntry.m_expire;
+          firstExpire = dst;
+        }
+    }
+  rreqDstMap.erase (firstExpire);
+}
+
+void
+RreqTable::FindAndUpdate (Ipv4Address dst)
+{
+  NS_LOG_LOGIC ("Find and update the route request entry for " << dst);
+  std::map<Ipv4Address, RreqTableEntry >::const_iterator i =
+    m_rreqDstMap.find (dst);
+  if (i == m_rreqDstMap.end ())
+    {
+      NS_LOG_DEBUG ("The request table entry not found");
+      /*
+       * Drop the most aged packet when buffer reaches to max
+       */
+      if (m_rreqDstMap.size () >= m_requestTableSize)
+        {
+          RemoveLeastExpire (m_rreqDstMap);
+          NS_LOG_DEBUG ("The request table size after erase ");
+        }
+      RreqTableEntry rreqTableEntry;
+      rreqTableEntry.m_reqNo = 0;
+      rreqTableEntry.m_expire = Simulator::Now ();
+      m_rreqDstMap [dst] = rreqTableEntry;
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Find the request table entry, increment the request count");
+      Ipv4Address dst = i->first;
+      RreqTableEntry rreqTableEntry = i->second;
+      NS_LOG_DEBUG ("The request count before incrementing " << rreqTableEntry.m_reqNo);
+      rreqTableEntry.m_reqNo = (rreqTableEntry.m_reqNo + 1);
+      rreqTableEntry.m_expire = Simulator::Now ();
+      m_rreqDstMap [dst] = rreqTableEntry;
+    }
+}
+
+void
+RreqTable::RemoveRreqEntry (Ipv4Address dst)
+{
+  NS_LOG_DEBUG ("Remove rreq entry with index dst");
+  std::map<Ipv4Address, RreqTableEntry >::const_iterator i =
+    m_rreqDstMap.find (dst);
+  if (i == m_rreqDstMap.end ())
+    {
+      NS_LOG_DEBUG ("The request table entry not found");
+    }
+  else
+    {
+      // erase the request entry
+      m_rreqDstMap.erase (dst);
+    }
+}
+
+uint16_t
+RreqTable::GetRreqCnt (Ipv4Address dst)
+{
+  NS_LOG_DEBUG ("Get the request count for a certain dst");
+  std::map<Ipv4Address, RreqTableEntry >::const_iterator i =
+    m_rreqDstMap.find (dst);
+  if (i == m_rreqDstMap.end ())
+    {
+      NS_LOG_DEBUG ("The request table entry not found");
+      FindAndUpdate (dst);
+      return 0;
+    }
+  else
+    {
+      RreqTableEntry rreqTableEntry = i->second;
+      NS_LOG_DEBUG ("Find the request count for " << dst << " " << rreqTableEntry.m_reqNo);
+      return rreqTableEntry.m_reqNo;
+    }
+}
+
+// ----------------------------------------------------------------------------------------------------------
+/**
+ * This part takes care of the route request from a specific source
+ * need to ignore future route requests from same source for same destination with same identification
+ */
+bool
+RreqTable::FindSrc (Ipv4Address source, Ipv4Address target, uint16_t id)
+{
+  Purge ();
+  std::map<Ipv4Address, std::list<SourceRreqEntry> >::const_iterator i =
+    m_rreqMap.find (source);
+  if (i == m_rreqMap.end ())
+    {
+      NS_LOG_LOGIC ("No Request entry for " << source << " found");
+      SourceRreqEntry sourceRreqEntry;
+      sourceRreqEntry.m_dst = target;
+      sourceRreqEntry.m_identification = id;
+      sourceRreqEntry.m_expire = m_rreqEntryExpire + Simulator::Now ();
+      NS_LOG_DEBUG ("The src rreq expire time " << sourceRreqEntry.m_expire);
+      std::list<SourceRreqEntry> rqVector;
+      rqVector.push_back (sourceRreqEntry);
+      m_rreqMap[source] = rqVector;
+      return false;
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Request entry for " << source << " found in the cache");
+      std::list<SourceRreqEntry> rqVector = i->second;
+      for (std::list<SourceRreqEntry>::iterator j = rqVector.begin (); j != rqVector.end (); ++j)
+        {
+          SourceRreqEntry rreqEntry = *j;
+          if ((rreqEntry.m_dst == target) && (rreqEntry.m_identification == id))
+            {
+              NS_LOG_DEBUG ("Found the request entry for source node with address " << source);
+//              j = rqVector.erase (j);
+//              rqVector.push_back(*j);
+//              m_rreqMap[source] = rqVector;
+              return true;
+            }
+        }
+
+      SourceRreqEntry rreqEntry;
+      rreqEntry.m_dst = target;
+      rreqEntry.m_identification = id;
+      rreqEntry.m_expire = m_rreqEntryExpire + Simulator::Now ();
+      if (rqVector.size () >= m_requestIdSize)
+        {
+          // erase the first element when the size is larger than the request id size (default: 16)
+          rqVector.pop_front ();
+        }
+      // May need to check the size of the entry
+      rqVector.push_back (rreqEntry);
+      m_rreqMap[source] = rqVector;
+      return false;
+    }
+  return false;
+}
+
+void
+RreqTable::Purge ()
+{
+  //Trying to purge the rreq table
+  if (m_rreqMap.empty ())
+    {
+      NS_LOG_DEBUG ("The rreq table is empty");
+      return;
+    }
+
+  for (std::map<Ipv4Address, std::list<SourceRreqEntry> >::iterator i =
+         m_rreqMap.begin (); i != m_rreqMap.end (); )
+    {
+      // Loop of rreq table entry with the source entries
+      std::map<Ipv4Address, std::list<SourceRreqEntry> >::iterator itmp = i;
+      /*
+       * The rreq table entries
+       */
+      Ipv4Address dst = i->first;
+      std::list<SourceRreqEntry> rqVector = i->second;
+      NS_LOG_DEBUG ("The rqVector size for " << dst << " is " << rqVector.size ());
+      if (rqVector.size ())
+        {
+          for (std::list<SourceRreqEntry>::iterator j = rqVector.begin (); j != rqVector.end (); )
+            {
+              NS_LOG_DEBUG ("The expire time of every entry with expire time " << j->m_expire - Simulator::Now ());
+              /*
+               * First verify if the rreq table entry has expired or not
+               */
+              if (j->m_expire - Simulator::Now () <= Seconds (0))
+                {
+                  /*
+                   * When the expire time has passed, erase the certain rreq table entry
+                   */
+                  NS_LOG_DEBUG ("Erase the expired rreq table entry for " << dst << " with expire time " << j->m_expire - Simulator::Now ());
+                  j = rqVector.erase (j);
+                }
+              else
+                {
+                  ++j;
+                }
+            }
+          NS_LOG_DEBUG ("The rreq table entry for " << dst << " " << rqVector.size ());
+          if (rqVector.size ())
+            {
+              ++i;
+              m_rreqMap.erase (itmp); // erase the entry first
+              /*
+               * Save the new rreq table entry along with the destination address in map
+               */
+              std::pair<std::map<Ipv4Address, std::list<SourceRreqEntry> >::iterator, bool> result =
+                m_rreqMap.insert (std::make_pair (dst, rqVector));
+            }
+          else
+            {
+              ++i;
+              m_rreqMap.erase (itmp);
+            }
+        }
+      else
+        {
+          ++i;
+          m_rreqMap.erase (itmp);
+        }
+    }
+  return;
+}
+
+// ----------------------------------------------------------------------------------------------------------
+/**
+ * This part takes care of the route request ID initialized from a specific source to one destination
+ * Essentially a counter
+ */
+uint16_t
+RreqTable::CheckUniqueRreqId (Ipv4Address dst)
+{
+  NS_LOG_DEBUG ("The size of id cache " << m_rreqIdCache.size ());
+  std::map<Ipv4Address, uint16_t>::const_iterator i =
+    m_rreqIdCache.find (dst);
+  if (i == m_rreqIdCache.end ())
+    {
+      NS_LOG_LOGIC ("No Request id for " << dst << " found");
+      m_rreqIdCache[dst] = 0;
+      return 0;
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Request id for " << dst << " found in the cache");
+      uint16_t rreqId = m_rreqIdCache[dst];
+      if (rreqId >= m_maxRreqId)
+        {
+          NS_LOG_DEBUG ("The request id increase past the max value, so reset it to 0");
+          rreqId = 0;
+          m_rreqIdCache[dst] = rreqId;
+        }
+      else
+        {
+          rreqId++;
+          m_rreqIdCache[dst] = rreqId;
+        }
+      NS_LOG_DEBUG ("The Request id for " << dst << " is " << rreqId);
+      return rreqId;
+    }
+}
+
+uint16_t
+RreqTable::GetRreqSize ()
+{
+  return m_rreqIdCache.size ();
+}
+
+// ----------------------------------------------------------------------------------------------------------
+/**
+ * This part takes care of black list which can save unidirectional link information
+ */
+
+void
+RreqTable::Invalidate ()
+{
+  if (m_linkStates == QUESTIONABLE)
+    {
+      return;
+    }
+  m_linkStates = QUESTIONABLE;
+}
+
+BlackList*
+RreqTable::FindUnidirectional (Ipv4Address neighbor)
+{
+  PurgeNeighbor ();  // purge the neighbor cache
+  for (std::vector<BlackList>::iterator i = m_blackList.begin ();
+       i != m_blackList.end (); ++i)
+    {
+      if (i->m_neighborAddress == neighbor)
+        {
+          return &(*i);
+        }
+    }
+  return NULL;
+}
+
+bool
+RreqTable::MarkLinkAsUnidirectional (Ipv4Address neighbor, Time blacklistTimeout)
+{
+  NS_LOG_LOGIC ("Add neighbor address in blacklist " << m_blackList.size ());
+  for (std::vector<BlackList>::iterator i = m_blackList.begin (); i != m_blackList.end (); ++i)
+    {
+      if (i->m_neighborAddress == neighbor)
+        {
+          NS_LOG_DEBUG ("Update the blacklist list timeout if found the blacklist entry");
+          i->m_expireTime = std::max (blacklistTimeout + Simulator::Now (), i->m_expireTime);
+        }
+      BlackList blackList (neighbor, blacklistTimeout + Simulator::Now ());
+      m_blackList.push_back (blackList);
+      PurgeNeighbor ();
+      return true;
+    }
+  return false;
+}
+
+void
+RreqTable::PurgeNeighbor ()
+{
+  /*
+   * Purge the expired blacklist entries
+   */
+  m_blackList.erase (remove_if (m_blackList.begin (), m_blackList.end (),
+                                IsExpired ()), m_blackList.end ());
+}
+
+} // namespace dsr
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-rreq-table.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,236 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_RREQ_TABLE_H
+#define DSR_RREQ_TABLE_H
+
+#include "ns3/simulator.h"
+#include "ns3/timer.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/callback.h"
+#include <list>
+#include <vector>
+#include <map>
+
+namespace ns3 {
+namespace dsr {
+
+enum LinkStates
+{
+  PROBABLE = 0,            // !< PROBABLE
+  QUESTIONABLE = 1,        // !< QUESTIONABLE
+};
+// / BlackList description
+struct BlackList
+{
+  Ipv4Address m_neighborAddress;
+  Time m_expireTime;
+  LinkStates m_linkStates;
+
+  BlackList (Ipv4Address ip, Time t)
+    : m_neighborAddress (ip),
+      m_expireTime (t),
+      m_linkStates (PROBABLE)
+  {
+  }
+};
+/*
+ * The route request table entries
+ */
+struct RreqTableEntry
+{
+  uint16_t m_reqNo;
+  Time m_expire;
+};
+/*
+ * The route request table id for originators
+ * It is responsible for checking duplicate requests from a single source to a specific destination
+ */
+struct SourceRreqEntry
+{
+  uint16_t m_identification;
+  Ipv4Address m_dst;
+  Time m_expire;
+};
+/**
+ * \ingroup dsr
+ * \brief maintain list of RreqTable entry
+ */
+class RreqTable  : public Object
+{
+public:
+  // / c-tor
+  /**
+   * \brief Get the type identificator.
+   * \return type identificator
+   */
+  static TypeId GetTypeId ();
+  /**
+   * \brief Constructor.
+   */
+  RreqTable ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~RreqTable ();
+
+  // /\name Fields
+  // \{
+  void SetInitHopLimit (uint8_t hl)
+  {
+    m_initHopLimit = hl;
+  }
+  uint8_t GetInitHopLimit () const
+  {
+    return m_initHopLimit;
+  }
+  void SetRreqTableSize (uint32_t rt)
+  {
+    m_requestTableSize = rt;
+  }
+  uint32_t GetRreqTableSize () const
+  {
+    return m_requestTableSize;
+  }
+  void SetRreqIdSize (uint32_t id)
+  {
+    m_requestIdSize = id;
+  }
+  uint32_t GetRreqIdSize () const
+  {
+    return m_requestIdSize;
+  }
+  void SetUniqueRreqIdSize (uint16_t uid)
+  {
+    m_maxRreqId = uid;
+  }
+  uint16_t GetUniqueRreqIdSize () const
+  {
+    return m_maxRreqId;
+  }
+
+  // \}
+  // / Remove the least used entry
+  void RemoveLeastExpire (std::map<Ipv4Address, RreqTableEntry > & rreqDstMap);
+  // / Find the entry in the route request queue to see if already exists
+  void FindAndUpdate (Ipv4Address dst);
+  // / Remove route request entry for dst
+  void RemoveRreqEntry (Ipv4Address dst);
+  // / Get the request count number for one destination address
+  uint16_t GetRreqCnt (Ipv4Address dst);
+
+  //----------------------------------------------------------------------------------------------------------
+  /*
+   * The following code deals with duplicate request ids
+   */
+  bool FindSrc (Ipv4Address source, Ipv4Address target, uint16_t id);
+  // / Purge the rreq table
+  void Purge ();
+  // / Set the source rreq expire time to the time of max route expire time
+  void SetRreqExpire (Time expire)
+  {
+    m_rreqEntryExpire = expire;
+  }
+
+  //----------------------------------------------------------------------------------------------------------
+  /*
+   * The following code generates new request id for each destination
+   */
+  // / Check for duplicate ids and save new entries if the id is not present in the table
+  uint16_t CheckUniqueRreqId (Ipv4Address dst);
+  // / Get the request id size
+  uint16_t GetRreqSize ();
+
+  // ---------------------------------------------------------------------------------------------------------
+  /*
+   * set the unidirectional entry as QUESTIONABLE state
+   */
+  void Invalidate ();
+  /** Verify if entry is unidirectional or not(e.g. add this neighbor to "blacklist" for blacklistTimeout period)
+   * \param neighbor - neighbor address link to which assumed to be unidirectional
+   * \return true on success
+   */
+  BlackList* FindUnidirectional (Ipv4Address neighbor);
+  /** Mark entry as unidirectional (e.g. add this neighbor to "blacklist" for blacklistTimeout period)
+   * \param neighbor - neighbor address link to which assumed to be unidirectional
+   * \param blacklistTimeout - time for which the neighboring node is put into the blacklist
+   * \return true on success
+   */
+  bool MarkLinkAsUnidirectional (Ipv4Address neighbor, Time blacklistTimeout);
+  // / Remove all expired black list entries
+  void PurgeNeighbor ();
+
+private:
+  // / Timer for neighbor's list. Schedule Purge().
+  Timer m_ntimer;
+  // / The max # of requests to retransmit
+  uint32_t MaxRequestRexmt;
+  // / The max request period among requests
+  Time  MaxRequestPeriod;
+  // / The original request period
+  Time  RequestPeriod;
+  // / The non-propagaton request timeout
+  Time  NonpropRequestTimeout;
+  // / The source route entry expire time
+  Time m_rreqEntryExpire;
+  // / The initial hop limit
+  uint8_t m_initHopLimit;
+  // / The request table size
+  uint32_t m_requestTableSize;
+  // / The request source id size
+  uint32_t m_requestIdSize;
+  // / The unique request id for any destination
+  uint16_t m_maxRreqId;
+  // / The state of the unidirectional link
+  LinkStates m_linkStates;
+  // / Map of entries
+  std::list<SourceRreqEntry> m_sourceRreq;
+  // / The id cache to ensure all the ids are unique
+  std::map<Ipv4Address, uint16_t> m_rreqIdCache;
+  // / The cache to save route request table entries indexed with destination address
+  std::map<Ipv4Address, RreqTableEntry > m_rreqDstMap;
+  // / The cache to ensure all the route request from unique source
+  std::map<Ipv4Address, std::list<SourceRreqEntry> > m_rreqMap;
+  // / The Black list
+  std::vector<BlackList> m_blackList;
+  // / Check if the entry is expired or not
+  struct IsExpired
+  {
+    bool operator() (const struct BlackList & b) const
+    {
+      return (b.m_expireTime < Simulator::Now ());
+    }
+  };
+};
+}  // namespace dsr
+}  // namespace ns3
+
+#endif /* DSR_RREQ_TABLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-rsendbuff.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,181 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsr-rsendbuff.h"
+#include <algorithm>
+#include <functional>
+#include "ns3/ipv4-route.h"
+#include "ns3/socket.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsrSendBuffer");
+
+namespace ns3 {
+namespace dsr {
+
+uint32_t
+SendBuffer::GetSize ()
+{
+  Purge ();
+  return m_sendBuffer.size ();
+}
+
+bool
+SendBuffer::Enqueue (SendBuffEntry & entry)
+{
+  Purge ();
+  for (std::vector<SendBuffEntry>::const_iterator i = m_sendBuffer.begin (); i
+       != m_sendBuffer.end (); ++i)
+    {
+      NS_LOG_INFO ("packet id " << i->GetPacket ()->GetUid () << " " << entry.GetPacket ()->GetUid ()
+                                << " dst " << i->GetDestination () << " " << entry.GetDestination ());
+
+      if ((i->GetPacket ()->GetUid () == entry.GetPacket ()->GetUid ())
+          && (i->GetDestination () == entry.GetDestination ()))
+        {
+          return false;
+        }
+    }
+
+  entry.SetExpireTime (m_sendBufferTimeout);     // Initialize the send buffer timeout
+  /*
+   * Drop the most aged packet when buffer reaches to max
+   */
+  if (m_sendBuffer.size () >= m_maxLen)
+    {
+      Drop (m_sendBuffer.front (), "Drop the most aged packet");         // Drop the most aged packet
+      m_sendBuffer.erase (m_sendBuffer.begin ());
+    }
+  // enqueue the entry
+  m_sendBuffer.push_back (entry);
+  return true;
+}
+
+void
+SendBuffer::DropPacketWithDst (Ipv4Address dst)
+{
+  NS_LOG_FUNCTION (this << dst);
+  Purge ();
+  const Ipv4Address addr = dst;
+  /*
+   * Drop the packet with destination address dst
+   */
+  for (std::vector<SendBuffEntry>::iterator i = m_sendBuffer.begin (); i
+       != m_sendBuffer.end (); ++i)
+    {
+      if (IsEqual (*i, dst))
+        {
+          Drop (*i, "DropPacketWithDst");
+        }
+    }
+  m_sendBuffer.erase (std::remove_if (m_sendBuffer.begin (), m_sendBuffer.end (),
+                                      std::bind2nd (std::ptr_fun (SendBuffer::IsEqual), dst)), m_sendBuffer.end ());
+}
+
+bool
+SendBuffer::Dequeue (Ipv4Address dst, SendBuffEntry & entry)
+{
+  Purge ();
+  /*
+   * Dequeue the entry with destination address dst
+   */
+  for (std::vector<SendBuffEntry>::iterator i = m_sendBuffer.begin (); i != m_sendBuffer.end (); ++i)
+    {
+      if (i->GetDestination () == dst)
+        {
+          entry = *i;
+          m_sendBuffer.erase (i);
+          NS_LOG_DEBUG ("Packet size while dequeuing " << entry.GetPacket ()->GetSize ());
+          return true;
+        }
+    }
+  return false;
+}
+
+bool
+SendBuffer::Find (Ipv4Address dst)
+{
+  /*
+   * Make sure if the send buffer contains entry with certain dst
+   */
+  for (std::vector<SendBuffEntry>::const_iterator i = m_sendBuffer.begin (); i
+       != m_sendBuffer.end (); ++i)
+    {
+      if (i->GetDestination () == dst)
+        {
+          NS_LOG_DEBUG ("Found the packet");
+          return true;
+        }
+    }
+  return false;
+}
+
+struct IsExpired
+{
+  bool
+  operator() (SendBuffEntry const & e) const
+  {
+    // NS_LOG_DEBUG("Expire time for packet in req queue: "<<e.GetExpireTime ());
+    return (e.GetExpireTime () < Seconds (0));
+  }
+};
+
+void
+SendBuffer::Purge ()
+{
+  /*
+   * Purge the buffer to eliminate expired entries
+   */
+  NS_LOG_DEBUG ("The send buffer size " << m_sendBuffer.size ());
+  IsExpired pred;
+  for (std::vector<SendBuffEntry>::iterator i = m_sendBuffer.begin (); i
+       != m_sendBuffer.end (); ++i)
+    {
+      if (pred (*i))
+        {
+          NS_LOG_DEBUG ("Dropping Queue Packets");
+          Drop (*i, "Drop out-dated packet ");
+        }
+    }
+  m_sendBuffer.erase (std::remove_if (m_sendBuffer.begin (), m_sendBuffer.end (), pred),
+                      m_sendBuffer.end ());
+}
+
+void
+SendBuffer::Drop (SendBuffEntry en, std::string reason)
+{
+  NS_LOG_LOGIC (reason << en.GetPacket ()->GetUid () << " " << en.GetDestination ());
+//  en.GetErrorCallback () (en.GetPacket (), en.GetDestination (),
+//     Socket::ERROR_NOROUTETOHOST);
+  return;
+}
+}  // namespace dsr
+}  // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/model/dsr-rsendbuff.h	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,190 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#ifndef DSR_SENDBUFF_H
+#define DSR_SENDBUFF_H
+
+#include <vector>
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+namespace dsr {
+/**
+ * \ingroup dsr
+ * \brief DSR Send Buffer Entry
+ */
+class SendBuffEntry
+{
+public:
+  // / c-tor
+  SendBuffEntry (Ptr<const Packet> pa = 0, Ipv4Address d = Ipv4Address (),
+                 Time exp = Simulator::Now (), uint8_t p = 0)
+    : m_packet (pa),
+      m_dst (d),
+      m_expire (exp + Simulator::Now ()),
+      m_protocol (p),
+      m_errHeader (false)
+  {
+  }
+  /**
+   * Compare send buffer entries
+   * \return true if equal
+   */
+  bool operator== (SendBuffEntry const & o) const
+  {
+    return ((m_packet == o.m_packet) && (m_dst == o.m_dst) && (m_expire == o.m_expire));
+  }
+  // /\name Fields
+  // \{
+  Ptr<const Packet> GetPacket () const
+  {
+    return m_packet;
+  }
+  void SetPacket (Ptr<const Packet> p)
+  {
+    m_packet = p;
+  }
+  Ipv4Address GetDestination () const
+  {
+    return m_dst;
+  }
+  void SetDestination (Ipv4Address d)
+  {
+    m_dst = d;
+  }
+  void SetExpireTime (Time exp)
+  {
+    m_expire = exp + Simulator::Now ();
+  }
+  Time GetExpireTime () const
+  {
+    return m_expire - Simulator::Now ();
+  }
+  void SetProtocol (uint8_t p)
+  {
+    m_protocol = p;
+  }
+  uint8_t GetProtocol () const
+  {
+    return m_protocol;
+  }
+  void SetErrHeader (bool e)
+  {
+    m_errHeader = e;
+  }
+  bool IsErrHeader () const
+  {
+    return m_errHeader;
+  }
+  // \}
+private:
+  // / Data packet
+  Ptr<const Packet> m_packet;
+  // / Destination address
+  Ipv4Address m_dst;
+  // / Expire time for queue entry
+  Time m_expire;
+  // / The protocol number
+  uint8_t m_protocol;
+  // / bool value to test the error header
+  bool m_errHeader;
+};
+
+/**
+ * \ingroup dsr
+ * \brief DSR send buffer
+ */
+/************************************************************************************************************************/
+class SendBuffer
+{
+public:
+  // / Default c-tor
+  SendBuffer ()
+  {
+  }
+  // / Push entry in queue, if there is no entry with the same packet and destination address in queue.
+  bool Enqueue (SendBuffEntry & entry);
+  // / Return first found (the earliest) entry for given destination
+  bool Dequeue (Ipv4Address dst, SendBuffEntry & entry);
+  // / Remove all packets with destination IP address dst
+  void DropPacketWithDst (Ipv4Address dst);
+  // / Finds whether a packet with destination dst exists in the queue
+  bool Find (Ipv4Address dst);
+  // / Number of entries
+  uint32_t GetSize ();
+  // /\name Fields
+  // \{
+  uint32_t GetMaxQueueLen () const
+  {
+    return m_maxLen;
+  }
+  void SetMaxQueueLen (uint32_t len)
+  {
+    m_maxLen = len;
+  }
+  Time GetSendBufferTimeout () const
+  {
+    return m_sendBufferTimeout;
+  }
+  void SetSendBufferTimeout (Time t)
+  {
+    m_sendBufferTimeout = t;
+  }
+  // \}
+
+  std::vector<SendBuffEntry> & GetBuffer ()
+  {
+    return m_sendBuffer;
+  }
+
+private:
+  // / The send buffer to cache unsent packet
+  std::vector<SendBuffEntry> m_sendBuffer;
+  // / Remove all expired entries
+  void Purge ();
+  // / Notify that packet is dropped from queue by timeout
+  void Drop (SendBuffEntry en, std::string reason);
+  // / The maximum number of packets that we allow a routing protocol to buffer.
+  uint32_t m_maxLen;
+  // / The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
+  Time m_sendBufferTimeout;
+  // / Check if the send buffer entry is the same or not
+  static bool IsEqual (SendBuffEntry en, const Ipv4Address dst)
+  {
+    return (en.GetDestination () == dst);
+  }
+};
+/*******************************************************************************************************************************/
+} // namespace dsr
+} // namespace ns3
+
+#endif /* DSR_SENDBUFF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/test/dsr-test-suite.cc	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,523 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2011 Yufei Cheng
+ *
+ * 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
+ *
+ * Author: Yufei Cheng   <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group  http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include <vector>
+#include "ns3/ptr.h"
+#include "ns3/boolean.h"
+#include "ns3/test.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/mesh-helper.h"
+#include "ns3/simulator.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+#include "ns3/string.h"
+#include "ns3/ipv4-address-helper.h"
+
+#include "ns3/dsr-fs-header.h"
+#include "ns3/dsr-option-header.h"
+#include "ns3/dsr-rreq-table.h"
+#include "ns3/dsr-rcache.h"
+#include "ns3/dsr-rsendbuff.h"
+#include "ns3/dsr-main-helper.h"
+#include "ns3/dsr-helper.h"
+
+namespace ns3 {
+namespace dsr {
+
+// -----------------------------------------------------------------------------
+// / Unit test for DSR Fixed Size Header
+class DsrFsHeaderTest : public TestCase
+{
+public:
+  DsrFsHeaderTest ();
+  ~DsrFsHeaderTest ();
+  virtual void
+  DoRun (void);
+};
+DsrFsHeaderTest::DsrFsHeaderTest ()
+  : TestCase ("DSR Fixed size Header")
+{
+}
+DsrFsHeaderTest::~DsrFsHeaderTest ()
+{
+}
+void
+DsrFsHeaderTest::DoRun ()
+{
+  dsr::DsrRoutingHeader header;
+  dsr::DsrOptionRreqHeader rreqHeader;
+  header.AddDsrOption (rreqHeader); // has an alignment of 4n+0
+
+  NS_TEST_EXPECT_MSG_EQ (header.GetSerializedSize () % 2, 0, "length of routing header is not a multiple of 4");
+  Buffer buf;
+  buf.AddAtStart (header.GetSerializedSize ());
+  header.Serialize (buf.Begin ());
+
+  const uint8_t* data = buf.PeekData ();
+  NS_TEST_EXPECT_MSG_EQ (*(data + 8), rreqHeader.GetType (), "expect the rreqHeader after fixed size header");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for RREQ
+class DsrRreqHeaderTest : public TestCase
+{
+public:
+  DsrRreqHeaderTest ();
+  ~DsrRreqHeaderTest ();
+  virtual void
+  DoRun (void);
+};
+DsrRreqHeaderTest::DsrRreqHeaderTest ()
+  : TestCase ("DSR RREQ")
+{
+}
+DsrRreqHeaderTest::~DsrRreqHeaderTest ()
+{
+}
+void
+DsrRreqHeaderTest::DoRun ()
+{
+  dsr::DsrOptionRreqHeader h;
+  std::vector<Ipv4Address> nodeList;
+  nodeList.push_back (Ipv4Address ("1.1.1.0"));
+  nodeList.push_back (Ipv4Address ("1.1.1.1"));
+  nodeList.push_back (Ipv4Address ("1.1.1.2"));
+
+  h.SetTarget (Ipv4Address ("1.1.1.3"));
+  NS_TEST_EXPECT_MSG_EQ (h.GetTarget (), Ipv4Address ("1.1.1.3"), "trivial");
+  h.SetNodesAddress (nodeList);
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (0), Ipv4Address ("1.1.1.0"), "trivial");
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (1), Ipv4Address ("1.1.1.1"), "trivial");
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (2), Ipv4Address ("1.1.1.2"), "trivial");
+  h.SetId (1);
+  NS_TEST_EXPECT_MSG_EQ (h.GetId (), 1, "trivial");
+
+  Ptr<Packet> p = Create<Packet> ();
+  dsr::DsrRoutingHeader header;
+  header.AddDsrOption (h);
+  p->AddHeader (header);
+  p->RemoveAtStart (8);
+  dsr::DsrOptionRreqHeader h2;
+  h2.SetNumberAddress (3);
+  uint32_t bytes = p->RemoveHeader (h2);
+  NS_TEST_EXPECT_MSG_EQ (bytes, 20, "Total RREP is 20 bytes long");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for RREP
+class DsrRrepHeaderTest : public TestCase
+{
+public:
+  DsrRrepHeaderTest ();
+  ~DsrRrepHeaderTest ();
+  virtual void
+  DoRun (void);
+};
+DsrRrepHeaderTest::DsrRrepHeaderTest ()
+  : TestCase ("DSR RREP")
+{
+}
+DsrRrepHeaderTest::~DsrRrepHeaderTest ()
+{
+}
+void
+DsrRrepHeaderTest::DoRun ()
+{
+  dsr::DsrOptionRrepHeader h;
+
+  std::vector<Ipv4Address> nodeList;
+  nodeList.push_back (Ipv4Address ("1.1.1.0"));
+  nodeList.push_back (Ipv4Address ("1.1.1.1"));
+  nodeList.push_back (Ipv4Address ("1.1.1.2"));
+  h.SetNodesAddress (nodeList);
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (0), Ipv4Address ("1.1.1.0"), "trivial");
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (1), Ipv4Address ("1.1.1.1"), "trivial");
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (2), Ipv4Address ("1.1.1.2"), "trivial");
+
+  Ptr<Packet> p = Create<Packet> ();
+  dsr::DsrRoutingHeader header;
+  header.AddDsrOption (h);
+  p->AddHeader (header);
+  p->RemoveAtStart (8);
+  dsr::DsrOptionRrepHeader h2;
+  h2.SetNumberAddress (3);
+  uint32_t bytes = p->RemoveHeader (h2);
+  NS_TEST_EXPECT_MSG_EQ (bytes, 16, "Total RREP is 16 bytes long");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for Source Route
+class DsrSRHeaderTest : public TestCase
+{
+public:
+  DsrSRHeaderTest ();
+  ~DsrSRHeaderTest ();
+  virtual void
+  DoRun (void);
+};
+DsrSRHeaderTest::DsrSRHeaderTest ()
+  : TestCase ("DSR Source Route")
+{
+}
+DsrSRHeaderTest::~DsrSRHeaderTest ()
+{
+}
+void
+DsrSRHeaderTest::DoRun ()
+{
+  dsr::DsrOptionSRHeader h;
+  std::vector<Ipv4Address> nodeList;
+  nodeList.push_back (Ipv4Address ("1.1.1.0"));
+  nodeList.push_back (Ipv4Address ("1.1.1.1"));
+  nodeList.push_back (Ipv4Address ("1.1.1.2"));
+  h.SetNodesAddress (nodeList);
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (0), Ipv4Address ("1.1.1.0"), "trivial");
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (1), Ipv4Address ("1.1.1.1"), "trivial");
+  NS_TEST_EXPECT_MSG_EQ (h.GetNodeAddress (2), Ipv4Address ("1.1.1.2"), "trivial");
+
+  h.SetSalvage (1);
+  NS_TEST_EXPECT_MSG_EQ (h.GetSalvage (), 1, "trivial");
+  h.SetSegmentsLeft (2);
+  NS_TEST_EXPECT_MSG_EQ (h.GetSegmentsLeft (), 2, "trivial");
+
+  Ptr<Packet> p = Create<Packet> ();
+  dsr::DsrRoutingHeader header;
+  header.AddDsrOption (h);
+  p->AddHeader (header);
+  p->RemoveAtStart (8);
+  dsr::DsrOptionSRHeader h2;
+  h2.SetNumberAddress (3);
+  uint32_t bytes = p->RemoveHeader (h2);
+  NS_TEST_EXPECT_MSG_EQ (bytes, 16, "Total RREP is 16 bytes long");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for RERR
+class DsrRerrHeaderTest : public TestCase
+{
+public:
+  DsrRerrHeaderTest ();
+  ~DsrRerrHeaderTest ();
+  virtual void
+  DoRun (void);
+};
+DsrRerrHeaderTest::DsrRerrHeaderTest ()
+  : TestCase ("DSR RERR")
+{
+}
+DsrRerrHeaderTest::~DsrRerrHeaderTest ()
+{
+}
+void
+DsrRerrHeaderTest::DoRun ()
+{
+  dsr::DsrOptionRerrUnreachHeader h;
+  h.SetErrorSrc (Ipv4Address ("1.1.1.0"));
+  NS_TEST_EXPECT_MSG_EQ (h.GetErrorSrc (), Ipv4Address ("1.1.1.0"), "trivial");
+  h.SetErrorDst (Ipv4Address ("1.1.1.1"));
+  NS_TEST_EXPECT_MSG_EQ (h.GetErrorDst (), Ipv4Address ("1.1.1.1"), "trivial");
+  h.SetSalvage (1);
+  NS_TEST_EXPECT_MSG_EQ (h.GetSalvage (), 1, "trivial");
+  h.SetUnreachNode (Ipv4Address ("1.1.1.2"));
+  NS_TEST_EXPECT_MSG_EQ (h.GetUnreachNode (), Ipv4Address ("1.1.1.2"), "trivial");
+
+  Ptr<Packet> p = Create<Packet> ();
+  dsr::DsrRoutingHeader header;
+  header.AddDsrOption (h);
+  p->AddHeader (header);
+  p->RemoveAtStart (8);
+  dsr::DsrOptionRerrUnreachHeader h2;
+  uint32_t bytes = p->RemoveHeader (h2);
+  NS_TEST_EXPECT_MSG_EQ (bytes, 16, "Total RREP is 16 bytes long");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for ACK-REQ
+class DsrAckReqHeaderTest : public TestCase
+{
+public:
+  DsrAckReqHeaderTest ();
+  ~DsrAckReqHeaderTest ();
+  virtual void
+  DoRun (void);
+};
+DsrAckReqHeaderTest::DsrAckReqHeaderTest ()
+  : TestCase ("DSR Ack Req")
+{
+}
+DsrAckReqHeaderTest::~DsrAckReqHeaderTest ()
+{
+}
+void
+DsrAckReqHeaderTest::DoRun ()
+{
+  dsr::DsrOptionAckReqHeader h;
+
+  h.SetAckId (1);
+  NS_TEST_EXPECT_MSG_EQ (h.GetAckId (), 1, "trivial");
+
+  Ptr<Packet> p = Create<Packet> ();
+  dsr::DsrRoutingHeader header;
+  header.AddDsrOption (h);
+  p->AddHeader (header);
+  p->RemoveAtStart (8);
+  p->AddHeader (header);
+  dsr::DsrOptionAckReqHeader h2;
+  p->RemoveAtStart (8);
+  uint32_t bytes = p->RemoveHeader (h2);
+  NS_TEST_EXPECT_MSG_EQ (bytes, 4, "Total RREP is 4 bytes long");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for ACK
+class DsrAckHeaderTest : public TestCase
+{
+public:
+  DsrAckHeaderTest ();
+  ~DsrAckHeaderTest ();
+  virtual void
+  DoRun (void);
+};
+DsrAckHeaderTest::DsrAckHeaderTest ()
+  : TestCase ("DSR ACK")
+{
+}
+DsrAckHeaderTest::~DsrAckHeaderTest ()
+{
+}
+void
+DsrAckHeaderTest::DoRun ()
+{
+  dsr::DsrOptionAckHeader h;
+
+  h.SetRealSrc (Ipv4Address ("1.1.1.0"));
+  NS_TEST_EXPECT_MSG_EQ (h.GetRealSrc (), Ipv4Address ("1.1.1.0"), "trivial");
+  h.SetRealDst (Ipv4Address ("1.1.1.1"));
+  NS_TEST_EXPECT_MSG_EQ (h.GetRealDst (), Ipv4Address ("1.1.1.1"), "trivial");
+  h.SetAckId (1);
+  NS_TEST_EXPECT_MSG_EQ (h.GetAckId (), 1, "trivial");
+
+  Ptr<Packet> p = Create<Packet> ();
+  dsr::DsrRoutingHeader header;
+  header.AddDsrOption (h);
+  p->AddHeader (header);
+  p->RemoveAtStart (8);
+  p->AddHeader (header);
+  dsr::DsrOptionAckHeader h2;
+  p->RemoveAtStart (8);
+  uint32_t bytes = p->RemoveHeader (h2);
+  NS_TEST_EXPECT_MSG_EQ (bytes, 12, "Total RREP is 12 bytes long");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for DSR route cache entry
+class DsrCacheEntryTest : public TestCase
+{
+public:
+  DsrCacheEntryTest ();
+  ~DsrCacheEntryTest ();
+  virtual void
+  DoRun (void);
+};
+DsrCacheEntryTest::DsrCacheEntryTest ()
+  : TestCase ("DSR ACK")
+{
+}
+DsrCacheEntryTest::~DsrCacheEntryTest ()
+{
+}
+void
+DsrCacheEntryTest::DoRun ()
+{
+  Ptr<dsr::RouteCache> rcache = CreateObject<dsr::RouteCache> ();
+  std::vector<Ipv4Address> ip;
+  ip.push_back (Ipv4Address ("0.0.0.0"));
+  ip.push_back (Ipv4Address ("0.0.0.1"));
+  Ipv4Address dst = Ipv4Address ("0.0.0.1");
+  dsr::RouteCacheEntry entry (ip, dst, Seconds (1));
+  NS_TEST_EXPECT_MSG_EQ (entry.GetVector ().size (), 2, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (entry.GetDestination (), Ipv4Address ("0.0.0.1"), "trivial");
+  NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (1), "trivial");
+
+  entry.SetExpireTime (Seconds (3));
+  NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (3), "trivial");
+  entry.SetDestination (Ipv4Address ("1.1.1.1"));
+  NS_TEST_EXPECT_MSG_EQ (entry.GetDestination (), Ipv4Address ("1.1.1.1"), "trivial");
+  ip.push_back (Ipv4Address ("0.0.0.2"));
+  entry.SetVector (ip);
+  NS_TEST_EXPECT_MSG_EQ (entry.GetVector ().size (), 3, "trivial");
+
+  NS_TEST_EXPECT_MSG_EQ (rcache->AddRoute (entry), true, "trivial");
+
+  std::vector<Ipv4Address> ip2;
+  ip2.push_back (Ipv4Address ("1.1.1.0"));
+  ip2.push_back (Ipv4Address ("1.1.1.1"));
+  Ipv4Address dst2 = Ipv4Address ("1.1.1.1");
+  dsr::RouteCacheEntry entry2 (ip2, dst2, Seconds (2));
+  dsr::RouteCacheEntry newEntry;
+  NS_TEST_EXPECT_MSG_EQ (rcache->AddRoute (entry2), true, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (rcache->LookupRoute (dst2, newEntry), true, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (rcache->DeleteRoute (Ipv4Address ("2.2.2.2")), false, "trivial");
+
+  NS_TEST_EXPECT_MSG_EQ (rcache->DeleteRoute (Ipv4Address ("1.1.1.1")), true, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (rcache->DeleteRoute (Ipv4Address ("1.1.1.1")), false, "trivial");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for Send Buffer
+class DsrSendBuffTest : public TestCase
+{
+public:
+  DsrSendBuffTest ();
+  ~DsrSendBuffTest ();
+  virtual void
+  DoRun (void);
+  void CheckSizeLimit ();
+  void CheckTimeout ();
+
+  dsr::SendBuffer q;
+};
+DsrSendBuffTest::DsrSendBuffTest ()
+  : TestCase ("DSR SendBuff"),
+    q ()
+{
+}
+DsrSendBuffTest::~DsrSendBuffTest ()
+{
+}
+void
+DsrSendBuffTest::DoRun ()
+{
+  q.SetMaxQueueLen (32);
+  NS_TEST_EXPECT_MSG_EQ (q.GetMaxQueueLen (), 32, "trivial");
+  q.SetSendBufferTimeout (Seconds (10));
+  NS_TEST_EXPECT_MSG_EQ (q.GetSendBufferTimeout (), Seconds (10), "trivial");
+
+  Ptr<const Packet> packet = Create<Packet> ();
+  Ipv4Address dst1 = Ipv4Address ("0.0.0.1");
+  dsr::SendBuffEntry e1 (packet, dst1, Seconds (1));
+  q.Enqueue (e1);
+  q.Enqueue (e1);
+  q.Enqueue (e1);
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("0.0.0.1")), true, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.1.1.1")), false, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 1, "trivial");
+  q.DropPacketWithDst (Ipv4Address ("0.0.0.1"));
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("0.0.0.1")), false, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "trivial");
+
+  Ipv4Address dst2 = Ipv4Address ("0.0.0.2");
+  dsr::SendBuffEntry e2 (packet, dst2, Seconds (1));
+  q.Enqueue (e1);
+  q.Enqueue (e2);
+  Ptr<Packet> packet2 = Create<Packet> ();
+  dsr::SendBuffEntry e3 (packet2, dst2, Seconds (1));
+  NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address ("0.0.0.3"), e3), false, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address ("0.0.0.2"), e3), true, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("0.0.0.2")), false, "trivial");
+  q.Enqueue (e2);
+  q.Enqueue (e3);
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
+  Ptr<Packet> packet4 = Create<Packet> ();
+  Ipv4Address dst4 = Ipv4Address ("0.0.0.4");
+  dsr::SendBuffEntry e4 (packet4, dst4, Seconds (20));
+  q.Enqueue (e4);
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 3, "trivial");
+  q.DropPacketWithDst (Ipv4Address ("0.0.0.4"));
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
+
+  CheckSizeLimit ();
+
+  Simulator::Schedule (q.GetSendBufferTimeout () + Seconds (1), &DsrSendBuffTest::CheckTimeout, this);
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
+void
+DsrSendBuffTest::CheckSizeLimit ()
+{
+  Ptr<Packet> packet = Create<Packet> ();
+  Ipv4Address dst;
+  dsr::SendBuffEntry e1 (packet, dst, Seconds (1));
+
+  for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i)
+    {
+      q.Enqueue (e1);
+    }
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 3, "trivial");
+
+  for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i)
+    {
+      q.Enqueue (e1);
+    }
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 3, "trivial");
+}
+void
+DsrSendBuffTest::CheckTimeout ()
+{
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "Must be empty now");
+}
+// -----------------------------------------------------------------------------
+// / Unit test for DSR routing table entry
+class DsrRreqTableTest : public TestCase
+{
+public:
+  DsrRreqTableTest ();
+  ~DsrRreqTableTest ();
+  virtual void
+  DoRun (void);
+};
+DsrRreqTableTest::DsrRreqTableTest ()
+  : TestCase ("DSR RreqTable")
+{
+}
+DsrRreqTableTest::~DsrRreqTableTest ()
+{
+}
+void
+DsrRreqTableTest::DoRun ()
+{
+  dsr::RreqTableEntry rt;
+
+  rt.m_reqNo = 2;
+  NS_TEST_EXPECT_MSG_EQ (rt.m_reqNo, 2, "trivial");
+}
+// -----------------------------------------------------------------------------
+class DsrTestSuite : public TestSuite
+{
+public:
+  DsrTestSuite () : TestSuite ("routing-dsr", UNIT)
+  {
+    AddTestCase (new DsrFsHeaderTest);
+    AddTestCase (new DsrRreqHeaderTest);
+    AddTestCase (new DsrRrepHeaderTest);
+    AddTestCase (new DsrSRHeaderTest);
+    AddTestCase (new DsrRerrHeaderTest);
+    AddTestCase (new DsrAckReqHeaderTest);
+    AddTestCase (new DsrAckHeaderTest);
+    AddTestCase (new DsrCacheEntryTest);
+    AddTestCase (new DsrSendBuffTest);
+  }
+} g_dsrTestSuite;
+} // namespace dsr
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dsr/wscript	Fri Jan 27 15:15:48 2012 -0800
@@ -0,0 +1,44 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    module = bld.create_ns3_module('dsr', ['internet', 'wifi', 'mesh', 'applications'])
+    module.includes = '.'
+    module.source = [
+        'model/dsr-routing.cc',
+        'model/dsr-options.cc',
+        'model/dsr-fs-header.cc',
+        'model/dsr-option-header.cc',
+        'model/dsr-maintain-buff.cc',
+        'model/dsr-rsendbuff.cc',
+        'model/dsr-rcache.cc',
+        'model/dsr-rreq-table.cc',
+        'model/dsr-gratuitous-reply-table.cc',
+        'helper/dsr-helper.cc',
+        'helper/dsr-main-helper.cc',
+        ]
+        
+    module_test = bld.create_ns3_module_test_library('dsr')
+    module_test.source = [
+        'test/dsr-test-suite.cc',
+        ]
+        
+    headers = bld.new_task_gen(features=['ns3header'])
+    headers.module = 'dsr'
+    headers.source = [
+        'model/dsr-routing.h',
+        'model/dsr-options.h',
+        'model/dsr-fs-header.h',
+        'model/dsr-option-header.h',
+        'model/dsr-maintain-buff.h',
+        'model/dsr-rsendbuff.h',
+        'model/dsr-rcache.h',
+        'model/dsr-rreq-table.h',
+        'model/dsr-gratuitous-reply-table.h',
+        'helper/dsr-helper.h',
+        'helper/dsr-main-helper.h',
+        ]
+
+    if (bld.env['ENABLE_EXAMPLES']):
+      bld.add_subdirs('examples')
+
+    bld.ns3_python_bindings()