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