raw socket added
authorBorovkova Elena <borovkovaes@iitp.ru>
Sun, 26 Jul 2009 22:22:00 +0400
changeset 5612 ecefb30bfb40
parent 5611 f051337ca99d
child 5613 c2e4bad4affc
raw socket added
src/internet-stack/raw-socket-impl.cc
src/internet-stack/raw-socket-impl.h
src/internet-stack/wscript
src/routing/aodv/aodv-routing-protocol.cc
src/routing/aodv/aodv-routing-protocol.h
src/routing/aodv/aodv-rtable.cc
src/routing/aodv/aodv-rtable.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/raw-socket-impl.cc	Sun Jul 26 22:22:00 2009 +0400
@@ -0,0 +1,299 @@
+#include "raw-socket-impl.h"
+#include "ipv4-l3-protocol.h"
+#include "icmpv4.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/node.h"
+#include "ns3/packet.h"
+#include "ns3/uinteger.h"
+#include "ns3/log.h"
+#include "ipv4-interface.h"
+
+
+NS_LOG_COMPONENT_DEFINE ("RawSocketImpl");
+
+namespace ns3
+{
+
+NS_OBJECT_ENSURE_REGISTERED (RawSocketImpl);
+
+TypeId
+RawSocketImpl::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::RawSocketImpl") .SetParent<Socket> () .AddAttribute ("Protocol", "Protocol number to match.", UintegerValue (0),
+      MakeUintegerAccessor (&RawSocketImpl::m_protocol), MakeUintegerChecker<uint16_t> ()) .AddAttribute ("IcmpFilter",
+          "Any icmp header whose type field matches a bit in this filter is dropped.", UintegerValue (0), MakeUintegerAccessor (
+              &RawSocketImpl::m_icmpFilter), MakeUintegerChecker<uint32_t> ());
+  return tid;
+}
+
+RawSocketImpl::RawSocketImpl ()
+{
+  NS_LOG_FUNCTION (this);
+  m_err = Socket::ERROR_NOTERROR;
+  m_node = 0;
+  m_src = Ipv4Address::GetAny ();
+  m_dst = Ipv4Address::GetAny ();
+  m_protocol = 0;
+  m_shutdownSend = false;
+  m_shutdownRecv = false;
+}
+
+void
+RawSocketImpl::SetNode (Ptr<Node> node)
+{
+  m_node = node;
+}
+
+void
+RawSocketImpl::DoDispose (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_node = 0;
+  Socket::DoDispose ();
+}
+
+enum Socket::SocketErrno
+RawSocketImpl::GetErrno (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_err;
+}
+Ptr<Node>
+RawSocketImpl::GetNode (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return m_node;
+}
+int
+RawSocketImpl::Bind (const Address &address)
+{
+  NS_LOG_FUNCTION (this << address);
+  if (!InetSocketAddress::IsMatchingType (address))
+  {
+    m_err = Socket::ERROR_INVAL;
+    return -1;
+  }
+  InetSocketAddress ad = InetSocketAddress::ConvertFrom (address);
+  m_src = ad.GetIpv4 ();
+  return 0;
+}
+int
+RawSocketImpl::Bind (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_src = Ipv4Address::GetAny ();
+  return 0;
+}
+int
+RawSocketImpl::GetSockName (Address &address) const
+{
+  address = InetSocketAddress (m_src, 0);
+  return 0;
+}
+int
+RawSocketImpl::Close (void)
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  if (ipv4 != 0)
+  {
+    ipv4->DeleteRawSocket (this);
+  }
+  return 0;
+}
+int
+RawSocketImpl::ShutdownSend (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_shutdownSend = true;
+  return 0;
+}
+int
+RawSocketImpl::ShutdownRecv (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_shutdownRecv = true;
+  return 0;
+}
+int
+RawSocketImpl::Connect (const Address &address)
+{
+  NS_LOG_FUNCTION (this << address);
+  if (!InetSocketAddress::IsMatchingType (address))
+  {
+    m_err = Socket::ERROR_INVAL;
+    return -1;
+  }
+  InetSocketAddress ad = InetSocketAddress::ConvertFrom (address);
+  m_dst = ad.GetIpv4 ();
+  return 0;
+}
+int
+RawSocketImpl::Listen (void)
+{
+  NS_LOG_FUNCTION (this);
+  m_err = Socket::ERROR_OPNOTSUPP;
+  return -1;
+}
+uint32_t
+RawSocketImpl::GetTxAvailable (void) const
+{
+  NS_LOG_FUNCTION (this);
+  return 0xffffffff;
+}
+int
+RawSocketImpl::Send (Ptr<Packet> p, uint32_t flags)
+{
+  NS_LOG_FUNCTION (this << p << flags);
+  InetSocketAddress to = InetSocketAddress (m_dst, m_protocol);
+  return SendTo (p, flags, to);
+}
+int
+RawSocketImpl::SendTo (Ptr<Packet> packet, uint32_t flags, const Address &toAddress)
+{
+  NS_LOG_FUNCTION (this << packet << flags << toAddress);
+  if (!InetSocketAddress::IsMatchingType (toAddress))
+  {
+    m_err = Socket::ERROR_INVAL;
+    return -1;
+  }
+  if (m_shutdownSend)
+  {
+    return 0;
+  }
+  InetSocketAddress ad = InetSocketAddress::ConvertFrom (toAddress);
+  Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
+  Ipv4Address dst = ad.GetIpv4 ();
+  if (ipv4->GetRoutingProtocol ())
+  {
+    Ipv4Header header;
+    packet->PeekHeader(header);
+    SocketErrno errno_ = ERROR_NOTERROR;//do not use errno as it is the standard C last error number
+    Ptr<Ipv4Route> route;
+    uint32_t oif = 0; //specify non-zero if bound to a source address
+    route = ipv4->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
+    if (route != 0)
+    {
+      NS_LOG_LOGIC ("Route exists");
+      Ptr<NetDevice> outDev = route->GetOutputDevice ();
+      int32_t interface = ipv4->GetInterfaceForDevice (outDev);
+      NS_ASSERT (interface >= 0);
+      Ptr<Ipv4Interface> outInterface = ipv4->GetInterface (interface);
+      NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
+
+      NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ());
+      if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0")))
+      {
+        if (outInterface->IsUp ())
+        {
+          NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
+          outInterface->Send (packet, route->GetGateway ());
+        }
+        else
+        {
+          NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
+        }
+      }
+      else
+      {
+        if (outInterface->IsUp ())
+        {
+          NS_LOG_LOGIC ("Send to destination " << header.GetDestination ());
+          outInterface->Send (packet, header.GetDestination ());
+        }
+        else
+        {
+          NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << header.GetDestination ());
+        }
+      }
+    }
+    else
+    {
+      NS_LOG_DEBUG ("dropped because no outgoing route.");
+    }
+  }
+  return 0;
+}
+uint32_t
+RawSocketImpl::GetRxAvailable (void) const
+{
+  NS_LOG_FUNCTION (this);
+  uint32_t rx = 0;
+  for (std::list<Data>::const_iterator i = m_recv.begin (); i != m_recv.end (); ++i)
+  {
+    rx += (i->packet)->GetSize ();
+  }
+  return rx;
+}
+Ptr<Packet>
+RawSocketImpl::Recv (uint32_t maxSize, uint32_t flags)
+{
+  NS_LOG_FUNCTION (this << maxSize << flags);
+  Address tmp;
+  return RecvFrom (maxSize, flags, tmp);
+}
+Ptr<Packet>
+RawSocketImpl::RecvFrom (uint32_t maxSize, uint32_t flags, Address &fromAddress)
+{
+  NS_LOG_FUNCTION (this << maxSize << flags << fromAddress);
+  if (m_recv.empty ())
+  {
+    return 0;
+  }
+  struct Data data = m_recv.front ();
+  m_recv.pop_front ();
+  if (data.packet->GetSize () > maxSize)
+  {
+    Ptr<Packet> first = data.packet->CreateFragment (0, maxSize);
+    data.packet->RemoveAtStart (maxSize);
+    m_recv.push_front (data);
+    return first;
+  }
+  InetSocketAddress inet = InetSocketAddress (data.fromIp, data.fromProtocol);
+  fromAddress = inet;
+  return data.packet;
+}
+
+void
+RawSocketImpl::SetProtocol (uint16_t protocol)
+{
+  NS_LOG_FUNCTION (this << protocol);
+  m_protocol = protocol;
+}
+
+bool
+RawSocketImpl::ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<NetDevice> device)
+{
+  NS_LOG_FUNCTION (this << *p << ipHeader << device);
+  if (m_shutdownRecv)
+  {
+    return false;
+  } NS_LOG_LOGIC ("src = " << m_src << " dst = " << m_dst);
+  if ((m_src == Ipv4Address::GetAny () || ipHeader.GetDestination () == m_src) && (m_dst == Ipv4Address::GetAny () || ipHeader.GetSource () == m_dst)
+      && ipHeader.GetProtocol () == m_protocol)
+  {
+    Ptr<Packet> copy = p->Copy ();
+    if (m_protocol == 1)
+    {
+      Icmpv4Header icmpHeader;
+      copy->PeekHeader (icmpHeader);
+      uint8_t type = icmpHeader.GetType ();
+      if (type < 32 && ((1 << type) & m_icmpFilter))
+      {
+        // filter out icmp packet.
+        return false;
+      }
+    }
+    copy->AddHeader (ipHeader);
+    struct Data data;
+    data.packet = copy;
+    data.fromIp = ipHeader.GetSource ();
+    data.fromProtocol = ipHeader.GetProtocol ();
+    m_recv.push_back (data);
+    NotifyDataRecv ();
+    return true;
+  }
+  return false;
+}
+
+} // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/internet-stack/raw-socket-impl.h	Sun Jul 26 22:22:00 2009 +0400
@@ -0,0 +1,66 @@
+#ifndef IPV4_RAW_SOCKET_IMPL_H
+#define IPV4_RAW_SOCKET_IMPL_H
+
+#include "ns3/socket.h"
+#include "ns3/ipv4-header.h"
+#include "ns3/ipv4-route.h"
+#include <list>
+
+namespace ns3 {
+
+class NetDevice;
+class Node;
+
+class RawSocketImpl : public Socket
+{
+public:
+  static TypeId GetTypeId (void);
+
+  RawSocketImpl ();
+
+  void SetNode (Ptr<Node> node);
+
+  virtual enum Socket::SocketErrno GetErrno (void) const;
+  virtual Ptr<Node> GetNode (void) const;
+  virtual int Bind (const Address &address);
+  virtual int Bind ();
+  virtual int GetSockName (Address &address) const; 
+  virtual int Close (void);
+  virtual int ShutdownSend (void);
+  virtual int ShutdownRecv (void);
+  virtual int Connect (const Address &address);
+  virtual int Listen (void);
+  virtual uint32_t GetTxAvailable (void) const;
+  virtual int Send (Ptr<Packet> p, uint32_t flags);
+  virtual int SendTo (Ptr<Packet> p, uint32_t flags, 
+		      const Address &toAddress);
+  virtual uint32_t GetRxAvailable (void) const;
+  virtual Ptr<Packet> Recv (uint32_t maxSize, uint32_t flags);
+  virtual Ptr<Packet> RecvFrom (uint32_t maxSize, uint32_t flags,  
+				Address &fromAddress);
+
+  void SetProtocol (uint16_t protocol);
+  bool ForwardUp (Ptr<const Packet> p, Ipv4Header ipHeader, Ptr<NetDevice> device);
+private:
+  virtual void DoDispose (void);
+
+  struct Data {
+    Ptr<Packet> packet;
+    Ipv4Address fromIp;
+    uint16_t fromProtocol;
+  };
+
+  enum Socket::SocketErrno m_err;
+  Ptr<Node> m_node;
+  Ipv4Address m_src;
+  Ipv4Address m_dst;
+  uint16_t m_protocol;
+  std::list<struct Data> m_recv;
+  bool m_shutdownSend;
+  bool m_shutdownRecv;
+  uint32_t m_icmpFilter;
+};
+
+} // namespace ns3
+
+#endif /* IPV4_RAW_SOCKET_IMPL_H */
--- a/src/internet-stack/wscript	Sun Jul 26 11:15:52 2009 +0400
+++ b/src/internet-stack/wscript	Sun Jul 26 22:22:00 2009 +0400
@@ -94,6 +94,7 @@
         'pending-data.cc',
         'sequence-number.cc',
         'rtt-estimator.cc',
