src/routing/click/model/ipv4-l3-click-protocol.cc
changeset 6826 943a8b1adb26
equal deleted inserted replaced
6825:f9a45d9a10d0 6826:943a8b1adb26
       
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
       
     2 //
       
     3 // Copyright (c) 2006 Georgia Tech Research Corporation
       
     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: George F. Riley <riley@ece.gatech.edu>
       
    19 // Author: Lalith Suresh <suresh.lalith@gmail.com>
       
    20 //
       
    21 
       
    22 #ifdef NS3_CLICK
       
    23 
       
    24 #include "ipv4-l3-click-protocol.h"
       
    25 #include "ns3/ipv4-click-routing.h"
       
    26 #include "ns3/node.h"
       
    27 #include "ns3/socket.h"
       
    28 #include "ns3/ethernet-header.h"
       
    29 #include "ns3/llc-snap-header.h"
       
    30 #include "ns3/net-device.h"
       
    31 #include "ns3/uinteger.h"
       
    32 #include "ns3/object-vector.h"
       
    33 
       
    34 #include "ns3/ipv4-raw-socket-impl.h"
       
    35 #include "ns3/arp-l3-protocol.h"
       
    36 #include "ns3/ipv4-l4-protocol.h"
       
    37 #include "ns3/icmpv4-l4-protocol.h"
       
    38 #include "ns3/loopback-net-device.h"
       
    39 
       
    40 NS_LOG_COMPONENT_DEFINE ("Ipv4L3ClickProtocol");
       
    41 
       
    42 namespace ns3 {
       
    43 
       
    44 const uint16_t Ipv4L3ClickProtocol::PROT_NUMBER = 0x0800;
       
    45 
       
    46 
       
    47 NS_OBJECT_ENSURE_REGISTERED (Ipv4L3ClickProtocol);
       
    48 
       
    49 TypeId
       
    50 Ipv4L3ClickProtocol::GetTypeId (void)
       
    51 {
       
    52   static TypeId tid = TypeId ("ns3::Ipv4L3ClickProtocol")
       
    53     .SetParent<Ipv4> ()
       
    54     .AddConstructor<Ipv4L3ClickProtocol> ()
       
    55     .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
       
    56                    UintegerValue (64),
       
    57                    MakeUintegerAccessor (&Ipv4L3ClickProtocol::m_defaultTtl),
       
    58                    MakeUintegerChecker<uint8_t> ())
       
    59     .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
       
    60                    ObjectVectorValue (),
       
    61                    MakeObjectVectorAccessor (&Ipv4L3ClickProtocol::m_interfaces),
       
    62                    MakeObjectVectorChecker<Ipv4Interface> ())
       
    63   ;
       
    64   return tid;
       
    65 }
       
    66 
       
    67 Ipv4L3ClickProtocol::Ipv4L3ClickProtocol ()
       
    68   : m_identification (0)
       
    69 {
       
    70 }
       
    71 
       
    72 Ipv4L3ClickProtocol::~Ipv4L3ClickProtocol ()
       
    73 {
       
    74 }
       
    75 
       
    76 void
       
    77 Ipv4L3ClickProtocol::DoDispose (void)
       
    78 {
       
    79   NS_LOG_FUNCTION (this);
       
    80   for (L4List_t::iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
       
    81     {
       
    82       *i = 0;
       
    83     }
       
    84   m_protocols.clear ();
       
    85 
       
    86   for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
       
    87     {
       
    88       *i = 0;
       
    89     }
       
    90   m_interfaces.clear ();
       
    91   m_sockets.clear ();
       
    92   m_node = 0;
       
    93   m_routingProtocol = 0;
       
    94   Object::DoDispose ();
       
    95 }
       
    96 
       
    97 void
       
    98 Ipv4L3ClickProtocol::NotifyNewAggregate ()
       
    99 {
       
   100   if (m_node == 0)
       
   101     {
       
   102       Ptr<Node>node = this->GetObject<Node>();
       
   103       // verify that it's a valid node and that
       
   104       // the node has not been set before
       
   105       if (node != 0)
       
   106         {
       
   107           this->SetNode (node);
       
   108         }
       
   109     }
       
   110   Object::NotifyNewAggregate ();
       
   111 }
       
   112 
       
   113 void
       
   114 Ipv4L3ClickProtocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol)
       
   115 {
       
   116   NS_LOG_FUNCTION (this);
       
   117   m_routingProtocol = routingProtocol;
       
   118   m_routingProtocol->SetIpv4 (this);
       
   119 }
       
   120 
       
   121 
       
   122 Ptr<Ipv4RoutingProtocol>
       
   123 Ipv4L3ClickProtocol::GetRoutingProtocol (void) const
       
   124 {
       
   125   return m_routingProtocol;
       
   126 }
       
   127 
       
   128 Ptr<Ipv4Interface>
       
   129 Ipv4L3ClickProtocol::GetInterface (uint32_t index) const
       
   130 {
       
   131   NS_LOG_FUNCTION (this << index);
       
   132   if (index < m_interfaces.size ())
       
   133     {
       
   134       return m_interfaces[index];
       
   135     }
       
   136   return 0;
       
   137 }
       
   138 
       
   139 uint32_t
       
   140 Ipv4L3ClickProtocol::GetNInterfaces (void) const
       
   141 {
       
   142   NS_LOG_FUNCTION_NOARGS ();
       
   143   return m_interfaces.size ();
       
   144 }
       
   145 
       
   146 int32_t
       
   147 Ipv4L3ClickProtocol::GetInterfaceForAddress (
       
   148   Ipv4Address address) const
       
   149 {
       
   150   NS_LOG_FUNCTION (this << address);
       
   151 
       
   152   int32_t interface = 0;
       
   153   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
       
   154        i != m_interfaces.end ();
       
   155        i++, interface++)
       
   156     {
       
   157       for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
       
   158         {
       
   159           if ((*i)->GetAddress (j).GetLocal () == address)
       
   160             {
       
   161               return interface;
       
   162             }
       
   163         }
       
   164     }
       
   165 
       
   166   return -1;
       
   167 }
       
   168 
       
   169 int32_t
       
   170 Ipv4L3ClickProtocol::GetInterfaceForPrefix (
       
   171   Ipv4Address address,
       
   172   Ipv4Mask mask) const
       
   173 {
       
   174   NS_LOG_FUNCTION (this << address << mask);
       
   175 
       
   176   int32_t interface = 0;
       
   177   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
       
   178        i != m_interfaces.end ();
       
   179        i++, interface++)
       
   180     {
       
   181       for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
       
   182         {
       
   183           if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
       
   184             {
       
   185               return interface;
       
   186             }
       
   187         }
       
   188     }
       
   189 
       
   190   return -1;
       
   191 }
       
   192 
       
   193 int32_t
       
   194 Ipv4L3ClickProtocol::GetInterfaceForDevice (
       
   195   Ptr<const NetDevice> device) const
       
   196 {
       
   197   NS_LOG_FUNCTION (this << device->GetIfIndex());
       
   198 
       
   199   int32_t interface = 0;
       
   200   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
       
   201        i != m_interfaces.end ();
       
   202        i++, interface++)
       
   203     {
       
   204       if ((*i)->GetDevice () == device)
       
   205         {
       
   206           return interface;
       
   207         }
       
   208     }
       
   209 
       
   210   return -1;
       
   211 }
       
   212 
       
   213 bool
       
   214 Ipv4L3ClickProtocol::IsDestinationAddress (Ipv4Address address, uint32_t iif) const
       
   215 {
       
   216   NS_LOG_FUNCTION (this << address << " " << iif);
       
   217 
       
   218   // First check the incoming interface for a unicast address match
       
   219   for (uint32_t i = 0; i < GetNAddresses (iif); i++)
       
   220     {
       
   221       Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
       
   222       if (address == iaddr.GetLocal ())
       
   223         {
       
   224           NS_LOG_LOGIC ("For me (destination " << address << " match)");
       
   225           return true;
       
   226         }
       
   227       if (address == iaddr.GetBroadcast ())
       
   228         {
       
   229           NS_LOG_LOGIC ("For me (interface broadcast address)");
       
   230           return true;
       
   231         }
       
   232     }
       
   233 
       
   234   if (address.IsMulticast ())
       
   235     {
       
   236 #ifdef NOTYET
       
   237       if (MulticastCheckGroup (iif, address ))
       
   238 #endif
       
   239       if (true)
       
   240         {
       
   241           NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
       
   242           return true;
       
   243         }
       
   244     }
       
   245 
       
   246   if (address.IsBroadcast ())
       
   247     {
       
   248       NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
       
   249       return true;
       
   250     }
       
   251 
       
   252   if (GetWeakEsModel ())  // Check other interfaces
       
   253     {
       
   254       for (uint32_t j = 0; j < GetNInterfaces (); j++)
       
   255         {
       
   256           if (j == uint32_t (iif)) continue;
       
   257           for (uint32_t i = 0; i < GetNAddresses (j); i++)
       
   258             {
       
   259               Ipv4InterfaceAddress iaddr = GetAddress (j, i);
       
   260               if (address == iaddr.GetLocal ())
       
   261                 {
       
   262                   NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
       
   263                   return true;
       
   264                 }
       
   265               //  This is a small corner case:  match another interface's broadcast address
       
   266               if (address == iaddr.GetBroadcast ())
       
   267                 {
       
   268                   NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
       
   269                   return true;
       
   270                 }
       
   271             }
       
   272         }
       
   273     }
       
   274   return false;
       
   275 }
       
   276 
       
   277 void
       
   278 Ipv4L3ClickProtocol::SetIpForward (bool forward)
       
   279 {
       
   280   NS_LOG_FUNCTION (this << forward);
       
   281   m_ipForward = forward;
       
   282   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
       
   283     {
       
   284       (*i)->SetForwarding (forward);
       
   285     }
       
   286 }
       
   287 
       
   288 bool
       
   289 Ipv4L3ClickProtocol::GetIpForward (void) const
       
   290 {
       
   291   return m_ipForward;
       
   292 }
       
   293 
       
   294 void
       
   295 Ipv4L3ClickProtocol::SetWeakEsModel (bool model)
       
   296 {
       
   297   m_weakEsModel = model;
       
   298 }
       
   299 
       
   300 bool
       
   301 Ipv4L3ClickProtocol::GetWeakEsModel (void) const
       
   302 {
       
   303   return m_weakEsModel;
       
   304 }
       
   305 
       
   306 Ptr<NetDevice>
       
   307 Ipv4L3ClickProtocol::GetNetDevice (uint32_t i)
       
   308 {
       
   309   NS_LOG_FUNCTION (this << i);
       
   310   return GetInterface (i)->GetDevice ();
       
   311 }
       
   312 
       
   313 void
       
   314 Ipv4L3ClickProtocol::SetDefaultTtl (uint8_t ttl)
       
   315 {
       
   316   NS_LOG_FUNCTION_NOARGS ();
       
   317   m_defaultTtl = ttl;
       
   318 }
       
   319 
       
   320 void
       
   321 Ipv4L3ClickProtocol::SetupLoopback (void)
       
   322 {
       
   323   NS_LOG_FUNCTION_NOARGS ();
       
   324 
       
   325   Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
       
   326   Ptr<LoopbackNetDevice> device = 0;
       
   327   // First check whether an existing LoopbackNetDevice exists on the node
       
   328   for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
       
   329     {
       
   330       if (device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i)))
       
   331         {
       
   332           break;
       
   333         }
       
   334     }
       
   335   if (device == 0)
       
   336     {
       
   337       device = CreateObject<LoopbackNetDevice> ();
       
   338       m_node->AddDevice (device);
       
   339     }
       
   340   interface->SetDevice (device);
       
   341   interface->SetNode (m_node);
       
   342   Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
       
   343   interface->AddAddress (ifaceAddr);
       
   344   uint32_t index = AddIpv4Interface (interface);
       
   345   Ptr<Node> node = GetObject<Node> ();
       
   346   node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
       
   347                                  Ipv4L3ClickProtocol::PROT_NUMBER, device);
       
   348   interface->SetUp ();
       
   349   if (m_routingProtocol != 0)
       
   350     {
       
   351       m_routingProtocol->NotifyInterfaceUp (index);
       
   352     }
       
   353 }
       
   354 
       
   355 Ptr<Socket>
       
   356 Ipv4L3ClickProtocol::CreateRawSocket (void)
       
   357 {
       
   358   NS_LOG_FUNCTION (this);
       
   359   Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
       
   360   socket->SetNode (m_node);
       
   361   m_sockets.push_back (socket);
       
   362   return socket;
       
   363 }
       
   364 void
       
   365 Ipv4L3ClickProtocol::DeleteRawSocket (Ptr<Socket> socket)
       
   366 {
       
   367   NS_LOG_FUNCTION (this << socket);
       
   368   for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
       
   369     {
       
   370       if ((*i) == socket)
       
   371         {
       
   372           m_sockets.erase (i);
       
   373           return;
       
   374         }
       
   375     }
       
   376   return;
       
   377 }
       
   378 
       
   379 
       
   380 void
       
   381 Ipv4L3ClickProtocol::SetNode (Ptr<Node> node)
       
   382 {
       
   383   m_node = node;
       
   384   // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
       
   385   SetupLoopback ();
       
   386 }
       
   387 
       
   388 bool
       
   389 Ipv4L3ClickProtocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
       
   390 {
       
   391   NS_LOG_FUNCTION (this << i << address);
       
   392   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   393   bool retVal = interface->AddAddress (address);
       
   394   if (m_routingProtocol != 0)
       
   395     {
       
   396       m_routingProtocol->NotifyAddAddress (i, address);
       
   397     }
       
   398   return retVal;
       
   399 }
       
   400 
       
   401 Ipv4InterfaceAddress
       
   402 Ipv4L3ClickProtocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
       
   403 {
       
   404   NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
       
   405   Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
       
   406   return interface->GetAddress (addressIndex);
       
   407 }
       
   408 
       
   409 uint32_t
       
   410 Ipv4L3ClickProtocol::GetNAddresses (uint32_t interface) const
       
   411 {
       
   412   NS_LOG_FUNCTION (this << interface);
       
   413   Ptr<Ipv4Interface> iface = GetInterface (interface);
       
   414   return iface->GetNAddresses ();
       
   415 }
       
   416 
       
   417 bool
       
   418 Ipv4L3ClickProtocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
       
   419 {
       
   420   NS_LOG_FUNCTION (this << i << addressIndex);
       
   421   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   422   Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
       
   423   if (address != Ipv4InterfaceAddress ())
       
   424     {
       
   425       if (m_routingProtocol != 0)
       
   426         {
       
   427           m_routingProtocol->NotifyRemoveAddress (i, address);
       
   428         }
       
   429       return true;
       
   430     }
       
   431   return false;
       
   432 }
       
   433 
       
   434 Ipv4Address
       
   435 Ipv4L3ClickProtocol::SelectSourceAddress (Ptr<const NetDevice> device,
       
   436                                           Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
       
   437 {
       
   438   NS_LOG_FUNCTION (device << dst << scope);
       
   439   Ipv4Address addr ("0.0.0.0");
       
   440   Ipv4InterfaceAddress iaddr;
       
   441   bool found = false;
       
   442 
       
   443   if (device != 0)
       
   444     {
       
   445       int32_t i = GetInterfaceForDevice (device);
       
   446       NS_ASSERT_MSG (i >= 0, "No device found on node");
       
   447       for (uint32_t j = 0; j < GetNAddresses (i); j++)
       
   448         {
       
   449           iaddr = GetAddress (i, j);
       
   450           if (iaddr.IsSecondary ()) continue;
       
   451           if (iaddr.GetScope () > scope) continue;
       
   452           if (dst.CombineMask (iaddr.GetMask ())  == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
       
   453             {
       
   454               return iaddr.GetLocal ();
       
   455             }
       
   456           if (!found)
       
   457             {
       
   458               addr = iaddr.GetLocal ();
       
   459               found = true;
       
   460             }
       
   461         }
       
   462     }
       
   463   if (found)
       
   464     {
       
   465       return addr;
       
   466     }
       
   467 
       
   468   // Iterate among all interfaces
       
   469   for (uint32_t i = 0; i < GetNInterfaces (); i++)
       
   470     {
       
   471       for (uint32_t j = 0; j < GetNAddresses (i); j++)
       
   472         {
       
   473           iaddr = GetAddress (i, j);
       
   474           if (iaddr.IsSecondary ()) continue;
       
   475           if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
       
   476               && iaddr.GetScope () <= scope)
       
   477             {
       
   478               return iaddr.GetLocal ();
       
   479             }
       
   480         }
       
   481     }
       
   482   NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
       
   483                                                     << scope << ", returning 0");
       
   484   return addr;
       
   485 }
       
   486 
       
   487 void
       
   488 Ipv4L3ClickProtocol::SetMetric (uint32_t i, uint16_t metric)
       
   489 {
       
   490   NS_LOG_FUNCTION (i << metric);
       
   491   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   492   interface->SetMetric (metric);
       
   493 }
       
   494 
       
   495 uint16_t
       
   496 Ipv4L3ClickProtocol::GetMetric (uint32_t i) const
       
   497 {
       
   498   NS_LOG_FUNCTION (i);
       
   499   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   500   return interface->GetMetric ();
       
   501 }
       
   502 
       
   503 uint16_t
       
   504 Ipv4L3ClickProtocol::GetMtu (uint32_t i) const
       
   505 {
       
   506   NS_LOG_FUNCTION (this << i);
       
   507   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   508   return interface->GetDevice ()->GetMtu ();
       
   509 }
       
   510 
       
   511 bool
       
   512 Ipv4L3ClickProtocol::IsUp (uint32_t i) const
       
   513 {
       
   514   NS_LOG_FUNCTION (this << i);
       
   515   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   516   return interface->IsUp ();
       
   517 }
       
   518 
       
   519 void
       
   520 Ipv4L3ClickProtocol::SetUp (uint32_t i)
       
   521 {
       
   522   NS_LOG_FUNCTION (this << i);
       
   523   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   524   interface->SetUp ();
       
   525 
       
   526   if (m_routingProtocol != 0)
       
   527     {
       
   528       m_routingProtocol->NotifyInterfaceUp (i);
       
   529     }
       
   530 }
       
   531 
       
   532 void
       
   533 Ipv4L3ClickProtocol::SetDown (uint32_t ifaceIndex)
       
   534 {
       
   535   NS_LOG_FUNCTION (this << ifaceIndex);
       
   536   Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
       
   537   interface->SetDown ();
       
   538 
       
   539   if (m_routingProtocol != 0)
       
   540     {
       
   541       m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
       
   542     }
       
   543 }
       
   544 
       
   545 bool
       
   546 Ipv4L3ClickProtocol::IsForwarding (uint32_t i) const
       
   547 {
       
   548   NS_LOG_FUNCTION (this << i);
       
   549   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   550   NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
       
   551   return interface->IsForwarding ();
       
   552 }
       
   553 
       
   554 void
       
   555 Ipv4L3ClickProtocol::SetForwarding (uint32_t i, bool val)
       
   556 {
       
   557   NS_LOG_FUNCTION (this << i);
       
   558   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   559   interface->SetForwarding (val);
       
   560 }
       
   561 
       
   562 void
       
   563 Ipv4L3ClickProtocol::SetPromisc (uint32_t i)
       
   564 {
       
   565   NS_ASSERT(i <= m_node->GetNDevices ());
       
   566   if (i > m_promiscDeviceList.size ())
       
   567     {
       
   568       m_promiscDeviceList.resize (i);
       
   569     }
       
   570   std::vector<bool>::iterator it = m_promiscDeviceList.begin();
       
   571   std::advance (it, i);
       
   572   m_promiscDeviceList.insert (it, true);
       
   573 }
       
   574 
       
   575 uint32_t
       
   576 Ipv4L3ClickProtocol::AddInterface (Ptr<NetDevice> device)
       
   577 {
       
   578   NS_LOG_FUNCTION (this << &device);
       
   579 
       
   580   Ptr<Node> node = GetObject<Node> ();
       
   581   NS_LOG_DEBUG("Size:" << m_promiscDeviceList.size () << " Interface index" << device->GetIfIndex ());
       
   582   if (m_promiscDeviceList.size () > 0 &&
       
   583       (m_promiscDeviceList.size () >= device->GetIfIndex ()) &&
       
   584       (m_promiscDeviceList[device->GetIfIndex ()]))
       
   585     {
       
   586       node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
       
   587                                      0, device,true);
       
   588     }
       
   589   else
       
   590     {
       
   591       node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
       
   592                                      Ipv4L3ClickProtocol::PROT_NUMBER, device);
       
   593     }
       
   594   node->RegisterProtocolHandler (MakeCallback (&Ipv4L3ClickProtocol::Receive, this),
       
   595                                  ArpL3Protocol::PROT_NUMBER, device);
       
   596 
       
   597   Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
       
   598   interface->SetNode (m_node);
       
   599   interface->SetDevice (device);
       
   600   interface->SetForwarding (m_ipForward);
       
   601   return AddIpv4Interface (interface);
       
   602 }
       
   603 
       
   604 uint32_t
       
   605 Ipv4L3ClickProtocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
       
   606 {
       
   607   NS_LOG_FUNCTION (this << interface);
       
   608   uint32_t index = m_interfaces.size ();
       
   609   m_interfaces.push_back (interface);
       
   610   return index;
       
   611 }
       
   612 
       
   613 // XXX when should we set ip_id?   check whether we are incrementing
       
   614 // m_identification on packets that may later be dropped in this stack
       
   615 // and whether that deviates from Linux
       
   616 Ipv4Header
       
   617 Ipv4L3ClickProtocol::BuildHeader (
       
   618   Ipv4Address source,
       
   619   Ipv4Address destination,
       
   620   uint8_t protocol,
       
   621   uint16_t payloadSize,
       
   622   uint8_t ttl,
       
   623   bool mayFragment)
       
   624 {
       
   625   NS_LOG_FUNCTION_NOARGS ();
       
   626   Ipv4Header ipHeader;
       
   627   ipHeader.SetSource (source);
       
   628   ipHeader.SetDestination (destination);
       
   629   ipHeader.SetProtocol (protocol);
       
   630   ipHeader.SetPayloadSize (payloadSize);
       
   631   ipHeader.SetTtl (ttl);
       
   632   if (mayFragment == true)
       
   633     {
       
   634       ipHeader.SetMayFragment ();
       
   635       ipHeader.SetIdentification (m_identification);
       
   636       m_identification++;
       
   637     }
       
   638   else
       
   639     {
       
   640       ipHeader.SetDontFragment ();
       
   641       // TBD:  set to zero here; will cause traces to change
       
   642       ipHeader.SetIdentification (m_identification);
       
   643       m_identification++;
       
   644     }
       
   645   if (Node::ChecksumEnabled ())
       
   646     {
       
   647       ipHeader.EnableChecksum ();
       
   648     }
       
   649   return ipHeader;
       
   650 }
       
   651 
       
   652 void
       
   653 Ipv4L3ClickProtocol::Send (Ptr<Packet> packet,
       
   654                            Ipv4Address source,
       
   655                            Ipv4Address destination,
       
   656                            uint8_t protocol,
       
   657                            Ptr<Ipv4Route> route)
       
   658 {
       
   659   NS_LOG_FUNCTION (this << packet << source << destination << uint32_t(protocol) << route);
       
   660 
       
   661   Ipv4Header ipHeader;
       
   662   bool mayFragment = true;
       
   663   uint8_t ttl = m_defaultTtl;
       
   664   SocketIpTtlTag tag;
       
   665   bool found = packet->RemovePacketTag (tag);
       
   666   if (found)
       
   667     {
       
   668       ttl = tag.GetTtl ();
       
   669     }
       
   670 
       
   671   ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
       
   672   Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (m_routingProtocol);
       
   673   if (Node::ChecksumEnabled ())
       
   674     {
       
   675       ipHeader.EnableChecksum ();
       
   676     }
       
   677   packet->AddHeader (ipHeader);
       
   678   click->Send (packet->Copy (), source, destination);
       
   679   return;
       
   680 }
       
   681 
       
   682 void
       
   683 Ipv4L3ClickProtocol::SendDown (Ptr<Packet> p, int ifid)
       
   684 {
       
   685   // Called by Ipv4ClickRouting.
       
   686 
       
   687   // NetDevice::Send () attaches ethernet headers,
       
   688   // so the one that Click attaches isn't required
       
   689   // but we need the destination address and
       
   690   // protocol values from the header.
       
   691 
       
   692   Ptr<NetDevice> netdev = GetNetDevice (ifid);
       
   693 
       
   694   EthernetHeader header;
       
   695   p->RemoveHeader (header);
       
   696 
       
   697   uint16_t protocol;
       
   698 
       
   699   if (header.GetLengthType () <= 1500)
       
   700     {
       
   701       LlcSnapHeader llc;
       
   702       p->RemoveHeader (llc);
       
   703       protocol = llc.GetType ();
       
   704     }
       
   705   else
       
   706     {
       
   707       protocol = header.GetLengthType ();
       
   708     }
       
   709 
       
   710   // Use the destination address and protocol obtained
       
   711   // from above to send the packet.
       
   712   netdev->Send (p, header.GetDestination (), protocol); 
       
   713 }
       
   714 
       
   715 void
       
   716 Ipv4L3ClickProtocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
       
   717                               const Address &to, NetDevice::PacketType packetType)
       
   718 {
       
   719   NS_LOG_FUNCTION (this << device << p << from << to);
       
   720   Ptr<Packet> packet = p->Copy ();
       
   721   
       
   722   // Add an ethernet frame. This allows
       
   723   // Click to work with csma and wifi
       
   724   EthernetHeader hdr;
       
   725   hdr.SetSource (Mac48Address::ConvertFrom (from));
       
   726   hdr.SetDestination (Mac48Address::ConvertFrom (to));
       
   727   hdr.SetLengthType (protocol);
       
   728   packet->AddHeader (hdr);
       
   729   
       
   730   Ptr<Ipv4ClickRouting> click = DynamicCast<Ipv4ClickRouting> (GetRoutingProtocol ());
       
   731   click->Receive (packet->Copy (), Mac48Address::ConvertFrom (device->GetAddress ()), Mac48Address::ConvertFrom (to));
       
   732 }
       
   733 
       
   734 void
       
   735 Ipv4L3ClickProtocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
       
   736 {
       
   737   NS_LOG_FUNCTION (this << packet << &ip);
       
   738   Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
       
   739 
       
   740   m_localDeliverTrace (ip, packet, iif);
       
   741 
       
   742   Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
       
   743   if (protocol != 0)
       
   744     {
       
   745       // we need to make a copy in the unlikely event we hit the
       
   746       // RX_ENDPOINT_UNREACH codepath
       
   747       Ptr<Packet> copy = p->Copy ();
       
   748       enum Ipv4L4Protocol::RxStatus status =
       
   749         protocol->Receive (p, ip, GetInterface (iif));
       
   750       switch (status) {
       
   751         case Ipv4L4Protocol::RX_OK:
       
   752         // fall through
       
   753         case Ipv4L4Protocol::RX_ENDPOINT_CLOSED:
       
   754         // fall through
       
   755         case Ipv4L4Protocol::RX_CSUM_FAILED:
       
   756           break;
       
   757         case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
       
   758           if (ip.GetDestination ().IsBroadcast () == true ||
       
   759               ip.GetDestination ().IsMulticast () == true)
       
   760             {
       
   761               break; // Do not reply to broadcast or multicast
       
   762             }
       
   763           // Another case to suppress ICMP is a subnet-directed broadcast
       
   764           bool subnetDirected = false;
       
   765           for (uint32_t i = 0; i < GetNAddresses (iif); i++)
       
   766             {
       
   767               Ipv4InterfaceAddress addr = GetAddress (iif, i);
       
   768               if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination().CombineMask (addr.GetMask ()) &&
       
   769                   ip.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
       
   770                 {
       
   771                   subnetDirected = true;
       
   772                 }
       
   773             }
       
   774           if (subnetDirected == false)
       
   775             {
       
   776               GetIcmp ()->SendDestUnreachPort (ip, copy);
       
   777             }
       
   778         }
       
   779     }
       
   780 }
       
   781 
       
   782 Ptr<Icmpv4L4Protocol>
       
   783 Ipv4L3ClickProtocol::GetIcmp (void) const
       
   784 {
       
   785   Ptr<Ipv4L4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
       
   786   if (prot != 0)
       
   787     {
       
   788       return prot->GetObject<Icmpv4L4Protocol> ();
       
   789     }
       
   790   else
       
   791     {
       
   792       return 0;
       
   793     }
       
   794 }
       
   795 
       
   796 void
       
   797 Ipv4L3ClickProtocol::Insert(Ptr<Ipv4L4Protocol> protocol)
       
   798 {
       
   799   m_protocols.push_back (protocol);
       
   800 }
       
   801 
       
   802 Ptr<Ipv4L4Protocol>
       
   803 Ipv4L3ClickProtocol::GetProtocol(int protocolNumber) const
       
   804 {
       
   805   for (L4List_t::const_iterator i = m_protocols.begin(); i != m_protocols.end(); ++i)
       
   806     {
       
   807       if ((*i)->GetProtocolNumber () == protocolNumber)
       
   808         {
       
   809           return *i;
       
   810         }
       
   811     }
       
   812   return 0;
       
   813 }
       
   814 
       
   815 
       
   816 } // namespace ns3
       
   817 
       
   818 #endif // NS3_CLICK