A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
aodv-routing-protocol.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2009 IITP RAS
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Based on
7 * NS-2 AODV model developed by the CMU/MONARCH group and optimized and
8 * tuned by Samir Das and Mahesh Marina, University of Cincinnati;
9 *
10 * AODV-UU implementation by Erik Nordström of Uppsala University
11 * https://web.archive.org/web/20100527072022/http://core.it.uu.se/core/index.php/AODV-UU
12 *
13 * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
14 * Pavel Boyko <boyko@iitp.ru>
15 */
16#define NS_LOG_APPEND_CONTEXT \
17 if (m_ipv4) \
18 { \
19 std::clog << "[node " << m_ipv4->GetObject<Node>()->GetId() << "] "; \
20 }
21
23
24#include "ns3/adhoc-wifi-mac.h"
25#include "ns3/boolean.h"
26#include "ns3/inet-socket-address.h"
27#include "ns3/log.h"
28#include "ns3/pointer.h"
29#include "ns3/random-variable-stream.h"
30#include "ns3/string.h"
31#include "ns3/trace-source-accessor.h"
32#include "ns3/udp-header.h"
33#include "ns3/udp-l4-protocol.h"
34#include "ns3/udp-socket-factory.h"
35#include "ns3/wifi-mpdu.h"
36#include "ns3/wifi-net-device.h"
37
38#include <algorithm>
39#include <limits>
40
41namespace ns3
42{
43
44NS_LOG_COMPONENT_DEFINE("AodvRoutingProtocol");
45
46namespace aodv
47{
48NS_OBJECT_ENSURE_REGISTERED(RoutingProtocol);
49
50/// UDP Port for AODV control traffic
52
53/**
54 * \ingroup aodv
55 * \brief Tag used by AODV implementation
56 */
58{
59 public:
60 /**
61 * \brief Constructor
62 * \param o the output interface
63 */
65 : Tag(),
66 m_oif(o)
67 {
68 }
69
70 /**
71 * \brief Get the type ID.
72 * \return the object TypeId
73 */
75 {
76 static TypeId tid = TypeId("ns3::aodv::DeferredRouteOutputTag")
77 .SetParent<Tag>()
78 .SetGroupName("Aodv")
79 .AddConstructor<DeferredRouteOutputTag>();
80 return tid;
81 }
82
83 TypeId GetInstanceTypeId() const override
84 {
85 return GetTypeId();
86 }
87
88 /**
89 * \brief Get the output interface
90 * \return the output interface
91 */
93 {
94 return m_oif;
95 }
96
97 /**
98 * \brief Set the output interface
99 * \param oif the output interface
100 */
102 {
103 m_oif = oif;
104 }
105
107 {
108 return sizeof(int32_t);
109 }
110
111 void Serialize(TagBuffer i) const override
112 {
113 i.WriteU32(m_oif);
114 }
115
116 void Deserialize(TagBuffer i) override
117 {
118 m_oif = i.ReadU32();
119 }
120
121 void Print(std::ostream& os) const override
122 {
123 os << "DeferredRouteOutputTag: output interface = " << m_oif;
124 }
125
126 private:
127 /// Positive if output device is fixed in RouteOutput
129};
130
132
133//-----------------------------------------------------------------------------
135 : m_rreqRetries(2),
136 m_ttlStart(1),
137 m_ttlIncrement(2),
138 m_ttlThreshold(7),
139 m_timeoutBuffer(2),
140 m_rreqRateLimit(10),
141 m_rerrRateLimit(10),
142 m_activeRouteTimeout(Seconds(3)),
143 m_netDiameter(35),
144 m_nodeTraversalTime(MilliSeconds(40)),
145 m_netTraversalTime(Time((2 * m_netDiameter) * m_nodeTraversalTime)),
146 m_pathDiscoveryTime(Time(2 * m_netTraversalTime)),
147 m_myRouteTimeout(Time(2 * std::max(m_pathDiscoveryTime, m_activeRouteTimeout))),
148 m_helloInterval(Seconds(1)),
149 m_allowedHelloLoss(2),
150 m_deletePeriod(Time(5 * std::max(m_activeRouteTimeout, m_helloInterval))),
151 m_nextHopWait(m_nodeTraversalTime + MilliSeconds(10)),
152 m_blackListTimeout(Time(m_rreqRetries * m_netTraversalTime)),
153 m_maxQueueLen(64),
154 m_maxQueueTime(Seconds(30)),
155 m_destinationOnly(false),
156 m_gratuitousReply(true),
157 m_enableHello(false),
158 m_routingTable(m_deletePeriod),
159 m_queue(m_maxQueueLen, m_maxQueueTime),
160 m_requestId(0),
161 m_seqNo(0),
162 m_rreqIdCache(m_pathDiscoveryTime),
163 m_dpd(m_pathDiscoveryTime),
164 m_nb(m_helloInterval),
165 m_rreqCount(0),
166 m_rerrCount(0),
167 m_htimer(Timer::CANCEL_ON_DESTROY),
168 m_rreqRateLimitTimer(Timer::CANCEL_ON_DESTROY),
169 m_rerrRateLimitTimer(Timer::CANCEL_ON_DESTROY),
170 m_lastBcastTime(Seconds(0))
171{
173}
174
175TypeId
177{
178 static TypeId tid =
179 TypeId("ns3::aodv::RoutingProtocol")
181 .SetGroupName("Aodv")
182 .AddConstructor<RoutingProtocol>()
183 .AddAttribute("HelloInterval",
184 "HELLO messages emission interval.",
185 TimeValue(Seconds(1)),
188 .AddAttribute("TtlStart",
189 "Initial TTL value for RREQ.",
190 UintegerValue(1),
193 .AddAttribute("TtlIncrement",
194 "TTL increment for each attempt using the expanding ring search for RREQ "
195 "dissemination.",
196 UintegerValue(2),
199 .AddAttribute("TtlThreshold",
200 "Maximum TTL value for expanding ring search, TTL = NetDiameter is used "
201 "beyond this value.",
202 UintegerValue(7),
205 .AddAttribute("TimeoutBuffer",
206 "Provide a buffer for the timeout.",
207 UintegerValue(2),
210 .AddAttribute("RreqRetries",
211 "Maximum number of retransmissions of RREQ to discover a route",
212 UintegerValue(2),
215 .AddAttribute("RreqRateLimit",
216 "Maximum number of RREQ per second.",
217 UintegerValue(10),
220 .AddAttribute("RerrRateLimit",
221 "Maximum number of RERR per second.",
222 UintegerValue(10),
225 .AddAttribute("NodeTraversalTime",
226 "Conservative estimate of the average one hop traversal time for packets "
227 "and should include "
228 "queuing delays, interrupt processing times and transfer times.",
232 .AddAttribute(
233 "NextHopWait",
234 "Period of our waiting for the neighbour's RREP_ACK = 10 ms + NodeTraversalTime",
238 .AddAttribute("ActiveRouteTimeout",
239 "Period of time during which the route is considered to be valid",
240 TimeValue(Seconds(3)),
243 .AddAttribute("MyRouteTimeout",
244 "Value of lifetime field in RREP generating by this node = 2 * "
245 "max(ActiveRouteTimeout, PathDiscoveryTime)",
246 TimeValue(Seconds(11.2)),
249 .AddAttribute("BlackListTimeout",
250 "Time for which the node is put into the blacklist = RreqRetries * "
251 "NetTraversalTime",
252 TimeValue(Seconds(5.6)),
255 .AddAttribute("DeletePeriod",
256 "DeletePeriod is intended to provide an upper bound on the time for "
257 "which an upstream node A "
258 "can have a neighbor B as an active next hop for destination D, while B "
259 "has invalidated the route to D."
260 " = 5 * max (HelloInterval, ActiveRouteTimeout)",
261 TimeValue(Seconds(15)),
264 .AddAttribute("NetDiameter",
265 "Net diameter measures the maximum possible number of hops between two "
266 "nodes in the network",
267 UintegerValue(35),
270 .AddAttribute(
271 "NetTraversalTime",
272 "Estimate of the average net traversal time = 2 * NodeTraversalTime * NetDiameter",
273 TimeValue(Seconds(2.8)),
276 .AddAttribute(
277 "PathDiscoveryTime",
278 "Estimate of maximum time needed to find route in network = 2 * NetTraversalTime",
279 TimeValue(Seconds(5.6)),
282 .AddAttribute("MaxQueueLen",
283 "Maximum number of packets that we allow a routing protocol to buffer.",
284 UintegerValue(64),
288 .AddAttribute("MaxQueueTime",
289 "Maximum time packets can be queued (in seconds)",
290 TimeValue(Seconds(30)),
294 .AddAttribute("AllowedHelloLoss",
295 "Number of hello messages which may be loss for valid link.",
296 UintegerValue(2),
299 .AddAttribute("GratuitousReply",
300 "Indicates whether a gratuitous RREP should be unicast to the node "
301 "originated route discovery.",
302 BooleanValue(true),
306 .AddAttribute("DestinationOnly",
307 "Indicates only the destination may respond to this RREQ.",
308 BooleanValue(false),
312 .AddAttribute("EnableHello",
313 "Indicates whether a hello messages enable.",
314 BooleanValue(true),
318 .AddAttribute("EnableBroadcast",
319 "Indicates whether a broadcast data packets forwarding enable.",
320 BooleanValue(true),
324 .AddAttribute("UniformRv",
325 "Access to the underlying UniformRandomVariable",
326 StringValue("ns3::UniformRandomVariable"),
329 return tid;
330}
331
332void
338
339void
345
349
350void
352{
353 m_ipv4 = nullptr;
354 for (auto iter = m_socketAddresses.begin(); iter != m_socketAddresses.end(); iter++)
355 {
356 iter->first->Close();
357 }
358 m_socketAddresses.clear();
359 for (auto iter = m_socketSubnetBroadcastAddresses.begin();
361 iter++)
362 {
363 iter->first->Close();
364 }
367}
368
369void
371{
372 *stream->GetStream() << "Node: " << m_ipv4->GetObject<Node>()->GetId()
373 << "; Time: " << Now().As(unit)
374 << ", Local time: " << m_ipv4->GetObject<Node>()->GetLocalTime().As(unit)
375 << ", AODV Routing table" << std::endl;
376
377 m_routingTable.Print(stream, unit);
378 *stream->GetStream() << std::endl;
379}
380
381int64_t
383{
384 NS_LOG_FUNCTION(this << stream);
385 m_uniformRandomVariable->SetStream(stream);
386 return 1;
387}
388
389void
403
406 const Ipv4Header& header,
407 Ptr<NetDevice> oif,
408 Socket::SocketErrno& sockerr)
409{
410 NS_LOG_FUNCTION(this << header << (oif ? oif->GetIfIndex() : 0));
411 if (!p)
412 {
413 NS_LOG_DEBUG("Packet is == 0");
414 return LoopbackRoute(header, oif); // later
415 }
416 if (m_socketAddresses.empty())
417 {
419 NS_LOG_LOGIC("No aodv interfaces");
420 Ptr<Ipv4Route> route;
421 return route;
422 }
423 sockerr = Socket::ERROR_NOTERROR;
424 Ptr<Ipv4Route> route;
425 Ipv4Address dst = header.GetDestination();
427 if (m_routingTable.LookupValidRoute(dst, rt))
428 {
429 route = rt.GetRoute();
430 NS_ASSERT(route);
431 NS_LOG_DEBUG("Exist route to " << route->GetDestination() << " from interface "
432 << route->GetSource());
433 if (oif && route->GetOutputDevice() != oif)
434 {
435 NS_LOG_DEBUG("Output device doesn't match. Dropped.");
437 return Ptr<Ipv4Route>();
438 }
440 UpdateRouteLifeTime(route->GetGateway(), m_activeRouteTimeout);
441 return route;
442 }
443
444 // Valid route not found, in this case we return loopback.
445 // Actual route request will be deferred until packet will be fully formed,
446 // routed to loopback, received from loopback and passed to RouteInput (see below)
447 uint32_t iif = (oif ? m_ipv4->GetInterfaceForDevice(oif) : -1);
448 DeferredRouteOutputTag tag(iif);
449 NS_LOG_DEBUG("Valid Route not found");
450 if (!p->PeekPacketTag(tag))
451 {
452 p->AddPacketTag(tag);
453 }
454 return LoopbackRoute(header, oif);
455}
456
457void
459 const Ipv4Header& header,
461 ErrorCallback ecb)
462{
463 NS_LOG_FUNCTION(this << p << header);
464 NS_ASSERT(p && p != Ptr<Packet>());
465
466 QueueEntry newEntry(p, header, ucb, ecb);
467 bool result = m_queue.Enqueue(newEntry);
468 if (result)
469 {
470 NS_LOG_LOGIC("Add packet " << p->GetUid() << " to queue. Protocol "
471 << (uint16_t)header.GetProtocol());
473 bool result = m_routingTable.LookupRoute(header.GetDestination(), rt);
474 if (!result || ((rt.GetFlag() != IN_SEARCH) && result))
475 {
476 NS_LOG_LOGIC("Send new RREQ for outbound packet to " << header.GetDestination());
477 SendRequest(header.GetDestination());
478 }
479 }
480}
481
482bool
484 const Ipv4Header& header,
486 const UnicastForwardCallback& ucb,
487 const MulticastForwardCallback& mcb,
488 const LocalDeliverCallback& lcb,
489 const ErrorCallback& ecb)
490{
491 NS_LOG_FUNCTION(this << p->GetUid() << header.GetDestination() << idev->GetAddress());
492 if (m_socketAddresses.empty())
493 {
494 NS_LOG_LOGIC("No aodv interfaces");
495 return false;
496 }
498 NS_ASSERT(p);
499 // Check if input device supports IP
502
503 Ipv4Address dst = header.GetDestination();
504 Ipv4Address origin = header.GetSource();
505
506 // Deferred route request
507 if (idev == m_lo)
508 {
510 if (p->PeekPacketTag(tag))
511 {
512 DeferredRouteOutput(p, header, ucb, ecb);
513 return true;
514 }
515 }
516
517 // Duplicate of own packet
518 if (IsMyOwnAddress(origin))
519 {
520 return true;
521 }
522
523 // AODV is not a multicast routing protocol
524 if (dst.IsMulticast())
525 {
526 return false;
527 }
528
529 // Broadcast local delivery/forwarding
530 for (auto j = m_socketAddresses.begin(); j != m_socketAddresses.end(); ++j)
531 {
532 Ipv4InterfaceAddress iface = j->second;
533 if (m_ipv4->GetInterfaceForAddress(iface.GetLocal()) == iif)
534 {
535 if (dst == iface.GetBroadcast() || dst.IsBroadcast())
536 {
537 if (m_dpd.IsDuplicate(p, header))
538 {
539 NS_LOG_DEBUG("Duplicated packet " << p->GetUid() << " from " << origin
540 << ". Drop.");
541 return true;
542 }
544 Ptr<Packet> packet = p->Copy();
545 if (!lcb.IsNull())
546 {
547 NS_LOG_LOGIC("Broadcast local delivery to " << iface.GetLocal());
548 lcb(p, header, iif);
549 // Fall through to additional processing
550 }
551 else
552 {
553 NS_LOG_ERROR("Unable to deliver packet locally due to null callback "
554 << p->GetUid() << " from " << origin);
555 ecb(p, header, Socket::ERROR_NOROUTETOHOST);
556 }
558 {
559 return true;
560 }
562 {
563 UdpHeader udpHeader;
564 p->PeekHeader(udpHeader);
565 if (udpHeader.GetDestinationPort() == AODV_PORT)
566 {
567 // AODV packets sent in broadcast are already managed
568 return true;
569 }
570 }
571 if (header.GetTtl() > 1)
572 {
573 NS_LOG_LOGIC("Forward broadcast. TTL " << (uint16_t)header.GetTtl());
574 RoutingTableEntry toBroadcast;
575 if (m_routingTable.LookupRoute(dst, toBroadcast))
576 {
577 Ptr<Ipv4Route> route = toBroadcast.GetRoute();
578 ucb(route, packet, header);
579 }
580 else
581 {
582 NS_LOG_DEBUG("No route to forward broadcast. Drop packet " << p->GetUid());
583 }
584 }
585 else
586 {
587 NS_LOG_DEBUG("TTL exceeded. Drop packet " << p->GetUid());
588 }
589 return true;
590 }
591 }
592 }
593
594 // Unicast local delivery
595 if (m_ipv4->IsDestinationAddress(dst, iif))
596 {
598 RoutingTableEntry toOrigin;
599 if (m_routingTable.LookupValidRoute(origin, toOrigin))
600 {
603 }
604 if (!lcb.IsNull())
605 {
606 NS_LOG_LOGIC("Unicast local delivery to " << dst);
607 lcb(p, header, iif);
608 }
609 else
610 {
611 NS_LOG_ERROR("Unable to deliver packet locally due to null callback "
612 << p->GetUid() << " from " << origin);
613 ecb(p, header, Socket::ERROR_NOROUTETOHOST);
614 }
615 return true;
616 }
617
618 // Check if input device supports IP forwarding
619 if (!m_ipv4->IsForwarding(iif))
620 {
621 NS_LOG_LOGIC("Forwarding disabled for this interface");
622 ecb(p, header, Socket::ERROR_NOROUTETOHOST);
623 return true;
624 }
625
626 // Forwarding
627 return Forwarding(p, header, ucb, ecb);
628}
629
630bool
632 const Ipv4Header& header,
634 ErrorCallback ecb)
635{
636 NS_LOG_FUNCTION(this);
637 Ipv4Address dst = header.GetDestination();
638 Ipv4Address origin = header.GetSource();
640 RoutingTableEntry toDst;
641 if (m_routingTable.LookupRoute(dst, toDst))
642 {
643 if (toDst.GetFlag() == VALID)
644 {
645 Ptr<Ipv4Route> route = toDst.GetRoute();
646 NS_LOG_LOGIC(route->GetSource() << " forwarding to " << dst << " from " << origin
647 << " packet " << p->GetUid());
648
649 /*
650 * Each time a route is used to forward a data packet, its Active Route
651 * Lifetime field of the source, destination and the next hop on the
652 * path to the destination is updated to be no less than the current
653 * time plus ActiveRouteTimeout.
654 */
657 UpdateRouteLifeTime(route->GetGateway(), m_activeRouteTimeout);
658 /*
659 * Since the route between each originator and destination pair is expected to be
660 * symmetric, the Active Route Lifetime for the previous hop, along the reverse path
661 * back to the IP source, is also updated to be no less than the current time plus
662 * ActiveRouteTimeout
663 */
664 RoutingTableEntry toOrigin;
665 m_routingTable.LookupRoute(origin, toOrigin);
667
668 m_nb.Update(route->GetGateway(), m_activeRouteTimeout);
670
671 ucb(route, p, header);
672 return true;
673 }
674 else
675 {
676 if (toDst.GetValidSeqNo())
677 {
678 SendRerrWhenNoRouteToForward(dst, toDst.GetSeqNo(), origin);
679 NS_LOG_DEBUG("Drop packet " << p->GetUid() << " because no route to forward it.");
680 return false;
681 }
682 }
683 }
684 NS_LOG_LOGIC("route not found to " << dst << ". Send RERR message.");
685 NS_LOG_DEBUG("Drop packet " << p->GetUid() << " because no route to forward it.");
686 SendRerrWhenNoRouteToForward(dst, 0, origin);
687 return false;
688}
689
690void
692{
693 NS_ASSERT(ipv4);
695
696 m_ipv4 = ipv4;
697
698 // Create lo route. It is asserted that the only one interface up for now is loopback
700 m_ipv4->GetAddress(0, 0).GetLocal() == Ipv4Address("127.0.0.1"));
703 // Remember lo route
705 /*dev=*/m_lo,
706 /*dst=*/Ipv4Address::GetLoopback(),
707 /*vSeqNo=*/true,
708 /*seqNo=*/0,
709 /*iface=*/Ipv4InterfaceAddress(Ipv4Address::GetLoopback(), Ipv4Mask("255.0.0.0")),
710 /*hops=*/1,
711 /*nextHop=*/Ipv4Address::GetLoopback(),
714
716}
717
718void
720{
721 NS_LOG_FUNCTION(this << m_ipv4->GetAddress(i, 0).GetLocal());
723 if (l3->GetNAddresses(i) > 1)
724 {
725 NS_LOG_WARN("AODV does not work with more then one address per each interface.");
726 }
727 Ipv4InterfaceAddress iface = l3->GetAddress(i, 0);
728 if (iface.GetLocal() == Ipv4Address("127.0.0.1"))
729 {
730 return;
731 }
732
733 // Create a socket to listen only on this interface
735 NS_ASSERT(socket);
736 socket->SetRecvCallback(MakeCallback(&RoutingProtocol::RecvAodv, this));
737 socket->BindToNetDevice(l3->GetNetDevice(i));
738 socket->Bind(InetSocketAddress(iface.GetLocal(), AODV_PORT));
739 socket->SetAllowBroadcast(true);
740 socket->SetIpRecvTtl(true);
741 m_socketAddresses.insert(std::make_pair(socket, iface));
742
743 // create also a subnet broadcast socket
745 NS_ASSERT(socket);
746 socket->SetRecvCallback(MakeCallback(&RoutingProtocol::RecvAodv, this));
747 socket->BindToNetDevice(l3->GetNetDevice(i));
748 socket->Bind(InetSocketAddress(iface.GetBroadcast(), AODV_PORT));
749 socket->SetAllowBroadcast(true);
750 socket->SetIpRecvTtl(true);
751 m_socketSubnetBroadcastAddresses.insert(std::make_pair(socket, iface));
752
753 // Add local broadcast record to the routing table
755 RoutingTableEntry rt(/*dev=*/dev,
756 /*dst=*/iface.GetBroadcast(),
757 /*vSeqNo=*/true,
758 /*seqNo=*/0,
759 /*iface=*/iface,
760 /*hops=*/1,
761 /*nextHop=*/iface.GetBroadcast(),
764
765 if (l3->GetInterface(i)->GetArpCache())
766 {
767 m_nb.AddArpCache(l3->GetInterface(i)->GetArpCache());
768 }
769
770 // Allow neighbor manager use this interface for layer 2 feedback if possible
771 Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice>();
772 if (!wifi)
773 {
774 return;
775 }
776 Ptr<WifiMac> mac = wifi->GetMac();
777 if (!mac)
778 {
779 return;
780 }
781
782 mac->TraceConnectWithoutContext("DroppedMpdu",
784}
785
786void
791
792void
794{
795 NS_LOG_FUNCTION(this << m_ipv4->GetAddress(i, 0).GetLocal());
796
797 // Disable layer 2 link state monitoring (if possible)
799 Ptr<NetDevice> dev = l3->GetNetDevice(i);
800 Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice>();
801 if (wifi)
802 {
803 Ptr<WifiMac> mac = wifi->GetMac()->GetObject<AdhocWifiMac>();
804 if (mac)
805 {
806 mac->TraceDisconnectWithoutContext("DroppedMpdu",
808 m_nb.DelArpCache(l3->GetInterface(i)->GetArpCache());
809 }
810 }
811
812 // Close socket
814 NS_ASSERT(socket);
815 socket->Close();
816 m_socketAddresses.erase(socket);
817
818 // Close socket
820 NS_ASSERT(socket);
821 socket->Close();
823
824 if (m_socketAddresses.empty())
825 {
826 NS_LOG_LOGIC("No aodv interfaces");
828 m_nb.Clear();
830 return;
831 }
833}
834
835void
837{
838 NS_LOG_FUNCTION(this << " interface " << i << " address " << address);
840 if (!l3->IsUp(i))
841 {
842 return;
843 }
844 if (l3->GetNAddresses(i) == 1)
845 {
846 Ipv4InterfaceAddress iface = l3->GetAddress(i, 0);
848 if (!socket)
849 {
850 if (iface.GetLocal() == Ipv4Address("127.0.0.1"))
851 {
852 return;
853 }
854 // Create a socket to listen only on this interface
855 Ptr<Socket> socket =
857 NS_ASSERT(socket);
858 socket->SetRecvCallback(MakeCallback(&RoutingProtocol::RecvAodv, this));
859 socket->BindToNetDevice(l3->GetNetDevice(i));
860 socket->Bind(InetSocketAddress(iface.GetLocal(), AODV_PORT));
861 socket->SetAllowBroadcast(true);
862 m_socketAddresses.insert(std::make_pair(socket, iface));
863
864 // create also a subnet directed broadcast socket
866 NS_ASSERT(socket);
867 socket->SetRecvCallback(MakeCallback(&RoutingProtocol::RecvAodv, this));
868 socket->BindToNetDevice(l3->GetNetDevice(i));
869 socket->Bind(InetSocketAddress(iface.GetBroadcast(), AODV_PORT));
870 socket->SetAllowBroadcast(true);
871 socket->SetIpRecvTtl(true);
872 m_socketSubnetBroadcastAddresses.insert(std::make_pair(socket, iface));
873
874 // Add local broadcast record to the routing table
875 Ptr<NetDevice> dev =
877 RoutingTableEntry rt(/*dev=*/dev,
878 /*dst=*/iface.GetBroadcast(),
879 /*vSeqNo=*/true,
880 /*seqNo=*/0,
881 /*iface=*/iface,
882 /*hops=*/1,
883 /*nextHop=*/iface.GetBroadcast(),
886 }
887 }
888 else
889 {
890 NS_LOG_LOGIC("AODV does not work with more then one address per each interface. Ignore "
891 "added address");
892 }
893}
894
895void
897{
898 NS_LOG_FUNCTION(this);
900 if (socket)
901 {
903 socket->Close();
904 m_socketAddresses.erase(socket);
905
907 if (unicastSocket)
908 {
909 unicastSocket->Close();
910 m_socketAddresses.erase(unicastSocket);
911 }
912
914 if (l3->GetNAddresses(i))
915 {
916 Ipv4InterfaceAddress iface = l3->GetAddress(i, 0);
917 // Create a socket to listen only on this interface
918 Ptr<Socket> socket =
920 NS_ASSERT(socket);
921 socket->SetRecvCallback(MakeCallback(&RoutingProtocol::RecvAodv, this));
922 // Bind to any IP address so that broadcasts can be received
923 socket->BindToNetDevice(l3->GetNetDevice(i));
924 socket->Bind(InetSocketAddress(iface.GetLocal(), AODV_PORT));
925 socket->SetAllowBroadcast(true);
926 socket->SetIpRecvTtl(true);
927 m_socketAddresses.insert(std::make_pair(socket, iface));
928
929 // create also a unicast socket
931 NS_ASSERT(socket);
932 socket->SetRecvCallback(MakeCallback(&RoutingProtocol::RecvAodv, this));
933 socket->BindToNetDevice(l3->GetNetDevice(i));
934 socket->Bind(InetSocketAddress(iface.GetBroadcast(), AODV_PORT));
935 socket->SetAllowBroadcast(true);
936 socket->SetIpRecvTtl(true);
937 m_socketSubnetBroadcastAddresses.insert(std::make_pair(socket, iface));
938
939 // Add local broadcast record to the routing table
940 Ptr<NetDevice> dev =
942 RoutingTableEntry rt(/*dev=*/dev,
943 /*dst=*/iface.GetBroadcast(),
944 /*vSeqNo=*/true,
945 /*seqNo=*/0,
946 /*iface=*/iface,
947 /*hops=*/1,
948 /*nextHop=*/iface.GetBroadcast(),
951 }
952 if (m_socketAddresses.empty())
953 {
954 NS_LOG_LOGIC("No aodv interfaces");
956 m_nb.Clear();
958 return;
959 }
960 }
961 else
962 {
963 NS_LOG_LOGIC("Remove address not participating in AODV operation");
964 }
965}
966
967bool
969{
970 NS_LOG_FUNCTION(this << src);
971 for (auto j = m_socketAddresses.begin(); j != m_socketAddresses.end(); ++j)
972 {
973 Ipv4InterfaceAddress iface = j->second;
974 if (src == iface.GetLocal())
975 {
976 return true;
977 }
978 }
979 return false;
980}
981
984{
985 NS_LOG_FUNCTION(this << hdr);
988 rt->SetDestination(hdr.GetDestination());
989 //
990 // Source address selection here is tricky. The loopback route is
991 // returned when AODV does not have a route; this causes the packet
992 // to be looped back and handled (cached) in RouteInput() method
993 // while a route is found. However, connection-oriented protocols
994 // like TCP need to create an endpoint four-tuple (src, src port,
995 // dst, dst port) and create a pseudo-header for checksumming. So,
996 // AODV needs to guess correctly what the eventual source address
997 // will be.
998 //
999 // For single interface, single address nodes, this is not a problem.
1000 // When there are possibly multiple outgoing interfaces, the policy
1001 // implemented here is to pick the first available AODV interface.
1002 // If RouteOutput() caller specified an outgoing interface, that
1003 // further constrains the selection of source address
1004 //
1005 auto j = m_socketAddresses.begin();
1006 if (oif)
1007 {
1008 // Iterate to find an address on the oif device
1009 for (j = m_socketAddresses.begin(); j != m_socketAddresses.end(); ++j)
1010 {
1011 Ipv4Address addr = j->second.GetLocal();
1012 int32_t interface = m_ipv4->GetInterfaceForAddress(addr);
1013 if (oif == m_ipv4->GetNetDevice(static_cast<uint32_t>(interface)))
1014 {
1015 rt->SetSource(addr);
1016 break;
1017 }
1018 }
1019 }
1020 else
1021 {
1022 rt->SetSource(j->second.GetLocal());
1023 }
1024 NS_ASSERT_MSG(rt->GetSource() != Ipv4Address(), "Valid AODV source address not found");
1025 rt->SetGateway(Ipv4Address("127.0.0.1"));
1026 rt->SetOutputDevice(m_lo);
1027 return rt;
1028}
1029
1030void
1032{
1033 NS_LOG_FUNCTION(this << dst);
1034 // A node SHOULD NOT originate more than RREQ_RATELIMIT RREQ messages per second.
1036 {
1039 this,
1040 dst);
1041 return;
1042 }
1043 else
1044 {
1045 m_rreqCount++;
1046 }
1047 // Create RREQ header
1048 RreqHeader rreqHeader;
1049 rreqHeader.SetDst(dst);
1050
1052 // Using the Hop field in Routing Table to manage the expanding ring search
1053 uint16_t ttl = m_ttlStart;
1054 if (m_routingTable.LookupRoute(dst, rt))
1055 {
1056 if (rt.GetFlag() != IN_SEARCH)
1057 {
1058 ttl = std::min<uint16_t>(rt.GetHop() + m_ttlIncrement, m_netDiameter);
1059 }
1060 else
1061 {
1062 ttl = rt.GetHop() + m_ttlIncrement;
1063 if (ttl > m_ttlThreshold)
1064 {
1065 ttl = m_netDiameter;
1066 }
1067 }
1068 if (ttl == m_netDiameter)
1069 {
1070 rt.IncrementRreqCnt();
1071 }
1072 if (rt.GetValidSeqNo())
1073 {
1074 rreqHeader.SetDstSeqno(rt.GetSeqNo());
1075 }
1076 else
1077 {
1078 rreqHeader.SetUnknownSeqno(true);
1079 }
1080 rt.SetHop(ttl);
1081 rt.SetFlag(IN_SEARCH);
1084 }
1085 else
1086 {
1087 rreqHeader.SetUnknownSeqno(true);
1088 Ptr<NetDevice> dev = nullptr;
1089 RoutingTableEntry newEntry(/*dev=*/dev,
1090 /*dst=*/dst,
1091 /*vSeqNo=*/false,
1092 /*seqNo=*/0,
1093 /*iface=*/Ipv4InterfaceAddress(),
1094 /*hops=*/ttl,
1095 /*nextHop=*/Ipv4Address(),
1096 /*lifetime=*/m_pathDiscoveryTime);
1097 // Check if TtlStart == NetDiameter
1098 if (ttl == m_netDiameter)
1099 {
1100 newEntry.IncrementRreqCnt();
1101 }
1102 newEntry.SetFlag(IN_SEARCH);
1103 m_routingTable.AddRoute(newEntry);
1104 }
1105
1107 {
1108 rreqHeader.SetGratuitousRrep(true);
1109 }
1111 {
1112 rreqHeader.SetDestinationOnly(true);
1113 }
1114
1115 m_seqNo++;
1116 rreqHeader.SetOriginSeqno(m_seqNo);
1117 m_requestId++;
1118 rreqHeader.SetId(m_requestId);
1119
1120 // Send RREQ as subnet directed broadcast from each interface used by aodv
1121 for (auto j = m_socketAddresses.begin(); j != m_socketAddresses.end(); ++j)
1122 {
1123 Ptr<Socket> socket = j->first;
1124 Ipv4InterfaceAddress iface = j->second;
1125
1126 rreqHeader.SetOrigin(iface.GetLocal());
1128
1129 Ptr<Packet> packet = Create<Packet>();
1130 SocketIpTtlTag tag;
1131 tag.SetTtl(ttl);
1132 packet->AddPacketTag(tag);
1133 packet->AddHeader(rreqHeader);
1134 TypeHeader tHeader(AODVTYPE_RREQ);
1135 packet->AddHeader(tHeader);
1136 // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
1137 Ipv4Address destination;
1138 if (iface.GetMask() == Ipv4Mask::GetOnes())
1139 {
1140 destination = Ipv4Address("255.255.255.255");
1141 }
1142 else
1143 {
1144 destination = iface.GetBroadcast();
1145 }
1146 NS_LOG_DEBUG("Send RREQ with id " << rreqHeader.GetId() << " to socket");
1150 this,
1151 socket,
1152 packet,
1153 destination);
1154 }
1155 ScheduleRreqRetry(dst);
1156}
1157
1158void
1160{
1161 socket->SendTo(packet, 0, InetSocketAddress(destination, AODV_PORT));
1162}
1163
1164void
1166{
1167 NS_LOG_FUNCTION(this << dst);
1168 if (m_addressReqTimer.find(dst) == m_addressReqTimer.end())
1169 {
1171 m_addressReqTimer[dst] = timer;
1172 }
1174 m_addressReqTimer[dst].Cancel();
1175 m_addressReqTimer[dst].SetArguments(dst);
1177 m_routingTable.LookupRoute(dst, rt);
1178 Time retry;
1179 if (rt.GetHop() < m_netDiameter)
1180 {
1181 retry = 2 * m_nodeTraversalTime * (rt.GetHop() + m_timeoutBuffer);
1182 }
1183 else
1184 {
1185 NS_ABORT_MSG_UNLESS(rt.GetRreqCnt() > 0, "Unexpected value for GetRreqCount ()");
1186 uint16_t backoffFactor = rt.GetRreqCnt() - 1;
1187 NS_LOG_LOGIC("Applying binary exponential backoff factor " << backoffFactor);
1188 retry = m_netTraversalTime * (1 << backoffFactor);
1189 }
1190 m_addressReqTimer[dst].Schedule(retry);
1191 NS_LOG_LOGIC("Scheduled RREQ retry in " << retry.As(Time::S));
1192}
1193
1194void
1196{
1197 NS_LOG_FUNCTION(this << socket);
1198 Address sourceAddress;
1199 Ptr<Packet> packet = socket->RecvFrom(sourceAddress);
1200 InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom(sourceAddress);
1201 Ipv4Address sender = inetSourceAddr.GetIpv4();
1202 Ipv4Address receiver;
1203
1204 if (m_socketAddresses.find(socket) != m_socketAddresses.end())
1205 {
1206 receiver = m_socketAddresses[socket].GetLocal();
1207 }
1208 else if (m_socketSubnetBroadcastAddresses.find(socket) !=
1210 {
1211 receiver = m_socketSubnetBroadcastAddresses[socket].GetLocal();
1212 }
1213 else
1214 {
1215 NS_ASSERT_MSG(false, "Received a packet from an unknown socket");
1216 }
1217 NS_LOG_DEBUG("AODV node " << this << " received a AODV packet from " << sender << " to "
1218 << receiver);
1219
1220 UpdateRouteToNeighbor(sender, receiver);
1221 TypeHeader tHeader(AODVTYPE_RREQ);
1222 packet->RemoveHeader(tHeader);
1223 if (!tHeader.IsValid())
1224 {
1225 NS_LOG_DEBUG("AODV message " << packet->GetUid() << " with unknown type received: "
1226 << tHeader.Get() << ". Drop");
1227 return; // drop
1228 }
1229 switch (tHeader.Get())
1230 {
1231 case AODVTYPE_RREQ: {
1232 RecvRequest(packet, receiver, sender);
1233 break;
1234 }
1235 case AODVTYPE_RREP: {
1236 RecvReply(packet, receiver, sender);
1237 break;
1238 }
1239 case AODVTYPE_RERR: {
1240 RecvError(packet, sender);
1241 break;
1242 }
1243 case AODVTYPE_RREP_ACK: {
1244 RecvReplyAck(sender);
1245 break;
1246 }
1247 }
1248}
1249
1250bool
1252{
1253 NS_LOG_FUNCTION(this << addr << lifetime);
1255 if (m_routingTable.LookupRoute(addr, rt))
1256 {
1257 if (rt.GetFlag() == VALID)
1258 {
1259 NS_LOG_DEBUG("Updating VALID route");
1260 rt.SetRreqCnt(0);
1261 rt.SetLifeTime(std::max(lifetime, rt.GetLifeTime()));
1263 return true;
1264 }
1265 }
1266 return false;
1267}
1268
1269void
1271{
1272 NS_LOG_FUNCTION(this << "sender " << sender << " receiver " << receiver);
1273 RoutingTableEntry toNeighbor;
1274 if (!m_routingTable.LookupRoute(sender, toNeighbor))
1275 {
1277 RoutingTableEntry newEntry(
1278 /*dev=*/dev,
1279 /*dst=*/sender,
1280 /*vSeqNo=*/false,
1281 /*seqNo=*/0,
1282 /*iface=*/m_ipv4->GetAddress(m_ipv4->GetInterfaceForAddress(receiver), 0),
1283 /*hops=*/1,
1284 /*nextHop=*/sender,
1285 /*lifetime=*/m_activeRouteTimeout);
1286 m_routingTable.AddRoute(newEntry);
1287 }
1288 else
1289 {
1291 if (toNeighbor.GetValidSeqNo() && (toNeighbor.GetHop() == 1) &&
1292 (toNeighbor.GetOutputDevice() == dev))
1293 {
1294 toNeighbor.SetLifeTime(std::max(m_activeRouteTimeout, toNeighbor.GetLifeTime()));
1295 }
1296 else
1297 {
1298 RoutingTableEntry newEntry(
1299 /*dev=*/dev,
1300 /*dst=*/sender,
1301 /*vSeqNo=*/false,
1302 /*seqNo=*/0,
1303 /*iface=*/m_ipv4->GetAddress(m_ipv4->GetInterfaceForAddress(receiver), 0),
1304 /*hops=*/1,
1305 /*nextHop=*/sender,
1306 /*lifetime=*/std::max(m_activeRouteTimeout, toNeighbor.GetLifeTime()));
1307 m_routingTable.Update(newEntry);
1308 }
1309 }
1310}
1311
1312void
1314{
1315 NS_LOG_FUNCTION(this);
1316 RreqHeader rreqHeader;
1317 p->RemoveHeader(rreqHeader);
1318
1319 // A node ignores all RREQs received from any node in its blacklist
1320 RoutingTableEntry toPrev;
1321 if (m_routingTable.LookupRoute(src, toPrev))
1322 {
1323 if (toPrev.IsUnidirectional())
1324 {
1325 NS_LOG_DEBUG("Ignoring RREQ from node in blacklist");
1326 return;
1327 }
1328 }
1329
1330 uint32_t id = rreqHeader.GetId();
1331 Ipv4Address origin = rreqHeader.GetOrigin();
1332
1333 /*
1334 * Node checks to determine whether it has received a RREQ with the same Originator IP Address
1335 * and RREQ ID. If such a RREQ has been received, the node silently discards the newly received
1336 * RREQ.
1337 */
1338 if (m_rreqIdCache.IsDuplicate(origin, id))
1339 {
1340 NS_LOG_DEBUG("Ignoring RREQ due to duplicate");
1341 return;
1342 }
1343
1344 // Increment RREQ hop count
1345 uint8_t hop = rreqHeader.GetHopCount() + 1;
1346 rreqHeader.SetHopCount(hop);
1347
1348 /*
1349 * When the reverse route is created or updated, the following actions on the route are also
1350 * carried out:
1351 * 1. the Originator Sequence Number from the RREQ is compared to the corresponding destination
1352 * sequence number in the route table entry and copied if greater than the existing value there
1353 * 2. the valid sequence number field is set to true;
1354 * 3. the next hop in the routing table becomes the node from which the RREQ was received
1355 * 4. the hop count is copied from the Hop Count in the RREQ message;
1356 * 5. the Lifetime is set to be the maximum of (ExistingLifetime, MinimalLifetime), where
1357 * MinimalLifetime = current time + 2*NetTraversalTime - 2*HopCount*NodeTraversalTime
1358 */
1359 RoutingTableEntry toOrigin;
1360 if (!m_routingTable.LookupRoute(origin, toOrigin))
1361 {
1363 RoutingTableEntry newEntry(
1364 /*dev=*/dev,
1365 /*dst=*/origin,
1366 /*vSeqNo=*/true,
1367 /*seqNo=*/rreqHeader.GetOriginSeqno(),
1368 /*iface=*/m_ipv4->GetAddress(m_ipv4->GetInterfaceForAddress(receiver), 0),
1369 /*hops=*/hop,
1370 /*nextHop=*/src,
1371 /*lifetime=*/Time(2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime));
1372 m_routingTable.AddRoute(newEntry);
1373 }
1374 else
1375 {
1376 if (toOrigin.GetValidSeqNo())
1377 {
1378 if (int32_t(rreqHeader.GetOriginSeqno()) - int32_t(toOrigin.GetSeqNo()) > 0)
1379 {
1380 toOrigin.SetSeqNo(rreqHeader.GetOriginSeqno());
1381 }
1382 }
1383 else
1384 {
1385 toOrigin.SetSeqNo(rreqHeader.GetOriginSeqno());
1386 }
1387 toOrigin.SetValidSeqNo(true);
1388 toOrigin.SetNextHop(src);
1391 toOrigin.SetHop(hop);
1392 toOrigin.SetLifeTime(std::max(Time(2 * m_netTraversalTime - 2 * hop * m_nodeTraversalTime),
1393 toOrigin.GetLifeTime()));
1394 m_routingTable.Update(toOrigin);
1395 // m_nb.Update (src, Time (AllowedHelloLoss * HelloInterval));
1396 }
1397
1398 RoutingTableEntry toNeighbor;
1399 if (!m_routingTable.LookupRoute(src, toNeighbor))
1400 {
1401 NS_LOG_DEBUG("Neighbor:" << src << " not found in routing table. Creating an entry");
1403 RoutingTableEntry newEntry(dev,
1404 src,
1405 false,
1406 rreqHeader.GetOriginSeqno(),
1408 1,
1409 src,
1411 m_routingTable.AddRoute(newEntry);
1412 }
1413 else
1414 {
1416 toNeighbor.SetValidSeqNo(false);
1417 toNeighbor.SetSeqNo(rreqHeader.GetOriginSeqno());
1418 toNeighbor.SetFlag(VALID);
1420 toNeighbor.SetInterface(m_ipv4->GetAddress(m_ipv4->GetInterfaceForAddress(receiver), 0));
1421 toNeighbor.SetHop(1);
1422 toNeighbor.SetNextHop(src);
1423 m_routingTable.Update(toNeighbor);
1424 }
1426
1427 NS_LOG_LOGIC(receiver << " receive RREQ with hop count "
1428 << static_cast<uint32_t>(rreqHeader.GetHopCount()) << " ID "
1429 << rreqHeader.GetId() << " to destination " << rreqHeader.GetDst());
1430
1431 // A node generates a RREP if either:
1432 // (i) it is itself the destination,
1433 if (IsMyOwnAddress(rreqHeader.GetDst()))
1434 {
1435 m_routingTable.LookupRoute(origin, toOrigin);
1436 NS_LOG_DEBUG("Send reply since I am the destination");
1437 SendReply(rreqHeader, toOrigin);
1438 return;
1439 }
1440 /*
1441 * (ii) or it has an active route to the destination, the destination sequence number in the
1442 * node's existing route table entry for the destination is valid and greater than or equal to
1443 * the Destination Sequence Number of the RREQ, and the "destination only" flag is NOT set.
1444 */
1445 RoutingTableEntry toDst;
1446 Ipv4Address dst = rreqHeader.GetDst();
1447 if (m_routingTable.LookupRoute(dst, toDst))
1448 {
1449 /*
1450 * Drop RREQ, This node RREP will make a loop.
1451 */
1452 if (toDst.GetNextHop() == src)
1453 {
1454 NS_LOG_DEBUG("Drop RREQ from " << src << ", dest next hop " << toDst.GetNextHop());
1455 return;
1456 }
1457 /*
1458 * The Destination Sequence number for the requested destination is set to the maximum of
1459 * the corresponding value received in the RREQ message, and the destination sequence value
1460 * currently maintained by the node for the requested destination. However, the forwarding
1461 * node MUST NOT modify its maintained value for the destination sequence number, even if
1462 * the value received in the incoming RREQ is larger than the value currently maintained by
1463 * the forwarding node.
1464 */
1465 if ((rreqHeader.GetUnknownSeqno() ||
1466 (int32_t(toDst.GetSeqNo()) - int32_t(rreqHeader.GetDstSeqno()) >= 0)) &&
1467 toDst.GetValidSeqNo())
1468 {
1469 if (!rreqHeader.GetDestinationOnly() && toDst.GetFlag() == VALID)
1470 {
1471 m_routingTable.LookupRoute(origin, toOrigin);
1472 SendReplyByIntermediateNode(toDst, toOrigin, rreqHeader.GetGratuitousRrep());
1473 return;
1474 }
1475 rreqHeader.SetDstSeqno(toDst.GetSeqNo());
1476 rreqHeader.SetUnknownSeqno(false);
1477 }
1478 }
1479
1480 SocketIpTtlTag tag;
1481 p->RemovePacketTag(tag);
1482 if (tag.GetTtl() < 2)
1483 {
1484 NS_LOG_DEBUG("TTL exceeded. Drop RREQ origin " << src << " destination " << dst);
1485 return;
1486 }
1487
1488 for (auto j = m_socketAddresses.begin(); j != m_socketAddresses.end(); ++j)
1489 {
1490 Ptr<Socket> socket = j->first;
1491 Ipv4InterfaceAddress iface = j->second;
1492 Ptr<Packet> packet = Create<Packet>();
1493 SocketIpTtlTag ttl;
1494 ttl.SetTtl(tag.GetTtl() - 1);
1495 packet->AddPacketTag(ttl);
1496 packet->AddHeader(rreqHeader);
1497 TypeHeader tHeader(AODVTYPE_RREQ);
1498 packet->AddHeader(tHeader);
1499 // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
1500 Ipv4Address destination;
1501 if (iface.GetMask() == Ipv4Mask::GetOnes())
1502 {
1503 destination = Ipv4Address("255.255.255.255");
1504 }
1505 else
1506 {
1507 destination = iface.GetBroadcast();
1508 }
1512 this,
1513 socket,
1514 packet,
1515 destination);
1516 }
1517}
1518
1519void
1521{
1522 NS_LOG_FUNCTION(this << toOrigin.GetDestination());
1523 /*
1524 * Destination node MUST increment its own sequence number by one if the sequence number in the
1525 * RREQ packet is equal to that incremented value. Otherwise, the destination does not change
1526 * its sequence number before generating the RREP message.
1527 */
1528 if (!rreqHeader.GetUnknownSeqno() && (rreqHeader.GetDstSeqno() == m_seqNo + 1))
1529 {
1530 m_seqNo++;
1531 }
1532 RrepHeader rrepHeader(/*prefixSize=*/0,
1533 /*hopCount=*/0,
1534 /*dst=*/rreqHeader.GetDst(),
1535 /*dstSeqNo=*/m_seqNo,
1536 /*origin=*/toOrigin.GetDestination(),
1537 /*lifetime=*/m_myRouteTimeout);
1538 Ptr<Packet> packet = Create<Packet>();
1539 SocketIpTtlTag tag;
1540 tag.SetTtl(toOrigin.GetHop());
1541 packet->AddPacketTag(tag);
1542 packet->AddHeader(rrepHeader);
1543 TypeHeader tHeader(AODVTYPE_RREP);
1544 packet->AddHeader(tHeader);
1546 NS_ASSERT(socket);
1547 socket->SendTo(packet, 0, InetSocketAddress(toOrigin.GetNextHop(), AODV_PORT));
1548}
1549
1550void
1552 RoutingTableEntry& toOrigin,
1553 bool gratRep)
1554{
1555 NS_LOG_FUNCTION(this);
1556 RrepHeader rrepHeader(/*prefixSize=*/0,
1557 /*hopCount=*/toDst.GetHop(),
1558 /*dst=*/toDst.GetDestination(),
1559 /*dstSeqNo=*/toDst.GetSeqNo(),
1560 /*origin=*/toOrigin.GetDestination(),
1561 /*lifetime=*/toDst.GetLifeTime());
1562 /* If the node we received a RREQ for is a neighbor we are
1563 * probably facing a unidirectional link... Better request a RREP-ack
1564 */
1565 if (toDst.GetHop() == 1)
1566 {
1567 rrepHeader.SetAckRequired(true);
1568 RoutingTableEntry toNextHop;
1569 m_routingTable.LookupRoute(toOrigin.GetNextHop(), toNextHop);
1573 }
1574 toDst.InsertPrecursor(toOrigin.GetNextHop());
1575 toOrigin.InsertPrecursor(toDst.GetNextHop());
1576 m_routingTable.Update(toDst);
1577 m_routingTable.Update(toOrigin);
1578
1579 Ptr<Packet> packet = Create<Packet>();
1580 SocketIpTtlTag tag;
1581 tag.SetTtl(toOrigin.GetHop());
1582 packet->AddPacketTag(tag);
1583 packet->AddHeader(rrepHeader);
1584 TypeHeader tHeader(AODVTYPE_RREP);
1585 packet->AddHeader(tHeader);
1587 NS_ASSERT(socket);
1588 socket->SendTo(packet, 0, InetSocketAddress(toOrigin.GetNextHop(), AODV_PORT));
1589
1590 // Generating gratuitous RREPs
1591 if (gratRep)
1592 {
1593 RrepHeader gratRepHeader(/*prefixSize=*/0,
1594 /*hopCount=*/toOrigin.GetHop(),
1595 /*dst=*/toOrigin.GetDestination(),
1596 /*dstSeqNo=*/toOrigin.GetSeqNo(),
1597 /*origin=*/toDst.GetDestination(),
1598 /*lifetime=*/toOrigin.GetLifeTime());
1599 Ptr<Packet> packetToDst = Create<Packet>();
1600 SocketIpTtlTag gratTag;
1601 gratTag.SetTtl(toDst.GetHop());
1602 packetToDst->AddPacketTag(gratTag);
1603 packetToDst->AddHeader(gratRepHeader);
1605 packetToDst->AddHeader(type);
1607 NS_ASSERT(socket);
1608 NS_LOG_LOGIC("Send gratuitous RREP " << packet->GetUid());
1609 socket->SendTo(packetToDst, 0, InetSocketAddress(toDst.GetNextHop(), AODV_PORT));
1610 }
1611}
1612
1613void
1615{
1616 NS_LOG_FUNCTION(this << " to " << neighbor);
1617 RrepAckHeader h;
1618 TypeHeader typeHeader(AODVTYPE_RREP_ACK);
1619 Ptr<Packet> packet = Create<Packet>();
1620 SocketIpTtlTag tag;
1621 tag.SetTtl(1);
1622 packet->AddPacketTag(tag);
1623 packet->AddHeader(h);
1624 packet->AddHeader(typeHeader);
1625 RoutingTableEntry toNeighbor;
1626 m_routingTable.LookupRoute(neighbor, toNeighbor);
1628 NS_ASSERT(socket);
1629 socket->SendTo(packet, 0, InetSocketAddress(neighbor, AODV_PORT));
1630}
1631
1632void
1634{
1635 NS_LOG_FUNCTION(this << " src " << sender);
1636 RrepHeader rrepHeader;
1637 p->RemoveHeader(rrepHeader);
1638 Ipv4Address dst = rrepHeader.GetDst();
1639 NS_LOG_LOGIC("RREP destination " << dst << " RREP origin " << rrepHeader.GetOrigin());
1640
1641 uint8_t hop = rrepHeader.GetHopCount() + 1;
1642 rrepHeader.SetHopCount(hop);
1643
1644 // If RREP is Hello message
1645 if (dst == rrepHeader.GetOrigin())
1646 {
1647 ProcessHello(rrepHeader, receiver);
1648 return;
1649 }
1650
1651 /*
1652 * If the route table entry to the destination is created or updated, then the following actions
1653 * occur:
1654 * - the route is marked as active,
1655 * - the destination sequence number is marked as valid,
1656 * - the next hop in the route entry is assigned to be the node from which the RREP is
1657 * received, which is indicated by the source IP address field in the IP header,
1658 * - the hop count is set to the value of the hop count from RREP message + 1
1659 * - the expiry time is set to the current time plus the value of the Lifetime in the RREP
1660 * message,
1661 * - and the destination sequence number is the Destination Sequence Number in the RREP
1662 * message.
1663 */
1665 RoutingTableEntry newEntry(
1666 /*dev=*/dev,
1667 /*dst=*/dst,
1668 /*vSeqNo=*/true,
1669 /*seqNo=*/rrepHeader.GetDstSeqno(),
1670 /*iface=*/m_ipv4->GetAddress(m_ipv4->GetInterfaceForAddress(receiver), 0),
1671 /*hops=*/hop,
1672 /*nextHop=*/sender,
1673 /*lifetime=*/rrepHeader.GetLifeTime());
1674 RoutingTableEntry toDst;
1675 if (m_routingTable.LookupRoute(dst, toDst))
1676 {
1677 // The existing entry is updated only in the following circumstances:
1678 if (
1679 // (i) the sequence number in the routing table is marked as invalid in route table
1680 // entry.
1681 (!toDst.GetValidSeqNo()) ||
1682
1683 // (ii) the Destination Sequence Number in the RREP is greater than the node's copy of
1684 // the destination sequence number and the known value is valid,
1685 ((int32_t(rrepHeader.GetDstSeqno()) - int32_t(toDst.GetSeqNo())) > 0) ||
1686
1687 // (iii) the sequence numbers are the same, but the route is marked as inactive.
1688 (rrepHeader.GetDstSeqno() == toDst.GetSeqNo() && toDst.GetFlag() != VALID) ||
1689
1690 // (iv) the sequence numbers are the same, and the New Hop Count is smaller than the
1691 // hop count in route table entry.
1692 (rrepHeader.GetDstSeqno() == toDst.GetSeqNo() && hop < toDst.GetHop()))
1693 {
1694 m_routingTable.Update(newEntry);
1695 }
1696 }
1697 else
1698 {
1699 // The forward route for this destination is created if it does not already exist.
1700 NS_LOG_LOGIC("add new route");
1701 m_routingTable.AddRoute(newEntry);
1702 }
1703 // Acknowledge receipt of the RREP by sending a RREP-ACK message back
1704 if (rrepHeader.GetAckRequired())
1705 {
1706 SendReplyAck(sender);
1707 rrepHeader.SetAckRequired(false);
1708 }
1709 NS_LOG_LOGIC("receiver " << receiver << " origin " << rrepHeader.GetOrigin());
1710 if (IsMyOwnAddress(rrepHeader.GetOrigin()))
1711 {
1712 if (toDst.GetFlag() == IN_SEARCH)
1713 {
1714 m_routingTable.Update(newEntry);
1715 m_addressReqTimer[dst].Cancel();
1716 m_addressReqTimer.erase(dst);
1717 }
1718 m_routingTable.LookupRoute(dst, toDst);
1719 SendPacketFromQueue(dst, toDst.GetRoute());
1720 return;
1721 }
1722
1723 RoutingTableEntry toOrigin;
1724 if (!m_routingTable.LookupRoute(rrepHeader.GetOrigin(), toOrigin) ||
1725 toOrigin.GetFlag() == IN_SEARCH)
1726 {
1727 return; // Impossible! drop.
1728 }
1729 toOrigin.SetLifeTime(std::max(m_activeRouteTimeout, toOrigin.GetLifeTime()));
1730 m_routingTable.Update(toOrigin);
1731
1732 // Update information about precursors
1733 if (m_routingTable.LookupValidRoute(rrepHeader.GetDst(), toDst))
1734 {
1735 toDst.InsertPrecursor(toOrigin.GetNextHop());
1736 m_routingTable.Update(toDst);
1737
1738 RoutingTableEntry toNextHopToDst;
1739 m_routingTable.LookupRoute(toDst.GetNextHop(), toNextHopToDst);
1740 toNextHopToDst.InsertPrecursor(toOrigin.GetNextHop());
1741 m_routingTable.Update(toNextHopToDst);
1742
1743 toOrigin.InsertPrecursor(toDst.GetNextHop());
1744 m_routingTable.Update(toOrigin);
1745
1746 RoutingTableEntry toNextHopToOrigin;
1747 m_routingTable.LookupRoute(toOrigin.GetNextHop(), toNextHopToOrigin);
1748 toNextHopToOrigin.InsertPrecursor(toDst.GetNextHop());
1749 m_routingTable.Update(toNextHopToOrigin);
1750 }
1751 SocketIpTtlTag tag;
1752 p->RemovePacketTag(tag);
1753 if (tag.GetTtl() < 2)
1754 {
1755 NS_LOG_DEBUG("TTL exceeded. Drop RREP destination " << dst << " origin "
1756 << rrepHeader.GetOrigin());
1757 return;
1758 }
1759
1760 Ptr<Packet> packet = Create<Packet>();
1761 SocketIpTtlTag ttl;
1762 ttl.SetTtl(tag.GetTtl() - 1);
1763 packet->AddPacketTag(ttl);
1764 packet->AddHeader(rrepHeader);
1765 TypeHeader tHeader(AODVTYPE_RREP);
1766 packet->AddHeader(tHeader);
1768 NS_ASSERT(socket);
1769 socket->SendTo(packet, 0, InetSocketAddress(toOrigin.GetNextHop(), AODV_PORT));
1770}
1771
1772void
1774{
1775 NS_LOG_FUNCTION(this);
1777 if (m_routingTable.LookupRoute(neighbor, rt))
1778 {
1779 rt.m_ackTimer.Cancel();
1780 rt.SetFlag(VALID);
1782 }
1783}
1784
1785void
1787{
1788 NS_LOG_FUNCTION(this << "from " << rrepHeader.GetDst());
1789 /*
1790 * Whenever a node receives a Hello message from a neighbor, the node
1791 * SHOULD make sure that it has an active route to the neighbor, and
1792 * create one if necessary.
1793 */
1794 RoutingTableEntry toNeighbor;
1795 if (!m_routingTable.LookupRoute(rrepHeader.GetDst(), toNeighbor))
1796 {
1798 RoutingTableEntry newEntry(
1799 /*dev=*/dev,
1800 /*dst=*/rrepHeader.GetDst(),
1801 /*vSeqNo=*/true,
1802 /*seqNo=*/rrepHeader.GetDstSeqno(),
1803 /*iface=*/m_ipv4->GetAddress(m_ipv4->GetInterfaceForAddress(receiver), 0),
1804 /*hops=*/1,
1805 /*nextHop=*/rrepHeader.GetDst(),
1806 /*lifetime=*/rrepHeader.GetLifeTime());
1807 m_routingTable.AddRoute(newEntry);
1808 }
1809 else
1810 {
1811 toNeighbor.SetLifeTime(
1812 std::max(Time(m_allowedHelloLoss * m_helloInterval), toNeighbor.GetLifeTime()));
1813 toNeighbor.SetSeqNo(rrepHeader.GetDstSeqno());
1814 toNeighbor.SetValidSeqNo(true);
1815 toNeighbor.SetFlag(VALID);
1817 toNeighbor.SetInterface(m_ipv4->GetAddress(m_ipv4->GetInterfaceForAddress(receiver), 0));
1818 toNeighbor.SetHop(1);
1819 toNeighbor.SetNextHop(rrepHeader.GetDst());
1820 m_routingTable.Update(toNeighbor);
1821 }
1822 if (m_enableHello)
1823 {
1825 }
1826}
1827
1828void
1830{
1831 NS_LOG_FUNCTION(this << " from " << src);
1832 RerrHeader rerrHeader;
1833 p->RemoveHeader(rerrHeader);
1834 std::map<Ipv4Address, uint32_t> dstWithNextHopSrc;
1835 std::map<Ipv4Address, uint32_t> unreachable;
1836 m_routingTable.GetListOfDestinationWithNextHop(src, dstWithNextHopSrc);
1837 std::pair<Ipv4Address, uint32_t> un;
1838 while (rerrHeader.RemoveUnDestination(un))
1839 {
1840 for (auto i = dstWithNextHopSrc.begin(); i != dstWithNextHopSrc.end(); ++i)
1841 {
1842 if (i->first == un.first)
1843 {
1844 unreachable.insert(un);
1845 }
1846 }
1847 }
1848
1849 std::vector<Ipv4Address> precursors;
1850 for (auto i = unreachable.begin(); i != unreachable.end();)
1851 {
1852 if (!rerrHeader.AddUnDestination(i->first, i->second))
1853 {
1854 TypeHeader typeHeader(AODVTYPE_RERR);
1855 Ptr<Packet> packet = Create<Packet>();
1856 SocketIpTtlTag tag;
1857 tag.SetTtl(1);
1858 packet->AddPacketTag(tag);
1859 packet->AddHeader(rerrHeader);
1860 packet->AddHeader(typeHeader);
1861 SendRerrMessage(packet, precursors);
1862 rerrHeader.Clear();
1863 }
1864 else
1865 {
1866 RoutingTableEntry toDst;
1867 m_routingTable.LookupRoute(i->first, toDst);
1868 toDst.GetPrecursors(precursors);
1869 ++i;
1870 }
1871 }
1872 if (rerrHeader.GetDestCount() != 0)
1873 {
1874 TypeHeader typeHeader(AODVTYPE_RERR);
1875 Ptr<Packet> packet = Create<Packet>();
1876 SocketIpTtlTag tag;
1877 tag.SetTtl(1);
1878 packet->AddPacketTag(tag);
1879 packet->AddHeader(rerrHeader);
1880 packet->AddHeader(typeHeader);
1881 SendRerrMessage(packet, precursors);
1882 }
1884}
1885
1886void
1888{
1889 NS_LOG_LOGIC(this);
1890 RoutingTableEntry toDst;
1891 if (m_routingTable.LookupValidRoute(dst, toDst))
1892 {
1893 SendPacketFromQueue(dst, toDst.GetRoute());
1894 NS_LOG_LOGIC("route to " << dst << " found");
1895 return;
1896 }
1897 /*
1898 * If a route discovery has been attempted RreqRetries times at the maximum TTL without
1899 * receiving any RREP, all data packets destined for the corresponding destination SHOULD be
1900 * dropped from the buffer and a Destination Unreachable message SHOULD be delivered to the
1901 * application.
1902 */
1903 if (toDst.GetRreqCnt() == m_rreqRetries)
1904 {
1905 NS_LOG_LOGIC("route discovery to " << dst << " has been attempted RreqRetries ("
1906 << m_rreqRetries << ") times with ttl "
1907 << m_netDiameter);
1908 m_addressReqTimer.erase(dst);
1910 NS_LOG_DEBUG("Route not found. Drop all packets with dst " << dst);
1912 return;
1913 }
1914
1915 if (toDst.GetFlag() == IN_SEARCH)
1916 {
1917 NS_LOG_LOGIC("Resend RREQ to " << dst << " previous ttl " << toDst.GetHop());
1918 SendRequest(dst);
1919 }
1920 else
1921 {
1922 NS_LOG_DEBUG("Route down. Stop search. Drop packet with destination " << dst);
1923 m_addressReqTimer.erase(dst);
1926 }
1927}
1928
1929void
1931{
1932 NS_LOG_FUNCTION(this);
1933 Time offset = Time(Seconds(0));
1934 if (m_lastBcastTime > Time(Seconds(0)))
1935 {
1936 offset = Simulator::Now() - m_lastBcastTime;
1937 NS_LOG_DEBUG("Hello deferred due to last bcast at:" << m_lastBcastTime);
1938 }
1939 else
1940 {
1941 SendHello();
1942 }
1943 m_htimer.Cancel();
1944 Time diff = m_helloInterval - offset;
1945 m_htimer.Schedule(std::max(Time(Seconds(0)), diff));
1947}
1948
1949void
1956
1957void
1964
1965void
1967{
1968 NS_LOG_FUNCTION(this);
1969 m_routingTable.MarkLinkAsUnidirectional(neighbor, blacklistTimeout);
1970}
1971
1972void
1974{
1975 NS_LOG_FUNCTION(this);
1976 /* Broadcast a RREP with TTL = 1 with the RREP message fields set as follows:
1977 * Destination IP Address The node's IP address.
1978 * Destination Sequence Number The node's latest sequence number.
1979 * Hop Count 0
1980 * Lifetime AllowedHelloLoss * HelloInterval
1981 */
1982 for (auto j = m_socketAddresses.begin(); j != m_socketAddresses.end(); ++j)
1983 {
1984 Ptr<Socket> socket = j->first;
1985 Ipv4InterfaceAddress iface = j->second;
1986 RrepHeader helloHeader(/*prefixSize=*/0,
1987 /*hopCount=*/0,
1988 /*dst=*/iface.GetLocal(),
1989 /*dstSeqNo=*/m_seqNo,
1990 /*origin=*/iface.GetLocal(),
1991 /*lifetime=*/Time(m_allowedHelloLoss * m_helloInterval));
1992 Ptr<Packet> packet = Create<Packet>();
1993 SocketIpTtlTag tag;
1994 tag.SetTtl(1);
1995 packet->AddPacketTag(tag);
1996 packet->AddHeader(helloHeader);
1997 TypeHeader tHeader(AODVTYPE_RREP);
1998 packet->AddHeader(tHeader);
1999 // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
2000 Ipv4Address destination;
2001 if (iface.GetMask() == Ipv4Mask::GetOnes())
2002 {
2003 destination = Ipv4Address("255.255.255.255");
2004 }
2005 else
2006 {
2007 destination = iface.GetBroadcast();
2008 }
2009 Time jitter = Time(MilliSeconds(m_uniformRandomVariable->GetInteger(0, 10)));
2010 Simulator::Schedule(jitter, &RoutingProtocol::SendTo, this, socket, packet, destination);
2011 }
2012}
2013
2014void
2016{
2017 NS_LOG_FUNCTION(this);
2018 QueueEntry queueEntry;
2019 while (m_queue.Dequeue(dst, queueEntry))
2020 {
2022 Ptr<Packet> p = ConstCast<Packet>(queueEntry.GetPacket());
2023 if (p->RemovePacketTag(tag) && tag.GetInterface() != -1 &&
2024 tag.GetInterface() != m_ipv4->GetInterfaceForDevice(route->GetOutputDevice()))
2025 {
2026 NS_LOG_DEBUG("Output device doesn't match. Dropped.");
2027 return;
2028 }
2030 Ipv4Header header = queueEntry.GetIpv4Header();
2031 header.SetSource(route->GetSource());
2032 header.SetTtl(header.GetTtl() +
2033 1); // compensate extra TTL decrement by fake loopback routing
2034 ucb(route, p, header);
2035 }
2036}
2037
2038void
2040{
2041 NS_LOG_FUNCTION(this << nextHop);
2042 RerrHeader rerrHeader;
2043 std::vector<Ipv4Address> precursors;
2044 std::map<Ipv4Address, uint32_t> unreachable;
2045
2046 RoutingTableEntry toNextHop;
2047 if (!m_routingTable.LookupRoute(nextHop, toNextHop))
2048 {
2049 return;
2050 }
2051 toNextHop.GetPrecursors(precursors);
2052 rerrHeader.AddUnDestination(nextHop, toNextHop.GetSeqNo());
2053 m_routingTable.GetListOfDestinationWithNextHop(nextHop, unreachable);
2054 for (auto i = unreachable.begin(); i != unreachable.end();)
2055 {
2056 if (!rerrHeader.AddUnDestination(i->first, i->second))
2057 {
2058 NS_LOG_LOGIC("Send RERR message with maximum size.");
2059 TypeHeader typeHeader(AODVTYPE_RERR);
2060 Ptr<Packet> packet = Create<Packet>();
2061 SocketIpTtlTag tag;
2062 tag.SetTtl(1);
2063 packet->AddPacketTag(tag);
2064 packet->AddHeader(rerrHeader);
2065 packet->AddHeader(typeHeader);
2066 SendRerrMessage(packet, precursors);
2067 rerrHeader.Clear();
2068 }
2069 else
2070 {
2071 RoutingTableEntry toDst;
2072 m_routingTable.LookupRoute(i->first, toDst);
2073 toDst.GetPrecursors(precursors);
2074 ++i;
2075 }
2076 }
2077 if (rerrHeader.GetDestCount() != 0)
2078 {
2079 TypeHeader typeHeader(AODVTYPE_RERR);
2080 Ptr<Packet> packet = Create<Packet>();
2081 SocketIpTtlTag tag;
2082 tag.SetTtl(1);
2083 packet->AddPacketTag(tag);
2084 packet->AddHeader(rerrHeader);
2085 packet->AddHeader(typeHeader);
2086 SendRerrMessage(packet, precursors);
2087 }
2088 unreachable.insert(std::make_pair(nextHop, toNextHop.GetSeqNo()));
2090}
2091
2092void
2094 uint32_t dstSeqNo,
2095 Ipv4Address origin)
2096{
2097 NS_LOG_FUNCTION(this);
2098 // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second.
2100 {
2101 // Just make sure that the RerrRateLimit timer is running and will expire
2103 // discard the packet and return
2104 NS_LOG_LOGIC("RerrRateLimit reached at "
2105 << Simulator::Now().As(Time::S) << " with timer delay left "
2106 << m_rerrRateLimitTimer.GetDelayLeft().As(Time::S) << "; suppressing RERR");
2107 return;
2108 }
2109 RerrHeader rerrHeader;
2110 rerrHeader.AddUnDestination(dst, dstSeqNo);
2111 RoutingTableEntry toOrigin;
2112 Ptr<Packet> packet = Create<Packet>();
2113 SocketIpTtlTag tag;
2114 tag.SetTtl(1);
2115 packet->AddPacketTag(tag);
2116 packet->AddHeader(rerrHeader);
2117 packet->AddHeader(TypeHeader(AODVTYPE_RERR));
2118 if (m_routingTable.LookupValidRoute(origin, toOrigin))
2119 {
2121 NS_ASSERT(socket);
2122 NS_LOG_LOGIC("Unicast RERR to the source of the data transmission");
2123 socket->SendTo(packet, 0, InetSocketAddress(toOrigin.GetNextHop(), AODV_PORT));
2124 }
2125 else
2126 {
2127 for (auto i = m_socketAddresses.begin(); i != m_socketAddresses.end(); ++i)
2128 {
2129 Ptr<Socket> socket = i->first;
2130 Ipv4InterfaceAddress iface = i->second;
2131 NS_ASSERT(socket);
2132 NS_LOG_LOGIC("Broadcast RERR message from interface " << iface.GetLocal());
2133 // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
2134 Ipv4Address destination;
2135 if (iface.GetMask() == Ipv4Mask::GetOnes())
2136 {
2137 destination = Ipv4Address("255.255.255.255");
2138 }
2139 else
2140 {
2141 destination = iface.GetBroadcast();
2142 }
2143 socket->SendTo(packet->Copy(), 0, InetSocketAddress(destination, AODV_PORT));
2144 }
2145 }
2146}
2147
2148void
2149RoutingProtocol::SendRerrMessage(Ptr<Packet> packet, std::vector<Ipv4Address> precursors)
2150{
2151 NS_LOG_FUNCTION(this);
2152
2153 if (precursors.empty())
2154 {
2155 NS_LOG_LOGIC("No precursors");
2156 return;
2157 }
2158 // A node SHOULD NOT originate more than RERR_RATELIMIT RERR messages per second.
2160 {
2161 // Just make sure that the RerrRateLimit timer is running and will expire
2163 // discard the packet and return
2164 NS_LOG_LOGIC("RerrRateLimit reached at "
2165 << Simulator::Now().As(Time::S) << " with timer delay left "
2166 << m_rerrRateLimitTimer.GetDelayLeft().As(Time::S) << "; suppressing RERR");
2167 return;
2168 }
2169 // If there is only one precursor, RERR SHOULD be unicast toward that precursor
2170 if (precursors.size() == 1)
2171 {
2172 RoutingTableEntry toPrecursor;
2173 if (m_routingTable.LookupValidRoute(precursors.front(), toPrecursor))
2174 {
2176 NS_ASSERT(socket);
2177 NS_LOG_LOGIC("one precursor => unicast RERR to "
2178 << toPrecursor.GetDestination() << " from "
2179 << toPrecursor.GetInterface().GetLocal());
2182 this,
2183 socket,
2184 packet,
2185 precursors.front());
2186 m_rerrCount++;
2187 }
2188 return;
2189 }
2190
2191 // Should only transmit RERR on those interfaces which have precursor nodes for the broken
2192 // route
2193 std::vector<Ipv4InterfaceAddress> ifaces;
2194 RoutingTableEntry toPrecursor;
2195 for (auto i = precursors.begin(); i != precursors.end(); ++i)
2196 {
2197 if (m_routingTable.LookupValidRoute(*i, toPrecursor) &&
2198 std::find(ifaces.begin(), ifaces.end(), toPrecursor.GetInterface()) == ifaces.end())
2199 {
2200 ifaces.push_back(toPrecursor.GetInterface());
2201 }
2202 }
2203
2204 for (auto i = ifaces.begin(); i != ifaces.end(); ++i)
2205 {
2207 NS_ASSERT(socket);
2208 NS_LOG_LOGIC("Broadcast RERR message from interface " << i->GetLocal());
2209 // std::cout << "Broadcast RERR message from interface " << i->GetLocal () << std::endl;
2210 // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
2211 Ptr<Packet> p = packet->Copy();
2212 Ipv4Address destination;
2213 if (i->GetMask() == Ipv4Mask::GetOnes())
2214 {
2215 destination = Ipv4Address("255.255.255.255");
2216 }
2217 else
2218 {
2219 destination = i->GetBroadcast();
2220 }
2223 this,
2224 socket,
2225 p,
2226 destination);
2227 }
2228}
2229
2232{
2233 NS_LOG_FUNCTION(this << addr);
2234 for (auto j = m_socketAddresses.begin(); j != m_socketAddresses.end(); ++j)
2235 {
2236 Ptr<Socket> socket = j->first;
2237 Ipv4InterfaceAddress iface = j->second;
2238 if (iface == addr)
2239 {
2240 return socket;
2241 }
2242 }
2243 Ptr<Socket> socket;
2244 return socket;
2245}
2246
2249{
2250 NS_LOG_FUNCTION(this << addr);
2251 for (auto j = m_socketSubnetBroadcastAddresses.begin();
2253 ++j)
2254 {
2255 Ptr<Socket> socket = j->first;
2256 Ipv4InterfaceAddress iface = j->second;
2257 if (iface == addr)
2258 {
2259 return socket;
2260 }
2261 }
2262 Ptr<Socket> socket;
2263 return socket;
2264}
2265
2266void
2268{
2269 NS_LOG_FUNCTION(this);
2270 uint32_t startTime;
2271 if (m_enableHello)
2272 {
2274 startTime = m_uniformRandomVariable->GetInteger(0, 100);
2275 NS_LOG_DEBUG("Starting at time " << startTime << "ms");
2276 m_htimer.Schedule(MilliSeconds(startTime));
2277 }
2279}
2280
2281} // namespace aodv
2282} // namespace ns3
a polymophic address class
Definition address.h:90
Wifi MAC high model for an ad-hoc Wifi MAC.
bool IsNull() const
Check for null implementation.
Definition callback.h:555
an Inet address class
Ipv4Address GetIpv4() const
static InetSocketAddress ConvertFrom(const Address &address)
Returns an InetSocketAddress which corresponds to the input Address.
Ipv4 addresses are stored in host order in this class.
static Ipv4Address GetLoopback()
bool IsMulticast() const
static Ipv4Address GetBroadcast()
bool IsBroadcast() const
Packet header for IPv4.
Definition ipv4-header.h:23
Ipv4Address GetSource() const
uint8_t GetProtocol() const
void SetTtl(uint8_t ttl)
Ipv4Address GetDestination() const
uint8_t GetTtl() const
void SetSource(Ipv4Address source)
virtual int32_t GetInterfaceForAddress(Ipv4Address address) const =0
Return the interface number of the interface that has been assigned the specified IP address.
virtual bool IsForwarding(uint32_t interface) const =0
virtual Ipv4InterfaceAddress GetAddress(uint32_t interface, uint32_t addressIndex) const =0
Because addresses can be removed, the addressIndex is not guaranteed to be static across calls to thi...
virtual Ptr< NetDevice > GetNetDevice(uint32_t interface)=0
virtual bool IsDestinationAddress(Ipv4Address address, uint32_t iif) const =0
Determine whether address and interface corresponding to received packet can be accepted for local de...
virtual int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const =0
virtual uint32_t GetNInterfaces() const =0
a class to store IPv4 address information on an interface
Ipv4Mask GetMask() const
Get the network mask.
Ipv4Address GetLocal() const
Get the local address.
Ipv4Address GetBroadcast() const
Get the broadcast address.
Implement the IPv4 layer.
a class to represent an Ipv4 address mask
static Ipv4Mask GetOnes()
Abstract base class for IPv4 routing protocols.
A network Node.
Definition node.h:46
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition object.h:511
virtual void DoInitialize()
Initialize() implementation.
Definition object.cc:440
virtual void DoDispose()
Destructor implementation.
Definition object.cc:433
Smart pointer class similar to boost::intrusive_ptr.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time Now()
Return the current simulation virtual time.
Definition simulator.cc:197
static EventId ScheduleNow(FUNC f, Ts &&... args)
Schedule an event to expire Now.
Definition simulator.h:594
static Time GetMaximumSimulationTime()
Get the maximum representable simulation time.
Definition simulator.cc:300
static Ptr< Socket > CreateSocket(Ptr< Node > node, TypeId tid)
This method wraps the creation of sockets that is performed on a given node by a SocketFactory specif...
Definition socket.cc:61
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition socket.h:73
@ ERROR_NOROUTETOHOST
Definition socket.h:84
@ ERROR_NOTERROR
Definition socket.h:74
This class implements a tag that carries the socket-specific TTL of a packet to the IP layer.
Definition socket.h:1113
void SetTtl(uint8_t ttl)
Set the tag's TTL.
Definition socket.cc:593
uint8_t GetTtl() const
Get the tag's TTL.
Definition socket.cc:600
Hold variables of type string.
Definition string.h:45
read and write tag data
Definition tag-buffer.h:41
TAG_BUFFER_INLINE uint32_t ReadU32()
Definition tag-buffer.h:206
TAG_BUFFER_INLINE void WriteU32(uint32_t v)
Definition tag-buffer.h:176
tag a set of bytes in a packet
Definition tag.h:28
Simulation virtual time values and global simulation resolution.
Definition nstime.h:94
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition time.cc:404
Unit
The unit to use to interpret a number representing time.
Definition nstime.h:100
@ S
second
Definition nstime.h:105
A simple virtual Timer class.
Definition timer.h:67
void SetDelay(const Time &delay)
Definition timer.cc:65
void SetFunction(FN fn)
Definition timer.h:268
Time GetDelayLeft() const
Definition timer.cc:79
void SetArguments(Ts... args)
Definition timer.h:284
@ CANCEL_ON_DESTROY
This policy cancels the event from the destructor of the Timer or from Suspend().
Definition timer.h:86
void Cancel()
Cancel the currently-running event if there is one.
Definition timer.cc:97
void Schedule()
Schedule a new event using the currently-configured delay, function, and arguments.
Definition timer.cc:151
bool IsRunning() const
Definition timer.cc:118
a unique identifier for an interface.
Definition type-id.h:48
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Packet header for UDP packets.
Definition udp-header.h:30
uint16_t GetDestinationPort() const
Definition udp-header.cc:43
static const uint8_t PROT_NUMBER
protocol number (0x11)
static TypeId GetTypeId()
Get the type ID.
Hold an unsigned integer type.
Definition uinteger.h:34
Hold together all Wifi-related objects.
Tag used by AODV implementation.
uint32_t GetSerializedSize() const override
TypeId GetInstanceTypeId() const override
Get the most derived TypeId for this Object.
static TypeId GetTypeId()
Get the type ID.
int32_t GetInterface() const
Get the output interface.
int32_t m_oif
Positive if output device is fixed in RouteOutput.
void SetInterface(int32_t oif)
Set the output interface.
void Serialize(TagBuffer i) const override
DeferredRouteOutputTag(int32_t o=-1)
Constructor.
void Print(std::ostream &os) const override
bool IsDuplicate(Ptr< const Packet > p, const Ipv4Header &header)
Check if the packet is a duplicate.
Definition aodv-dpd.cc:19
bool IsDuplicate(Ipv4Address addr, uint32_t id)
Check that entry (addr, id) exists in cache.
void ScheduleTimer()
Schedule m_ntimer.
void Clear()
Remove all entries.
void Update(Ipv4Address addr, Time expire)
Update expire time for entry with address addr, if it exists, else add new entry.
Callback< void, const WifiMacHeader & > GetTxErrorCallback() const
Get callback to ProcessTxError.
void SetCallback(Callback< void, Ipv4Address > cb)
Set link failure callback.
void DelArpCache(Ptr< ArpCache > a)
Don't use given ARP cache any more (interface is down)
void AddArpCache(Ptr< ArpCache > a)
Add ARP cache to be used to allow layer 2 notifications processing.
AODV Queue Entry.
Definition aodv-rqueue.h:34
Ipv4Header GetIpv4Header() const
Get IPv4 header.
Ptr< const Packet > GetPacket() const
Get packet from entry.
UnicastForwardCallback GetUnicastForwardCallback() const
Get unicast forward callback.
Definition aodv-rqueue.h:80
bool Dequeue(Ipv4Address dst, QueueEntry &entry)
Return first found (the earliest) entry for given destination.
void SetMaxQueueLen(uint32_t len)
Set maximum queue length.
void SetQueueTimeout(Time t)
Set queue timeout.
void DropPacketWithDst(Ipv4Address dst)
Remove all packets with destination IP address dst.
bool Enqueue(QueueEntry &entry)
Push entry in queue, if there is no entry with the same packet and destination address in queue.
Route Error (RERR) Message Format.
uint8_t GetDestCount() const
void Clear()
Clear header.
bool AddUnDestination(Ipv4Address dst, uint32_t seqNo)
Add unreachable node address and its sequence number in RERR header.
bool RemoveUnDestination(std::pair< Ipv4Address, uint32_t > &un)
Delete pair (address + sequence number) from REER header, if the number of unreachable destinations >...
Ptr< Ipv4Route > LoopbackRoute(const Ipv4Header &header, Ptr< NetDevice > oif) const
Create loopback route for given header.
uint32_t m_requestId
Broadcast ID.
void RecvAodv(Ptr< Socket > socket)
Receive and process control packet.
void UpdateRouteToNeighbor(Ipv4Address sender, Ipv4Address receiver)
Update neighbor record.
Timer m_rerrRateLimitTimer
RERR rate limit timer.
Time m_lastBcastTime
Keep track of the last bcast time.
void RecvReply(Ptr< Packet > p, Ipv4Address my, Ipv4Address src)
Receive RREP.
bool m_enableBroadcast
Indicates whether a a broadcast data packets forwarding enable.
bool GetBroadcastEnable() const
Get broadcast enable flag.
bool UpdateRouteLifeTime(Ipv4Address addr, Time lt)
Set lifetime field in routing table entry to the maximum of existing lifetime and lt,...
void RerrRateLimitTimerExpire()
Reset RERR count and schedule RERR rate limit timer with delay 1 sec.
Time m_blackListTimeout
Time for which the node is put into the blacklist.
void RecvReplyAck(Ipv4Address neighbor)
Receive RREP_ACK.
std::map< Ptr< Socket >, Ipv4InterfaceAddress > m_socketSubnetBroadcastAddresses
Raw subnet directed broadcast socket per each IP interface, map socket -> iface address (IP.
Time m_maxQueueTime
The maximum period of time that a routing protocol is allowed to buffer a packet for.
Time m_activeRouteTimeout
Period of time during which the route is considered to be valid.
std::map< Ipv4Address, Timer > m_addressReqTimer
Map IP address + RREQ timer.
uint32_t GetMaxQueueLen() const
Get the maximum queue length.
void DeferredRouteOutput(Ptr< const Packet > p, const Ipv4Header &header, UnicastForwardCallback ucb, ErrorCallback ecb)
Queue packet and send route request.
void SendTo(Ptr< Socket > socket, Ptr< Packet > packet, Ipv4Address destination)
Send packet to destination socket.
DuplicatePacketDetection m_dpd
Handle duplicated broadcast/multicast packets.
Time m_netTraversalTime
Estimate of the average net traversal time.
void DoDispose() override
Destructor implementation.
void SendRequest(Ipv4Address dst)
Send RREQ.
Time m_pathDiscoveryTime
Estimate of maximum time needed to find route in network.
bool m_gratuitousReply
Indicates whether a gratuitous RREP should be unicast to the node originated route discovery.
uint16_t m_rerrCount
Number of RERRs used for RERR rate control.
void HelloTimerExpire()
Schedule next send of hello message.
void NotifyTxError(WifiMacDropReason reason, Ptr< const WifiMpdu > mpdu)
Notify that an MPDU was dropped.
RoutingTable m_routingTable
Routing table.
uint16_t m_rreqRateLimit
Maximum number of RREQ per second.
Ptr< NetDevice > m_lo
Loopback device used to defer RREQ until packet will be fully formed.
uint32_t m_netDiameter
Net diameter measures the maximum possible number of hops between two nodes in the network.
uint32_t m_maxQueueLen
The maximum number of packets that we allow a routing protocol to buffer.
uint16_t m_ttlThreshold
Maximum TTL value for expanding ring search, TTL = NetDiameter is used beyond this value.
Ptr< UniformRandomVariable > m_uniformRandomVariable
Provides uniform random variables.
void SetMaxQueueTime(Time t)
Set the maximum queue time.
uint16_t m_ttlIncrement
TTL increment for each attempt using the expanding ring search for RREQ dissemination.
Time m_myRouteTimeout
Value of lifetime field in RREP generating by this node.
uint16_t m_timeoutBuffer
Provide a buffer for the timeout.
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
Ptr< Socket > FindSocketWithInterfaceAddress(Ipv4InterfaceAddress iface) const
Find unicast socket with local interface address iface.
void NotifyInterfaceDown(uint32_t interface) override
void SetBroadcastEnable(bool f)
Set broadcast enable flag.
void SendPacketFromQueue(Ipv4Address dst, Ptr< Ipv4Route > route)
Forward packet from route request queue.
uint32_t m_allowedHelloLoss
Number of hello messages which may be loss for valid link.
bool IsMyOwnAddress(Ipv4Address src)
Test whether the provided address is assigned to an interface on this node.
void SetMaxQueueLen(uint32_t len)
Set the maximum queue length.
void ScheduleRreqRetry(Ipv4Address dst)
Repeated attempts by a source node at route discovery for a single destination use the expanding ring...
void SendReplyByIntermediateNode(RoutingTableEntry &toDst, RoutingTableEntry &toOrigin, bool gratRep)
Send RREP by intermediate node.
std::map< Ptr< Socket >, Ipv4InterfaceAddress > m_socketAddresses
Raw unicast socket per each IP interface, map socket -> iface address (IP + mask)
void SetGratuitousReplyFlag(bool f)
Set gratuitous reply flag.
bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb) override
Route an input packet (to be forwarded or locally delivered)
void Start()
Start protocol operation.
uint16_t m_rreqCount
Number of RREQs used for RREQ rate control.
IdCache m_rreqIdCache
Handle duplicated RREQ.
Time m_deletePeriod
DeletePeriod is intended to provide an upper bound on the time for which an upstream node A can have ...
void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address) override
void SendRerrWhenNoRouteToForward(Ipv4Address dst, uint32_t dstSeqNo, Ipv4Address origin)
Send RERR message when no route to forward input packet.
Time m_helloInterval
Every HelloInterval the node checks whether it has sent a broadcast within the last HelloInterval.
void AckTimerExpire(Ipv4Address neighbor, Time blacklistTimeout)
Mark link to neighbor node as unidirectional for blacklistTimeout.
void SetHelloEnable(bool f)
Set hello enable.
bool m_destinationOnly
Indicates only the destination may respond to this RREQ.
void SetIpv4(Ptr< Ipv4 > ipv4) override
static TypeId GetTypeId()
Get the type ID.
void SetDestinationOnlyFlag(bool f)
Set destination only flag.
bool GetDestinationOnlyFlag() const
Get destination only flag.
void SendRerrMessage(Ptr< Packet > packet, std::vector< Ipv4Address > precursors)
Forward RERR.
uint16_t m_ttlStart
Initial TTL value for RREQ.
uint32_t m_rreqRetries
Maximum number of retransmissions of RREQ with TTL = NetDiameter to discover a route.
uint32_t m_seqNo
Request sequence number.
bool m_enableHello
Indicates whether a hello messages enable.
Neighbors m_nb
Handle neighbors.
bool Forwarding(Ptr< const Packet > p, const Ipv4Header &header, UnicastForwardCallback ucb, ErrorCallback ecb)
If route exists and is valid, forward packet.
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
static const uint32_t AODV_PORT
UDP Port for AODV control traffic.
Timer m_rreqRateLimitTimer
RREQ rate limit timer.
Time GetMaxQueueTime() const
Get maximum queue time.
void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address) override
Time m_nodeTraversalTime
NodeTraversalTime is a conservative estimate of the average one hop traversal time for packets and sh...
uint16_t m_rerrRateLimit
Maximum number of REER per second.
void RecvRequest(Ptr< Packet > p, Ipv4Address receiver, Ipv4Address src)
Receive RREQ.
Ptr< Socket > FindSubnetBroadcastSocketWithInterfaceAddress(Ipv4InterfaceAddress iface) const
Find subnet directed broadcast socket with local interface address iface.
void DoInitialize() override
Initialize() implementation.
bool GetHelloEnable() const
Get hello enable flag.
void SendRerrWhenBreaksLinkToNextHop(Ipv4Address nextHop)
Initiate RERR.
void RouteRequestTimerExpire(Ipv4Address dst)
Handle route discovery process.
void NotifyInterfaceUp(uint32_t interface) override
bool GetGratuitousReplyFlag() const
Get gratuitous reply flag.
void RecvError(Ptr< Packet > p, Ipv4Address src)
Receive RERR.
Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr) override
Query routing cache for an existing route, for an outbound packet.
Time m_nextHopWait
Period of our waiting for the neighbour's RREP_ACK.
void SendReplyAck(Ipv4Address neighbor)
Send RREP_ACK.
Ptr< Ipv4 > m_ipv4
IP protocol.
void RreqRateLimitTimerExpire()
Reset RREQ count and schedule RREQ rate limit timer with delay 1 sec.
void ProcessHello(const RrepHeader &rrepHeader, Ipv4Address receiverIfaceAddr)
Process hello message.
void SendReply(const RreqHeader &rreqHeader, const RoutingTableEntry &toOrigin)
Send RREP.
RequestQueue m_queue
A "drop-front" queue used by the routing layer to buffer packets to which it does not have a route.
Routing table entry.
Definition aodv-rtable.h:51
Timer m_ackTimer
RREP_ACK timer.
void SetHop(uint16_t hop)
Set the number of hops.
bool InsertPrecursor(Ipv4Address id)
Insert precursor in precursor list if it doesn't yet exist in the list.
Ptr< NetDevice > GetOutputDevice() const
Get output device.
uint8_t GetRreqCnt() const
Get the RREQ count.
Ipv4InterfaceAddress GetInterface() const
Get the Ipv4InterfaceAddress.
void SetNextHop(Ipv4Address nextHop)
Set next hop address.
void SetLifeTime(Time lt)
Set the lifetime.
bool IsUnidirectional() const
Get the unidirectional flag.
void GetPrecursors(std::vector< Ipv4Address > &prec) const
Inserts precursors in output parameter prec if they do not yet exist in vector.
RouteFlags GetFlag() const
Get the route flags.
Ipv4Address GetNextHop() const
Get next hop address.
void IncrementRreqCnt()
Increment the RREQ count.
void SetSeqNo(uint32_t sn)
Set the sequence number.
void SetInterface(Ipv4InterfaceAddress iface)
Set the Ipv4InterfaceAddress.
void SetRreqCnt(uint8_t n)
Set the RREQ count.
void SetOutputDevice(Ptr< NetDevice > dev)
Set output device.
Ipv4Address GetDestination() const
Get destination address function.
uint16_t GetHop() const
Get the number of hops.
void SetValidSeqNo(bool s)
Set the valid sequence number.
uint32_t GetSeqNo() const
Get the sequence number.
bool GetValidSeqNo() const
Get the valid sequence number.
void SetFlag(RouteFlags flag)
Set the route flags.
Time GetLifeTime() const
Get the lifetime.
Ptr< Ipv4Route > GetRoute() const
Get route function.
void GetListOfDestinationWithNextHop(Ipv4Address nextHop, std::map< Ipv4Address, uint32_t > &unreachable)
Lookup routing entries with next hop Address dst and not empty list of precursors.
bool LookupValidRoute(Ipv4Address dst, RoutingTableEntry &rt)
Lookup route in VALID state.
void Purge()
Delete all outdated entries and invalidate valid entry if Lifetime is expired.
bool Update(RoutingTableEntry &rt)
Update routing table.
bool AddRoute(RoutingTableEntry &r)
Add routing table entry if it doesn't yet exist in routing table.
void Print(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print routing table.
bool LookupRoute(Ipv4Address dst, RoutingTableEntry &rt)
Lookup routing table entry with destination address dst.
void DeleteAllRoutesFromInterface(Ipv4InterfaceAddress iface)
Delete all route from interface with address iface.
void Clear()
Delete all entries from routing table.
void InvalidateRoutesWithDst(const std::map< Ipv4Address, uint32_t > &unreachable)
Update routing entries with this destination as follows:
bool MarkLinkAsUnidirectional(Ipv4Address neighbor, Time blacklistTimeout)
Mark entry as unidirectional (e.g.
bool DeleteRoute(Ipv4Address dst)
Delete routing table entry with destination address dst, if it exists.
Route Reply Acknowledgment (RREP-ACK) Message Format.
Route Reply (RREP) Message Format.
bool GetAckRequired() const
get the ack required flag
Ipv4Address GetOrigin() const
Get the origin address.
uint8_t GetHopCount() const
Get the hop count.
void SetHopCount(uint8_t count)
Set the hop count.
void SetAckRequired(bool f)
Set the ack required flag.
Time GetLifeTime() const
Get the lifetime.
uint32_t GetDstSeqno() const
Get the destination sequence number.
Ipv4Address GetDst() const
Get the destination address.
Route Request (RREQ) Message Format.
uint32_t GetId() const
Get the request ID.
void SetDst(Ipv4Address a)
Set the destination address.
uint8_t GetHopCount() const
Get the hop count.
bool GetUnknownSeqno() const
Get the unknown sequence number flag.
void SetId(uint32_t id)
Set the request ID.
uint32_t GetOriginSeqno() const
Get the origin sequence number.
void SetUnknownSeqno(bool f)
Set the unknown sequence number flag.
Ipv4Address GetOrigin() const
Get the origin address.
void SetGratuitousRrep(bool f)
Set the gratuitous RREP flag.
void SetDestinationOnly(bool f)
Set the Destination only flag.
bool GetDestinationOnly() const
Get the Destination only flag.
void SetHopCount(uint8_t count)
Set the hop count.
void SetDstSeqno(uint32_t s)
Set the destination sequence number.
uint32_t GetDstSeqno() const
Get the destination sequence number.
Ipv4Address GetDst() const
Get the destination address.
void SetOriginSeqno(uint32_t s)
Set the origin sequence number.
bool GetGratuitousRrep() const
Get the gratuitous RREP flag.
void SetOrigin(Ipv4Address a)
Set the origin address.
bool IsValid() const
Check that type if valid.
Definition aodv-packet.h:80
MessageType Get() const
Definition aodv-packet.h:71
@ IN_SEARCH
IN_SEARCH.
Definition aodv-rtable.h:43
@ VALID
VALID.
Definition aodv-rtable.h:41
@ AODVTYPE_RREP
AODVTYPE_RREP.
Definition aodv-packet.h:39
@ AODVTYPE_RREP_ACK
AODVTYPE_RREP_ACK.
Definition aodv-packet.h:41
@ AODVTYPE_RERR
AODVTYPE_RERR.
Definition aodv-packet.h:40
@ AODVTYPE_RREQ
AODVTYPE_RREQ.
Definition aodv-packet.h:38
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition assert.h:55
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition assert.h:75
Ptr< const AttributeAccessor > MakePointerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition pointer.h:248
Ptr< AttributeChecker > MakePointerChecker()
Create a PointerChecker for a type.
Definition pointer.h:269
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
Definition abort.h:133
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
Definition log.h:243
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition log.h:191
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition log.h:257
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition log.h:271
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition log.h:250
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition object-base.h:35
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Definition ptr.h:436
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition simulator.cc:294
Time MicroSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1332
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition nstime.h:1320
WifiMacDropReason
The reason why an MPDU was dropped.
Definition wifi-mac.h:70
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeChecker > MakeBooleanChecker()
Definition boolean.cc:113
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition nstime.h:1396
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition callback.h:684
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition uinteger.h:35
Ptr< const AttributeAccessor > MakeBooleanAccessor(T1 a1)
Definition boolean.h:70
Ptr< T1 > ConstCast(const Ptr< T2 > &p)
Cast a Ptr.
Definition ptr.h:573
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416
STL namespace.