+        'raw-socket-impl.cc',
         'ipv4-raw-socket-factory-impl.cc',
         'ipv4-raw-socket-impl.cc',
         'icmpv4.cc',
--- a/src/routing/aodv/aodv-routing-protocol.cc	Sun Jul 26 11:15:52 2009 +0400
+++ b/src/routing/aodv/aodv-routing-protocol.cc	Sun Jul 26 22:22:00 2009 +0400
@@ -163,9 +163,16 @@
   NODE_TRAVERSAL_TIME (MilliSeconds (40)),
   ALLOWED_HELLO_LOSS (2),
   FREQUENCY (Seconds (0.5)),
+  BLACKLIST_TIMEOUT(Scalar(RREQ_RETRIES) * NET_TRAVERSAL_TIME),
+    /* BLACKLIST_TIMEOUT should be suitably increased if an expanding ring search is used.  In such cases, it should be
+     *    {[(TTL_THRESHOLD - TTL_START)/TTL_INCREMENT] + 1 + RREQ_RETRIES} *NET_TRAVERSAL_TIME.
+     * This is to account for possible additional route discovery attempts.
+     */
+  NEXT_HOP_WAIT(NODE_TRAVERSAL_TIME + MilliSeconds (10)),
   m_broadcastID (0), m_seqNo (0), btimer (Timer::CANCEL_ON_DESTROY), htimer (Timer::CANCEL_ON_DESTROY), ntimer (Timer::CANCEL_ON_DESTROY),
   rtimer (Timer::CANCEL_ON_DESTROY), lrtimer (Timer::CANCEL_ON_DESTROY), m_routeRequestTimer (Timer::CANCEL_ON_DESTROY)
 
