src/internet-stack/arp-l3-protocol.cc
changeset 3260 8c0ab08144e6
parent 3177 8ce20d798105
child 3430 a8eb6b890f14
child 3448 0bd851bb1225
equal deleted inserted replaced
3259:43b3f8ecd86d 3260:8c0ab08144e6
       
     1 /* -*-  Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
       
     2 /*
       
     3  * Copyright (c) 2006 INRIA
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License version 2 as
       
     7  * published by the Free Software Foundation;
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    17  *
       
    18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
       
    19  */
       
    20 #include "ns3/packet.h"
       
    21 #include "ns3/log.h"
       
    22 #include "ns3/node.h"
       
    23 #include "ns3/net-device.h"
       
    24 #include "ns3/object-vector.h"
       
    25 #include "ns3/trace-source-accessor.h"
       
    26 
       
    27 #include "ipv4-l3-protocol.h"
       
    28 #include "arp-l3-protocol.h"
       
    29 #include "arp-header.h"
       
    30 #include "arp-cache.h"
       
    31 #include "ipv4-interface.h"
       
    32 
       
    33 NS_LOG_COMPONENT_DEFINE ("ArpL3Protocol");
       
    34 
       
    35 namespace ns3 {
       
    36 
       
    37 const uint16_t ArpL3Protocol::PROT_NUMBER = 0x0806;
       
    38 
       
    39 NS_OBJECT_ENSURE_REGISTERED (ArpL3Protocol);
       
    40 
       
    41 TypeId 
       
    42 ArpL3Protocol::GetTypeId (void)
       
    43 {
       
    44   static TypeId tid = TypeId ("ns3::ArpL3Protocol")
       
    45     .SetParent<Object> ()
       
    46     .AddAttribute ("CacheList",
       
    47                    "The list of ARP caches",
       
    48                    ObjectVectorValue (),
       
    49                    MakeObjectVectorAccessor (&ArpL3Protocol::m_cacheList),
       
    50                    MakeObjectVectorChecker<ArpCache> ())
       
    51     .AddTraceSource ("Drop",
       
    52                      "Packet dropped because not enough room in pending queue for a specific cache entry.",
       
    53                      MakeTraceSourceAccessor (&ArpL3Protocol::m_dropTrace))
       
    54     ;
       
    55   return tid;
       
    56 }
       
    57 
       
    58 ArpL3Protocol::ArpL3Protocol ()
       
    59 {
       
    60   NS_LOG_FUNCTION (this);
       
    61 }
       
    62 
       
    63 ArpL3Protocol::~ArpL3Protocol ()
       
    64 {
       
    65   NS_LOG_FUNCTION (this);
       
    66 }
       
    67 
       
    68 void 
       
    69 ArpL3Protocol::SetNode (Ptr<Node> node)
       
    70 {
       
    71   m_node = node;
       
    72 }
       
    73 
       
    74 void 
       
    75 ArpL3Protocol::DoDispose (void)
       
    76 {
       
    77   NS_LOG_FUNCTION (this);
       
    78   for (CacheList::iterator i = m_cacheList.begin (); i != m_cacheList.end (); ++i)
       
    79     {
       
    80       Ptr<ArpCache> cache = *i;
       
    81       cache->Dispose ();
       
    82     }
       
    83   m_cacheList.clear ();
       
    84   m_node = 0;
       
    85   Object::DoDispose ();
       
    86 }
       
    87 
       
    88 Ptr<ArpCache> 
       
    89 ArpL3Protocol::CreateCache (Ptr<NetDevice> device, Ptr<Ipv4Interface> interface)
       
    90 {
       
    91   Ptr<Ipv4L3Protocol> ipv4 = m_node->GetObject<Ipv4L3Protocol> ();
       
    92   Ptr<ArpCache> cache = CreateObject<ArpCache> ();
       
    93   cache->SetDevice (device, interface);
       
    94   NS_ASSERT (device->IsBroadcast ());
       
    95   device->SetLinkChangeCallback (MakeCallback (&ArpCache::Flush, cache));
       
    96   m_cacheList.push_back (cache);
       
    97   return cache;
       
    98 }
       
    99 
       
   100 Ptr<ArpCache>
       
   101 ArpL3Protocol::FindCache (Ptr<NetDevice> device)
       
   102 {
       
   103   NS_LOG_FUNCTION_NOARGS ();
       
   104   for (CacheList::const_iterator i = m_cacheList.begin (); i != m_cacheList.end (); i++)
       
   105     {
       
   106       if ((*i)->GetDevice () == device)
       
   107 	{
       
   108 	  return *i;
       
   109 	}
       
   110     }
       
   111   NS_ASSERT (false);
       
   112   // quiet compiler
       
   113   return 0;
       
   114 }
       
   115 
       
   116 void 
       
   117 ArpL3Protocol::Receive(Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
       
   118 {
       
   119   NS_LOG_FUNCTION_NOARGS ();
       
   120   Ptr<ArpCache> cache = FindCache (device);
       
   121   ArpHeader arp;
       
   122   packet->RemoveHeader (arp);
       
   123   
       
   124   NS_LOG_LOGIC ("ARP: received "<< (arp.IsRequest ()? "request" : "reply") <<
       
   125             " node="<<m_node->GetId ()<<", got request from " <<
       
   126             arp.GetSourceIpv4Address () << " for address " <<
       
   127             arp.GetDestinationIpv4Address () << "; we have address " <<
       
   128             cache->GetInterface ()->GetAddress ());
       
   129 
       
   130   /**
       
   131    * Note: we do not update the ARP cache when we receive an ARP request
       
   132    * from an unknown node. See bug #107
       
   133    */
       
   134 
       
   135   if (arp.IsRequest () && 
       
   136       arp.GetDestinationIpv4Address () == cache->GetInterface ()->GetAddress ()) 
       
   137     {
       
   138       NS_LOG_LOGIC ("node="<<m_node->GetId () <<", got request from " << 
       
   139                 arp.GetSourceIpv4Address () << " -- send reply");
       
   140       SendArpReply (cache, arp.GetSourceIpv4Address (),
       
   141                     arp.GetSourceHardwareAddress ());
       
   142     } 
       
   143   else if (arp.IsReply () &&
       
   144            arp.GetDestinationIpv4Address ().IsEqual (cache->GetInterface ()->GetAddress ()) &&
       
   145            arp.GetDestinationHardwareAddress () == device->GetAddress ()) 
       
   146     {
       
   147       Ipv4Address from = arp.GetSourceIpv4Address ();
       
   148       ArpCache::Entry *entry = cache->Lookup (from);
       
   149       if (entry != 0)
       
   150         {
       
   151           if (entry->IsWaitReply ()) 
       
   152             {
       
   153               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply from " << 
       
   154                         arp.GetSourceIpv4Address ()
       
   155                      << " for waiting entry -- flush");
       
   156               Address from_mac = arp.GetSourceHardwareAddress ();
       
   157               entry->MarkAlive (from_mac);
       
   158               Ptr<Packet> pending = entry->DequeuePending();
       
   159               while (pending != 0)
       
   160                 {
       
   161                   cache->GetInterface ()->Send (pending,
       
   162                                                 arp.GetSourceIpv4Address ());
       
   163                   pending = entry->DequeuePending();
       
   164                 }
       
   165             } 
       
   166           else 
       
   167             {
       
   168               // ignore this reply which might well be an attempt 
       
   169               // at poisening my arp cache.
       
   170               NS_LOG_LOGIC("node="<<m_node->GetId ()<<", got reply from " << 
       
   171                         arp.GetSourceIpv4Address () << 
       
   172                         " for non-waiting entry -- drop");
       
   173               m_dropTrace (packet);
       
   174             }
       
   175         } 
       
   176       else 
       
   177         {
       
   178           NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got reply for unknown entry -- drop");
       
   179           m_dropTrace (packet);
       
   180         }
       
   181     }
       
   182   else
       
   183     {
       
   184       NS_LOG_LOGIC ("node="<<m_node->GetId ()<<", got request from " <<
       
   185                 arp.GetSourceIpv4Address () << " for unknown address " <<
       
   186                 arp.GetDestinationIpv4Address () << " -- drop");
       
   187     }
       
   188 }
       
   189 bool 
       
   190 ArpL3Protocol::Lookup (Ptr<Packet> packet, Ipv4Address destination, 
       
   191                        Ptr<NetDevice> device,
       
   192                        Ptr<ArpCache> cache,
       
   193                        Address *hardwareDestination)
       
   194 {
       
   195   NS_LOG_FUNCTION_NOARGS ();
       
   196   ArpCache::Entry *entry = cache->Lookup (destination);
       
   197   if (entry != 0)
       
   198     {
       
   199       if (entry->IsExpired ()) 
       
   200         {
       
   201           if (entry->IsDead ()) 
       
   202             {
       
   203               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
       
   204                         ", dead entry for " << destination << " expired -- send arp request");
       
   205               entry->MarkWaitReply (packet);
       
   206               SendArpRequest (cache, destination);
       
   207             } 
       
   208           else if (entry->IsAlive ()) 
       
   209             {
       
   210               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
       
   211                         ", alive entry for " << destination << " expired -- send arp request");
       
   212               entry->MarkWaitReply (packet);
       
   213               SendArpRequest (cache, destination);
       
   214             } 
       
   215           else if (entry->IsWaitReply ()) 
       
   216             {
       
   217               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
       
   218                         ", wait reply for " << destination << " expired -- drop");
       
   219               entry->MarkDead ();
       
   220               Ptr<Packet> pending = entry->DequeuePending();
       
   221               while (pending != 0)
       
   222                 {
       
   223                   m_dropTrace (pending);
       
   224                   pending = entry->DequeuePending();
       
   225                 }
       
   226               m_dropTrace (packet);
       
   227             }
       
   228         } 
       
   229       else 
       
   230         {
       
   231           if (entry->IsDead ()) 
       
   232             {
       
   233               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
       
   234                             ", dead entry for " << destination << " valid -- drop");
       
   235               m_dropTrace (packet);
       
   236             } 
       
   237           else if (entry->IsAlive ()) 
       
   238             {
       
   239               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
       
   240                             ", alive entry for " << destination << " valid -- send");
       
   241 	      *hardwareDestination = entry->GetMacAddress ();
       
   242               return true;
       
   243             } 
       
   244           else if (entry->IsWaitReply ()) 
       
   245             {
       
   246               NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
       
   247                             ", wait reply for " << destination << " valid -- drop previous");
       
   248               if (!entry->UpdateWaitReply (packet))
       
   249                 {
       
   250                   m_dropTrace (packet);
       
   251                 }
       
   252             }
       
   253         }
       
   254     }
       
   255   else
       
   256     {
       
   257       // This is our first attempt to transmit data to this destination.
       
   258       NS_LOG_LOGIC ("node="<<m_node->GetId ()<<
       
   259                 ", no entry for " << destination << " -- send arp request");
       
   260       entry = cache->Add (destination);
       
   261       entry->MarkWaitReply (packet);
       
   262       SendArpRequest (cache, destination);
       
   263     }
       
   264   return false;
       
   265 }
       
   266 
       
   267 void
       
   268 ArpL3Protocol::SendArpRequest (Ptr<const ArpCache> cache, Ipv4Address to)
       
   269 {
       
   270   NS_LOG_FUNCTION_NOARGS ();
       
   271   ArpHeader arp;
       
   272   NS_LOG_LOGIC ("ARP: sending request from node "<<m_node->GetId ()<<
       
   273             " || src: " << cache->GetDevice ()->GetAddress () <<
       
   274             " / " << cache->GetInterface ()->GetAddress () <<
       
   275             " || dst: " << cache->GetDevice ()->GetBroadcast () <<
       
   276             " / " << to);
       
   277   arp.SetRequest (cache->GetDevice ()->GetAddress (),
       
   278 		  cache->GetInterface ()->GetAddress (), 
       
   279                   cache->GetDevice ()->GetBroadcast (),
       
   280                   to);
       
   281   Ptr<Packet> packet = Create<Packet> ();
       
   282   packet->AddHeader (arp);
       
   283   cache->GetDevice ()->Send (packet, cache->GetDevice ()->GetBroadcast (), PROT_NUMBER);
       
   284 }
       
   285 
       
   286 void
       
   287 ArpL3Protocol::SendArpReply (Ptr<const ArpCache> cache, Ipv4Address toIp, Address toMac)
       
   288 {
       
   289   NS_LOG_FUNCTION_NOARGS ();
       
   290   ArpHeader arp;
       
   291   NS_LOG_LOGIC ("ARP: sending reply from node "<<m_node->GetId ()<<
       
   292             "|| src: " << cache->GetDevice ()->GetAddress () << 
       
   293             " / " << cache->GetInterface ()->GetAddress () <<
       
   294             " || dst: " << toMac << " / " << toIp);
       
   295   arp.SetReply (cache->GetDevice ()->GetAddress (),
       
   296                 cache->GetInterface ()->GetAddress (),
       
   297                 toMac, toIp);
       
   298   Ptr<Packet> packet = Create<Packet> ();
       
   299   packet->AddHeader (arp);
       
   300   cache->GetDevice ()->Send (packet, toMac, PROT_NUMBER);
       
   301 }
       
   302 
       
   303 }//namespace ns3