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