--- 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()