+
 {
   NET_TRAVERSAL_TIME = Scalar (2 * NET_DIAMETER) * NODE_TRAVERSAL_TIME;
   BCAST_ID_SAVE = Scalar (2) * NET_TRAVERSAL_TIME;
@@ -234,12 +241,8 @@
 
     // Add local broadcast record to the routing table
     Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()));
-    RoutingTableEntry rt (/*device=*/dev, /*dst=*/iface.GetBroadcast (),
-        /*know seqno=*/true, /*seqno=*/0,
-        /*iface=*/iface.GetLocal (),
-        /*hops=*/1,
-        /*next hop=*/iface.GetBroadcast (),
-        /*lifetime=*/Seconds (1e9)); // TODO use infty
+    RoutingTableEntry rt (/*device=*/dev, /*dst=*/iface.GetBroadcast (), /*know seqno=*/true, /*seqno=*/0, /*iface=*/iface.GetLocal (),
+                          /*hops=*/1, /*next hop=*/iface.GetBroadcast (), /*lifetime=*/Seconds (1e9)); // TODO use infty
     m_routingTable.AddRoute (rt);
   }
 
@@ -376,6 +379,7 @@
   htimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this);
   m_routeRequestTimer.SetFunction(&RoutingProtocol::RouteRequestTimerExpire, this);
 
