A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
ripng.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2014 Universita' di Firenze, Italy
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
7 */
8
9#include "ripng.h"
10
12#include "ipv6-route.h"
13#include "ripng-header.h"
14#include "udp-header.h"
15
16#include "ns3/abort.h"
17#include "ns3/assert.h"
18#include "ns3/enum.h"
19#include "ns3/log.h"
20#include "ns3/names.h"
21#include "ns3/node.h"
22#include "ns3/random-variable-stream.h"
23#include "ns3/simulator.h"
24#include "ns3/uinteger.h"
25
26#include <iomanip>
27
28#define RIPNG_ALL_NODE "ff02::9"
29#define RIPNG_PORT 521
30
31namespace ns3
32{
33
35
37
39 : m_ipv6(nullptr),
40 m_splitHorizonStrategy(RipNg::POISON_REVERSE),
41 m_initialized(false)
42{
44}
45
47{
48}
49
52{
53 static TypeId tid =
54 TypeId("ns3::RipNg")
56 .SetGroupName("Internet")
57 .AddConstructor<RipNg>()
58 .AddAttribute("UnsolicitedRoutingUpdate",
59 "The time between two Unsolicited Routing Updates.",
60 TimeValue(Seconds(30)),
63 .AddAttribute("StartupDelay",
64 "Maximum random delay for protocol startup (send route requests).",
68 .AddAttribute("TimeoutDelay",
69 "The delay to invalidate a route.",
70 TimeValue(Seconds(180)),
73 .AddAttribute("GarbageCollectionDelay",
74 "The delay to delete an expired route.",
75 TimeValue(Seconds(120)),
78 .AddAttribute("MinTriggeredCooldown",
79 "Min cooldown delay after a Triggered Update.",
83 .AddAttribute("MaxTriggeredCooldown",
84 "Max cooldown delay after a Triggered Update.",
88 .AddAttribute("SplitHorizon",
89 "Split Horizon strategy.",
93 "NoSplitHorizon",
95 "SplitHorizon",
97 "PoisonReverse"))
98 .AddAttribute("LinkDownValue",
99 "Value for link down in count to infinity.",
100 UintegerValue(16),
103 return tid;
104}
105
106int64_t
107RipNg::AssignStreams(int64_t stream)
108{
109 NS_LOG_FUNCTION(this << stream);
110
111 m_rng->SetStream(stream);
112 return 1;
113}
114
115void
117{
118 NS_LOG_FUNCTION(this);
119
120 bool addedGlobal = false;
121
122 m_initialized = true;
123
124 Time delay =
127
128 for (uint32_t i = 0; i < m_ipv6->GetNInterfaces(); i++)
129 {
130 bool activeInterface = false;
131 if (m_interfaceExclusions.find(i) == m_interfaceExclusions.end())
132 {
133 activeInterface = true;
134 m_ipv6->SetForwarding(i, true);
135 }
136
137 for (uint32_t j = 0; j < m_ipv6->GetNAddresses(i); j++)
138 {
139 Ipv6InterfaceAddress address = m_ipv6->GetAddress(i, j);
140 if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && activeInterface)
141 {
142 NS_LOG_LOGIC("RIPng: adding socket to " << address.GetAddress());
143 TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
144 Ptr<Node> theNode = GetObject<Node>();
145 Ptr<Socket> socket = Socket::CreateSocket(theNode, tid);
146 Inet6SocketAddress local = Inet6SocketAddress(address.GetAddress(), RIPNG_PORT);
147 socket->BindToNetDevice(m_ipv6->GetNetDevice(i));
148 int ret = socket->Bind(local);
149 NS_ASSERT_MSG(ret == 0, "Bind unsuccessful");
150 socket->SetRecvCallback(MakeCallback(&RipNg::Receive, this));
151 socket->SetIpv6RecvHopLimit(true);
152 socket->SetRecvPktInfo(true);
153 m_unicastSocketList[socket] = i;
154 }
156 {
157 addedGlobal = true;
158 }
159 }
160 }
161
163 {
164 NS_LOG_LOGIC("RIPng: adding receiving socket");
165 TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
166 Ptr<Node> theNode = GetObject<Node>();
173 }
174
175 if (addedGlobal)
176 {
180 }
181
182 delay = Seconds(m_rng->GetValue(0.01, m_startupDelay.GetSeconds()));
184
186}
187
190 const Ipv6Header& header,
191 Ptr<NetDevice> oif,
192 Socket::SocketErrno& sockerr)
193{
194 NS_LOG_FUNCTION(this << header << oif);
195
196 Ipv6Address destination = header.GetDestination();
197 Ptr<Ipv6Route> rtentry = nullptr;
198
199 if (destination.IsMulticast())
200 {
201 // Note: Multicast routes for outbound packets are stored in the
202 // normal unicast table. An implication of this is that it is not
203 // possible to source multicast datagrams on multiple interfaces.
204 // This is a well-known property of sockets implementation on
205 // many Unix variants.
206 // So, we just log it and fall through to LookupStatic ()
207 NS_LOG_LOGIC("RouteOutput (): Multicast destination");
208 }
209
210 rtentry = Lookup(destination, true, oif);
211 if (rtentry)
212 {
213 sockerr = Socket::ERROR_NOTERROR;
214 }
215 else
216 {
218 }
219 return rtentry;
220}
221
222bool
224 const Ipv6Header& header,
226 const UnicastForwardCallback& ucb,
227 const MulticastForwardCallback& mcb,
228 const LocalDeliverCallback& lcb,
229 const ErrorCallback& ecb)
230{
231 NS_LOG_FUNCTION(this << p << header << header.GetSource() << header.GetDestination() << idev);
232
234 // Check if input device supports IP
237 Ipv6Address dst = header.GetDestination();
238
239 if (dst.IsMulticast())
240 {
241 NS_LOG_LOGIC("Multicast route not supported by RIPng");
242 return false; // Let other routing protocols try to handle this
243 }
244
245 if (header.GetDestination().IsLinkLocal() || header.GetSource().IsLinkLocal())
246 {
247 NS_LOG_LOGIC("Dropping packet not for me and with src or dst LinkLocal");
248 if (!ecb.IsNull())
249 {
250 ecb(p, header, Socket::ERROR_NOROUTETOHOST);
251 }
252 return false;
253 }
254
255 // Check if input device supports IP forwarding
256 if (!m_ipv6->IsForwarding(iif))
257 {
258 NS_LOG_LOGIC("Forwarding disabled for this interface");
259 if (!ecb.IsNull())
260 {
261 ecb(p, header, Socket::ERROR_NOROUTETOHOST);
262 }
263 return true;
264 }
265 // Next, try to find a route
266 NS_LOG_LOGIC("Unicast destination");
267 Ptr<Ipv6Route> rtentry = Lookup(header.GetDestination(), false);
268
269 if (rtentry)
270 {
271 NS_LOG_LOGIC("Found unicast destination - calling unicast callback");
272 ucb(idev, rtentry, p, header); // unicast forwarding callback
273 return true;
274 }
275 else
276 {
277 NS_LOG_LOGIC("Did not find unicast destination - returning false");
278 return false; // Let other routing protocols try to handle this
279 }
280}
281
282void
284{
285 NS_LOG_FUNCTION(this << i);
286
287 for (uint32_t j = 0; j < m_ipv6->GetNAddresses(i); j++)
288 {
289 Ipv6InterfaceAddress address = m_ipv6->GetAddress(i, j);
290 Ipv6Prefix networkMask = address.GetPrefix();
291 Ipv6Address networkAddress = address.GetAddress().CombinePrefix(networkMask);
292
293 if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
294 {
295 AddNetworkRouteTo(networkAddress, networkMask, i);
296 }
297 }
298
299 if (!m_initialized)
300 {
301 return;
302 }
303
304 bool sendSocketFound = false;
305 for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
306 {
307 if (iter->second == i)
308 {
309 sendSocketFound = true;
310 break;
311 }
312 }
313
314 bool activeInterface = false;
315 if (m_interfaceExclusions.find(i) == m_interfaceExclusions.end())
316 {
317 activeInterface = true;
318 m_ipv6->SetForwarding(i, true);
319 }
320
321 for (uint32_t j = 0; j < m_ipv6->GetNAddresses(i); j++)
322 {
323 Ipv6InterfaceAddress address = m_ipv6->GetAddress(i, j);
324
325 if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && !sendSocketFound &&
326 activeInterface)
327 {
328 NS_LOG_LOGIC("RIPng: adding sending socket to " << address.GetAddress());
329 TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
330 Ptr<Node> theNode = GetObject<Node>();
331 Ptr<Socket> socket = Socket::CreateSocket(theNode, tid);
332 Inet6SocketAddress local = Inet6SocketAddress(address.GetAddress(), RIPNG_PORT);
333 socket->BindToNetDevice(m_ipv6->GetNetDevice(i));
334 socket->Bind(local);
335 socket->SetRecvCallback(MakeCallback(&RipNg::Receive, this));
336 socket->SetIpv6RecvHopLimit(true);
337 socket->SetRecvPktInfo(true);
338 m_unicastSocketList[socket] = i;
339 }
340 else if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
341 {
343 }
344 }
345
347 {
348 NS_LOG_LOGIC("RIPng: adding receiving socket");
349 TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
350 Ptr<Node> theNode = GetObject<Node>();
357 }
358}
359
360void
362{
363 NS_LOG_FUNCTION(this << interface);
364
365 /* remove all routes that are going through this interface */
366 for (auto it = m_routes.begin(); it != m_routes.end(); it++)
367 {
368 if (it->first->GetInterface() == interface)
369 {
370 InvalidateRoute(it->first);
371 }
372 }
373
374 for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
375 {
376 NS_LOG_INFO("Checking socket for interface " << interface);
377 if (iter->second == interface)
378 {
379 NS_LOG_INFO("Removed socket for interface " << interface);
380 iter->first->Close();
381 m_unicastSocketList.erase(iter);
382 break;
383 }
384 }
385
386 if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
387 {
389 }
390}
391
392void
394{
395 NS_LOG_FUNCTION(this << interface << address);
396
397 if (!m_ipv6->IsUp(interface))
398 {
399 return;
400 }
401
402 if (m_interfaceExclusions.find(interface) != m_interfaceExclusions.end())
403 {
404 return;
405 }
406
407 Ipv6Address networkAddress = address.GetAddress().CombinePrefix(address.GetPrefix());
408 Ipv6Prefix networkMask = address.GetPrefix();
409
410 if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
411 {
412 AddNetworkRouteTo(networkAddress, networkMask, interface);
413 }
414
416}
417
418void
420{
421 NS_LOG_FUNCTION(this << interface << address);
422
423 if (!m_ipv6->IsUp(interface))
424 {
425 return;
426 }
427
428 if (address.GetScope() != Ipv6InterfaceAddress::GLOBAL)
429 {
430 return;
431 }
432
433 Ipv6Address networkAddress = address.GetAddress().CombinePrefix(address.GetPrefix());
434 Ipv6Prefix networkMask = address.GetPrefix();
435
436 // Remove all routes that are going through this interface
437 // which reference this network
438 for (auto it = m_routes.begin(); it != m_routes.end(); it++)
439 {
440 if (it->first->GetInterface() == interface && it->first->IsNetwork() &&
441 it->first->GetDestNetwork() == networkAddress &&
442 it->first->GetDestNetworkPrefix() == networkMask)
443 {
444 InvalidateRoute(it->first);
445 }
446 }
447
448 if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
449 {
451 }
452}
453
454void
456 Ipv6Prefix mask,
457 Ipv6Address nextHop,
458 uint32_t interface,
459 Ipv6Address prefixToUse)
460{
461 NS_LOG_INFO(this << dst << mask << nextHop << interface << prefixToUse);
462 // \todo this can be used to add delegate routes
463}
464
465void
467 Ipv6Prefix mask,
468 Ipv6Address nextHop,
469 uint32_t interface,
470 Ipv6Address prefixToUse)
471{
472 NS_LOG_FUNCTION(this << dst << mask << nextHop << interface);
473 // \todo this can be used to delete delegate routes
474}
475
476void
478{
479 NS_LOG_FUNCTION(this << ipv6);
480
481 NS_ASSERT(!m_ipv6 && ipv6);
482 uint32_t i = 0;
483 m_ipv6 = ipv6;
484
485 for (i = 0; i < m_ipv6->GetNInterfaces(); i++)
486 {
487 if (m_ipv6->IsUp(i))
488 {
490 }
491 else
492 {
494 }
495 }
496}
497
498void
500{
501 NS_LOG_FUNCTION(this << stream);
502
503 std::ostream* os = stream->GetStream();
504 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
505
506 *os << "Node: " << m_ipv6->GetObject<Node>()->GetId() << ", Time: " << Now().As(unit)
507 << ", Local time: " << m_ipv6->GetObject<Node>()->GetLocalTime().As(unit)
508 << ", IPv6 RIPng table" << std::endl;
509
510 if (!m_routes.empty())
511 {
512 *os << "Destination Next Hop Flag Met Ref Use If"
513 << std::endl;
514 for (auto it = m_routes.begin(); it != m_routes.end(); it++)
515 {
516 RipNgRoutingTableEntry* route = it->first;
518
520 {
521 std::ostringstream dest;
522 std::ostringstream gw;
523 std::ostringstream mask;
524 std::ostringstream flags;
525
526 dest << route->GetDest() << "/"
527 << int(route->GetDestNetworkPrefix().GetPrefixLength());
528 *os << std::setw(31) << dest.str();
529 gw << route->GetGateway();
530 *os << std::setw(27) << gw.str();
531 flags << "U";
532 if (route->IsHost())
533 {
534 flags << "H";
535 }
536 else if (route->IsGateway())
537 {
538 flags << "G";
539 }
540 *os << std::setw(5) << flags.str();
541 *os << std::setw(4) << int(route->GetRouteMetric());
542 // Ref ct not implemented
543 *os << "-"
544 << " ";
545 // Use not implemented
546 *os << "-"
547 << " ";
548 if (!Names::FindName(m_ipv6->GetNetDevice(route->GetInterface())).empty())
549 {
551 }
552 else
553 {
554 *os << route->GetInterface();
555 }
556 *os << std::endl;
557 }
558 }
559 }
560 *os << std::endl;
561}
562
563void
565{
566 NS_LOG_FUNCTION(this);
567
568 for (auto j = m_routes.begin(); j != m_routes.end(); j = m_routes.erase(j))
569 {
570 delete j->first;
571 }
572 m_routes.clear();
573
578
579 for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
580 {
581 iter->first->Close();
582 }
583 m_unicastSocketList.clear();
584
586 m_multicastRecvSocket = nullptr;
587
588 m_ipv6 = nullptr;
589
591}
592
594RipNg::Lookup(Ipv6Address dst, bool setSource, Ptr<NetDevice> interface)
595{
596 NS_LOG_FUNCTION(this << dst << interface);
597
598 Ptr<Ipv6Route> rtentry = nullptr;
599 uint16_t longestMask = 0;
600
601 /* when sending on link-local multicast, there have to be interface specified */
602 if (dst.IsLinkLocalMulticast())
603 {
605 interface,
606 "Try to send on link-local multicast address, and no interface index is given!");
607 rtentry = Create<Ipv6Route>();
608 rtentry->SetSource(
610 rtentry->SetDestination(dst);
611 rtentry->SetGateway(Ipv6Address::GetZero());
612 rtentry->SetOutputDevice(interface);
613 return rtentry;
614 }
615
616 for (auto it = m_routes.begin(); it != m_routes.end(); it++)
617 {
618 RipNgRoutingTableEntry* j = it->first;
619
621 {
623 uint16_t maskLen = mask.GetPrefixLength();
624 Ipv6Address entry = j->GetDestNetwork();
625
626 NS_LOG_LOGIC("Searching for route to " << dst << ", mask length " << maskLen);
627
628 if (mask.IsMatch(dst, entry))
629 {
630 NS_LOG_LOGIC("Found global network route " << j << ", mask length " << maskLen);
631
632 /* if interface is given, check the route will output on this interface */
633 if (!interface || interface == m_ipv6->GetNetDevice(j->GetInterface()))
634 {
635 if (maskLen < longestMask)
636 {
637 NS_LOG_LOGIC("Previous match longer, skipping");
638 continue;
639 }
640
641 longestMask = maskLen;
642
643 Ipv6RoutingTableEntry* route = j;
644 uint32_t interfaceIdx = route->GetInterface();
645 rtentry = Create<Ipv6Route>();
646
647 if (setSource)
648 {
649 // GetGateway().IsAny() means that the destination is reachable without a
650 // gateway (is on-link). GetDest().IsAny() means that the route is the
651 // default route. Having both true is very strange, but possible.
652 // If the RT entry is specific for a destination, use that as a hint for the
653 // source address to be used. Else, use the destination or the prefix to be
654 // used stated in the RT entry.
655 if (!route->GetDest().IsAny())
656 {
657 rtentry->SetSource(
658 m_ipv6->SourceAddressSelection(interfaceIdx, route->GetDest()));
659 }
660 else
661 {
662 rtentry->SetSource(m_ipv6->SourceAddressSelection(
663 interfaceIdx,
664 route->GetPrefixToUse().IsAny() ? dst : route->GetPrefixToUse()));
665 }
666 }
667
668 rtentry->SetDestination(route->GetDest());
669 rtentry->SetGateway(route->GetGateway());
670 rtentry->SetOutputDevice(m_ipv6->GetNetDevice(interfaceIdx));
671 }
672 }
673 }
674 }
675
676 if (rtentry)
677 {
678 NS_LOG_LOGIC("Matching route via " << rtentry->GetDestination() << " (through "
679 << rtentry->GetGateway() << ") at the end");
680 }
681 return rtentry;
682}
683
684void
686 Ipv6Prefix networkPrefix,
687 Ipv6Address nextHop,
688 uint32_t interface,
689 Ipv6Address prefixToUse)
690{
691 NS_LOG_FUNCTION(this << network << networkPrefix << nextHop << interface << prefixToUse);
692
693 if (nextHop.IsLinkLocal())
694 {
695 NS_LOG_WARN("Ripng::AddNetworkRouteTo - Next hop should be link-local");
696 }
697
698 auto route =
699 new RipNgRoutingTableEntry(network, networkPrefix, nextHop, interface, prefixToUse);
700 route->SetRouteMetric(1);
701 route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
702 route->SetRouteChanged(true);
703
704 m_routes.emplace_back(route, EventId());
705}
706
707void
708RipNg::AddNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
709{
710 NS_LOG_FUNCTION(this << network << networkPrefix << interface);
711
712 auto route = new RipNgRoutingTableEntry(network, networkPrefix, interface);
713 route->SetRouteMetric(1);
714 route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
715 route->SetRouteChanged(true);
716
717 m_routes.emplace_back(route, EventId());
718}
719
720void
722{
723 NS_LOG_FUNCTION(this << *route);
724
725 for (auto it = m_routes.begin(); it != m_routes.end(); it++)
726 {
727 if (it->first == route)
728 {
731 route->SetRouteChanged(true);
732 if (it->second.IsPending())
733 {
734 it->second.Cancel();
735 }
736 it->second =
738 return;
739 }
740 }
741 NS_ABORT_MSG("Ripng::InvalidateRoute - cannot find the route to update");
742}
743
744void
746{
747 NS_LOG_FUNCTION(this << *route);
748
749 for (auto it = m_routes.begin(); it != m_routes.end(); it++)
750 {
751 if (it->first == route)
752 {
753 delete route;
754 m_routes.erase(it);
755 return;
756 }
757 }
758 NS_ABORT_MSG("Ripng::DeleteRoute - cannot find the route to delete");
759}
760
761void
763{
764 NS_LOG_FUNCTION(this << socket);
765
766 Address sender;
767 Ptr<Packet> packet = socket->RecvFrom(sender);
769 NS_LOG_INFO("Received " << *packet << " from " << senderAddr);
770
771 Ipv6Address senderAddress = senderAddr.GetIpv6();
772 uint16_t senderPort = senderAddr.GetPort();
773
774 Ipv6PacketInfoTag interfaceInfo;
775 if (!packet->RemovePacketTag(interfaceInfo))
776 {
777 NS_ABORT_MSG("No incoming interface on RIPng message, aborting.");
778 }
779 uint32_t incomingIf = interfaceInfo.GetRecvIf();
780 Ptr<Node> node = this->GetObject<Node>();
781 Ptr<NetDevice> dev = node->GetDevice(incomingIf);
782 uint32_t ipInterfaceIndex = m_ipv6->GetInterfaceForDevice(dev);
783
784 SocketIpv6HopLimitTag hoplimitTag;
785 if (!packet->RemovePacketTag(hoplimitTag))
786 {
787 NS_ABORT_MSG("No incoming Hop Count on RIPng message, aborting.");
788 }
789 uint8_t hopLimit = hoplimitTag.GetHopLimit();
790
791 int32_t interfaceForAddress = m_ipv6->GetInterfaceForAddress(senderAddress);
792 if (interfaceForAddress != -1)
793 {
794 NS_LOG_LOGIC("Ignoring a packet sent by myself.");
795 return;
796 }
797
798 RipNgHeader hdr;
799 packet->RemoveHeader(hdr);
800
802 {
803 HandleResponses(hdr, senderAddress, ipInterfaceIndex, hopLimit);
804 }
805 else if (hdr.GetCommand() == RipNgHeader::REQUEST)
806 {
807 HandleRequests(hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
808 }
809 else
810 {
811 NS_LOG_LOGIC("Ignoring message with unknown command: " << int(hdr.GetCommand()));
812 }
813}
814
815void
817 Ipv6Address senderAddress,
818 uint16_t senderPort,
819 uint32_t incomingInterface,
820 uint8_t hopLimit)
821{
822 NS_LOG_FUNCTION(this << senderAddress << int(senderPort) << incomingInterface << int(hopLimit)
823 << requestHdr);
824
825 std::list<RipNgRte> rtes = requestHdr.GetRteList();
826
827 if (rtes.empty())
828 {
829 return;
830 }
831
832 // check if it's a request for the full table from a neighbor
833 if (rtes.size() == 1 && senderAddress.IsLinkLocal())
834 {
835 if (rtes.begin()->GetPrefix() == Ipv6Address::GetAny() &&
836 rtes.begin()->GetPrefixLen() == 0 && rtes.begin()->GetRouteMetric() == m_linkDown)
837 {
838 // Output whole thing. Use Split Horizon
839 if (m_interfaceExclusions.find(incomingInterface) == m_interfaceExclusions.end())
840 {
841 // we use one of the sending sockets, as they're bound to the right interface
842 // and the local address might be used on different interfaces.
843 Ptr<Socket> sendingSocket;
844 for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end();
845 iter++)
846 {
847 if (iter->second == incomingInterface)
848 {
849 sendingSocket = iter->first;
850 }
851 }
852 NS_ASSERT_MSG(sendingSocket,
853 "HandleRequest - Impossible to find a socket to send the reply");
854
855 uint16_t mtu = m_ipv6->GetMtu(incomingInterface);
856 uint16_t maxRte =
860
863 p->RemovePacketTag(tag);
864 tag.SetHopLimit(255);
865 p->AddPacketTag(tag);
866
867 RipNgHeader hdr;
869
870 for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
871 {
872 bool splitHorizoning = (rtIter->first->GetInterface() == incomingInterface);
873
874 Ipv6InterfaceAddress rtDestAddr =
875 Ipv6InterfaceAddress(rtIter->first->GetDestNetwork(),
876 rtIter->first->GetDestNetworkPrefix());
877
878 bool isGlobal = (rtDestAddr.GetScope() == Ipv6InterfaceAddress::GLOBAL);
879 bool isDefaultRoute =
880 ((rtIter->first->GetDestNetwork() == Ipv6Address::GetAny()) &&
881 (rtIter->first->GetDestNetworkPrefix() == Ipv6Prefix::GetZero()) &&
882 (rtIter->first->GetInterface() != incomingInterface));
883
884 if ((isGlobal || isDefaultRoute) &&
885 (rtIter->first->GetRouteStatus() == RipNgRoutingTableEntry::RIPNG_VALID))
886 {
887 RipNgRte rte;
888 rte.SetPrefix(rtIter->first->GetDestNetwork());
889 rte.SetPrefixLen(rtIter->first->GetDestNetworkPrefix().GetPrefixLength());
890 if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
891 {
893 }
894 else
895 {
896 rte.SetRouteMetric(rtIter->first->GetRouteMetric());
897 }
898 rte.SetRouteTag(rtIter->first->GetRouteTag());
900 (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
901 {
902 hdr.AddRte(rte);
903 }
904 }
905 if (hdr.GetRteNumber() == maxRte)
906 {
907 p->AddHeader(hdr);
908 NS_LOG_DEBUG("SendTo: " << *p);
909 sendingSocket->SendTo(p, 0, Inet6SocketAddress(senderAddress, RIPNG_PORT));
910 p->RemoveHeader(hdr);
911 hdr.ClearRtes();
912 }
913 }
914 if (hdr.GetRteNumber() > 0)
915 {
916 p->AddHeader(hdr);
917 NS_LOG_DEBUG("SendTo: " << *p);
918 sendingSocket->SendTo(p, 0, Inet6SocketAddress(senderAddress, RIPNG_PORT));
919 }
920 }
921 }
922 }
923 else
924 {
925 // note: we got the request as a single packet, so no check is necessary for MTU limit
926
927 // we use one of the sending sockets, as they're bound to the right interface
928 // and the local address might be used on different interfaces.
929 Ptr<Socket> sendingSocket;
930 if (senderAddress.IsLinkLocal())
931 {
932 for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
933 {
934 if (iter->second == incomingInterface)
935 {
936 sendingSocket = iter->first;
937 }
938 }
939 }
940 else
941 {
942 sendingSocket = m_multicastRecvSocket;
943 }
944
947 p->RemovePacketTag(tag);
948 tag.SetHopLimit(255);
949 p->AddPacketTag(tag);
950
951 RipNgHeader hdr;
953
954 for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
955 {
956 bool found = false;
957 for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
958 {
959 Ipv6InterfaceAddress rtDestAddr =
960 Ipv6InterfaceAddress(rtIter->first->GetDestNetwork(),
961 rtIter->first->GetDestNetworkPrefix());
962 if ((rtDestAddr.GetScope() == Ipv6InterfaceAddress::GLOBAL) &&
963 (rtIter->first->GetRouteStatus() == RipNgRoutingTableEntry::RIPNG_VALID))
964 {
965 Ipv6Address requestedAddress = iter->GetPrefix();
966 requestedAddress.CombinePrefix(Ipv6Prefix(iter->GetPrefixLen()));
967 Ipv6Address rtAddress = rtIter->first->GetDestNetwork();
968 rtAddress.CombinePrefix(rtIter->first->GetDestNetworkPrefix());
969
970 if (requestedAddress == rtAddress)
971 {
972 iter->SetRouteMetric(rtIter->first->GetRouteMetric());
973 iter->SetRouteTag(rtIter->first->GetRouteTag());
974 hdr.AddRte(*iter);
975 found = true;
976 break;
977 }
978 }
979 }
980 if (!found)
981 {
982 iter->SetRouteMetric(m_linkDown);
983 iter->SetRouteTag(0);
984 hdr.AddRte(*iter);
985 }
986 }
987 p->AddHeader(hdr);
988 NS_LOG_DEBUG("SendTo: " << *p);
989 sendingSocket->SendTo(p, 0, Inet6SocketAddress(senderAddress, senderPort));
990 }
991}
992
993void
995 Ipv6Address senderAddress,
996 uint32_t incomingInterface,
997 uint8_t hopLimit)
998{
999 NS_LOG_FUNCTION(this << senderAddress << incomingInterface << int(hopLimit) << hdr);
1000
1001 if (m_interfaceExclusions.find(incomingInterface) != m_interfaceExclusions.end())
1002 {
1004 "Ignoring an update message from an excluded interface: " << incomingInterface);
1005 return;
1006 }
1007
1008 if (!senderAddress.IsLinkLocal())
1009 {
1010 NS_LOG_LOGIC("Ignoring an update message from a non-link-local source: " << senderAddress);
1011 return;
1012 }
1013
1014 if (hopLimit != 255)
1015 {
1016 NS_LOG_LOGIC("Ignoring an update message with suspicious hop count: " << int(hopLimit));
1017 return;
1018 }
1019
1020 std::list<RipNgRte> rtes = hdr.GetRteList();
1021
1022 // validate the RTEs before processing
1023 for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
1024 {
1025 if (iter->GetRouteMetric() == 0 || iter->GetRouteMetric() > m_linkDown)
1026 {
1027 NS_LOG_LOGIC("Ignoring an update message with malformed metric: "
1028 << int(iter->GetRouteMetric()));
1029 return;
1030 }
1031 if (iter->GetPrefixLen() > 128)
1032 {
1033 NS_LOG_LOGIC("Ignoring an update message with malformed prefix length: "
1034 << int(iter->GetPrefixLen()));
1035 return;
1036 }
1037 if (iter->GetPrefix().IsLocalhost() || iter->GetPrefix().IsLinkLocal() ||
1038 iter->GetPrefix().IsMulticast())
1039 {
1040 NS_LOG_LOGIC("Ignoring an update message with wrong prefixes: " << iter->GetPrefix());
1041 return;
1042 }
1043 }
1044
1045 bool changed = false;
1046
1047 for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
1048 {
1049 Ipv6Prefix rtePrefix = Ipv6Prefix(iter->GetPrefixLen());
1050 Ipv6Address rteAddr = iter->GetPrefix().CombinePrefix(rtePrefix);
1051
1052 NS_LOG_LOGIC("Processing RTE " << *iter);
1053
1054 uint8_t interfaceMetric = 1;
1055 if (m_interfaceMetrics.find(incomingInterface) != m_interfaceMetrics.end())
1056 {
1057 interfaceMetric = m_interfaceMetrics[incomingInterface];
1058 }
1059 uint16_t rteMetric = iter->GetRouteMetric() + interfaceMetric;
1060 if (rteMetric > m_linkDown)
1061 {
1062 rteMetric = m_linkDown;
1063 }
1064 RoutesI it;
1065 bool found = false;
1066 for (it = m_routes.begin(); it != m_routes.end(); it++)
1067 {
1068 if (it->first->GetDestNetwork() == rteAddr &&
1069 it->first->GetDestNetworkPrefix() == rtePrefix)
1070 {
1071 found = true;
1072 if (rteMetric < it->first->GetRouteMetric())
1073 {
1074 if (senderAddress != it->first->GetGateway())
1075 {
1076 auto route = new RipNgRoutingTableEntry(rteAddr,
1077 rtePrefix,
1078 senderAddress,
1079 incomingInterface,
1081 delete it->first;
1082 it->first = route;
1083 }
1084 it->first->SetRouteMetric(rteMetric);
1085 it->first->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1086 it->first->SetRouteTag(iter->GetRouteTag());
1087 it->first->SetRouteChanged(true);
1088 it->second.Cancel();
1091 this,
1092 it->first);
1093 changed = true;
1094 }
1095 else if (rteMetric == it->first->GetRouteMetric())
1096 {
1097 if (senderAddress == it->first->GetGateway())
1098 {
1099 it->second.Cancel();
1102 this,
1103 it->first);
1104 }
1105 else
1106 {
1107 if (Simulator::GetDelayLeft(it->second) < m_timeoutDelay / 2)
1108 {
1109 auto route = new RipNgRoutingTableEntry(rteAddr,
1110 rtePrefix,
1111 senderAddress,
1112 incomingInterface,
1114 route->SetRouteMetric(rteMetric);
1115 route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1116 route->SetRouteTag(iter->GetRouteTag());
1117 route->SetRouteChanged(true);
1118 delete it->first;
1119 it->first = route;
1120 it->second.Cancel();
1123 this,
1124 route);
1125 changed = true;
1126 }
1127 }
1128 }
1129 else if (rteMetric > it->first->GetRouteMetric() &&
1130 senderAddress == it->first->GetGateway())
1131 {
1132 it->second.Cancel();
1133 if (rteMetric < m_linkDown)
1134 {
1135 it->first->SetRouteMetric(rteMetric);
1136 it->first->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1137 it->first->SetRouteTag(iter->GetRouteTag());
1138 it->first->SetRouteChanged(true);
1139 it->second.Cancel();
1142 this,
1143 it->first);
1144 }
1145 else
1146 {
1147 InvalidateRoute(it->first);
1148 }
1149 changed = true;
1150 }
1151 }
1152 }
1153 if (!found && rteMetric != m_linkDown)
1154 {
1155 NS_LOG_LOGIC("Received a RTE with new route, adding.");
1156
1157 auto route = new RipNgRoutingTableEntry(rteAddr,
1158 rtePrefix,
1159 senderAddress,
1160 incomingInterface,
1162 route->SetRouteMetric(rteMetric);
1163 route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1164 route->SetRouteChanged(true);
1165 m_routes.emplace_front(route, EventId());
1166 EventId invalidateEvent =
1168 (m_routes.begin())->second = invalidateEvent;
1169 changed = true;
1170 }
1171 }
1172
1173 if (changed)
1174 {
1176 }
1177}
1178
1179void
1181{
1182 NS_LOG_FUNCTION(this << (periodic ? " periodic" : " triggered"));
1183
1184 for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
1185 {
1186 uint32_t interface = iter->second;
1187
1188 if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
1189 {
1190 uint16_t mtu = m_ipv6->GetMtu(interface);
1191 uint16_t maxRte =
1195
1198 tag.SetHopLimit(255);
1199 p->AddPacketTag(tag);
1200
1201 RipNgHeader hdr;
1203
1204 for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
1205 {
1206 bool splitHorizoning = (rtIter->first->GetInterface() == interface);
1207 Ipv6InterfaceAddress rtDestAddr =
1208 Ipv6InterfaceAddress(rtIter->first->GetDestNetwork(),
1209 rtIter->first->GetDestNetworkPrefix());
1210
1211 NS_LOG_DEBUG("Processing RT " << rtDestAddr << " "
1212 << int(rtIter->first->IsRouteChanged()));
1213
1214 bool isGlobal = (rtDestAddr.GetScope() == Ipv6InterfaceAddress::GLOBAL);
1215 bool isDefaultRoute =
1216 ((rtIter->first->GetDestNetwork() == Ipv6Address::GetAny()) &&
1217 (rtIter->first->GetDestNetworkPrefix() == Ipv6Prefix::GetZero()) &&
1218 (rtIter->first->GetInterface() != interface));
1219
1220 if ((isGlobal || isDefaultRoute) && (periodic || rtIter->first->IsRouteChanged()))
1221 {
1222 RipNgRte rte;
1223 rte.SetPrefix(rtIter->first->GetDestNetwork());
1224 rte.SetPrefixLen(rtIter->first->GetDestNetworkPrefix().GetPrefixLength());
1225 if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
1226 {
1228 }
1229 else
1230 {
1231 rte.SetRouteMetric(rtIter->first->GetRouteMetric());
1232 }
1233 rte.SetRouteTag(rtIter->first->GetRouteTag());
1234 if ((m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning) ||
1236 {
1237 hdr.AddRte(rte);
1238 }
1239 }
1240 if (hdr.GetRteNumber() == maxRte)
1241 {
1242 p->AddHeader(hdr);
1243 NS_LOG_DEBUG("SendTo: " << *p);
1244 iter->first->SendTo(p, 0, Inet6SocketAddress(RIPNG_ALL_NODE, RIPNG_PORT));
1245 p->RemoveHeader(hdr);
1246 hdr.ClearRtes();
1247 }
1248 }
1249 if (hdr.GetRteNumber() > 0)
1250 {
1251 p->AddHeader(hdr);
1252 NS_LOG_DEBUG("SendTo: " << *p);
1253 iter->first->SendTo(p, 0, Inet6SocketAddress(RIPNG_ALL_NODE, RIPNG_PORT));
1254 }
1255 }
1256 }
1257 for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
1258 {
1259 rtIter->first->SetRouteChanged(false);
1260 }
1261}
1262
1263void
1265{
1266 NS_LOG_FUNCTION(this);
1267
1269 {
1270 NS_LOG_LOGIC("Skipping Triggered Update due to cooldown");
1271 return;
1272 }
1273
1274 // DoSendRouteUpdate (false);
1275
1276 // note: The RFC states:
1277 // After a triggered
1278 // update is sent, a timer should be set for a random interval between 1
1279 // and 5 seconds. If other changes that would trigger updates occur
1280 // before the timer expires, a single update is triggered when the timer
1281 // expires. The timer is then reset to another random value between 1
1282 // and 5 seconds. Triggered updates may be suppressed if a regular
1283 // update is due by the time the triggered update would be sent.
1284 // Here we rely on this:
1285 // When an update occurs (either Triggered or Periodic) the "IsChanged ()"
1286 // route field will be cleared.
1287 // Hence, the following Triggered Update will be fired, but will not send
1288 // any route update.
1289
1293}
1294
1295void
1311
1312std::set<uint32_t>
1317
1318void
1319RipNg::SetInterfaceExclusions(std::set<uint32_t> exceptions)
1320{
1321 NS_LOG_FUNCTION(this);
1322
1323 m_interfaceExclusions = exceptions;
1324}
1325
1326uint8_t
1328{
1329 NS_LOG_FUNCTION(this << interface);
1330
1331 auto iter = m_interfaceMetrics.find(interface);
1332 if (iter != m_interfaceMetrics.end())
1333 {
1334 return iter->second;
1335 }
1336 return 1;
1337}
1338
1339void
1340RipNg::SetInterfaceMetric(uint32_t interface, uint8_t metric)
1341{
1342 NS_LOG_FUNCTION(this << interface << int(metric));
1343
1344 if (metric < m_linkDown)
1345 {
1346 m_interfaceMetrics[interface] = metric;
1347 }
1348}
1349
1350void
1352{
1353 NS_LOG_FUNCTION(this);
1354
1357 p->RemovePacketTag(tag);
1358 tag.SetHopLimit(255);
1359 p->AddPacketTag(tag);
1360
1361 RipNgHeader hdr;
1363
1364 RipNgRte rte;
1366 rte.SetPrefixLen(0);
1368
1369 hdr.AddRte(rte);
1370 p->AddHeader(hdr);
1371
1372 for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
1373 {
1374 uint32_t interface = iter->second;
1375
1376 if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
1377 {
1378 NS_LOG_DEBUG("SendTo: " << *p);
1379 iter->first->SendTo(p, 0, Inet6SocketAddress(RIPNG_ALL_NODE, RIPNG_PORT));
1380 }
1381 }
1382}
1383
1384void
1386{
1387 NS_LOG_FUNCTION(this << interface);
1388
1391 nextHop,
1392 interface,
1393 Ipv6Address("::"));
1394}
1395
1396/*
1397 * RipNgRoutingTableEntry
1398 */
1399
1401 : m_tag(0),
1402 m_metric(0),
1403 m_status(RIPNG_INVALID),
1404 m_changed(false)
1405{
1406}
1407
1409 Ipv6Prefix networkPrefix,
1410 Ipv6Address nextHop,
1411 uint32_t interface,
1412 Ipv6Address prefixToUse)
1413 : Ipv6RoutingTableEntry(RipNgRoutingTableEntry::CreateNetworkRouteTo(network,
1414 networkPrefix,
1415 nextHop,
1416 interface,
1417 prefixToUse)),
1418 m_tag(0),
1419 m_metric(0),
1420 m_status(RIPNG_INVALID),
1421 m_changed(false)
1422{
1423}
1424
1426 Ipv6Prefix networkPrefix,
1427 uint32_t interface)
1429 Ipv6RoutingTableEntry::CreateNetworkRouteTo(network, networkPrefix, interface)),
1430 m_tag(0),
1431 m_metric(0),
1432 m_status(RIPNG_INVALID),
1433 m_changed(false)
1434{
1435}
1436
1440
1441void
1443{
1444 if (m_tag != routeTag)
1445 {
1446 m_tag = routeTag;
1447 m_changed = true;
1448 }
1449}
1450
1451uint16_t
1453{
1454 return m_tag;
1455}
1456
1457void
1459{
1460 if (m_metric != routeMetric)
1461 {
1462 m_metric = routeMetric;
1463 m_changed = true;
1464 }
1465}
1466
1467uint8_t
1469{
1470 return m_metric;
1471}
1472
1473void
1475{
1476 if (m_status != status)
1477 {
1478 m_status = status;
1479 m_changed = true;
1480 }
1481}
1482
1485{
1486 return m_status;
1487}
1488
1489void
1491{
1492 m_changed = changed;
1493}
1494
1495bool
1497{
1498 return m_changed;
1499}
1500
1501std::ostream&
1502operator<<(std::ostream& os, const RipNgRoutingTableEntry& rte)
1503{
1504 os << static_cast<const Ipv6RoutingTableEntry&>(rte);
1505 os << ", metric: " << int(rte.GetRouteMetric()) << ", tag: " << int(rte.GetRouteTag());
1506
1507 return os;
1508}
1509
1510} // namespace ns3
a polymophic address class
Definition address.h:90
bool IsNull() const
Check for null implementation.
Definition callback.h:555
Hold variables of type enum.
Definition enum.h:52
An identifier for simulation events.
Definition event-id.h:45
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition event-id.cc:44
bool IsPending() const
This method is syntactic sugar for !IsExpired().
Definition event-id.cc:65
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
uint16_t GetPort() const
Get the port.
Ipv6Address GetIpv6() const
Get the IPv6 address.
Describes an IPv6 address.
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
bool IsLinkLocalMulticast() const
If the IPv6 address is link-local multicast (ff02::/16).
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
bool IsAny() const
If the IPv6 address is the "Any" address.
Ipv6Address CombinePrefix(const Ipv6Prefix &prefix) const
Combine this address with a prefix.
Packet header for IPv6.
Definition ipv6-header.h:24
Ipv6Address GetDestination() const
Get the "Destination address" field.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Ipv6Address GetSource() const
Get the "Source address" field.
virtual Ipv6InterfaceAddress GetAddress(uint32_t interface, uint32_t addressIndex) const =0
Get IPv6 address on specified IPv6 interface.
virtual Ipv6Address SourceAddressSelection(uint32_t interface, Ipv6Address dest)=0
Choose the source address to use with destination address.
virtual uint16_t GetMtu(uint32_t interface) const =0
Get MTU for the specified IPv6 interface.
virtual int32_t GetInterfaceForDevice(Ptr< const NetDevice > device) const =0
Get the interface index of the specified NetDevice.
virtual uint32_t GetNInterfaces() const =0
Get number of interfaces.
virtual bool IsUp(uint32_t interface) const =0
If the specified interface index is in "up" state.
virtual bool IsForwarding(uint32_t interface) const =0
If the specified IPv6 interface has forwarding enabled.
virtual void SetForwarding(uint32_t interface, bool val)=0
Set forwarding on specified IPv6 interface.
virtual int32_t GetInterfaceForAddress(Ipv6Address address) const =0
Return the interface number of the interface that has been assigned the specified IP address.
virtual uint32_t GetNAddresses(uint32_t interface) const =0
Get number of addresses on specified IPv6 interface.
virtual Ptr< NetDevice > GetNetDevice(uint32_t interface)=0
Get the NetDevice of the specified interface number.
IPv6 address associated with an interface.
Ipv6InterfaceAddress::Scope_e GetScope() const
Get address scope.
@ LINKLOCAL
Link-local address (fe80::/64)
@ GLOBAL
Global address (2000::/3)
This class implements a tag that carries socket ancillary data to the socket interface.
uint32_t GetRecvIf() const
Get the tag's receiving interface.
Describes an IPv6 prefix.
uint8_t GetPrefixLength() const
Get prefix length.
static Ipv6Prefix GetZero()
Get the zero prefix ( /0).
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
Abstract base class for IPv6 routing protocols.
A record of an IPv6 route.
Ipv6Address GetDest() const
Get the destination.
Ipv6Address GetDestNetwork() const
Get the destination network.
Ipv6Address GetPrefixToUse() const
Get the prefix to use (for multihomed link).
bool IsHost() const
Is the route entry correspond to a host ?
uint32_t GetInterface() const
Get the interface index.
Ipv6Prefix GetDestNetworkPrefix() const
Get the destination prefix.
Ipv6Address GetGateway() const
Get the gateway.
bool IsGateway() const
Is it the gateway ?
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
Definition names.cc:818
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.
RipNgHeader - see RFC 2080
void SetCommand(Command_e command)
Set the command.
void ClearRtes()
Clear all the RTEs from the header.
uint16_t GetRteNumber() const
Get the number of RTE included in the message.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Command_e GetCommand() const
Get the command.
std::list< RipNgRte > GetRteList() const
Get the list of the RTEs included in the message.
void AddRte(RipNgRte rte)
Add a RTE to the message.
RIPng Routing Protocol, defined in RFC 2080 .
Definition ripng.h:167
Ptr< Socket > m_multicastRecvSocket
multicast receive socket
Definition ripng.h:417
void NotifyInterfaceUp(uint32_t interface) override
Notify when specified interface goes UP.
Definition ripng.cc:283
void NotifyAddAddress(uint32_t interface, Ipv6InterfaceAddress address) override
Notify when specified interface add an address.
Definition ripng.cc:393
void NotifyAddRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero()) override
Notify a new route.
Definition ripng.cc:455
void DoSendRouteUpdate(bool periodic)
Send Routing Updates on all interfaces.
Definition ripng.cc:1180
Time m_startupDelay
Random delay before protocol startup.
Definition ripng.h:399
void DoDispose() override
Dispose this object.
Definition ripng.cc:564
SplitHorizonType_e m_splitHorizonStrategy
Split Horizon strategy.
Definition ripng.h:427
@ SPLIT_HORIZON
Split Horizon.
Definition ripng.h:215
@ POISON_REVERSE
Poison Reverse Split Horizon.
Definition ripng.h:216
@ NO_SPLIT_HORIZON
No Split Horizon.
Definition ripng.h:214
EventId m_nextTriggeredUpdate
Next Triggered Update event.
Definition ripng.h:420
std::list< std::pair< RipNgRoutingTableEntry *, EventId > >::iterator RoutesI
Iterator for container for the network routes.
Definition ripng.h:285
~RipNg() override
Definition ripng.cc:46
void NotifyRemoveAddress(uint32_t interface, Ipv6InterfaceAddress address) override
Notify when specified interface add an address.
Definition ripng.cc:419
Time m_minTriggeredUpdateDelay
Min cooldown delay after a Triggered Update.
Definition ripng.h:400
void SetInterfaceExclusions(std::set< uint32_t > exceptions)
Set the set of interface excluded from the protocol.
Definition ripng.cc:1319
Ptr< Ipv6Route > RouteOutput(Ptr< Packet > p, const Ipv6Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr) override
Query routing cache for an existing route, for an outbound packet.
Definition ripng.cc:189
EventId m_nextUnsolicitedUpdate
Next Unsolicited Update event.
Definition ripng.h:419
uint8_t m_linkDown
Link down value.
Definition ripng.h:430
Time m_maxTriggeredUpdateDelay
Max cooldown delay after a Triggered Update.
Definition ripng.h:401
void DoInitialize() override
Start protocol operation.
Definition ripng.cc:116
bool m_initialized
flag to allow socket's late-creation.
Definition ripng.h:429
SocketList m_unicastSocketList
list of sockets for unicast messages (socket, interface index)
Definition ripng.h:416
uint8_t GetInterfaceMetric(uint32_t interface) const
Get the metric for an interface.
Definition ripng.cc:1327
bool RouteInput(Ptr< const Packet > p, const Ipv6Header &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)
Definition ripng.cc:223
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
Definition ripng.h:402
std::set< uint32_t > m_interfaceExclusions
Set of excluded interfaces.
Definition ripng.h:424
void SetInterfaceMetric(uint32_t interface, uint8_t metric)
Set the metric for an interface.
Definition ripng.cc:1340
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition ripng.cc:107
void DeleteRoute(RipNgRoutingTableEntry *route)
Delete a route.
Definition ripng.cc:745
void AddNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
Add route to network.
Definition ripng.cc:685
Time m_garbageCollectionDelay
Delay before deleting an INVALID route.
Definition ripng.h:404
std::map< uint32_t, uint8_t > m_interfaceMetrics
Map of interface metrics.
Definition ripng.h:425
void SendRouteRequest()
Send Routing Request on all interfaces.
Definition ripng.cc:1351
void NotifyInterfaceDown(uint32_t interface) override
Notify when specified interface goes DOWN.
Definition ripng.cc:361
Ptr< Ipv6 > m_ipv6
IPv6 reference.
Definition ripng.h:398
Routes m_routes
the forwarding table for network.
Definition ripng.h:397
std::set< uint32_t > GetInterfaceExclusions() const
Get the set of interface excluded from the protocol.
Definition ripng.cc:1313
void SendTriggeredRouteUpdate()
Send Triggered Routing Updates on all interfaces.
Definition ripng.cc:1264
void HandleRequests(RipNgHeader hdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIPng requests.
Definition ripng.cc:816
Ptr< UniformRandomVariable > m_rng
Rng stream.
Definition ripng.h:422
void HandleResponses(RipNgHeader hdr, Ipv6Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIPng responses.
Definition ripng.cc:994
void NotifyRemoveRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero()) override
Notify route removing.
Definition ripng.cc:466
static TypeId GetTypeId()
Get the type ID.
Definition ripng.cc:51
void InvalidateRoute(RipNgRoutingTableEntry *route)
Invalidate a route.
Definition ripng.cc:721
void SetIpv6(Ptr< Ipv6 > ipv6) override
Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol.
Definition ripng.cc:477
void Receive(Ptr< Socket > socket)
Receive RIPng packets.
Definition ripng.cc:762
void AddDefaultRouteTo(Ipv6Address nextHop, uint32_t interface)
Add a default route to the router through the nextHop located on interface.
Definition ripng.cc:1385
Time m_timeoutDelay
Delay before invalidating a route.
Definition ripng.h:403
void SendUnsolicitedRouteUpdate()
Send Unsolicited Routing Updates on all interfaces.
Definition ripng.cc:1296
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
Definition ripng.cc:499
Ptr< Ipv6Route > Lookup(Ipv6Address dest, bool setSource, Ptr< NetDevice >=nullptr)
Lookup in the forwarding table for destination.
Definition ripng.cc:594
RipNg Routing Table Entry.
Definition ripng.h:54
bool IsRouteChanged() const
Get the route changed status.
Definition ripng.cc:1496
RipNgRoutingTableEntry()
Definition ripng.cc:1400
uint16_t GetRouteTag() const
Get the route tag.
Definition ripng.cc:1452
bool m_changed
route has been updated
Definition ripng.h:149
uint16_t m_tag
route tag
Definition ripng.h:146
void SetRouteTag(uint16_t routeTag)
Set the route tag.
Definition ripng.cc:1442
uint8_t GetRouteMetric() const
Get the route metric.
Definition ripng.cc:1468
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
Definition ripng.cc:1458
uint8_t m_metric
route metric
Definition ripng.h:147
Status_e m_status
route status
Definition ripng.h:148
Status_e GetRouteStatus() const
Get the route status.
Definition ripng.cc:1484
void SetRouteChanged(bool changed)
Set the route as changed.
Definition ripng.cc:1490
~RipNgRoutingTableEntry() override
Definition ripng.cc:1437
Status_e
Route status.
Definition ripng.h:60
@ RIPNG_INVALID
Definition ripng.h:62
@ RIPNG_VALID
Definition ripng.h:61
void SetRouteStatus(Status_e status)
Set the route status.
Definition ripng.cc:1474
RipNg Routing Table Entry (RTE) - see RFC 2080
void SetPrefix(Ipv6Address prefix)
Set the prefix.
void SetPrefixLen(uint8_t prefixLen)
Set the prefix length.
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
void SetRouteTag(uint16_t routeTag)
Set the route tag.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition simulator.h:560
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition simulator.cc:206
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition socket.cc:343
void SetRecvCallback(Callback< void, Ptr< Socket > > receivedData)
Notify application when new data is available to be read.
Definition socket.cc:117
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
virtual int Close()=0
Close a socket.
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
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
void SetIpv6RecvHopLimit(bool ipv6RecvHopLimit)
Tells a socket to pass information about IPv6 Hop Limit up the stack.
Definition socket.cc:537
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition socket.h:1161
uint8_t GetHopLimit() const
Get the tag's Hop Limit.
Definition socket.cc:663
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition socket.cc:657
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
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition nstime.h:392
Unit
The unit to use to interpret a number representing time.
Definition nstime.h:100
AttributeValue implementation for Time.
Definition nstime.h:1395
a unique identifier for an interface.
Definition type-id.h:48
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition type-id.cc:872
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition type-id.cc:1001
Packet header for UDP packets.
Definition udp-header.h:30
uint32_t GetSerializedSize() const override
Hold an unsigned integer type.
Definition uinteger.h:34
#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 > MakeEnumAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition enum.h:221
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition nstime.h:1396
Ptr< const AttributeChecker > MakeTimeChecker()
Helper to make an unbounded Time checker.
Definition nstime.h:1416
Ptr< const AttributeChecker > MakeUintegerChecker()
Definition uinteger.h:85
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition uinteger.h:35
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition abort.h:38
#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_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition log.h:264
Ptr< T > CreateObject(Args &&... args)
Create an object by type, with varying number of constructor parameters.
Definition object.h:619
#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 Seconds(double value)
Construct a Time in the indicated unit.
Definition nstime.h:1308
Definition first.py:1
Every class exported by the ns3 library is enclosed in the ns3 namespace.
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
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition angles.cc:148
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition enum.h:179
#define RIPNG_ALL_NODE
Definition ripng.cc:28
#define RIPNG_PORT
Definition ripng.cc:29