src/dsr/model/dsr-routing.cc
changeset 8752 2da1fab73114
parent 8751 efad81f3cb47
child 8753 8d84b96e26bf
--- a/src/dsr/model/dsr-routing.cc	Fri Jan 27 15:15:48 2012 -0800
+++ b/src/dsr/model/dsr-routing.cc	Sun May 06 20:52:24 2012 -0700
@@ -39,11 +39,17 @@
 #include <algorithm>
 #include <iostream>
 
+#include "ns3/enum.h"
 #include "ns3/string.h"
 #include "ns3/ptr.h"
 #include "ns3/log.h"
 #include "ns3/assert.h"
 #include "ns3/uinteger.h"
+#include "ns3/packet.h"
+#include "ns3/boolean.h"
+#include "ns3/node-list.h"
+#include "ns3/double.h"
+#include "ns3/pointer.h"
 #include "ns3/object-vector.h"
 #include "ns3/ipv4-address.h"
 #include "ns3/ipv4-header.h"
@@ -53,17 +59,12 @@
 #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"
@@ -138,20 +139,16 @@
                    TimeValue (Seconds (300)),
                    MakeTimeAccessor (&DsrRouting::m_maxCacheTime),
                    MakeTimeChecker ())
-    .AddAttribute ("RreqEntryTimeout","Maximum time for the route request entry to time out.",
-                   TimeValue (Seconds (30)),
-                   MakeTimeAccessor (&DsrRouting::m_maxRreqTime),
-                   MakeTimeChecker ())
     .AddAttribute ("MaxEntriesEachDst","Maximum number of route entries for a single destination to respond.",
                    UintegerValue (20),
                    MakeUintegerAccessor (&DsrRouting::m_maxEntriesEachDst),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("SendBuffInterval","How often to check send buffer for packet with route.",
-                   TimeValue (Seconds (50)),
+                   TimeValue (Seconds (500)),
                    MakeTimeAccessor (&DsrRouting::m_sendBuffInterval),
                    MakeTimeChecker ())
     .AddAttribute ("NodeTraversalTime","The time it takes to traverse two neighboring nodes.",
-                   TimeValue (MicroSeconds (2)),
+                   TimeValue (MilliSeconds (40)),
                    MakeTimeAccessor (&DsrRouting::m_nodeTraversalTime),
                    MakeTimeChecker ())
     .AddAttribute ("RreqRetries","Maximum number of retransmissions for request discovery of a route.",
@@ -159,9 +156,9 @@
                    MakeUintegerAccessor (&DsrRouting::m_rreqRetries),
                    MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("MaintenanceRetries","Maximum number of retransmissions for data packets from maintenance buffer.",
-                   UintegerValue (3),
-                   MakeUintegerAccessor (&DsrRouting::m_maxMaintRexmt),
-                   MakeUintegerChecker<uint32_t> ())
+                   DoubleValue (2),
+                   MakeDoubleAccessor (&DsrRouting::m_maxMaintRexmt),
+                   MakeDoubleChecker<uint32_t> ())
     .AddAttribute ("RequestTableSize","Maximum number of request entries in the request table.",
                    UintegerValue (64),
                    MakeUintegerAccessor (&DsrRouting::m_requestTableSize),
@@ -169,7 +166,7 @@
     .AddAttribute ("RequestIdSize","Maximum number of request source Ids in the request table.",
                    UintegerValue (16),
                    MakeUintegerAccessor (&DsrRouting::m_requestTableIds),
-                   MakeUintegerChecker<uint16_t> ())
+                   MakeUintegerChecker<uint32_t> ())
     .AddAttribute ("UniqueRequestIdSize","Maximum number of request Ids in the request table for a single destination.",
                    UintegerValue (256),
                    MakeUintegerAccessor (&DsrRouting::m_maxRreqId),
@@ -179,9 +176,9 @@
                    MakeTimeAccessor (&DsrRouting::m_nonpropRequestTimeout),
                    MakeTimeChecker ())
     .AddAttribute ("DiscoveryHopLimit","The max discovery hop limit for route requests.",
-                   UintegerValue (255),
-                   MakeUintegerAccessor (&DsrRouting::m_discoveryHopLimit),
-                   MakeUintegerChecker<uint8_t> ())
+                   DoubleValue (255),
+                   MakeDoubleAccessor (&DsrRouting::m_discoveryHopLimit),
+                   MakeDoubleChecker<uint32_t> ())
     .AddAttribute ("MaxSalvageCount","The max salvage count for a single data packet.",
                    UintegerValue (15),
                    MakeUintegerAccessor (&DsrRouting::m_maxSalvageCount),
@@ -199,7 +196,7 @@
                    MakeUintegerAccessor (&DsrRouting::m_broadcastJitter),
                    MakeUintegerChecker<uint16_t> ())
     .AddAttribute ("PassiveAckTimeout","The time a packet in maintenance buffer wait for passive acknowledgment.",
-                   TimeValue (MicroSeconds (4)),
+                   TimeValue (MilliSeconds (100)),
                    MakeTimeAccessor (&DsrRouting::m_passiveAckTimeout),
                    MakeTimeChecker ())
     .AddAttribute ("TryPassiveAcks","The number of passive acknowledgment to use.",
@@ -223,29 +220,45 @@
                    MakeStringAccessor (&DsrRouting::m_cacheType),
                    MakeStringChecker ())
     .AddAttribute ("StabilityDecrFactor","The stability decrease factor for link cache",
-                   DoubleValue (2.0),
-                   MakeDoubleAccessor (&DsrRouting::m_stabilityDecrFactor),
-                   MakeDoubleChecker<double> ())
+                   UintegerValue (2),
+                   MakeUintegerAccessor (&DsrRouting::m_stabilityDecrFactor),
+                   MakeUintegerChecker<uint64_t> ())
     .AddAttribute ("StabilityIncrFactor","The stability increase factor for link cache",
-                   DoubleValue (4.0),
-                   MakeDoubleAccessor (&DsrRouting::m_stabilityIncrFactor),
-                   MakeDoubleChecker<double> ())
+                   UintegerValue (4),
+                   MakeUintegerAccessor (&DsrRouting::m_stabilityIncrFactor),
+                   MakeUintegerChecker<uint64_t> ())
     .AddAttribute ("InitStability","The initial stability factor for link cache",
-                   DoubleValue (25.0),
-                   MakeDoubleAccessor (&DsrRouting::m_initStability),
-                   MakeDoubleChecker<double> ())
+                   TimeValue (Seconds (25)),
+                   MakeTimeAccessor (&DsrRouting::m_initStability),
+                   MakeTimeChecker ())
     .AddAttribute ("MinLifeTime","The minimal life time for link cache",
-                   DoubleValue (1.0),
-                   MakeDoubleAccessor (&DsrRouting::m_minLifeTime),
-                   MakeDoubleChecker<double> ())
+                   TimeValue (Seconds (1)),
+                   MakeTimeAccessor (&DsrRouting::m_minLifeTime),
+                   MakeTimeChecker ())
     .AddAttribute ("UseExtends","The extension time for link cache",
-                   DoubleValue (120.0),
-                   MakeDoubleAccessor (&DsrRouting::m_useExtends),
-                   MakeDoubleChecker<double> ())
+                   TimeValue (Seconds (120)),
+                   MakeTimeAccessor (&DsrRouting::m_useExtends),
+                   MakeTimeChecker ())
     .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 ())
+    .AddAttribute ("RetransIncr","The increase time for retransmission timer when facing network congestion",
+                   TimeValue (MilliSeconds (20)),
+                   MakeTimeAccessor (&DsrRouting::m_retransIncr),
+                   MakeTimeChecker ())
+    .AddAttribute ("MaxNetworkQueueSize","The max number of packet to save in the network queue.",
+                   UintegerValue (400),
+                   MakeUintegerAccessor (&DsrRouting::m_maxNetworkSize),
+                   MakeUintegerChecker<uint32_t> ())
+    .AddAttribute ("MaxNetworkQueueDelay","The max time for a packet to stay in the network queue.",
+                   TimeValue (Seconds (30.0)),
+                   MakeTimeAccessor (&DsrRouting::m_maxNetworkDelay),
+                   MakeTimeChecker ())
+    .AddAttribute ("NumPriorityQueues","The max number of packet to save in the network queue.",
+                   UintegerValue (2),
+                   MakeUintegerAccessor (&DsrRouting::m_numPriorityQueues),
+                   MakeUintegerChecker<uint32_t> ())
     .AddTraceSource ("Tx", "Send DSR packet.",
                      MakeTraceSourceAccessor (&DsrRouting::m_txPacketTrace))
     .AddTraceSource ("Drop", "Drop DSR packet",
@@ -283,7 +296,7 @@
 
   // Check the send buffer for sending packets
   m_sendBuffTimer.SetFunction (&DsrRouting::SendBuffTimerExpire, this);
-  m_sendBuffTimer.Schedule (Seconds (0));
+  m_sendBuffTimer.Schedule (Seconds (100));
 }
 
 DsrRouting::~DsrRouting ()
@@ -322,6 +335,24 @@
 void DsrRouting::Start ()
 {
   NS_LOG_FUNCTION (this << "Start DSR Routing protocol");
+  Ptr<dsr::RouteCache> routeCache = CreateObject<dsr::RouteCache> ();
+  // Configure the path cache parameters
+  routeCache->SetCacheType (m_cacheType);
+  routeCache->SetSubRoute (m_subRoute);
+  routeCache->SetMaxCacheLen (m_maxCacheLen);
+  routeCache->SetCacheTimeout (m_maxCacheTime);
+  routeCache->SetMaxEntriesEachDst (m_maxEntriesEachDst);
+  // Parameters for link cache
+  routeCache->SetStabilityDecrFactor (m_stabilityDecrFactor);
+  routeCache->SetStabilityIncrFactor (m_stabilityIncrFactor);
+  routeCache->SetInitStability (m_initStability);
+  routeCache->SetMinLifeTime (m_minLifeTime);
+  routeCache->SetUseExtends (m_useExtends);
+  routeCache->ScheduleTimer ();
+  // The call back to handle link error and send error message to appropriate nodes
+  routeCache->SetCallback (MakeCallback (&DsrRouting::SendRerrWhenBreaksLinkToNextHop, this));
+  SetRouteCache (routeCache);
+
   if (m_mainAddress == Ipv4Address ())
     {
       Ipv4Address loopback ("127.0.0.1");
@@ -329,7 +360,7 @@
         {
           // Use primary address, if multiple
           Ipv4Address addr = m_ipv4->GetAddress (i, 0).GetLocal ();
-          m_broadcast = m_ipv4->GetAddress (i, 0).GetBroadcast ();
+          m_broadcast = m_ipv4->GetAddress (i, 0).GetBroadcast();
           NS_LOG_DEBUG ("The addr " << addr);
           if (addr != loopback)
             {
@@ -352,47 +383,70 @@
                 }
 
               // 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 ());
+              mac->TraceConnectWithoutContext ("TxErrHeader", routeCache->GetTxErrorCallback ());
+              routeCache->AddArpCache (m_ipv4->GetInterface (i)->GetArpCache ());
               break;
             }
         }
+      NS_ASSERT (m_mainAddress != Ipv4Address () && m_broadcast != Ipv4Address());
     }
 
+  NS_LOG_DEBUG ("The number queues " << m_numPriorityQueues);
+  for (uint32_t i = 0; i < m_numPriorityQueues; i++)
+  {
+    // Set the network queue max size and the delay
+    NS_LOG_DEBUG ("The network size " << m_maxNetworkSize << " and the network delay " << m_maxNetworkDelay.GetSeconds());
+    Ptr<dsr::DsrNetworkQueue> queue_i = CreateObject<dsr::DsrNetworkQueue> (m_maxNetworkSize,m_maxNetworkDelay);
+    std::pair<std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator, bool> result_i = m_priorityQueue.insert (std::make_pair (i, queue_i));
+    NS_ASSERT_MSG (result_i.second, "Error in creating queues");
+  }
+  Ptr<dsr::RreqTable> rreqTable = CreateObject<dsr::RreqTable> ();
   // Set the initial hop limit
-  m_rreqTable->SetInitHopLimit (m_discoveryHopLimit);
+  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);
+  rreqTable->SetRreqTableSize (m_requestTableSize);
+  rreqTable->SetRreqIdSize (m_requestTableIds);
+  rreqTable->SetUniqueRreqIdSize (m_maxRreqId);
+  SetRequestTable (rreqTable);
   // Set the send buffer parameters
   m_sendBuffer.SetMaxQueueLen (m_maxSendBuffLen);
   m_sendBuffer.SetSendBufferTimeout (m_sendBufferTimeout);
