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