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