+  // Set the error buffer parameters using just the send buffer parameters
+  m_errorBuffer.SetMaxQueueLen (m_maxSendBuffLen);
+  m_errorBuffer.SetErrorBufferTimeout (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::DoDispose (void)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  m_node = 0;
+  for (uint32_t i = 0; i < m_ipv4->GetNInterfaces (); i++)
+    {
+      // Disable layer 2 link state monitoring (if possible)
+      Ptr<NetDevice> dev = m_ipv4->GetNetDevice (i);
+      Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
+      if (wifi != 0)
+        {
+          Ptr<WifiMac> mac = wifi->GetMac ()->GetObject<AdhocWifiMac> ();
+          if (mac != 0)
+            {
+              mac->TraceDisconnectWithoutContext ("TxErrHeader",
+                                                  m_routeCache->GetTxErrorCallback ());
+              m_routeCache->DelArpCache (m_ipv4->GetInterface (i)->GetArpCache ());
+            }
+        }
+    }
+  Ipv4L4Protocol::DoDispose ();
+}
+
+void
 DsrRouting::SetNode (Ptr<Node> node)
 {
   m_node = node;
@@ -431,9 +485,50 @@
   return m_rreqTable;
 }
 
+bool DsrRouting::IsLinkCache ()
+{
+  return m_routeCache->IsLinkCache ();
+}
+
+void DsrRouting::UseExtends (RouteCacheEntry::IP_VECTOR rt)
+{
+  m_routeCache->UseExtends (rt);
+}
+
+bool DsrRouting::LookupRoute (Ipv4Address id, RouteCacheEntry & rt)
+{
+  return m_routeCache->LookupRoute (id, rt);
+}
+
+bool DsrRouting::AddRoute_Link (RouteCacheEntry::IP_VECTOR nodelist, Ipv4Address source)
+{
+  Ipv4Address nextHop = SearchNextHop (source, nodelist);
+  m_errorBuffer.DropPacketForErrLink (source, nextHop);
+  return m_routeCache->AddRoute_Link (nodelist, source);
+}
+
+bool DsrRouting::AddRoute (RouteCacheEntry & rt)
+{
+  std::vector<Ipv4Address> nodelist = rt.GetVector ();
+  Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodelist);
+  m_errorBuffer.DropPacketForErrLink (m_mainAddress, nextHop);
+  return m_routeCache->AddRoute (rt);
+}
+
+void DsrRouting::DeleteAllRoutesIncludeLink (Ipv4Address errorSrc, Ipv4Address unreachNode, Ipv4Address node)
+{
+  m_routeCache->DeleteAllRoutesIncludeLink (errorSrc, unreachNode, node);
+}
+
+bool DsrRouting::UpdateRouteEntry (Ipv4Address dst)
+{
+  return m_routeCache->UpdateRouteEntry (dst);
+}
+
 Ipv4Address
 DsrRouting::GetIPfromMAC (Mac48Address address)
 {
+  NS_LOG_FUNCTION (this << address);
   int32_t nNodes = NodeList::GetNNodes ();
   for (int32_t i = 0; i < nNodes; ++i)
     {
@@ -451,6 +546,7 @@
 
 void DsrRouting::PrintVector (std::vector<Ipv4Address>& vec)
 {
+  NS_LOG_FUNCTION (this);
   /*
    * Check elements in a route vector
    */
@@ -470,7 +566,9 @@
 
 Ipv4Address DsrRouting::SearchNextHop (Ipv4Address ipv4Address, std::vector<Ipv4Address>& vec)
 {
+  NS_LOG_FUNCTION (this << ipv4Address);
   Ipv4Address nextHop;
+  NS_LOG_DEBUG ("the vector size " << vec.size ());
   if (vec.size () == 2)
     {
       NS_LOG_DEBUG ("The two nodes are neighbors");
@@ -484,10 +582,11 @@
           NS_LOG_DEBUG ("We have reached to the final destination " << ipv4Address << " " << vec.back ());
           return ipv4Address;
         }
-      for (std::vector<Ipv4Address>::iterator i = vec.begin (); i != vec.end (); ++i)
+      for (std::vector<Ipv4Address>::const_iterator i = vec.begin (); i != vec.end (); ++i)
         {
           if (ipv4Address == (*i))
             {
+              NS_LOG_DEBUG (ipv4Address << " and " << *i);
               nextHop = *(++i);
               return nextHop;
             }
@@ -509,21 +608,6 @@
   return m_ipv4Route;
 }
 
-void
-DsrRouting::CutRoute (Ipv4Address ourAdd, std::vector<Ipv4Address>& nodeList)
-{
-  NS_LOG_FUNCTION (this << ourAdd);
-  std::vector<Ipv4Address> newRoute = nodeList;
-  nodeList.clear ();
-
-  std::vector<Ipv4Address>::iterator it = find (newRoute.begin (), newRoute.end (), ourAdd);
-
-  for (std::vector<Ipv4Address>::iterator i = it; i != newRoute.end (); ++i)
-    {
-      nodeList.push_back (*i);
-    }
-}
-
 int
 DsrRouting::GetProtocolNumber (void) const
 {
@@ -531,15 +615,7 @@
   return PROT_NUMBER;
 }
 
-void
-DsrRouting::DoDispose (void)
-{
-  NS_LOG_FUNCTION_NOARGS ();
-  m_node = 0;
-  Ipv4L4Protocol::DoDispose ();
-}
-
-uint32_t
+uint16_t
 DsrRouting::GetIDfromIP (Ipv4Address address)
 {
   int32_t nNodes = NodeList::GetNNodes ();
@@ -549,28 +625,41 @@
       Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
       if (ipv4->GetAddress (1, 0).GetLocal () == address)
         {
-          return i;
+          return uint16_t(i);
         }
     }
-  return 255;
+  return 256;
 }
 
 Ipv4Address
-DsrRouting::GetIPfromID (uint32_t id)
+DsrRouting::GetIPfromID (uint16_t id)
 {
-  if (id >= 255)
+  if (id >= 256)
     {
       NS_LOG_DEBUG ("Exceed the node range");
       return "0.0.0.0";
     }
   else
     {
-      Ptr<Node> node = NodeList::GetNode (id);
+      Ptr<Node> node = NodeList::GetNode (uint32_t (id));
       Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
       return ipv4->GetAddress (1, 0).GetLocal ();
     }
 }
 
+uint32_t
+DsrRouting::GetPriority (DsrMessageType messageType)
+{
+  if (messageType == DSR_CONTROL_PACKET)
+    {
+      return 0;
+    }
+  else
+    {
+      return 1;
+    }
+}
+
 void DsrRouting::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop, uint8_t protocol)
 {
   NS_LOG_FUNCTION (this << nextHop << (uint32_t)protocol);
@@ -585,7 +674,7 @@
           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,
+           * if only queue the original packet to the buffer,
            * when dequeue the packet, it turns to be empty.
            */
           Ptr<Packet> dequeP = ConstCast<Packet> (entry.GetPacket ());
@@ -595,8 +684,12 @@
           Ipv4Address source = entry.GetSrc ();
           Ipv4Address destination = entry.GetDst ();
 
+          // Send the data packet out before schedule the next packet transmission
+          SendPacket (dequeP, source, nextHop, protocol);
+
           DsrRoutingHeader dsrRoutingHeader;
           p->RemoveHeader (dsrRoutingHeader);
+          Ptr<Packet> cleanP = p->Copy ();
           uint8_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
           newPacket->RemoveAtStart (offset);
 
@@ -610,17 +703,19 @@
           newPacket->RemoveHeader (sourceRoute);
           uint8_t salvage = sourceRoute.GetSalvage ();
 
+          // TODO
           DsrOptionAckReqHeader ackReq;
           newPacket->RemoveHeader (ackReq);
           /*
            * Get the node list address
            */
           std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
-          Ipv4Address address1 = nodeList.front ();
+          Ipv4Address address1 = nodeList[1];
           Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);
           NS_LOG_DEBUG ("The next hop address" << nextHop);
           if (nextHop == "0.0.0.0")
             {
+              PacketNewRoute (cleanP, m_mainAddress, destination, protocol);
               return;
             }
           RouteCacheEntry salvageRoute;
@@ -639,14 +734,32 @@
                 {
                   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);
+
+              NetworkKey networkKey;
+              networkKey.m_ackId = entry.GetAckId ();
+              networkKey.m_ourAdd = entry.GetOurAdd ();
+              networkKey.m_nextHop = entry.GetNextHop ();
+              networkKey.m_source = entry.GetSrc ();
+              networkKey.m_destination = entry.GetDst ();
+
+              PassiveKey passiveKey;
+              passiveKey.m_ackId = 0;
+              passiveKey.m_source = entry.GetSrc ();
+              passiveKey.m_destination = entry.GetDst ();
+              passiveKey.m_segsLeft = entry.GetSegsLeft ();
+
+              m_addressForwardCnt[networkKey] = 0;
+              m_passiveCnt[passiveKey] = 0;
+
+              if (nextHop != destination)
+                {
+                  SchedulePassivePacketRetry (entry, false, protocol);
+                }
+              else
+                {
+                  // This is the first network retry
+                  ScheduleNetworkPacketRetry (entry, true, protocol);
+                }
             }
           else
             {
@@ -654,45 +767,24 @@
                * 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
                */
+              Ipv4Address errorDst;
               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);
-                    }
+                  errorDst = address1;
                 }
               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);
-                    }
+                  errorDst = source;
                 }
+              SendUnreachError (nextHop, errorDst, destination, salvage, protocol);
+              /*
+               * here we cancel the packet retransmission time for all the packets have next hop address
+               * as nextHop
+               */
             }
           if (m_maintainBuffer.GetSize () != 0 && m_maintainBuffer.Find (nextHop))
             {
@@ -735,6 +827,8 @@
 
           DsrRoutingHeader dsrRoutingHeader;
           Ptr<Packet> copyP = packet->Copy ();
+          Ptr<Packet> dsrPacket = packet->Copy ();
+          dsrPacket->RemoveHeader (dsrRoutingHeader);
           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
@@ -782,6 +876,7 @@
 
                   if (nextHop == "0.0.0.0")
                     {
+                      PacketNewRoute (dsrPacket, m_mainAddress, destination, protocol);
                       return;
                     }
 
@@ -791,7 +886,7 @@
                   dsrRoutingHeader.SetMessageType (1);
                   dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
                   dsrRoutingHeader.SetDestId (255);
-                  dsrRoutingHeader.SetPayloadLength (length + 4);
+                  dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
                   dsrRoutingHeader.AddDsrOption (newUnreach);
                   dsrRoutingHeader.AddDsrOption (sourceRoute);
 
@@ -799,7 +894,22 @@
                   newPacket->AddHeader (dsrRoutingHeader); // Add the routing header with rerr and sourceRoute attached to it
                   Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
                   m_ipv4Route->SetOutputDevice (dev);
-                  m_downTarget (newPacket, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route);
+
+                  uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
+                  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+                  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+                  NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+                  DsrNetworkQueueEntry newEntry (newPacket, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
+
+                  if (dsrNetworkQueue->Enqueue (newEntry))
+                    {
+                      Scheduler (priority);
+                    }
+                  else
+                    {
+                      NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+                    }
                 }
             }
           else
@@ -814,7 +924,7 @@
               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);
+                  PacketNewRoute (dsrPacket, m_mainAddress, destination, protocol);
                   return;
                 }
               uint8_t salvage = 0;
@@ -822,43 +932,52 @@
               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);
+              uint8_t length = sourceRoute.GetLength ();
+              dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
               dsrRoutingHeader.AddDsrOption (sourceRoute);
-              dsrRoutingHeader.AddDsrOption (ackReq);
               cleanP->AddHeader (dsrRoutingHeader);
+              // Send the data packet out before schedule the next packet transmission
+              SendPacket (cleanP, m_mainAddress, nextHop, protocol);
               Ptr<const Packet> mtP = cleanP->Copy ();
               // Put the data packet in the maintenance queue for data packet retransmission
               MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*Ipv4Address=*/ m_mainAddress, /*nextHop=*/ nextHop,
-                                                      /*source=*/ m_mainAddress, /*destination=*/ destination, /*ackId=*/ m_ackId,
-                                                      /*SegsLeft=*/ nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
+                                          /*source=*/ m_mainAddress, /*destination=*/ destination, /*ackId=*/ 0,
+                                          /*SegsLeft=*/nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
               bool result = m_maintainBuffer.Enqueue (newEntry); // Enqueue the packet the the maintenance buffer
               if (result)
                 {
-                  Ptr<Packet> newPacket = cleanP->Copy ();
-                  PacketKey packetKey;
-                  packetKey.m_ackId = newEntry.GetAckId ();
-                  packetKey.m_ourAdd = newEntry.GetOurAdd ();
-                  packetKey.m_nextHop = newEntry.GetNextHop ();
-                  packetKey.m_source = newEntry.GetSrc ();
-                  packetKey.m_destination = newEntry.GetDst ();
-                  packetKey.m_segsLeft = newEntry.GetSegsLeft ();
-                  SchedulePacketRetry (newEntry, packetKey, protocol);
+                  NetworkKey networkKey;
+                  networkKey.m_ackId = newEntry.GetAckId ();
+                  networkKey.m_ourAdd = newEntry.GetOurAdd ();
+                  networkKey.m_nextHop = newEntry.GetNextHop ();
+                  networkKey.m_source = newEntry.GetSrc ();
+                  networkKey.m_destination = newEntry.GetDst ();
+
+                  PassiveKey passiveKey;
+                  passiveKey.m_ackId = 0;
+                  passiveKey.m_source = newEntry.GetSrc ();
+                  passiveKey.m_destination = newEntry.GetDst ();
+                  passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
+
+                  m_addressForwardCnt[networkKey] = 0;
+                  m_passiveCnt[passiveKey] = 0;
+                  if (nextHop != destination)
+                    {
+                      SchedulePassivePacketRetry (newEntry, false, protocol);
+                    }
+                  else
+                    {
+                      // This is the first network retry
+                      ScheduleNetworkPacketRetry (newEntry, true, protocol);
+                    }
                 }