+
   htimer.SetDelay (HELLO_INTERVAL);
   btimer.SetDelay (BCAST_ID_SAVE);
   rtimer.SetDelay (FREQUENCY);
@@ -506,20 +510,19 @@
 RoutingProtocol::RecvAodv (Ptr<Socket> socket)
 {
   NS_LOG_FUNCTION (this);
-
   Ptr<Packet> packet;
   Address sourceAddress;
   packet = socket->RecvFrom (sourceAddress);
 
   InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
   NS_ASSERT (inetSourceAddr.GetPort () == AODV_PORT);
-  Ipv4Address senderIfaceAddr = inetSourceAddr.GetIpv4 ();
-  Ipv4Address receiverIfaceAddr = m_socketAddresses[socket].GetLocal ();
+  Ipv4Address sender = inetSourceAddr.GetIpv4 ();
+  Ipv4Address receiver = m_socketAddresses[socket].GetLocal ();
 
-  NS_LOG_DEBUG ("AODV node " << this << " received a AODV packet from " << senderIfaceAddr << " to " << receiverIfaceAddr);
+  NS_LOG_DEBUG ("AODV node " << this << " received a AODV packet from " << sender << " to " << receiver);
 
-  UpdateRouteToNeighbor (senderIfaceAddr, receiverIfaceAddr);
-
+  UpdateRouteToNeighbor (sender, receiver);
+  NS_LOG_LOGIC("xxx");
   TypeHeader tHeader (AODVTYPE_RREQ);
   packet->RemoveHeader (tHeader);
   if (!tHeader.IsValid ())
@@ -532,21 +535,24 @@
     {
     case AODVTYPE_RREQ:
       {
-        RecvRequest (packet, receiverIfaceAddr, senderIfaceAddr, socket);
+        RecvRequest (packet, receiver, sender, socket);
         break;
       }
     case AODVTYPE_RREP:
       {
-        RecvReply (packet, receiverIfaceAddr, senderIfaceAddr);
+        RecvReply (packet, receiver, sender);
         break;
       }
     case AODVTYPE_RERR:
       {
-        RecvError (packet, senderIfaceAddr);
+        RecvError (packet, sender);
         break;
       }
     case AODVTYPE_RREP_ACK:
-      break;
+      {
+        RecvReplyAck(sender);
+        break;
+      }
     }
 }
 
