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