-              //we need to suspend the normal timer that checks the send buffer
-              //until we are done sending packets
+              // 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);
+              Simulator::Schedule (m_sendBuffInterval, &DsrRouting::SendBuffTimerExpire, this);
               return;
             }
         }
@@ -996,41 +1115,54 @@
       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);
+      uint8_t length = sourceRoute.GetLength ();
+      dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
       dsrRoutingHeader.AddDsrOption (sourceRoute);
-      dsrRoutingHeader.AddDsrOption (ackReq);
       cleanP->AddHeader (dsrRoutingHeader);
+      // Send the data packet out before schedule the next packet transmission
+      SendPacket (cleanP, source, nextHop, protocol);
       Ptr<const Packet> mtP = cleanP->Copy ();
       SetRoute (nextHop, m_mainAddress);
       // Put the data packet in the maintenance queue for data packet retransmission
       MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*Ipv4Address=*/ m_mainAddress, /*nextHop=*/ nextHop,
-                                              /*source=*/ source, /*destination=*/ destination, /*ackId=*/ m_ackId,
-                                              /*SegsLeft=*/ nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
+                                              /*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
+                                              /*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);
+          NetworkKey networkKey;
+          networkKey.m_ackId = newEntry.GetAckId ();
+          networkKey.m_ourAdd = newEntry.GetOurAdd ();
+          networkKey.m_nextHop = newEntry.GetNextHop ();
+          networkKey.m_source = newEntry.GetSrc ();
+          networkKey.m_destination = newEntry.GetDst ();
+
+          PassiveKey passiveKey;
+          passiveKey.m_ackId = 0;
+          passiveKey.m_source = newEntry.GetSrc ();
+          passiveKey.m_destination = newEntry.GetDst ();
+          passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
+
+          m_addressForwardCnt[networkKey] = 0;
+          m_passiveCnt[passiveKey] = 0;
+          if (nextHop != destination)
+            {
+              SchedulePassivePacketRetry (newEntry, false, protocol);
+            }
+          else
+            {
+              // This is the first network retry
+              ScheduleNetworkPacketRetry (newEntry, true, protocol);
+            }
         }
     }
 }
 
 void
-DsrRouting::SendUnreachError (Ipv4Address errorHop, Ipv4Address destination, uint8_t salvage, uint8_t protocol)
+DsrRouting::SendUnreachError (Ipv4Address errorHop, Ipv4Address destination, Ipv4Address originalDst, uint8_t salvage, uint8_t protocol)
 {
-  NS_LOG_FUNCTION (this << errorHop << destination << (uint32_t)salvage << (uint32_t)protocol);
+  NS_LOG_FUNCTION (this << errorHop << destination << originalDst << (uint32_t)salvage << (uint32_t)protocol);
   DsrRoutingHeader dsrRoutingHeader;
   dsrRoutingHeader.SetNextHeader (protocol);
   dsrRoutingHeader.SetMessageType (1);
@@ -1042,12 +1174,14 @@
   rerrUnreachHeader.SetErrorSrc (m_mainAddress);
   rerrUnreachHeader.SetUnreachNode (errorHop);
   rerrUnreachHeader.SetErrorDst (destination);
-  rerrUnreachHeader.SetSalvage (salvage);     // Set the value about whether to salvage a packet or not
+  rerrUnreachHeader.SetOriginalDst (originalDst);
+  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
+  Ptr<Packet> newPacket = Create<Packet> ();
   if (!findRoute)
     {
       NS_LOG_INFO (Simulator::Now ().GetSeconds ()
@@ -1055,12 +1189,11 @@
 
       dsrRoutingHeader.SetPayloadLength (rerrLength + 2);
       dsrRoutingHeader.AddDsrOption (rerrUnreachHeader);
-      Ptr<Packet> newPacket = Create<Packet> ();
       newPacket->AddHeader (dsrRoutingHeader);
       Ptr<Packet> p = newPacket->Copy ();
-      SendBuffEntry newEntry (p, destination, m_sendBufferTimeout);
-      newEntry.SetErrHeader (true);        // Note it as an error packet
-      bool result = m_sendBuffer.Enqueue (newEntry);     // Enqueue the packet in send buffer
+      // Save the error packet in the error buffer
+      ErrorBuffEntry newEntry (p, destination, m_mainAddress, errorHop, m_sendBufferTimeout, protocol);
+      bool result = m_errorBuffer.Enqueue (newEntry);                    // Enqueue the packet in send buffer
       if (result)
         {
           NS_LOG_INFO (Simulator::Now ().GetSeconds ()
@@ -1082,6 +1215,8 @@
       Ipv4Address nextHop = SearchNextHop (m_mainAddress, nodeList);
       if (nextHop == "0.0.0.0")
         {
+          NS_LOG_DEBUG ("The route is not right");
+          PacketNewRoute (newPacket, m_mainAddress, destination, protocol);
           return;
         }
       DsrOptionSRHeader sourceRoute;
@@ -1094,17 +1229,31 @@
       uint8_t srLength = sourceRoute.GetLength ();
       uint8_t length = (srLength + rerrLength);
 
-      dsrRoutingHeader.SetNextHeader (protocol);
-      dsrRoutingHeader.SetPayloadLength (length + 4);
+      dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
       dsrRoutingHeader.AddDsrOption (rerrUnreachHeader);
       dsrRoutingHeader.AddDsrOption (sourceRoute);
-      Ptr<Packet> newPacket = Create<Packet> ();
       newPacket->AddHeader (dsrRoutingHeader);
 
       SetRoute (nextHop, m_mainAddress);
       Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
       m_ipv4Route->SetOutputDevice (dev);
-      m_downTarget (newPacket, m_mainAddress, nextHop, protocol, m_ipv4Route);
+      NS_LOG_INFO ("Send the packet to the next hop address " << nextHop << " from " << m_mainAddress << " with the size " << newPacket->GetSize());
+
+      uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
+      std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+      Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+      NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+      DsrNetworkQueueEntry newEntry (newPacket, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
+
+      if (dsrNetworkQueue->Enqueue (newEntry))
+        {
+          Scheduler (priority);
+        }
+      else
+        {
+          NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+        }
     }
 }
 
@@ -1124,14 +1273,29 @@
   dsrRoutingHeader.SetDestId (GetIDfromIP (rerr.GetErrorDst ()));
 
   uint8_t length = (sourceRoute.GetLength () + rerr.GetLength ());
-  dsrRoutingHeader.SetPayloadLength (length + 4);
+  dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
   dsrRoutingHeader.AddDsrOption (rerr);
   dsrRoutingHeader.AddDsrOption (sourceRoute);
   Ptr<Packet> packet = Create<Packet> ();
   packet->AddHeader (dsrRoutingHeader);
   Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
   route->SetOutputDevice (dev);
-  m_downTarget (packet, m_mainAddress, nextHop, GetProtocolNumber (), route);
+
+  uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
+  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+  NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+   DsrNetworkQueueEntry newEntry (packet, m_mainAddress, nextHop, Simulator::Now (), route);
+
+  if (dsrNetworkQueue->Enqueue (newEntry))
+    {
+      Scheduler (priority);
+    }
+  else
+    {
+      NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+    }
 }
 
 void
@@ -1160,7 +1324,6 @@
                        << "s " << m_mainAddress << " there is no route for this packet, queue the packet");
 
           Ptr<Packet> p = packet->Copy ();
-          m_newPacketSize = packet->GetSize ();
           SendBuffEntry newEntry (p, destination, m_sendBufferTimeout, protocol);     // Create a new entry for send buffer
           bool result = m_sendBuffer.Enqueue (newEntry);     // Enqueue the packet in send buffer
           if (result)
@@ -1177,6 +1340,10 @@
                    */
                   SendInitialRequest (source, destination, protocol);
                 }
+              else
+                {
+                  NS_LOG_DEBUG ("There is existing route request timer and the request count here " << m_rreqTable->GetRreqCnt (destination));
+                }
             }
         }
       else
@@ -1205,53 +1372,245 @@
           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 ();
 
-          uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
-
-          dsrRoutingHeader.SetPayloadLength (length + 4);
+          dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
           dsrRoutingHeader.AddDsrOption (sourceRoute);
-          dsrRoutingHeader.AddDsrOption (ackReq);
           cleanP->AddHeader (dsrRoutingHeader);
+          // Send the data packet out before schedule the next packet transmission
+          SendPacket (cleanP, source, nextHop, protocol);
 
           Ptr<const Packet> mtP = cleanP->Copy ();
+          NS_LOG_DEBUG ("maintain packet size " << cleanP->GetSize());
           // 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);
+                                      /*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
+                                      /*SegsLeft=*/nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
           bool result = m_maintainBuffer.Enqueue (newEntry);       // Enqueue the packet the the maintenance buffer
           if (result)
             {
-              Ptr<Packet> newPacket = cleanP->Copy ();
-              /*
-               * Schedule the packet retransmission
-               */
-              PacketKey packetKey;
-              packetKey.m_ackId = newEntry.GetAckId ();
-              packetKey.m_ourAdd = newEntry.GetOurAdd ();
-              packetKey.m_nextHop = newEntry.GetNextHop ();
-              packetKey.m_source = newEntry.GetSrc ();
-              packetKey.m_destination = newEntry.GetDst ();
-              packetKey.m_segsLeft = newEntry.GetSegsLeft ();
-              PacketKey networkKey = packetKey;
-              networkKey.m_segsLeft = 0;
+              NetworkKey networkKey;
+              networkKey.m_ackId = newEntry.GetAckId ();
+              networkKey.m_ourAdd = newEntry.GetOurAdd ();
+              networkKey.m_nextHop = newEntry.GetNextHop ();
+              networkKey.m_source = newEntry.GetSrc ();
+              networkKey.m_destination = newEntry.GetDst ();
+
+              PassiveKey passiveKey;
+              passiveKey.m_ackId = 0;
+              passiveKey.m_source = newEntry.GetSrc ();
+              passiveKey.m_destination = newEntry.GetDst ();
+              passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
+
               m_addressForwardCnt[networkKey] = 0;
-              SchedulePacketRetry (newEntry, packetKey, protocol);
+              m_passiveCnt[passiveKey] = 0;
+              if (nextHop != destination)
+                {
+                  SchedulePassivePacketRetry (newEntry, false, protocol);
+                }
+              else
+                {
+                  // This is the first network retry
+                  ScheduleNetworkPacketRetry (newEntry, true, protocol);
+                }
             }
           // Try to send packet from *previously* queued entries from send buffer if any
-          SendPacket (sourceRoute, nextHop, protocol);
+          Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
+                               &DsrRouting::SendPacketFromBuffer,this,sourceRoute,nextHop,protocol);
         }
     }
 }
 
+uint16_t
+DsrRouting::AddAckReqHeader (Ptr<Packet>& packet, Ipv4Address nextHop)
+{
+  NS_LOG_FUNCTION (this << packet << nextHop);
+  // This packet is used to peek option type
+  Ptr<Packet> dsrP = packet->Copy ();
+  Ptr<Packet> tmpP = packet->Copy ();
+
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrP->RemoveHeader (dsrRoutingHeader);          // Remove the DSR header in whole
+  uint8_t protocol = dsrRoutingHeader.GetNextHeader ();
+  uint32_t sourceId = dsrRoutingHeader.GetSourceId ();
+  uint32_t destinationId = dsrRoutingHeader.GetDestId ();
+  uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
+  tmpP->RemoveAtStart (offset);       // Here the processed size is 8 bytes, which is the fixed sized extension header
+
+  // Get the number of routers' address field
+  uint8_t buf[2];
+  tmpP->CopyData (buf, sizeof(buf));
+  uint8_t numberAddress = (buf[1] - 2) / 4;
+  DsrOptionSRHeader sourceRoute;
+  sourceRoute.SetNumberAddress (numberAddress);
+  tmpP->RemoveHeader (sourceRoute);               // this is a clean packet without any dsr involved headers
+
+  DsrOptionAckReqHeader ackReq;
+  m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+  ackReq.SetAckId (m_ackId);
+
+  uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
+  DsrRoutingHeader newDsrRoutingHeader;
+  newDsrRoutingHeader.SetNextHeader (protocol);
+  newDsrRoutingHeader.SetMessageType (2);
+  newDsrRoutingHeader.SetSourceId (sourceId);
+  newDsrRoutingHeader.SetDestId (destinationId);
+  newDsrRoutingHeader.SetPayloadLength (length + 4);
+  newDsrRoutingHeader.AddDsrOption (sourceRoute);
+  newDsrRoutingHeader.AddDsrOption (ackReq);
+  dsrP->AddHeader (newDsrRoutingHeader);
+  // give the dsrP value to packet and then return
+  packet = dsrP;
+  return m_ackId;
+}
+
 void
