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, m_node->GetObject<Ipv4> (), 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, m_node->GetObject<Ipv4> (), 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, m_node->GetObject<Ipv4> (), 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, m_node->GetObject<Ipv4> (), 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, m_node->GetObject<Ipv4> (), 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  Ptr<Packet> packetCopy = packet->Copy ();
745  packetCopy->AddHeader (ipHeader);
746  m_txTrace (packetCopy, ipv4, interface);
747 }
748 
749 void
751  Ipv4Address source,
752  Ipv4Address destination,
753  uint8_t protocol,
754  Ptr<Ipv4Route> route)
755 {
756  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t (protocol) << route);
757 
758  bool mayFragment = true;
759 
760  // we need a copy of the packet with its tags in case we need to invoke recursion.
761  Ptr<Packet> pktCopyWithTags = packet->Copy ();
762 
763  uint8_t ttl = m_defaultTtl;
764  SocketIpTtlTag ipTtlTag;
765  bool ipTtlTagFound = packet->RemovePacketTag (ipTtlTag);
766  if (ipTtlTagFound)
767  {
768  ttl = ipTtlTag.GetTtl ();
769  }
770 
771  uint8_t tos = 0;
772  SocketIpTosTag ipTosTag;
773  bool ipTosTagFound = packet->RemovePacketTag (ipTosTag);
774  if (ipTosTagFound)
775  {
776  tos = ipTosTag.GetTos ();
777  }
778 
779  // can construct the header here
780  Ipv4Header ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, tos, mayFragment);
781 
782  // Handle a few cases:
783  // 1) packet is passed in with a route entry
784  // 1a) packet is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
785  // 1b) packet is passed in with a route entry and valid gateway
786  // 2) packet is passed without a route and packet is destined to limited broadcast address
787  // 3) packet is passed without a route and packet is destined to a subnet-directed broadcast address
788  // 4) packet is passed without a route, packet is not broadcast (e.g., a raw socket call, or ICMP)
789 
790  // 1) packet is passed in with route entry
791  if (route)
792  {
793  // 1a) route->GetGateway is not set (e.g., on-demand)
794  if (!route->GetGateway ().IsInitialized ())
795  {
796  // This could arise because the synchronous RouteOutput() call
797  // returned to the transport protocol with a source address but
798  // there was no next hop available yet (since a route may need
799  // to be queried).
800  NS_FATAL_ERROR ("Ipv4L3Protocol::Send case 1a: packet passed with a route but the Gateway address is uninitialized. This case not yet implemented.");
801  }
802 
803  // 1b) with a valid gateway
804  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1b: passed in with route and valid gateway");
805  int32_t interface = GetInterfaceForDevice (route->GetOutputDevice ());
806  m_sendOutgoingTrace (ipHeader, packet, interface);
807  SendRealOut (route, packet->Copy (), ipHeader);
808  return;
809  }
810 
811  // 2) packet is destined to limited broadcast address or link-local multicast address
812  if (destination.IsBroadcast () || destination.IsLocalMulticast ())
813  {
814  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2: limited broadcast - no route");
815  uint32_t ifaceIndex = 0;
816  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
817  ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
818  {
819  Ptr<Ipv4Interface> outInterface = *ifaceIter;
820  // ANY source matches any interface
821  bool sendIt = source.IsAny ();
822  // check if some specific address on outInterface matches
823  for (uint32_t index = 0; !sendIt && index < outInterface->GetNAddresses (); index++)
824  {
825  if (outInterface->GetAddress (index).GetLocal () == source)
826  {
827  sendIt = true;
828  }
829  }
830 
831  if (sendIt)
832  {
833  // create a proxy route for this interface
834  Ptr<Ipv4Route> route = Create<Ipv4Route> ();
835  route->SetDestination (destination);
836  route->SetGateway (Ipv4Address::GetAny ());
837  route->SetSource (source);
838  route->SetOutputDevice (outInterface->GetDevice ());
839  DecreaseIdentification (source, destination, protocol);
840  Send (pktCopyWithTags, source, destination, protocol, route);
841  }
842  }
843  return;
844  }
845 
846  // 3) check: packet is destined to a subnet-directed broadcast address
847  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
848  ifaceIter != m_interfaces.end (); ifaceIter++)
849  {
850  Ptr<Ipv4Interface> outInterface = *ifaceIter;
851  uint32_t ifaceIndex = GetInterfaceForDevice (outInterface->GetDevice ());
852  for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
853  {
854  Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
855  NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
856  if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) &&
857  destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ()) )
858  {
859  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3: subnet directed bcast to " << ifAddr.GetLocal () << " - no route");
860  // create a proxy route for this interface
861  Ptr<Ipv4Route> route = Create<Ipv4Route> ();
862  route->SetDestination (destination);
863  route->SetGateway (Ipv4Address::GetAny ());
864  route->SetSource (source);
865  route->SetOutputDevice (outInterface->GetDevice ());
866  DecreaseIdentification (source, destination, protocol);
867  Send (pktCopyWithTags, source, destination, protocol, route);
868  return;
869  }
870  }
871  }
872 
873  // 4) packet is not broadcast, and route is NULL (e.g., a raw socket call)
874  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4: not broadcast and passed in with no route " << destination);
875  Socket::SocketErrno errno_;
876  Ptr<NetDevice> oif (0); // unused for now
877  Ptr<Ipv4Route> newRoute;
878  if (m_routingProtocol != 0)
879  {
880  newRoute = m_routingProtocol->RouteOutput (pktCopyWithTags, ipHeader, oif, errno_);
881  }
882  else
883  {
884  NS_LOG_ERROR ("Ipv4L3Protocol::Send: m_routingProtocol == 0");
885  }
886  if (newRoute)
887  {
888  DecreaseIdentification (source, destination, protocol);
889  Send (pktCopyWithTags, source, destination, protocol, newRoute);
890  }
891  else
892  {
893  NS_LOG_WARN ("No route to host. Drop.");
894  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
895  DecreaseIdentification (source, destination, protocol);
896  }
897 }
898 
899 void
901  Ipv4Address destination,
902  uint8_t protocol)
903 {
904  uint64_t src = source.Get ();
905  uint64_t dst = destination.Get ();
906  uint64_t srcDst = dst | (src << 32);
907  std::pair<uint64_t, uint8_t> key = std::make_pair (srcDst, protocol);
908  m_identification[key]--;
909 }
910 
913  Ipv4Address source,
914  Ipv4Address destination,
915  uint8_t protocol,
916  uint16_t payloadSize,
917  uint8_t ttl,
918  uint8_t tos,
919  bool mayFragment)
920 {
921  NS_LOG_FUNCTION (this << source << destination << (uint16_t)protocol << payloadSize << (uint16_t)ttl << (uint16_t)tos << mayFragment);
922  Ipv4Header ipHeader;
923  ipHeader.SetSource (source);
924  ipHeader.SetDestination (destination);
925  ipHeader.SetProtocol (protocol);
926  ipHeader.SetPayloadSize (payloadSize);
927  ipHeader.SetTtl (ttl);
928  ipHeader.SetTos (tos);
929 
930  uint64_t src = source.Get ();
931  uint64_t dst = destination.Get ();
932  uint64_t srcDst = dst | (src << 32);
933  std::pair<uint64_t, uint8_t> key = std::make_pair (srcDst, protocol);
934 
935  if (mayFragment == true)
936  {
937  ipHeader.SetMayFragment ();
938  ipHeader.SetIdentification (m_identification[key]);
939  m_identification[key]++;
940  }
941  else
942  {
943  ipHeader.SetDontFragment ();
944  // RFC 6864 does not state anything about atomic datagrams
945  // identification requirement:
946  // >> Originating sources MAY set the IPv4 ID field of atomic datagrams
947  // to any value.
948  ipHeader.SetIdentification (m_identification[key]);
949  m_identification[key]++;
950  }
951  if (Node::ChecksumEnabled ())
952  {
953  ipHeader.EnableChecksum ();
954  }
955  return ipHeader;
956 }
957 
958 void
960  Ptr<Packet> packet,
961  Ipv4Header const &ipHeader)
962 {
963  NS_LOG_FUNCTION (this << route << packet << &ipHeader);
964  if (route == 0)
965  {
966  NS_LOG_WARN ("No route to host. Drop.");
967  m_dropTrace (ipHeader, packet, DROP_NO_ROUTE, m_node->GetObject<Ipv4> (), 0);
968  return;
969  }
970  Ptr<NetDevice> outDev = route->GetOutputDevice ();
971  int32_t interface = GetInterfaceForDevice (outDev);
972  NS_ASSERT (interface >= 0);
973  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
974  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
975 
976  Ipv4Address target;
977  std::string targetLabel;
978  if (route->GetGateway ().IsAny ())
979  {
980  target = ipHeader.GetDestination ();
981  targetLabel = "destination";
982  }
983  else
984  {
985  target = route->GetGateway ();
986  targetLabel = "gateway";
987  }
988 
989  if (outInterface->IsUp ())
990  {
991  NS_LOG_LOGIC ("Send to " << targetLabel << " " << target);
992  if ( packet->GetSize () + ipHeader.GetSerializedSize () > outInterface->GetDevice ()->GetMtu () )
993  {
994  std::list<Ipv4PayloadHeaderPair> listFragments;
995  DoFragmentation (packet, ipHeader, outInterface->GetDevice ()->GetMtu (), listFragments);
996  for ( std::list<Ipv4PayloadHeaderPair>::iterator it = listFragments.begin (); it != listFragments.end (); it++ )
997  {
998  NS_LOG_LOGIC ("Sending fragment " << *(it->first) );
999  CallTxTrace (it->second, it->first, m_node->GetObject<Ipv4> (), interface);
1000  outInterface->Send (it->first, it->second, target);
1001  }
1002  }
1003  else
1004  {
1005  CallTxTrace (ipHeader, packet, m_node->GetObject<Ipv4> (), interface);
1006  outInterface->Send (packet, ipHeader, target);
1007  }
1008  }
1009 }
1010 
1011 // This function analogous to Linux ip_mr_forward()
1012 void
1014 {
1015  NS_LOG_FUNCTION (this << mrtentry << p << header);
1016  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
1017 
1018  std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap ();
1019  std::map<uint32_t, uint32_t>::iterator mapIter;
1020 
1021  for (mapIter = ttlMap.begin (); mapIter != ttlMap.end (); mapIter++)
1022  {
1023  uint32_t interface = mapIter->first;
1024  //uint32_t outputTtl = mapIter->second; // Unused for now
1025 
1026  Ptr<Packet> packet = p->Copy ();
1027  Ipv4Header ipHeader = header;
1028  ipHeader.SetTtl (header.GetTtl () - 1);
1029  if (ipHeader.GetTtl () == 0)
1030  {
1031  NS_LOG_WARN ("TTL exceeded. Drop.");
1032  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interface);
1033  return;
1034  }
1035  NS_LOG_LOGIC ("Forward multicast via interface " << interface);
1036  Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
1037  rtentry->SetSource (ipHeader.GetSource ());
1038  rtentry->SetDestination (ipHeader.GetDestination ());
1039  rtentry->SetGateway (Ipv4Address::GetAny ());
1040  rtentry->SetOutputDevice (GetNetDevice (interface));
1041 
1042  m_multicastForwardTrace (ipHeader, packet, interface);
1043  SendRealOut (rtentry, packet, ipHeader);
1044  continue;
1045  }
1046 }
1047 
1048 // This function analogous to Linux ip_forward()
1049 void
1051 {
1052  NS_LOG_FUNCTION (this << rtentry << p << header);
1053  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
1054  // Forwarding
1055  Ipv4Header ipHeader = header;
1056  Ptr<Packet> packet = p->Copy ();
1057  int32_t interface = GetInterfaceForDevice (rtentry->GetOutputDevice ());
1058  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
1059  if (ipHeader.GetTtl () == 0)
1060  {
1061  // Do not reply to multicast/broadcast IP address
1062  if (ipHeader.GetDestination ().IsBroadcast () == false &&
1063  ipHeader.GetDestination ().IsMulticast () == false)
1064  {
1065  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1066  icmp->SendTimeExceededTtl (ipHeader, packet, false);
1067  }
1068  NS_LOG_WARN ("TTL exceeded. Drop.");
1069  m_dropTrace (header, packet, DROP_TTL_EXPIRED, m_node->GetObject<Ipv4> (), interface);
1070  return;
1071  }
1072  // in case the packet still has a priority tag attached, remove it
1073  SocketPriorityTag priorityTag;
1074  packet->RemovePacketTag (priorityTag);
1075  uint8_t priority = Socket::IpTos2Priority (ipHeader.GetTos ());
1076  // add a priority tag if the priority is not null
1077  if (priority)
1078  {
1079  priorityTag.SetPriority (priority);
1080  packet->AddPacketTag (priorityTag);
1081  }
1082 
1083  m_unicastForwardTrace (ipHeader, packet, interface);
1084  SendRealOut (rtentry, packet, ipHeader);
1085 }
1086 
1087 void
1089 {
1090  NS_LOG_FUNCTION (this << packet << &ip << iif);
1091  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
1092  Ipv4Header ipHeader = ip;
1093 
1094  if ( !ipHeader.IsLastFragment () || ipHeader.GetFragmentOffset () != 0 )
1095  {
1096  NS_LOG_LOGIC ("Received a fragment, processing " << *p );
1097  bool isPacketComplete;
1098  isPacketComplete = ProcessFragment (p, ipHeader, iif);
1099  if ( isPacketComplete == false)
1100  {
1101  return;
1102  }
1103  NS_LOG_LOGIC ("Got last fragment, Packet is complete " << *p );
1104  ipHeader.SetFragmentOffset (0);
1105  ipHeader.SetPayloadSize (p->GetSize ());
1106  }
1107 
1108  m_localDeliverTrace (ipHeader, p, iif);
1109 
1110  Ptr<IpL4Protocol> protocol = GetProtocol (ipHeader.GetProtocol (), iif);
1111  if (protocol != 0)
1112  {
1113  // we need to make a copy in the unlikely event we hit the
1114  // RX_ENDPOINT_UNREACH codepath
1115  Ptr<Packet> copy = p->Copy ();
1116  enum IpL4Protocol::RxStatus status =
1117  protocol->Receive (p, ipHeader, GetInterface (iif));
1118  switch (status) {
1119  case IpL4Protocol::RX_OK:
1120  // fall through
1122  // fall through
1124  break;
1126  if (ipHeader.GetDestination ().IsBroadcast () == true ||
1127  ipHeader.GetDestination ().IsMulticast () == true)
1128  {
1129  break; // Do not reply to broadcast or multicast
1130  }
1131  // Another case to suppress ICMP is a subnet-directed broadcast
1132  bool subnetDirected = false;
1133  for (uint32_t i = 0; i < GetNAddresses (iif); i++)
1134  {
1135  Ipv4InterfaceAddress addr = GetAddress (iif, i);
1136  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ipHeader.GetDestination ().CombineMask (addr.GetMask ()) &&
1137  ipHeader.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
1138  {
1139  subnetDirected = true;
1140  }
1141  }
1142  if (subnetDirected == false)
1143  {
1144  GetIcmp ()->SendDestUnreachPort (ipHeader, copy);
1145  }
1146  }
1147  }
1148 }
1149 
1150 bool
1152 {
1153  NS_LOG_FUNCTION (this << i << address);
1154  Ptr<Ipv4Interface> interface = GetInterface (i);
1155  bool retVal = interface->AddAddress (address);
1156  if (m_routingProtocol != 0)
1157  {
1158  m_routingProtocol->NotifyAddAddress (i, address);
1159  }
1160  return retVal;
1161 }
1162 
1164 Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
1165 {
1166  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
1167  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
1168  return interface->GetAddress (addressIndex);
1169 }
1170 
1171 uint32_t
1172 Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
1173 {
1174  NS_LOG_FUNCTION (this << interface);
1175  Ptr<Ipv4Interface> iface = GetInterface (interface);
1176  return iface->GetNAddresses ();
1177 }
1178 
1179 bool
1180 Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
1181 {
1182  NS_LOG_FUNCTION (this << i << addressIndex);
1183  Ptr<Ipv4Interface> interface = GetInterface (i);
1184  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
1185  if (address != Ipv4InterfaceAddress ())
1186  {
1187  if (m_routingProtocol != 0)
1188  {
1189  m_routingProtocol->NotifyRemoveAddress (i, address);
1190  }
1191  return true;
1192  }
1193  return false;
1194 }
1195 
1196 bool
1198 {
1199  NS_LOG_FUNCTION (this << i << address);
1200 
1202  {
1203  NS_LOG_WARN ("Cannot remove loopback address.");
1204  return false;
1205  }
1206  Ptr<Ipv4Interface> interface = GetInterface (i);
1207  Ipv4InterfaceAddress ifAddr = interface->RemoveAddress (address);
1208  if (ifAddr != Ipv4InterfaceAddress ())
1209  {
1210  if (m_routingProtocol != 0)
1211  {
1212  m_routingProtocol->NotifyRemoveAddress (i, ifAddr);
1213  }
1214  return true;
1215  }
1216  return false;
1217 }
1218 
1221 {
1222  NS_LOG_FUNCTION (this << interfaceIdx << " " << dest);
1223  if (GetNAddresses (interfaceIdx) == 1) // common case
1224  {
1225  return GetAddress (interfaceIdx, 0).GetLocal ();
1226  }
1227  // no way to determine the scope of the destination, so adopt the
1228  // following rule: pick the first available address (index 0) unless
1229  // a subsequent address is on link (in which case, pick the primary
1230  // address if there are multiple)
1231  Ipv4Address candidate = GetAddress (interfaceIdx, 0).GetLocal ();
1232  for (uint32_t i = 0; i < GetNAddresses (interfaceIdx); i++)
1233  {
1234  Ipv4InterfaceAddress test = GetAddress (interfaceIdx, i);
1235  if (test.GetLocal ().CombineMask (test.GetMask ()) == dest.CombineMask (test.GetMask ()))
1236  {
1237  if (test.IsSecondary () == false)
1238  {
1239  return test.GetLocal ();
1240  }
1241  }
1242  }
1243  return candidate;
1244 }
1245 
1246 Ipv4Address
1249 {
1250  NS_LOG_FUNCTION (this << device << dst << scope);
1251  Ipv4Address addr ("0.0.0.0");
1252  Ipv4InterfaceAddress iaddr;
1253  bool found = false;
1254 
1255  if (device != 0)
1256  {
1257  int32_t i = GetInterfaceForDevice (device);
1258  NS_ASSERT_MSG (i >= 0, "No device found on node");
1259  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1260  {
1261  iaddr = GetAddress (i, j);
1262  if (iaddr.IsSecondary ()) continue;
1263  if (iaddr.GetScope () > scope) continue;
1264  if (dst.CombineMask (iaddr.GetMask ()) == iaddr.GetLocal ().CombineMask (iaddr.GetMask ()) )
1265  {
1266  return iaddr.GetLocal ();
1267  }
1268  if (!found)
1269  {
1270  addr = iaddr.GetLocal ();
1271  found = true;
1272  }
1273  }
1274  }
1275  if (found)
1276  {
1277  return addr;
1278  }
1279 
1280  // Iterate among all interfaces
1281  for (uint32_t i = 0; i < GetNInterfaces (); i++)
1282  {
1283  for (uint32_t j = 0; j < GetNAddresses (i); j++)
1284  {
1285  iaddr = GetAddress (i, j);
1286  if (iaddr.IsSecondary ()) continue;
1287  if (iaddr.GetScope () != Ipv4InterfaceAddress::LINK
1288  && iaddr.GetScope () <= scope)
1289  {
1290  return iaddr.GetLocal ();
1291  }
1292  }
1293  }
1294  NS_LOG_WARN ("Could not find source address for " << dst << " and scope "
1295  << scope << ", returning 0");
1296  return addr;
1297 }
1298 
1299 void
1300 Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
1301 {
1302  NS_LOG_FUNCTION (this << i << metric);
1303  Ptr<Ipv4Interface> interface = GetInterface (i);
1304  interface->SetMetric (metric);
1305 }
1306 
1307 uint16_t
1308 Ipv4L3Protocol::GetMetric (uint32_t i) const
1309 {
1310  NS_LOG_FUNCTION (this << i);
1311  Ptr<Ipv4Interface> interface = GetInterface (i);
1312  return interface->GetMetric ();
1313 }
1314 
1315 uint16_t
1316 Ipv4L3Protocol::GetMtu (uint32_t i) const
1317 {
1318  NS_LOG_FUNCTION (this << i);
1319  Ptr<Ipv4Interface> interface = GetInterface (i);
1320  return interface->GetDevice ()->GetMtu ();
1321 }
1322 
1323 bool
1324 Ipv4L3Protocol::IsUp (uint32_t i) const
1325 {
1326  NS_LOG_FUNCTION (this << i);
1327  Ptr<Ipv4Interface> interface = GetInterface (i);
1328  return interface->IsUp ();
1329 }
1330 
1331 void
1333 {
1334  NS_LOG_FUNCTION (this << i);
1335  Ptr<Ipv4Interface> interface = GetInterface (i);
1336 
1337  // RFC 791, pg.25:
1338  // Every internet module must be able to forward a datagram of 68
1339  // octets without further fragmentation. This is because an internet
1340  // header may be up to 60 octets, and the minimum fragment is 8 octets.
1341  if (interface->GetDevice ()->GetMtu () >= 68)
1342  {
1343  interface->SetUp ();
1344 
1345  if (m_routingProtocol != 0)
1346  {
1347  m_routingProtocol->NotifyInterfaceUp (i);
1348  }
1349  }
1350  else
1351  {
1352  NS_LOG_LOGIC ("Interface " << int(i) << " is set to be down for IPv4. Reason: not respecting minimum IPv4 MTU (68 octects)");
1353  }
1354 }
1355 
1356 void
1357 Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
1358 {
1359  NS_LOG_FUNCTION (this << ifaceIndex);
1360  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
1361  interface->SetDown ();
1362 
1363  if (m_routingProtocol != 0)
1364  {
1365  m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
1366  }
1367 }
1368 
1369 bool
1371 {
1372  NS_LOG_FUNCTION (this << i);
1373  Ptr<Ipv4Interface> interface = GetInterface (i);
1374  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
1375  return interface->IsForwarding ();
1376 }
1377 
1378 void
1379 Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
1380 {
1381  NS_LOG_FUNCTION (this << i);
1382  Ptr<Ipv4Interface> interface = GetInterface (i);
1383  interface->SetForwarding (val);
1384 }
1385 
1388 {
1389  NS_LOG_FUNCTION (this << i);
1390  return GetInterface (i)->GetDevice ();
1391 }
1392 
1393 void
1395 {
1396  NS_LOG_FUNCTION (this << forward);
1397  m_ipForward = forward;
1398  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
1399  {
1400  (*i)->SetForwarding (forward);
1401  }
1402 }
1403 
1404 bool
1406 {
1407  NS_LOG_FUNCTION (this);
1408  return m_ipForward;
1409 }
1410 
1411 void
1413 {
1414  NS_LOG_FUNCTION (this << model);
1415  m_weakEsModel = model;
1416 }
1417 
1418 bool
1420 {
1421  NS_LOG_FUNCTION (this);
1422  return m_weakEsModel;
1423 }
1424 
1425 void
1427 {
1428  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
1429  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno);
1430  m_dropTrace (ipHeader, p, DROP_ROUTE_ERROR, m_node->GetObject<Ipv4> (), 0);
1431 
1432  // \todo Send an ICMP no route.
1433 }
1434 
1435 void
1436 Ipv4L3Protocol::DoFragmentation (Ptr<Packet> packet, const Ipv4Header & ipv4Header, uint32_t outIfaceMtu, std::list<Ipv4PayloadHeaderPair>& listFragments)
1437 {
1438  // BEWARE: here we do assume that the header options are not present.
1439  // a much more complex handling is necessary in case there are options.
1440  // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1441  // Of course also the reassemby code shall be changed as well.
1442 
1443  NS_LOG_FUNCTION (this << *packet << outIfaceMtu << &listFragments);
1444 
1445  Ptr<Packet> p = packet->Copy ();
1446 
1447  NS_ASSERT_MSG( (ipv4Header.GetSerializedSize() == 5*4),
1448  "IPv4 fragmentation implementation only works without option headers." );
1449 
1450  uint16_t offset = 0;
1451  bool moreFragment = true;
1452  uint16_t originalOffset = ipv4Header.GetFragmentOffset();
1453  bool isLastFragment = ipv4Header.IsLastFragment();
1454  uint32_t currentFragmentablePartSize = 0;
1455 
1456  // IPv4 fragments are all 8 bytes aligned but the last.
1457  // The IP payload size is:
1458  // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1459  uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize () ) & ~uint32_t (0x7);
1460 
1461  NS_LOG_LOGIC ("Fragmenting - Target Size: " << fragmentSize );
1462 
1463  do
1464  {
1465  Ipv4Header fragmentHeader = ipv4Header;
1466 
1467  if (p->GetSize () > offset + fragmentSize )
1468  {
1469  moreFragment = true;
1470  currentFragmentablePartSize = fragmentSize;
1471  fragmentHeader.SetMoreFragments ();
1472  }
1473  else
1474  {
1475  moreFragment = false;
1476  currentFragmentablePartSize = p->GetSize () - offset;
1477  if (!isLastFragment)
1478  {
1479  fragmentHeader.SetMoreFragments ();
1480  }
1481  else
1482  {
1483  fragmentHeader.SetLastFragment ();
1484  }
1485  }
1486 
1487  NS_LOG_LOGIC ("Fragment creation - " << offset << ", " << currentFragmentablePartSize );
1488  Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
1489  NS_LOG_LOGIC ("Fragment created - " << offset << ", " << fragment->GetSize () );
1490 
1491  fragmentHeader.SetFragmentOffset (offset+originalOffset);
1492  fragmentHeader.SetPayloadSize (currentFragmentablePartSize);
1493 
1494  if (Node::ChecksumEnabled ())
1495  {
1496  fragmentHeader.EnableChecksum ();
1497  }
1498 
1499  NS_LOG_LOGIC ("Fragment check - " << fragmentHeader.GetFragmentOffset () );
1500 
1501  NS_LOG_LOGIC ("New fragment Header " << fragmentHeader);
1502 
1503  std::ostringstream oss;
1504  oss << fragmentHeader;
1505  fragment->Print (oss);
1506 
1507  NS_LOG_LOGIC ("New fragment " << *fragment);
1508 
1509  listFragments.emplace_back (fragment, fragmentHeader);
1510 
1511  offset += currentFragmentablePartSize;
1512 
1513  }
1514  while (moreFragment);
1515 
1516  return;
1517 }
1518 
1519 bool
1520 Ipv4L3Protocol::ProcessFragment (Ptr<Packet>& packet, Ipv4Header& ipHeader, uint32_t iif)
1521 {
1522  NS_LOG_FUNCTION (this << packet << ipHeader << iif);
1523 
1524  uint64_t addressCombination = uint64_t (ipHeader.GetSource ().Get ()) << 32 | uint64_t (ipHeader.GetDestination ().Get ());
1525  uint32_t idProto = uint32_t (ipHeader.GetIdentification ()) << 16 | uint32_t (ipHeader.GetProtocol ());
1526  FragmentKey_t key;
1527  bool ret = false;
1528  Ptr<Packet> p = packet->Copy ();
1529 
1530  key.first = addressCombination;
1531  key.second = idProto;
1532 
1533  Ptr<Fragments> fragments;
1534 
1535  MapFragments_t::iterator it = m_fragments.find (key);
1536  if (it == m_fragments.end ())
1537  {
1538  fragments = Create<Fragments> ();
1539  m_fragments.insert (std::make_pair (key, fragments));
1540 
1541  FragmentsTimeoutsListI_t iter = SetTimeout (key, ipHeader, iif);
1542  fragments->SetTimeoutIter (iter);
1543  }
1544  else
1545  {
1546  fragments = it->second;
1547  }
1548 
1549  NS_LOG_LOGIC ("Adding fragment - Size: " << packet->GetSize ( ) << " - Offset: " << (ipHeader.GetFragmentOffset ()) );
1550 
1551  fragments->AddFragment (p, ipHeader.GetFragmentOffset (), !ipHeader.IsLastFragment () );
1552 
1553  if ( fragments->IsEntire () )
1554  {
1555  packet = fragments->GetPacket ();
1556  m_timeoutEventList.erase (fragments->GetTimeoutIter ());
1557  fragments = 0;
1558  m_fragments.erase (key);
1559  ret = true;
1560  }
1561 
1562  return ret;
1563 }
1564 
1566  : m_moreFragment (0)
1567 {
1568  NS_LOG_FUNCTION (this);
1569 }
1570 
1572 {
1573  NS_LOG_FUNCTION (this);
1574 }
1575 
1576 void
1577 Ipv4L3Protocol::Fragments::AddFragment (Ptr<Packet> fragment, uint16_t fragmentOffset, bool moreFragment)
1578 {
1579  NS_LOG_FUNCTION (this << fragment << fragmentOffset << moreFragment);
1580 
1581  std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
1582 
1583  for (it = m_fragments.begin (); it != m_fragments.end (); it++)
1584  {
1585  if (it->second > fragmentOffset)
1586  {
1587  break;
1588  }
1589  }
1590 
1591  if (it == m_fragments.end ())
1592  {
1593  m_moreFragment = moreFragment;
1594  }
1595 
1596  m_fragments.insert (it, std::pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
1597 }
1598 
1599 bool
1601 {
1602  NS_LOG_FUNCTION (this);
1603 
1604  bool ret = !m_moreFragment && m_fragments.size () > 0;
1605 
1606  if (ret)
1607  {
1608  uint16_t lastEndOffset = 0;
1609 
1610  for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
1611  {
1612  // overlapping fragments do exist
1613  NS_LOG_LOGIC ("Checking overlaps " << lastEndOffset << " - " << it->second );
1614 
1615  if (lastEndOffset < it->second)
1616  {
1617  ret = false;
1618  break;
1619  }
1620  // fragments might overlap in strange ways
1621  uint16_t fragmentEnd = it->first->GetSize () + it->second;
1622  lastEndOffset = std::max ( lastEndOffset, fragmentEnd );
1623  }
1624  }
1625 
1626  return ret;
1627 }
1628 
1631 {
1632  NS_LOG_FUNCTION (this);
1633 
1634  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1635 
1636  Ptr<Packet> p = it->first->Copy ();
1637  uint16_t lastEndOffset = p->GetSize ();
1638  it++;
1639 
1640  for ( ; it != m_fragments.end (); it++)
1641  {
1642  if ( lastEndOffset > it->second )
1643  {
1644  // The fragments are overlapping.
1645  // We do not overwrite the "old" with the "new" because we do not know when each arrived.
1646  // This is different from what Linux does.
1647  // It is not possible to emulate a fragmentation attack.
1648  uint32_t newStart = lastEndOffset - it->second;
1649  if ( it->first->GetSize () > newStart )
1650  {
1651  uint32_t newSize = it->first->GetSize () - newStart;
1652  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1653  p->AddAtEnd (tempFragment);
1654  }
1655  }
1656  else
1657  {
1658  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1659  p->AddAtEnd (it->first);
1660  }
1661  lastEndOffset = p->GetSize ();
1662  }
1663 
1664  return p;
1665 }
1666 
1669 {
1670  NS_LOG_FUNCTION (this);
1671 
1672  std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin ();
1673 
1674  Ptr<Packet> p = Create<Packet> ();
1675  uint16_t lastEndOffset = 0;
1676 
1677  if ( m_fragments.begin ()->second > 0 )
1678  {
1679  return p;
1680  }
1681 
1682  for ( it = m_fragments.begin (); it != m_fragments.end (); it++)
1683  {
1684  if ( lastEndOffset > it->second )
1685  {
1686  uint32_t newStart = lastEndOffset - it->second;
1687  uint32_t newSize = it->first->GetSize () - newStart;
1688  Ptr<Packet> tempFragment = it->first->CreateFragment (newStart, newSize);
1689  p->AddAtEnd (tempFragment);
1690  }
1691  else if ( lastEndOffset == it->second )
1692  {
1693  NS_LOG_LOGIC ("Adding: " << *(it->first) );
1694  p->AddAtEnd (it->first);
1695  }
1696  lastEndOffset = p->GetSize ();
1697  }
1698 
1699  return p;
1700 }
1701 
1702 void
1704 {
1705  m_timeoutIter = iter;
1706  return;
1707 }
1708 
1711 {
1712  return m_timeoutIter;
1713 }
1714 
1715 
1716 void
1718 {
1719  NS_LOG_FUNCTION (this << &key << &ipHeader << iif);
1720 
1721  MapFragments_t::iterator it = m_fragments.find (key);
1722  Ptr<Packet> packet = it->second->GetPartialPacket ();
1723 
1724  // if we have at least 8 bytes, we can send an ICMP.
1725  if ( packet->GetSize () > 8 )
1726  {
1727  Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
1728  icmp->SendTimeExceededTtl (ipHeader, packet, true);
1729  }
1730  m_dropTrace (ipHeader, packet, DROP_FRAGMENT_TIMEOUT, m_node->GetObject<Ipv4> (), iif);
1731 
1732  // clear the buffers
1733  it->second = 0;
1734 
1735  m_fragments.erase (key);
1736 }
1737 
1738 bool
1740 {
1741  NS_LOG_FUNCTION (this << p << header);
1742 
1743  // \todo RFC 6621 mandates SHA-1 hash. For now ns3 hash should be fine.
1744  uint8_t proto = header.GetProtocol ();
1745  Ipv4Address src = header.GetSource ();
1746  Ipv4Address dst = header.GetDestination ();
1747  uint64_t id = header.GetIdentification ();
1748 
1749  // concat hash value onto id
1750  uint64_t hash = id << 32;
1751  if (header.GetFragmentOffset () || !header.IsLastFragment ())
1752  {
1753  // use I-DPD (RFC 6621, Sec 6.2.1)
1754  hash |= header.GetFragmentOffset ();
1755  }
1756  else
1757  {
1758  // use H-DPD (RFC 6621, Sec 6.2.2)
1759 
1760  // serialize packet
1761  Ptr<Packet> pkt = p->Copy ();
1762  pkt->AddHeader (header);
1763 
1764  std::ostringstream oss (std::ios_base::binary);
1765  pkt->CopyData (&oss, pkt->GetSize ());
1766  std::string bytes = oss.str ();
1767 
1768  NS_ASSERT_MSG (bytes.size () >= 20, "Degenerate header serialization");
1769 
1770  // zero out mutable fields
1771  bytes[1] = 0; // DSCP / ECN
1772  bytes[6] = bytes[7] = 0; // Flags / Fragment offset
1773  bytes[8] = 0; // TTL
1774  bytes[10] = bytes[11] = 0; // Header checksum
1775  if (header.GetSerializedSize () > 20) // assume options should be 0'd
1776  {
1777  std::fill_n (bytes.begin () + 20, header.GetSerializedSize () - 20, 0);
1778  }
1779 
1780  // concat hash onto ID
1781  hash |= (uint64_t)Hash32 (bytes);
1782  }
1783 
1784  // set cleanup job for new duplicate entries
1786  {
1788  }
1789 
1790  // assume this is a new entry
1791  DupTuple_t key {hash, proto, src, dst};
1792  NS_LOG_DEBUG ("Packet " << p->GetUid () << " key = (" <<
1793  std::hex << std::get<0> (key) << ", " <<
1794  std::dec << +std::get<1> (key) << ", " <<
1795  std::get<2> (key) << ", " <<
1796  std::get<3> (key) << ")");
1797 
1798  // place a new entry, on collision the existing entry iterator is returned
1799  DupMap_t::iterator iter;
1800  bool inserted, isDup;
1801  std::tie (iter, inserted) = m_dups.emplace (key, Seconds (0));
1802  isDup = !inserted && iter->second > Simulator::Now ();
1803 
1804  // set the expiration event
1805  iter->second = Simulator::Now () + m_expire;
1806  return isDup;
1807 }
1808 
1809 void
1811 {
1812  NS_LOG_FUNCTION (this);
1813 
1814  DupMap_t::size_type n = 0;
1815  Time expire = Simulator::Now ();
1816  auto iter = m_dups.cbegin ();
1817  while (iter != m_dups.cend ())
1818  {
1819  if (iter->second < expire)
1820  {
1821  NS_LOG_LOGIC ("Remove key = (" <<
1822  std::hex << std::get<0> (iter->first) << ", " <<
1823  std::dec << +std::get<1> (iter->first) << ", " <<
1824  std::get<2> (iter->first) << ", " <<
1825  std::get<3> (iter->first) << ")");
1826  iter = m_dups.erase (iter);
1827  ++n;
1828  }
1829  else
1830  {
1831  ++iter;
1832  }
1833  }
1834 
1835  NS_LOG_DEBUG ("Purged " << n << " expired duplicate entries out of " << (n + m_dups.size ()));
1836 
1837  // keep cleaning up if necessary
1838  if (!m_dups.empty () && m_purge.IsStrictlyPositive ())
1839  {
1841  }
1842 }
1843 
1846 {
1848 
1849  if (m_timeoutEventList.empty ())
1850  {
1852  }
1853  m_timeoutEventList.emplace_back (now, key, ipHeader, iif);
1854 
1856 
1857  return (iter);
1858 }
1859 
1860 void
1862 {
1863  Time now = Simulator::Now ();
1864 
1865  while (!m_timeoutEventList.empty () && std::get<0> (*m_timeoutEventList.begin ()) == now)
1866  {
1867  HandleFragmentsTimeout (std::get<1> (*m_timeoutEventList.begin ()),
1868  std::get<2> (*m_timeoutEventList.begin ()),
1869  std::get<3> (*m_timeoutEventList.begin ()));
1870  m_timeoutEventList.pop_front ();
1871  }
1872 
1873  if (m_timeoutEventList.empty ())
1874  {
1875  return;
1876  }
1877 
1878  Time difference = std::get<0> (*m_timeoutEventList.begin ()) - now;
1880 
1881  return;
1882 }
1883 
1884 } // namespace ns3
virtual Ipv4Address SourceAddressSelection(uint32_t interface, Ipv4Address dest)
Choose the source address to use with destination address.
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:280
uint8_t GetTos(void) const
Get the tag&#39;s TOS.
Definition: socket.cc:791
void SetPayloadSize(uint16_t size)
Definition: ipv4-header.cc:56
bool m_weakEsModel
Weak ES model state.
void SetForwarding(bool val)
FragmentsTimeoutsListI_t GetTimeoutIter()
Get the Timeout iterator.
static EventId Schedule(Time const &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:557
uint64_t GetUid(void) const
Returns the packet&#39;s Uid.
Definition: packet.cc:390
void SetDefaultTtl(uint8_t ttl)
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:103
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.
void Send(Ptr< Packet > p, const Ipv4Header &hdr, Ipv4Address dest)
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:298
static Ipv4Address GetAny(void)
void Print(std::ostream &os) const
Print the packet contents.
Definition: packet.cc:434
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
uint32_t GetNAddresses(uint32_t interface) const
bool IsDestinationAddress(Ipv4Address address, uint32_t iif) const
Determine whether address and interface corresponding to received packet can be accepted for local de...
virtual void NotifyNewAggregate()
This function will notify other components connected to the node that a new stack member is now conne...
AttributeValue implementation for Boolean.
Definition: boolean.h:36
Time m_fragmentExpirationTimeout
Expiration timeout.
Definition: second.py:1
uint32_t GetId(void) const
Definition: node.cc:109
bool IsBroadcast(void) const
bool IsInitialized(void) const
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
uint32_t GetSize(void) const
Returns the the size in bytes of the packet (including the zero-filled initial payload).
Definition: packet.h:852
Introspection did not find any typical Config paths.
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:269
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:144
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
static bool ChecksumEnabled(void)
Definition: node.cc:278
ArpCache::Entry * Lookup(Ipv4Address destination)
Do lookup in the ARP cache against an IP address.
Definition: arp-cache.cc:318
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:291
The IPv4 representation of a network interface.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Definition: object-vector.h:81
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
#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
U * PeekPointer(const Ptr< U > &p)
Definition: ptr.h:411
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:205
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1297
void HandleFragmentsTimeout(FragmentKey_t key, Ipv4Header &ipHeader, uint32_t iif)
Process the timeout for packet fragments.
void SetNode(Ptr< Node > node)
Set the node associated with this socket.
DupMap_t m_dups
map of packet duplicate tuples to expiry event
void SetFragmentOffset(uint16_t offsetBytes)
The offset is measured in bytes for the packet start.
Definition: ipv4-header.cc:238
bool IsLastFragment(void) const
Definition: ipv4-header.cc:212
#define NS_FATAL_ERROR(msg)
Report a fatal error with a message and terminate.
Definition: fatal-error.h:165
bool IsStrictlyPositive(void) const
Exactly equivalent to t > 0.
Definition: nstime.h:333
void RemoveDuplicates(void)
Remove expired duplicates packet entry.
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
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.
bool AddAddress(Ipv4InterfaceAddress address)
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:278
uint32_t AddInterface(Ptr< NetDevice > device)
TracedCallback< const Ipv4Header &, Ptr< const Packet >, DropReason, Ptr< Ipv4 >, uint32_t > m_dropTrace
Trace of dropped packets.
bool IsEntire() const
If all fragments have been added.
static uint8_t IpTos2Priority(uint8_t ipTos)
Return the priority corresponding to a given TOS value.
Definition: socket.cc:402
int32_t GetInterfaceForAddress(Ipv4Address addr) const
Return the interface number of the interface that has been assigned the specified IP address...
virtual int GetProtocolNumber(void) const =0
Returns the protocol number of this protocol.
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer...
Definition: socket.h:1116
void SetDontFragment(void)
Don&#39;t fragment this packet: if you need to anyway, drop it.
Definition: ipv4-header.cc:219
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
virtual bool GetIpForward(void) const
Get the IP forwarding state.
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_multicastForwardTrace
Trace of multicast forwarded packets.
bool IsAlive(void)
Definition: arp-cache.cc:375
Ipv4InterfaceAddress GetAddress(uint32_t index) const
Ptr< Ipv4RoutingProtocol > m_routingProtocol
Routing protocol associated with the stack.
uint32_t GetNInterfaces(void) const
void SetUp(uint32_t i)
L4List_t m_protocols
List of transport protocol.
void SetNode(Ptr< Node > node)
Set node associated with interface.
a polymophic address class
Definition: address.h:90
Ptr< const TraceSourceAccessor > MakeTraceSourceAccessor(T a)
Create a TraceSourceAccessor which will control access to the underlying trace source.
Ptr< Packet > GetPartialPacket() const
Get the complete part of the packet.
bool m_enableDpd
Enable multicast duplicate packet detection.
uint8_t GetProtocol(void) const
Definition: ipv4-header.cc:272
void SetSource(Ipv4Address src)
Definition: ipv4-route.cc:49
Ipv4InterfaceList m_interfaces
List of IPv4 interfaces.
TracedCallback< Ptr< const Packet >, Ptr< Ipv4 >, uint32_t > m_rxTrace
Trace of received packets.
Packet header for IPv4.
Definition: ipv4-header.h:33
void AddAtEnd(Ptr< const Packet > packet)
Concatenate the input packet at the end of the current packet.
Definition: packet.cc:335
bool IsMulticast(void) const
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 SetLastFragment(void)
This packet is the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:206
Ptr< Icmpv4L4Protocol > GetIcmp(void) const
Get ICMPv4 protocol.
#define max(a, b)
Definition: 80211b.c:43
bool IsSubnetDirectedBroadcast(Ipv4Mask const &mask) const
Generate subnet-directed broadcast address corresponding to mask.
void SetupLoopback(void)
Setup loopback interface.
Ipv4Address CombineMask(Ipv4Mask const &mask) const
Combine this address with a network mask.
AttributeValue implementation for Time.
Definition: nstime.h:1353
bool IsUnicast(Ipv4Address ad) const
Check if an IPv4 address is unicast according to the node.
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:44
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:49
Ptr< Ipv4Interface > GetInterface(uint32_t i) const
Get an interface.
void SetMetric(uint32_t i, uint16_t metric)
virtual void DoDispose(void)
Destructor implementation.
EventId m_cleanDpd
event to cleanup expired duplicate entries
indicates whether the socket has a priority set.
Definition: socket.h:1308
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.
virtual uint32_t GetSerializedSize(void) const
Definition: ipv4-header.cc:375
bool IsLocalMulticast(void) const
EventId m_timeoutEvent
Event for the next scheduled timeout.
virtual bool GetWeakEsModel(void) const
Get the Weak Es Model status.
Ptr< Socket > CreateRawSocket(void)
Creates a raw socket.
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:75
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:225
std::pair< uint64_t, uint32_t > FragmentKey_t
Key identifying a fragmented packet.
static TypeId GetTypeId(void)
Get the type ID.
Ipv4Address GetBroadcast(void) const
Get the broadcast address.
MapFragments_t m_fragments
Fragmented packets.
Ipv4Mask GetMask(void) const
Get the network mask.
void SendWithHeader(Ptr< Packet > packet, Ipv4Header ipHeader, Ptr< Ipv4Route > route)
uint16_t GetFragmentOffset(void) const
Definition: ipv4-header.cc:246
void IpForward(Ptr< Ipv4Route > rtentry, Ptr< const Packet > p, const Ipv4Header &header)
Forward a packet.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:289
Ptr< Ipv4RoutingProtocol > GetRoutingProtocol(void) const
Get the routing protocol to be used by this Ipv4 stack.
#define list
bool RemoveAddress(uint32_t interfaceIndex, uint32_t addressIndex)
Remove the address at addressIndex on named interface.
FragmentsTimeoutsList_t m_timeoutEventList
Timeout "events" container.
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...
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
bool UpdateDuplicate(Ptr< const Packet > p, const Ipv4Header &header)
Registers duplicate entry, return false if new.
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:76
bool m_ipForward
Forwarding packets (i.e.
Ptr< T > GetObject(void) const
Get a pointer to the requested aggregated Object.
Definition: object.h:470
void SetForwarding(uint32_t i, bool val)
void DoFragmentation(Ptr< Packet > packet, const Ipv4Header &ipv4Header, uint32_t outIfaceMtu, std::list< Ipv4PayloadHeaderPair > &listFragments)
Fragment a packet.
Time m_expire
duplicate entry expiration delay
Implement the IPv4 layer.
Ptr< NetDevice > GetOutputDevice(void) const
Definition: ipv4-route.cc:84
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806)
Every class exported by the ns3 library is enclosed in the ns3 namespace.
address
Definition: first.py:44
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:276
Ptr< NetDevice > GetDevice(void) const
void SetMoreFragments(void)
This packet is not the last packet of a fragmented ipv4 packet.
Definition: ipv4-header.cc:200
Ptr< ArpCache > GetArpCache() const
Ptr< Packet > Copy(void) const
performs a COW copy of the packet.
Definition: packet.cc:121
void RemoveAtEnd(uint32_t size)
Remove size bytes from the end of the current packet.
Definition: packet.cc:355
std::pair< int, int32_t > L4ListKey_t
Container of the IPv4 L4 keys: protocol number, interface index.
void SetTos(uint8_t tos)
Definition: ipv4-header.cc:82
Time m_purge
time between purging expired duplicate entries
bool IsForwarding(uint32_t i) const
void DecreaseIdentification(Ipv4Address source, Ipv4Address destination, uint8_t protocol)
Decrease the identification value for a dropped or recursed packet.
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.
A record that that holds information about an ArpCache entry.
Definition: arp-cache.h:188
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:1354
Ipv4InterfaceAddress::InterfaceAddressScope_e GetScope(void) const
Get address scope.
FragmentsTimeoutsListI_t SetTimeout(FragmentKey_t key, Ipv4Header ipHeader, uint32_t iif)
Set a new timeout "event" for a fragmented packet.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:195
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)
bool IsUp(void) const
These are IP interface states and may be distinct from NetDevice states, such as found in real implem...
Ipv4Address GetGateway(void) const
Definition: ipv4-route.cc:70
void RegisterProtocolHandler(ProtocolHandler handler, uint16_t protocolType, Ptr< NetDevice > device, bool promiscuous=false)
Definition: node.cc:229
Ptr< NetDevice > GetNetDevice(uint32_t i)
uint8_t GetTtl(void) const
Definition: ipv4-header.cc:265
void HandleTimeout(void)
Handles a fragmented packet timeout.
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:304
void UpdateSeen(void)
Update the entry when seeing a packet.
Definition: arp-cache.cc:532
#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
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.
uint16_t GetMetric(uint32_t i) const
uint16_t GetMetric(void) const
virtual void Remove(Ptr< IpL4Protocol > protocol)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:41
bool IsAny(void) const
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)
Associate a NetDevice to this node.
Definition: node.cc:130
int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const
a class to store IPv4 address information on an interface
Ptr< Packet > GetPacket() const
Get the entire packet.
void SetTimeoutIter(FragmentsTimeoutsListI_t iter)
Set the Timeout iterator.
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:956
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)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
uint32_t CopyData(uint8_t *buffer, uint32_t size) const
Copy the packet contents to a byte buffer.
Definition: packet.cc:378
static uint16_t GetStaticProtocolNumber(void)
Get the protocol number.
virtual void Insert(Ptr< IpL4Protocol > protocol)
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:963
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
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.
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1289
Ptr< const AttributeChecker > MakeBooleanChecker(void)
Definition: boolean.cc:121
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:71
void SetTtl(uint8_t ttl)
Definition: ipv4-header.cc:259
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 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.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
bool IsSecondary(void) const
Check if the address is a secondary address.
Ipv4Address GetLocal(void) const
Get the local address.
uint8_t m_defaultTtl
Default TTL.
bool IsChecksumOk(void) const
Definition: ipv4-header.cc:312
uint16_t GetPayloadSize(void) const
Definition: ipv4-header.cc:62
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Interface is down so can not send packet.
void SetMetric(uint16_t metric)
RxStatus
Rx status codes.
std::list< ArpCache::Entry * > LookupInverse(Address destination)
Do lookup in the ARP cache against a MAC address.
Definition: arp-cache.cc:300
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition: log.h:257
std::list< std::tuple< Time, FragmentKey_t, Ipv4Header, uint32_t > >::iterator FragmentsTimeoutsListI_t
Container Iterator for fragment timeouts..
uint32_t Get(void) const
Get the host-order 32-bit IP address.
uint32_t GetNAddresses(void) const
uint16_t GetMtu(uint32_t i) const
virtual void NotifyNewAggregate(void)
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:325
PacketType
Packet types are used as they are in Linux.
Definition: net-device.h:296
TracedCallback< const Ipv4Header &, Ptr< const Packet >, uint32_t > m_unicastForwardTrace
Trace of unicast forwarded packets.
Container for a set of ns3::Object pointers.
This is the implementation of the ICMP protocol as described in RFC 792.
uint16_t GetIdentification(void) const
Definition: ipv4-header.cc:69
Definition: first.py:1
void SetPriority(uint8_t priority)
Set the tag&#39;s priority.
Definition: socket.cc:842
Ipv4InterfaceReverseContainer m_reverseInterfacesContainer
Container of NetDevice / Interface index associations.
indicates whether the socket has IP_TOS set.
Definition: socket.h:1262
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
a unique identifier for an interface.
Definition: type-id.h:58
std::map< std::pair< uint64_t, uint8_t >, uint16_t > m_identification
Identification (for each {src, dst, proto} tuple)
Duplicate packet received.
bool IsUp(uint32_t i) const
void SetDown(uint32_t i)
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
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:1642
virtual Ptr< IpL4Protocol > GetProtocol(int protocolNumber) const
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:256
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition: object.h:576
uint8_t GetTtl(void) const
Get the tag&#39;s TTL.
Definition: socket.cc:611
static const uint16_t PROT_NUMBER
Protocol number (0x0800)
void SetDestination(Ipv4Address dest)
Definition: ipv4-route.cc:35
uint32_t GetNDevices(void) const
Definition: node.cc:152
void SetUp(void)
Enable this interface.
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.