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