-DsrRouting::SendPacket (DsrOptionSRHeader const &sourceRoute,
-                        Ipv4Address nextHop,
-                        uint8_t protocol)
+DsrRouting::SendPacket (Ptr<Packet> packet, Ipv4Address source, Ipv4Address nextHop, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << packet << source << nextHop << (uint32_t)protocol);
+  // Send out the data packet
+  m_ipv4Route = SetRoute (nextHop, m_mainAddress);
+  Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
+  m_ipv4Route->SetOutputDevice (dev);
+
+  uint32_t priority = GetPriority (DSR_DATA_PACKET);
+  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+  NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+  DsrNetworkQueueEntry newEntry (packet, source, nextHop, Simulator::Now (), m_ipv4Route);
+
+  if (dsrNetworkQueue->Enqueue (newEntry))
+    {
+      Scheduler (priority);
+    }
+  else
+    {
+      NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+    }
+}
+
+void
+DsrRouting::Scheduler (uint32_t priority)
+{
+  NS_LOG_FUNCTION (this);
+  PriorityScheduler (priority, true);
+}
+
+void
+DsrRouting::PriorityScheduler (uint32_t priority, bool continueWithFirst)
 {
-  NS_LOG_FUNCTION (this << (uint32_t)protocol);
+  NS_LOG_FUNCTION (this << priority << continueWithFirst);
+  NS_LOG_DEBUG ("Scheduler looking for packets in network queue");
+  uint32_t numPriorities;
+  if (continueWithFirst)
+    {
+      numPriorities = 0;
+    }
+  else
+    {
+      numPriorities = priority;
+    }
+  // priorities range from 0 to m_numPriorityQueues, with 0 as the highest priority
+  for (uint32_t i = priority; numPriorities < m_numPriorityQueues; numPriorities++)
+  {
+    std::map<uint32_t, Ptr<DsrNetworkQueue> >::iterator q = m_priorityQueue.find (i);
+    Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = q->second;
+    uint32_t queueSize = dsrNetworkQueue->GetSize ();
+    if (queueSize == 0)
+    {
+      if ((i == (m_numPriorityQueues - 1)) && continueWithFirst)
+      {
+        i = 0;
+      }
+      else
+      {
+        i++;
+      }
+    }
+    else
+    {
+      uint32_t totalQueueSize;
+      for (std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator j = m_priorityQueue.begin (); j != m_priorityQueue.end (); j++)
+        {
+          NS_LOG_DEBUG ("The size of the network queue for " << j->first << " is " << j->second->GetSize());
+          totalQueueSize += j->second->GetSize ();
+          NS_LOG_DEBUG ("And the total size is " << totalQueueSize);
+        }
+      if (totalQueueSize > 5)
+        {
+          // Here the queue size is larger than 5, we need to increase the retransmission timer for each packet in the network queue
+          IncreaseRetransTimer ();
+        }
+      DsrNetworkQueueEntry newEntry;
+      dsrNetworkQueue->Dequeue (newEntry);
+      if (SendRealDown (newEntry))
+      {
+        NS_LOG_DEBUG("Packet sent by Dsr. Calling PriorityScheduler after some time");
+        //packet was successfully sent down. call scheduler after some time
+        Simulator::Schedule (MicroSeconds (UniformVariable ().GetInteger (0, 1000)),
+            &DsrRouting::PriorityScheduler,this, i, false);
+      }
+      else
+      {
+        // packet was dropped by Dsr. Call scheduler immediately so that we can
+        // send another packet immediately.
+        NS_LOG_DEBUG("Packet dropped by Dsr. Calling PriorityScheduler immediately");
+        Simulator::Schedule (Seconds (0), &DsrRouting::PriorityScheduler, this, i, false);
+      }
+      if ((i == (m_numPriorityQueues - 1)) && continueWithFirst)
+      {
+        i = 0;
+      }
+      else
+      {
+        i++;
+      }
+    }
+  }
+}
+
+void
+DsrRouting::IncreaseRetransTimer ()
+{
+  NS_LOG_FUNCTION (this);
+  // We may want to get the queue first and then we need to save a vector of the entries here and then find
+  uint32_t priority = GetPriority (DSR_DATA_PACKET);
+  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+
+  std::vector<DsrNetworkQueueEntry> newNetworkQueue = dsrNetworkQueue->GetQueue ();
+  for (std::vector<DsrNetworkQueueEntry>::iterator i = newNetworkQueue.begin (); i != newNetworkQueue.end (); i++)
+    {
+      Ipv4Address nextHop = i->GetNextHopAddress ();
+      for (std::map<NetworkKey, Timer>::iterator j = m_addressForwardTimer.begin (); j != m_addressForwardTimer.end (); j++)
+        {
+          if (nextHop == j->first.m_nextHop)
+            {
+              NS_LOG_DEBUG ("The network delay left is " << j->second.GetDelayLeft());
+              j->second.SetDelay (j->second.GetDelayLeft () + m_retransIncr);
+              NS_LOG_DEBUG ("The new network delay time is " << j->second.GetDelayLeft ());
+            }
+        }
+    }
+}
+
+bool
+DsrRouting::SendRealDown (DsrNetworkQueueEntry & newEntry)
+{
+  NS_LOG_FUNCTION (this);
+  Ipv4Address source = newEntry.GetSourceAddress ();
+  Ipv4Address nextHop = newEntry.GetNextHopAddress ();
+  Ptr<Packet> packet = newEntry.GetPacket ()->Copy ();
+  Ptr<Ipv4Route> route = newEntry.GetIpv4Route ();
+  m_downTarget (packet, source, nextHop, GetProtocolNumber(), route);
+  return true;
+}
+
+void
+DsrRouting::SendPacketFromBuffer (DsrOptionSRHeader const &sourceRoute, Ipv4Address nextHop, uint8_t protocol)
+{
+  NS_LOG_FUNCTION (this << nextHop << (uint32_t)protocol);
   NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
 
   // Reconstruct the route and Retransmit the data packet
@@ -1261,6 +1620,9 @@
 
   NS_LOG_INFO ("The nexthop address " << nextHop << " the source " << source << " the destination " << destination);
 
+  /*
+   * Here we try to find data packet from send buffer, if packet with this destiantion found, send it out
+   */
   if (m_sendBuffer.Find (destination))
     {
       SendBuffEntry entry;
@@ -1269,8 +1631,86 @@
           Ptr<Packet> packet = entry.GetPacket ()->Copy ();
           NS_LOG_DEBUG ("The queued packet size " << packet->GetSize ());
 
+          NS_LOG_DEBUG ("This is the data packet");
+          Ptr<Packet> p = packet->Copy ();      // get a copy of the packet
+          // Set the source route option
+          DsrRoutingHeader dsrRoutingHeader;
+          dsrRoutingHeader.SetNextHeader (protocol);
+          dsrRoutingHeader.SetMessageType (2);
+          dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
+          dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
+
+          uint8_t length = sourceRoute.GetLength ();
+          dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
+          dsrRoutingHeader.AddDsrOption (sourceRoute);
+
+          p->AddHeader (dsrRoutingHeader);
+          // Send the data packet out before schedule the next packet transmission
+          NS_LOG_DEBUG ("Send out the data packet");
+          SendPacket (p, source, nextHop, protocol);
+
+          Ptr<const Packet> mtP = p->Copy ();
+          // Put the data packet in the maintenance queue for data packet retransmission
+          MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
+                                                  /*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
+                                                  /*SegsLeft=*/nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
+          bool result = m_maintainBuffer.Enqueue (newEntry);       // Enqueue the packet the the maintenance buffer
+
+          if (result)
+            {
+              NetworkKey networkKey;
+              networkKey.m_ackId = newEntry.GetAckId ();
+              networkKey.m_ourAdd = newEntry.GetOurAdd ();
+              networkKey.m_nextHop = newEntry.GetNextHop ();
+              networkKey.m_source = newEntry.GetSrc ();
+              networkKey.m_destination = newEntry.GetDst ();
+
+              PassiveKey passiveKey;
+              passiveKey.m_ackId = 0;
+              passiveKey.m_source = newEntry.GetSrc ();
+              passiveKey.m_destination = newEntry.GetDst ();
+              passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
+
+              m_addressForwardCnt[networkKey] = 0;
+              m_passiveCnt[passiveKey] = 0;
+              if (nextHop != destination)
+                {
+                  SchedulePassivePacketRetry (newEntry, false, protocol);
+                }
+              else
+                {
+                  // This is the first network retry
+                  ScheduleNetworkPacketRetry (newEntry, true, 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::SendPacketFromBuffer,this,sourceRoute,nextHop,protocol);
+            }
+        }
+      else
+        {
+          NS_LOG_DEBUG ("All queued packets are out-dated for the destination in send buffer");
+        }
+    }
+  /*
+   * Here we try to find data packet from send buffer, if packet with this destiantion found, send it out
+   */
+  else if (m_errorBuffer.Find (destination))
+    {
+      ErrorBuffEntry entry;
+      if (m_errorBuffer.Dequeue (destination, entry))
+        {
+          Ptr<Packet> packet = entry.GetPacket ()->Copy ();
+          NS_LOG_DEBUG ("The queued packet size " << packet->GetSize ());
+
           DsrRoutingHeader dsrRoutingHeader;
           Ptr<Packet> copyP = packet->Copy ();
+          Ptr<Packet> dsrPacket = packet->Copy ();
+          dsrPacket->RemoveHeader (dsrRoutingHeader);
           uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
           copyP->RemoveAtStart (offset);       // Here the processed size is 8 bytes, which is the fixed sized extension header
           /*
@@ -1282,14 +1722,18 @@
 
           uint8_t optionType = 0;
           optionType = *(data);
+          NS_LOG_DEBUG ("The option type value in send packet " << (uint32_t)optionType);
           if (optionType == 3)
             {
+              NS_LOG_DEBUG ("The packet is error packet");
               Ptr<dsr::DsrOptions> dsrOption;
               DsrOptionHeader dsrOptionHeader;
 
               uint8_t errorType = *(data + 2);
+              NS_LOG_DEBUG ("The error type");
               if (errorType == 1)
                 {
+                  NS_LOG_DEBUG ("The packet is route error unreach packet");
                   DsrOptionRerrUnreachHeader rerr;
                   copyP->RemoveHeader (rerr);
                   NS_ASSERT (copyP->GetSize () == 0);
@@ -1300,6 +1744,7 @@
                   newUnreach.SetErrorSrc (rerr.GetErrorSrc ());
                   newUnreach.SetUnreachNode (rerr.GetUnreachNode ());
                   newUnreach.SetErrorDst (rerr.GetErrorDst ());
+                  newUnreach.SetOriginalDst (rerr.GetOriginalDst ());
                   newUnreach.SetSalvage (rerr.GetSalvage ());       // Set the value about whether to salvage a packet or not
 
                   std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
@@ -1308,7 +1753,7 @@
                   newRoutingHeader.SetMessageType (1);
                   newRoutingHeader.SetSourceId (GetIDfromIP (rerr.GetErrorSrc ()));
                   newRoutingHeader.SetDestId (GetIDfromIP (rerr.GetErrorDst ()));
-                  newRoutingHeader.SetPayloadLength (length + 4);
+                  newRoutingHeader.SetPayloadLength (uint16_t(length) + 4);
                   newRoutingHeader.AddDsrOption (newUnreach);
                   newRoutingHeader.AddDsrOption (sourceRoute);
                   if (m_routeCache->IsLinkCache ())
@@ -1320,90 +1765,62 @@
                   newPacket->AddHeader (newRoutingHeader);       // Add the extension header with rerr and sourceRoute attached to it
                   Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
                   m_ipv4Route->SetOutputDevice (dev);
-                  m_downTarget (newPacket, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route);
-                }
-            }
-          else
-            {
-              Ptr<Packet> p = packet->Copy ();      // get a copy of the packet
-              // Set the source route option
-              dsrRoutingHeader.SetNextHeader (protocol);
-              dsrRoutingHeader.SetMessageType (2);
-              dsrRoutingHeader.SetSourceId (GetIDfromIP (source));
-              dsrRoutingHeader.SetDestId (GetIDfromIP (destination));
 
-              DsrOptionAckReqHeader ackReq;
-              m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
-              ackReq.SetAckId (m_ackId);
+                  uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
+                  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+                  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+                  NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
 
-              uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
-              dsrRoutingHeader.SetPayloadLength (length + 4);
-              dsrRoutingHeader.AddDsrOption (sourceRoute);
-              dsrRoutingHeader.AddDsrOption (ackReq);
+                  DsrNetworkQueueEntry newEntry (newPacket, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
 
-              p->AddHeader (dsrRoutingHeader);
-              Ptr<const Packet> mtP = p->Copy ();
-              // Put the data packet in the maintenance queue for data packet retransmission
-              MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
-                                                      /*source=*/ source, /*destination=*/ destination, /*ackId=*/ m_ackId,
-                                                      /*SegsLeft=*/ nodeList.size () - 2, /*expire time=*/ m_maxMaintainTime);
-              bool result = m_maintainBuffer.Enqueue (newEntry);       // Enqueue the packet the the maintenance buffer
-
-              if (result)
-                {
-                  // Send out data packet
-                  NS_LOG_DEBUG ("Send out packet with ack id " << m_ackId);
-                  // Schedule the packet retry timer
-                  PacketKey packetKey;
-                  packetKey.m_ackId = newEntry.GetAckId ();
-                  packetKey.m_ourAdd = newEntry.GetOurAdd ();
-                  packetKey.m_nextHop = newEntry.GetNextHop ();
-                  packetKey.m_source = newEntry.GetSrc ();
-                  packetKey.m_destination = newEntry.GetDst ();
-                  packetKey.m_segsLeft = newEntry.GetSegsLeft ();
-                  PacketKey networkKey = packetKey;
-                  networkKey.m_segsLeft = 0;
-                  m_addressForwardCnt[networkKey] = 0;
-                  SchedulePacketRetry (newEntry, packetKey, protocol);
+                  if (dsrNetworkQueue->Enqueue (newEntry))
+                    {
+                      Scheduler (priority);
+                    }
+                  else
+                    {
+                      NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+                    }
                 }
             }
 
-          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");
+        if (m_errorBuffer.GetSize () != 0 && m_errorBuffer.Find (destination))
+          {
+            NS_LOG_DEBUG ("Schedule sending the next packet in send buffer");
+            Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
+                                 &DsrRouting::SendPacketFromBuffer,this,sourceRoute,nextHop,protocol);
+          }
         }
     }
   else
     {
-      NS_LOG_DEBUG ("Packet not found in send buffer");
+      NS_LOG_DEBUG ("Packet not found in either the send or error buffer");
     }
 }
 
 bool
