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