A Discrete-Event Network Simulator
API
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 
41 namespace 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 
60 TypeId
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).",
75  TimeValue(Seconds(1)),
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.",
90  TimeValue(Seconds(1)),
93  .AddAttribute("MaxTriggeredCooldown",
94  "Max cooldown delay after a Triggered Update.",
95  TimeValue(Seconds(5)),
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 
116 int64_t
117 RipNg::AssignStreams(int64_t stream)
118 {
119  NS_LOG_FUNCTION(this << stream);
120 
121  m_rng->SetStream(stream);
122  return 1;
123 }
124 
125 void
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);
157  socket->BindToNetDevice(m_ipv6->GetNetDevice(i));
158  int ret = socket->Bind(local);
159  NS_ASSERT_MSG(ret == 0, "Bind unsuccessful");
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>();
179  m_multicastRecvSocket->Bind(local);
183  }
184 
185  if (addedGlobal)
186  {
190  }
191 
192  delay = Seconds(m_rng->GetValue(0.01, m_startupDelay.GetSeconds()));
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  {
227  sockerr = Socket::ERROR_NOROUTETOHOST;
228  }
229  return rtentry;
230 }
231 
232 bool
234  const Ipv6Header& header,
239  ErrorCallback ecb)
240 {
241  NS_LOG_FUNCTION(this << p << header << header.GetSource() << header.GetDestination() << idev);
242 
243  NS_ASSERT(m_ipv6);
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 
292 void
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);
343  socket->BindToNetDevice(m_ipv6->GetNetDevice(i));
344  socket->Bind(local);
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>();
363  m_multicastRecvSocket->Bind(local);
367  }
368 }
369 
370 void
371 RipNg::NotifyInterfaceDown(uint32_t interface)
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 
402 void
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 
428 void
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 
464 void
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 
475 void
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 
486 void
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 
508 void
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() << "/"
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 
573 void
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 
604 RipNg::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  {
632  Ipv6Prefix mask = j->GetDestNetworkPrefix();
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 
693 void
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 
707  RipNgRoutingTableEntry* route =
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 
716 void
717 RipNg::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 
729 void
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  {
739  route->SetRouteMetric(m_linkDown);
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 
753 void
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 
770 void
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 
810  if (hdr.GetCommand() == RipNgHeader::RESPONSE)
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 
824 void
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 
1004 void
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  {
1014  NS_LOG_LOGIC(
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();
1101  it->second = Simulator::Schedule(m_timeoutDelay,
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();
1112  it->second = Simulator::Schedule(m_timeoutDelay,
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();
1134  it->second = Simulator::Schedule(m_timeoutDelay,
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();
1153  it->second = Simulator::Schedule(m_timeoutDelay,
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 
1170  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry(rteAddr,
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 
1192 void
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 
1279 void
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 
1311 void
1313 {
1314  NS_LOG_FUNCTION(this);
1315 
1317  {
1319  }
1320 
1321  DoSendRouteUpdate(true);
1322 
1323  Time delay =
1326 }
1327 
1328 std::set<uint32_t>
1330 {
1331  return m_interfaceExclusions;
1332 }
1333 
1334 void
1335 RipNg::SetInterfaceExclusions(std::set<uint32_t> exceptions)
1336 {
1337  NS_LOG_FUNCTION(this);
1338 
1339  m_interfaceExclusions = exceptions;
1340 }
1341 
1342 uint8_t
1343 RipNg::GetInterfaceMetric(uint32_t interface) const
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 
1355 void
1356 RipNg::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 
1366 void
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 
1400 void
1401 RipNg::AddDefaultRouteTo(Ipv6Address nextHop, uint32_t interface)
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 
1457 void
1459 {
1460  if (m_tag != routeTag)
1461  {
1462  m_tag = routeTag;
1463  m_changed = true;
1464  }
1465 }
1466 
1467 uint16_t
1469 {
1470  return m_tag;
1471 }
1472 
1473 void
1475 {
1476  if (m_metric != routeMetric)
1477  {
1478  m_metric = routeMetric;
1479  m_changed = true;
1480  }
1481 }
1482 
1483 uint8_t
1485 {
1486  return m_metric;
1487 }
1488 
1489 void
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 
1505 void
1507 {
1508  m_changed = changed;
1509 }
1510 
1511 bool
1513 {
1514  return m_changed;
1515 }
1516 
1517 std::ostream&
1518 operator<<(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
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:152
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:360
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:986
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:979
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
~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
std::map< Ptr< Socket >, uint32_t >::iterator SocketListI
Socket list type iterator.
Definition: ripng.h:421
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
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
std::list< std::pair< RipNgRoutingTableEntry *, EventId > >::iterator RoutesI
Iterator for container for the network routes.
Definition: ripng.h:295
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
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:325
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
virtual Ptr< Packet > RecvFrom(uint32_t maxSize, uint32_t flags, Address &fromAddress)=0
Read a single packet from the socket and retrieve the sender address.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
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)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: enum.h:205
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: nstime.h:1424
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Create an AttributeAccessor for a class data member, or a lone class get functor or set method.
Definition: uinteger.h: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
address
Definition: first.py:40
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
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
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:535
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:129
Definition: second.py:1
#define RIPNG_ALL_NODE
Definition: ripng.cc:38
#define RIPNG_PORT
Definition: ripng.cc:39