-DsrRouting::FindSamePackets (Ptr<Packet> packet, Ipv4Header const& ipv4Header, Ipv4Address source, Ipv4Address destination,
+DsrRouting::FindSamePackets (Ptr<Packet> packet, 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 ();
+  NS_LOG_FUNCTION (this << packet << source << destination << (uint32_t)segsLeft);
 
   Ptr<Packet> p = packet->Copy ();
-  MaintainBuffEntry newEntry (/*Packet=*/ p, /*Ipv4Address=*/ ourAdd, /*nextHop=*/ nextHop,
-                                          /*source=*/ source, /*destination=*/ destination, /*ackId=*/ 0,
-                                          /*SegsLeft=*/ segsLeft, /*expire time=*/ m_maxMaintainTime);
-  // Temporarily disable passive acknowledgment
-//  CancelPassivePacketTimer (newEntry);
-  return true;
+  // Here the segments left value need to plus one to check the earlier hop maintain buffer entry
+  MaintainBuffEntry newEntry;
+  newEntry.SetPacket (p);
+  newEntry.SetSrc (source);
+  newEntry.SetDst (destination);
+  newEntry.SetAckId (0);
+  newEntry.SetSegsLeft (segsLeft + 1);
+
+  if (m_maintainBuffer.PromiscEqual (newEntry))
+    {
+      // The PromiscEqual function will remove the maintain buffer entry if equal value found
+      // It only compares the source and destination address, ackId, and the segments left value
+      CancelPassivePacketTimer (newEntry);
+      return true;
+    }
+  return false;
 }
 
 void
@@ -1418,8 +1835,8 @@
    */
   Ptr<Packet> mainP = Create<Packet> ();
   MaintainBuffEntry newEntry (/*Packet=*/ mainP, /*ourAddress=*/ sender, /*nextHop=*/ receiver,
-                                          /*source=*/ realSrc, /*destination=*/ realDst, /*ackId=*/ ackId,
-                                          /*SegsLeft=*/ 0, /*expire time=*/ Simulator::Now ());
+                              /*source=*/ realSrc, /*destination=*/ realDst, /*ackId=*/ ackId,
+                              /*SegsLeft=*/0, /*expire time=*/ Simulator::Now ());
   CancelNetworkPacketTimer (newEntry);
 }
 
@@ -1427,77 +1844,75 @@
 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;
+  NetworkKey networkKey;
+  networkKey.m_ackId = mb.GetAckId ();
+  networkKey.m_ourAdd = mb.GetOurAdd ();
+  networkKey.m_nextHop = mb.GetNextHop ();
+  networkKey.m_source = mb.GetSrc ();
+  networkKey.m_destination = mb.GetDst ();
   /*
    * 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);
+  m_addressForwardCnt[networkKey] = 0;
+  m_addressForwardCnt.erase (networkKey);
 
   NS_LOG_INFO ("ackId " << mb.GetAckId () << " ourAdd " << mb.GetOurAdd () << " nextHop " << mb.GetNextHop ()
                         << " source " << mb.GetSrc () << " destination " << mb.GetDst ()
                         << " segsLeft " << (uint32_t)mb.GetSegsLeft ()
-               );
+                        );
   // Find the network acknowledgment timer
-  std::map<PacketKey, Timer>::const_iterator i =
-    m_addressForwardTimer.find (packetKey);
+  std::map<NetworkKey, Timer>::const_iterator i =
+      m_addressForwardTimer.find (networkKey);
   if (i == m_addressForwardTimer.end ())
     {
-      NS_LOG_DEBUG ("did not find the packet timer");
+      NS_LOG_INFO ("did not find the packet timer");
     }
   else
     {
-      NS_LOG_DEBUG ("did find the packet timer");
+      NS_LOG_INFO ("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 ())
+      m_addressForwardTimer[networkKey].Cancel ();
+      m_addressForwardTimer[networkKey].Remove ();
+      if (m_addressForwardTimer[networkKey].IsRunning ())
         {
-          NS_LOG_DEBUG ("Timer not canceled");
+          NS_LOG_INFO ("Timer not canceled");
         }
-      m_addressForwardTimer.erase (packetKey);
+      m_addressForwardTimer.erase (networkKey);
     }
-  // Erase the maintenance entry
-  if (m_maintainBuffer.AllEqual (mb))
-    {
-      NS_LOG_DEBUG ("Remove same maintenance buffer entry based on network acknowledgment");
-    }
+    // Erase the maintenance entry
+    // yet this does not check the segments left value here
+    if (m_maintainBuffer.NetworkEqual (mb))
+      {
+        NS_LOG_INFO ("Remove same maintenance buffer entry based on network acknowledgment");
+      }
 }
 
 void
 DsrRouting::CancelPassivePacketTimer (MaintainBuffEntry & mb)
 {
   NS_LOG_FUNCTION (this);
-  PacketKey passiveKey;
+  PassiveKey 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);
+  m_passiveCnt[passiveKey] = 0;
+  m_passiveCnt.erase (passiveKey);
 
   // Find the passive acknowledgment timer
-  std::map<PacketKey, Timer>::const_iterator j =
-    m_passiveAckTimer.find (passiveKey);
+  std::map<PassiveKey, Timer>::const_iterator j =
+      m_passiveAckTimer.find (passiveKey);
   if (j == m_passiveAckTimer.end ())
     {
-      NS_LOG_DEBUG ("did not find the passive timer");
+      NS_LOG_INFO ("did not find the passive timer");
     }
   else
     {
-      NS_LOG_DEBUG ("find the passive timer");
+      NS_LOG_INFO ("find the passive timer");
       /*
        * Cancel passive acknowledgment timer
        */
