src/internet-stack/ipv4-l3-protocol.cc
changeset 3260 8c0ab08144e6
parent 3235 c2f34dac1b9e
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 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 //
       
    20 
       
    21 #include "ns3/packet.h"
       
    22 #include "ns3/log.h"
       
    23 #include "ns3/callback.h"
       
    24 #include "ns3/ipv4-address.h"
       
    25 #include "ns3/ipv4-route.h"
       
    26 #include "ns3/node.h"
       
    27 #include "ns3/socket.h"
       
    28 #include "ns3/net-device.h"
       
    29 #include "ns3/uinteger.h"
       
    30 #include "ns3/trace-source-accessor.h"
       
    31 #include "ns3/object-vector.h"
       
    32 #include "ns3/ipv4-header.h"
       
    33 #include "ns3/boolean.h"
       
    34 #include "arp-l3-protocol.h"
       
    35 
       
    36 #include "ipv4-l3-protocol.h"
       
    37 #include "ipv4-l4-protocol.h"
       
    38 #include "ipv4-interface.h"
       
    39 #include "ipv4-loopback-interface.h"
       
    40 #include "arp-ipv4-interface.h"
       
    41 #include "ipv4-l4-demux.h"
       
    42 
       
    43 NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
       
    44 
       
    45 namespace ns3 {
       
    46 
       
    47 const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
       
    48 
       
    49 NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
       
    50 
       
    51 TypeId 
       
    52 Ipv4L3Protocol::GetTypeId (void)
       
    53 {
       
    54   static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
       
    55     .SetParent<Object> ()
       
    56     .AddConstructor<Ipv4L3Protocol> ()
       
    57     .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
       
    58                    UintegerValue (64),
       
    59                    MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl),
       
    60                    MakeUintegerChecker<uint8_t> ())
       
    61     .AddAttribute ("CalcChecksum", "If true, we calculate the checksum of outgoing packets"
       
    62                    " and verify the checksum of incoming packets.",
       
    63                    BooleanValue (false),
       
    64                    MakeBooleanAccessor (&Ipv4L3Protocol::m_calcChecksum),
       
    65                    MakeBooleanChecker ())
       
    66     .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
       
    67                    MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace))
       
    68     .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
       
    69                      MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace))
       
    70     .AddTraceSource ("Drop", "Drop ipv4 packet",
       
    71                      MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace))
       
    72     .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
       
    73                    ObjectVectorValue (),
       
    74                    MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces),
       
    75                    MakeObjectVectorChecker<Ipv4Interface> ())
       
    76     ;
       
    77   return tid;
       
    78 }
       
    79 
       
    80 Ipv4L3Protocol::Ipv4L3Protocol()
       
    81   : m_nInterfaces (0),
       
    82     m_identification (0)
       
    83 {
       
    84   NS_LOG_FUNCTION_NOARGS ();
       
    85   m_staticRouting = CreateObject<Ipv4StaticRouting> ();
       
    86   AddRoutingProtocol (m_staticRouting, 0);
       
    87 }
       
    88 
       
    89 Ipv4L3Protocol::~Ipv4L3Protocol ()
       
    90 {
       
    91   NS_LOG_FUNCTION (this);
       
    92 }
       
    93 
       
    94 void
       
    95 Ipv4L3Protocol::SetNode (Ptr<Node> node)
       
    96 {
       
    97   m_node = node;
       
    98   SetupLoopback ();
       
    99 }
       
   100 
       
   101 void 
       
   102 Ipv4L3Protocol::DoDispose (void)
       
   103 {
       
   104   NS_LOG_FUNCTION (this);
       
   105   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
       
   106     {
       
   107       Ptr<Ipv4Interface> interface = *i;
       
   108       interface->Dispose ();
       
   109     }
       
   110   m_interfaces.clear ();
       
   111   m_node = 0;
       
   112   m_staticRouting->Dispose ();
       
   113   m_staticRouting = 0;
       
   114   Object::DoDispose ();
       
   115 }
       
   116 
       
   117 void
       
   118 Ipv4L3Protocol::SetupLoopback (void)
       
   119 {
       
   120   NS_LOG_FUNCTION_NOARGS ();
       
   121 
       
   122   Ptr<Ipv4LoopbackInterface> interface = CreateObject<Ipv4LoopbackInterface> ();
       
   123   interface->SetNode (m_node);
       
   124   interface->SetAddress (Ipv4Address::GetLoopback ());
       
   125   interface->SetNetworkMask (Ipv4Mask::GetLoopback ());
       
   126   uint32_t index = AddIpv4Interface (interface);
       
   127   AddHostRouteTo (Ipv4Address::GetLoopback (), index);
       
   128   interface->SetUp ();
       
   129 }
       
   130 
       
   131 void 
       
   132 Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
       
   133 {
       
   134   NS_LOG_FUNCTION_NOARGS ();
       
   135   m_defaultTtl = ttl;
       
   136 }
       
   137     
       
   138 
       
   139 void 
       
   140 Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
       
   141                       Ipv4Address nextHop, 
       
   142                       uint32_t interface)
       
   143 {
       
   144   NS_LOG_FUNCTION (this << dest << nextHop << interface);
       
   145   m_staticRouting->AddHostRouteTo (dest, nextHop, interface);
       
   146 }
       
   147 
       
   148 void 
       
   149 Ipv4L3Protocol::AddHostRouteTo (Ipv4Address dest, 
       
   150 				uint32_t interface)
       
   151 {
       
   152   NS_LOG_FUNCTION (this << dest << interface);
       
   153   m_staticRouting->AddHostRouteTo (dest, interface);
       
   154 }
       
   155 
       
   156 void 
       
   157 Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
       
   158 				   Ipv4Mask networkMask, 
       
   159 				   Ipv4Address nextHop, 
       
   160 				   uint32_t interface)
       
   161 {
       
   162   NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
       
   163   m_staticRouting->AddNetworkRouteTo (network, networkMask, nextHop, interface);
       
   164 }
       
   165 
       
   166 void 
       
   167 Ipv4L3Protocol::AddNetworkRouteTo (Ipv4Address network, 
       
   168 				   Ipv4Mask networkMask, 
       
   169 				   uint32_t interface)
       
   170 {
       
   171   NS_LOG_FUNCTION (this << network << networkMask << interface);
       
   172   m_staticRouting->AddNetworkRouteTo (network, networkMask, interface);
       
   173 }
       
   174 
       
   175 void 
       
   176 Ipv4L3Protocol::SetDefaultRoute (Ipv4Address nextHop, 
       
   177 				 uint32_t interface)
       
   178 {
       
   179   NS_LOG_FUNCTION (this << nextHop << interface);
       
   180   m_staticRouting->SetDefaultRoute (nextHop, interface);
       
   181 }
       
   182 
       
   183 void
       
   184 Ipv4L3Protocol::Lookup (
       
   185   Ipv4Header const &ipHeader,
       
   186   Ptr<Packet> packet,
       
   187   Ipv4RoutingProtocol::RouteReplyCallback routeReply)
       
   188 {
       
   189   NS_LOG_FUNCTION (this << &ipHeader << packet << &routeReply);
       
   190 
       
   191   Lookup (Ipv4RoutingProtocol::IF_INDEX_ANY, ipHeader, packet, routeReply);
       
   192 }
       
   193 
       
   194 void
       
   195 Ipv4L3Protocol::Lookup (
       
   196   uint32_t ifIndex,
       
   197   Ipv4Header const &ipHeader,
       
   198   Ptr<Packet> packet,
       
   199   Ipv4RoutingProtocol::RouteReplyCallback routeReply)
       
   200 {
       
   201   NS_LOG_FUNCTION (this << ifIndex << &ipHeader << packet << &routeReply);
       
   202 
       
   203   for (Ipv4RoutingProtocolList::const_iterator rprotoIter = 
       
   204          m_routingProtocols.begin ();
       
   205        rprotoIter != m_routingProtocols.end (); 
       
   206        rprotoIter++)
       
   207     {
       
   208       NS_LOG_LOGIC ("Requesting route");
       
   209       if ((*rprotoIter).second->RequestRoute (ifIndex, ipHeader, packet, 
       
   210                                               routeReply))
       
   211         return;
       
   212     }
       
   213 
       
   214   if (ipHeader.GetDestination ().IsMulticast () && 
       
   215       ifIndex == Ipv4RoutingProtocol::IF_INDEX_ANY)
       
   216     {
       
   217       NS_LOG_LOGIC ("Multicast destination with local source");
       
   218 //
       
   219 // We have a multicast packet originating from the current node and were not
       
   220 // able to send it using the usual RequestRoute process.  Since the usual
       
   221 // process includes trying to use a default multicast route, this means that
       
   222 // there was no specific route out of the node found, and there was no default
       
   223 // multicast route set.
       
   224 //
       
   225 // The fallback position is to look for a default unicast route and use that
       
   226 // to get the packet off the node if we have one.
       
   227 //
       
   228       Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
       
   229 
       
   230       if (route)
       
   231         {
       
   232           NS_LOG_LOGIC ("Local source. Using unicast default route for "
       
   233             "multicast packet");
       
   234 
       
   235           routeReply (true, *route, packet, ipHeader);
       
   236           return;
       
   237         }
       
   238     }
       
   239 //
       
   240 // No route found
       
   241 //
       
   242   routeReply (false, Ipv4Route (), packet, ipHeader);
       
   243 }
       
   244 
       
   245 void
       
   246 Ipv4L3Protocol::AddRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol,
       
   247                                     int priority)
       
   248 {
       
   249   NS_LOG_FUNCTION (this << &routingProtocol << priority);
       
   250   m_routingProtocols.push_back
       
   251     (std::pair<int, Ptr<Ipv4RoutingProtocol> > (-priority, routingProtocol));
       
   252   m_routingProtocols.sort ();
       
   253 }
       
   254 
       
   255 uint32_t 
       
   256 Ipv4L3Protocol::GetNRoutes (void)
       
   257 {
       
   258   NS_LOG_FUNCTION_NOARGS ();
       
   259   return m_staticRouting->GetNRoutes ();
       
   260 }
       
   261 
       
   262 Ipv4Route *
       
   263 Ipv4L3Protocol::GetRoute (uint32_t index)
       
   264 {
       
   265   NS_LOG_FUNCTION_NOARGS ();
       
   266   return m_staticRouting->GetRoute (index);
       
   267 }
       
   268 
       
   269 void 
       
   270 Ipv4L3Protocol::RemoveRoute (uint32_t index)
       
   271 {
       
   272   NS_LOG_FUNCTION (this << index);
       
   273   m_staticRouting->RemoveRoute (index);
       
   274 }
       
   275 
       
   276 void 
       
   277 Ipv4L3Protocol::AddMulticastRoute (Ipv4Address origin,
       
   278                                    Ipv4Address group,
       
   279                                    uint32_t inputInterface,
       
   280                                    std::vector<uint32_t> outputInterfaces)
       
   281 {
       
   282   NS_LOG_FUNCTION (this << origin << group << inputInterface << &outputInterfaces);
       
   283 
       
   284   m_staticRouting->AddMulticastRoute (origin, group, inputInterface,
       
   285     outputInterfaces);
       
   286 }
       
   287 
       
   288 void 
       
   289 Ipv4L3Protocol::SetDefaultMulticastRoute (uint32_t outputInterface)
       
   290 {
       
   291   NS_LOG_FUNCTION (this << outputInterface);
       
   292 
       
   293   m_staticRouting->SetDefaultMulticastRoute (outputInterface);
       
   294 }
       
   295 
       
   296 uint32_t 
       
   297 Ipv4L3Protocol::GetNMulticastRoutes (void) const
       
   298 {
       
   299   NS_LOG_FUNCTION_NOARGS ();
       
   300   return m_staticRouting->GetNMulticastRoutes ();
       
   301 }
       
   302 
       
   303 Ipv4MulticastRoute *
       
   304 Ipv4L3Protocol::GetMulticastRoute (uint32_t index) const
       
   305 {
       
   306   NS_LOG_FUNCTION (this << index);
       
   307   return m_staticRouting->GetMulticastRoute (index);
       
   308 }
       
   309 
       
   310 void 
       
   311 Ipv4L3Protocol::RemoveMulticastRoute (Ipv4Address origin,
       
   312                                        Ipv4Address group,
       
   313                                        uint32_t inputInterface)
       
   314 {
       
   315   NS_LOG_FUNCTION (this << origin << group << inputInterface);
       
   316   m_staticRouting->RemoveMulticastRoute (origin, group, inputInterface);
       
   317 }
       
   318 
       
   319 void 
       
   320 Ipv4L3Protocol::RemoveMulticastRoute (uint32_t index)
       
   321 {
       
   322   NS_LOG_FUNCTION (this << index);
       
   323   m_staticRouting->RemoveMulticastRoute (index);
       
   324 }
       
   325 
       
   326 uint32_t 
       
   327 Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
       
   328 {
       
   329   NS_LOG_FUNCTION (this << &device);
       
   330 
       
   331   Ptr<Node> node = GetObject<Node> ();
       
   332   node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), 
       
   333                                  Ipv4L3Protocol::PROT_NUMBER, device);
       
   334   node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
       
   335                                  ArpL3Protocol::PROT_NUMBER, device);
       
   336 
       
   337   Ptr<ArpIpv4Interface> interface = CreateObject<ArpIpv4Interface> ();
       
   338   interface->SetNode (m_node);
       
   339   interface->SetDevice (device);
       
   340   return AddIpv4Interface (interface);
       
   341 }
       
   342 
       
   343 uint32_t 
       
   344 Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
       
   345 {
       
   346   NS_LOG_FUNCTION (this << interface);
       
   347   uint32_t index = m_nInterfaces;
       
   348   m_interfaces.push_back (interface);
       
   349   m_nInterfaces++;
       
   350   return index;
       
   351 }
       
   352 
       
   353 Ptr<Ipv4Interface>
       
   354 Ipv4L3Protocol::GetInterface (uint32_t index) const
       
   355 {
       
   356   NS_LOG_FUNCTION (this << index);
       
   357   uint32_t tmp = 0;
       
   358   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
       
   359     {
       
   360       if (index == tmp) 
       
   361 	{
       
   362 	  return *i;
       
   363 	}
       
   364       tmp++;
       
   365     }
       
   366   return 0;
       
   367 }
       
   368 
       
   369 uint32_t 
       
   370 Ipv4L3Protocol::GetNInterfaces (void) const
       
   371 {
       
   372   NS_LOG_FUNCTION_NOARGS ();
       
   373   return m_nInterfaces;
       
   374 }
       
   375 
       
   376 uint32_t 
       
   377 Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr) const
       
   378 {
       
   379   NS_LOG_FUNCTION (this << addr);
       
   380 
       
   381   uint32_t ifIndex = 0;
       
   382   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
       
   383        i != m_interfaces.end (); 
       
   384        i++, ifIndex++)
       
   385     {
       
   386       if ((*i)->GetAddress () == addr)
       
   387         {
       
   388           return ifIndex;
       
   389         }
       
   390     }
       
   391 
       
   392   NS_FATAL_ERROR ("Ipv4L3Protocol::FindInterfaceForAddr (): "
       
   393                   "Interface not found for IP address " << addr);
       
   394   return 0;
       
   395 }
       
   396 
       
   397 uint32_t 
       
   398 Ipv4L3Protocol::FindInterfaceForAddr (Ipv4Address addr, Ipv4Mask mask) const
       
   399 {
       
   400   NS_LOG_FUNCTION (this << addr << mask);
       
   401 
       
   402   uint32_t ifIndex = 0;
       
   403   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
       
   404        i != m_interfaces.end (); 
       
   405        i++, ifIndex++)
       
   406     {
       
   407       if ((*i)->GetAddress ().CombineMask (mask) == addr.CombineMask (mask))
       
   408         {
       
   409           return ifIndex;
       
   410         }
       
   411     }
       
   412 
       
   413   NS_ASSERT_MSG(false, "Ipv4L3Protocol::FindInterfaceForAddr (): "
       
   414     "Interface not found for masked IP address");
       
   415   return 0;
       
   416 }
       
   417 
       
   418 int32_t 
       
   419 Ipv4L3Protocol::FindInterfaceIndexForDevice (Ptr<NetDevice> device) const
       
   420 {
       
   421   NS_LOG_FUNCTION (this << device);
       
   422 
       
   423   uint32_t ifIndex = 0;
       
   424   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
       
   425        i != m_interfaces.end (); 
       
   426        i++, ifIndex++)
       
   427     {
       
   428       if ((*i)->GetDevice () == device)
       
   429         {
       
   430           return ifIndex;
       
   431         }
       
   432     }
       
   433 
       
   434   return -1;
       
   435 }
       
   436 
       
   437 Ptr<Ipv4Interface>
       
   438 Ipv4L3Protocol::FindInterfaceForDevice (Ptr<const NetDevice> device)
       
   439 {
       
   440   NS_LOG_FUNCTION (this << &device);
       
   441   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
       
   442     {
       
   443       if ((*i)->GetDevice () == device)
       
   444         {
       
   445           return *i;
       
   446         }
       
   447     }
       
   448   return 0;
       
   449 }  
       
   450 
       
   451 void 
       
   452 Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<Packet> packet, uint16_t protocol, const Address &from)
       
   453 {
       
   454   NS_LOG_FUNCTION (this << &device << packet << protocol <<  from);
       
   455 
       
   456   NS_LOG_LOGIC ("Packet from " << from << " received on node " << m_node->GetId ());
       
   457 
       
   458   uint32_t index = 0;
       
   459   Ptr<Ipv4Interface> ipv4Interface;
       
   460   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
       
   461        i != m_interfaces.end (); 
       
   462        i++)
       
   463     {
       
   464       ipv4Interface = *i;
       
   465       if (ipv4Interface->GetDevice () == device)
       
   466         {
       
   467           m_rxTrace (packet, index);
       
   468           break;
       
   469         }
       
   470       index++;
       
   471     }
       
   472   Ipv4Header ipHeader;
       
   473   if (m_calcChecksum)
       
   474     {
       
   475       ipHeader.EnableChecksum ();
       
   476     }
       
   477   packet->RemoveHeader (ipHeader);
       
   478 
       
   479   if (!ipHeader.IsChecksumOk ()) 
       
   480     {
       
   481       m_dropTrace (packet);
       
   482       return;
       
   483     }
       
   484 
       
   485   if (Forwarding (index, packet, ipHeader, device)) 
       
   486     {
       
   487       return;
       
   488     }
       
   489 
       
   490   ForwardUp (packet, ipHeader, ipv4Interface);
       
   491 }
       
   492 
       
   493 
       
   494 void 
       
   495 Ipv4L3Protocol::Send (Ptr<Packet> packet, 
       
   496             Ipv4Address source, 
       
   497             Ipv4Address destination,
       
   498             uint8_t protocol)
       
   499 {
       
   500   NS_LOG_FUNCTION (this << packet << source << destination << protocol);
       
   501 
       
   502   Ipv4Header ipHeader;
       
   503 
       
   504   if (m_calcChecksum)
       
   505     {
       
   506       ipHeader.EnableChecksum ();
       
   507     }
       
   508 
       
   509   ipHeader.SetSource (source);
       
   510   ipHeader.SetDestination (destination);
       
   511   ipHeader.SetProtocol (protocol);
       
   512   ipHeader.SetPayloadSize (packet->GetSize ());
       
   513   ipHeader.SetTtl (m_defaultTtl);
       
   514   ipHeader.SetMayFragment ();
       
   515   ipHeader.SetIdentification (m_identification);
       
   516 
       
   517   m_identification ++;
       
   518 
       
   519   // Set TTL to 1 if it is a broadcast packet of any type.  Otherwise,
       
   520   // possibly override the default TTL if the packet is tagged
       
   521   SocketIpTtlTag tag;
       
   522   bool found = packet->FindFirstMatchingTag (tag);
       
   523 
       
   524   if (destination.IsBroadcast ()) 
       
   525     {
       
   526       ipHeader.SetTtl (1);
       
   527     }
       
   528   else if (found)
       
   529     {
       
   530       ipHeader.SetTtl (tag.GetTtl ());
       
   531       // XXX remove tag here?  
       
   532     }
       
   533   else
       
   534     {
       
   535       uint32_t ifaceIndex = 0;
       
   536       for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
       
   537            ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
       
   538         {
       
   539           Ptr<Ipv4Interface> outInterface = *ifaceIter;
       
   540           if (destination.IsSubnetDirectedBroadcast (
       
   541                 outInterface->GetNetworkMask ()))
       
   542           {
       
   543             ipHeader.SetTtl (1);
       
   544           }
       
   545         }
       
   546     }
       
   547   if (destination.IsBroadcast ())
       
   548     {
       
   549       uint32_t ifaceIndex = 0;
       
   550       for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
       
   551            ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
       
   552         {
       
   553           Ptr<Ipv4Interface> outInterface = *ifaceIter;
       
   554           Ptr<Packet> packetCopy = packet->Copy ();
       
   555 
       
   556           NS_ASSERT (packetCopy->GetSize () <= outInterface->GetMtu ());
       
   557           packetCopy->AddHeader (ipHeader);
       
   558           m_txTrace (packetCopy, ifaceIndex);
       
   559           outInterface->Send (packetCopy, destination);
       
   560         }
       
   561     }
       
   562   else
       
   563     {
       
   564       // XXX Note here that in most ipv4 stacks in the world,
       
   565       // the route calculation for an outgoing packet is not
       
   566       // done in the ip layer. It is done within the application
       
   567       // socket when the first packet is sent to avoid this
       
   568       // costly lookup on a per-packet basis.
       
   569       // That would require us to get the route from the packet,
       
   570       // most likely with a packet tag. The higher layers do not
       
   571       // do this yet for us.
       
   572       Lookup (ipHeader, packet,
       
   573               MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
       
   574     }
       
   575 }
       
   576 
       
   577 void
       
   578 Ipv4L3Protocol::SendRealOut (bool found,
       
   579                              Ipv4Route const &route,
       
   580                              Ptr<Packet> packet,
       
   581                              Ipv4Header const &ipHeader)
       
   582 {
       
   583   NS_LOG_FUNCTION (this << found << &route << packet << &ipHeader);
       
   584 
       
   585   packet->AddHeader (ipHeader);
       
   586   if (!found)
       
   587     {
       
   588       NS_LOG_WARN ("No route to host.  Drop.");
       
   589       m_dropTrace (packet);
       
   590       return;
       
   591     }
       
   592 
       
   593   NS_LOG_LOGIC ("Send via interface " << route.GetInterface ());
       
   594 
       
   595   Ptr<Ipv4Interface> outInterface = GetInterface (route.GetInterface ());
       
   596   NS_ASSERT (packet->GetSize () <= outInterface->GetMtu ());
       
   597   m_txTrace (packet, route.GetInterface ());
       
   598   if (route.IsGateway ()) 
       
   599     {
       
   600       NS_LOG_LOGIC ("Send to gateway " << route.GetGateway ());
       
   601       outInterface->Send (packet, route.GetGateway ());
       
   602     } 
       
   603   else 
       
   604     {
       
   605       NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
       
   606       outInterface->Send (packet, ipHeader.GetDestination ());
       
   607     }
       
   608 }
       
   609 
       
   610 bool
       
   611 Ipv4L3Protocol::Forwarding (
       
   612   uint32_t ifIndex, 
       
   613   Ptr<Packet> packet, 
       
   614   Ipv4Header &ipHeader, 
       
   615   Ptr<NetDevice> device)
       
   616 {
       
   617   NS_LOG_FUNCTION (ifIndex << packet << &ipHeader<< device);
       
   618   NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
       
   619 
       
   620   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
       
   621        i != m_interfaces.end (); i++) 
       
   622     {
       
   623       if ((*i)->GetAddress ().IsEqual (ipHeader.GetDestination ())) 
       
   624         {
       
   625           NS_LOG_LOGIC ("For me (destination match)");
       
   626           return false;
       
   627         }
       
   628     }
       
   629   
       
   630   for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
       
   631        i != m_interfaces.end (); i++) 
       
   632     {
       
   633       Ptr<Ipv4Interface> interface = *i;
       
   634       if (interface->GetDevice () == device)
       
   635 	{
       
   636 	  if (ipHeader.GetDestination ().IsEqual (interface->GetBroadcast ())) 
       
   637 	    {
       
   638               NS_LOG_LOGIC ("For me (interface broadcast address)");
       
   639 	      return false;
       
   640 	    }
       
   641 	  break;
       
   642 	}
       
   643     }
       
   644       
       
   645   if (ipHeader.GetDestination ().IsBroadcast ()) 
       
   646     {
       
   647       NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
       
   648       return false;
       
   649     }
       
   650 
       
   651   if (ipHeader.GetDestination ().IsEqual (Ipv4Address::GetAny ())) 
       
   652     {
       
   653       NS_LOG_LOGIC ("For me (Ipv4Addr any address)");
       
   654       return false;
       
   655     }
       
   656 
       
   657   if (ipHeader.GetTtl () == 1) 
       
   658     {
       
   659       // Should send ttl expired here
       
   660       // XXX
       
   661       NS_LOG_LOGIC ("Not for me (TTL expired).  Drop");
       
   662       m_dropTrace (packet);
       
   663       return true;
       
   664     }
       
   665   ipHeader.SetTtl (ipHeader.GetTtl () - 1);
       
   666 
       
   667 //  
       
   668 // If this is a to a multicast address and this node is a member of the 
       
   669 // indicated group we need to return false so the multicast is forwarded up.
       
   670 //        
       
   671   for (Ipv4MulticastGroupList::const_iterator i = m_multicastGroups.begin ();
       
   672        i != m_multicastGroups.end (); i++)
       
   673     {
       
   674       if ((*i).first.IsEqual (ipHeader.GetSource ()) &&
       
   675           (*i).second.IsEqual (ipHeader.GetDestination ()))
       
   676         {
       
   677           NS_LOG_LOGIC ("For me (Joined multicast group)");
       
   678           // We forward with a packet copy, since forwarding may change
       
   679           // the packet, affecting our local delivery
       
   680           NS_LOG_LOGIC ("Forwarding (multicast).");
       
   681           Lookup (ifIndex, ipHeader, packet->Copy (),
       
   682           MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
       
   683           return false;
       
   684         }   
       
   685     }     
       
   686   NS_LOG_LOGIC ("Not for me, forwarding.");
       
   687   Lookup (ifIndex, ipHeader, packet,
       
   688   MakeCallback (&Ipv4L3Protocol::SendRealOut, this));
       
   689   
       
   690   return true;
       
   691 }
       
   692 
       
   693 void
       
   694 Ipv4L3Protocol::ForwardUp (Ptr<Packet> p, Ipv4Header const&ip,
       
   695                            Ptr<Ipv4Interface> incomingInterface)
       
   696 {
       
   697   NS_LOG_FUNCTION (this << p << &ip);
       
   698 
       
   699   Ptr<Ipv4L4Demux> demux = m_node->GetObject<Ipv4L4Demux> ();
       
   700   Ptr<Ipv4L4Protocol> protocol = demux->GetProtocol (ip.GetProtocol ());
       
   701   protocol->Receive (p, ip.GetSource (), ip.GetDestination (), incomingInterface);
       
   702 }
       
   703 
       
   704 void 
       
   705 Ipv4L3Protocol::JoinMulticastGroup (Ipv4Address origin, Ipv4Address group)
       
   706 {
       
   707   NS_LOG_FUNCTION (this << origin << group);
       
   708   m_multicastGroups.push_back(
       
   709     std::pair<Ipv4Address, Ipv4Address> (origin, group));
       
   710 }
       
   711 
       
   712 void
       
   713 Ipv4L3Protocol::LeaveMulticastGroup (Ipv4Address origin, Ipv4Address group)
       
   714 {
       
   715   NS_LOG_FUNCTION (this << origin << group);
       
   716 
       
   717   for (Ipv4MulticastGroupList::iterator i = m_multicastGroups.begin ();
       
   718        i != m_multicastGroups.end (); 
       
   719        i++)
       
   720     {
       
   721       if ((*i).first.IsEqual(origin) && (*i).second.IsEqual(group))
       
   722         {
       
   723           m_multicastGroups.erase (i);
       
   724           return;
       
   725         }
       
   726     }
       
   727 }
       
   728 
       
   729 void 
       
   730 Ipv4L3Protocol::SetAddress (uint32_t i, Ipv4Address address)
       
   731 {
       
   732   NS_LOG_FUNCTION (this << i << address);
       
   733   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   734   interface->SetAddress (address);
       
   735 }
       
   736 
       
   737 void 
       
   738 Ipv4L3Protocol::SetNetworkMask (uint32_t i, Ipv4Mask mask)
       
   739 {
       
   740   NS_LOG_FUNCTION (this << i << mask);
       
   741   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   742   interface->SetNetworkMask (mask);
       
   743 }
       
   744 
       
   745 Ipv4Mask 
       
   746 Ipv4L3Protocol::GetNetworkMask (uint32_t i) const
       
   747 {
       
   748   NS_LOG_FUNCTION (this << i);
       
   749   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   750   return interface->GetNetworkMask ();
       
   751 }
       
   752 
       
   753 Ipv4Address 
       
   754 Ipv4L3Protocol::GetAddress (uint32_t i) const
       
   755 {
       
   756   NS_LOG_FUNCTION (this << i);
       
   757   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   758   return interface->GetAddress ();
       
   759 }
       
   760 
       
   761 void 
       
   762 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
       
   763 {
       
   764   NS_LOG_FUNCTION (i << metric);
       
   765   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   766   interface->SetMetric (metric);
       
   767 }
       
   768 
       
   769 uint16_t
       
   770 Ipv4L3Protocol::GetMetric (uint32_t i) const
       
   771 {
       
   772   NS_LOG_FUNCTION (i);
       
   773   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   774   return interface->GetMetric ();
       
   775 }
       
   776 
       
   777 bool
       
   778 Ipv4L3Protocol::GetIfIndexForDestination (
       
   779   Ipv4Address destination, uint32_t& ifIndex) const
       
   780 {
       
   781   NS_LOG_FUNCTION (this << destination << &ifIndex);
       
   782 //
       
   783 // The first thing we do in trying to determine a source address is to 
       
   784 // consult the routing protocols.  These will also check for a default route
       
   785 // if one has been set.
       
   786 //
       
   787   for (Ipv4RoutingProtocolList::const_iterator i = m_routingProtocols.begin ();
       
   788        i != m_routingProtocols.end (); 
       
   789        i++)
       
   790     {
       
   791       NS_LOG_LOGIC ("Requesting Source Address");
       
   792       uint32_t ifIndexTmp;
       
   793 
       
   794       if ((*i).second->RequestIfIndex (destination, ifIndexTmp))
       
   795         {
       
   796           NS_LOG_LOGIC ("Found ifIndex " << ifIndexTmp);
       
   797           ifIndex = ifIndexTmp;
       
   798           return true;
       
   799         }
       
   800     }
       
   801 //
       
   802 // If there's no routing table entry telling us what *single* interface will 
       
   803 // be used to send a packet to this destination, we'll have to just pick one.  
       
   804 // If there's only one interface on this node, a good answer isn't very hard
       
   805 // to come up with.  Before jumping to any conclusions, remember that the 
       
   806 // zeroth interface is the loopback interface, so what we actually want is
       
   807 // a situation where there are exactly two interfaces on the node, in which
       
   808 // case interface one is the "single" interface connected to the outside world.
       
   809 //
       
   810   if (GetNInterfaces () == 2)
       
   811     {
       
   812       NS_LOG_LOGIC ("One Interface.  Using interface 1.");
       
   813       ifIndex = 1;
       
   814       return true;
       
   815     }
       
   816 //
       
   817 // If we fall through to here, we have a node with multiple interfaces and
       
   818 // no routes to guide us in determining what interface to choose.  Either
       
   819 // no default route was found (for unicast or multicast), or in the case of a
       
   820 // multicast, the default route contained multiple outbound interfaces.
       
   821 //
       
   822 // The fallback position is to just get the unicast default route and use 
       
   823 // the outgoing interface specified there.  We don't want to leave the source
       
   824 // address unset, so we just assert here.
       
   825 //
       
   826 // N.B. that in the case of a multicast with a route containing multiple
       
   827 // outgoing interfaces, the source address of packets from that node will be
       
   828 // set to the IP address of the interface set in the default unicast route.
       
   829 // Also, in the case of a broadcast, the same will be true.
       
   830 //
       
   831   NS_LOG_LOGIC ("Using default unicast route");
       
   832   Ipv4Route *route = m_staticRouting->GetDefaultRoute ();
       
   833 
       
   834   if (route == NULL)
       
   835     {
       
   836       NS_LOG_LOGIC ("Ipv4L3Protocol::GetIfIndexForDestination (): "
       
   837                     "Unable to determine outbound interface.  No default route set");
       
   838       return false;
       
   839     }
       
   840 
       
   841   ifIndex = route->GetInterface ();
       
   842 
       
   843   NS_LOG_LOGIC ("Default route specifies interface " << ifIndex);
       
   844   return true;
       
   845 }
       
   846 
       
   847 uint16_t 
       
   848 Ipv4L3Protocol::GetMtu (uint32_t i) const
       
   849 {
       
   850   NS_LOG_FUNCTION (this << i);
       
   851   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   852   return interface->GetMtu ();
       
   853 }
       
   854 
       
   855 bool 
       
   856 Ipv4L3Protocol::IsUp (uint32_t i) const
       
   857 {
       
   858   NS_LOG_FUNCTION (this << i);
       
   859   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   860   return interface->IsUp ();
       
   861 }
       
   862 
       
   863 void 
       
   864 Ipv4L3Protocol::SetUp (uint32_t i)
       
   865 {
       
   866   NS_LOG_FUNCTION (this << i);
       
   867   Ptr<Ipv4Interface> interface = GetInterface (i);
       
   868   interface->SetUp ();
       
   869 
       
   870   // If interface address and network mask have been set, add a route
       
   871   // to the network of the interface (like e.g. ifconfig does on a
       
   872   // Linux box)
       
   873   if ((interface->GetAddress ()) != (Ipv4Address ())
       
   874       && (interface->GetNetworkMask ()) != (Ipv4Mask ()))
       
   875     {
       
   876       AddNetworkRouteTo (interface->GetAddress ().CombineMask (interface->GetNetworkMask ()),
       
   877                          interface->GetNetworkMask (), i);
       
   878     }
       
   879 }
       
   880 
       
   881 void 
       
   882 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
       
   883 {
       
   884   NS_LOG_FUNCTION (this << ifaceIndex);
       
   885   Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
       
   886   interface->SetDown ();
       
   887 
       
   888   // Remove all routes that are going through this interface
       
   889   bool modified = true;
       
   890   while (modified)
       
   891     {
       
   892       modified = false;
       
   893       for (uint32_t i = 0; i < GetNRoutes (); i++)
       
   894         {
       
   895           Ipv4Route *route = GetRoute (i);
       
   896           if (route->GetInterface () == ifaceIndex)
       
   897             {
       
   898               RemoveRoute (i);
       
   899               modified = true;
       
   900               break;
       
   901             }
       
   902         }
       
   903     }
       
   904 }
       
   905 
       
   906 }//namespace ns3