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