@@ -1505,15 +1920,10 @@
       m_passiveAckTimer[passiveKey].Remove ();
       if (m_passiveAckTimer[passiveKey].IsRunning ())
         {
-          NS_LOG_DEBUG ("Timer not canceled");
+          NS_LOG_INFO ("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
@@ -1534,15 +1944,14 @@
 
       if (m_maintainBuffer.GetSize () && m_maintainBuffer.Find (nextHop))
         {
-          NS_LOG_DEBUG ("Cancel the packet timer for next maintenance entry");
-
+          NS_LOG_INFO ("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");
+      NS_LOG_INFO ("Maintenance buffer entry not found");
     }
 }
 
@@ -1550,10 +1959,6 @@
 DsrRouting::SalvagePacket (Ptr<const Packet> packet, Ipv4Address source, Ipv4Address dst, uint8_t protocol)
 {
   NS_LOG_FUNCTION (this << packet << source << dst << (uint32_t)protocol);
-  /*
-   * Look in the route cache for other routes for this destination
-   */
-  RouteCacheEntry toDst;
   // Create two copies of packet
   Ptr<Packet> p = packet->Copy ();
   Ptr<Packet> newPacket = packet->Copy ();
@@ -1573,9 +1978,10 @@
   sourceRoute.SetNumberAddress (numberAddress);
   newPacket->RemoveHeader (sourceRoute);
   uint8_t salvage = sourceRoute.GetSalvage ();
-
-  NS_LOG_DEBUG ("The salvage value get from remove headers " << (uint32_t)salvage);
-
+  /*
+   * Look in the route cache for other routes for this destination
+   */
+  RouteCacheEntry toDst;
   bool findRoute = m_routeCache->LookupRoute (dst, toDst);
   if (findRoute && (salvage < m_maxSalvageCount))
     {
@@ -1598,19 +2004,19 @@
       DsrOptionSRHeader sourceRoute;
       sourceRoute.SetSalvage (salvage);
       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
+      DsrOptionAckReqHeader ackReq;
+      m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
+      ackReq.SetAckId (m_ackId);
       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.SetPayloadLength (uint16_t(length) + 4);
       newDsrRoutingHeader.AddDsrOption (sourceRoute);
       newDsrRoutingHeader.AddDsrOption (ackReq);
       p->AddHeader (newDsrRoutingHeader);
@@ -1619,7 +2025,22 @@
       Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
       m_ipv4Route->SetOutputDevice (dev);
       // Send out the data packet
-      m_downTarget (p, m_mainAddress, nextHop, GetProtocolNumber (), m_ipv4Route);
+
+      uint32_t priority = GetPriority (DSR_DATA_PACKET);
+      std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+      Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+      NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+      DsrNetworkQueueEntry newEntry (p, m_mainAddress, nextHop, Simulator::Now (), m_ipv4Route);
+
+      if (dsrNetworkQueue->Enqueue (newEntry))
+        {
+          Scheduler (priority);
+        }
+      else
+        {
+          NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+        }
       /*
        * Mark the next hop address in blacklist
        */
@@ -1633,66 +2054,106 @@
 }
 
 void
-DsrRouting::SchedulePacketRetry (MaintainBuffEntry & mb,
-                                 PacketKey const & packetKey,
-                                 uint8_t protocol)
+DsrRouting::SchedulePassivePacketRetry (MaintainBuffEntry & mb,
+                                        bool onlyPassive,
+                                        uint8_t protocol)
 {
-  NS_LOG_FUNCTION (this << (uint32_t)protocol);
+  NS_LOG_FUNCTION (this << onlyPassive << (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;
+  PassiveKey passiveKey;
+  passiveKey.m_ackId = 0;
+  passiveKey.m_source = mb.GetSrc ();
+  passiveKey.m_destination = mb.GetDst ();
+  passiveKey.m_segsLeft = mb.GetSegsLeft ();
 
-  if (isPassive && nextHop != dst)
+  if (m_passiveAckTimer.find (passiveKey) == m_passiveAckTimer.end ())
     {
-      // 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;
+      Timer timer (Timer::CANCEL_ON_DESTROY);
+      m_passiveAckTimer[passiveKey] = timer;
     }
-  else
+  NS_LOG_DEBUG ("The passive acknowledgment option for data packet");
+  m_passiveAckTimer[passiveKey].SetFunction (&DsrRouting::PassiveScheduleTimerExpire, this);
+  m_passiveAckTimer[passiveKey].Remove ();
+  m_passiveAckTimer[passiveKey].SetArguments (mb, onlyPassive, protocol);
+  m_passiveAckTimer[passiveKey].Schedule (m_passiveAckTimeout);
+}
+
+void
+DsrRouting::ScheduleNetworkPacketRetry (MaintainBuffEntry & mb,
+                                        bool isFirst,
+                                        uint8_t protocol)
+{
+  Ptr<Packet> p = Create<Packet> ();
+  Ptr<Packet> dsrP = Create<Packet> ();
+  // The new entry will be used for retransmission
+  NetworkKey networkKey;
+  Ipv4Address nextHop = mb.GetNextHop ();
+  Ipv4Address source = mb.GetSrc ();
+  Ipv4Address dst = mb.GetDst ();
+  NS_LOG_DEBUG ("is the first retry or not " << isFirst);
+  if (isFirst)
     {
-      // There is no segments left value for network key, so 0 it
-      networkKey.m_segsLeft = 0;
+      // This is the very first network packet retry
+      p = mb.GetPacket ()->Copy ();
+      // Here we add the ack request header to the data packet for network acknowledgement
+      uint16_t ackId = AddAckReqHeader (p, nextHop);
+      dsrP = p->Copy ();
+      MaintainBuffEntry newEntry = mb;
+      // The function AllEqual will find the exact entry and delete it if found
+      m_maintainBuffer.AllEqual (mb);
+      newEntry.SetPacket (dsrP);
+      newEntry.SetAckId (ackId);
+      newEntry.SetExpireTime (m_maxMaintainTime);
+
+      networkKey.m_ackId = newEntry.GetAckId ();
+      networkKey.m_ourAdd = newEntry.GetOurAdd ();
+      networkKey.m_nextHop = newEntry.GetNextHop ();
+      networkKey.m_source = newEntry.GetSrc ();
+      networkKey.m_destination = newEntry.GetDst ();
+
+      m_addressForwardCnt[networkKey] = 0;
+      m_maintainBuffer.Enqueue (newEntry);
 
       if (m_addressForwardTimer.find (networkKey) == m_addressForwardTimer.end ())
         {
           Timer timer (Timer::CANCEL_ON_DESTROY);
           m_addressForwardTimer[networkKey] = timer;
         }
+
+      // After m_tryPassiveAcks, schedule the packet retransmission using network acknowledgment option
+      m_addressForwardTimer[networkKey].SetFunction (&DsrRouting::NetworkScheduleTimerExpire, this);
+      m_addressForwardTimer[networkKey].Remove ();
+      m_addressForwardTimer[networkKey].SetArguments (newEntry, protocol);
+      NS_LOG_DEBUG ("The packet retries time for " << newEntry.GetAckId() << " is " << m_sendRetries
+          << " and the delay time is " << Time (2 * m_nodeTraversalTime));
+      // Back-off mechanism
+      m_addressForwardTimer[networkKey].Schedule (Time (2 * m_nodeTraversalTime));
+    }
+  else
+    {
+      networkKey.m_ackId = mb.GetAckId ();
+      networkKey.m_ourAdd = mb.GetOurAdd ();
+      networkKey.m_nextHop = mb.GetNextHop ();
+      networkKey.m_source = mb.GetSrc ();
+      networkKey.m_destination = mb.GetDst ();
       /*
        * 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);
+
+      p = mb.GetPacket ()->Copy ();
+      dsrP = mb.GetPacket ()->Copy ();
+
+      NS_LOG_DEBUG ("The packet with dsr header " << dsrP->GetSize());
+      networkKey.m_ackId = mb.GetAckId ();
+      networkKey.m_ourAdd = mb.GetOurAdd ();
+      networkKey.m_nextHop = mb.GetNextHop ();
+      networkKey.m_source = mb.GetSrc ();
+      networkKey.m_destination = mb.GetDst ();
       /*
        *  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
@@ -1700,162 +2161,146 @@
        *
        *  The maxMaintRexmt also needs to decrease one for the passive ack packet
        */
-      Ptr<Packet> p = mb.GetPacket ()->Copy ();
-      Ptr<Packet> dsrP = p->Copy ();
-      Ptr<Packet> salP = p->Copy ();
-      Ptr<Packet> retransP = p->Copy ();
-      // The packet retries time has exceed the max maintenance retransmission times
-      if (m_sendRetries > m_maxMaintRexmt)
-        {
-          NS_LOG_LOGIC ("Packet transmissions to " << nextHop << " has been attempted SendRetries times for " << networkKey.m_ackId);
-          DsrRoutingHeader dsrRoutingHeader;
-          dsrP->RemoveHeader (dsrRoutingHeader);          // Remove the dsr header in whole
-          uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
-          p->RemoveAtStart (offset);
-
-          // Get the number of routers' address field
-          uint8_t buf[2];
-          p->CopyData (buf, sizeof(buf));
-          uint8_t numberAddress = (buf[1] - 2) / 4;
-          NS_LOG_DEBUG ("The number of addresses " << (uint32_t)numberAddress);
-          DsrOptionSRHeader sourceRoute;
-          sourceRoute.SetNumberAddress (numberAddress);
-          p->RemoveHeader (sourceRoute);
-          std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
-          uint8_t salvage = sourceRoute.GetSalvage ();
-          Ipv4Address address1 = nodeList.front ();
-          NS_LOG_DEBUG ("address1 " << address1);
+      /*
+       * Check if the send retry time for a certain packet has already passed max maintenance retransmission
+       * time or not
+       */
 
-          CutRoute (m_mainAddress, nodeList);
-          NS_LOG_DEBUG ("The route vector after cut and the route source " << nodeList.front ());
-//          PrintVector (nodeList);
-          // Delete the route cache entry
-          RouteCacheEntry toDst;
-          // Cancel the packet timer for maintenance buffer entry
-          CancelNetworkPacketTimer (mb);
-          /*
-           * Mark the next hop address in blacklist
-           */
-//          NS_LOG_DEBUG ("Save the next hop node in blacklist");
-//          m_rreqTable->MarkLinkAsUnidirectional (nextHop, m_blacklistTimeout);
-          // Delete all the routes including the links
-          m_routeCache->DeleteAllRoutesIncludeLink (m_mainAddress, nextHop, m_mainAddress);
-          // After deleting the broken link from all routes, need to salvage the packet right after dropping it
-          SalvagePacket (salP, source, dst, protocol);
-          /*
-           * If the salvage is not 0, use the first address in the route as the error dst in error header
-           * otherwise use the source of packet as the error destination
-           */
-          if (salvage)
-            {
-              if (address1 == m_mainAddress)
-                {
-                  DsrOptionRerrUnreachHeader rerr;
-                  rerr.SetErrorType (1);
-                  rerr.SetErrorSrc (address1);
-                  rerr.SetUnreachNode (nextHop);
-                  rerr.SetErrorDst (address1);
-                  rerr.SetSalvage (salvage);       // Set the value about whether to salvage a packet or not
-                  SendErrorRequest (rerr, protocol);
-                }
-              else
-                {
-                  SendUnreachError (nextHop, address1, salvage, protocol);
-                }
-            }
-          else
-            {
-              if (source == m_mainAddress)
-                {
-                  DsrOptionRerrUnreachHeader rerr;
-                  rerr.SetErrorType (1);
-                  rerr.SetErrorSrc (source);
-                  rerr.SetUnreachNode (nextHop);
-                  rerr.SetErrorDst (source);
-                  rerr.SetSalvage (salvage);     // Set the value about whether to salvage a packet or not
-                  SendErrorRequest (rerr, protocol);
-                }
-              else
-                {
-                  SendUnreachError (nextHop, source, salvage, protocol);
-                }
-            }
-          CancelPacketTimerNextHop (nextHop, protocol);
-        }
-      else
-        {
-          m_sendRetries++;
-          // Send out the retransmission packet
-          m_ipv4Route = SetRoute (nextHop, m_mainAddress);
-          Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
-          m_ipv4Route->SetOutputDevice (dev);
-          m_downTarget (retransP, source, nextHop, GetProtocolNumber (), m_ipv4Route);
-          // After m_tryPassiveAcks, schedule the packet retransmission using network acknowledgment option
-          m_addressForwardTimer[networkKey].SetFunction (&DsrRouting::PacketScheduleTimerExpire, this);
-          m_addressForwardTimer[networkKey].Remove ();
-          m_addressForwardTimer[networkKey].SetArguments (mb, networkKey, protocol, false);
-          // forward count
-          m_addressForwardCnt[networkKey] = m_sendRetries;
-          NS_LOG_DEBUG ("The packet retries time for " << mb.GetAckId () << " is " << m_sendRetries);
-          // Back-off mechanism
-          m_addressForwardTimer[networkKey].Schedule (Time (2 * m_sendRetries *  m_nodeTraversalTime));
-        }
+      // After m_tryPassiveAcks, schedule the packet retransmission using network acknowledgment option
+      m_addressForwardTimer[networkKey].SetFunction (&DsrRouting::NetworkScheduleTimerExpire, this);
+      m_addressForwardTimer[networkKey].Remove ();
+      m_addressForwardTimer[networkKey].SetArguments (mb, protocol);
+      NS_LOG_DEBUG ("The packet retries time for " << mb.GetAckId() << " is " << m_sendRetries
+          << " and the delay time is " << Time (2 * m_sendRetries *  m_nodeTraversalTime));
+      // Back-off mechanism
+      m_addressForwardTimer[networkKey].Schedule (Time (2 * m_sendRetries * m_nodeTraversalTime));
     }
-  return;
 }
 
 void
-DsrRouting::AddAckReqHeader (Ptr<Packet> packet, DsrOptionSRHeader const &sourceRoute, Ipv4Address nextHop)
+DsrRouting::PassiveScheduleTimerExpire  (MaintainBuffEntry & mb,
+                                         bool onlyPassive,
+                                         uint8_t protocol)
 {
-  NS_LOG_FUNCTION (this << packet << nextHop);
-  // This packet is used to peek option type
-  Ptr<Packet> cleanP = packet->Copy ();
-
-  DsrOptionAckReqHeader ackReq;
-  m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
-  ackReq.SetAckId (m_ackId);
-
-  uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
-  DsrRoutingHeader dsrRoutingHeader;
-  dsrRoutingHeader.SetPayloadLength (length + 4);
-  dsrRoutingHeader.AddDsrOption (sourceRoute);
-  dsrRoutingHeader.AddDsrOption (ackReq);
-  cleanP->AddHeader (dsrRoutingHeader);
-}
-
-void
-DsrRouting::PacketScheduleTimerExpire  (MaintainBuffEntry & mb,
-                                        PacketKey const & pk,
-                                        uint8_t protocol,
-                                        bool isPassive)
-{
-  NS_LOG_FUNCTION (this << (uint32_t)protocol << isPassive);
+  NS_LOG_FUNCTION (this << onlyPassive << (uint32_t)protocol);
   Ipv4Address nextHop = mb.GetNextHop ();
   Ipv4Address source = mb.GetSrc ();
   Ipv4Address dst = mb.GetDst ();
   Ptr<const Packet> packet = mb.GetPacket ();
   SetRoute (nextHop, m_mainAddress);
   Ptr<Packet> p = packet->Copy ();
-  if (isPassive)
+
+  PassiveKey pk;
+  pk.m_ackId = 0;
+  pk.m_source = mb.GetSrc ();
+  pk.m_destination = mb.GetDst ();
+  pk.m_segsLeft = mb.GetSegsLeft ();
+
+  // Cancel passive ack timer
+  m_passiveAckTimer[pk].Cancel ();
+  m_passiveAckTimer[pk].Remove ();
+  if (m_passiveAckTimer[pk].IsRunning ())
     {
-      // 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);
+      NS_LOG_DEBUG ("Timer not canceled");
+    }
+  m_passiveAckTimer.erase (pk);
+  // Send the data packet out before schedule the next packet transmission
+  SendPacket (p, source, nextHop, protocol);
+  // Increase the send retry times
+  m_passiveRetries = m_passiveCnt[pk];
+  if (m_passiveRetries < m_tryPassiveAcks)
+    {
+      m_passiveCnt[pk] = ++m_passiveRetries;
+      SchedulePassivePacketRetry (mb, onlyPassive, protocol);
+    }
+  else if (!onlyPassive)
+    {
+      // This is the first network acknowledgement retry
+      // Cancel the passive packet timer now and remove maintenance buffer entry for it
+      CancelPassivePacketTimer (mb);
+      ScheduleNetworkPacketRetry (mb, true, protocol);
     }
   else
     {
-      mb.SetPassive (false);
-      SchedulePacketRetry (mb, pk, protocol);
+      // This is the end of the data retransmission retries
+      CancelPassivePacketTimer (mb);
+      // The function AllEqual will find the exact entry and delete it if found
+      m_maintainBuffer.AllEqual (mb);
     }
-  return;
+}
+
+void
+DsrRouting::NetworkScheduleTimerExpire  (MaintainBuffEntry & mb,
+                                         uint8_t protocol)
+{
+  Ptr<Packet> p = mb.GetPacket ()->Copy ();
+  Ipv4Address source = mb.GetSrc ();
+  Ipv4Address nextHop = mb.GetNextHop ();
+  Ipv4Address dst = mb.GetDst ();
+
+  NetworkKey networkKey;
+  networkKey.m_ackId = mb.GetAckId ();
+  networkKey.m_ourAdd = mb.GetOurAdd ();
+  networkKey.m_nextHop = nextHop;
+  networkKey.m_source = source;
+  networkKey.m_destination = dst;
+
+  // Send the data packet out before schedule the next packet transmission
+  SendPacket (p, source, nextHop, protocol);
+  // Increase the send retry times
+  m_sendRetries = m_addressForwardCnt[networkKey];
+  NS_LOG_DEBUG ("The send retry time is " << m_sendRetries);
+  if (m_sendRetries >= m_maxMaintRexmt)
+    {
+      Ptr<Packet> dsrP = mb.GetPacket ()->Copy ();
+      // The packet retries time has exceed the max maintenance retransmission times
+      NS_LOG_LOGIC ("Packet transmissions to " << nextHop << " has been attempted SendRetries times for " << networkKey.m_ackId);
+      DsrRoutingHeader dsrRoutingHeader;
+      dsrP->RemoveHeader (dsrRoutingHeader);          // Remove the dsr header in whole
+      uint32_t offset = dsrRoutingHeader.GetDsrOptionsOffset ();
+      p->RemoveAtStart (offset);
+
+      // Get the number of routers' address field
+      uint8_t buf[2];
+      p->CopyData (buf, sizeof(buf));
+      uint8_t numberAddress = (buf[1] - 2) / 4;
+      NS_LOG_DEBUG ("The number of addresses " << (uint32_t)numberAddress);
+      DsrOptionSRHeader sourceRoute;
+      sourceRoute.SetNumberAddress (numberAddress);
+      p->RemoveHeader (sourceRoute);
+      std::vector<Ipv4Address> nodeList = sourceRoute.GetNodesAddress ();
+      uint8_t salvage = sourceRoute.GetSalvage ();
+      Ipv4Address address1 = nodeList[1];
+      NS_LOG_DEBUG ("address1 " << address1);
+      PrintVector (nodeList);
+
+      // Delete all the routes including the links
+      m_routeCache->DeleteAllRoutesIncludeLink (m_mainAddress, 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
+       */
+      Ipv4Address errorDst;
+      if (salvage)
+        {
+          errorDst = address1;
+        }
+      else
+        {
+          errorDst = source;
+        }
+      SendUnreachError (nextHop, errorDst, dst, salvage, protocol);
+      /*
+       * here we cancel the packet retransmission time for all the packets have next hop address as nextHop
+       * Also salvage the packet for the all the packet destined for the nextHop address
+       */
+      CancelPacketTimerNextHop (nextHop, protocol);
+    }
+  else
+    {
+      m_addressForwardCnt[networkKey] = ++m_sendRetries;
+      ScheduleNetworkPacketRetry (mb, false, protocol);
+    }
 }
 
 void
@@ -1879,36 +2324,47 @@
 
   // We get the salvage value in sourceRoute header and set it to route error header if triggered error
   Ptr<Packet> p = packet->Copy ();
-  DsrOptionAckReqHeader ackReq;
-  m_ackId = m_routeCache->CheckUniqueAckId (nextHop);
-  ackReq.SetAckId (m_ackId);
+  uint8_t length = sourceRoute.GetLength ();
+  dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
+  dsrRoutingHeader.AddDsrOption (sourceRoute);
+  p->AddHeader (dsrRoutingHeader);
 
-  uint8_t length = (sourceRoute.GetLength () + ackReq.GetLength ());
-  dsrRoutingHeader.SetPayloadLength (length + 4);
-  dsrRoutingHeader.AddDsrOption (sourceRoute);
-  dsrRoutingHeader.AddDsrOption (ackReq);
-  p->AddHeader (dsrRoutingHeader);
+  // Send the data packet out before schedule the next packet transmission
+  SendPacket (p, source, nextHop, protocol);
+
   Ptr<const Packet> mtP = p->Copy ();
 
   MaintainBuffEntry newEntry (/*Packet=*/ mtP, /*ourAddress=*/ m_mainAddress, /*nextHop=*/ nextHop,
                                           /*source=*/ source, /*destination=*/ targetAddress,
-                                          /*ackId=*/ m_ackId, /*SegsLeft=*/ sourceRoute.GetSegmentsLeft (), /*expire time=*/ m_maxMaintainTime);
+                                          /*ackId=*/ m_ackId, /*SegsLeft=*/sourceRoute.GetSegmentsLeft(), /*expire time=*/ m_maxMaintainTime);
   bool result = m_maintainBuffer.Enqueue (newEntry);
 
   if (result)
     {
-      Ptr<Packet> newPacket = p->Copy ();
-      PacketKey packetKey;
-      packetKey.m_ackId = newEntry.GetAckId ();
-      packetKey.m_ourAdd = newEntry.GetOurAdd ();
-      packetKey.m_nextHop = newEntry.GetNextHop ();
-      packetKey.m_source = newEntry.GetSrc ();
-      packetKey.m_destination = newEntry.GetDst ();
-      packetKey.m_segsLeft = newEntry.GetSegsLeft ();
-      PacketKey networkKey = packetKey;
-      networkKey.m_segsLeft = 0;
+      NetworkKey networkKey;
+      networkKey.m_ackId = newEntry.GetAckId ();
+      networkKey.m_ourAdd = newEntry.GetOurAdd ();
+      networkKey.m_nextHop = newEntry.GetNextHop ();
+      networkKey.m_source = newEntry.GetSrc ();
+      networkKey.m_destination = newEntry.GetDst ();
+
+      PassiveKey passiveKey;
+      passiveKey.m_ackId = 0;
+      passiveKey.m_source = newEntry.GetSrc ();
+      passiveKey.m_destination = newEntry.GetDst ();
+      passiveKey.m_segsLeft = newEntry.GetSegsLeft ();
+
       m_addressForwardCnt[networkKey] = 0;
-      SchedulePacketRetry (newEntry, packetKey, protocol);
+      m_passiveCnt[passiveKey] = 0;
+      if (nextHop != targetAddress)
+        {
+          SchedulePassivePacketRetry (newEntry, false, protocol);
+        }
+      else
+        {
+          // This is the first network retry
+          ScheduleNetworkPacketRetry (newEntry, true, protocol);
+        }
     }
 }
 
@@ -1931,24 +2387,32 @@
   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
+  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
+  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
+  dsrRoutingHeader.AddDsrOption (rreqHeader);                      // Add the rreqHeader to the dsr extension header
   uint8_t length = rreqHeader.GetLength ();
-  dsrRoutingHeader.SetPayloadLength (length + 2);
+  dsrRoutingHeader.SetPayloadLength (uint16_t(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);
+  std::vector<Ipv4Address> address;
+  address.push_back (source);
+  address.push_back (destination);
+  /*
+   * Add the socket ip ttl tag to the packet to limit the scope of route requests
+   */
+  SocketIpTtlTag tag;
+  tag.SetTtl (0);
+  Ptr<Packet> nonPropPacket = packet->Copy ();
+  nonPropPacket->AddPacketTag (tag);
+  SendRequest (nonPropPacket, source);
+  // Schedule the next route request
+  ScheduleRreqRetry (packet, address, nonProp, m_requestId, protocol);
 }
 
 void
@@ -1956,80 +2420,106 @@
 {
   NS_LOG_FUNCTION (this << (uint32_t)protocol);
   NS_ASSERT_MSG (!m_downTarget.IsNull (), "Error, DsrRouting cannot send downward");
-  Ptr<Packet> packet = Create<Packet> ();
-  Ipv4Address destination = rerr.GetErrorSrc ();
-  Ipv4Address unreachAddress = rerr.GetUnreachNode ();
-  // Create an empty route ptr
-  Ptr<Ipv4Route> route = 0;
-  /*
-   * Construct the route request option header
-   */
-  DsrRoutingHeader dsrRoutingHeader;
-  dsrRoutingHeader.SetNextHeader (protocol);
-  dsrRoutingHeader.SetMessageType (1);
-  dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
-  dsrRoutingHeader.SetDestId (255);
-
-  if (m_mainAddress != destination)
+  uint8_t salvage = rerr.GetSalvage ();
+  Ipv4Address dst = rerr.GetOriginalDst ();
+  NS_LOG_DEBUG ("our own address here " << m_mainAddress << " error source " << rerr.GetErrorSrc () << " error destination " << rerr.GetErrorDst ()
+      << " error next hop " << rerr.GetUnreachNode () << " original dst " << rerr.GetOriginalDst ()
+     );
+  RouteCacheEntry toDst;
+  if (m_routeCache->LookupRoute (dst, toDst))
     {
       /*
-       * Send error request to the error source
+       * Found a route the dst, construct the source route option header
        */
-      NS_LOG_DEBUG ("Send error packet to the error source");
+      DsrOptionSRHeader sourceRoute;
+      std::vector<Ipv4Address> ip = toDst.GetVector ();
+      sourceRoute.SetNodesAddress (ip);
+      if (m_routeCache->IsLinkCache ())
+        {
+          m_routeCache->UseExtends (ip);
+        }
+      sourceRoute.SetSegmentsLeft ((ip.size () - 2));
+      sourceRoute.SetSalvage (salvage);
+      Ipv4Address nextHop = SearchNextHop (m_mainAddress, ip);       // Get the next hop address
+      NS_LOG_DEBUG ("The nextHop address " << nextHop);
+      Ptr<Packet> packet = Create<Packet> ();
+      if (nextHop == "0.0.0.0")
+        {
+          NS_LOG_DEBUG ("Error next hop address");
+          PacketNewRoute (packet, m_mainAddress, dst, protocol);
+          return;
+        }
+      SetRoute (nextHop, m_mainAddress);
+      CancelRreqTimer (dst, true);
+      SendPacketFromBuffer (sourceRoute, nextHop, protocol);
+      NS_LOG_LOGIC ("Route to " << dst << " found");
+      return;
+    }
+  else
+    {
+      NS_LOG_INFO ("No route found, initiate route error request");
+      Ptr<Packet> packet = Create<Packet> ();
+      Ipv4Address unreachAddress = rerr.GetUnreachNode ();
+      Ipv4Address originalDst = rerr.GetOriginalDst ();
+      // Create an empty route ptr
+      Ptr<Ipv4Route> route = 0;
+      /*
+       * Construct the route request option header
+       */
+      DsrRoutingHeader dsrRoutingHeader;
+      dsrRoutingHeader.SetNextHeader (protocol);
+      dsrRoutingHeader.SetMessageType (1);
+      dsrRoutingHeader.SetSourceId (GetIDfromIP (m_mainAddress));
+      dsrRoutingHeader.SetDestId (255);
+
       Ptr<Packet> dstP = Create<Packet> ();
       DsrOptionRreqHeader rreqHeader;                                // has an alignment of 4n+0
       rreqHeader.AddNodeAddress (m_mainAddress);                     // Add our own address in the header
-      rreqHeader.SetTarget (destination);
-      m_requestId = m_rreqTable->CheckUniqueRreqId (destination);       // Check the Id cache for duplicate ones
+      rreqHeader.SetTarget (originalDst);
+      m_requestId = m_rreqTable->CheckUniqueRreqId (originalDst);       // 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);
+      dsrRoutingHeader.SetPayloadLength (uint16_t(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
-    {
+      std::vector<Ipv4Address> address;
+      address.push_back (m_mainAddress);
+      address.push_back (originalDst);
       /*
-       * Send error request to the unreachable node
+       * Add the socket ip ttl tag to the packet to limit the scope of route requests
        */
-      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);
+      SocketIpTtlTag tag;
+      tag.SetTtl ((uint8_t)m_discoveryHopLimit);
+      Ptr<Packet> propPacket = dstP->Copy ();
+      propPacket->AddPacketTag (tag);
 
-      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 ()))
+      if ((m_addressReqTimer.find (originalDst) == m_addressReqTimer.end ()) && (m_nonPropReqTimer.find (originalDst) == m_nonPropReqTimer.end ()))
+        {
+          NS_LOG_INFO ("Only when there is no existing route request time when the initial route request is scheduled");
+          SendRequest (propPacket, m_mainAddress);
+          ScheduleRreqRetry (dstP, address, nonProp, m_requestId, protocol);
+        }
+      else
         {
-          NS_LOG_DEBUG ("Only when there is no existing route request time when this one is triggered");
-          ScheduleRreqRetry (packet, m_mainAddress, unreachAddress, nonProp, protocol);
+          NS_LOG_INFO ("There is existing route request, find the existing route request entry");
+          /*
+           * Cancel the route request timer first before scheduling the route request
+           * in this case, we do not want to remove the route request entry, so the isRemove value is false
+           */
+          CancelRreqTimer (originalDst, false);
+          ScheduleRreqRetry (dstP, address, nonProp, m_requestId, protocol);
         }
     }
 }
 
 void
-DsrRouting::CancelRreqTimer (Ipv4Address dst)
+DsrRouting::CancelRreqTimer (Ipv4Address dst, bool isRemove)
 {
-  NS_LOG_FUNCTION (this << dst);
+  NS_LOG_FUNCTION (this << dst << isRemove);
   // Cancel the non propagation request timer if found
   if (m_nonPropReqTimer.find (dst) == m_nonPropReqTimer.end ())
     {
@@ -2064,35 +2554,37 @@
       NS_LOG_DEBUG ("Timer not canceled");
     }
   m_addressReqTimer.erase (dst);
-
-  // remove the route request entry from route request table
-  m_rreqTable->RemoveRreqEntry (dst);
+  /*
+   * If the route request is scheduled to remove the route request entry
+   * Remove the route request entry with the route retry times done for certain destination
+   */
+  if (isRemove)
+    {
+      // remove the route request entry from route request table
+      m_rreqTable->RemoveRreqEntry (dst);
+    }
 }
 
 void
-DsrRouting::ScheduleRreqRetry (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dst, bool nonProp, uint8_t protocol)
+DsrRouting::ScheduleRreqRetry (Ptr<Packet> packet, std::vector<Ipv4Address> address, bool nonProp, uint32_t requestId, uint8_t protocol)
 {
-  NS_LOG_FUNCTION (this << packet << source << dst << nonProp << (uint32_t)protocol);
+  NS_LOG_FUNCTION (this << packet << nonProp << requestId << (uint32_t)protocol);
+  Ipv4Address source = address[0];
+  Ipv4Address dst = address[1];
   if (nonProp)
     {
-      nonProp = false;
+      // The nonProp route request is only sent out only and is already used
       if (m_nonPropReqTimer.find (dst) == m_nonPropReqTimer.end ())
         {
           Timer timer (Timer::CANCEL_ON_DESTROY);
           m_nonPropReqTimer[dst] = timer;
         }
-      /*
-       * Add the socket ip ttl tag to the packet to limit the scope of route requests
-       */
-      SocketIpTtlTag tag;
-      tag.SetTtl (0);
-      Ptr<Packet> nonPropPacket = packet->Copy ();
-      nonPropPacket->AddPacketTag (tag);
-      SendRequest (nonPropPacket, source);
-      NS_LOG_DEBUG ("Check the route request entry3 " << source << " " << dst);
-      m_nonPropReqTimer[dst].SetFunction (&DsrRouting::ScheduleRreqRetry, this);
+      std::vector<Ipv4Address> address;
+      address.push_back (source);
+      address.push_back (dst);
+      m_nonPropReqTimer[dst].SetFunction (&DsrRouting::RouteRequestTimerExpire, this);
       m_nonPropReqTimer[dst].Remove ();
-      m_nonPropReqTimer[dst].SetArguments (packet, source, dst, nonProp, protocol);
+      m_nonPropReqTimer[dst].SetArguments (packet, address, requestId, protocol);
       m_nonPropReqTimer[dst].Schedule (m_nonpropRequestTimeout);
     }
   else
@@ -2105,43 +2597,57 @@
           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;
         }
+      std::vector<Ipv4Address> address;
+      address.push_back (source);
+      address.push_back (dst);
       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);
+      m_addressReqTimer[dst].SetArguments (packet, address, requestId, protocol);
+      Time rreqDelay;
       // back off mechanism for sending route requests
-      Time rreqDelay = Time (pow (m_rreqTable->GetRreqCnt (dst), 2) * m_requestPeriod);
+      if (m_rreqTable->GetRreqCnt (dst))
+        {
+          // When the route request count is larger than 0
+          rreqDelay = Time (pow (m_rreqTable->GetRreqCnt (dst), 2) * m_requestPeriod);
+        }
+      else
+        {
+          // This is the first route request retry
+          rreqDelay = 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 ());
+          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 ());
+          NS_LOG_DEBUG ("The request delay time " << rreqDelay.GetSeconds());
           m_addressReqTimer[dst].Schedule (rreqDelay);
         }
