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