@@ -573,20 +579,19 @@
   if (!m_routingTable.LookupRoute (sender, toNeighbor))
   {
     Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
-    RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/sender,
-    /*know seqno=*/false, /*seqno=*/0,
-    /*iface=*/receiver,
-    /*hops=*/1, /*next hop=*/sender,
-    /*lifetime=*/Simulator::Now () + ACTIVE_ROUTE_TIMEOUT);
+    RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/sender, /*know seqno=*/false, /*seqno=*/0, /*iface=*/receiver,
+                                /*hops=*/1, /*next hop=*/sender,/*lifetime=*/Simulator::Now () + ACTIVE_ROUTE_TIMEOUT);
     m_routingTable.AddRoute (newEntry);
   }
   else
   {
     toNeighbor.SetFlag (RTF_UP);
     toNeighbor.SetValidSeqNo(false);
-    Time t = toNeighbor.GetLifeTime ();
-    if (t < Simulator::Now () + ACTIVE_ROUTE_TIMEOUT)
+    if (toNeighbor.GetLifeTime () < Simulator::Now () + ACTIVE_ROUTE_TIMEOUT)
+    {
+
       toNeighbor.SetLifeTime (Simulator::Now () + ACTIVE_ROUTE_TIMEOUT);
+    }
     m_routingTable.Update (sender, toNeighbor);
   }
 }
