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