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
40
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();
323 if (m_timeoutEvent.IsPending())
324 {
325 m_timeoutEvent.Cancel();
326 }
327
328 if (m_cleanDpd.IsPending())
329 {
330 m_cleanDpd.Cancel();
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 {
347 if ((device = DynamicCast<LoopbackNetDevice>(m_node->GetDevice(i))))
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
391 m_node->RegisterProtocolHandler(MakeCallback(&TrafficControlLayer::Receive, tc),
393 device);
394 m_node->RegisterProtocolHandler(MakeCallback(&TrafficControlLayer::Receive, tc),
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;
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 if (m_enableDpd && ipHeader.GetDestination().IsMulticast() && UpdateDuplicate(packet, ipHeader))
635 {
636 NS_LOG_LOGIC("Dropping received packet -- duplicate.");
637 m_dropTrace(ipHeader, packet, DROP_DUPLICATE, this, interface);
638 return;
639 }
640
641 NS_ASSERT_MSG(m_routingProtocol, "Need a routing protocol object to process packets");
642 if (!m_routingProtocol->RouteInput(packet, ipHeader, device, m_ucb, m_mcb, m_lcb, m_ecb))
643 {
644 NS_LOG_WARN("No route found for forwarding packet. Drop.");
645 m_dropTrace(ipHeader, packet, DROP_NO_ROUTE, this, interface);
646 }
647}
648
651{
653 if (prot)
654 {
655 return prot->GetObject<Icmpv4L4Protocol>();
656 }
657 else
658 {
659 return nullptr;
660 }
661}
662
663bool
665{
666 if (ad.IsBroadcast() || ad.IsMulticast())
667 {
668 return false;
669 }
670 else
671 {
672 // check for subnet-broadcast
673 for (uint32_t ifaceIndex = 0; ifaceIndex < GetNInterfaces(); ifaceIndex++)
674 {
675 for (uint32_t j = 0; j < GetNAddresses(ifaceIndex); j++)
676 {
677 Ipv4InterfaceAddress ifAddr = GetAddress(ifaceIndex, j);
678 NS_LOG_LOGIC("Testing address " << ad << " with subnet-directed broadcast "
679 << ifAddr.GetBroadcast());
680 if (ad == ifAddr.GetBroadcast())
681 {
682 return false;
683 }
684 }
685 }
686 }
687
688 return true;
689}
690
691bool
693{
694 return !ad.IsMulticast() && !ad.IsSubnetDirectedBroadcast(interfaceMask);
695}
696
697void
699{
700 NS_LOG_FUNCTION(this << packet << ipHeader << route);
702 {
703 ipHeader.EnableChecksum();
704 }
705 SendRealOut(route, packet, ipHeader);
706}
707
708void
710 Ptr<Packet> packet,
711 Ptr<Ipv4> ipv4,
712 uint32_t interface)
713{
714 if (!m_txTrace.IsEmpty())
715 {
716 Ptr<Packet> packetCopy = packet->Copy();
717 packetCopy->AddHeader(ipHeader);
718 m_txTrace(packetCopy, ipv4, interface);
719 }
720}
721
722void
724 Ipv4Address source,
725 Ipv4Address destination,
726 uint8_t protocol,
727 Ptr<Ipv4Route> route)
728{
729 NS_LOG_FUNCTION(this << packet << source << destination << uint32_t(protocol) << route);
730
731 bool mayFragment = true;
732
733 // we need a copy of the packet with its tags in case we need to invoke recursion.
734 Ptr<Packet> pktCopyWithTags = packet->Copy();
735
736 uint8_t ttl = m_defaultTtl;
737 SocketIpTtlTag ipTtlTag;
738 bool ipTtlTagFound = packet->RemovePacketTag(ipTtlTag);
739 if (ipTtlTagFound)
740 {
741 ttl = ipTtlTag.GetTtl();
742 }
743
744 uint8_t tos = 0;
745 SocketIpTosTag ipTosTag;
746 bool ipTosTagFound = packet->RemovePacketTag(ipTosTag);
747 if (ipTosTagFound)
748 {
749 tos = ipTosTag.GetTos();
750 }
751
752 // can construct the header here
753 Ipv4Header ipHeader =
754 BuildHeader(source, destination, protocol, packet->GetSize(), ttl, tos, mayFragment);
755
756 // Handle a few cases:
757 // 1) packet is passed in with a route entry
758 // 2) packet is passed without a route and packet is destined to limited broadcast address
759 // 3) packet is passed without a route and packet is destined to a subnet-directed broadcast
760 // address 4) packet is passed without a route, packet is not broadcast (e.g., a raw socket
761 // call, or ICMP)
762
763 // 1) packet is passed in with route entry
764 if (route)
765 {
766 NS_LOG_LOGIC("Ipv4L3Protocol::Send case 1b: passed in with route and valid gateway");
767 int32_t interface = GetInterfaceForDevice(route->GetOutputDevice());
768 m_sendOutgoingTrace(ipHeader, packet, interface);
769 if (m_enableDpd && ipHeader.GetDestination().IsMulticast())
770 {
771 UpdateDuplicate(packet, ipHeader);
772 }
773 SendRealOut(route, packet->Copy(), ipHeader);
774 return;
775 }
776
777 // 2) packet is destined to limited broadcast address or link-local multicast address
778 if (destination.IsBroadcast() || destination.IsLocalMulticast())
779 {
780 NS_LOG_LOGIC("Ipv4L3Protocol::Send case 2: limited broadcast - no route");
781 uint32_t ifaceIndex = 0;
782 for (auto ifaceIter = m_interfaces.begin(); ifaceIter != m_interfaces.end();
783 ifaceIter++, ifaceIndex++)
784 {
785 Ptr<Ipv4Interface> outInterface = *ifaceIter;
786 // ANY source matches any interface
787 bool sendIt = source.IsAny();
788 // check if some specific address on outInterface matches
789 for (uint32_t index = 0; !sendIt && index < outInterface->GetNAddresses(); index++)
790 {
791 if (outInterface->GetAddress(index).GetLocal() == source)
792 {
793 sendIt = true;
794 }
795 }
796
797 if (sendIt)
798 {
799 // create a proxy route for this interface
801 route->SetDestination(destination);
802 route->SetGateway(Ipv4Address::GetAny());
803 route->SetSource(source);
804 route->SetOutputDevice(outInterface->GetDevice());
805 DecreaseIdentification(source, destination, protocol);
806 Send(pktCopyWithTags, source, destination, protocol, route);
807 }
808 }
809 return;
810 }
811
812 // 3) check: packet is destined to a subnet-directed broadcast address
813 for (auto ifaceIter = m_interfaces.begin(); ifaceIter != m_interfaces.end(); ifaceIter++)
814 {
815 Ptr<Ipv4Interface> outInterface = *ifaceIter;
816 uint32_t ifaceIndex = GetInterfaceForDevice(outInterface->GetDevice());
817 for (uint32_t j = 0; j < GetNAddresses(ifaceIndex); j++)
818 {
819 Ipv4InterfaceAddress ifAddr = GetAddress(ifaceIndex, j);
820 NS_LOG_LOGIC("Testing address " << ifAddr.GetLocal() << " with mask "
821 << ifAddr.GetMask());
822 if (destination.IsSubnetDirectedBroadcast(ifAddr.GetMask()) &&
823 destination.CombineMask(ifAddr.GetMask()) ==
824 ifAddr.GetLocal().CombineMask(ifAddr.GetMask()))
825 {
826 NS_LOG_LOGIC("Ipv4L3Protocol::Send case 3: subnet directed bcast to "
827 << ifAddr.GetLocal() << " - no route");
828 // create a proxy route for this interface
830 route->SetDestination(destination);
831 route->SetGateway(Ipv4Address::GetAny());
832 route->SetSource(source);
833 route->SetOutputDevice(outInterface->GetDevice());
834 DecreaseIdentification(source, destination, protocol);
835 Send(pktCopyWithTags, source, destination, protocol, route);
836 return;
837 }
838 }
839 }
840
841 // 4) packet is not broadcast, and route is NULL (e.g., a raw socket call)
842 NS_LOG_LOGIC("Ipv4L3Protocol::Send case 4: not broadcast and passed in with no route "
843 << destination);
844 Socket::SocketErrno errno_;
845 Ptr<NetDevice> oif(nullptr); // unused for now
846 Ptr<Ipv4Route> newRoute;
848 {
849 newRoute = m_routingProtocol->RouteOutput(pktCopyWithTags, ipHeader, oif, errno_);
850 }
851 else
852 {
853 NS_LOG_ERROR("Ipv4L3Protocol::Send: m_routingProtocol == 0");
854 }
855 if (newRoute)
856 {
857 DecreaseIdentification(source, destination, protocol);
858 Send(pktCopyWithTags, source, destination, protocol, newRoute);
859 }
860 else
861 {
862 NS_LOG_WARN("No route to host. Drop.");
863 m_dropTrace(ipHeader, packet, DROP_NO_ROUTE, this, 0);
864 DecreaseIdentification(source, destination, protocol);
865 }
866}
867
868void
870 Ipv4Address destination,
871 uint8_t protocol)
872{
873 uint64_t src = source.Get();
874 uint64_t dst = destination.Get();
875 uint64_t srcDst = dst | (src << 32);
876 std::pair<uint64_t, uint8_t> key = std::make_pair(srcDst, protocol);
877 m_identification[key]--;
878}
879
882 Ipv4Address destination,
883 uint8_t protocol,
884 uint16_t payloadSize,
885 uint8_t ttl,
886 uint8_t tos,
887 bool mayFragment)
888{
889 NS_LOG_FUNCTION(this << source << destination << (uint16_t)protocol << payloadSize
890 << (uint16_t)ttl << (uint16_t)tos << mayFragment);
891 Ipv4Header ipHeader;
892 ipHeader.SetSource(source);
893 ipHeader.SetDestination(destination);
894 ipHeader.SetProtocol(protocol);
895 ipHeader.SetPayloadSize(payloadSize);
896 ipHeader.SetTtl(ttl);
897 ipHeader.SetTos(tos);
898
899 uint64_t src = source.Get();
900 uint64_t dst = destination.Get();
901 uint64_t srcDst = dst | (src << 32);
902 std::pair<uint64_t, uint8_t> key = std::make_pair(srcDst, protocol);
903
904 if (mayFragment)
905 {
906 ipHeader.SetMayFragment();
907 ipHeader.SetIdentification(m_identification[key]);
908 m_identification[key]++;
909 }
910 else
911 {
912 ipHeader.SetDontFragment();
913 // RFC 6864 does not state anything about atomic datagrams
914 // identification requirement:
915 // >> Originating sources MAY set the IPv4 ID field of atomic datagrams
916 // to any value.
917 ipHeader.SetIdentification(m_identification[key]);
918 m_identification[key]++;
919 }
921 {
922 ipHeader.EnableChecksum();
923 }
924 return ipHeader;
925}
926
927void
929{
930 NS_LOG_FUNCTION(this << route << packet << &ipHeader);
931 if (!route)
932 {
933 NS_LOG_WARN("No route to host. Drop.");
934 m_dropTrace(ipHeader, packet, DROP_NO_ROUTE, this, 0);
935 return;
936 }
937 Ptr<NetDevice> outDev = route->GetOutputDevice();
938 int32_t interface = GetInterfaceForDevice(outDev);
939 NS_ASSERT(interface >= 0);
940 Ptr<Ipv4Interface> outInterface = GetInterface(interface);
941 NS_LOG_LOGIC("Send via NetDevice ifIndex " << outDev->GetIfIndex() << " ipv4InterfaceIndex "
942 << interface);
943
944 Ipv4Address target;
945 std::string targetLabel;
946 if (route->GetGateway().IsAny())
947 {
948 target = ipHeader.GetDestination();
949 targetLabel = "destination";
950 }
951 else
952 {
953 target = route->GetGateway();
954 targetLabel = "gateway";
955 }
956
957 if (outInterface->IsUp())
958 {
959 NS_LOG_LOGIC("Send to " << targetLabel << " " << target);
960 if (packet->GetSize() + ipHeader.GetSerializedSize() > outInterface->GetDevice()->GetMtu())
961 {
962 std::list<Ipv4PayloadHeaderPair> listFragments;
963 DoFragmentation(packet, ipHeader, outInterface->GetDevice()->GetMtu(), listFragments);
964 for (auto it = listFragments.begin(); it != listFragments.end(); it++)
965 {
966 NS_LOG_LOGIC("Sending fragment " << *(it->first));
967 CallTxTrace(it->second, it->first, this, interface);
968 outInterface->Send(it->first, it->second, target);
969 }
970 }
971 else
972 {
973 CallTxTrace(ipHeader, packet, this, interface);
974 outInterface->Send(packet, ipHeader, target);
975 }
976 }
977}
978
979// This function analogous to Linux ip_mr_forward()
980void
983 const Ipv4Header& header)
984{
985 NS_LOG_FUNCTION(this << mrtentry << p << header);
986 NS_LOG_LOGIC("Multicast forwarding logic for node: " << m_node->GetId());
987
988 std::map<uint32_t, uint32_t> ttlMap = mrtentry->GetOutputTtlMap();
989
990 for (auto mapIter = ttlMap.begin(); mapIter != ttlMap.end(); mapIter++)
991 {
992 uint32_t interface = mapIter->first;
993 // uint32_t outputTtl = mapIter->second; // Unused for now
994
995 Ptr<Packet> packet = p->Copy();
996 Ipv4Header ipHeader = header;
997 if (ipHeader.GetTtl() <= 1)
998 {
999 NS_LOG_WARN("TTL exceeded. Drop.");
1000 m_dropTrace(header, packet, DROP_TTL_EXPIRED, this, interface);
1001 return;
1002 }
1003 ipHeader.SetTtl(header.GetTtl() - 1);
1004 NS_LOG_LOGIC("Forward multicast via interface " << interface);
1006 rtentry->SetSource(ipHeader.GetSource());
1007 rtentry->SetDestination(ipHeader.GetDestination());
1008 rtentry->SetGateway(Ipv4Address::GetAny());
1009 rtentry->SetOutputDevice(GetNetDevice(interface));
1010
1011 m_multicastForwardTrace(ipHeader, packet, interface);
1012 SendRealOut(rtentry, packet, ipHeader);
1013 }
1014}
1015
1016// This function analogous to Linux ip_forward()
1017void
1019{
1020 NS_LOG_FUNCTION(this << rtentry << p << header);
1021 NS_LOG_LOGIC("Forwarding logic for node: " << m_node->GetId());
1022 // Forwarding
1023 Ipv4Header ipHeader = header;
1024 Ptr<Packet> packet = p->Copy();
1025 int32_t interface = GetInterfaceForDevice(rtentry->GetOutputDevice());
1026 if (ipHeader.GetTtl() <= 1)
1027 {
1028 // Do not reply to multicast/broadcast IP address
1029 if (!ipHeader.GetDestination().IsBroadcast() && !ipHeader.GetDestination().IsMulticast())
1030 {
1031 Ptr<Icmpv4L4Protocol> icmp = GetIcmp();
1032 icmp->SendTimeExceededTtl(ipHeader, packet, false);
1033 }
1034 NS_LOG_WARN("TTL exceeded. Drop.");
1035 m_dropTrace(header, packet, DROP_TTL_EXPIRED, this, interface);
1036 return;
1037 }
1038 ipHeader.SetTtl(ipHeader.GetTtl() - 1);
1039 // in case the packet still has a priority tag attached, remove it
1040 SocketPriorityTag priorityTag;
1041 packet->RemovePacketTag(priorityTag);
1042 uint8_t priority = Socket::IpTos2Priority(ipHeader.GetTos());
1043 // add a priority tag if the priority is not null
1044 if (priority)
1045 {
1046 priorityTag.SetPriority(priority);
1047 packet->AddPacketTag(priorityTag);
1048 }
1049
1050 m_unicastForwardTrace(ipHeader, packet, interface);
1051 SendRealOut(rtentry, packet, ipHeader);
1052}
1053
1054void
1056{
1057 NS_LOG_FUNCTION(this << packet << &ip << iif);
1058 Ptr<Packet> p = packet->Copy(); // need to pass a non-const packet up
1059 Ipv4Header ipHeader = ip;
1060
1061 if (!ipHeader.IsLastFragment() || ipHeader.GetFragmentOffset() != 0)
1062 {
1063 NS_LOG_LOGIC("Received a fragment, processing " << *p);
1064 bool isPacketComplete;
1065 isPacketComplete = ProcessFragment(p, ipHeader, iif);
1066 if (!isPacketComplete)
1067 {
1068 return;
1069 }
1070 NS_LOG_LOGIC("Got last fragment, Packet is complete " << *p);
1071 ipHeader.SetFragmentOffset(0);
1072 ipHeader.SetPayloadSize(p->GetSize());
1073 }
1074
1075 m_localDeliverTrace(ipHeader, p, iif);
1076
1077 Ptr<Ipv4Interface> ipv4Interface = GetInterface(iif);
1078
1079 for (auto& socket : m_sockets)
1080 {
1081 NS_LOG_INFO("Delivering to raw socket " << socket);
1082 socket->ForwardUp(p, ipHeader, ipv4Interface);
1083 }
1084
1085 Ptr<IpL4Protocol> protocol = GetProtocol(ipHeader.GetProtocol(), iif);
1086 if (protocol)
1087 {
1088 // we need to make a copy in the unlikely event we hit the
1089 // RX_ENDPOINT_UNREACH codepath
1090 Ptr<Packet> copy = p->Copy();
1091 IpL4Protocol::RxStatus status = protocol->Receive(p, ipHeader, GetInterface(iif));
1092 switch (status)
1093 {
1095 // fall through
1097 // fall through
1099 break;
1101 if (ipHeader.GetDestination().IsBroadcast() || ipHeader.GetDestination().IsMulticast())
1102 {
1103 break; // Do not reply to broadcast or multicast
1104 }
1105 // Another case to suppress ICMP is a subnet-directed broadcast
1106 bool subnetDirected = false;
1107 for (uint32_t i = 0; i < GetNAddresses(iif); i++)
1108 {
1109 Ipv4InterfaceAddress addr = GetAddress(iif, i);
1110 if (addr.GetLocal().CombineMask(addr.GetMask()) ==
1111 ipHeader.GetDestination().CombineMask(addr.GetMask()) &&
1113 {
1114 subnetDirected = true;
1115 }
1116 }
1117 if (!subnetDirected)
1118 {
1119 GetIcmp()->SendDestUnreachPort(ipHeader, copy);
1120 }
1121 }
1122 }
1123}
1124
1125bool
1127{
1128 NS_LOG_FUNCTION(this << i << address);
1129 Ptr<Ipv4Interface> interface = GetInterface(i);
1130 bool retVal = interface->AddAddress(address);
1132 {
1133 m_routingProtocol->NotifyAddAddress(i, address);
1134 }
1135 return retVal;
1136}
1137
1139Ipv4L3Protocol::GetAddress(uint32_t interfaceIndex, uint32_t addressIndex) const
1140{
1141 Ptr<Ipv4Interface> interface = GetInterface(interfaceIndex);
1142 return interface->GetAddress(addressIndex);
1143}
1144
1147{
1148 Ptr<Ipv4Interface> iface = GetInterface(interface);
1149 return iface->GetNAddresses();
1150}
1151
1152bool
1154{
1155 NS_LOG_FUNCTION(this << i << addressIndex);
1156 Ptr<Ipv4Interface> interface = GetInterface(i);
1157 Ipv4InterfaceAddress address = interface->RemoveAddress(addressIndex);
1158 if (address != Ipv4InterfaceAddress())
1159 {
1161 {
1162 m_routingProtocol->NotifyRemoveAddress(i, address);
1163 }
1164 return true;
1165 }
1166 return false;
1167}
1168
1169bool
1171{
1172 NS_LOG_FUNCTION(this << i << address);
1173
1174 if (address == Ipv4Address::GetLoopback())
1175 {
1176 NS_LOG_WARN("Cannot remove loopback address.");
1177 return false;
1178 }
1179 Ptr<Ipv4Interface> interface = GetInterface(i);
1180 Ipv4InterfaceAddress ifAddr = interface->RemoveAddress(address);
1181 if (ifAddr != Ipv4InterfaceAddress())
1182 {
1184 {
1185 m_routingProtocol->NotifyRemoveAddress(i, ifAddr);
1186 }
1187 return true;
1188 }
1189 return false;
1190}
1191
1194{
1195 NS_LOG_FUNCTION(this << interfaceIdx << " " << dest);
1196 if (GetNAddresses(interfaceIdx) == 1) // common case
1197 {
1198 return GetAddress(interfaceIdx, 0).GetLocal();
1199 }
1200 // no way to determine the scope of the destination, so adopt the
1201 // following rule: pick the first available address (index 0) unless
1202 // a subsequent address is on link (in which case, pick the primary
1203 // address if there are multiple)
1204 Ipv4Address candidate = GetAddress(interfaceIdx, 0).GetLocal();
1205 for (uint32_t i = 0; i < GetNAddresses(interfaceIdx); i++)
1206 {
1207 Ipv4InterfaceAddress test = GetAddress(interfaceIdx, i);
1208 if (test.GetLocal().CombineMask(test.GetMask()) == dest.CombineMask(test.GetMask()))
1209 {
1210 if (!test.IsSecondary())
1211 {
1212 return test.GetLocal();
1213 }
1214 }
1215 }
1216 return candidate;
1217}
1218
1221 Ipv4Address dst,
1223{
1224 NS_LOG_FUNCTION(this << device << dst << scope);
1225 Ipv4Address addr("0.0.0.0");
1227 bool found = false;
1228
1229 if (device)
1230 {
1231 int32_t i = GetInterfaceForDevice(device);
1232 NS_ASSERT_MSG(i >= 0, "No device found on node");
1233 for (uint32_t j = 0; j < GetNAddresses(i); j++)
1234 {
1235 iaddr = GetAddress(i, j);
1236 if (iaddr.IsSecondary())
1237 {
1238 continue;
1239 }
1240 if (iaddr.GetScope() > scope)
1241 {
1242 continue;
1243 }
1244 if (dst.CombineMask(iaddr.GetMask()) == iaddr.GetLocal().CombineMask(iaddr.GetMask()))
1245 {
1246 return iaddr.GetLocal();
1247 }
1248 if (!found)
1249 {
1250 addr = iaddr.GetLocal();
1251 found = true;
1252 }
1253 }
1254 }
1255 if (found)
1256 {
1257 return addr;
1258 }
1259
1260 // Iterate among all interfaces
1261 for (uint32_t i = 0; i < GetNInterfaces(); i++)
1262 {
1263 for (uint32_t j = 0; j < GetNAddresses(i); j++)
1264 {
1265 iaddr = GetAddress(i, j);
1266 if (iaddr.IsSecondary())
1267 {
1268 continue;
1269 }
1270 if (iaddr.GetScope() != Ipv4InterfaceAddress::LINK && iaddr.GetScope() <= scope)
1271 {
1272 return iaddr.GetLocal();
1273 }
1274 }
1275 }
1276 NS_LOG_WARN("Could not find source address for " << dst << " and scope " << scope
1277 << ", returning 0");
1278 return addr;
1279}
1280
1281void
1283{
1284 NS_LOG_FUNCTION(this << i << metric);
1285 Ptr<Ipv4Interface> interface = GetInterface(i);
1286 interface->SetMetric(metric);
1287}
1288
1289uint16_t
1291{
1292 Ptr<Ipv4Interface> interface = GetInterface(i);
1293 return interface->GetMetric();
1294}
1295
1296uint16_t
1298{
1299 Ptr<Ipv4Interface> interface = GetInterface(i);
1300 return interface->GetDevice()->GetMtu();
1301}
1302
1303bool
1305{
1306 Ptr<Ipv4Interface> interface = GetInterface(i);
1307 return interface->IsUp();
1308}
1309
1310void
1312{
1313 NS_LOG_FUNCTION(this << i);
1314 Ptr<Ipv4Interface> interface = GetInterface(i);
1315
1316 // RFC 791, pg.25:
1317 // Every internet module must be able to forward a datagram of 68
1318 // octets without further fragmentation. This is because an internet
1319 // header may be up to 60 octets, and the minimum fragment is 8 octets.
1320 if (interface->GetDevice()->GetMtu() >= 68)
1321 {
1322 interface->SetUp();
1323
1325 {
1326 m_routingProtocol->NotifyInterfaceUp(i);
1327 }
1328 }
1329 else
1330 {
1332 "Interface "
1333 << int(i)
1334 << " is set to be down for IPv4. Reason: not respecting minimum IPv4 MTU (68 octets)");
1335 }
1336}
1337
1338void
1340{
1341 NS_LOG_FUNCTION(this << ifaceIndex);
1342 Ptr<Ipv4Interface> interface = GetInterface(ifaceIndex);
1343 interface->SetDown();
1344
1346 {
1347 m_routingProtocol->NotifyInterfaceDown(ifaceIndex);
1348 }
1349}
1350
1351bool
1353{
1354 Ptr<Ipv4Interface> interface = GetInterface(i);
1355 NS_LOG_LOGIC("Forwarding state: " << interface->IsForwarding());
1356 return interface->IsForwarding();
1357}
1358
1359void
1361{
1362 NS_LOG_FUNCTION(this << i);
1363 Ptr<Ipv4Interface> interface = GetInterface(i);
1364 interface->SetForwarding(val);
1365}
1366
1369{
1370 return GetInterface(i)->GetDevice();
1371}
1372
1373void
1375{
1376 NS_LOG_FUNCTION(this << forward);
1377 m_ipForward = forward;
1378 for (auto i = m_interfaces.begin(); i != m_interfaces.end(); i++)
1379 {
1380 (*i)->SetForwarding(forward);
1381 }
1382}
1383
1384bool
1386{
1387 return m_ipForward;
1388}
1389
1390void
1392{
1393 NS_LOG_FUNCTION(this << model);
1394 m_strongEndSystemModel = model;
1395}
1396
1397bool
1402
1403void
1405 const Ipv4Header& ipHeader,
1406 Socket::SocketErrno sockErrno)
1407{
1408 NS_LOG_FUNCTION(this << p << ipHeader << sockErrno);
1409 NS_LOG_LOGIC("Route input failure-- dropping packet to " << ipHeader << " with errno "
1410 << sockErrno);
1411 m_dropTrace(ipHeader, p, DROP_ROUTE_ERROR, this, 0);
1412
1413 // \todo Send an ICMP no route.
1414}
1415
1416void
1418 const Ipv4Header& ipv4Header,
1419 uint32_t outIfaceMtu,
1420 std::list<Ipv4PayloadHeaderPair>& listFragments)
1421{
1422 // BEWARE: here we do assume that the header options are not present.
1423 // a much more complex handling is necessary in case there are options.
1424 // If (when) IPv4 option headers will be implemented, the following code shall be changed.
1425 // Of course also the reassembly code shall be changed as well.
1426
1427 NS_LOG_FUNCTION(this << *packet << outIfaceMtu << &listFragments);
1428
1429 Ptr<Packet> p = packet->Copy();
1430
1431 NS_ASSERT_MSG((ipv4Header.GetSerializedSize() == 5 * 4),
1432 "IPv4 fragmentation implementation only works without option headers.");
1433
1434 uint16_t offset = 0;
1435 bool moreFragment = true;
1436 uint16_t originalOffset = ipv4Header.GetFragmentOffset();
1437 bool isLastFragment = ipv4Header.IsLastFragment();
1438 uint32_t currentFragmentablePartSize = 0;
1439
1440 // IPv4 fragments are all 8 bytes aligned but the last.
1441 // The IP payload size is:
1442 // floor( ( outIfaceMtu - ipv4Header.GetSerializedSize() ) /8 ) *8
1443 uint32_t fragmentSize = (outIfaceMtu - ipv4Header.GetSerializedSize()) & ~uint32_t(0x7);
1444
1445 NS_LOG_LOGIC("Fragmenting - Target Size: " << fragmentSize);
1446
1447 do
1448 {
1449 Ipv4Header fragmentHeader = ipv4Header;
1450
1451 if (p->GetSize() > offset + fragmentSize)
1452 {
1453 moreFragment = true;
1454 currentFragmentablePartSize = fragmentSize;
1455 fragmentHeader.SetMoreFragments();
1456 }
1457 else
1458 {
1459 moreFragment = false;
1460 currentFragmentablePartSize = p->GetSize() - offset;
1461 if (!isLastFragment)
1462 {
1463 fragmentHeader.SetMoreFragments();
1464 }
1465 else
1466 {
1467 fragmentHeader.SetLastFragment();
1468 }
1469 }
1470
1471 NS_LOG_LOGIC("Fragment creation - " << offset << ", " << currentFragmentablePartSize);
1472 Ptr<Packet> fragment = p->CreateFragment(offset, currentFragmentablePartSize);
1473 NS_LOG_LOGIC("Fragment created - " << offset << ", " << fragment->GetSize());
1474
1475 fragmentHeader.SetFragmentOffset(offset + originalOffset);
1476 fragmentHeader.SetPayloadSize(currentFragmentablePartSize);
1477
1479 {
1480 fragmentHeader.EnableChecksum();
1481 }
1482
1483 NS_LOG_LOGIC("Fragment check - " << fragmentHeader.GetFragmentOffset());
1484
1485 NS_LOG_LOGIC("New fragment Header " << fragmentHeader);
1486
1487 std::ostringstream oss;
1488 oss << fragmentHeader;
1489 fragment->Print(oss);
1490
1491 NS_LOG_LOGIC("New fragment " << *fragment);
1492
1493 listFragments.emplace_back(fragment, fragmentHeader);
1494
1495 offset += currentFragmentablePartSize;
1496
1497 } while (moreFragment);
1498}
1499
1500bool
1502{
1503 NS_LOG_FUNCTION(this << packet << ipHeader << iif);
1504
1505 uint64_t addressCombination =
1506 uint64_t(ipHeader.GetSource().Get()) << 32 | uint64_t(ipHeader.GetDestination().Get());
1507 uint32_t idProto =
1508 uint32_t(ipHeader.GetIdentification()) << 16 | uint32_t(ipHeader.GetProtocol());
1509 FragmentKey_t key;
1510 bool ret = false;
1511 Ptr<Packet> p = packet->Copy();
1512
1513 key.first = addressCombination;
1514 key.second = idProto;
1515
1516 Ptr<Fragments> fragments;
1517
1518 auto it = m_fragments.find(key);
1519 if (it == m_fragments.end())
1520 {
1521 fragments = Create<Fragments>();
1522 m_fragments.insert(std::make_pair(key, fragments));
1523
1524 auto iter = SetTimeout(key, ipHeader, iif);
1525 fragments->SetTimeoutIter(iter);
1526 }
1527 else
1528 {
1529 fragments = it->second;
1530 }
1531
1532 NS_LOG_LOGIC("Adding fragment - Size: " << packet->GetSize()
1533 << " - Offset: " << (ipHeader.GetFragmentOffset()));
1534
1535 fragments->AddFragment(p, ipHeader.GetFragmentOffset(), !ipHeader.IsLastFragment());
1536
1537 if (fragments->IsEntire())
1538 {
1539 packet = fragments->GetPacket();
1540 m_timeoutEventList.erase(fragments->GetTimeoutIter());
1541 fragments = nullptr;
1542 m_fragments.erase(key);
1543 ret = true;
1544 }
1545
1546 return ret;
1547}
1548
1554
1555void
1557 uint16_t fragmentOffset,
1558 bool moreFragment)
1559{
1560 NS_LOG_FUNCTION(this << fragment << fragmentOffset << moreFragment);
1561
1562 std::list<std::pair<Ptr<Packet>, uint16_t>>::iterator it;
1563
1564 for (it = m_fragments.begin(); it != m_fragments.end(); it++)
1565 {
1566 if (it->second > fragmentOffset)
1567 {
1568 break;
1569 }
1570 }
1571
1572 if (it == m_fragments.end())
1573 {
1574 m_moreFragment = moreFragment;
1575 }
1576
1577 m_fragments.insert(it, std::pair<Ptr<Packet>, uint16_t>(fragment, fragmentOffset));
1578}
1579
1580bool
1582{
1583 NS_LOG_FUNCTION(this);
1584
1585 bool ret = !m_moreFragment && !m_fragments.empty();
1586
1587 if (ret)
1588 {
1589 uint16_t lastEndOffset = 0;
1590
1591 for (auto it = m_fragments.begin(); it != m_fragments.end(); it++)
1592 {
1593 // overlapping fragments do exist
1594 NS_LOG_LOGIC("Checking overlaps " << lastEndOffset << " - " << it->second);
1595
1596 if (lastEndOffset < it->second)
1597 {
1598 ret = false;
1599 break;
1600 }
1601 // fragments might overlap in strange ways
1602 uint16_t fragmentEnd = it->first->GetSize() + it->second;
1603 lastEndOffset = std::max(lastEndOffset, fragmentEnd);
1604 }
1605 }
1606
1607 return ret;
1608}
1609
1612{
1613 NS_LOG_FUNCTION(this);
1614
1615 auto it = m_fragments.begin();
1616
1617 Ptr<Packet> p = it->first->Copy();
1618 uint16_t lastEndOffset = p->GetSize();
1619 it++;
1620
1621 for (; it != m_fragments.end(); it++)
1622 {
1623 if (lastEndOffset > it->second)
1624 {
1625 // The fragments are overlapping.
1626 // We do not overwrite the "old" with the "new" because we do not know when each
1627 // arrived. This is different from what Linux does. It is not possible to emulate a
1628 // fragmentation attack.
1629 uint32_t newStart = lastEndOffset - it->second;
1630 if (it->first->GetSize() > newStart)
1631 {
1632 uint32_t newSize = it->first->GetSize() - newStart;
1633 Ptr<Packet> tempFragment = it->first->CreateFragment(newStart, newSize);
1634 p->AddAtEnd(tempFragment);
1635 }
1636 }
1637 else
1638 {
1639 NS_LOG_LOGIC("Adding: " << *(it->first));
1640 p->AddAtEnd(it->first);
1641 }
1642 lastEndOffset = p->GetSize();
1643 }
1644
1645 return p;
1646}
1647
1650{
1651 NS_LOG_FUNCTION(this);
1652
1653 auto it = m_fragments.begin();
1654
1656 uint16_t lastEndOffset = 0;
1657
1658 if (m_fragments.begin()->second > 0)
1659 {
1660 return p;
1661 }
1662
1663 for (it = m_fragments.begin(); it != m_fragments.end(); it++)
1664 {
1665 if (lastEndOffset > it->second)
1666 {
1667 uint32_t newStart = lastEndOffset - it->second;
1668 uint32_t newSize = it->first->GetSize() - newStart;
1669 Ptr<Packet> tempFragment = it->first->CreateFragment(newStart, newSize);
1670 p->AddAtEnd(tempFragment);
1671 }
1672 else if (lastEndOffset == it->second)
1673 {
1674 NS_LOG_LOGIC("Adding: " << *(it->first));
1675 p->AddAtEnd(it->first);
1676 }
1677 lastEndOffset = p->GetSize();
1678 }
1679
1680 return p;
1681}
1682
1683void
1688
1694
1695void
1697{
1698 NS_LOG_FUNCTION(this << &key << &ipHeader << iif);
1699
1700 auto it = m_fragments.find(key);
1701 Ptr<Packet> packet = it->second->GetPartialPacket();
1702
1703 // if we have at least 8 bytes, we can send an ICMP.
1704 if (packet->GetSize() > 8)
1705 {
1707 icmp->SendTimeExceededTtl(ipHeader, packet, true);
1708 }
1709 m_dropTrace(ipHeader, packet, DROP_FRAGMENT_TIMEOUT, this, iif);
1710
1711 // clear the buffers
1712 it->second = nullptr;
1713
1714 m_fragments.erase(key);
1715}
1716
1717bool
1719{
1720 NS_LOG_FUNCTION(this << p << header);
1721
1722 // \todo RFC 6621 mandates SHA-1 hash. For now ns3 hash should be fine.
1723 uint8_t proto = header.GetProtocol();
1724 Ipv4Address src = header.GetSource();
1725 Ipv4Address dst = header.GetDestination();
1726 uint64_t id = header.GetIdentification();
1727
1728 // concat hash value onto id
1729 uint64_t hash = id << 32;
1730 if (header.GetFragmentOffset() || !header.IsLastFragment())
1731 {
1732 // use I-DPD (RFC 6621, Sec 6.2.1)
1733 hash |= header.GetFragmentOffset();
1734 }
1735 else
1736 {
1737 // use H-DPD (RFC 6621, Sec 6.2.2)
1738
1739 // serialize packet
1740 Ptr<Packet> pkt = p->Copy();
1741 pkt->AddHeader(header);
1742
1743 std::ostringstream oss(std::ios_base::binary);
1744 pkt->CopyData(&oss, pkt->GetSize());
1745 std::string bytes = oss.str();
1746
1747 NS_ASSERT_MSG(bytes.size() >= 20, "Degenerate header serialization");
1748
1749 // zero out mutable fields
1750 bytes[1] = 0; // DSCP / ECN
1751 bytes[6] = bytes[7] = 0; // Flags / Fragment offset
1752 bytes[8] = 0; // TTL
1753 bytes[10] = bytes[11] = 0; // Header checksum
1754 if (header.GetSerializedSize() > 20) // assume options should be 0'd
1755 {
1756 std::fill_n(bytes.begin() + 20, header.GetSerializedSize() - 20, 0);
1757 }
1758
1759 // concat hash onto ID
1760 hash |= (uint64_t)Hash32(bytes);
1761 }
1762
1763 // set cleanup job for new duplicate entries
1764 if (!m_cleanDpd.IsPending() && m_purge.IsStrictlyPositive())
1765 {
1767 }
1768
1769 // assume this is a new entry
1770 DupTuple_t key{hash, proto, src, dst};
1771 NS_LOG_DEBUG("Packet " << p->GetUid() << " key = (" << std::hex << std::get<0>(key) << ", "
1772 << std::dec << +std::get<1>(key) << ", " << std::get<2>(key) << ", "
1773 << std::get<3>(key) << ")");
1774
1775 // place a new entry, on collision the existing entry iterator is returned
1776 auto [iter, inserted] = m_dups.emplace(key, Seconds(0));
1777 bool isDup = !inserted && iter->second > Simulator::Now();
1778
1779 // set the expiration event
1780 iter->second = Simulator::Now() + m_expire;
1781 return isDup;
1782}
1783
1784void
1786{
1787 NS_LOG_FUNCTION(this);
1788
1789 DupMap_t::size_type n = 0;
1790 Time expire = Simulator::Now();
1791 auto iter = m_dups.cbegin();
1792 while (iter != m_dups.cend())
1793 {
1794 if (iter->second < expire)
1795 {
1796 NS_LOG_LOGIC("Remove key = (" << std::hex << std::get<0>(iter->first) << ", "
1797 << std::dec << +std::get<1>(iter->first) << ", "
1798 << std::get<2>(iter->first) << ", "
1799 << std::get<3>(iter->first) << ")");
1800 iter = m_dups.erase(iter);
1801 ++n;
1802 }
1803 else
1804 {
1805 ++iter;
1806 }
1807 }
1808
1809 NS_LOG_DEBUG("Purged " << n << " expired duplicate entries out of " << (n + m_dups.size()));
1810
1811 // keep cleaning up if necessary
1812 if (!m_dups.empty() && m_purge.IsStrictlyPositive())
1813 {
1815 }
1816}
1817
1820{
1822
1823 if (m_timeoutEventList.empty())
1824 {
1827 }
1828 m_timeoutEventList.emplace_back(now, key, ipHeader, iif);
1829
1830 auto iter = --m_timeoutEventList.end();
1831
1832 return iter;
1833}
1834
1835void
1837{
1838 Time now = Simulator::Now();
1839
1840 while (!m_timeoutEventList.empty() && std::get<0>(*m_timeoutEventList.begin()) == now)
1841 {
1842 HandleFragmentsTimeout(std::get<1>(*m_timeoutEventList.begin()),
1843 std::get<2>(*m_timeoutEventList.begin()),
1844 std::get<3>(*m_timeoutEventList.begin()));
1845 m_timeoutEventList.pop_front();
1846 }
1847
1848 if (m_timeoutEventList.empty())
1849 {
1850 return;
1851 }
1852
1853 Time difference = std::get<0>(*m_timeoutEventList.begin()) - now;
1855}
1856
1857} // namespace ns3
a polymophic address class
Definition address.h:111
A record that that holds information about an ArpCache entry.
Definition arp-cache.h:178
bool IsAlive()
Definition arp-cache.cc:400
void UpdateSeen()
Update the entry when seeing a packet.
Definition arp-cache.cc:583
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Receive a packet.
static const uint16_t PROT_NUMBER
ARP protocol number (0x0806).
AttributeValue implementation for Boolean.
Definition boolean.h:26
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.
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)
Ipv4()
Definition ipv4.cc:57
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.
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.
std::list< std::pair< Ptr< Packet >, uint16_t > > m_fragments
The current fragments.
void AddFragment(Ptr< Packet > fragment, uint16_t fragmentOffset, bool moreFragment)
Add a fragment.
bool m_moreFragment
True if other fragments will be sent.
FragmentsTimeoutsListI_t m_timeoutIter
Timeout iterator to "event" handler.
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_BAD_CHECKSUM
Bad checksum.
@ DROP_NO_ROUTE
No route to host.
@ DROP_INTERFACE_DOWN
Interface is down so can not send packet.
@ DROP_DUPLICATE
Duplicate packet received.
@ DROP_TTL_EXPIRED
Packet TTL has expired.
@ DROP_ROUTE_ERROR
Route error.
@ DROP_FRAGMENT_TIMEOUT
Fragment timeout exceeded.
void DecreaseIdentification(Ipv4Address source, Ipv4Address destination, uint8_t protocol)
Decrease the identification value for a dropped or recursed packet.
Ipv4InterfaceList m_interfaces
List of IPv4 interfaces.
void DeleteRawSocket(Ptr< Socket > socket) override
Deletes a particular raw socket.
MapFragments_t m_fragments
Fragmented packets.
void LocalDeliver(Ptr< const Packet > p, const Ipv4Header &ip, uint32_t iif)
Deliver a packet.
bool IsDestinationAddress(Ipv4Address address, uint32_t iif) const override
Determine whether address and interface corresponding to received packet can be accepted for local de...
std::pair< uint64_t, uint32_t > FragmentKey_t
Key identifying a fragmented packet.
Time m_expire
duplicate entry expiration delay
bool m_strongEndSystemModel
Strong End System Model state.
Ipv4RoutingProtocol::ErrorCallback m_ecb
Error callback.
bool m_ipForward
Forwarding packets (i.e.
void Receive(Ptr< NetDevice > device, Ptr< const Packet > p, uint16_t protocol, const Address &from, const Address &to, NetDevice::PacketType packetType)
Lower layer calls this method after calling L3Demux::Lookup The ARP subclass needs to know from which...
void SetUp(uint32_t i) override
uint32_t GetNInterfaces() const override
Ipv4Header BuildHeader(Ipv4Address source, Ipv4Address destination, uint8_t protocol, uint16_t payloadSize, uint8_t ttl, uint8_t tos, bool mayFragment)
Construct an IPv4 header.
void RouteInputError(Ptr< const Packet > p, const Ipv4Header &ipHeader, Socket::SocketErrno sockErrno)
Fallback when no route is found.
void SetMetric(uint32_t i, uint16_t metric) override
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.
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...
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
static bool ChecksumEnabled()
Definition node.cc:267
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.
Definition ptr.h:67
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:561
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:96
AttributeValue implementation for Time.
Definition nstime.h:1456
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
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:114
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition boolean.h:70
Ptr< const AttributeChecker > MakeObjectVectorChecker()
ObjectPtrContainerValue ObjectVectorValue
ObjectVectorValue is an alias for ObjectPtrContainerValue.
Ptr< const AttributeAccessor > MakeObjectVectorAccessor(U T::*memberVariable)
MakeAccessorHelper implementation for ObjectVector.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1457
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1477
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
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:265
#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
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
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:439
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1369
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1381
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.
U * PeekPointer(const Ptr< U > &p)
Definition ptr.h:448
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< T1 > DynamicCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:585
-ns3 Test suite for the ns3 wrapper script