@@ -630,10 +635,8 @@
   if (!m_routingTable.LookupRoute (origin, toOrigin))
   {
     Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
-    RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/origin, /*validSeno=*/
-    true, /*seqNo=*/rreqHeader.GetOriginSeqno (),
-    /*iface=*/receiver, /*hops=*/hop, /*nextHop*/src,
-    /*timeLife=*/Simulator::Now () + Scalar (2) * NET_TRAVERSAL_TIME - Scalar (2 * hop) * NODE_TRAVERSAL_TIME);
+    RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/origin, /*validSeno=*/true, /*seqNo=*/rreqHeader.GetOriginSeqno (),/*iface=*/receiver,
+    /*hops=*/hop, /*nextHop*/src, /*timeLife=*/Simulator::Now () + Scalar (2) * NET_TRAVERSAL_TIME - Scalar (2 * hop) * NODE_TRAVERSAL_TIME);
     m_routingTable.AddRoute (newEntry);
   }
   else
@@ -645,8 +648,11 @@
     toOrigin.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));
     toOrigin.SetHop (hop);
     Time minimalLifetime = Simulator::Now () + Scalar (2) * NET_TRAVERSAL_TIME - Scalar (2 * hop) * NODE_TRAVERSAL_TIME;
+
     if (toOrigin.GetLifeTime () < minimalLifetime)
+    {
       toOrigin.SetLifeTime (minimalLifetime);
+    }
     m_routingTable.Update (origin, toOrigin);
   }
 
@@ -718,6 +724,14 @@
   if (!rreqHeader.GetUnknownSeqno () && (rreqHeader.GetDstSeqno () == m_seqNo + 1)) m_seqNo++;
   RrepHeader rrepHeader ( /*prefixSize=*/0, /*hops=*/toOrigin.GetHop (), /*dst=*/rreqHeader.GetDst (),
                         /*dstSeqNo=*/m_seqNo, /*origin=*/toOrigin.GetDestination (), /*lifeTime=*/MY_ROUTE_TIMEOUT);
+  // TODO when??
+  rrepHeader.SetAckRequired(true);
+  RoutingTableEntry toNextHop;
+  m_routingTable.LookupRoute(toOrigin.GetNextHop (), toNextHop);
+  toNextHop.m_ackTimer.SetFunction(&RoutingProtocol::AckTimerExpire, this);
+  toNextHop.m_ackTimer.SetArguments(toNextHop.GetDestination(), BLACKLIST_TIMEOUT);
+  toNextHop.m_ackTimer.SetDelay(NEXT_HOP_WAIT);
+
   Ptr<Packet> packet = Create<Packet> ();
   packet->AddHeader (rrepHeader);
   TypeHeader tHeader (AODVTYPE_RREP);
@@ -757,17 +771,20 @@
 }
 
 void
-RoutingProtocol::SendRouteReplyAck(Ipv4Address neighbor, Ptr<Socket> socket)
+RoutingProtocol::SendReplyAck(Ipv4Address neighbor)
 {
+  NS_LOG_FUNCTION(this);
   RrepAckHeader h;
   TypeHeader typeHeader(AODVTYPE_RREP_ACK);
   Ptr<Packet> packet = Create<Packet> ();
   packet->AddHeader(h);
   packet->AddHeader(typeHeader);
+  RoutingTableEntry toNeighbor;
+  m_routingTable.LookupRoute(neighbor, toNeighbor);
+  Ptr<Socket> socket = FindSocketWithInterfaceAddress(toNeighbor.GetInterface());
   socket->SendTo (packet, 0, InetSocketAddress (neighbor, AODV_PORT));
 }
 
-
 void
 RoutingProtocol::RecvReply (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address sender)
 {
@@ -836,7 +853,8 @@
     NS_LOG_LOGIC("add new route");
     m_routingTable.AddRoute (newEntry);
   }
-
+  // Acknowledge receipt of the RREP by sending a RREP-ACK message back
+  if(rrepHeader.GetAckRequired()) SendReplyAck(sender);
   if (receiver == rrepHeader.GetOrigin ())
   {
     if (toDst.GetFlag () == RTF_IN_SEARCH)
@@ -876,6 +894,13 @@
   }
 }
 
