A Discrete-Event Network Simulator
API
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/string.h"
31 #include "ns3/boolean.h"
32 #include "ns3/trace-source-accessor.h"
33 #include "ns3/object-vector.h"
34 #include "ns3/ipv4-header.h"
35 #include "ns3/boolean.h"
36 #include "ns3/ipv4-routing-table-entry.h"
37 #include "ns3/traffic-control-layer.h"
38 
39 #include "loopback-net-device.h"
40 #include "arp-l3-protocol.h"
41 #include "arp-cache.h"
42 #include "ipv4-l3-protocol.h"
43 #include "icmpv4-l4-protocol.h"
44 #include "ipv4-interface.h"
45 #include "ipv4-raw-socket-impl.h"
46 
47 namespace ns3 {
48 
49 NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
50 
51 const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
52 
53 NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
54 
55 TypeId
57 {
58  static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
59  .SetParent<Ipv4> ()
60  .SetGroupName ("Internet")
61  .AddConstructor<Ipv4L3Protocol> ()
62  .AddAttribute ("DefaultTtl",
63  "The TTL value set by default on "
64  "all outgoing packets generated on this node.",
65  UintegerValue (64),
67  MakeUintegerChecker<uint8_t> ())
68  .AddAttribute ("FragmentExpirationTimeout",
69  "When this timeout expires, the fragments "
70  "will be cleared from the buffer.",
71  TimeValue (Seconds (30)),
73  MakeTimeChecker ())
74  .AddAttribute ("EnableDuplicatePacketDetection",
75  "Enable multicast duplicate packet detection based on RFC 6621",
76  BooleanValue (false),
79  .AddAttribute ("DuplicateExpire", "Expiration delay for duplicate cache entries",
80  TimeValue (MilliSeconds (1)),
82  MakeTimeChecker ())
83  .AddAttribute ("PurgeExpiredPeriod",
84  "Time between purges of expired duplicate packet entries, "
85  "0 means never purge",
86  TimeValue (Seconds (1)),
89  .AddTraceSource ("Tx",
90  "Send ipv4 packet to outgoing interface.",
92  "ns3::Ipv4L3Protocol::TxRxTracedCallback")
93  .AddTraceSource ("Rx",
94  "Receive ipv4 packet from incoming interface.",
96  "ns3::Ipv4L3Protocol::TxRxTracedCallback")
97  .AddTraceSource ("Drop",
98  "Drop ipv4 packet",
100  "ns3::Ipv4L3Protocol::DropTracedCallback")
101  .AddAttribute ("InterfaceList",
102  "The set of Ipv4 interfaces associated to this Ipv4 stack.",
105  MakeObjectVectorChecker<Ipv4Interface> ())
106 
107  .AddTraceSource ("SendOutgoing",
108  "A newly-generated packet by this node is "
109  "about to be queued for transmission",
111  "ns3::Ipv4L3Protocol::SentTracedCallback")
112  .AddTraceSource ("UnicastForward",
113  "A unicast IPv4 packet was received by this node "
114  "and is being forwarded to another node",
116  "ns3::Ipv4L3Protocol::SentTracedCallback")
117  .AddTraceSource ("MulticastForward",
118  "A multicast IPv4 packet was received by this node "
119  "and is being forwarded to another node",
121  "ns3::Ipv4L3Protocol::SentTracedCallback")
122  .AddTraceSource ("LocalDeliver",
123  "An IPv4 packet was received by/for this node, "
124  "and it is being forward up the stack",
126  "ns3::Ipv4L3Protocol::SentTracedCallback")
127 
128  ;
129  return tid;
130 }
131 
133 {
134  NS_LOG_FUNCTION (this);
135 }
136 
138 {
139  NS_LOG_FUNCTION (this);
140 }
141 
142 void
144 {
145  NS_LOG_FUNCTION (this << protocol);
146  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
147  if (m_protocols.find (key) != m_protocols.end ())
148  {
149  NS_LOG_WARN ("Overwriting default protocol " << int(protocol->GetProtocolNumber ()));
150  }
151  m_protocols[key] = protocol;
152 }
153 
154 void
155 Ipv4L3Protocol::Insert (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
156 {
157  NS_LOG_FUNCTION (this << protocol << interfaceIndex);
158 
159  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
160  if (m_protocols.find (key) != m_protocols.end ())
161  {
162  NS_LOG_WARN ("Overwriting protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
163  }
164  m_protocols[key] = protocol;
165 }
166 
167 void
169 {
170  NS_LOG_FUNCTION (this << protocol);
171 
172  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), -1);
173  L4List_t::iterator iter = m_protocols.find (key);
174  if (iter == m_protocols.end ())
175  {
176  NS_LOG_WARN ("Trying to remove an non-existent default protocol " << int(protocol->GetProtocolNumber ()));
177  }
178  else
179  {
180  m_protocols.erase (key);
181  }
182 }
183 
184 void
185 Ipv4L3Protocol::Remove (Ptr<IpL4Protocol> protocol, uint32_t interfaceIndex)
186 {
187  NS_LOG_FUNCTION (this << protocol << interfaceIndex);
188 
189  L4ListKey_t key = std::make_pair (protocol->GetProtocolNumber (), interfaceIndex);
190  L4List_t::iterator iter = m_protocols.find (key);
191  if (iter == m_protocols.end ())
192  {
193  NS_LOG_WARN ("Trying to remove an non-existent protocol " << int(protocol->GetProtocolNumber ()) << " on interface " << int(interfaceIndex));
194  }
195  else
196  {
197  m_protocols.erase (key);
198  }
199 }
200 
202 Ipv4L3Protocol::GetProtocol (int protocolNumber) const
203 {
204  NS_LOG_FUNCTION (this << protocolNumber);
205 
206  return GetProtocol (protocolNumber, -1);
207 }
208 
210 Ipv4L3Protocol::GetProtocol (int protocolNumber, int32_t interfaceIndex) const
211 {
212  NS_LOG_FUNCTION (this << protocolNumber << interfaceIndex);
213 
214  L4ListKey_t key;
215  L4List_t::const_iterator i;
216  if (interfaceIndex >= 0)
217  {
218  // try the interface-specific protocol.
219  key = std::make_pair (protocolNumber, interfaceIndex);
220  i = m_protocols.find (key);
221  if (i != m_protocols.end ())
222  {
223  return i->second;
224  }
225  }
226  // try the generic protocol.
227  key = std::make_pair (protocolNumber, -1);
228  i = m_protocols.find (key);
229  if (i != m_protocols.end ())
230  {
231  return i->second;
232  }
233 
234  return 0;
235 }
236 
237 void
239 {
240  NS_LOG_FUNCTION (this << node);
241  m_node = node;
242  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
243  SetupLoopback ();
244 }
245 
248 {
249  NS_LOG_FUNCTION (this);
250  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
251  socket->SetNode (m_node);
252  m_sockets.push_back (socket);
253  return socket;
254 }
255 void
257 {
258  NS_LOG_FUNCTION (this << socket);
259  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
260  {
261  if ((*i) == socket)
262  {
263  m_sockets.erase (i);
264  return;
265  }
266  }
267  return;
268 }
269 /*
270  * This method is called by AggregateObject and completes the aggregation
271  * by setting the node in the ipv4 stack
272  */
273 void
275 {
276  NS_LOG_FUNCTION (this);
277  if (m_node == 0)
278  {
279  Ptr<Node>node = this->GetObject<Node>();
280  // verify that it's a valid node and that
281  // the node has not been set before
282  if (node != 0)
283  {
284  this->SetNode (node);
285  }
286  }
288 }
289 
290 void
292 {
293  NS_LOG_FUNCTION (this << routingProtocol);
294  m_routingProtocol = routingProtocol;
295  m_routingProtocol->SetIpv4 (this);
296 }
297 
298 
301 {
302  NS_LOG_FUNCTION (this);
303  return m_routingProtocol;
304 }
305 
306 void
308 {
309  NS_LOG_FUNCTION (this);
310  for (L4List_t::iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
311  {
312  i->second = 0;
313  }
314  m_protocols.clear ();
315 
316  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
317  {
318  *i = 0;
319  }
320  m_interfaces.clear ();
322 
323  m_sockets.clear ();
324  m_node = 0;
325  m_routingProtocol = 0;
326 
327  for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
328  {
329  it->second = 0;
330  }
331 
332  m_fragments.clear ();
333  m_timeoutEventList.clear ();
334  if (m_timeoutEvent.IsRunning ())
335  {
337  }
338 
339  if (m_cleanDpd.IsRunning ())
340  {
341  m_cleanDpd.Cancel ();
342  }
343  m_dups.clear ();
344 
346 }
347 
348 void
350 {
351  NS_LOG_FUNCTION (this);
352 
354  Ptr<LoopbackNetDevice> device = 0;
355  // First check whether an existing LoopbackNetDevice exists on the node
356  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
357  {
358  if ((device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i))))
359  {
360  break;
361  }
362  }
363  if (device == 0)
364  {
365  device = CreateObject<LoopbackNetDevice> ();
366  m_node->AddDevice (device);
367  }
368  interface->SetDevice (device);
369  interface->SetNode (m_node);
371  interface->AddAddress (ifaceAddr);
372  uint32_t index = AddIpv4Interface (interface);
373  Ptr<Node> node = GetObject<Node> ();
376  interface->SetUp ();
377  if (m_routingProtocol != 0)
378  {
379  m_routingProtocol->NotifyInterfaceUp (index);
380  }
381 }
382 
383 void
385 {
386  NS_LOG_FUNCTION (this << static_cast<uint32_t> (ttl));
387  m_defaultTtl = ttl;
388 }
389 
390 uint32_t
392 {
393  NS_LOG_FUNCTION (this << device);
394  NS_ASSERT (m_node != 0);
395 
397 
398  NS_ASSERT (tc != 0);
399 
404 
405  tc->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this),
407  tc->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
409 
411  interface->SetNode (m_node);
412  interface->SetDevice (device);
413  interface->SetTrafficControl (tc);
414  interface->SetForwarding (m_ipForward);
415  return AddIpv4Interface (interface);
416 }
417 
418 uint32_t
420 {
421  NS_LOG_FUNCTION (this << interface);
422  uint32_t index = m_interfaces.size ();
423  m_interfaces.push_back (interface);
424  m_reverseInterfacesContainer[interface->GetDevice ()] = index;
425  return index;
426 }
427 
429 Ipv4L3Protocol::GetInterface (uint32_t index) const
430 {
431  NS_LOG_FUNCTION (this << index);
432  if (index < m_interfaces.size ())
433  {
434  return m_interfaces[index];
435  }
436  return 0;
437 }
438 
439 uint32_t
441 {
442  NS_LOG_FUNCTION (this);
443  return m_interfaces.size ();
444 }
445 
446 int32_t
448  Ipv4Address address) const
449 {
450  NS_LOG_FUNCTION (this << address);
451  int32_t interface = 0;
452  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
453  i != m_interfaces.end ();
454  i++, interface++)
455  {
456  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
457  {
458  if ((*i)->GetAddress (j).GetLocal () == address)
459  {
460  return interface;
461  }
462  }
463  }
464 
465  return -1;
466 }
467 
468 int32_t
471  Ipv4Mask mask) const
472 {
473  NS_LOG_FUNCTION (this << address << mask);
474  int32_t interface = 0;
475  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin ();
476  i != m_interfaces.end ();
477  i++, interface++)
478  {
479  for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
480  {
481  if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
482  {
483  return interface;
484  }
485  }
486  }
487 
488  return -1;
489 }
490 
491 int32_t
493  Ptr<const NetDevice> device) const
494 {
495  NS_LOG_FUNCTION (this << device);
496 
497  Ipv4InterfaceReverseContainer::const_iterator iter = m_reverseInterfacesContainer.find (device);
498  if (iter != m_reverseInterfacesContainer.end ())
499  {
500  return (*iter).second;
501  }
502 
503  return -1;
504 }
505 
506 bool
508 {
509  NS_LOG_FUNCTION (this << address << iif);
510  // First check the incoming interface for a unicast address match
511  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
512  {
513  Ipv4InterfaceAddress iaddr = GetAddress (iif, i);
514  if (address == iaddr.GetLocal ())
515  {
516  NS_LOG_LOGIC ("For me (destination " << address << " match)");
517  return true;
518  }
519  if (address == iaddr.GetBroadcast ())
520  {
521  NS_LOG_LOGIC ("For me (interface broadcast address)");
522  return true;
523  }
524  }
525 
526  if (address.IsMulticast ())
527  {
528 #ifdef NOTYET
529  if (MulticastCheckGroup (iif, address ))
530 #endif
531  if (true)
532  {
533  NS_LOG_LOGIC ("For me (Ipv4Addr multicast address)");
534  return true;
535  }
536  }
537 
538  if (address.IsBroadcast ())
539  {
540  NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
541  return true;
542  }
543 
544  if (GetWeakEsModel ()) // Check other interfaces
545  {
546  for (uint32_t j = 0; j < GetNInterfaces (); j++)
547  {
548  if (j == uint32_t (iif)) continue;
549  for (uint32_t i = 0; i < GetNAddresses (j); i++)
550  {
551  Ipv4InterfaceAddress iaddr = GetAddress (j, i);
552  if (address == iaddr.GetLocal ())
553  {
554  NS_LOG_LOGIC ("For me (destination " << address << " match) on another interface");
555  return true;
556  }
557  // This is a small corner case: match another interface's broadcast address
558  if (address == iaddr.GetBroadcast ())
559  {
560  NS_LOG_LOGIC ("For me (interface broadcast address on another interface)");
561  return true;
562  }
563  }
564  }
565  }
566  return false;
567 }
568 
569 void
570 Ipv4L3Protocol::Receive ( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
571  const Address &to, NetDevice::PacketType packetType)
572 {
573  NS_LOG_FUNCTION (this << device << p << protocol << from << to << packetType);
574 
575  NS_LOG_LOGIC ("Packet from " << from << " received on node " <<
576  m_node->GetId ());
577 
578 
579  int32_t interface = GetInterfaceForDevice(device);
580  NS_ASSERT_MSG (interface != -1, "Received a packet from an interface that is not known to IPv4");
581 
582  Ptr<Packet> packet = p->Copy ();
583 
584  Ptr<Ipv4Interface> ipv4Interface = m_interfaces[interface];
585 
586  if (ipv4Interface->IsUp ())
587  {
588  m_rxTrace (packet, this, interface);
589  }
590  else
591  {
592  NS_LOG_LOGIC ("Dropping received packet -- interface is down");
593  Ipv4Header ipHeader;
594  packet->RemoveHeader (ipHeader);
595  m_dropTrace (ipHeader, packet, DROP_INTERFACE_DOWN, this, interface);
596  return;
597  }
598 
599  Ipv4Header ipHeader;
600  if (Node::ChecksumEnabled ())
601  {
602  ipHeader.EnableChecksum ();
603  }
604  packet->RemoveHeader (ipHeader);
605 
606  // Trim any residual frame padding from underlying devices
607  if (ipHeader.GetPayloadSize () < packet->GetSize ())
608  {
609  packet->RemoveAtEnd (packet->GetSize () - ipHeader.GetPayloadSize ());
610  }
611 
612  if (!ipHeader.IsChecksumOk ())
613  {
614  NS_LOG_LOGIC ("Dropping received packet -- checksum not ok");
615  m_dropTrace (ipHeader, packet, DROP_BAD_CHECKSUM, this, interface);
616  return;
617  }
618 
619  // the packet is valid, we update the ARP cache entry (if present)
620  Ptr<ArpCache> arpCache = ipv4Interface->GetArpCache ();
621  if (arpCache)
622  {
623  // case one, it's a a direct routing.
624  ArpCache::Entry *entry = arpCache->Lookup (ipHeader.GetSource ());
625  if (entry)
626  {
627  if (entry->IsAlive ())
628  {
629  entry->UpdateSeen ();
630  }
631  }
632  else
633  {
634  // It's not in the direct routing, so it's the router, and it could have multiple IP addresses.
635  // In doubt, update all of them.
636  // Note: it's a confirmed behavior for Linux routers.
637  std::list<ArpCache::Entry *> entryList = arpCache->LookupInverse (from);
638  std::list<ArpCache::Entry *>::iterator iter;
639  for (iter = entryList.begin (); iter != entryList.end (); iter ++)
640  {
641  if ((*iter)->IsAlive ())
642  {
643  (*iter)->UpdateSeen ();
644  }
645  }
646  }
647  }
648 
649  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
650  {
651  NS_LOG_LOGIC ("Forwarding to raw socket");
652  Ptr<Ipv4RawSocketImpl> socket = *i;
653  socket->ForwardUp (packet, ipHeader, ipv4Interface);
654  }
655 
656  if (m_enableDpd && ipHeader.GetDestination ().IsMulticast () && UpdateDuplicate (packet, ipHeader))
657  {
658  NS_LOG_LOGIC ("Dropping received packet -- duplicate.");
659  m_dropTrace (ipHeader, packet, DROP_DUPLICATE, this, interface);
660  return;
661  }
662 
663  NS_ASSERT_MSG (m_routingProtocol != 0, "Need a routing protocol object to process packets");
664  if (!m_routingProtocol->RouteInput (packet, ipHeader, device,
669  ))
670  {
671  NS_LOG_WARN ("No route found for forwarding packet. Drop.");
672  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, this, interface);
673  }
674 }
675 
678 {
679  NS_LOG_FUNCTION (this);
681  if (prot != 0)
682  {
683  return prot->GetObject<Icmpv4L4Protocol> ();
684  }
685  else
686  {
687  return 0;
688  }
689 }
690 
691 bool
693 {
694  NS_LOG_FUNCTION (this << ad);
695 
696  if (ad.IsBroadcast () || ad.IsMulticast ())
697  {
698  return false;
699  }
700  else
701  {
702  // check for subnet-broadcast
703  for (uint32_t ifaceIndex = 0; ifaceIndex < GetNInterfaces (); ifaceIndex++)
704  {
705  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
706  {
707  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
708  NS_LOG_LOGIC ("Testing address " << ad << " with subnet-directed broadcast " << ifAddr.GetBroadcast () );
709  if (ad == ifAddr.GetBroadcast () )
710  {
711  return false;
712  }
713  }
714  }
715  }
716 
717  return true;
718 }
719 
720 bool
722 {
723  NS_LOG_FUNCTION (this << ad << interfaceMask);
724  return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask);
725 }
726 
727 void
729  Ipv4Header ipHeader,
730  Ptr<Ipv4Route> route)
731 {
732  NS_LOG_FUNCTION (this << packet << ipHeader << route);
733  if (Node::ChecksumEnabled ())
734  {
735  ipHeader.EnableChecksum ();
736  }
737  SendRealOut (route, packet, ipHeader);
738 }
739 
740 void
742  Ptr<Ipv4> ipv4, uint32_t interface)
743 {
744  if (!m_txTrace.IsEmpty ())
745  {
746  Ptr<Packet> packetCopy = packet->Copy ();
747  packetCopy->AddHeader (ipHeader);
748  m_txTrace (packetCopy, ipv4, interface);
749  }
750 }
751 
752 void
754  Ipv4Address source,
755  Ipv4Address destination,
756  uint8_t protocol,
757  Ptr<Ipv4Route> route)
758 {
759  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t (protocol) << route);
760 
761  bool mayFragment = true;
762 
763  // we need a copy of the packet with its tags in case we need to invoke recursion.
764  Ptr<Packet> pktCopyWithTags = packet->Copy ();
765 
766  uint8_t ttl = m_defaultTtl;
767  SocketIpTtlTag ipTtlTag;
768  bool ipTtlTagFound = packet->RemovePacketTag (ipTtlTag);
769  if (ipTtlTagFound)
770  {
771  ttl = ipTtlTag.GetTtl ();
772  }
773 
774  uint8_t tos = 0;
775  SocketIpTosTag ipTosTag;
776  bool ipTosTagFound = packet->RemovePacketTag (ipTosTag);
777  if (ipTosTagFound)
778  {
779  tos = ipTosTag.GetTos ();
780  }
781 
782  // can construct the header here
783  Ipv4Header ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
784 
785  // Handle a few cases:
786  // 1) packet is passed in with a route entry
787  // 1a) packet is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
788  // 1b) packet is passed in with a route entry and valid gateway
789  // 2) packet is passed without a route and packet is destined to limited broadcast address
790  // 3) packet is passed without a route and packet is destined to a subnet-directed broadcast address
791  // 4) packet is passed without a route, packet is not broadcast (e.g., a raw socket call, or ICMP)
792 
793  // 1) packet is passed in with route entry
794  if (route)
795  {
796  // 1a) route->GetGateway is not set (e.g., on-demand)
797  if (!route->GetGateway ().IsInitialized ())
798  {
799  // This could arise because the synchronous RouteOutput() call
800  // returned to the transport protocol with a source address but
801  // there was no next hop available yet (since a route may need
802  // to be queried).
803  NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 1a: packet passed with a route but the Gateway address is uninitialized. This case not yet implemented.");
804  }
805 
806  // 1b) with a valid gateway
807  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1b: passed in with route and valid gateway");
808  int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
809  m_sendOutgoingTrace (ipHeader, packet, interface);
810  if (m_enableDpd && ipHeader.GetDestination ().IsMulticast ())
811  {
812  UpdateDuplicate (packet, ipHeader);
813  }
814  SendRealOut (route, packet->Copy (), ipHeader);
815  return;
816  }
817 
818  // 2) packet is destined to limited broadcast address or link-local multicast address
819  if (destination.IsBroadcast () || destination.IsLocalMulticast ())
820  {
821  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: limited broadcast - no route");
822  uint32_t ifaceIndex = 0;
823  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
824  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
825  {
826  Ptr<Ipv4Interface> outInterface = *ifaceIter;
827  // ANY source matches any interface
828  bool sendIt = source.IsAny ();
829  // check if some specific address on outInterface matches
830  for (uint32_t index = 0; !sendIt && index < outInterface->GetNAddresses (); index++)
831  {
832  if (outInterface->GetAddress (index).GetLocal () == source)
833  {
834  sendIt = true;
835  }
836  }
837 
838  if (sendIt)
839  {
840  // create a proxy route for this interface
841  Ptr<Ipv4Route> route = Create<Ipv4Route> ();
842  route->SetDestination (destination);
843  route->SetGateway (Ipv4Address::GetAny ());
844  route->SetSource (source);
845  route->SetOutputDevice (outInterface->GetDevice ());
846  DecreaseIdentification (source, destination, protocol);
847  Send (pktCopyWithTags, source, destination, protocol, route);
848  }
849  }
850  return;
851  }
852 
853  // 3) check: packet is destined to a subnet-directed broadcast address
854  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
855  ifaceIter != m_interfaces.end (); ifaceIter++)
856  {
857  Ptr<Ipv4Interface> outInterface = *ifaceIter;
858  uint32_t ifaceIndex = GetInterfaceForDevice (outInterface->GetDevice ());
859  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
860  {
861  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
862  NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
863  if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
864  destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
865  {
866  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: subnet directed bcast to " << ifAddr.GetLocal () << " - no route");
867  // create a proxy route for this interface
868  Ptr<Ipv4Route> route = Create<Ipv4Route> ();
869  route->SetDestination (destination);
870  route->SetGateway (Ipv4Address::GetAny ());
871  route->SetSource (source);
872  route->SetOutputDevice (outInterface->GetDevice ());
873  DecreaseIdentification (source, destination, protocol);
874  Send (pktCopyWithTags, source, destination, protocol, route);
875  return;
876  }
877  }
878  }
879 
880  // 4) packet is not broadcast, and route is NULL (e.g., a raw socket call)
881  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4: not broadcast and passed in with no route " << destination);
882  Socket::SocketErrno errno_;
883  Ptr<NetDevice> oif (0); // unused for now
884  Ptr<Ipv4Route> newRoute;
885  if (m_routingProtocol != 0)
886  {
887  newRoute = m_routingProtocol->RouteOutput (pktCopyWithTags, ipHeader, oif, errno_);
888  }
889  else
890  {
891  NS_LOG_ERROR ("Ipv4L3Protocol::Send: m_routingProtocol == 0");
892  }
893  if (newRoute)
894  {
895  DecreaseIdentification (source, destination, protocol);
896  Send (pktCopyWithTags, source, destination, protocol, newRoute);
897  }
898  else
899  {
900  NS_LOG_WARN ("No route to host. Drop.");
901  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, this, 0);
902  DecreaseIdentification (source, destination, protocol);
903  }
904 }
905 
906 void
908  Ipv4Address destination,
909  uint8_t protocol)
910 {
911  uint64_t src = source.Get ();
912  uint64_t dst = destination.Get ();
913  uint64_t srcDst = dst | (src << 32);
914  std::pair<uint64_t, uint8_t> key = std::make_pair (srcDst, protocol);
915  m_identification[key]--;
916 }
917 
920  Ipv4Address source,
921  Ipv4Address destination,
922  uint8_t protocol,
923  uint16_t payloadSize,
924  uint8_t ttl,
925  uint8_t tos,
926  bool mayFragment)
927 {
928  NS_LOG_FUNCTION (this << source << destination << (uint16_t)protocol << payloadSize << (uint16_t)ttl << (uint16_t)tos << mayFragment);
929  Ipv4Header ipHeader;
930  ipHeader.SetSource (source);
931  ipHeader.SetDestination (destination);
932  ipHeader.SetProtocol (protocol);
933  ipHeader.SetPayloadSize (payloadSize);
934  ipHeader.SetTtl (ttl);
935  ipHeader.SetTos (tos);
936 
937  uint64_t src = source.Get ();
938  uint64_t dst = destination.Get ();
939  uint64_t srcDst = dst | (src << 32);
940  std::pair<uint64_t, uint8_t> key = std::make_pair (srcDst, protocol);
941 
942  if (mayFragment == true)
943  {
944  ipHeader.SetMayFragment ();
945  ipHeader.SetIdentification (m_identification[key]);
946  m_identification[key]++;
947  }
948  else
949  {
950  ipHeader.SetDontFragment ();
951  // RFC 6864 does not state anything about atomic datagrams
952  // identification requirement:
953  // >> Originating sources MAY set the IPv4 ID field of atomic datagrams
954  // to any value.
955  ipHeader.SetIdentification (m_identification[key]);
956  m_identification[key]++;
957  }
958  if (Node::ChecksumEnabled ())
959  {
960  ipHeader.EnableChecksum ();
961  }
962  return ipHeader;
963 }
964 
965 void
967  Ptr<Packet> packet,
968  Ipv4Header const &ipHeader)
969 {
970  NS_LOG_FUNCTION (this << route << packet << &ipHeader);
971  if (route == 0)
972  {
973  NS_LOG_WARN ("No route to host. Drop.");
974  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, this, 0);
975  return;
976  }
977  Ptr<NetDevice> outDev = route->GetOutputDevice ();
978  int32_t interface = GetInterfaceForDevice (outDev);
979  NS_ASSERT (interface >= 0);
980  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
981  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
982 
983  Ipv4Address target;
984  std::string targetLabel;
985  if (route->GetGateway ().IsAny ())
986  {
987  target = ipHeader.GetDestination ();
988  targetLabel = "destination";
989  }
990  else
991  {
992  target = route->GetGateway ();
993  targetLabel = "gateway";
994  }
995 
996  if (outInterface->IsUp ())
997  {
998  NS_LOG_LOGIC ("Send to " << targetLabel << " " << target);
999  if ( packet->GetSize () + ipHeader.GetSerializedSize () > outInterface->GetDevice ()->GetMtu () )
1000  {
1001  std::list<Ipv4PayloadHeaderPair> listFragments;
1002  DoFragmentation (packet, ipHeader, outInterface->GetDevice ()->GetMtu (), listFragments);
1003  for ( std::list<Ipv4PayloadHeaderPair>::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
1004  {
1005  NS_LOG_LOGIC ("Sending fragment " << *(it->first) );
1006  CallTxTrace (it->second, it->first, this, interface);
1007  outInterface->Send (it->first, it->second, target);
1008  }
1009  }
1010  else
1011  {
1012  CallTxTrace (ipHeader, packet, this, interface);
1013  outInterface->Send (packet, ipHeader, target);
1014  }
1015  }
1016 }
1017 
1018 // This function analogous to Linux ip_mr_forward()
1019 void
1021 {
1022  NS_LOG_FUNCTION (this << mrtentry << p << header);
1023  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
1024 
1025  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
1026  std::map<uint32_t, uint32_t>::iterator mapIter;
1027 
1028  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
1029  {
1030  uint32_t interface = mapIter->first;
1031  //uint32_t outputTtl = mapIter->second; // Unused for now
1032 
1033  Ptr<Packet> packet = p->Copy ();
1034  Ipv4Header ipHeader = header;
1035  ipHeader.SetTtl (header.GetTtl () - 1);
1036  if (ipHeader.GetTtl () == 0)
1037  {
1038  NS_LOG_WARN ("TTL exceeded. Drop.");
1039  m_dropTrace (header, packet, DROP_TTL_EXPIRED, this, interface);
1040  return;
1041  }
1042  NS_LOG_LOGIC ("Forward multicast via interface " << interface);
1043  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
1044  rtentry->SetSource (ipHeader.GetSource ());
1045  rtentry->SetDestination (ipHeader.GetDestination ());
1046  rtentry->SetGateway (Ipv4Address::GetAny ());
1047  rtentry->SetOutputDevice (GetNetDevice (interface));
1048 
1049  m_multicastForwardTrace (ipHeader, packet, interface);
1050  SendRealOut (rtentry, packet, ipHeader);
1051  continue;
1052  }
1053 }
1054 
1055 // This function analogous to Linux ip_forward()
1056 void
1058 {
1059  NS_LOG_FUNCTION (this << rtentry << p << header);
1060  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
1061  // Forwarding
1062  Ipv4Header ipHeader = header;
1063  Ptr<Packet> packet = p->Copy ();
1064  int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
1065  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
1066  if (ipHeader.GetTtl () == 0)
1067  {
1068  // Do not reply to multicast/broadcast IP address
1069  if (ipHeader.GetDestination ().IsBroadcast () == false &&
1070  ipHeader.GetDestination ().IsMulticast () == false)
1071  {
1072  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1073  icmp->SendTimeExceededTtl (ipHeader, packet, false);
1074  }
1075  NS_LOG_WARN ("TTL exceeded. Drop.");
1076  m_dropTrace (header, packet, DROP_TTL_EXPIRED, this, interface);
1077  return;
1078  }
1079  // in case the packet still has a priority tag attached, remove it
1080  SocketPriorityTag priorityTag;
1081  packet->RemovePacketTag (priorityTag);
1082  uint8_t priority = Socket::IpTos2Priority (ipHeader.GetTos ());
1083  // add a priority tag if the priority is not null
1084  if (priority)
1085  {
1086  priorityTag.SetPriority (priority);
1087  packet->AddPacketTag (priorityTag);
1088  }
1089 
1090  m_unicastForwardTrace (ipHeader, packet, interface);
1091  SendRealOut (rtentry, packet, ipHeader);
1092 }
1093 
1094 void
1096 {
1097  NS_LOG_FUNCTION (this << packet << &ip << iif);
1098  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
1099  Ipv4Header ipHeader = ip;
1100 
1101  if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 )
1102  {
1103  NS_LOG_LOGIC ("Received a fragment, processing " << *p );
1104  bool isPacketComplete;
1105  isPacketComplete = ProcessFragment (p, ipHeader, iif);
1106  if ( isPacketComplete == false)
1107  {
1108  return;
1109  }
1110  NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p );
1111  ipHeader.SetFragmentOffset (0);
1112  ipHeader.SetPayloadSize (p->GetSize ());
1113  }
1114 
1115  m_localDeliverTrace (ipHeader, p, iif);
1116 
1117  Ptr<IpL4Protocol> protocol = GetProtocol (ipHeader.GetProtocol (), iif);
1118  if (protocol != 0)
1119  {
1120  // we need to make a copy in the unlikely event we hit the
1121  // RX_ENDPOINT_UNREACH codepath
1122  Ptr<Packet> copy = p->Copy ();
1123  enum IpL4Protocol::RxStatus status =
1124  protocol->Receive (p, ipHeader, GetInterface (iif));
1125  switch (status) {
1126  case IpL4Protocol::RX_OK:
1127  // fall through
1129  // fall through
1131  break;
1133  if (ipHeader.GetDestination ().IsBroadcast () == true ||
1134  ipHeader.GetDestination ().IsMulticast () == true)
1135  {
1136  break; // Do not reply to broadcast or multicast
1137  }
1138  // Another case to suppress ICMP is a subnet-directed broadcast
1139  bool subnetDirected = false;
1140  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
1141  {
1142  Ipv4InterfaceAddress addr = GetAddress (iif, i);
1143  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ipHeader.GetDestination ().CombineMask (addr.GetMask ()) &&
1144  ipHeader.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
1145  {
1146  subnetDirected = true;
1147  }
1148  }
1149  if (subnetDirected == false)
1150  {
1151  GetIcmp ()->SendDestUnreachPort (ipHeader, copy);
1152  }
1153  }
1154  }
1155 }
1156 
1157 bool
1159 {
1160  NS_LOG_FUNCTION (this << i << address);
1161  Ptr<Ipv4Interface> interface = GetInterface (i);
1162  bool retVal = interface->AddAddress (address);
1163  if (m_routingProtocol != 0)
1164  {
1165  m_routingProtocol->NotifyAddAddress (i, address);
1166  }
1167  return retVal;
1168 }
1169 
1171 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
1172 {
1173  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
1174  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
1175  return interface->GetAddress (addressIndex);
1176 }
1177 
1178 uint32_t
1179 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
1180 {
1181  NS_LOG_FUNCTION (this << interface);
1182  Ptr<Ipv4Interface> iface = GetInterface (interface);
1183  return iface->GetNAddresses ();
1184 }
1185 
1186 bool
1187 Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
1188 {
1189  NS_LOG_FUNCTION (this << i << addressIndex);
1190  Ptr<Ipv4Interface> interface = GetInterface (i);
1191  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
1192  if (address != Ipv4InterfaceAddress ())
1193  {
1194  if (m_routingProtocol != 0)
1195  {
1196  m_routingProtocol->NotifyRemoveAddress (i, address);
1197  }
1198  return true;
1199  }
1200  return false;
1201 }
1202 
1203 bool
1205 {
1206  NS_LOG_FUNCTION (this << i << address);
1207 
1209  {
1210  NS_LOG_WARN ("Cannot remove loopback address.");
1211  return false;
1212  }
1213  Ptr<Ipv4Interface> interface = GetInterface (i);
1214  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
1215  if (ifAddr != Ipv4InterfaceAddress ())
1216  {
1217  if (m_routingProtocol != 0)
1218  {
1219  m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
1220  }
1221  return true;
1222  }
1223  return false;
1224 }
1225 
1228 {
1229  NS_LOG_FUNCTION (this << interfaceIdx << " " << dest);
1230  if (GetNAddresses (interfaceIdx) == 1) // common case
1231  {
1232  return GetAddress (interfaceIdx, 0).GetLocal ();
1233  }
1234  // no way to determine the scope of the destination, so adopt the
1235  // following rule: pick the first available address (index 0) unless
1236  // a subsequent address is on link (in which case, pick the primary
1237  // address if there are multiple)
1238  Ipv4Address candidate = GetAddress (interfaceIdx, 0).GetLocal ();
1239  for (uint32_t i = 0; i < GetNAddresses (interfaceIdx); i++)
1240  {
1241  Ipv4InterfaceAddress test = GetAddress (interfaceIdx, i);
1242  if (test.GetLocal ().CombineMask (test.GetMask ()) == dest.CombineMask (test.GetMask ()))
1243  {
1244  if (test.IsSecondary () == false)
1245  {
1246  return test.GetLocal ();
1247  }
1248  }
1249  }
1250  return candidate;
1251 }
1252 
1253 Ipv4Address
1256 {
1257  NS_LOG_FUNCTION (this << device << dst << scope);
1258  Ipv4Address addr ("0.0.0.0");
1259  Ipv4InterfaceAddress iaddr;
1260  bool found = false;
1261 
1262  if (device != 0)
1263  {
1264  int32_t i = GetInterfaceForDevice (device);
1265  NS_ASSERT_MSG (i >= 0, "No device found on node");
1266  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1267  {
1268  iaddr = GetAddress (i, j);
1269  if (iaddr.IsSecondary ()) continue;
1270  if (iaddr.GetScope () > scope) continue;
1271  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1272  {
1273  return iaddr.GetLocal ();
1274  }
1275  if (!found)
1276  {
1277  addr = iaddr.GetLocal ();
1278  found = true;
1279  }
1280  }
1281  }
1282  if (found)
1283  {
1284  return addr;
1285  }
1286 
1287  // Iterate among all interfaces
1288  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1289  {
1290  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1291  {
1292  iaddr = GetAddress (i, j);
1293  if (iaddr.IsSecondary ()) continue;
1294  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1295  && iaddr.GetScope () <= scope)
1296  {
1297  return iaddr.GetLocal ();
1298  }
1299  }
1300  }
1301  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1302  << scope << ", returning 0");
1303  return addr;
1304 }
1305 
1306 void
1307 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1308 {
1309  NS_LOG_FUNCTION (this << i << metric);
1310  Ptr<Ipv4Interface> interface = GetInterface (i);
1311  interface->SetMetric (metric);
1312 }
1313 
1314 uint16_t
1315 Ipv4L3Protocol::GetMetric (uint32_t i) const
1316 {
1317  NS_LOG_FUNCTION (this << i);
1318  Ptr<Ipv4Interface> interface = GetInterface (i);
1319  return interface->GetMetric ();
1320 }
1321 
1322 uint16_t
1323 Ipv4L3Protocol::GetMtu (uint32_t i) const
1324 {
1325  NS_LOG_FUNCTION (this << i);
1326  Ptr<Ipv4Interface> interface = GetInterface (i);
1327  return interface->GetDevice ()->GetMtu ();
1328 }
1329 
1330 bool
1331 Ipv4L3Protocol::IsUp (uint32_t i) const
1332 {
1333  NS_LOG_FUNCTION (this << i);
1334  Ptr<Ipv4Interface> interface = GetInterface (i);
1335  return interface->IsUp ();
1336 }
1337 
1338 void
1340 {
1341  NS_LOG_FUNCTION (this << i);
1342  Ptr<Ipv4Interface> interface = GetInterface (i);
1343 
1344  // RFC 791, pg.25:
1345  // Every internet module must be able to forward a datagram of 68
1346  // octets without further fragmentation. This is because an internet
1347  // header may be up to 60 octets, and the minimum fragment is 8 octets.
1348  if (interface->GetDevice ()->GetMtu () >= 68)
1349  {
1350  interface->SetUp ();
1351 
1352  if (m_routingProtocol != 0)
1353  {
1354  m_routingProtocol->NotifyInterfaceUp (i);
1355  }
1356  }
1357  else
1358  {
1359  NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv4. Reason: not respecting minimum IPv4 MTU (68 octects)");
1360  }
1361 }
1362 
1363 void
1364 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1365 {
1366  NS_LOG_FUNCTION (this << ifaceIndex);
1367  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1368  interface->SetDown ();
1369 
1370  if (m_routingProtocol != 0)
1371  {
1372  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1373  }
1374 }
1375 
1376 bool
1378 {
1379  NS_LOG_FUNCTION (this << i);
1380  Ptr<Ipv4Interface> interface = GetInterface (i);
1381  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1382  return interface->IsForwarding ();
1383 }
1384 
1385 void
1386 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1387 {
1388  NS_LOG_FUNCTION (this << i);
1389  Ptr<Ipv4Interface> interface = GetInterface (i);
1390  interface->SetForwarding (val);
1391 }
1392 
1395 {
1396  NS_LOG_FUNCTION (this << i);
1397  return GetInterface (i)->GetDevice ();
1398 }
1399 
1400 void
1402 {
1403  NS_LOG_FUNCTION (this << forward);
1404  m_ipForward = forward;
1405  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1406  {
1407  (*i)->SetForwarding (forward);
1408  }
1409 }
1410 
1411 bool
1413 {
1414  NS_LOG_FUNCTION (this);
1415  return m_ipForward;
1416 }
1417 
1418 void
1420 {
1421  NS_LOG_FUNCTION (this << model);
1422  m_weakEsModel = model;
1423 }
1424 
1425 bool
1427 {
1428  NS_LOG_FUNCTION (this);
1429  return m_weakEsModel;
1430 }
1431 
1432 void
1434 {
1435  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1436  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1437  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, this, 0);
1438 
1439  // \todo Send an ICMP no route.
1440 }
1441 
1442 void
1443 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, const Ipv4Header & ipv4Header, uint32_t outIfaceMtu, std::list<Ipv4PayloadHeaderPair>& listFragments)
1444 {
1445  // BEWARE: here we do assume that the header options are not present.
1446  // a much more complex handling is necessary in case there are options.
1447  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1448  // Of course also the reassemby code shall be changed as well.
1449 
1450  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1451 
1452  Ptr<Packet> p = packet->Copy ();
1453 
1454  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1455  "IPv4 fragmentation implementation only works without option headers." );
1456 
1457  uint16_t offset = 0;
1458  bool moreFragment = true;
1459  uint16_t originalOffset = ipv4Header.GetFragmentOffset();
1460  bool isLastFragment = ipv4Header.IsLastFragment();
1461  uint32_t currentFragmentablePartSize = 0;
1462 
1463  // IPv4 fragments are all 8 bytes aligned but the last.
1464  // The IP payload size is:
1465  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1466  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1467 
1468  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1469 
1470  do
1471  {
1472  Ipv4Header fragmentHeader = ipv4Header;
1473 
1474  if (p->GetSize () > offset + fragmentSize )
1475  {
1476  moreFragment = true;
1477  currentFragmentablePartSize = fragmentSize;
1478  fragmentHeader.SetMoreFragments ();
1479  }
1480  else
1481  {
1482  moreFragment = false;
1483  currentFragmentablePartSize = p->GetSize () - offset;
1484  if (!isLastFragment)
1485  {
1486  fragmentHeader.SetMoreFragments ();
1487  }
1488  else
1489  {
1490  fragmentHeader.SetLastFragment ();
1491  }
1492  }
1493 
1494  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1495  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1496  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1497 
1498  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1499  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1500 
1501  if (Node::ChecksumEnabled ())
1502  {
1503  fragmentHeader.EnableChecksum ();
1504  }
1505 
1506  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1507 
1508  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1509 
1510  std::ostringstream oss;
1511  oss << fragmentHeader;
1512  fragment->Print (oss);
1513 
1514  NS_LOG_LOGIC ("New fragment " << *fragment);
1515 
1516  listFragments.emplace_back (fragment, fragmentHeader);
1517 
1518  offset += currentFragmentablePartSize;
1519 
1520  }
1521  while (moreFragment);
1522 
1523  return;
1524 }
1525 
1526 bool
1527 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1528 {
1529  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1530 
1531  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 | uint64_t (ipHeader.GetDestination ().Get ());
1532  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 | uint32_t (ipHeader.GetProtocol ());
1533  FragmentKey_t key;
1534  bool ret = false;
1535  Ptr<Packet> p = packet->Copy ();
1536 
1537  key.first = addressCombination;
1538  key.second = idProto;
1539 
1540  Ptr<Fragments> fragments;
1541 
1542  MapFragments_t::iterator it = m_fragments.find (key);
1543  if (it == m_fragments.end ())
1544  {
1545  fragments = Create<Fragments> ();
1546  m_fragments.insert (std::make_pair (key, fragments));
1547 
1548  FragmentsTimeoutsListI_t iter = SetTimeout (key, ipHeader, iif);
1549  fragments->SetTimeoutIter (iter);
1550  }
1551  else
1552  {
1553  fragments = it->second;
1554  }
1555 
1556  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1557 
1558  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1559 
1560  if ( fragments->IsEntire () )
1561  {
1562  packet = fragments->GetPacket ();
1563  m_timeoutEventList.erase (fragments->GetTimeoutIter ());
1564  fragments = 0;
1565  m_fragments.erase (key);
1566  ret = true;
1567  }
1568 
1569  return ret;
1570 }
1571 
1573  : m_moreFragment (0)
1574 {
1575  NS_LOG_FUNCTION (this);
1576 }
1577 
1579 {
1580  NS_LOG_FUNCTION (this);
1581 }
1582 
1583 void
1584 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1585 {
1586  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1587 
1588  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1589 
1590  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1591  {
1592  if (it->second > fragmentOffset)
1593  {
1594  break;
1595  }
1596  }
1597 
1598  if (it == m_fragments.end ())
1599  {
1600  m_moreFragment = moreFragment;
1601  }
1602 
1603  m_fragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1604 }
1605 
1606 bool
1608 {
1609  NS_LOG_FUNCTION (this);
1610 
1611  bool ret = !m_moreFragment && m_fragments.size () > 0;
1612 
1613  if (ret)
1614  {
1615  uint16_t lastEndOffset = 0;
1616 
1617  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1618  {
1619  // overlapping fragments do exist
1620  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1621 
1622  if (lastEndOffset < it->second)
1623  {
1624  ret = false;
1625  break;
1626  }
1627  // fragments might overlap in strange ways
1628  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1629  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1630  }
1631  }
1632 
1633  return ret;
1634 }
1635 
1638 {
1639  NS_LOG_FUNCTION (this);
1640 
1641  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1642 
1643  Ptr<Packet> p = it->first->Copy ();
1644  uint16_t lastEndOffset = p->GetSize ();
1645  it++;
1646 
1647  for ( ; it != m_fragments.end (); it++)
1648  {
1649  if ( lastEndOffset > it->second )
1650  {
1651  // The fragments are overlapping.
1652  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1653  // This is different from what Linux does.
1654  // It is not possible to emulate a fragmentation attack.
1655  uint32_t newStart = lastEndOffset - it->second;
1656  if ( it->first->GetSize () > newStart )
1657  {
1658  uint32_t newSize = it->first->GetSize () - newStart;
1659  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1660  p->AddAtEnd (tempFragment);
1661  }
1662  }
1663  else
1664  {
1665  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1666  p->AddAtEnd (it->first);
1667  }
1668  lastEndOffset = p->GetSize ();
1669  }
1670 
1671  return p;
1672 }
1673 
1676 {
1677  NS_LOG_FUNCTION (this);
1678 
1679  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1680 
1681  Ptr<Packet> p = Create<Packet> ();
1682  uint16_t lastEndOffset = 0;
1683 
1684  if ( m_fragments.begin ()->second > 0 )
1685  {
1686  return p;
1687  }
1688 
1689  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1690  {
1691  if ( lastEndOffset > it->second )
1692  {
1693  uint32_t newStart = lastEndOffset - it->second;
1694  uint32_t newSize = it->first->GetSize () - newStart;
1695  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1696  p->AddAtEnd (tempFragment);
1697  }
1698  else if ( lastEndOffset == it->second )
1699  {
1700  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1701  p->AddAtEnd (it->first);
1702  }
1703  lastEndOffset = p->GetSize ();
1704  }
1705 
1706  return p;
1707 }
1708 
1709 void
1711 {
1712  m_timeoutIter = iter;
1713  return;
1714 }
1715 
1718 {
1719  return m_timeoutIter;
1720 }
1721 
1722 
1723 void
1725 {
1726  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1727 
1728  MapFragments_t::iterator it = m_fragments.find (key);
1729  Ptr<Packet> packet = it->second->GetPartialPacket ();
1730 
1731  // if we have at least 8 bytes, we can send an ICMP.
1732  if ( packet->GetSize () > 8 )
1733  {
1734  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1735  icmp->SendTimeExceededTtl (ipHeader, packet, true);
1736  }
1737  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, this, iif);
1738 
1739  // clear the buffers
1740  it->second = 0;
1741 
1742  m_fragments.erase (key);
1743 }
1744 
1745 bool
1747 {
1748  NS_LOG_FUNCTION (this << p << header);
1749 
1750  // \todo RFC 6621 mandates SHA-1 hash. For now ns3 hash should be fine.
1751  uint8_t proto = header.GetProtocol ();
1752  Ipv4Address src = header.GetSource ();
1753  Ipv4Address dst = header.GetDestination ();
1754  uint64_t id = header.GetIdentification ();
1755 
1756  // concat hash value onto id
1757  uint64_t hash = id << 32;
1758  if (header.GetFragmentOffset () || !header.IsLastFragment ())
1759  {
1760  // use I-DPD (RFC 6621, Sec 6.2.1)
1761  hash |= header.GetFragmentOffset ();
1762  }
1763  else
1764  {
1765  // use H-DPD (RFC 6621, Sec 6.2.2)
1766 
1767  // serialize packet
1768  Ptr<Packet> pkt = p->Copy ();
1769  pkt->AddHeader (header);
1770 
1771  std::ostringstream oss (std::ios_base::binary);
1772  pkt->CopyData (&oss, pkt->GetSize ());
1773  std::string bytes = oss.str ();
1774 
1775  NS_ASSERT_MSG (bytes.size () >= 20, "Degenerate header serialization");
1776 
1777  // zero out mutable fields
1778  bytes[1] = 0; // DSCP / ECN
1779  bytes[6] = bytes[7] = 0; // Flags / Fragment offset
1780  bytes[8] = 0; // TTL
1781  bytes[10] = bytes[11] = 0; // Header checksum
1782  if (header.GetSerializedSize () > 20) // assume options should be 0'd
1783  {
1784  std::fill_n (bytes.begin () + 20, header.GetSerializedSize () - 20, 0);
1785  }
1786 
1787  // concat hash onto ID
1788  hash |= (uint64_t)Hash32 (bytes);
1789  }
1790 
1791  // set cleanup job for new duplicate entries
1793  {
1795  }
1796 
1797  // assume this is a new entry
1798  DupTuple_t key {hash, proto, src, dst};
1799  NS_LOG_DEBUG ("Packet " << p->GetUid () << " key = (" <<
1800  std::hex << std::get<0> (key) << ", " <<
1801  std::dec << +std::get<1> (key) << ", " <<
1802  std::get<2> (key) << ", " <<
1803  std::get<3> (key) << ")");
1804 
1805  // place a new entry, on collision the existing entry iterator is returned
1806  DupMap_t::iterator iter;
1807  bool inserted, isDup;
1808  std::tie (iter, inserted) = m_dups.emplace (key, Seconds (0));
1809  isDup = !inserted && iter->second > Simulator::Now ();
1810 
1811  // set the expiration event
1812  iter->second = Simulator::Now () + m_expire;
1813  return isDup;
1814 }
1815 
1816 void
1818 {
1819  NS_LOG_FUNCTION (this);
1820 
1821  DupMap_t::size_type n = 0;
1822  Time expire = Simulator::Now ();
1823  auto iter = m_dups.cbegin ();
1824  while (iter != m_dups.cend ())
1825  {
1826  if (iter->second < expire)
1827  {
1828  NS_LOG_LOGIC ("Remove key = (" <<
1829  std::hex << std::get<0> (iter->first) << ", " <<
1830  std::dec << +std::get<1> (iter->first) << ", " <<
1831  std::get<2> (iter->first) << ", " <<
1832  std::get<3> (iter->first) << ")");
1833  iter = m_dups.erase (iter);
1834  ++n;
1835  }
1836  else
1837  {
1838  ++iter;
1839  }
1840  }
1841 
1842  NS_LOG_DEBUG ("Purged " << n << " expired duplicate entries out of " << (n + m_dups.size ()));
1843 
1844  // keep cleaning up if necessary
1845  if (!m_dups.empty () && m_purge.IsStrictlyPositive ())
1846  {
1848  }
1849 }
1850 
1853 {
1855 
1856  if (m_timeoutEventList.empty ())
1857  {
1859  }
1860  m_timeoutEventList.emplace_back (now, key, ipHeader, iif);
1861 
1863 
1864  return (iter);
1865 }
1866 
1867 void
1869 {
1870  Time now = Simulator::Now ();
1871 
1872  while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
1873  {
1874  HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
1875  std::get<2> (*m_timeoutEventList.begin ()),
1876  std::get<3> (*m_timeoutEventList.begin ()));
1877  m_timeoutEventList.pop_front ();
1878  }
1879 
1880  if (m_timeoutEventList.empty ())
1881  {
1882  return;
1883  }
1884 
1885  Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
1887 
1888  return;
1889 }
1890 
1891 } // namespace ns3
#define max(a, b)
Definition: 80211b.c:43
a polymophic address class
Definition: address.h:91
A record that that holds information about an ArpCache entry.
Definition: arp-cache.h:178
bool IsAlive(void)
Definition: arp-cache.cc:375
void UpdateSeen(void)
Update the entry when seeing a packet.
Definition: arp-cache.cc:532
std::list< ArpCache::Entry * > LookupInverse(Address destination)
Do lookup in the ARP cache against a MAC address.
Definition: arp-cache.cc:300
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:318
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Receive a packet.
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806)
AttributeValue implementation for Boolean.
Definition: boolean.h:37
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
This is the implementation of the ICMP protocol as described in RFC 792.
static uint16_t GetStaticProtocolNumber(void)
Get the protocol number.
virtual int GetProtocolNumber(void) const =0
Returns the protocol number of this protocol.
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.
RxStatus
Rx status codes.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
uint32_t Get(void) const
Get the host-order 32-bit IP address.
bool IsMulticast(void) const
static Ipv4Address GetLoopback(void)
bool IsBroadcast(void) const
static Ipv4Address GetAny(void)
bool IsSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
bool IsLocalMulticast(void) const
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
bool IsAny(void) const
Packet header for IPv4.
Definition: ipv4-header.h:34
void SetMoreFragments(void)
This packet is not the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:200
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
void SetLastFragment(void)
This packet is the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:206
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:375
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
uint8_t GetTos(void) const
Definition: ipv4-header.cc:194
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:259
void SetMayFragment(void)
If you need to fragment this packet, you can do it.
Definition: ipv4-header.cc:225
void SetDontFragment(void)
Don't fragment this packet: if you need to anyway, drop it.
Definition: ipv4-header.cc:219
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
void EnableChecksum(void)
Enable checksum calculation for this header.
Definition: ipv4-header.cc:49
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:278
void SetFragmentOffset(uint16_t offsetBytes)
The offset is measured in bytes for the packet start.
Definition: ipv4-header.cc:238
void SetIdentification(uint16_t identification)
Definition: ipv4-header.cc:75
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:312
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
void SetTos(uint8_t tos)
Definition: ipv4-header.cc:82
void SetSource(Ipv4Address source)
Definition: ipv4-header.cc:285
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:265
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:77
a class to store IPv4 address information on an interface
Ipv4Address GetBroadcast(void) const
Get the broadcast address.
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope(void) const
Get address scope.
Ipv4Mask GetMask(void) const
Get the network mask.
Ipv4Address GetLocal(void) const
Get the local address.
bool IsSecondary(void) const
Check if the address is a secondary address.
The IPv4 representation of a network interface.
void SetUp(void)
Enable this interface.
void SetNode(Ptr< Node > node)
Set node associated with interface.
Ipv4InterfaceAddress GetAddress(uint32_t index) const
bool AddAddress(Ipv4InterfaceAddress address)
uint32_t GetNAddresses(void) const
Ptr< ArpCache > GetArpCache() const
uint16_t GetMetric(void) const
Ptr< NetDevice > GetDevice(void) const
void Send(Ptr< Packet > p, const Ipv4Header &hdr, Ipv4Address dest)
void SetDown(void)
Disable this interface.
bool IsUp(void) const
These are IP interface states and may be distinct from NetDevice states, such as found in real implem...
void SetForwarding(bool val)
void SetMetric(uint16_t metric)
bool IsEntire() const
If all fragments have been added.
Ptr< Packet > GetPartialPacket() const
Get the complete part of the packet.
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
Ptr< Packet > GetPacket() const
Get the entire packet.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
Implement the IPv4 layer.
static const uint16_t PROT_NUMBER
Protocol number (0x0800)
std::tuple< uint64_t, uint8_t, Ipv4Address, Ipv4Address > DupTuple_t
IETF RFC 6621, Section 6.2 de-duplication w/o IPSec RFC 6621 recommended duplicate packet tuple: {IPV...
void CallTxTrace(const Ipv4Header &ipHeader, Ptr< Packet > packet, Ptr< Ipv4 > ipv4, uint32_t interface)
Make a copy of the packet, add the header and invoke the TX trace callback.
@ DROP_BAD_CHECKSUM
Bad checksum.
@ DROP_NO_ROUTE
No route to host.
@ DROP_INTERFACE_DOWN
Interface is down so can not send packet.
@ DROP_DUPLICATE
Duplicate packet received.
@ DROP_TTL_EXPIRED
Packet TTL has expired.
@ DROP_ROUTE_ERROR
Route error.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout exceeded.
void DecreaseIdentification(Ipv4Address source, Ipv4Address destination, uint8_t protocol)
Decrease the identification value for a dropped or recursed packet.
Ipv4InterfaceList m_interfaces
List of IPv4 interfaces.
bool IsUp(uint32_t i) const
MapFragments_t m_fragments
Fragmented packets.
bool RemoveAddress(uint32_t interfaceIndex, uint32_t addressIndex)
Remove the address at addressIndex on named interface.
std::pair< uint64_t, uint32_t > FragmentKey_t
Key identifying a fragmented packet.
void DeleteRawSocket(Ptr< Socket > socket)
Deletes a particular raw socket.
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...
Time m_expire
duplicate entry expiration delay
virtual bool GetIpForward(void) const
Get the IP forwarding state.
bool m_ipForward
Forwarding packets (i.e.
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...
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 RouteInputError(Ptr< const Packet > p, const Ipv4Header &ipHeader, Socket::SocketErrno sockErrno)
Fallback when no route is found.
void SetForwarding(uint32_t i, bool val)
virtual void NotifyNewAggregate()
This function will notify other components connected to the node that a new stack member is now conne...
uint32_t GetNAddresses(uint32_t interface) const
uint16_t GetMtu(uint32_t i) const
virtual void SetIpForward(bool forward)
Set or unset the IP forwarding state.
virtual void SetWeakEsModel(bool model)
Set or unset the Weak Es Model.
virtual Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const
Ptr< Ipv4RoutingProtocol > GetRoutingProtocol(void) const
Get the routing protocol to be used by this Ipv4 stack.
bool IsUnicast(Ipv4Address ad) const
Check if an IPv4 address is unicast according to the node.
void HandleFragmentsTimeout(FragmentKey_t key, Ipv4Header &ipHeader, uint32_t iif)
Process the timeout for packet fragments.
void DoFragmentation(Ptr< Packet > packet, const Ipv4Header &ipv4Header, uint32_t outIfaceMtu, std::list< Ipv4PayloadHeaderPair > &listFragments)
Fragment a packet.
SocketList m_sockets
List of IPv4 raw sockets.
virtual Ipv4Address SourceAddressSelection(uint32_t interface, Ipv4Address dest)
Choose the source address to use with destination address.
bool m_enableDpd
Enable multicast duplicate packet detection.
bool AddAddress(uint32_t i, Ipv4InterfaceAddress address)
std::map< std::pair< uint64_t, uint8_t >, uint16_t > m_identification
Identification (for each {src, dst, proto} tuple)
Time m_fragmentExpirationTimeout
Expiration timeout.
static TypeId GetTypeId(void)
Get the type ID.
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_localDeliverTrace
Trace of locally delivered packets.
virtual void Remove(Ptr< IpL4Protocol > protocol)
void HandleTimeout(void)
Handles a fragmented packet timeout.
Ptr< NetDevice > GetNetDevice(uint32_t i)
EventId m_timeoutEvent
Event for the next scheduled timeout.
void SetRoutingProtocol(Ptr< Ipv4RoutingProtocol > routingProtocol)
Register a new routing protocol to be used by this Ipv4 stack.
Time m_purge
time between purging expired duplicate entries
TracedCallback< const Ipv4Header &, Ptr< const Packet >, DropReason, Ptr< Ipv4 >, uint32_t > m_dropTrace
Trace of dropped packets.
void SetNode(Ptr< Node > node)
Set node associated with this stack.
void IpMulticastForward(Ptr< Ipv4MulticastRoute > mrtentry, Ptr< const Packet > p, const Ipv4Header &header)
Forward a multicast packet.
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_rxTrace
Trace of received packets.
uint16_t GetMetric(uint32_t i) const
void RemoveDuplicates(void)
Remove expired duplicates packet entry.
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
bool IsForwarding(uint32_t i) const
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_sendOutgoingTrace
Trace of sent packets.
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_txTrace
Trace of transmitted packets.
void SendWithHeader(Ptr< Packet > packet, Ipv4Header ipHeader, Ptr< Ipv4Route > route)
bool ProcessFragment(Ptr< Packet > &packet, Ipv4Header &ipHeader, uint32_t iif)
Process a packet fragment.
void SetUp(uint32_t i)
Ipv4InterfaceReverseContainer m_reverseInterfacesContainer
Container of NetDevice / Interface index associations.
void SetupLoopback(void)
Setup loopback interface.
void LocalDeliver(Ptr< const Packet > p, Ipv4Header const &ip, uint32_t iif)
Deliver a packet.
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,...
EventId m_cleanDpd
event to cleanup expired duplicate entries
void SetDown(uint32_t i)
L4List_t m_protocols
List of transport protocol.
Ptr< Socket > CreateRawSocket(void)
Creates a raw socket.
Ptr< Ipv4RoutingProtocol > m_routingProtocol
Routing protocol associated with the stack.
void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)
void SendRealOut(Ptr< Ipv4Route > route, Ptr< Packet > packet, Ipv4Header const &ipHeader)
Send packet with route.
Ptr< Icmpv4L4Protocol > GetIcmp(void) const
Get ICMPv4 protocol.
uint32_t AddInterface(Ptr< NetDevice > device)
virtual void DoDispose(void)
Destructor implementation.
uint8_t m_defaultTtl
Default TTL.
bool m_weakEsModel
Weak ES model state.
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_unicastForwardTrace
Trace of unicast forwarded packets.
void SetMetric(uint32_t i, uint16_t metric)
DupMap_t m_dups
map of packet duplicate tuples to expiry event
Ptr< Node > m_node
Node attached to stack.
bool UpdateDuplicate(Ptr< const Packet > p, const Ipv4Header &header)
Registers duplicate entry, return false if new.
virtual void Insert(Ptr< IpL4Protocol > protocol)
int32_t GetInterfaceForAddress(Ipv4Address addr) const
Return the interface number of the interface that has been assigned the specified IP address.
Ptr< Ipv4Interface > GetInterface(uint32_t i) const
Get an interface.
void IpForward(Ptr< Ipv4Route > rtentry, Ptr< const Packet > p, const Ipv4Header &header)
Forward a packet.
void SetDefaultTtl(uint8_t ttl)
int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const
uint32_t GetNInterfaces(void) const
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, Ipv4Header ipHeader, uint32_t iif)
Set a new timeout "event" for a fragmented packet.
virtual bool GetWeakEsModel(void) const
Get the Weak Es Model status.
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...
std::pair< int, int32_t > L4ListKey_t
Container of the IPv4 L4 keys: protocol number, interface index.
std::list< std::tuple< Time, FragmentKey_t, Ipv4Header, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts..
bool IsDestinationAddress(Ipv4Address address, uint32_t iif) const
Determine whether address and interface corresponding to received packet can be accepted for local de...
uint32_t AddIpv4Interface(Ptr< Ipv4Interface > interface)
Add an IPv4 interface to the stack.
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_multicastForwardTrace
Trace of multicast forwarded packets.
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:256
static Ipv4Mask GetLoopback(void)
bool ForwardUp(Ptr< const Packet > p, Ipv4Header ipHeader, Ptr< Ipv4Interface > incomingInterface)
Forward up to receive method.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
virtual uint32_t GetIfIndex(void) const =0
virtual uint16_t GetMtu(void) const =0
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:297
static bool ChecksumEnabled(void)
Definition: node.cc:278
uint32_t GetId(void) const
Definition: node.cc:109
uint32_t AddDevice(Ptr< NetDevice > device)
Associate a NetDevice to this node.
Definition: node.cc:130
uint32_t GetNDevices(void) const
Definition: node.cc:152
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:229
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:325
Container for a set of ns3::Object pointers.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:280
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:355
uint64_t GetUid(void) const
Returns the packet's Uid.
Definition: packet.cc:390
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
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:227
void Print(std::ostream &os) const
Print the packet contents.
Definition: packet.cc:434
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:856
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:556
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
static uint8_t IpTos2Priority(uint8_t ipTos)
Return the priority corresponding to a given TOS value.
Definition: socket.cc:402
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
indicates whether the socket has IP_TOS set.
Definition: socket.h:1263
uint8_t GetTos(void) const
Get the tag's TOS.
Definition: socket.cc:791
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
Definition: socket.h:1117
uint8_t GetTtl(void) const
Get the tag's TTL.
Definition: socket.cc:611
indicates whether the socket has a priority set.
Definition: socket.h:1309
void SetPriority(uint8_t priority)
Set the tag's priority.
Definition: socket.cc:842
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
Definition: nstime.h:332
AttributeValue implementation for Time.
Definition: nstime.h:1308
Introspection did not find any typical Config paths.
virtual void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Called by NetDevices, incoming packet.
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:922
Hold an unsigned integer type.
Definition: uinteger.h:44
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:67
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:88
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: boolean.h:85
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1309
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h:45
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
uint32_t Hash32(const char *buffer, const std::size_t size)
Compute 32-bit hash of a byte buffer, using the default hash function.
Definition: hash.h:282
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:576
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1244
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1252
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Definition: first.py:1
address
Definition: first.py:44
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition: json.h:4680
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:522
Callback< R, Ts... > MakeCallback(R(T::*memPtr)(Ts...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:1648
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:415
Definition: second.py:1
#define list