+
     }
 }
 
 void
-DsrRouting::RouteRequestTimerExpire (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dst, uint8_t protocol)
+DsrRouting::RouteRequestTimerExpire (Ptr<Packet> packet, std::vector<Ipv4Address> address, uint32_t requestId, uint8_t protocol)
 {
-  NS_LOG_FUNCTION (this << packet << source << dst << (uint32_t)protocol);
+  NS_LOG_FUNCTION (this << packet << requestId << (uint32_t)protocol);
+  // Get a clean packet without dsr header
+  Ptr<Packet> dsrP = packet->Copy ();
+  DsrRoutingHeader dsrRoutingHeader;
+  dsrP->RemoveHeader (dsrRoutingHeader);          // Remove the dsr header in whole
+
+  Ipv4Address source = address[0];
+  Ipv4Address dst = address[1];
   RouteCacheEntry toDst;
   if (m_routeCache->LookupRoute (dst, toDst))
     {
@@ -2150,7 +2656,6 @@
        */
       DsrOptionSRHeader sourceRoute;
       std::vector<Ipv4Address> ip = toDst.GetVector ();
-//      PrintVector (ip);
       sourceRoute.SetNodesAddress (ip);
       if (m_routeCache->IsLinkCache ())
         {
@@ -2163,11 +2668,13 @@
       NS_LOG_DEBUG ("The nextHop address " << nextHop);
       if (nextHop == "0.0.0.0")
         {
+          NS_LOG_DEBUG ("Error next hop address");
+          PacketNewRoute (dsrP, source, dst, protocol);
           return;
         }
       SetRoute (nextHop, m_mainAddress);
-      CancelRreqTimer (dst);
-      SendPacket (sourceRoute, nextHop, protocol);
+      CancelRreqTimer (dst, true);
+      SendPacketFromBuffer (sourceRoute, nextHop, protocol);
       NS_LOG_LOGIC ("Route to " << dst << " found");
       return;
     }
@@ -2180,15 +2687,21 @@
   if (m_rreqTable->GetRreqCnt (dst) >= m_rreqRetries)
     {
       NS_LOG_LOGIC ("Route discovery to " << dst << " has been attempted " << m_rreqRetries << " times");
-      CancelRreqTimer (dst);
+      CancelRreqTimer (dst, true);
       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);
+      SocketIpTtlTag tag;
+      tag.SetTtl ((uint8_t)m_discoveryHopLimit);
+      Ptr<Packet> propPacket = packet->Copy ();
+      propPacket->AddPacketTag (tag);
+      // Increase the request count
+      m_rreqTable->FindAndUpdate (dst);
+      SendRequest (propPacket, source);
+      NS_LOG_DEBUG ("Check the route request entry " << source << " " << dst);
+      ScheduleRreqRetry (packet, address, false, requestId, protocol);
     }
   return;
 }