+void
+RoutingProtocol::RecvReplyAck(Ipv4Address neighbor)
+{
+  // TODO
+}
+
+
 // TODO may be used for determining connectivity
 void
 RoutingProtocol::ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiverIfaceAddr)
@@ -899,7 +924,9 @@
   else
   {
     if (toNeighbor.GetLifeTime () < Simulator::Now () + Scalar (ALLOWED_HELLO_LOSS) * HELLO_INTERVAL)
+    {
       toNeighbor.SetLifeTime (Simulator::Now () + Scalar (ALLOWED_HELLO_LOSS) * HELLO_INTERVAL);
+    }
     toNeighbor.SetSeqNo (rrepHeader.GetDstSeqno ());
     toNeighbor.SetValidSeqNo (true);
     toNeighbor.SetFlag (RTF_UP);
@@ -1022,6 +1049,19 @@
 }
 
 void
+RoutingProtocol::AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout)
+{
+  NS_LOG_FUNCTION(this);
+  m_routingTable.MarkLinkAsUinidirectional(neighbor, blacklistTimeout);
+}
+
+void
+RoutingProtocol::RoutingTableEntryTimerExpire(Ipv4Address dst)
+{
+  // TODO
+}
+
+void
 RoutingProtocol::SendHello ()
 {
   NS_LOG_FUNCTION(this);
--- a/src/routing/aodv/aodv-routing-protocol.h	Sun Jul 26 11:15:52 2009 +0400
+++ b/src/routing/aodv/aodv-routing-protocol.h	Sun Jul 26 22:22:00 2009 +0400
@@ -93,6 +93,8 @@
   Time MinHelloInterval; //        (0.75 * HELLO_INTERVAL)
   Time FREQUENCY;
   Time NET_TRAVERSAL_TIME;          // 2 * NODE_TRAVERSAL_TIME * NET_DIAMETER
+  Time BLACKLIST_TIMEOUT;
+  Time NEXT_HOP_WAIT;
   //\}
 
   /// \name Handle Broadcast sequence number cache
@@ -213,6 +215,8 @@
   void RecvRequest (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src, Ptr<Socket> socket);
   /// Receive RREP
   void RecvReply (Ptr<Packet> p, Ipv4Address my ,Ipv4Address src);
+  /// receive RREP_ACK
+  void RecvReplyAck(Ipv4Address neighbor);
   /// Receive RERR from node with address src
   void RecvError (Ptr<Packet> p, Ipv4Address src);
   //\}
@@ -234,7 +238,7 @@
    */
   void SendReplyByIntermediateNode (RoutingTableEntry & toDst, RoutingTableEntry & toOrigin, bool gratRep,  Ptr<Socket> socket);
   /// Send RREP_ACK
-  void SendRouteReplyAck (Ipv4Address neighbor, Ptr<Socket> socket);
+  void SendReplyAck (Ipv4Address neighbor);
   ///\name Send RERR
   //\{
   void SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop);
@@ -258,6 +262,8 @@
   void LocalRepairTimerExpire ();
   Timer m_routeRequestTimer;
   void RouteRequestTimerExpire(Ipv4Address dst);
+  void AckTimerExpire (Ipv4Address neighbor,  Time blacklistTimeout);
+  void RoutingTableEntryTimerExpire(Ipv4Address dst);
   //\}
 };
 
--- a/src/routing/aodv/aodv-rtable.cc	Sun Jul 26 11:15:52 2009 +0400
+++ b/src/routing/aodv/aodv-rtable.cc	Sun Jul 26 22:22:00 2009 +0400
@@ -42,7 +42,9 @@
 
 RoutingTableEntry::RoutingTableEntry(Ptr<NetDevice> dev, Ipv4Address dst, bool vSeqNo, u_int32_t seqNo, Ipv4Address iface, u_int16_t  hops,
                               Ipv4Address nextHop, Time lifetime)
