# HG changeset patch # User Yufei Cheng # Date 1327706148 28800 # Node ID efad81f3cb47880df56c33569c57ba68a05a60b1 # Parent b3db7d51f260659f2980343b36c2f124ec4416ca Add IPv4 DSR routing diff -r b3db7d51f260 -r efad81f3cb47 doc/models/Makefile --- 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 \ diff -r b3db7d51f260 -r efad81f3cb47 doc/models/source/index.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 diff -r b3db7d51f260 -r efad81f3cb47 examples/routing/manet-routing-compare.cc --- 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 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 flowmon; diff -r b3db7d51f260 -r efad81f3cb47 examples/routing/wscript --- 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']) diff -r b3db7d51f260 -r efad81f3cb47 manet-routing.output.csv.dsr --- /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 diff -r b3db7d51f260 -r efad81f3cb47 manet-routing.output.csv.olsr --- /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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/doc/dsr.h --- /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 + * + * James P.G. Sterbenz , 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/doc/dsr.rst --- /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 `_ +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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/examples/dsr.cc --- /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 + * + * James P.G. Sterbenz , 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 +#include +#include +#include + +#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 positionAlloc = pos.Create ()->GetObject (); + 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 stream = ascii.CreateFileStream ("dsrtest.tr"); + wifiPhy.EnableAsciiAll (stream); + + NS_LOG_INFO ("Run Simulation."); + Simulator::Stop (Seconds (totalTime)); + Simulator::Run (); + Simulator::Destroy (); +} diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/examples/wscript --- /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' + diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/helper/dsr-helper.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 + * + * James P.G. Sterbenz , 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 +DsrHelper::Create (Ptr node) const +{ + NS_LOG_FUNCTION (this); + Ptr agent = m_agentFactory.Create (); + // deal with the downtargets, install UdpL4Protocol, TcpL4Protocol, Icmpv4L4Protocol + Ptr udp = node->GetObject (); + agent->SetDownTarget (udp->GetDownTarget ()); + udp->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent)); + Ptr tcp = node->GetObject (); + tcp->SetDownTarget (MakeCallback (&dsr::DsrRouting::Send, agent)); + Ptr icmp = node->GetObject (); + 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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/helper/dsr-helper.h --- /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 + * + * James P.G. Sterbenz , 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 Create (Ptr 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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/helper/dsr-main-helper.cc --- /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 + * + * James P.G. Sterbenz , 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) +{ + NS_LOG_FUNCTION (node); + Ptr dsr = m_dsrHelper->Create (node); + Ptr routeCache = CreateObject (); + Ptr rreqTable = CreateObject (); + 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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/helper/dsr-main-helper.h --- /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 + * + * James P.G. Sterbenz , 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 routeCache); + void SetRreqTable (Ptr rreqTable); + +private: + void Install (Ptr 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-fs-header.cc --- /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 + * + * James P.G. Sterbenz , 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 () + .SetParent
() + ; + 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 () + .SetParent () + ; + 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-fs-header.h --- /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 + * + * James P.G. Sterbenz , 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 +#include +#include + +#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 */ + diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-gratuitous-reply-table.cc --- /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 + * + * James P.G. Sterbenz , 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 + +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 () + .AddConstructor () + ; + 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::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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-gratuitous-reply-table.h --- /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 + * + * James P.G. Sterbenz , 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 + +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 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-maintain-buff.cc --- /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 + * + * James P.G. Sterbenz , 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 +#include +#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::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::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::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::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::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: "< + * + * James P.G. Sterbenz , 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 +#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 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 GetPacket () const + { + return m_packet; + } + void SetPacket (Ptr 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 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 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-option-header.cc --- /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 + * + * James P.G. Sterbenz , 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 () + .SetParent
() + ; + 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 () + .SetParent () + ; + 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 () + .SetParent () + ; + 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 () + .SetParent () + ; + 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) +{ + m_ipv4Address = ipv4Address; + SetLength (6 + m_ipv4Address.size () * 4); +} + +std::vector 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::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::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 () + .SetParent () + ; + 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) +{ + m_ipv4Address = ipv4Address; + SetLength (2 + m_ipv4Address.size () * 4); +} + +std::vector 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) 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::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::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 () + .SetParent () + ; + 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) +{ + m_ipv4Address = ipv4Address; + SetLength (2 + m_ipv4Address.size () * 4); +} + +std::vector 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::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::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 () + .SetParent () + .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 () + .SetParent () + ; + 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 () + .SetParent () + ; + 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 () + .SetParent () + ; + 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 () + .SetParent () + ; + 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-option-header.h --- /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 + * + * James P.G. Sterbenz , 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 +#include + +#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); + /** + * \brief Get the vector of ipv4 address + * \return the vector of ipv4 address + */ + std::vector 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 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); + /** + * \brief Get the vector of ipv4 address + * \return the vector of ipv4 address + */ + std::vector GetNodesAddress () const; + /* + * \brief Get the target node Ip address + * \return the target address + */ + Ipv4Address GetTargetAddress (std::vector 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 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); + /** + * \brief Get the vector of ipv4 address + * \return the vector of ipv4 address + */ + std::vector 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 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-options.cc --- /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 + * + * James P.G. Sterbenz , 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 ()) { std::clog << "[node " << GetObject ()->GetId () << "] "; } + +#include +#include +#include + +#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 () + .AddAttribute ("OptionNumber", "The Dsr option number.", + UintegerValue (0), + MakeUintegerAccessor (&DsrOptions::GetOptionNumber), + MakeUintegerChecker ()) + .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) +{ + NS_LOG_FUNCTION (this << node); + m_node = node; +} + +Ptr DsrOptions::GetNode () const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + +bool DsrOptions::ContainAddressAfter (Ipv4Address ipv4Address, Ipv4Address destAddress, std::vector &nodeList) +{ + std::vector::iterator it = find (nodeList.begin (), nodeList.end (), destAddress); + + for (std::vector::iterator i = it; i != nodeList.end (); ++i) + { + if ((ipv4Address == (*i)) && ((*i) != nodeList.back ())) + { + return true; + } + } + return false; +} + +std::vector +DsrOptions::CutRoute (Ipv4Address ipv4Address, std::vector &nodeList) +{ + std::vector::iterator it = find (nodeList.begin (), nodeList.end (), ipv4Address); + std::vector cutRoute; + for (std::vector::iterator i = it; i != nodeList.end (); ++i) + { + cutRoute.push_back (*i); + } + return cutRoute; +} + +Ptr DsrOptions::SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress) +{ + NS_LOG_FUNCTION (this << nextHop << srcAddress); + m_ipv4Route = Create (); + m_ipv4Route->SetDestination (nextHop); + m_ipv4Route->SetGateway (nextHop); + m_ipv4Route->SetSource (srcAddress); + return m_ipv4Route; +} + +bool DsrOptions::ReverseRoutes (std::vector & vec) +{ + std::vector vec2 (vec); + vec.clear (); // To ensure vec is empty before start + for (std::vector::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& 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::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& vec) +{ + Ipv4Address nextHop; + if (vec.size () == 2) + { + NS_LOG_DEBUG ("The two nodes are neighbors"); + nextHop = vec[0]; + return nextHop; + } + else + { + for (std::vector::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& 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::const_iterator i = vec.begin (); i != vec.end (); ++i) + { + NS_LOG_DEBUG ("The ip address " << *i); + } + } +} + +bool DsrOptions::IfDuplicates (std::vector& vec, std::vector& vec2) +{ + for (std::vector::const_iterator i = vec.begin (); i != vec.end (); ++i) + { + for (std::vector::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& vec) +{ + for (std::vector::const_iterator i = vec.begin (); i != vec.end (); ++i) + { + if ((*i) == ipv4Address) + { + return true; + } + else + { + continue; + } + } + return false; +} + +void DsrOptions::RemoveDuplicates (std::vector& vec) +{ + //Remove duplicate ip address from the route if any, should not happen with normal behavior nodes + std::vector 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::const_iterator i = vec2.begin (); i != vec2.end (); ++i) + { + if (vec.empty ()) + { + vec.push_back (*i); + continue; + } + else + { + for (std::vector::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 = NodeList::GetNode (i); + Ptr ipv4 = node->GetObject (); + if (ipv4->GetAddress (1, 0).GetLocal () == address) + { + return i; + } + } + return 255; +} + +Ptr DsrOptions::GetNodeWithAddress (Ipv4Address ipv4Address) +{ + int32_t nNodes = NodeList::GetNNodes (); + for (int32_t i = 0; i < nNodes; ++i) + { + Ptr node = NodeList::GetNode (i); + Ptr ipv4 = node->GetObject (); + 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 () + .AddConstructor () + ; + 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, Ptr 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 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 () + .AddConstructor () + ; + 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, Ptr 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 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 () + .AddConstructor () + ; + 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, Ptr 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + Ptr m_routeCache = node->GetObject (); + Ptr m_rreqTable = node->GetObject (); + ActiveRouteTimeout = m_routeCache->GetCacheTimeout (); + + // Set the isError boolean value as false + bool isError = false; + Ptr 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 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 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::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 newPacket = Create (); + 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 nodeList = rreq.GetNodesAddresses (); // Route from rreq header + std::vector 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::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::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 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 newPacket = Create (); + 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 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 interP = Create (); + 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 () + .AddConstructor () + ; + 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, Ptr 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 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + Ptr m_routeCache = node->GetObject (); + Ptr m_rreqTable = node->GetObject (); + ActiveRouteTimeout = m_routeCache->GetCacheTimeout (); + + NS_LOG_DEBUG ("The next header value " << (uint32_t)protocol); + + std::vector 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 routeCopy = nodeList; + std::vector 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 newPacket = Create (); + 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 () + .AddConstructor () + ; + 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, Ptr 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 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 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + /* + * 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + + 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 () + .AddConstructor () + ; + 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, Ptr 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 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + + 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 = GetNodeWithAddress (ipv4Address); + Ptr m_routeCache = node->GetObject (); + m_routeCache->DeleteAllRoutesIncludeLink (errorSource, unreachAddress, ipv4Address); + + Ptr 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 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + /* + * 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 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 () + .AddConstructor () + ; + 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, Ptr 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 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + Ptr m_routeCache = node->GetObject (); + + 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 () + .AddConstructor () + ; + 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, Ptr 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 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 = GetNodeWithAddress (ipv4Address); + Ptr dsr = node->GetObject (); + Ptr srcRouteCache = node->GetObject (); + 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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-options.h --- /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 + * + * James P.G. Sterbenz , 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 +#include + +#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); + /** + * \brief Get the node. + * \return the node + */ + Ptr 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 &nodeList); + /** + * \brief Cut the route from ipv4Address to the end of the route vector + * \return the vector after the route cut + */ + std::vector CutRoute (Ipv4Address ipv4Address, std::vector &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 SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress); + /** + * \brief Reverse the routes. + * \return true if successfully reversed + */ + bool ReverseRoutes (std::vector& vec); + /* + * \brief Search for the next hop in the route + * \return the next hop address if found + */ + Ipv4Address SearchNextHop (Ipv4Address ipv4Address, std::vector& vec); + /* + * \brief Reverse search for the next hop in the route + * \return the next hop address if found + */ + Ipv4Address ReverseSearchNextHop (Ipv4Address ipv4Address, std::vector& vec); + /* + * \brief Print out the elements in the route vector + */ + void PrintVector (std::vector& vec); + /* + * \brief Check if the two vectors contain duplicate or not + * \return true if contains duplicate + */ + bool IfDuplicates (std::vector& vec, std::vector& vec2); + /* + * \brief Check if the route already contains the node ip address + * \return true if it already exists + */ + bool CheckDuplicates (Ipv4Address ipv4Address, std::vector& vec); + /* + * \brief Remove the duplicates from the route + * \return the route after route shorten + */ + void RemoveDuplicates (std::vector& 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, std::vector &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 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, Ptr dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc) = 0; + +protected: + /** + * \brief Drop trace callback. + */ + TracedCallback > m_dropTrace; + /** + * \brief The broadcast IP address. + */ + Ipv4Address Broadcast; + /** + * \brief The route request table. + */ + Ptr m_rreqTable; + /** + * \brief The route cache table. + */ + Ptr m_routeCache; + /** + * \brief The ipv4 route. + */ + Ptr m_ipv4Route; + /** + * \brief The ipv4. + */ + Ptr m_ipv4; + /** + * \brief The vector of Ipv4 address. + */ + std::vector m_ipv4Address; + /** + * \brief The vector of final Ipv4 address. + */ + std::vector m_finalRoute; + /** + * \brief The active route timeout value. + */ + Time ActiveRouteTimeout; + /* + * The receive trace back, only triggered when final destination receive data packet + */ + TracedCallback m_rxPacketTrace; + +private: + Ptr 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, Ptr 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, Ptr 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, Ptr dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc); + +private: + /** + * \brief The route cache. + */ + Ptr m_routeCache; + /** + * \brief The ipv4. + */ + Ptr 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, Ptr dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc); + +private: + /** + * \brief The route cache. + */ + Ptr m_routeCache; + /** + * \brief The length of the packet. + */ + uint32_t m_length; + /** + * \brief The ip layer 3. + */ + Ptr 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, Ptr 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 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, Ptr 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 p, DsrOptionRerrUnreachHeader &rerr, uint32_t rerrSize, Ipv4Address ipv4Address, uint8_t protocol); + +private: + /** + * \brief The route cache. + */ + Ptr m_routeCache; + /** + * \brief The length of the packet. + */ + uint32_t m_length; + /** + * \brief The ipv4 layer 3. + */ + Ptr 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, Ptr dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc); + +private: + /** + * \brief The route cache. + */ + Ptr m_routeCache; + /** + * \brief The length of the packet. + */ + uint32_t m_length; + /** + * \brief The ipv4 layer 3. + */ + Ptr 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, Ptr dsrP, Ipv4Address ipv4Address, Ipv4Address source, Ipv4Header const& ipv4Header, uint8_t protocol, bool& isPromisc); + +private: + /** + * \brief The route cache. + */ + Ptr m_routeCache; + /** + * \brief The length of the packet. + */ + uint32_t m_length; + /** + * \brief The ipv4 layer 3. + */ + Ptr m_ipv4; +}; +} // namespace dsr +} // Namespace ns3 + +#endif diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-rcache.cc --- /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 + * Song Luan (Implemented Link Cache using Dijsktra algorithm) + * + * James P.G. Sterbenz , 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 +#include +#include +#include +#include +#include +#include +#include + +#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::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 () + .AddConstructor () + ; + 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 & 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 >::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 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 >::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 >::const_iterator i = m_sortedRoutes.find (id); + if (i == m_sortedRoutes.end ()) + { + NS_LOG_LOGIC ("No Direct Route to " << id << " found"); + for (std::map >::const_iterator j = + m_sortedRoutes.begin (); j != m_sortedRoutes.end (); ++j) + { + std::list rtVector = j->second; // The route cache vector linked with destination address + /* + * Loop through the possibly multiple routes within the route vector + */ + for (std::list::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 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 >::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 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 d; + // @pre preceeding node + std::map pre; + NS_LOG_FUNCTION (this << source); + for (std::map >::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 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::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::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::iterator oldlink = m_linkCache.find (Link (k->first, pre[k->first])); + std::map::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::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::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 path = rt.GetVector (); + PrintVector (path); + return true; + } +} + +void +RouteCache::PurgeLinkNode () +{ + NS_LOG_FUNCTION (this); + for (std::map::iterator i = m_linkCache.begin (); i != m_linkCache.end (); ) + { + if (i->second.GetLinkStability () <= Seconds (0)) + { + m_linkCache.erase (i++); + } + else + { + i++; + } + } + for (std::map::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::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 rtVector; // Declare the route cache entry vector + Ipv4Address dst = rt.GetDestination (); + std::vector route = rt.GetVector (); + + NS_LOG_DEBUG ("The route destination we have " << dst); + std::map >::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 >::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 >::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 & rtVector) +{ + NS_LOG_FUNCTION (this); + for (std::list::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 >::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::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 >::iterator j = + m_sortedRoutes.begin (); j != m_sortedRoutes.end (); ) + { + std::map >::iterator jtmp = j; + Ipv4Address address = j->first; + std::list rtVector = j->second; + /* + * Loop all the routes for a single destination + */ + for (std::list::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& 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::const_iterator i = vec.begin (); i != vec.end (); ++i) + { + NS_LOG_DEBUG ("The ip address " << *i); + } + } +} + +void +RouteCache::PrintRouteVector (std::list route) +{ + for (std::list::iterator i = route.begin (); i != route.end (); i++) + { + std::vector 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 >::iterator i = + m_sortedRoutes.begin (); i != m_sortedRoutes.end (); ) + { + // Loop of route cache entry with the route size + std::map >::iterator itmp = i; + /* + * The route cache entry vector + */ + Ipv4Address dst = i->first; + std::list rtVector = i->second; + NS_LOG_DEBUG ("The route vector size of1 " << dst << " " << rtVector.size ()); + if (rtVector.size ()) + { + for (std::list::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 >::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::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::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::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::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 nodeList, Time expire) +{ + for (std::vector::iterator i = m_nb.begin (); i != m_nb.end (); ++i) + { + for (std::vector::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 nodeList, Ipv4Address ownAddress, Time expire) +{ + NS_LOG_LOGIC ("Add neighbor number " << nodeList.size ()); + for (std::vector::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::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 a) +{ + m_arp.push_back (a); +} + +void +RouteCache::DelArpCache (Ptr 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 >::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::iterator i = m_nb.begin (); i != m_nb.end (); ++i) + { + if (i->m_hardwareAddress == addr) + { + i->close = true; + } + } + PurgeMac (); +} +} // namespace dsr +} // namespace ns3 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-rcache.h --- /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 + * Song Luan (Implemented Link Cache using dijsktra algorithm to get the best route) + * + * James P.G. Sterbenz , 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 +#include +#include +#include +#include +#include + +#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 IP_VECTOR; // Define the vector to hold Ip address + typedef std::vector::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 m_ipv4Route; + // / The Ipv4 layer 3 + Ptr 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 & rtVector); + // / Define the vector of route entries. + typedef std::list 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& vec); + /** + * Print all the route vector elements from the route list + * \param route the route list + */ + void PrintRouteVector (std::list 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 & 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 nodeList, Time expire); + // / Add to the neighbor list + void AddNeighbor (std::vector 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); + // / Don't use given ARP cache any more (interface is down) + void DelArpCache (Ptr); + // / 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 GetTxErrorCallback () const + { + return m_txErrorCallback; + } + // /\name Handle link failure callback + // \{ + void SetCallback (Callback cb) + { + m_handleLinkFailure = cb; + } + Callback 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 routeEntryVector; + // / Map the ipv4Address to route entry vector + std::map 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 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 > m_netGraph; + // for link route cache + std::map m_bestRoutesTable_link; + std::map m_linkCache; + std::map 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 m_handleLinkFailure; + // / TX error callback + Callback m_txErrorCallback; + // / Timer for neighbor's list. Schedule Purge(). + Timer m_ntimer; + // / vector of entries + std::vector m_nb; + // / list of ARP cached to be used for layer 2 notifications processing + std::vector > 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-routing.cc --- /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 + * + * James P.G. Sterbenz , 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 ()) { std::clog << "[node " << GetObject ()->GetId () << "] "; } + +#include +#include +#include +#include +#include +#include + +#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 () + .AddConstructor () + .AddAttribute ("RouteCache", "The route cache for saving routes from route discovery process.", + PointerValue (0), + MakePointerAccessor (&DsrRouting::SetRouteCache, + &DsrRouting::GetRouteCache), + MakePointerChecker ()) + .AddAttribute ("RreqTable", "The request table to manage route requests.", + PointerValue (0), + MakePointerAccessor (&DsrRouting::SetRequestTable, + &DsrRouting::GetRequestTable), + MakePointerChecker ()) + .AddAttribute ("MaxSendBuffLen","Maximum number of packets that can be stored in send buffer.", + UintegerValue (64), + MakeUintegerAccessor (&DsrRouting::m_maxSendBuffLen), + MakeUintegerChecker ()) + .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 ()) + .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 ()) + .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 ()) + .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 ()) + .AddAttribute ("MaintenanceRetries","Maximum number of retransmissions for data packets from maintenance buffer.", + UintegerValue (3), + MakeUintegerAccessor (&DsrRouting::m_maxMaintRexmt), + MakeUintegerChecker ()) + .AddAttribute ("RequestTableSize","Maximum number of request entries in the request table.", + UintegerValue (64), + MakeUintegerAccessor (&DsrRouting::m_requestTableSize), + MakeUintegerChecker ()) + .AddAttribute ("RequestIdSize","Maximum number of request source Ids in the request table.", + UintegerValue (16), + MakeUintegerAccessor (&DsrRouting::m_requestTableIds), + MakeUintegerChecker ()) + .AddAttribute ("UniqueRequestIdSize","Maximum number of request Ids in the request table for a single destination.", + UintegerValue (256), + MakeUintegerAccessor (&DsrRouting::m_maxRreqId), + MakeUintegerChecker ()) + .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 ()) + .AddAttribute ("MaxSalvageCount","The max salvage count for a single data packet.", + UintegerValue (15), + MakeUintegerAccessor (&DsrRouting::m_maxSalvageCount), + MakeUintegerChecker ()) + .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 ()) + .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 ()) + .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 ()) + .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 ()) + .AddAttribute ("StabilityIncrFactor","The stability increase factor for link cache", + DoubleValue (4.0), + MakeDoubleAccessor (&DsrRouting::m_stabilityIncrFactor), + MakeDoubleChecker ()) + .AddAttribute ("InitStability","The initial stability factor for link cache", + DoubleValue (25.0), + MakeDoubleAccessor (&DsrRouting::m_initStability), + MakeDoubleChecker ()) + .AddAttribute ("MinLifeTime","The minimal life time for link cache", + DoubleValue (1.0), + MakeDoubleAccessor (&DsrRouting::m_minLifeTime), + MakeDoubleChecker ()) + .AddAttribute ("UseExtends","The extension time for link cache", + DoubleValue (120.0), + MakeDoubleAccessor (&DsrRouting::m_useExtends), + MakeDoubleChecker ()) + .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 pad1Option = CreateObject (); + Ptr padnOption = CreateObject (); + Ptr rreqOption = CreateObject (); + Ptr rrepOption = CreateObject (); + Ptr srOption = CreateObject (); + Ptr rerrOption = CreateObject (); + Ptr ackReq = CreateObject (); + Ptr ack = CreateObject (); + + 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 = this->GetObject (); + if (node != 0) + { + m_ipv4 = this->GetObject (); + if (m_ipv4 != 0) + { + this->SetNode (node); + m_ipv4->Insert (this); + this->SetDownTarget (MakeCallback (&Ipv4L3Protocol::Send, m_ipv4)); + } + + m_ip = node->GetObject (); + 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 dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (addr)); + Ptr wifi = dev->GetObject (); + if (wifi == 0) + { + break; + } + Ptr 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) +{ + m_node = node; +} + +Ptr +DsrRouting::GetNode () const +{ + NS_LOG_FUNCTION_NOARGS (); + return m_node; +} + +void DsrRouting::SetRouteCache (Ptr r) +{ + // / Set the route cache to use + m_routeCache = r; +} + +Ptr +DsrRouting::GetRouteCache () const +{ + // / Get the route cache to use + return m_routeCache; +} + +void DsrRouting::SetRequestTable (Ptr q) +{ + // / Set the request table to use + m_rreqTable = q; +} + +Ptr +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 = NodeList::GetNode (i); + Ptr ipv4 = node->GetObject (); + Ptr netDevice = ipv4->GetNetDevice (1); + + if (netDevice->GetAddress () == address) + { + return ipv4->GetAddress (1, 0).GetLocal (); + } + } + return 0; +} + +void DsrRouting::PrintVector (std::vector& 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::const_iterator i = vec.begin (); i != vec.end (); ++i) + { + NS_LOG_DEBUG ("The ip address " << *i); + } + } +} + +Ipv4Address DsrRouting::SearchNextHop (Ipv4Address ipv4Address, std::vector& 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::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 +DsrRouting::SetRoute (Ipv4Address nextHop, Ipv4Address srcAddress) +{ + NS_LOG_FUNCTION (this << nextHop << srcAddress); + m_ipv4Route = Create (); + m_ipv4Route->SetDestination (nextHop); + m_ipv4Route->SetGateway (nextHop); + m_ipv4Route->SetSource (srcAddress); + return m_ipv4Route; +} + +void +DsrRouting::CutRoute (Ipv4Address ourAdd, std::vector& nodeList) +{ + NS_LOG_FUNCTION (this << ourAdd); + std::vector newRoute = nodeList; + nodeList.clear (); + + std::vector::iterator it = find (newRoute.begin (), newRoute.end (), ourAdd); + + for (std::vector::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 = NodeList::GetNode (i); + Ptr ipv4 = node->GetObject (); + 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 = NodeList::GetNode (id); + Ptr ipv4 = node->GetObject (); + 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 dequeP = ConstCast (entry.GetPacket ()); + Ptr newPacket = dequeP->Copy (); + Ptr 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 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 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::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 packet = i->GetPacket (); + Ptr cleanP = packet->Copy (); + uint8_t protocol = i->GetProtocol (); + + m_sendBuffer.GetBuffer ().erase (i); + + DsrRoutingHeader dsrRoutingHeader; + Ptr 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 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 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 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 newPacket = Create (); + newPacket->AddHeader (dsrRoutingHeader); // Add the routing header with rerr and sourceRoute attached to it + Ptr 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 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 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 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 device, Ptr 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 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 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 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, + 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 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 cleanP = packet->Copy (); + DsrRoutingHeader dsrRoutingHeader; + dsrRoutingHeader.SetNextHeader (protocol); + dsrRoutingHeader.SetMessageType (2); + dsrRoutingHeader.SetSourceId (GetIDfromIP (source)); + dsrRoutingHeader.SetDestId (GetIDfromIP (destination)); + + DsrOptionSRHeader sourceRoute; + std::vector 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 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 newPacket = Create (); + newPacket->AddHeader (dsrRoutingHeader); + Ptr 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 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 newPacket = Create (); + newPacket->AddHeader (dsrRoutingHeader); + + SetRoute (nextHop, m_mainAddress); + Ptr 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 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 = Create (); + packet->AddHeader (dsrRoutingHeader); + Ptr 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, + Ipv4Address source, + Ipv4Address destination, + uint8_t protocol, + Ptr 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 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 cleanP = packet->Copy (); + DsrRoutingHeader dsrRoutingHeader; + dsrRoutingHeader.SetNextHeader (protocol); + dsrRoutingHeader.SetMessageType (2); + dsrRoutingHeader.SetSourceId (GetIDfromIP (source)); + dsrRoutingHeader.SetDestId (GetIDfromIP (destination)); + + DsrOptionSRHeader sourceRoute; + std::vector 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 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 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 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 = entry.GetPacket ()->Copy (); + NS_LOG_DEBUG ("The queued packet size " << packet->GetSize ()); + + DsrRoutingHeader dsrRoutingHeader; + Ptr 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 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 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 newPacket = Create (); + newPacket->AddHeader (newRoutingHeader); // Add the extension header with rerr and sourceRoute attached to it + Ptr dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress)); + m_ipv4Route->SetOutputDevice (dev); + m_downTarget (newPacket, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route); + } + } + else + { + Ptr 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 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, 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 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 mainP = Create (); + 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::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::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 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 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 p = packet->Copy (); + Ptr 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 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 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 p = mb.GetPacket ()->Copy (); + Ptr dsrP = p->Copy (); + Ptr salP = p->Copy (); + Ptr 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 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 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, DsrOptionSRHeader const &sourceRoute, Ipv4Address nextHop) +{ + NS_LOG_FUNCTION (this << packet << nextHop); + // This packet is used to peek option type + Ptr 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 packet = mb.GetPacket (); + SetRoute (nextHop, m_mainAddress); + Ptr 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 packet, + DsrOptionSRHeader &sourceRoute, + Ipv4Header const& ipv4Header, + Ipv4Address source, + Ipv4Address nextHop, + Ipv4Address targetAddress, + uint8_t protocol, + Ptr 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 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 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 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 = Create (); + // Create an empty Ipv4 route ptr + Ptr 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 = Create (); + Ipv4Address destination = rerr.GetErrorSrc (); + Ipv4Address unreachAddress = rerr.GetUnreachNode (); + // Create an empty route ptr + Ptr 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 dstP = Create (); + 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, 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 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, 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 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, + 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) +{ + 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 &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::iterator before = find (nodeList.begin (), nodeList.end (), srcAddress); + for (std::vector::iterator i = nodeList.begin (); i != before; ++i) + { + m_finalRoute.push_back (*i); + } + m_finalRoute.push_back (srcAddress); + std::vector::iterator after = find (nodeList.begin (), nodeList.end (), m_mainAddress); + for (std::vector::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 newPacket = Create (); + 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, + Ipv4Address source, + Ipv4Address nextHop, + Ptr route) +{ + NS_LOG_FUNCTION (this << packet << source << nextHop); + NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward"); + Ptr 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, + Ipv4Address source, + Ipv4Address nextHop, + Ptr route) +{ + NS_LOG_FUNCTION (this << packet << source << nextHop); + Simulator::ScheduleNow (&DsrRouting::SendReply, this, + packet, source, nextHop, route); +} + +void +DsrRouting::ScheduleCachedReply (Ptr packet, + Ipv4Address source, + Ipv4Address destination, + Ptr 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 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 = Create (); + packet->AddHeader (dsrRoutingHeader); + Ptr 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 p, + Ipv4Header const &ip, + Ptr 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 = 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 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 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 l3proto = m_node->GetObject (); + Ptr 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 option) +{ + m_options.push_back (option); +} + +Ptr 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-routing.h --- /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 + * + * James P.G. Sterbenz , 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 +#include +#include +#include +#include +#include + +#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 GetNode () const; + /** + * \brief Set the node. + * \param node the node to set + */ + void SetNode (Ptr node); + /** + * \brief Set the route cache. + * \param the route cache to set + */ + void SetRouteCache (Ptr r); + /** + * \brief Get the route cache. + * \return the route cache + */ + Ptr GetRouteCache () const; + /** + * \brief Set the node. + * \param the request table to set + */ + void SetRequestTable (Ptr r); + /** + * \brief Get the request table. + * \return the request table + */ + Ptr 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& vec); + /** + * \brief Get the next hop of the route. + * \return the next hop address of the route + */ + Ipv4Address SearchNextHop (Ipv4Address ipv4Address, std::vector& vec); + /** + * \brief Cut the route before our own ip address + */ + void CutRoute (Ipv4Address ourAdd, std::vector& 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, + 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 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 route); + /* + * \brief This function is called by higher layer protocol when sending packets + */ + void Send (Ptr packet, Ipv4Address source, + Ipv4Address destination, uint8_t protocol, Ptr 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, 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 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, 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 packet, + DsrOptionSRHeader &sourceRoute, + Ipv4Header const& ipv4Header, + Ipv4Address source, + Ipv4Address destination, + Ipv4Address targetAddress, + uint8_t protocol, + Ptr 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, + 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, + 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); + /* + * \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 &nodeList, + uint8_t protocol); + /* + * Send the route reply back to the request originator with the cumulated route + */ + void SendReply (Ptr packet, + Ipv4Address source, + Ipv4Address nextHop, + Ptr 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, + Ipv4Address source, + Ipv4Address nextHop, + Ptr route); + /* + * Schedule the cached reply to a random start time to avoid possible route reply storm + */ + void ScheduleCachedReply (Ptr packet, + Ipv4Address source, + Ipv4Address destination, + Ptr 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 route); + /* + * Get the node using the ip address + */ + Ptr 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 p, + Ipv4Header const &header, + Ptr 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, 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 option); + /** + * \brief Get the option corresponding to optionNumber. + * \param optionNumber the option number of the option to retrieve + * \return a matching Dsr option + */ + Ptr 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, Ipv4Address source, Ipv4Address dst, bool nonProp, uint8_t protocol); + // / Handle route discovery timer + void RouteRequestTimerExpire (Ptr 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 > m_dropTrace; + TracedCallback 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 device, Ptr packet, uint16_t protocol, const Address &from, + const Address &to, NetDevice::PacketType packetType); + /** + * \brief Define the list to hold DSR options. + */ + typedef std::list > DsrOptionList_t; + /** + * \brief List of DSR Options supported. + */ + DsrOptionList_t m_options; + + Ptr m_ipv4; // / Ipv4l3Protocol + + Ptr m_ipv4Route; // / Ipv4 Route + + Ptr m_ip; // / The ip ptr + + Ptr 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 m_finalRoute; // / The route cache + + std::map m_addressReqTimer; // / Map IP address + RREQ timer. + + std::map m_nonPropReqTimer; // / Map IP address + RREQ timer. + + std::map m_addressForwardTimer; // / Map packet key + forward timer. + + std::map m_addressForwardCnt; // / Map packet key + forward counts. + + std::map m_passiveAckTimer; // / The timer for passive acknowledgment + + Ptr m_routeCache; // / A "drop-front" queue used by the routing layer to cache routes found. + + Ptr 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 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 m_addresses; // / The bind ipv4 addresses with next hop, src, destination address in sequence +}; +} /* namespace dsr */ +} /* namespace ns3 */ +#endif /* DSR_ROUTING_H */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-rreq-table.cc --- /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 + * + * James P.G. Sterbenz , 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 +#include + +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 () + .AddConstructor () + ; + return tid; +} + +RreqTable::RreqTable () + : m_linkStates (PROBABLE) +{ +} + +RreqTable::~RreqTable () +{ + NS_LOG_FUNCTION_NOARGS (); +} + +void +RreqTable::RemoveLeastExpire (std::map & rreqDstMap) +{ + NS_LOG_FUNCTION (this); + Ipv4Address firstExpire; + Time max = Seconds (0.0); + for (std::map::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::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::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::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 >::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 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 rqVector = i->second; + for (std::list::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 >::iterator i = + m_rreqMap.begin (); i != m_rreqMap.end (); ) + { + // Loop of rreq table entry with the source entries + std::map >::iterator itmp = i; + /* + * The rreq table entries + */ + Ipv4Address dst = i->first; + std::list rqVector = i->second; + NS_LOG_DEBUG ("The rqVector size for " << dst << " is " << rqVector.size ()); + if (rqVector.size ()) + { + for (std::list::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 >::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::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::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::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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-rreq-table.h --- /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 + * + * James P.G. Sterbenz , 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 +#include +#include + +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 & 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 m_sourceRreq; + // / The id cache to ensure all the ids are unique + std::map m_rreqIdCache; + // / The cache to save route request table entries indexed with destination address + std::map m_rreqDstMap; + // / The cache to ensure all the route request from unique source + std::map > m_rreqMap; + // / The Black list + std::vector 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-rsendbuff.cc --- /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 + * + * James P.G. Sterbenz , 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 +#include +#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::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::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::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::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: "<::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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/model/dsr-rsendbuff.h --- /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 + * + * James P.G. Sterbenz , 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 +#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 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 GetPacket () const + { + return m_packet; + } + void SetPacket (Ptr 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 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 & GetBuffer () + { + return m_sendBuffer; + } + +private: + // / The send buffer to cache unsent packet + std::vector 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 */ diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/test/dsr-test-suite.cc --- /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 + * + * James P.G. Sterbenz , 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 +#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 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 p = Create (); + 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 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 p = Create (); + 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 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 p = Create (); + 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 p = Create (); + 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 p = Create (); + 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 p = Create (); + 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 rcache = CreateObject (); + std::vector 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 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 packet = Create (); + 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 packet2 = Create (); + 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 packet4 = Create (); + 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 = Create (); + 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 diff -r b3db7d51f260 -r efad81f3cb47 src/dsr/wscript --- /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()