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