A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv4-l3-protocol.cc
Go to the documentation of this file.
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 "ns3/ipv4-routing-table-entry.h"
35 
36 #include "loopback-net-device.h"
37 #include "arp-l3-protocol.h"
38 #include "ipv4-l3-protocol.h"
39 #include "icmpv4-l4-protocol.h"
40 #include "ipv4-interface.h"
41 #include "ipv4-raw-socket-impl.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
53 {
54  static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
55  .SetParent<Ipv4> ()
56  .AddConstructor<Ipv4L3Protocol> ()
57  .AddAttribute ("DefaultTos", "The TOS value set by default on all outgoing packets generated on this node.",
58  UintegerValue (0),
59  MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTos),
60  MakeUintegerChecker<uint8_t> ())
61  .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
62  UintegerValue (64),
63  MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl),
64  MakeUintegerChecker<uint8_t> ())
65  .AddAttribute ("FragmentExpirationTimeout",
66  "When this timeout expires, the fragments will be cleared from the buffer.",
67  TimeValue (Seconds (30)),
69  MakeTimeChecker ())
70  .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
72  .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
74  .AddTraceSource ("Drop", "Drop ipv4 packet",
76  .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
79  MakeObjectVectorChecker<Ipv4Interface> ())
80 
81  .AddTraceSource ("SendOutgoing", "A newly-generated packet by this node is about to be queued for transmission",
83  .AddTraceSource ("UnicastForward", "A unicast IPv4 packet was received by this node and is being forwarded to another node",
85  .AddTraceSource ("LocalDeliver", "An IPv4 packet was received by/for this node, and it is being forward up the stack",
87 
88  ;
89  return tid;
90 }
91 
93  : m_identification (0)
94 
95 {
96  NS_LOG_FUNCTION (this);
97 }
98 
100 {
101  NS_LOG_FUNCTION (this);
102 }
103 
104 void
106 {
107  NS_LOG_FUNCTION (this << protocol);
108  m_protocols.push_back (protocol);
109 }
111 Ipv4L3Protocol::GetProtocol (int protocolNumber) const
112 {
113  NS_LOG_FUNCTION (this << protocolNumber);
114  for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
115  {
116  if ((*i)->GetProtocolNumber () == protocolNumber)
117  {
118  return *i;
119  }
120  }
121  return 0;
122 }
123 void
125 {
126  NS_LOG_FUNCTION (this << protocol);
127  m_protocols.remove (protocol);
128 }
129 
130 void
132 {
133  NS_LOG_FUNCTION (this << node);
134  m_node = node;
135  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
136  SetupLoopback ();
137 }
138 
141 {
142  NS_LOG_FUNCTION (this);
143  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
144  socket->SetNode (m_node);
145  m_sockets.push_back (socket);
146  return socket;
147 }
148 void
150 {
151  NS_LOG_FUNCTION (this << socket);
152  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
153  {
154  if ((*i) == socket)
155  {
156  m_sockets.erase (i);
157  return;
158  }
159  }
160  return;
161 }
162 /*
163  * This method is called by AddAgregate and completes the aggregation
164  * by setting the node in the ipv4 stack
165  */
166 void
168 {
169  NS_LOG_FUNCTION (this);
170  if (m_node == 0)
171  {
172  Ptr<Node>node = this->GetObject<Node>();
173  // verify that it's a valid node and that
174  // the node has not been set before
175  if (node != 0)
176  {
177  this->SetNode (node);
178  }
179  }
181 }
182 
183 void
185 {
186  NS_LOG_FUNCTION (this << routingProtocol);
187  m_routingProtocol = routingProtocol;
188  m_routingProtocol->SetIpv4 (this);
189 }
190 
191 
194 {
195  NS_LOG_FUNCTION (this);
196  return m_routingProtocol;
197 }
198 
199 void
201 {
202  NS_LOG_FUNCTION (this);
203  for (L4List_t::iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
204  {
205  *i = 0;
206  }
207  m_protocols.clear ();
208 
209  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
210  {
211  *i = 0;
212  }
213  m_interfaces.clear ();
214  m_sockets.clear ();
215  m_node = 0;
216  m_routingProtocol = 0;
217 
218  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
219  {
220  it->second = 0;
221  }
222 
223  for (MapFragmentsTimers_t::iterator it = m_fragmentsTimers.begin (); it != m_fragmentsTimers.end (); it++)
224  {
225  if (it->second.IsRunning ())
226  {
227  it->second.Cancel ();
228  }
229  }
230 
231  m_fragments.clear ();
232  m_fragmentsTimers.clear ();
233 
235 }
236 
237 void
239 {
240  NS_LOG_FUNCTION (this);
241 
242  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
243  Ptr<LoopbackNetDevice> device = 0;
244  // First check whether an existing LoopbackNetDevice exists on the node
245  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
246  {
247  if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
248  {
249  break;
250  }
251  }
252  if (device == 0)
253  {
254  device = CreateObject<LoopbackNetDevice> ();
255  m_node->AddDevice (device);
256  }
257  interface->SetDevice (device);
258  interface->SetNode (m_node);
260  interface->AddAddress (ifaceAddr);
261  uint32_t index = AddIpv4Interface (interface);
262  Ptr<Node> node = GetObject<Node> ();
265  interface->SetUp ();
266  if (m_routingProtocol != 0)
267  {
269  }
270 }
271 
272 void
274 {
275  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ttl));
276  m_defaultTtl = ttl;
277 }
278 
279 uint32_t
281 {
282  NS_LOG_FUNCTION (this << device);
283 
284  Ptr<Node> node = GetObject<Node> ();
287  node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
289 
290  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
291  interface->SetNode (m_node);
292  interface->SetDevice (device);
293  interface->SetForwarding (m_ipForward);
294  return AddIpv4Interface (interface);
295 }
296 
297 uint32_t
299 {
300  NS_LOG_FUNCTION (this << interface);
301  uint32_t index = m_interfaces.size ();
302  m_interfaces.push_back (interface);
303  return index;
304 }
305 
307 Ipv4L3Protocol::GetInterface (uint32_t index) const
308 {
309  NS_LOG_FUNCTION (this << index);
310  if (index < m_interfaces.size ())
311  {
312  return m_interfaces[index];
313  }
314  return 0;
315 }
316 
317 uint32_t
319 {
320  NS_LOG_FUNCTION (this);
321  return m_interfaces.size ();
322 }
323 
324 int32_t
326  Ipv4Address address) const
327 {
328  NS_LOG_FUNCTION (this << address);
329  int32_t interface = 0;
330  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
331  i != m_interfaces.end ();
332  i++, interface++)
333  {
334  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
335  {
336  if ((*i)->GetAddress (j).GetLocal () == address)
337  {
338  return interface;
339  }
340  }
341  }
342 
343  return -1;
344 }
345 
346 int32_t
348  Ipv4Address address,
349  Ipv4Mask mask) const
350 {
351  NS_LOG_FUNCTION (this << address << mask);
352  int32_t interface = 0;
353  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
354  i != m_interfaces.end ();
355  i++, interface++)
356  {
357  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
358  {
359  if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
360  {
361  return interface;
362  }
363  }
364  }
365 
366  return -1;
367 }
368 
369 int32_t
371  Ptr<const NetDevice> device) const
372 {
373  NS_LOG_FUNCTION (this << device);
374  int32_t interface = 0;
375  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
376  i != m_interfaces.end ();
377  i++, interface++)
378  {
379  if ((*i)->GetDevice () == device)
380  {
381  return interface;
382  }
383  }
384 
385  return -1;
386 }
387 
388 bool
390 {
391  NS_LOG_FUNCTION (this << address << iif);
392  // First check the incoming interface for a unicast address match
393  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
394  {
395  Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
396  if (address == iaddr.GetLocal ())
397  {
398  NS_LOG_LOGIC ("For me (destination " << address << " match)");
399  return true;
400  }
401  if (address == iaddr.GetBroadcast ())
402  {
403  NS_LOG_LOGIC ("For me (interface broadcast address)");
404  return true;
405  }
406  }
407 
408  if (address.IsMulticast ())
409  {
410 #ifdef NOTYET
411  if (MulticastCheckGroup (iif, address ))
412 #endif
413  if (true)
414  {
415  NS_LOG_LOGIC ("For me (Ipv4Addr multicast address");
416  return true;
417  }
418  }
419 
420  if (address.IsBroadcast ())
421  {
422  NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
423  return true;
424  }
425 
426  if (GetWeakEsModel ()) // Check other interfaces
427  {
428  for (uint32_t j = 0; j < GetNInterfaces (); j++)
429  {
430  if (j == uint32_t (iif)) continue;
431  for (uint32_t i = 0; i < GetNAddresses (j); i++)
432  {
433  Ipv4InterfaceAddress iaddr = GetAddress (j, i);
434  if (address == iaddr.GetLocal ())
435  {
436  NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
437  return true;
438  }
439  // This is a small corner case: match another interface's broadcast address
440  if (address == iaddr.GetBroadcast ())
441  {
442  NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
443  return true;
444  }
445  }
446  }
447  }
448  return false;
449 }
450 
451 void
452 Ipv4L3Protocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
453  const Address &to, NetDevice::PacketType packetType)
454 {
455  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
456 
457  NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
458  m_node->GetId ());
459 
460  uint32_t interface = 0;
461  Ptr<Packet> packet = p->Copy ();
462 
463  Ptr<Ipv4Interface> ipv4Interface;
464  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
465  i != m_interfaces.end ();
466  i++, interface++)
467  {
468  ipv4Interface = *i;
469  if (ipv4Interface->GetDevice () == device)
470  {
471  if (ipv4Interface->IsUp ())
472  {
473  m_rxTrace (packet, m_node->GetObject<Ipv4> (), interface);
474  break;
475  }
476  else
477  {
478  NS_LOG_LOGIC ("Dropping received packet -- interface is down");
479  Ipv4Header ipHeader;
480  packet->RemoveHeader (ipHeader);
481  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
482  return;
483  }
484  }
485  }
486 
487  Ipv4Header ipHeader;
488  if (Node::ChecksumEnabled ())
489  {
490  ipHeader.EnableChecksum ();
491  }
492  packet->RemoveHeader (ipHeader);
493 
494  // Trim any residual frame padding from underlying devices
495  if (ipHeader.GetPayloadSize () < packet->GetSize ())
496  {
497  packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
498  }
499 
500  if (!ipHeader.IsChecksumOk ())
501  {
502  NS_LOG_LOGIC ("Dropping received packet -- checksum not ok");
503  m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, m_node->GetObject<Ipv4> (), interface);
504  return;
505  }
506 
507  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
508  {
509  NS_LOG_LOGIC ("Forwarding to raw socket");
510  Ptr<Ipv4RawSocketImpl> socket = *i;
511  socket->ForwardUp (packet, ipHeader, ipv4Interface);
512  }
513 
514  NS_ASSERT_MSG (m_routingProtocol != 0, "Need a routing protocol object to process packets");
515  if (!m_routingProtocol->RouteInput (packet, ipHeader, device,
520  ))
521  {
522  NS_LOG_WARN ("No route found for forwarding packet. Drop.");
523  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), interface);
524  }
525 }
526 
529 {
530  NS_LOG_FUNCTION (this);
532  if (prot != 0)
533  {
534  return prot->GetObject<Icmpv4L4Protocol> ();
535  }
536  else
537  {
538  return 0;
539  }
540 }
541 
542 bool
544 {
545  NS_LOG_FUNCTION (this << ad << interfaceMask);
546  return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask);
547 }
548 
549 void
551  Ipv4Header ipHeader,
552  Ptr<Ipv4Route> route)
553 {
554  NS_LOG_FUNCTION (this << packet << ipHeader << route);
555  if (Node::ChecksumEnabled ())
556  {
557  ipHeader.EnableChecksum ();
558  }
559  SendRealOut (route, packet, ipHeader);
560 }
561 
562 void
564  Ipv4Address source,
565  Ipv4Address destination,
566  uint8_t protocol,
567  Ptr<Ipv4Route> route)
568 {
569  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t (protocol) << route);
570 
571  Ipv4Header ipHeader;
572  bool mayFragment = true;
573  uint8_t ttl = m_defaultTtl;
574  SocketIpTtlTag tag;
575  bool found = packet->RemovePacketTag (tag);
576  if (found)
577  {
578  ttl = tag.GetTtl ();
579  }
580 
581  uint8_t tos = m_defaultTos;
582  SocketIpTosTag ipTosTag;
583  found = packet->RemovePacketTag (ipTosTag);
584  if (found)
585  {
586  tos = ipTosTag.GetTos ();
587  }
588 
589  // Handle a few cases:
590  // 1) packet is destined to limited broadcast address
591  // 2) packet is destined to a subnet-directed broadcast address
592  // 3) packet is not broadcast, and is passed in with a route entry
593  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
594  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
595 
596  // 1) packet is destined to limited broadcast address or link-local multicast address
597  if (destination.IsBroadcast () || destination.IsLocalMulticast ())
598  {
599  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1: limited broadcast");
600  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
601  uint32_t ifaceIndex = 0;
602  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
603  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
604  {
605  Ptr<Ipv4Interface> outInterface = *ifaceIter;
606  Ptr<Packet> packetCopy = packet->Copy ();
607 
608  NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice ()->GetMtu ());
609 
610  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
611  packetCopy->AddHeader (ipHeader);
612  m_txTrace (packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
613  outInterface->Send (packetCopy, destination);
614  }
615  return;
616  }
617 
618  // 2) check: packet is destined to a subnet-directed broadcast address
619  uint32_t ifaceIndex = 0;
620  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
621  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
622  {
623  Ptr<Ipv4Interface> outInterface = *ifaceIter;
624  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
625  {
626  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
627  NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
628  if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
629  destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
630  {
631  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: subnet directed bcast to " << ifAddr.GetLocal ());
632  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
633  Ptr<Packet> packetCopy = packet->Copy ();
634  m_sendOutgoingTrace (ipHeader, packetCopy, ifaceIndex);
635  packetCopy->AddHeader (ipHeader);
636  m_txTrace (packetCopy, m_node->GetObject<Ipv4> (), ifaceIndex);
637  outInterface->Send (packetCopy, destination);
638  return;
639  }
640  }
641  }
642 
643  // 3) packet is not broadcast, and is passed in with a route entry
644  // with a valid Ipv4Address as the gateway
645  if (route && route->GetGateway () != Ipv4Address ())
646  {
647  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: passed in with route");
648  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
649  int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
650  m_sendOutgoingTrace (ipHeader, packet, interface);
651  SendRealOut (route, packet->Copy (), ipHeader);
652  return;
653  }
654  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
655  if (route && route->GetGateway () == Ipv4Address ())
656  {
657  // This could arise because the synchronous RouteOutput() call
658  // returned to the transport protocol with a source address but
659  // there was no next hop available yet (since a route may need
660  // to be queried).
661  NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 4: This case not yet implemented");
662  }
663  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
664  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 5: passed in with no route " << destination);
665  Socket::SocketErrno errno_;
666  Ptr<NetDevice> oif (0); // unused for now
667  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
668  Ptr<Ipv4Route> newRoute;
669  if (m_routingProtocol != 0)
670  {
671  newRoute = m_routingProtocol->RouteOutput (packet, ipHeader, oif, errno_);
672  }
673  else
674  {
675  NS_LOG_ERROR ("Ipv4L3Protocol::Send: m_routingProtocol == 0");
676  }
677  if (newRoute)
678  {
679  int32_t interface = GetInterfaceForDevice (newRoute->GetOutputDevice ());
680  m_sendOutgoingTrace (ipHeader, packet, interface);
681  SendRealOut (newRoute, packet->Copy (), ipHeader);
682  }
683  else
684  {
685  NS_LOG_WARN ("No route to host. Drop.");
686  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
687  }
688 }
689 
690 // XXX when should we set ip_id? check whether we are incrementing
691 // m_identification on packets that may later be dropped in this stack
692 // and whether that deviates from Linux
695  Ipv4Address source,
696  Ipv4Address destination,
697  uint8_t protocol,
698  uint16_t payloadSize,
699  uint8_t ttl,
700  uint8_t tos,
701  bool mayFragment)
702 {
703  NS_LOG_FUNCTION (this << source << destination << (uint16_t)protocol << payloadSize << (uint16_t)ttl << (uint16_t)tos << mayFragment);
704  Ipv4Header ipHeader;
705  ipHeader.SetSource (source);
706  ipHeader.SetDestination (destination);
707  ipHeader.SetProtocol (protocol);
708  ipHeader.SetPayloadSize (payloadSize);
709  ipHeader.SetTtl (ttl);
710  ipHeader.SetTos (tos);
711  if (mayFragment == true)
712  {
713  ipHeader.SetMayFragment ();
716  }
717  else
718  {
719  ipHeader.SetDontFragment ();
720  // TBD: set to zero here; will cause traces to change
723  }
724  if (Node::ChecksumEnabled ())
725  {
726  ipHeader.EnableChecksum ();
727  }
728  return ipHeader;
729 }
730 
731 void
733  Ptr<Packet> packet,
734  Ipv4Header const &ipHeader)
735 {
736  NS_LOG_FUNCTION (this << route << packet << &ipHeader);
737  if (route == 0)
738  {
739  NS_LOG_WARN ("No route to host. Drop.");
740  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
741  return;
742  }
743  packet->AddHeader (ipHeader);
744  Ptr<NetDevice> outDev = route->GetOutputDevice ();
745  int32_t interface = GetInterfaceForDevice (outDev);
746  NS_ASSERT (interface >= 0);
747  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
748  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
749 
750  if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0")))
751  {
752  if (outInterface->IsUp ())
753  {
754  NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
755  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
756  {
757  std::list<Ptr<Packet> > listFragments;
758  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
759  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
760  {
761  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
762  outInterface->Send (*it, route->GetGateway ());
763  }
764  }
765  else
766  {
767  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
768  outInterface->Send (packet, route->GetGateway ());
769  }
770  }
771  else
772  {
773  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << route->GetGateway ());
774  Ipv4Header ipHeader;
775  packet->RemoveHeader (ipHeader);
776  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
777  }
778  }
779  else
780  {
781  if (outInterface->IsUp ())
782  {
783  NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
784  if ( packet->GetSize () > outInterface->GetDevice ()->GetMtu () )
785  {
786  std::list<Ptr<Packet> > listFragments;
787  DoFragmentation (packet, outInterface->GetDevice ()->GetMtu (), listFragments);
788  for ( std::list<Ptr<Packet> >::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
789  {
790  NS_LOG_LOGIC ("Sending fragment " << **it );
791  m_txTrace (*it, m_node->GetObject<Ipv4> (), interface);
792  outInterface->Send (*it, ipHeader.GetDestination ());
793  }
794  }
795  else
796  {
797  m_txTrace (packet, m_node->GetObject<Ipv4> (), interface);
798  outInterface->Send (packet, ipHeader.GetDestination ());
799  }
800  }
801  else
802  {
803  NS_LOG_LOGIC ("Dropping -- outgoing interface is down: " << ipHeader.GetDestination ());
804  Ipv4Header ipHeader;
805  packet->RemoveHeader (ipHeader);
806  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, m_node->GetObject<Ipv4> (), interface);
807  }
808  }
809 }
810 
811 // This function analogous to Linux ip_mr_forward()
812 void
814 {
815  NS_LOG_FUNCTION (this << mrtentry << p << header);
816  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
817 
818  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
819  std::map<uint32_t, uint32_t>::iterator mapIter;
820 
821  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
822  {
823  uint32_t interfaceId = mapIter->first;
824  //uint32_t outputTtl = mapIter->second; // Unused for now
825 
826  Ptr<Packet> packet = p->Copy ();
827  Ipv4Header h = header;
828  h.SetTtl (header.GetTtl () - 1);
829  if (h.GetTtl () == 0)
830  {
831  NS_LOG_WARN ("TTL exceeded. Drop.");
832  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interfaceId);
833  return;
834  }
835  NS_LOG_LOGIC ("Forward multicast via interface " << interfaceId);
836  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
837  rtentry->SetSource (h.GetSource ());
838  rtentry->SetDestination (h.GetDestination ());
839  rtentry->SetGateway (Ipv4Address::GetAny ());
840  rtentry->SetOutputDevice (GetNetDevice (interfaceId));
841  SendRealOut (rtentry, packet, h);
842  continue;
843  }
844 }
845 
846 // This function analogous to Linux ip_forward()
847 void
849 {
850  NS_LOG_FUNCTION (this << rtentry << p << header);
851  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
852  // Forwarding
853  Ipv4Header ipHeader = header;
854  Ptr<Packet> packet = p->Copy ();
855  int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
856  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
857  if (ipHeader.GetTtl () == 0)
858  {
859  // Do not reply to ICMP or to multicast/broadcast IP address
860  if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER &&
861  ipHeader.GetDestination ().IsBroadcast () == false &&
862  ipHeader.GetDestination ().IsMulticast () == false)
863  {
864  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
865  icmp->SendTimeExceededTtl (ipHeader, packet);
866  }
867  NS_LOG_WARN ("TTL exceeded. Drop.");
868  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interface);
869  return;
870  }
871  m_unicastForwardTrace (ipHeader, packet, interface);
872  SendRealOut (rtentry, packet, ipHeader);
873 }
874 
875 void
877 {
878  NS_LOG_FUNCTION (this << packet << &ip << iif);
879  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
880  Ipv4Header ipHeader = ip;
881 
882  if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 )
883  {
884  NS_LOG_LOGIC ("Received a fragment, processing " << *p );
885  bool isPacketComplete;
886  isPacketComplete = ProcessFragment (p, ipHeader, iif);
887  if ( isPacketComplete == false)
888  {
889  return;
890  }
891  NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p );
892  }
893 
894  m_localDeliverTrace (ip, packet, iif);
895 
896  Ptr<IpL4Protocol> protocol = GetProtocol (ip.GetProtocol ());
897  if (protocol != 0)
898  {
899  // we need to make a copy in the unlikely event we hit the
900  // RX_ENDPOINT_UNREACH codepath
901  Ptr<Packet> copy = p->Copy ();
902  enum IpL4Protocol::RxStatus status =
903  protocol->Receive (p, ip, GetInterface (iif));
904  switch (status) {
905  case IpL4Protocol::RX_OK:
906  // fall through
908  // fall through
910  break;
912  if (ip.GetDestination ().IsBroadcast () == true ||
913  ip.GetDestination ().IsMulticast () == true)
914  {
915  break; // Do not reply to broadcast or multicast
916  }
917  // Another case to suppress ICMP is a subnet-directed broadcast
918  bool subnetDirected = false;
919  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
920  {
921  Ipv4InterfaceAddress addr = GetAddress (iif, i);
922  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination ().CombineMask (addr.GetMask ()) &&
924  {
925  subnetDirected = true;
926  }
927  }
928  if (subnetDirected == false)
929  {
930  GetIcmp ()->SendDestUnreachPort (ip, copy);
931  }
932  }
933  }
934 }
935 
936 bool
938 {
939  NS_LOG_FUNCTION (this << i << address);
940  Ptr<Ipv4Interface> interface = GetInterface (i);
941  bool retVal = interface->AddAddress (address);
942  if (m_routingProtocol != 0)
943  {
944  m_routingProtocol->NotifyAddAddress (i, address);
945  }
946  return retVal;
947 }
948 
950 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
951 {
952  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
953  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
954  return interface->GetAddress (addressIndex);
955 }
956 
957 uint32_t
958 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
959 {
960  NS_LOG_FUNCTION (this << interface);
961  Ptr<Ipv4Interface> iface = GetInterface (interface);
962  return iface->GetNAddresses ();
963 }
964 
965 bool
966 Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
967 {
968  NS_LOG_FUNCTION (this << i << addressIndex);
969  Ptr<Ipv4Interface> interface = GetInterface (i);
970  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
971  if (address != Ipv4InterfaceAddress ())
972  {
973  if (m_routingProtocol != 0)
974  {
976  }
977  return true;
978  }
979  return false;
980 }
981 
985 {
986  NS_LOG_FUNCTION (this << device << dst << scope);
987  Ipv4Address addr ("0.0.0.0");
988  Ipv4InterfaceAddress iaddr;
989  bool found = false;
990 
991  if (device != 0)
992  {
993  int32_t i = GetInterfaceForDevice (device);
994  NS_ASSERT_MSG (i >= 0, "No device found on node");
995  for (uint32_t j = 0; j < GetNAddresses (i); j++)
996  {
997  iaddr = GetAddress (i, j);
998  if (iaddr.IsSecondary ()) continue;
999  if (iaddr.GetScope () > scope) continue;
1000  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1001  {
1002  return iaddr.GetLocal ();
1003  }
1004  if (!found)
1005  {
1006  addr = iaddr.GetLocal ();
1007  found = true;
1008  }
1009  }
1010  }
1011  if (found)
1012  {
1013  return addr;
1014  }
1015 
1016  // Iterate among all interfaces
1017  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1018  {
1019  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1020  {
1021  iaddr = GetAddress (i, j);
1022  if (iaddr.IsSecondary ()) continue;
1023  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1024  && iaddr.GetScope () <= scope)
1025  {
1026  return iaddr.GetLocal ();
1027  }
1028  }
1029  }
1030  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1031  << scope << ", returning 0");
1032  return addr;
1033 }
1034 
1035 void
1036 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1037 {
1038  NS_LOG_FUNCTION (this << i << metric);
1039  Ptr<Ipv4Interface> interface = GetInterface (i);
1040  interface->SetMetric (metric);
1041 }
1042 
1043 uint16_t
1044 Ipv4L3Protocol::GetMetric (uint32_t i) const
1045 {
1046  NS_LOG_FUNCTION (this << i);
1047  Ptr<Ipv4Interface> interface = GetInterface (i);
1048  return interface->GetMetric ();
1049 }
1050 
1051 uint16_t
1052 Ipv4L3Protocol::GetMtu (uint32_t i) const
1053 {
1054  NS_LOG_FUNCTION (this << i);
1055  Ptr<Ipv4Interface> interface = GetInterface (i);
1056  return interface->GetDevice ()->GetMtu ();
1057 }
1058 
1059 bool
1060 Ipv4L3Protocol::IsUp (uint32_t i) const
1061 {
1062  NS_LOG_FUNCTION (this << i);
1063  Ptr<Ipv4Interface> interface = GetInterface (i);
1064  return interface->IsUp ();
1065 }
1066 
1067 void
1069 {
1070  NS_LOG_FUNCTION (this << i);
1071  Ptr<Ipv4Interface> interface = GetInterface (i);
1072  interface->SetUp ();
1073 
1074  if (m_routingProtocol != 0)
1075  {
1077  }
1078 }
1079 
1080 void
1081 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1082 {
1083  NS_LOG_FUNCTION (this << ifaceIndex);
1084  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1085  interface->SetDown ();
1086 
1087  if (m_routingProtocol != 0)
1088  {
1089  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1090  }
1091 }
1092 
1093 bool
1095 {
1096  NS_LOG_FUNCTION (this << i);
1097  Ptr<Ipv4Interface> interface = GetInterface (i);
1098  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1099  return interface->IsForwarding ();
1100 }
1101 
1102 void
1103 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1104 {
1105  NS_LOG_FUNCTION (this << i);
1106  Ptr<Ipv4Interface> interface = GetInterface (i);
1107  interface->SetForwarding (val);
1108 }
1109 
1112 {
1113  NS_LOG_FUNCTION (this << i);
1114  return GetInterface (i)->GetDevice ();
1115 }
1116 
1117 void
1119 {
1120  NS_LOG_FUNCTION (this << forward);
1121  m_ipForward = forward;
1122  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1123  {
1124  (*i)->SetForwarding (forward);
1125  }
1126 }
1127 
1128 bool
1130 {
1131  NS_LOG_FUNCTION (this);
1132  return m_ipForward;
1133 }
1134 
1135 void
1137 {
1138  NS_LOG_FUNCTION (this << model);
1139  m_weakEsModel = model;
1140 }
1141 
1142 bool
1144 {
1145  NS_LOG_FUNCTION (this);
1146  return m_weakEsModel;
1147 }
1148 
1149 void
1151 {
1152  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1153  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1154  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0);
1155 }
1156 
1157 void
1158 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, uint32_t outIfaceMtu, std::list<Ptr<Packet> >& listFragments)
1159 {
1160  // BEWARE: here we do assume that the header options are not present.
1161  // a much more complex handling is necessary in case there are options.
1162  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1163  // Of course also the reassemby code shall be changed as well.
1164 
1165  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1166 
1167  Ptr<Packet> p = packet->Copy ();
1168 
1169  Ipv4Header ipv4Header;
1170  p->RemoveHeader (ipv4Header);
1171 
1172  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1173  "IPv4 fragmentation implementation only works without option headers." );
1174 
1175  uint16_t offset = 0;
1176  bool moreFragment = true;
1177  uint16_t originalOffset = 0;
1178  bool alreadyFragmented = false;
1179  uint32_t currentFragmentablePartSize = 0;
1180 
1181  if (!ipv4Header.IsLastFragment())
1182  {
1183  alreadyFragmented = true;
1184  originalOffset = ipv4Header.GetFragmentOffset();
1185  }
1186 
1187  // IPv4 fragments are all 8 bytes aligned but the last.
1188  // The IP payload size is:
1189  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1190  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1191 
1192  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1193 
1194  do
1195  {
1196  Ipv4Header fragmentHeader = ipv4Header;
1197 
1198  if (p->GetSize () > offset + fragmentSize )
1199  {
1200  moreFragment = true;
1201  currentFragmentablePartSize = fragmentSize;
1202  fragmentHeader.SetMoreFragments ();
1203  }
1204  else
1205  {
1206  moreFragment = false;
1207  currentFragmentablePartSize = p->GetSize () - offset;
1208  if (alreadyFragmented)
1209  {
1210  fragmentHeader.SetMoreFragments ();
1211  }
1212  else
1213  {
1214  fragmentHeader.SetLastFragment ();
1215  }
1216  }
1217 
1218  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1219  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1220  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1221 
1222  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1223  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1224 
1225  if (Node::ChecksumEnabled ())
1226  {
1227  fragmentHeader.EnableChecksum ();
1228  }
1229 
1230  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1231 
1232  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1233  fragment->AddHeader (fragmentHeader);
1234 
1235  std::ostringstream oss;
1236  fragment->Print (oss);
1237 
1238  NS_LOG_LOGIC ("New fragment " << *fragment);
1239 
1240  listFragments.push_back (fragment);
1241 
1242  offset += currentFragmentablePartSize;
1243 
1244  }
1245  while (moreFragment);
1246 
1247  return;
1248 }
1249 
1250 bool
1251 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1252 {
1253  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1254 
1255  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 & uint64_t (ipHeader.GetDestination ().Get ());
1256  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 & uint32_t (ipHeader.GetProtocol ());
1257  std::pair<uint64_t, uint32_t> key;
1258  bool ret = false;
1259  Ptr<Packet> p = packet->Copy ();
1260 
1261  key.first = addressCombination;
1262  key.second = idProto;
1263 
1264  Ptr<Fragments> fragments;
1265 
1266  MapFragments_t::iterator it = m_fragments.find (key);
1267  if (it == m_fragments.end ())
1268  {
1269  fragments = Create<Fragments> ();
1270  m_fragments.insert (std::make_pair (key, fragments));
1273  key, ipHeader, iif);
1274  }
1275  else
1276  {
1277  fragments = it->second;
1278  }
1279 
1280  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1281 
1282  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1283 
1284  if ( fragments->IsEntire () )
1285  {
1286  packet = fragments->GetPacket ();
1287  fragments = 0;
1288  m_fragments.erase (key);
1289  if (m_fragmentsTimers[key].IsRunning ())
1290  {
1291  NS_LOG_LOGIC ("Stopping WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
1292  m_fragmentsTimers[key].Cancel ();
1293  }
1294  m_fragmentsTimers.erase (key);
1295  ret = true;
1296  }
1297 
1298  return ret;
1299 }
1300 
1302  : m_moreFragment (0)
1303 {
1304  NS_LOG_FUNCTION (this);
1305 }
1306 
1308 {
1309  NS_LOG_FUNCTION (this);
1310 }
1311 
1312 void
1313 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1314 {
1315  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1316 
1317  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1318 
1319  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1320  {
1321  if (it->second > fragmentOffset)
1322  {
1323  break;
1324  }
1325  }
1326 
1327  if (it == m_fragments.end ())
1328  {
1329  m_moreFragment = moreFragment;
1330  }
1331 
1332  m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1333 }
1334 
1335 bool
1337 {
1338  NS_LOG_FUNCTION (this);
1339 
1340  bool ret = !m_moreFragment && m_fragments.size () > 0;
1341 
1342  if (ret)
1343  {
1344  uint16_t lastEndOffset = 0;
1345 
1346  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1347  {
1348  // overlapping fragments do exist
1349  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1350 
1351  if (lastEndOffset < it->second)
1352  {
1353  ret = false;
1354  break;
1355  }
1356  // fragments might overlap in strange ways
1357  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1358  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1359  }
1360  }
1361 
1362  return ret;
1363 }
1364 
1367 {
1368  NS_LOG_FUNCTION (this);
1369 
1370  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1371 
1372  Ptr<Packet> p = Create<Packet> ();
1373  uint16_t lastEndOffset = 0;
1374 
1375  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1376  {
1377  if ( lastEndOffset > it->second )
1378  {
1379  // The fragments are overlapping.
1380  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1381  // This is different from what Linux does.
1382  // It is not possible to emulate a fragmentation attack.
1383  uint32_t newStart = lastEndOffset - it->second;
1384  if ( it->first->GetSize () > newStart )
1385  {
1386  uint32_t newSize = it->first->GetSize () - newStart;
1387  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1388  p->AddAtEnd (tempFragment);
1389  }
1390  }
1391  else
1392  {
1393  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1394  p->AddAtEnd (it->first);
1395  }
1396  lastEndOffset = p->GetSize ();
1397  }
1398 
1399  return p;
1400 }
1401 
1404 {
1405  NS_LOG_FUNCTION (this);
1406 
1407  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1408 
1409  Ptr<Packet> p = Create<Packet> ();
1410  uint16_t lastEndOffset = 0;
1411 
1412  if ( m_fragments.begin ()->second > 0 )
1413  {
1414  return p;
1415  }
1416 
1417  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1418  {
1419  if ( lastEndOffset > it->second )
1420  {
1421  uint32_t newStart = lastEndOffset - it->second;
1422  uint32_t newSize = it->first->GetSize () - newStart;
1423  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1424  p->AddAtEnd (tempFragment);
1425  }
1426  else if ( lastEndOffset == it->second )
1427  {
1428  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1429  p->AddAtEnd (it->first);
1430  }
1431  lastEndOffset = p->GetSize ();
1432  }
1433 
1434  return p;
1435 }
1436 
1437 void
1438 Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4Header & ipHeader, uint32_t iif)
1439 {
1440  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1441 
1442  MapFragments_t::iterator it = m_fragments.find (key);
1443  Ptr<Packet> packet = it->second->GetPartialPacket ();
1444 
1445  // if we have at least 8 bytes, we can send an ICMP.
1446  if ( packet->GetSize () > 8 )
1447  {
1448  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1449  icmp->SendTimeExceededTtl (ipHeader, packet);
1450  }
1451  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4> (), iif);
1452 
1453  // clear the buffers
1454  it->second = 0;
1455 
1456  m_fragments.erase (key);
1457  m_fragmentsTimers.erase (key);
1458 }
1459 
1460 } // namespace ns3