-                            : m_validSeqNo(vSeqNo), m_seqNo(seqNo), m_hops(hops), m_lifeTime(lifetime + Simulator::Now()), m_reqCount(0)
+                            : m_validSeqNo(vSeqNo), m_seqNo(seqNo), m_hops(hops), m_lifeTime(lifetime + Simulator::Now()),
+                              m_reqCount(0), m_blackListState(false), m_blackListTimeout(Simulator::Now()),
+                              m_ackTimer(Timer::CANCEL_ON_DESTROY), lifeTimeTimer(Timer::CANCEL_ON_DESTROY)
 {
   m_ipv4Route = Create<Ipv4Route> ();
   m_ipv4Route->SetDestination(dst);
@@ -155,7 +157,7 @@
  */
 
 bool
-RoutingTable::LookupRoute(Ipv4Address id, RoutingTableEntry & rt)
+RoutingTable::LookupRoute(Ipv4Address id, RoutingTableEntry & rt) const
 {
   std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = m_ipv4AddressEntry.find(id);
   if (i == m_ipv4AddressEntry.end()) return false;
@@ -241,6 +243,17 @@
   }
 }
 
+bool
+RoutingTable::MarkLinkAsUinidirectional (Ipv4Address neighbor, Time blacklistTimeout)
+{
+  std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.find(neighbor);
+  if (i == m_ipv4AddressEntry.end()) return false;
+  i->second.SetUnidirectional (true);
+  i->second.SetBalcklistTimeout(blacklistTimeout);
+  return true;
+}
+
+
 void
 RoutingTable::Print(std::ostream &os) const
 {
--- a/src/routing/aodv/aodv-rtable.h	Sun Jul 26 11:15:52 2009 +0400
+++ b/src/routing/aodv/aodv-rtable.h	Sun Jul 26 22:22:00 2009 +0400
@@ -123,6 +123,10 @@
   void SetRreqCnt(uint8_t n) { m_reqCount = n; }
   uint8_t GetRreqCnt() const { return m_reqCount; }
   void IncrementRreqCnt() { m_reqCount++; }
+  bool IsInBlacklist() const { return m_blackListState; }
+  void SetUnidirectional(bool u) { m_blackListState = u; }
+  void SetBalcklistTimeout (Time t) { m_blackListTimeout = t; }
+  Time GetBlacklistTimeout () { return m_blackListTimeout; }
   //\}
 
   /**
@@ -165,6 +169,14 @@
   Time m_routeRequestTimout;
   /// Number of route requests
   uint8_t m_reqCount;
+  /// Indicate if this entry is in "blacklist"
+  bool m_blackListState;
+  Time m_blackListTimeout;
+public:
+  /// RREP_ACK timer
+  Timer m_ackTimer;
+  /// LifeTime timer of this entry
+  Timer lifeTimeTimer;
 };
 
 /**
@@ -194,7 +206,7 @@
    * \param rt entry with destination address dst, if exists
    * \return true on success
    */
-  bool LookupRoute(Ipv4Address dst, RoutingTableEntry & rt);
+  bool LookupRoute(Ipv4Address dst, RoutingTableEntry & rt) const;
   /// Update routing table
   bool Update(Ipv4Address dst, RoutingTableEntry & rt);
   /// Set routing table entry flags
@@ -213,6 +225,11 @@
   void InvalidateRoutesWithDst(std::map<Ipv4Address, uint32_t> const & unreachable, Time badLinkLifetime);
   /// Delete all outdated entries and invalidate valid entry if Lifetime is expired
   void Purge(Time badLinkLifetime);
+  /** Mark entry as unidirectional (e.g. add this neighbor to "blacklist" for blacklistTimeout period)
+   * \param neighbor - neighbor address link to which assumed to be unidirectional
+   * \return true on success
+   */
+  bool MarkLinkAsUinidirectional(Ipv4Address neighbor, Time blacklistTimeout);
   /// Print routing table
   void Print(std::ostream &os) const;