@@ -2202,7 +2715,21 @@
   /*
    * The destination address here is directed broadcast address
    */
-  m_downTarget (packet, source, m_broadcast, GetProtocolNumber (), 0);
+  uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
+  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+  NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+  DsrNetworkQueueEntry newEntry (packet, source, m_broadcast, Simulator::Now (), 0);
+
+  if (dsrNetworkQueue->Enqueue (newEntry))
+    {
+      Scheduler (priority);
+    }
+  else
+    {
+      NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+    }
 }
 
 void
@@ -2210,7 +2737,7 @@
 {
   NS_LOG_FUNCTION (this << packet);
   /*
-   * this is a forwarding case when sending route requests, a random delay time [0, m_broadcastJitter]
+   * 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,
@@ -2233,7 +2760,6 @@
       /**
        * Push back the node addresses other than those between srcAddress and our own ip address
        */
-//      PrintVector (nodeList);
       std::vector<Ipv4Address>::iterator before = find (nodeList.begin (), nodeList.end (), srcAddress);
       for (std::vector<Ipv4Address>::iterator i = nodeList.begin (); i != before; ++i)
         {
@@ -2245,7 +2771,6 @@
         {
           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
@@ -2265,7 +2790,7 @@
       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.SetPayloadLength (uint16_t(length) + 2);
       dsrRoutingHeader.AddDsrOption (rrep);
       Ptr<Packet> newPacket = Create<Packet> ();
       newPacket->AddHeader (dsrRoutingHeader);
@@ -2292,7 +2817,22 @@
   Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (m_mainAddress));
   route->SetOutputDevice (dev);
   NS_LOG_INFO ("The output device " << dev << " packet is: " << *packet);
-  m_downTarget (packet, source, nextHop, GetProtocolNumber (), route);
+
+  uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
+  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+  NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+  DsrNetworkQueueEntry newEntry (packet, source, nextHop, Simulator::Now (), route);
+
+  if (dsrNetworkQueue->Enqueue (newEntry))
+    {
+      Scheduler (priority);
+    }
+  else
+    {
+      NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+    }
 }
 
 void
@@ -2311,7 +2851,7 @@
                                  Ipv4Address source,
                                  Ipv4Address destination,
                                  Ptr<Ipv4Route> route,
-                                 uint16_t hops)
+                                 double 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);
@@ -2344,7 +2884,7 @@
   ack.SetRealDst (realDst);
 
   uint8_t length = ack.GetLength ();
-  dsrRoutingHeader.SetPayloadLength (length + 2);
+  dsrRoutingHeader.SetPayloadLength (uint16_t(length) + 2);
   dsrRoutingHeader.AddDsrOption (ack);
 
   Ptr<Packet> packet = Create<Packet> ();
@@ -2352,7 +2892,22 @@
   Ptr<NetDevice> dev = m_ip->GetNetDevice (m_ip->GetInterfaceForAddress (m_mainAddress));
   route->SetOutputDevice (dev);
   NS_LOG_DEBUG ("Send out the ACK");
-  m_downTarget (packet, m_mainAddress, destination, GetProtocolNumber (), route);
+
+  uint32_t priority = GetPriority (DSR_CONTROL_PACKET);
+  std::map<uint32_t, Ptr<dsr::DsrNetworkQueue> >::iterator i = m_priorityQueue.find (priority);
+  Ptr<dsr::DsrNetworkQueue> dsrNetworkQueue = i->second;
+  NS_LOG_DEBUG("Will be inserting into priority queue " << dsrNetworkQueue << " number: " << priority);
+
+  DsrNetworkQueueEntry newEntry (packet, m_mainAddress, destination, Simulator::Now (), route);
+
+  if (dsrNetworkQueue->Enqueue (newEntry))
+    {
+      Scheduler (priority);
+    }
+  else
+    {
+      NS_LOG_INFO ("Packet dropped as dsr network queue is full");
+    }
 }
 
 enum Ipv4L4Protocol::RxStatus
@@ -2374,12 +2929,11 @@
   uint8_t protocol = dsrRoutingHeader.GetNextHeader ();
   uint32_t sourceId = dsrRoutingHeader.GetSourceId ();
   Ipv4Address source = GetIPfromID (sourceId);
-  NS_LOG_DEBUG ("The source address " << source);
+  NS_LOG_DEBUG ("The source address " << source << " with source id " << sourceId);
   /*
    * 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
@@ -2401,7 +2955,7 @@
   uint8_t segmentsLeft = 0;
 
   optionType = *(data);
-  NS_LOG_LOGIC ("The option type value " << (uint32_t)optionType);
+  NS_LOG_LOGIC ("The option type value " << (uint32_t)optionType << " with packet size " << p->GetSize());
   dsrOption = GetOption (optionType);       // Get the relative dsr option and demux to the process function
 
   if (optionType == 1)        // This is the request option
@@ -2478,9 +3032,9 @@
         }
       else
         {
-          if (segmentsLeft != 0)
+          if (segmentsLeft == 0)
             {
-              // / get the next header
+              // / Get the next header
               uint8_t nextHeader = dsrRoutingHeader.GetNextHeader ();
               Ptr<Ipv4L3Protocol> l3proto = m_node->GetObject<Ipv4L3Protocol> ();
               Ptr<Ipv4L4Protocol> nextProto = l3proto->GetProtocol (nextHeader);
@@ -2489,6 +3043,7 @@
                   // 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 size here " << copy->GetSize());
                   NS_LOG_DEBUG ("The packet received " << *copy);
                   enum Ipv4L4Protocol::RxStatus status =
                     nextProto->Receive (copy, ip, incomingInterface);
@@ -2502,16 +3057,20 @@
                       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
-                          }
+                      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
                     }
-                  // Another case to suppress ICMP is a subnet-directed broadcast
-                 return status;
+                  return status;
                 }
             }
+          else
+            {
+              NS_LOG_INFO ("This is not the final destination, the packet has already been forward to next hop");
+            }
         }
     }
   else
@@ -2535,7 +3094,7 @@
        */
 //            SendError (rerrUnsupportHeader, 0, protocol); // Send the error packet
     }
-  return Ipv4L4Protocol::RX_ENDPOINT_UNREACH;
+  return Ipv4L4Protocol::RX_OK;
 }
 
 void