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