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