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  {
268  m_routingProtocol->NotifyInterfaceUp (index);
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
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 
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  {
975  m_routingProtocol->NotifyRemoveAddress (i, address);
976  }
977  return true;
978  }
979  return false;
980 }
981 
982 bool
984 {
985  NS_LOG_FUNCTION (this << i << address);
986 
987  if (address == Ipv4Address::GetLoopback())
988  {
989  NS_LOG_WARN ("Cannot remove loopback address.");
990  return false;
991  }
992  Ptr<Ipv4Interface> interface = GetInterface (i);
993  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
994  if (ifAddr != Ipv4InterfaceAddress ())
995  {
996  if (m_routingProtocol != 0)
997  {
998  m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
999  }
1000  return true;
1001  }
1002  return false;
1003 }
1004 
1005 Ipv4Address
1008 {
1009  NS_LOG_FUNCTION (this << device << dst << scope);
1010  Ipv4Address addr ("0.0.0.0");
1011  Ipv4InterfaceAddress iaddr;
1012  bool found = false;
1013 
1014  if (device != 0)
1015  {
1016  int32_t i = GetInterfaceForDevice (device);
1017  NS_ASSERT_MSG (i >= 0, "No device found on node");
1018  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1019  {
1020  iaddr = GetAddress (i, j);
1021  if (iaddr.IsSecondary ()) continue;
1022  if (iaddr.GetScope () > scope) continue;
1023  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1024  {
1025  return iaddr.GetLocal ();
1026  }
1027  if (!found)
1028  {
1029  addr = iaddr.GetLocal ();
1030  found = true;
1031  }
1032  }
1033  }
1034  if (found)
1035  {
1036  return addr;
1037  }
1038 
1039  // Iterate among all interfaces
1040  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1041  {
1042  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1043  {
1044  iaddr = GetAddress (i, j);
1045  if (iaddr.IsSecondary ()) continue;
1046  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1047  && iaddr.GetScope () <= scope)
1048  {
1049  return iaddr.GetLocal ();
1050  }
1051  }
1052  }
1053  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1054  << scope << ", returning 0");
1055  return addr;
1056 }
1057 
1058 void
1059 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1060 {
1061  NS_LOG_FUNCTION (this << i << metric);
1062  Ptr<Ipv4Interface> interface = GetInterface (i);
1063  interface->SetMetric (metric);
1064 }
1065 
1066 uint16_t
1067 Ipv4L3Protocol::GetMetric (uint32_t i) const
1068 {
1069  NS_LOG_FUNCTION (this << i);
1070  Ptr<Ipv4Interface> interface = GetInterface (i);
1071  return interface->GetMetric ();
1072 }
1073 
1074 uint16_t
1075 Ipv4L3Protocol::GetMtu (uint32_t i) const
1076 {
1077  NS_LOG_FUNCTION (this << i);
1078  Ptr<Ipv4Interface> interface = GetInterface (i);
1079  return interface->GetDevice ()->GetMtu ();
1080 }
1081 
1082 bool
1083 Ipv4L3Protocol::IsUp (uint32_t i) const
1084 {
1085  NS_LOG_FUNCTION (this << i);
1086  Ptr<Ipv4Interface> interface = GetInterface (i);
1087  return interface->IsUp ();
1088 }
1089 
1090 void
1092 {
1093  NS_LOG_FUNCTION (this << i);
1094  Ptr<Ipv4Interface> interface = GetInterface (i);
1095  interface->SetUp ();
1096 
1097  if (m_routingProtocol != 0)
1098  {
1099  m_routingProtocol->NotifyInterfaceUp (i);
1100  }
1101 }
1102 
1103 void
1104 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1105 {
1106  NS_LOG_FUNCTION (this << ifaceIndex);
1107  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1108  interface->SetDown ();
1109 
1110  if (m_routingProtocol != 0)
1111  {
1112  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1113  }
1114 }
1115 
1116 bool
1118 {
1119  NS_LOG_FUNCTION (this << i);
1120  Ptr<Ipv4Interface> interface = GetInterface (i);
1121  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1122  return interface->IsForwarding ();
1123 }
1124 
1125 void
1126 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1127 {
1128  NS_LOG_FUNCTION (this << i);
1129  Ptr<Ipv4Interface> interface = GetInterface (i);
1130  interface->SetForwarding (val);
1131 }
1132 
1135 {
1136  NS_LOG_FUNCTION (this << i);
1137  return GetInterface (i)->GetDevice ();
1138 }
1139 
1140 void
1142 {
1143  NS_LOG_FUNCTION (this << forward);
1144  m_ipForward = forward;
1145  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1146  {
1147  (*i)->SetForwarding (forward);
1148  }
1149 }
1150 
1151 bool
1153 {
1154  NS_LOG_FUNCTION (this);
1155  return m_ipForward;
1156 }
1157 
1158 void
1160 {
1161  NS_LOG_FUNCTION (this << model);
1162  m_weakEsModel = model;
1163 }
1164 
1165 bool
1167 {
1168  NS_LOG_FUNCTION (this);
1169  return m_weakEsModel;
1170 }
1171 
1172 void
1174 {
1175  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1176  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1177  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0);
1178 }
1179 
1180 void
1181 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, uint32_t outIfaceMtu, std::list<Ptr<Packet> >& listFragments)
1182 {
1183  // BEWARE: here we do assume that the header options are not present.
1184  // a much more complex handling is necessary in case there are options.
1185  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1186  // Of course also the reassemby code shall be changed as well.
1187 
1188  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1189 
1190  Ptr<Packet> p = packet->Copy ();
1191 
1192  Ipv4Header ipv4Header;
1193  p->RemoveHeader (ipv4Header);
1194 
1195  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1196  "IPv4 fragmentation implementation only works without option headers." );
1197 
1198  uint16_t offset = 0;
1199  bool moreFragment = true;
1200  uint16_t originalOffset = 0;
1201  bool alreadyFragmented = false;
1202  uint32_t currentFragmentablePartSize = 0;
1203 
1204  if (!ipv4Header.IsLastFragment())
1205  {
1206  alreadyFragmented = true;
1207  originalOffset = ipv4Header.GetFragmentOffset();
1208  }
1209 
1210  // IPv4 fragments are all 8 bytes aligned but the last.
1211  // The IP payload size is:
1212  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1213  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1214 
1215  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1216 
1217  do
1218  {
1219  Ipv4Header fragmentHeader = ipv4Header;
1220 
1221  if (p->GetSize () > offset + fragmentSize )
1222  {
1223  moreFragment = true;
1224  currentFragmentablePartSize = fragmentSize;
1225  fragmentHeader.SetMoreFragments ();
1226  }
1227  else
1228  {
1229  moreFragment = false;
1230  currentFragmentablePartSize = p->GetSize () - offset;
1231  if (alreadyFragmented)
1232  {
1233  fragmentHeader.SetMoreFragments ();
1234  }
1235  else
1236  {
1237  fragmentHeader.SetLastFragment ();
1238  }
1239  }
1240 
1241  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1242  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1243  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1244 
1245  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1246  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1247 
1248  if (Node::ChecksumEnabled ())
1249  {
1250  fragmentHeader.EnableChecksum ();
1251  }
1252 
1253  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1254 
1255  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1256  fragment->AddHeader (fragmentHeader);
1257 
1258  std::ostringstream oss;
1259  fragment->Print (oss);
1260 
1261  NS_LOG_LOGIC ("New fragment " << *fragment);
1262 
1263  listFragments.push_back (fragment);
1264 
1265  offset += currentFragmentablePartSize;
1266 
1267  }
1268  while (moreFragment);
1269 
1270  return;
1271 }
1272 
1273 bool
1274 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1275 {
1276  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1277 
1278  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 & uint64_t (ipHeader.GetDestination ().Get ());
1279  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 & uint32_t (ipHeader.GetProtocol ());
1280  std::pair<uint64_t, uint32_t> key;
1281  bool ret = false;
1282  Ptr<Packet> p = packet->Copy ();
1283 
1284  key.first = addressCombination;
1285  key.second = idProto;
1286 
1287  Ptr<Fragments> fragments;
1288 
1289  MapFragments_t::iterator it = m_fragments.find (key);
1290  if (it == m_fragments.end ())
1291  {
1292  fragments = Create<Fragments> ();
1293  m_fragments.insert (std::make_pair (key, fragments));
1296  key, ipHeader, iif);
1297  }
1298  else
1299  {
1300  fragments = it->second;
1301  }
1302 
1303  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1304 
1305  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1306 
1307  if ( fragments->IsEntire () )
1308  {
1309  packet = fragments->GetPacket ();
1310  fragments = 0;
1311  m_fragments.erase (key);
1312  if (m_fragmentsTimers[key].IsRunning ())
1313  {
1314  NS_LOG_LOGIC ("Stopping WaitFragmentsTimer at " << Simulator::Now ().GetSeconds () << " due to complete packet");
1315  m_fragmentsTimers[key].Cancel ();
1316  }
1317  m_fragmentsTimers.erase (key);
1318  ret = true;
1319  }
1320 
1321  return ret;
1322 }
1323 
1325  : m_moreFragment (0)
1326 {
1327  NS_LOG_FUNCTION (this);
1328 }
1329 
1331 {
1332  NS_LOG_FUNCTION (this);
1333 }
1334 
1335 void
1336 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1337 {
1338  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1339 
1340  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1341 
1342  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1343  {
1344  if (it->second > fragmentOffset)
1345  {
1346  break;
1347  }
1348  }
1349 
1350  if (it == m_fragments.end ())
1351  {
1352  m_moreFragment = moreFragment;
1353  }
1354 
1355  m_fragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1356 }
1357 
1358 bool
1360 {
1361  NS_LOG_FUNCTION (this);
1362 
1363  bool ret = !m_moreFragment && m_fragments.size () > 0;
1364 
1365  if (ret)
1366  {
1367  uint16_t lastEndOffset = 0;
1368 
1369  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1370  {
1371  // overlapping fragments do exist
1372  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1373 
1374  if (lastEndOffset < it->second)
1375  {
1376  ret = false;
1377  break;
1378  }
1379  // fragments might overlap in strange ways
1380  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1381  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1382  }
1383  }
1384 
1385  return ret;
1386 }
1387 
1390 {
1391  NS_LOG_FUNCTION (this);
1392 
1393  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1394 
1395  Ptr<Packet> p = Create<Packet> ();
1396  uint16_t lastEndOffset = 0;
1397 
1398  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1399  {
1400  if ( lastEndOffset > it->second )
1401  {
1402  // The fragments are overlapping.
1403  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1404  // This is different from what Linux does.
1405  // It is not possible to emulate a fragmentation attack.
1406  uint32_t newStart = lastEndOffset - it->second;
1407  if ( it->first->GetSize () > newStart )
1408  {
1409  uint32_t newSize = it->first->GetSize () - newStart;
1410  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1411  p->AddAtEnd (tempFragment);
1412  }
1413  }
1414  else
1415  {
1416  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1417  p->AddAtEnd (it->first);
1418  }
1419  lastEndOffset = p->GetSize ();
1420  }
1421 
1422  return p;
1423 }
1424 
1427 {
1428  NS_LOG_FUNCTION (this);
1429 
1430  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1431 
1432  Ptr<Packet> p = Create<Packet> ();
1433  uint16_t lastEndOffset = 0;
1434 
1435  if ( m_fragments.begin ()->second > 0 )
1436  {
1437  return p;
1438  }
1439 
1440  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1441  {
1442  if ( lastEndOffset > it->second )
1443  {
1444  uint32_t newStart = lastEndOffset - it->second;
1445  uint32_t newSize = it->first->GetSize () - newStart;
1446  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1447  p->AddAtEnd (tempFragment);
1448  }
1449  else if ( lastEndOffset == it->second )
1450  {
1451  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1452  p->AddAtEnd (it->first);
1453  }
1454  lastEndOffset = p->GetSize ();
1455  }
1456 
1457  return p;
1458 }
1459 
1460 void
1461 Ipv4L3Protocol::HandleFragmentsTimeout (std::pair<uint64_t, uint32_t> key, Ipv4Header & ipHeader, uint32_t iif)
1462 {
1463  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1464 
1465  MapFragments_t::iterator it = m_fragments.find (key);
1466  Ptr<Packet> packet = it->second->GetPartialPacket ();
1467 
1468  // if we have at least 8 bytes, we can send an ICMP.
1469  if ( packet->GetSize () > 8 )
1470  {
1471  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1472  icmp->SendTimeExceededTtl (ipHeader, packet);
1473  }
1474  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4> (), iif);
1475 
1476  // clear the buffers
1477  it->second = 0;
1478 
1479  m_fragments.erase (key);
1480  m_fragmentsTimers.erase (key);
1481 }
1482 
1483 } // namespace ns3
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:284
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:268
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
void SetForwarding(bool val)
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberContainer)
Definition: object-vector.h:51
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
void SetDefaultTtl(uint8_t ttl)
virtual void SetIpForward(bool forward)
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Receive a packet.
Ptr< Packet > GetPacket() const
Get the entire packet.
static Ipv4Address GetAny(void)
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:297
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
virtual void NotifyNewAggregate()
Ipv4Address GetLocal(void) const
uint8_t GetTos(void) const
Definition: socket.cc:766
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_sendOutgoingTrace
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:210
void Send(Ptr< Packet > p, Ipv4Address dest)
static bool ChecksumEnabled(void)
Definition: node.cc:265
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
bool IsLocalMulticast(void) const
#define NS_ASSERT(condition)
Definition: assert.h:64
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:271
virtual bool GetWeakEsModel(void) const
void SetNode(Ptr< Node > node)
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
uint32_t GetSize(void) const
Definition: packet.h:650
bool IsMulticast(void) const
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
void SetFragmentOffset(uint16_t offsetBytes)
Definition: ipv4-header.cc:238
virtual void DoDispose(void)
Definition: object.cc:335
int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
int32_t GetInterfaceForPrefix(Ipv4Address addr, Ipv4Mask mask) const
Return the interface number of first interface found that has an Ipv4 address within the prefix speci...
bool AddAddress(Ipv4InterfaceAddress address)
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:277
uint32_t AddInterface(Ptr< NetDevice > device)
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Definition: simulator.h:824
TracedCallback< const Ipv4Header &, Ptr< const Packet >, DropReason, Ptr< Ipv4 >, uint32_t > m_dropTrace
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:869
void SetDontFragment(void)
Definition: ipv4-header.cc:219
void Print(std::ostream &os) const
Definition: packet.cc:429
Ptr< Ipv4RoutingProtocol > m_routingProtocol
void SetUp(uint32_t i)
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
a polymophic address class
Definition: address.h:86
Ipv4InterfaceAddress GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const
void SetSource(Ipv4Address src)
Definition: ipv4-route.cc:49
Ptr< T > CreateObject(void)
Definition: object.h:419
bool IsSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
Ptr< NetDevice > GetOutputDevice(void) const
Definition: ipv4-route.cc:84
Ipv4InterfaceList m_interfaces
bool IsDestinationAddress(Ipv4Address address, uint32_t iif) const
Determine whether address and interface corresponding to received packet can be accepted for local de...
Ptr< Packet > GetPartialPacket() const
Get the complete part of the packet.
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_rxTrace
Ptr< Packet > CreateFragment(uint32_t start, uint32_t length) const
Definition: packet.cc:228
Packet header for IPv4.
Definition: ipv4-header.h:31
void AddAtEnd(Ptr< const Packet > packet)
Definition: packet.cc:317
void SetLastFragment(void)
Definition: ipv4-header.cc:206
hold objects of type ns3::Time
Definition: nstime.h:828
Ptr< Icmpv4L4Protocol > GetIcmp(void) const
Get ICMPv4 protocol.
uint32_t Get(void) const
void SetGateway(Ipv4Address gw)
Definition: ipv4-route.cc:63
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_txTrace
Hold an unsigned integer type.
Definition: uinteger.h:46
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_localDeliverTrace
void EnableChecksum(void)
Enable checksum calculation for this header.
Definition: ipv4-header.cc:49
bool IsEntire() const
If all fragments have been added.
void SetMetric(uint32_t i, uint16_t metric)
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
virtual void DoDispose(void)
bool IsBroadcast(void) const
T * PeekPointer(const Ptr< T > &p)
Definition: ptr.h:279
Ptr< NetDevice > GetDevice(uint32_t index) const
Definition: node.cc:131
Ptr< Socket > CreateRawSocket(void)
Creates a raw socket.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1238
virtual enum RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > incomingInterface)=0
void SetIdentification(uint16_t identification)
Definition: ipv4-header.cc:75
void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)
void SetMayFragment(void)
Definition: ipv4-header.cc:225
static TypeId GetTypeId(void)
bool IsUp(uint32_t i) const
MapFragments_t m_fragments
The hash of fragmented packets.
void SendWithHeader(Ptr< Packet > packet, Ipv4Header ipHeader, Ptr< Ipv4Route > route)
void IpForward(Ptr< Ipv4Route > rtentry, Ptr< const Packet > p, const Ipv4Header &header)
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
Ipv4Address GetGateway(void) const
Definition: ipv4-route.cc:70
#define list
bool RemoveAddress(uint32_t interfaceIndex, uint32_t addressIndex)
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
Ipv4InterfaceAddress GetAddress(uint32_t index) const
virtual void NotifyNewAggregate(void)
Definition: object.cc:314
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:75
uint32_t GetNDevices(void) const
Definition: node.cc:139
void SetForwarding(uint32_t i, bool val)
Ptr< Packet > Copy(void) const
Definition: packet.cc:122
NS_LOG_COMPONENT_DEFINE("Ipv4L3Protocol")
static const uint16_t PROT_NUMBER
int32_t GetInterfaceForAddress(Ipv4Address addr) const
Return the interface number of the interface that has been assigned the specified IP address...
bool IsEqual(const Ipv4Address &other) const
Comparison operation between two Ipv4Addresses.
Definition: ipv4-address.h:81
void SetMoreFragments(void)
Definition: ipv4-header.cc:200
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
void DoFragmentation(Ptr< Packet > packet, uint32_t outIfaceMtu, std::list< Ptr< Packet > > &listFragments)
Fragment a packet.
void SetTos(uint8_t tos)
Definition: ipv4-header.cc:82
void RouteInputError(Ptr< const Packet > p, const Ipv4Header &ipHeader, Socket::SocketErrno sockErrno)
Ipv4Header BuildHeader(Ipv4Address source, Ipv4Address destination, uint8_t protocol, uint16_t payloadSize, uint8_t ttl, uint8_t tos, bool mayFragment)
void SendRealOut(Ptr< Ipv4Route > route, Ptr< Packet > packet, Ipv4Header const &ipHeader)
static Time Now(void)
Definition: simulator.cc:180
void SetOutputDevice(Ptr< NetDevice > outputDevice)
Definition: ipv4-route.cc:77
static Ipv4Address GetLoopback(void)
static Ipv4Mask GetLoopback(void)
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:216
Ptr< NetDevice > GetNetDevice(uint32_t i)
uint16_t GetMetric(void) const
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
bool ProcessFragment(Ptr< Packet > &packet, Ipv4Header &ipHeader, uint32_t iif)
Process a packet fragment.
uint32_t AddIpv4Interface(Ptr< Ipv4Interface > interface)
void Remove(Ptr< IpL4Protocol > protocol)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
Ipv4Address GetBroadcast(void) const
virtual void SetWeakEsModel(bool model)
void SetNode(Ptr< Node > node)
uint32_t AddDevice(Ptr< NetDevice > device)
Definition: node.cc:117
uint32_t GetId(void) const
Definition: node.cc:103
a class to store IPv4 address information on an interface
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
void DeleteRawSocket(Ptr< Socket > socket)
Deletes a particular raw socket.
bool AddAddress(uint32_t i, Ipv4InterfaceAddress address)
#define NS_LOG_WARN(msg)
Definition: log.h:246
Ptr< NetDevice > GetDevice(void) const
Ptr< Ipv4Interface > GetInterface(uint32_t i) const
static uint16_t GetStaticProtocolNumber(void)
void Insert(Ptr< IpL4Protocol > protocol)
bool RemovePacketTag(Tag &tag)
Definition: packet.cc:848
void LocalDeliver(Ptr< const Packet > p, Ipv4Header const &ip, uint32_t iif)
void IpMulticastForward(Ptr< Ipv4MulticastRoute > mrtentry, Ptr< const Packet > p, const Ipv4Header &header)
uint32_t GetNAddresses(uint32_t interface) const
MapFragmentsTimers_t m_fragmentsTimers
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:258
uint16_t GetMtu(uint32_t i) const
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
bool ForwardUp(Ptr< const Packet > p, Ipv4Header ipHeader, Ptr< Ipv4Interface > incomingInterface)
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope(void) const
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:311
uint32_t GetNInterfaces(void) const
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range. Both limits are inclusive.
Definition: time.cc:404
Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const
void SetMetric(uint16_t metric)
#define NS_LOG_ERROR(msg)
Definition: log.h:237
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:264
bool IsUnicast(Ipv4Address ad, Ipv4Mask interfaceMask) const
tuple address
Definition: first.py:37
uint8_t GetTtl(void) const
Definition: socket.cc:589
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_unicastForwardTrace
contain a set of ns3::Object pointers.
uint16_t GetMetric(uint32_t i) const
Ptr< Ipv4RoutingProtocol > GetRoutingProtocol(void) const
Get the routing protocol to be used by this Ipv4 stack.
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:373
Ptr< T > GetObject(void) const
Definition: object.h:360
uint32_t GetNAddresses(void) const
a unique identifier for an interface.
Definition: type-id.h:49
void SetDown(uint32_t i)
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
void HandleFragmentsTimeout(std::pair< uint64_t, uint32_t > key, Ipv4Header &ipHeader, uint32_t iif)
Process the timeout for packet fragments.
virtual bool GetIpForward(void) const
void AddHeader(const Header &header)
Definition: packet.cc:253
static const uint8_t PROT_NUMBER
static const uint16_t PROT_NUMBER
void SetDestination(Ipv4Address dest)
Definition: ipv4-route.cc:35
bool IsUp(void) const
bool IsForwarding(uint32_t i) const
Ipv4Address SelectSourceAddress(Ptr< const NetDevice > device, Ipv4Address dst, Ipv4InterfaceAddress::InterfaceAddressScope_e scope)
Return the first primary source address with scope less than or equal to the requested scope...
void SetRoutingProtocol(Ptr< Ipv4RoutingProtocol > routingProtocol)
Register a new routing protocol to be used by this Ipv4 stack.