A Discrete-Event Network Simulator
API
ripng.cc
Go to the documentation of this file.
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2014 Universita' di Firenze, Italy
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19  */
20 
21 #include <iomanip>
22 #include "ripng.h"
23 #include "ns3/log.h"
24 #include "ns3/abort.h"
25 #include "ns3/assert.h"
26 #include "ns3/unused.h"
27 #include "ns3/random-variable-stream.h"
28 #include "ns3/ipv6-route.h"
29 #include "ns3/node.h"
30 #include "ns3/names.h"
31 #include "ns3/ripng-header.h"
32 #include "ns3/udp-header.h"
33 #include "ns3/enum.h"
34 #include "ns3/ipv6-packet-info-tag.h"
35 
36 #define RIPNG_ALL_NODE "ff02::9"
37 #define RIPNG_PORT 521
38 
39 namespace ns3 {
40 
41 NS_LOG_COMPONENT_DEFINE ("RipNg");
42 
44 
46  : m_ipv6 (0), m_splitHorizonStrategy (RipNg::POISON_REVERSE), m_initialized (false)
47 {
48  m_rng = CreateObject<UniformRandomVariable> ();
49 }
50 
52 {
53 }
54 
55 TypeId
57 {
58  static TypeId tid = TypeId ("ns3::RipNg")
60  .AddConstructor<RipNg> ()
61  .AddAttribute ("UnsolicitedRoutingUpdate", "The time between two Unsolicited Routing Updates.",
62  TimeValue (Seconds(30)),
64  MakeTimeChecker ())
65  .AddAttribute ("StartupDelay", "Maximum random delay for protocol startup (send route requests).",
66  TimeValue (Seconds(1)),
68  MakeTimeChecker ())
69  .AddAttribute ("TimeoutDelay", "The delay to invalidate a route.",
70  TimeValue (Seconds(180)),
72  MakeTimeChecker ())
73  .AddAttribute ("GarbageCollectionDelay", "The delay to delete an expired route.",
74  TimeValue (Seconds(120)),
76  MakeTimeChecker ())
77  .AddAttribute ("MinTriggeredCooldown", "Min cooldown delay after a Triggered Update.",
78  TimeValue (Seconds(1)),
80  MakeTimeChecker ())
81  .AddAttribute ("MaxTriggeredCooldown", "Max cooldown delay after a Triggered Update.",
82  TimeValue (Seconds(5)),
84  MakeTimeChecker ())
85  .AddAttribute ("SplitHorizon", "Split Horizon strategy.",
88  MakeEnumChecker (RipNg::NO_SPLIT_HORIZON, "NoSplitHorizon",
89  RipNg::SPLIT_HORIZON, "SplitHorizon",
90  RipNg::POISON_REVERSE, "PoisonReverse"))
91  ;
92  return tid;
93 }
94 
95 int64_t RipNg::AssignStreams (int64_t stream)
96 {
97  NS_LOG_FUNCTION (this << stream);
98 
99  m_rng->SetStream (stream);
100  return 1;
101 }
102 
104 {
105  NS_LOG_FUNCTION (this);
106 
107  bool addedGlobal = false;
108 
109  m_initialized = true;
110 
113 
114 
115  for (uint32_t i = 0 ; i < m_ipv6->GetNInterfaces (); i++)
116  {
117  bool activeInterface = false;
118  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
119  {
120  activeInterface = true;
121  }
122 
123  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
124  {
125  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
126  if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && activeInterface == true)
127  {
128  NS_LOG_LOGIC ("RIPng: adding socket to " << address.GetAddress ());
129  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
130  Ptr<Node> theNode = GetObject<Node> ();
131  Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
133  int ret = socket->Bind (local);
134  NS_ASSERT_MSG (ret == 0, "Bind unsuccessful");
135  socket->BindToNetDevice (m_ipv6->GetNetDevice (i));
136  socket->ShutdownRecv ();
137  socket->SetIpv6RecvHopLimit (true);
138  m_sendSocketList[socket] = i;
139  }
140  else if (m_ipv6->GetAddress (i, j).GetScope() == Ipv6InterfaceAddress::GLOBAL)
141  {
142  addedGlobal = true;
143  }
144  }
145  }
146 
147  if (!m_recvSocket)
148  {
149  NS_LOG_LOGIC ("RIPng: adding receiving socket");
150  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
151  Ptr<Node> theNode = GetObject<Node> ();
152  m_recvSocket = Socket::CreateSocket (theNode, tid);
154  m_recvSocket->Bind (local);
155  m_recvSocket->SetRecvCallback (MakeCallback (&RipNg::Receive, this));
156  m_recvSocket->SetIpv6RecvHopLimit (true);
157  m_recvSocket->SetRecvPktInfo (true);
158  }
159 
160 
161  if (addedGlobal)
162  {
165  }
166 
167  delay = Seconds (m_rng->GetValue (0.01, m_startupDelay.GetSeconds ()));
169 
171 }
172 
174 {
175  NS_LOG_FUNCTION (this << header << oif);
176 
177  Ipv6Address destination = header.GetDestinationAddress ();
178  Ptr<Ipv6Route> rtentry = 0;
179 
180  if (destination.IsMulticast ())
181  {
182  // Note: Multicast routes for outbound packets are stored in the
183  // normal unicast table. An implication of this is that it is not
184  // possible to source multicast datagrams on multiple interfaces.
185  // This is a well-known property of sockets implementation on
186  // many Unix variants.
187  // So, we just log it and fall through to LookupStatic ()
188  NS_LOG_LOGIC ("RouteOutput (): Multicast destination");
189  }
190 
191  rtentry = Lookup (destination, oif);
192  if (rtentry)
193  {
194  sockerr = Socket::ERROR_NOTERROR;
195  }
196  else
197  {
198  sockerr = Socket::ERROR_NOROUTETOHOST;
199  }
200  return rtentry;
201 }
202 
206 {
207  NS_LOG_FUNCTION (this << p << header << header.GetSourceAddress () << header.GetDestinationAddress () << idev);
208 
209  NS_ASSERT (m_ipv6 != 0);
210  // Check if input device supports IP
211  NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0);
212  uint32_t iif = m_ipv6->GetInterfaceForDevice (idev);
213  Ipv6Address dst = header.GetDestinationAddress ();
214 
215  if (dst.IsMulticast ())
216  {
217  NS_LOG_LOGIC ("Multicast route not supported by RIPng");
218  return false; // Let other routing protocols try to handle this
219  }
220 
222  // Right now, we will be permissive and allow a source to send us
223  // a packet to one of our other interface addresses; that is, the
224  // destination unicast address does not match one of the iif addresses,
225  // but we check our other interfaces. This could be an option
226  // (to remove the outer loop immediately below and just check iif).
227  for (uint32_t j = 0; j < m_ipv6->GetNInterfaces (); j++)
228  {
229  for (uint32_t i = 0; i < m_ipv6->GetNAddresses (j); i++)
230  {
231  Ipv6InterfaceAddress iaddr = m_ipv6->GetAddress (j, i);
232  Ipv6Address addr = iaddr.GetAddress ();
233  if (addr.IsEqual (header.GetDestinationAddress ()))
234  {
235  if (j == iif)
236  {
237  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
238  }
239  else
240  {
241  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestinationAddress ());
242  }
243  lcb (p, header, iif);
244  return true;
245  }
246  NS_LOG_LOGIC ("Address " << addr << " not a match");
247  }
248  }
249  // Check if input device supports IP forwarding
250  if (m_ipv6->IsForwarding (iif) == false)
251  {
252  NS_LOG_LOGIC ("Forwarding disabled for this interface");
253  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
254  return false;
255  }
256  // Next, try to find a route
257  NS_LOG_LOGIC ("Unicast destination");
258  Ptr<Ipv6Route> rtentry = Lookup (header.GetDestinationAddress ());
259 
260  if (rtentry != 0)
261  {
262  NS_LOG_LOGIC ("Found unicast destination- calling unicast callback");
263  ucb (idev, rtentry, p, header); // unicast forwarding callback
264  return true;
265  }
266  else
267  {
268  NS_LOG_LOGIC ("Did not find unicast destination- returning false");
269  return false; // Let other routing protocols try to handle this
270  }
271 }
272 
273 void RipNg::NotifyInterfaceUp (uint32_t i)
274 {
275  NS_LOG_FUNCTION (this << i);
276 
277  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
278  {
279  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
280  Ipv6Prefix networkMask = address.GetPrefix ();
281  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (networkMask);
282 
283  if (address != Ipv6Address () && networkMask != Ipv6Prefix ())
284  {
285  if (networkMask == Ipv6Prefix (128))
286  {
287  /* host route */
288  AddNetworkRouteTo (networkAddress, Ipv6Prefix::GetOnes (), 0);
289  }
290  else
291  {
292  AddNetworkRouteTo (networkAddress, networkMask, i);
293  }
294  }
295  }
296 
297  if (!m_initialized)
298  {
299  return;
300  }
301 
302 
303  bool sendSocketFound = false;
304  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
305  {
306  if (iter->second == i)
307  {
308  sendSocketFound = true;
309  break;
310  }
311  }
312 
313  bool activeInterface = false;
314  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
315  {
316  activeInterface = true;
317  }
318 
319  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
320  {
321  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
322 
323  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
324  Ipv6Prefix networkMask = address.GetPrefix ();
325  AddNetworkRouteTo (networkAddress, networkMask, i);
326 
327  if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && sendSocketFound == false && activeInterface == true)
328  {
329  NS_LOG_LOGIC ("RIPng: adding sending socket to " << address.GetAddress ());
330  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
331  Ptr<Node> theNode = GetObject<Node> ();
332  Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
334  socket->Bind (local);
335  socket->BindToNetDevice (m_ipv6->GetNetDevice (i));
336  socket->ShutdownRecv ();
337  socket->SetIpv6RecvHopLimit (true);
338  m_sendSocketList[socket] = i;
339  }
340  else if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
341  {
343  }
344  }
345 
346  if (!m_recvSocket)
347  {
348  NS_LOG_LOGIC ("RIPng: adding receiving socket");
349  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
350  Ptr<Node> theNode = GetObject<Node> ();
351  m_recvSocket = Socket::CreateSocket (theNode, tid);
353  m_recvSocket->Bind (local);
354  m_recvSocket->SetRecvCallback (MakeCallback (&RipNg::Receive, this));
355  m_recvSocket->SetIpv6RecvHopLimit (true);
356  m_recvSocket->SetRecvPktInfo (true);
357  }
358 }
359 
360 void RipNg::NotifyInterfaceDown (uint32_t interface)
361 {
362  NS_LOG_FUNCTION (this << interface);
363 
364  /* remove all routes that are going through this interface */
365  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
366  {
367  if (it->first->GetInterface () == interface)
368  {
369  InvalidateRoute (it->first);
370  }
371  }
372 
373  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
374  {
375  NS_LOG_INFO ("Checking socket for interface " << interface);
376  if (iter->second == interface)
377  {
378  NS_LOG_INFO ("Removed socket for interface " << interface);
379  iter->first->Close ();
380  m_sendSocketList.erase (iter);
381  break;
382  }
383  }
384 
385  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
386  {
388  }
389 }
390 
392 {
393  NS_LOG_FUNCTION (this << interface << address);
394 
395  if (!m_ipv6->IsUp (interface))
396  {
397  return;
398  }
399 
400  if (m_interfaceExclusions.find (interface) != m_interfaceExclusions.end ())
401  {
402  return;
403  }
404 
405  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
406  Ipv6Prefix networkMask = address.GetPrefix ();
407 
408  if (address.GetAddress () != Ipv6Address () && address.GetPrefix () != Ipv6Prefix ())
409  {
410  AddNetworkRouteTo (networkAddress, networkMask, interface);
411  }
412 
414 }
415 
417 {
418  NS_LOG_FUNCTION (this << interface << address);
419 
420  if (!m_ipv6->IsUp (interface))
421  {
422  return;
423  }
424 
425  if (address.GetScope() != Ipv6InterfaceAddress::GLOBAL)
426  {
427  return;
428  }
429 
430  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
431  Ipv6Prefix networkMask = address.GetPrefix ();
432 
433  // Remove all routes that are going through this interface
434  // which reference this network
435  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
436  {
437  if (it->first->GetInterface () == interface
438  && it->first->IsNetwork ()
439  && it->first->GetDestNetwork () == networkAddress
440  && it->first->GetDestNetworkPrefix () == networkMask)
441  {
442  InvalidateRoute (it->first);
443  }
444  }
445 
446  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
447  {
449  }
450 
451 }
452 
453 void RipNg::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
454 {
455  NS_LOG_INFO (this << dst << mask << nextHop << interface << prefixToUse);
456  // \todo this can be used to add delegate routes
457 }
458 
459 void RipNg::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
460 {
461  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
462  // \todo this can be used to delete delegate routes
463 }
464 
466 {
467  NS_LOG_FUNCTION (this << ipv6);
468 
469  NS_ASSERT (m_ipv6 == 0 && ipv6 != 0);
470  uint32_t i = 0;
471  m_ipv6 = ipv6;
472 
473  for (i = 0; i < m_ipv6->GetNInterfaces (); i++)
474  {
475  if (m_ipv6->IsUp (i))
476  {
477  NotifyInterfaceUp (i);
478  }
479  else
480  {
482  }
483  }
484 }
485 
487 {
488  NS_LOG_FUNCTION (this << stream);
489 
490  std::ostream* os = stream->GetStream ();
491 
492  *os << "Node: " << m_ipv6->GetObject<Node> ()->GetId ()
493  << " Time: " << Simulator::Now ().GetSeconds () << "s "
494  << "Ipv6 RIPng table" << std::endl;
495 
496  if (!m_routes.empty ())
497  {
498  *os << "Destination Next Hop Flag Met Ref Use If" << std::endl;
499  for (RoutesCI it = m_routes.begin (); it != m_routes.end (); it++)
500  {
501  RipNgRoutingTableEntry* route = it->first;
503 
505  {
506  std::ostringstream dest, gw, mask, flags;
507 
508  dest << route->GetDest () << "/" << int(route->GetDestNetworkPrefix ().GetPrefixLength ());
509  *os << std::setiosflags (std::ios::left) << std::setw (31) << dest.str ();
510  gw << route->GetGateway ();
511  *os << std::setiosflags (std::ios::left) << std::setw (27) << gw.str ();
512  flags << "U";
513  if (route->IsHost ())
514  {
515  flags << "H";
516  }
517  else if (route->IsGateway ())
518  {
519  flags << "G";
520  }
521  *os << std::setiosflags (std::ios::left) << std::setw (5) << flags.str ();
522  *os << std::setiosflags (std::ios::left) << std::setw (4) << int(route->GetRouteMetric ());
523  // Ref ct not implemented
524  *os << "-" << " ";
525  // Use not implemented
526  *os << "-" << " ";
527  if (Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ())) != "")
528  {
529  *os << Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ()));
530  }
531  else
532  {
533  *os << route->GetInterface ();
534  }
535  *os << std::endl;
536  }
537  }
538  }
539 }
540 
542 {
543  NS_LOG_FUNCTION (this);
544 
545  for (RoutesI j = m_routes.begin (); j != m_routes.end (); j = m_routes.erase (j))
546  {
547  delete j->first;
548  }
549  m_routes.clear ();
550 
555 
556  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
557  {
558  iter->first->Close ();
559  }
560  m_sendSocketList.clear ();
561 
562  m_recvSocket->Close ();
563  m_recvSocket = 0;
564 
565  m_ipv6 = 0;
566 
568 }
569 
570 
572 {
573  NS_LOG_FUNCTION (this << dst << interface);
574 
575  Ptr<Ipv6Route> rtentry = 0;
576  uint16_t longestMask = 0;
577 
578  /* when sending on link-local multicast, there have to be interface specified */
579  if (dst.IsLinkLocalMulticast ())
580  {
581  NS_ASSERT_MSG (interface, "Try to send on link-local multicast address, and no interface index is given!");
582  rtentry = Create<Ipv6Route> ();
583  rtentry->SetSource (m_ipv6->SourceAddressSelection (m_ipv6->GetInterfaceForDevice (interface), dst));
584  rtentry->SetDestination (dst);
585  rtentry->SetGateway (Ipv6Address::GetZero ());
586  rtentry->SetOutputDevice (interface);
587  return rtentry;
588  }
589 
590  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
591  {
592  RipNgRoutingTableEntry* j = it->first;
593 
595  {
596  Ipv6Prefix mask = j->GetDestNetworkPrefix ();
597  uint16_t maskLen = mask.GetPrefixLength ();
598  Ipv6Address entry = j->GetDestNetwork ();
599 
600  NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen);
601 
602  if (mask.IsMatch (dst, entry))
603  {
604  NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen);
605 
606  /* if interface is given, check the route will output on this interface */
607  if (!interface || interface == m_ipv6->GetNetDevice (j->GetInterface ()))
608  {
609  if (maskLen < longestMask)
610  {
611  NS_LOG_LOGIC ("Previous match longer, skipping");
612  continue;
613  }
614 
615  longestMask = maskLen;
616 
617  Ipv6RoutingTableEntry* route = j;
618  uint32_t interfaceIdx = route->GetInterface ();
619  rtentry = Create<Ipv6Route> ();
620 
621  if (route->GetGateway ().IsAny ())
622  {
623  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ()));
624  }
625  else if (route->GetDest ().IsAny ()) /* default route */
626  {
627  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetPrefixToUse ().IsAny () ? dst : route->GetPrefixToUse ()));
628  }
629  else
630  {
631  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ()));
632  }
633 
634  rtentry->SetDestination (route->GetDest ());
635  rtentry->SetGateway (route->GetGateway ());
636  rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interfaceIdx));
637  }
638  }
639  }
640  }
641 
642  if (rtentry)
643  {
644  NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (through " << rtentry->GetGateway () << ") at the end");
645  }
646  return rtentry;
647 }
648 
649 void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
650 {
651  NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface << prefixToUse);
652 
653  if (nextHop.IsLinkLocal())
654  {
655  NS_LOG_WARN ("Ripng::AddNetworkRouteTo - Next hop should be link-local");
656  }
657 
658  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, nextHop, interface, prefixToUse);
659  route->SetRouteMetric (1);
661  route->SetRouteChanged (true);
662 
663  m_routes.push_back (std::make_pair (route, EventId ()));
664 }
665 
666 void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
667 {
668  NS_LOG_FUNCTION (this << network << networkPrefix << interface);
669 
670  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, interface);
671  route->SetRouteMetric (1);
673  route->SetRouteChanged (true);
674 
675  m_routes.push_back (std::make_pair (route, EventId ()));
676 }
677 
679 {
680  NS_LOG_FUNCTION (this << *route);
681 
682  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
683  {
684  if (it->first == route)
685  {
687  route->SetRouteMetric (16);
688  route->SetRouteChanged (true);
689  if (it->second.IsRunning ())
690  {
691  it->second.Cancel ();
692  }
694  return;
695  }
696  }
697  NS_ABORT_MSG ("Ripng::InvalidateRoute - cannot find the route to update");
698 }
699 
701 {
702  NS_LOG_FUNCTION (this << *route);
703 
704  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
705  {
706  if (it->first == route)
707  {
708  delete route;
709  m_routes.erase (it);
710  return;
711  }
712  }
713  NS_ABORT_MSG ("Ripng::DeleteRoute - cannot find the route to delete");
714 }
715 
716 
718 {
719  NS_LOG_FUNCTION (this << socket);
720 
721  Ptr<Packet> packet = socket->Recv ();
722  NS_LOG_INFO ("Received " << *packet);
723 
724  Ipv6PacketInfoTag interfaceInfo;
725  if (!packet->RemovePacketTag (interfaceInfo))
726  {
727  NS_ABORT_MSG ("No incoming interface on RIPng message, aborting.");
728  }
729  uint32_t incomingIf = interfaceInfo.GetRecvIf ();
730  Ptr<Node> node = this->GetObject<Node> ();
731  Ptr<NetDevice> dev = node->GetDevice (incomingIf);
732  uint32_t ipInterfaceIndex = m_ipv6->GetInterfaceForDevice (dev);
733 
734  SocketIpv6HopLimitTag hoplimitTag;
735  if (!packet->RemovePacketTag (hoplimitTag))
736  {
737  NS_ABORT_MSG ("No incoming Hop Count on RIPng message, aborting.");
738  }
739  uint8_t hopLimit = hoplimitTag.GetHopLimit ();
740 
741  SocketAddressTag tag;
742  if (!packet->RemovePacketTag (tag))
743  {
744  NS_ABORT_MSG ("No incoming sender address on RIPng message, aborting.");
745  }
746  Ipv6Address senderAddress = Inet6SocketAddress::ConvertFrom (tag.GetAddress ()).GetIpv6 ();
747  uint16_t senderPort = Inet6SocketAddress::ConvertFrom (tag.GetAddress ()).GetPort ();
748 
749  int32_t interfaceForAddress = m_ipv6->GetInterfaceForAddress (senderAddress);
750  if (interfaceForAddress != -1)
751  {
752  NS_LOG_LOGIC ("Ignoring a packet sent by myself.");
753  return;
754  }
755 
756  RipNgHeader hdr;
757  packet->RemoveHeader (hdr);
758 
759  if (hdr.GetCommand () == RipNgHeader::RESPONSE)
760  {
761  HandleResponses (hdr, senderAddress, ipInterfaceIndex, hopLimit);
762  }
763  else if (hdr.GetCommand () == RipNgHeader::REQUEST)
764  {
765  HandleRequests (hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
766  }
767  else
768  {
769  NS_LOG_LOGIC ("Ignoring message with unknown command: " << int (hdr.GetCommand ()));
770  }
771  return;
772 }
773 
774 void RipNg::HandleRequests (RipNgHeader requestHdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
775 {
776  NS_LOG_FUNCTION (this << senderAddress << int (senderPort) << incomingInterface << int (hopLimit) << requestHdr);
777 
778  std::list<RipNgRte> rtes = requestHdr.GetRteList ();
779 
780  if (rtes.empty ())
781  {
782  return;
783  }
784 
785  // check if it's a request for the full table from a neighbor
786  if (rtes.size () == 1 && senderAddress.IsLinkLocal ())
787  {
788  if (rtes.begin ()->GetPrefix () == Ipv6Address::GetAny () &&
789  rtes.begin ()->GetPrefixLen () == 0 &&
790  rtes.begin ()->GetRouteMetric () == 16)
791  {
792  // Output whole thing. Use Split Horizon
793  if (m_interfaceExclusions.find (incomingInterface) == m_interfaceExclusions.end ())
794  {
795  // we use one of the sending sockets, as they're bound to the right interface
796  // and the local address might be used on different interfaces.
797  Ptr<Socket> sendingSoket;
798  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
799  {
800  if (iter->second == incomingInterface)
801  {
802  sendingSoket = iter->first;
803  }
804  }
805  NS_ASSERT_MSG (sendingSoket, "HandleRequest - Impossible to find a socket to send the reply");
806 
807  uint16_t mtu = m_ipv6->GetMtu (incomingInterface);
808  uint16_t maxRte = (mtu - Ipv6Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipNgHeader ().GetSerializedSize ()) / RipNgRte ().GetSerializedSize ();
809 
810  Ptr<Packet> p = Create<Packet> ();
812  p->RemovePacketTag (tag);
813  tag.SetHopLimit (255);
814  p->AddPacketTag (tag);
815 
816  RipNgHeader hdr;
818 
819  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
820  {
821  bool splitHorizoning = (rtIter->first->GetInterface () == incomingInterface);
822 
823  Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ());
824 
825  bool isGlobal = (rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL);
826  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv6Address::GetAny ()) &&
827  (rtIter->first->GetDestNetworkPrefix () == Ipv6Prefix::GetZero ()) &&
828  (rtIter->first->GetInterface () != incomingInterface));
829 
830  if ((isGlobal || isDefaultRoute) &&
831  (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID) )
832  {
833  RipNgRte rte;
834  rte.SetPrefix (rtIter->first->GetDestNetwork ());
835  rte.SetPrefixLen (rtIter->first->GetDestNetworkPrefix ().GetPrefixLength ());
836  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
837  {
838  rte.SetRouteMetric (16);
839  }
840  else
841  {
842  rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
843  }
844  rte.SetRouteTag (rtIter->first->GetRouteTag ());
846  (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
847  {
848  hdr.AddRte (rte);
849  }
850  }
851  if (hdr.GetRteNumber () == maxRte)
852  {
853  p->AddHeader (hdr);
854  NS_LOG_DEBUG ("SendTo: " << *p);
855  sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, RIPNG_PORT));
856  p->RemoveHeader (hdr);
857  hdr.ClearRtes ();
858  }
859  }
860  if (hdr.GetRteNumber () > 0)
861  {
862  p->AddHeader (hdr);
863  NS_LOG_DEBUG ("SendTo: " << *p);
864  sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, RIPNG_PORT));
865  }
866  }
867  }
868  }
869  else
870  {
871  // note: we got the request as a single packet, so no check is necessary for MTU limit
872 
873  // we use one of the sending sockets, as they're bound to the right interface
874  // and the local address might be used on different interfaces.
875  Ptr<Socket> sendingSoket;
876  if (senderAddress.IsLinkLocal ())
877  {
878  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
879  {
880  if (iter->second == incomingInterface)
881  {
882  sendingSoket = iter->first;
883  }
884  }
885  }
886  else
887  {
888  sendingSoket = m_recvSocket;
889  }
890 
891  Ptr<Packet> p = Create<Packet> ();
893  p->RemovePacketTag (tag);
894  tag.SetHopLimit (255);
895  p->AddPacketTag (tag);
896 
897  RipNgHeader hdr;
899 
900  for (std::list<RipNgRte>::iterator iter = rtes.begin ();
901  iter != rtes.end (); iter++)
902  {
903  bool found = false;
904  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
905  {
906  Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ());
907  if ((rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL) &&
908  (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID))
909  {
910  Ipv6Address requestedAddress = iter->GetPrefix ();
911  requestedAddress.CombinePrefix (Ipv6Prefix (iter->GetPrefixLen ()));
912  Ipv6Address rtAddress = rtIter->first->GetDestNetwork ();
913  rtAddress.CombinePrefix (rtIter->first->GetDestNetworkPrefix ());
914 
915  if (requestedAddress == rtAddress)
916  {
917  iter->SetRouteMetric (rtIter->first->GetRouteMetric ());
918  iter->SetRouteTag (rtIter->first->GetRouteTag ());
919  hdr.AddRte (*iter);
920  found = true;
921  break;
922  }
923  }
924  }
925  if (!found)
926  {
927  iter->SetRouteMetric (16);
928  iter->SetRouteTag (0);
929  hdr.AddRte (*iter);
930  }
931  }
932  p->AddHeader (hdr);
933  NS_LOG_DEBUG ("SendTo: " << *p);
934  sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, senderPort));
935  }
936 
937 }
938 
939 void RipNg::HandleResponses (RipNgHeader hdr, Ipv6Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
940 {
941  NS_LOG_FUNCTION (this << senderAddress << incomingInterface << int (hopLimit) << hdr);
942 
943  if (m_interfaceExclusions.find (incomingInterface) != m_interfaceExclusions.end ())
944  {
945  NS_LOG_LOGIC ("Ignoring an update message from an excluded interface: " << incomingInterface);
946  return;
947  }
948 
949  if (!senderAddress.IsLinkLocal ())
950  {
951  NS_LOG_LOGIC ("Ignoring an update message from a non-link-local source: " << senderAddress);
952  return;
953  }
954 
955  if (hopLimit != 255)
956  {
957  NS_LOG_LOGIC ("Ignoring an update message with suspicious hop count: " << int (hopLimit));
958  return;
959  }
960 
961  std::list<RipNgRte> rtes = hdr.GetRteList ();
962 
963  // validate the RTEs before processing
964  for (std::list<RipNgRte>::iterator iter = rtes.begin ();
965  iter != rtes.end (); iter++)
966  {
967  if (iter->GetRouteMetric () == 0 || iter->GetRouteMetric () > 16)
968  {
969  NS_LOG_LOGIC ("Ignoring an update message with malformed metric: " << int (iter->GetRouteMetric ()));
970  return;
971  }
972  if (iter->GetPrefixLen () > 128)
973  {
974  NS_LOG_LOGIC ("Ignoring an update message with malformed prefix length: " << int (iter->GetPrefixLen ()));
975  return;
976  }
977  if (iter->GetPrefix ().IsLocalhost () ||
978  iter->GetPrefix ().IsLinkLocal () ||
979  iter->GetPrefix ().IsMulticast ())
980  {
981  NS_LOG_LOGIC ("Ignoring an update message with wrong prefixes: " << iter->GetPrefix ());
982  return;
983  }
984  }
985 
986  bool changed = false;
987 
988  for (std::list<RipNgRte>::iterator iter = rtes.begin ();
989  iter != rtes.end (); iter++)
990  {
991  Ipv6Prefix rtePrefix = Ipv6Prefix (iter->GetPrefixLen ());
992  Ipv6Address rteAddr = iter->GetPrefix ().CombinePrefix (rtePrefix);
993 
994  NS_LOG_LOGIC ("Processing RTE " << *iter);
995 
996  uint8_t interfaceMetric = 1;
997  if (m_interfaceMetrics.find (incomingInterface) != m_interfaceMetrics.end ())
998  {
999  interfaceMetric = m_interfaceMetrics[incomingInterface];
1000  }
1001  uint8_t rteMetric = std::min (iter->GetRouteMetric () + interfaceMetric, 16);
1002  RoutesI it;
1003  bool found = false;
1004  for (it = m_routes.begin (); it != m_routes.end (); it++)
1005  {
1006  if (it->first->GetDestNetwork () == rteAddr &&
1007  it->first->GetDestNetworkPrefix () == rtePrefix)
1008  {
1009  found = true;
1010  if (rteMetric < it->first->GetRouteMetric ())
1011  {
1012  if (senderAddress != it->first->GetGateway ())
1013  {
1014  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
1015  delete it->first;
1016  it->first = route;
1017  }
1018  it->first->SetRouteMetric (rteMetric);
1019  it->first->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID);
1020  it->first->SetRouteTag (iter->GetRouteTag ());
1021  it->first->SetRouteChanged (true);
1022  it->second.Cancel ();
1023  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first);
1024  changed = true;
1025  }
1026  else if (rteMetric == it->first->GetRouteMetric ())
1027  {
1028  if (senderAddress == it->first->GetGateway ())
1029  {
1030  it->second.Cancel ();
1031  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first);
1032  }
1033  else
1034  {
1035  if (Simulator::GetDelayLeft (it->second) < m_timeoutDelay/2)
1036  {
1037  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
1038  route->SetRouteMetric (rteMetric);
1040  route->SetRouteTag (iter->GetRouteTag ());
1041  route->SetRouteChanged (true);
1042  delete it->first;
1043  it->first = route;
1044  it->second.Cancel ();
1045  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, route);
1046  changed = true;
1047  }
1048  }
1049  }
1050  else if (rteMetric > it->first->GetRouteMetric () && senderAddress == it->first->GetGateway ())
1051  {
1052  it->second.Cancel ();
1053  if (rteMetric < 16)
1054  {
1055  it->first->SetRouteMetric (rteMetric);
1056  it->first->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID);
1057  it->first->SetRouteTag (iter->GetRouteTag ());
1058  it->first->SetRouteChanged (true);
1059  it->second.Cancel ();
1060  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first);
1061  }
1062  else
1063  {
1064  InvalidateRoute (it->first);
1065  }
1066  changed = true;
1067  }
1068  }
1069  }
1070  if (!found && rteMetric != 16)
1071  {
1072  NS_LOG_LOGIC ("Received a RTE with new route, adding.");
1073 
1074  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
1075  route->SetRouteMetric (rteMetric);
1077  route->SetRouteChanged (true);
1078  m_routes.push_front (std::make_pair (route, EventId ()));
1079  EventId invalidateEvent = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, route);
1080  (m_routes.begin ())->second = invalidateEvent;
1081  changed = true;
1082  }
1083  }
1084 
1085  if (changed)
1086  {
1088  }
1089 }
1090 
1091 void RipNg::DoSendRouteUpdate (bool periodic)
1092 {
1093  NS_LOG_FUNCTION (this << (periodic ? " periodic" : " triggered"));
1094 
1095  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
1096  {
1097  uint32_t interface = iter->second;
1098 
1099  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1100  {
1101  uint16_t mtu = m_ipv6->GetMtu (interface);
1102  uint16_t maxRte = (mtu - Ipv6Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipNgHeader ().GetSerializedSize ()) / RipNgRte ().GetSerializedSize ();
1103 
1104  Ptr<Packet> p = Create<Packet> ();
1106  tag.SetHopLimit (255);
1107  p->AddPacketTag (tag);
1108 
1109  RipNgHeader hdr;
1111 
1112  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1113  {
1114  bool splitHorizoning = (rtIter->first->GetInterface () == interface);
1115  Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ());
1116 
1117  NS_LOG_DEBUG ("Processing RT " << rtDestAddr << " " << int(rtIter->first->IsRouteChanged ()));
1118 
1119  bool isGlobal = (rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL);
1120  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv6Address::GetAny ()) &&
1121  (rtIter->first->GetDestNetworkPrefix () == Ipv6Prefix::GetZero ()) &&
1122  (rtIter->first->GetInterface () != interface));
1123 
1124  if ((isGlobal || isDefaultRoute) &&
1125  (periodic || rtIter->first->IsRouteChanged ()))
1126  {
1127  RipNgRte rte;
1128  rte.SetPrefix (rtIter->first->GetDestNetwork ());
1129  rte.SetPrefixLen (rtIter->first->GetDestNetworkPrefix ().GetPrefixLength ());
1130  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
1131  {
1132  rte.SetRouteMetric (16);
1133  }
1134  else
1135  {
1136  rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
1137  }
1138  rte.SetRouteTag (rtIter->first->GetRouteTag ());
1139  if (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning)
1140  {
1141  hdr.AddRte (rte);
1142  }
1144  {
1145  hdr.AddRte (rte);
1146  }
1147  }
1148  if (hdr.GetRteNumber () == maxRte)
1149  {
1150  p->AddHeader (hdr);
1151  NS_LOG_DEBUG ("SendTo: " << *p);
1152  iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT));
1153  p->RemoveHeader (hdr);
1154  hdr.ClearRtes ();
1155  }
1156  }
1157  if (hdr.GetRteNumber () > 0)
1158  {
1159  p->AddHeader (hdr);
1160  NS_LOG_DEBUG ("SendTo: " << *p);
1161  iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT));
1162  }
1163  }
1164  }
1165  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1166  {
1167  rtIter->first->SetRouteChanged (false);
1168  }
1169 }
1170 
1172 {
1173  NS_LOG_FUNCTION (this);
1174 
1176  {
1177  NS_LOG_LOGIC ("Skipping Triggered Update due to cooldown");
1178  return;
1179  }
1180 
1181  // DoSendRouteUpdate (false);
1182 
1183  // note: The RFC states:
1184  // After a triggered
1185  // update is sent, a timer should be set for a random interval between 1
1186  // and 5 seconds. If other changes that would trigger updates occur
1187  // before the timer expires, a single update is triggered when the timer
1188  // expires. The timer is then reset to another random value between 1
1189  // and 5 seconds. Triggered updates may be suppressed if a regular
1190  // update is due by the time the triggered update would be sent.
1191  // Here we rely on this:
1192  // When an update occurs (either Triggered or Periodic) the "IsChanged ()"
1193  // route field will be cleared.
1194  // Hence, the following Triggered Update will be fired, but will not send
1195  // any route update.
1196 
1199 }
1200 
1202 {
1203  NS_LOG_FUNCTION (this);
1204 
1206  {
1208  }
1209 
1210  DoSendRouteUpdate (true);
1211 
1214 }
1215 
1216 std::set<uint32_t> RipNg::GetInterfaceExclusions () const
1217 {
1218  return m_interfaceExclusions;
1219 }
1220 
1221 void RipNg::SetInterfaceExclusions (std::set<uint32_t> exceptions)
1222 {
1223  NS_LOG_FUNCTION (this);
1224 
1225  m_interfaceExclusions = exceptions;
1226 }
1227 
1228 uint8_t RipNg::GetInterfaceMetric (uint32_t interface) const
1229 {
1230  NS_LOG_FUNCTION (this << interface);
1231 
1232  std::map<uint32_t, uint8_t>::const_iterator iter = m_interfaceMetrics.find (interface);
1233  if (iter != m_interfaceMetrics.end ())
1234  {
1235  return iter->second;
1236  }
1237  return 1;
1238 }
1239 
1240 void RipNg::SetInterfaceMetric (uint32_t interface, uint8_t metric)
1241 {
1242  NS_LOG_FUNCTION (this << interface << int (metric));
1243 
1244  if (metric < 16)
1245  {
1246  m_interfaceMetrics[interface] = metric;
1247  }
1248 }
1249 
1251 {
1252  NS_LOG_FUNCTION (this);
1253 
1254  Ptr<Packet> p = Create<Packet> ();
1256  p->RemovePacketTag (tag);
1257  tag.SetHopLimit (255);
1258  p->AddPacketTag (tag);
1259 
1260  RipNgHeader hdr;
1262 
1263  RipNgRte rte;
1264  rte.SetPrefix (Ipv6Address::GetAny ());
1265  rte.SetPrefixLen (0);
1266  rte.SetRouteMetric (16);
1267 
1268  hdr.AddRte (rte);
1269  p->AddHeader (hdr);
1270 
1271  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
1272  {
1273  uint32_t interface = iter->second;
1274 
1275  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1276  {
1277  NS_LOG_DEBUG ("SendTo: " << *p);
1278  iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT));
1279  }
1280  }
1281 }
1282 
1283 void RipNg::AddDefaultRouteTo (Ipv6Address nextHop, uint32_t interface)
1284 {
1285  NS_LOG_FUNCTION (this << interface);
1286 
1287  AddNetworkRouteTo (Ipv6Address ("::"), Ipv6Prefix::GetZero (), nextHop, interface, Ipv6Address ("::"));
1288 }
1289 
1290 
1291 /*
1292  * RipNgRoutingTableEntry
1293  */
1294 
1296  : m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false)
1297 {
1298 }
1299 
1300 RipNgRoutingTableEntry::RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
1301  : Ipv6RoutingTableEntry ( RipNgRoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, nextHop, interface, prefixToUse) ),
1302  m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false)
1303 {
1304 }
1305 
1306 RipNgRoutingTableEntry::RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
1307  : Ipv6RoutingTableEntry ( Ipv6RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, interface) ),
1308  m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false)
1309 {
1310 }
1311 
1313 {
1314 }
1315 
1316 
1317 void RipNgRoutingTableEntry::SetRouteTag (uint16_t routeTag)
1318 {
1319  if (m_tag != routeTag)
1320  {
1321  m_tag = routeTag;
1322  m_changed = true;
1323  }
1324 }
1325 
1327 {
1328  return m_tag;
1329 }
1330 
1331 void RipNgRoutingTableEntry::SetRouteMetric (uint8_t routeMetric)
1332 {
1333  if (m_metric != routeMetric)
1334  {
1335  m_metric = routeMetric;
1336  m_changed = true;
1337  }
1338 }
1339 
1341 {
1342  return m_metric;
1343 }
1344 
1346 {
1347  if (m_status != status)
1348  {
1349  m_status = status;
1350  m_changed = true;
1351  }
1352 }
1353 
1355 {
1356  return m_status;
1357 }
1358 
1360 {
1361  m_changed = changed;
1362 }
1363 
1365 {
1366  return m_changed;
1367 }
1368 
1369 
1370 std::ostream & operator << (std::ostream& os, const RipNgRoutingTableEntry& rte)
1371 {
1372  os << static_cast<const Ipv6RoutingTableEntry &>(rte);
1373  os << ", metric: " << int (rte.GetRouteMetric ()) << ", tag: " << int (rte.GetRouteTag ());
1374 
1375  return os;
1376 }
1377 
1378 
1379 }
1380 
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:232
bool IsAny() const
If the IPv6 address is the "Any" address.
#define RIPNG_ALL_NODE
Definition: ripng.cc:36
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:268
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:143
SplitHorizonType_e m_splitHorizonStrategy
Split Horizon strategy.
Definition: ripng.h:407
uint16_t GetRteNumber(void) const
Get the number of RTE included in the message.
std::map< Ptr< Socket >, uint32_t >::iterator SocketListI
Socket list type iterator.
Definition: ripng.h:392
Split Horizon.
Definition: ripng.h:208
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:95
virtual void NotifyInterfaceDown(uint32_t interface)
Notify when specified interface goes DOWN.
Definition: ripng.cc:360
Introspection did not find any typical Config paths.
Definition: ipv6-header.h:33
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by "...
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
Ipv6Address GetPrefixToUse() const
Get the prefix to use (for multihomed link).
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:82
Callback template class.
Definition: callback.h:978
bool IsLinkLocalMulticast() const
If the IPv6 address is link-local multicast (ff02::/16).
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
Ipv6Prefix GetDestNetworkPrefix() const
Get the destination prefix.
void SetRouteTag(uint16_t routeTag)
Set the route tag.
Definition: ripng.cc:1317
void AddNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
Add route to network.
Definition: ripng.cc:649
std::list< RipNgRte > GetRteList(void) const
Get the list of the RTEs included in the message.
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer...
Definition: socket.h:1047
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:44
void SetInterfaceExclusions(std::set< uint32_t > exceptions)
Set the set of interface excluded from the protocol.
Definition: ripng.cc:1221
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:209
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:836
void SetPrefix(Ipv6Address prefix)
Set the prefix.
Definition: ripng-header.cc:82
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
EventId m_nextTriggeredUpdate
Next Triggered Update event.
Definition: ripng.h:400
virtual ~RipNg()
Definition: ripng.cc:51
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file...
Definition: assert.h:61
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:201
IPv6 address associated with an interface.
uint8_t m_metric
route metric
Definition: ripng.h:152
Link-local address (fe80::/64)
RipNg()
Definition: ripng.cc:45
bool IsEqual(const Ipv6Address &other) const
Comparison operation between two Ipv6Addresses.
void SetInterfaceMetric(uint32_t interface, uint8_t metric)
Set the metric for an interface.
Definition: ripng.cc:1240
void SendUnsolicitedRouteUpdate(void)
Send Unsolicited Routing Updates on all interfaces.
Definition: ripng.cc:1201
EventId m_nextUnsolicitedUpdate
Next Unsolicited Update event.
Definition: ripng.h:399
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:338
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:244
void Receive(Ptr< Socket > socket)
Receive RIPng packets.
Definition: ripng.cc:717
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
virtual void DoDispose()
Dispose this object.
Definition: ripng.cc:541
static EventId Schedule(Time const &time, MEM mem_ptr, OBJ obj)
Schedule an event to expire at the relative time "time" is reached.
Definition: simulator.h:819
static Ipv6Prefix GetZero()
Get the zero prefix ( /0).
void AddDefaultRouteTo(Ipv6Address nextHop, uint32_t interface)
Add a default route to the router through the nextHop located on interface.
Definition: ripng.cc:1283
uint16_t m_tag
route tag
Definition: ripng.h:151
SocketList m_sendSocketList
list of sockets for sending (socket, interface index)
Definition: ripng.h:396
void InvalidateRoute(RipNgRoutingTableEntry *route)
Invalidate a route.
Definition: ripng.cc:678
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:439
RIPng Routing Protocol, defined in RFC 2080.
Definition: ripng.h:173
void SendTriggeredRouteUpdate()
Send Triggered Routing Updates on all interfaces.
Definition: ripng.cc:1171
std::set< uint32_t > m_interfaceExclusions
Set of excluded interfaces.
Definition: ripng.h:404
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:327
Ipv6Address GetDestNetwork() const
Get the destination network.
void DoInitialize()
Start protocol operation.
Definition: ripng.cc:103
Ipv6Address GetAddress() const
Get the IPv6 address.
A record of an IPv6 route.
virtual void NotifyAddRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero())
Notify a new route.
Definition: ripng.cc:453
void AddRte(RipNgRte rte)
Add a RTE to the message.
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
Definition: ripng.cc:1331
Hold variables of type enum.
Definition: enum.h:54
uint8_t GetInterfaceMetric(uint32_t interface) const
Get the metric for an interface.
Definition: ripng.cc:1228
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model...
Definition: ripng.cc:95
AttributeValue implementation for Time.
Definition: nstime.h:921
Ptr< Ipv6 > m_ipv6
IPv6 reference.
Definition: ripng.h:379
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
Time m_timeoutDelay
Delay before invalidating a route.
Definition: ripng.h:384
An Inet6 address class.
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:134
This class implements a tag that carries an address of a packet across the socket interface...
Definition: socket.h:951
void DoSendRouteUpdate(bool periodic)
Send Routing Updates on all interfaces.
Definition: ripng.cc:1091
void SetRouteTag(uint16_t routeTag)
Set the route tag.
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:1290
bool IsHost() const
Is the route entry correspond to a host ?
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:70
void SetRouteChanged(bool changed)
Set the route as changed.
Definition: ripng.cc:1359
Ipv6Prefix GetPrefix() const
Get the IPv6 prefix.
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:252
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:642
RipNgHeader - see RFC 2080
Definition: ripng-header.h:144
Ptr< Socket > m_recvSocket
receive socket
Definition: ripng.h:397
virtual void NotifyRemoveAddress(uint32_t interface, Ipv6InterfaceAddress address)
Notify when specified interface add an address.
Definition: ripng.cc:416
void DeleteRoute(RipNgRoutingTableEntry *route)
Delete a route.
Definition: ripng.cc:700
std::ostream & operator<<(std::ostream &os, const Angles &a)
print a struct Angles to output
Definition: angles.cc:42
Ptr< Ipv6Route > RouteOutput(Ptr< Packet > p, const Ipv6Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
Definition: ripng.cc:173
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
bool RouteInput(Ptr< const Packet > p, const Ipv6Header &header, Ptr< const NetDevice > idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
Route an input packet (to be forwarded or locally delivered)
Definition: ripng.cc:203
Status_e GetRouteStatus(void) const
Get the route status.
Definition: ripng.cc:1354
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
Definition: ripng.h:383
virtual ~RipNgRoutingTableEntry()
Definition: ripng.cc:1312
virtual Ptr< Packet > Recv(uint32_t maxSize, uint32_t flags)=0
Read data from the socket.
uint8_t GetRouteMetric(void) const
Get the route metric.
Definition: ripng.cc:1340
virtual void NotifyAddAddress(uint32_t interface, Ipv6InterfaceAddress address)
Notify when specified interface add an address.
Definition: ripng.cc:391
void HandleResponses(RipNgHeader hdr, Ipv6Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIPng responses.
Definition: ripng.cc:939
double GetValue(double min, double max)
Returns a random double from the uniform distribution with the specified range.
Packet header for UDP packets.
Definition: udp-header.h:39
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
void HandleRequests(RipNgHeader hdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIPng requests.
Definition: ripng.cc:774
virtual void SetIpv6(Ptr< Ipv6 > ipv6)
Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol.
Definition: ripng.cc:465
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:922
Ipv6Address GetGateway() const
Get the gateway.
static Time Now(void)
Return the current simulation virtual time.
Definition: simulator.cc:223
uint32_t GetInterface() const
Get the interface index.
Ptr< UniformRandomVariable > m_rng
Rng stream.
Definition: ripng.h:402
std::set< uint32_t > GetInterfaceExclusions() const
Get the set of interface excluded from the protocol.
Definition: ripng.cc:1216
void SetRouteStatus(Status_e status)
Set the route status.
Definition: ripng.cc:1345
virtual void NotifyInterfaceUp(uint32_t interface)
Notify when specified interface goes UP.
Definition: ripng.cc:273
uint16_t GetRouteTag(void) const
Get the route tag.
Definition: ripng.cc:1326
#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:84
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ripng-header.cc:52
uint8_t GetHopLimit(void) const
Get the tag's Hop Limit.
Definition: socket.cc:648
Ptr< const AttributeChecker > MakeEnumChecker(int v1, std::string n1, int v2, std::string n2, int v3, std::string n3, int v4, std::string n4, int v5, std::string n5, int v6, std::string n6, int v7, std::string n7, int v8, std::string n8, int v9, std::string n9, int v10, std::string n10, int v11, std::string n11, int v12, std::string n12, int v13, std::string n13, int v14, std::string n14, int v15, std::string n15, int v16, std::string n16, int v17, std::string n17, int v18, std::string n18, int v19, std::string n19, int v20, std::string n20, int v21, std::string n21, int v22, std::string n22)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.cc:184
Describes an IPv6 address.
Definition: ipv6-address.h:47
void SendRouteRequest()
Send Routing Request on all interfaces.
Definition: ripng.cc:1250
Ipv6InterfaceAddress::Scope_e GetScope() const
Get address scope.
static Ipv6Prefix GetOnes()
Get the "all-1" IPv6 mask (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff).
static TypeId GetTypeId(void)
Get the type ID.
Definition: ripng.cc:56
An identifier for simulation events.
Definition: event-id.h:53
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:228
std::map< uint32_t, uint8_t > m_interfaceMetrics
Map of interface metrics.
Definition: ripng.h:405
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream) const
Print the Routing Table entries.
Definition: ripng.cc:486
Address GetAddress(void) const
Get the tag's address.
Definition: socket.cc:529
std::list< std::pair< RipNgRoutingTableEntry *, EventId > >::const_iterator RoutesCI
Const Iterator for container for the network routes.
Definition: ripng.h:275
No Split Horizon.
Definition: ripng.h:207
RipNg Routing Table Entry.
Definition: ripng.h:62
Ipv6Address GetDest() const
Get the destination.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:843
A network Node.
Definition: node.h:55
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:236
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:859
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
Routes m_routes
the forwarding table for network.
Definition: ripng.h:378
std::list< std::pair< RipNgRoutingTableEntry *, EventId > >::iterator RoutesI
Iterator for container for the network routes.
Definition: ripng.h:278
uint32_t GetRecvIf(void) const
Get the tag's receiving interface.
void Cancel(void)
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:53
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:664
void SetCommand(Command_e command)
Set the command.
Ptr< Ipv6Route > Lookup(Ipv6Address dest, Ptr< NetDevice >=0)
Lookup in the forwarding table for destination.
Definition: ripng.cc:571
Describes an IPv6 prefix.
Definition: ipv6-address.h:389
bool m_changed
route has been updated
Definition: ripng.h:154
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
Command_e GetCommand(void) const
Get the command.
bool IsGateway() const
Is it the gateway ?
uint8_t GetPrefixLength() const
Get prefix length.
This class implements a tag that carries socket ancillary data to the socket interface.
bool m_initialized
flag to allow socket's late-creation.
Definition: ripng.h:409
RipNgRoutingTableEntry(void)
Definition: ripng.cc:1295
tuple address
Definition: first.py:37
void ClearRtes()
Clear all the RTEs from the header.
Time m_maxTriggeredUpdateDelay
Max cooldown delay after a Triggered Update.
Definition: ripng.h:382
Time m_garbageCollectionDelay
Delay before deleting an INVALID route.
Definition: ripng.h:385
virtual int Close(void)=0
Close a socket.
Definition: first.py:1
RipNg Routing Table Entry (RTE) - see RFC 2080
Definition: ripng-header.h:37
Poison Reverse Split Horizon.
Definition: ripng.h:209
Ipv6Address CombinePrefix(Ipv6Prefix const &prefix)
Combine this address with a prefix.
Abstract base class for Ipv6 routing protocols.
virtual void NotifyRemoveRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero())
Notify route removing.
Definition: ripng.cc:459
Status_e m_status
route status
Definition: ripng.h:153
a unique identifier for an interface.
Definition: type-id.h:51
#define RIPNG_PORT
Definition: ripng.cc:37
TypeId SetParent(TypeId tid)
Definition: type-id.cc:631
Status_e
Route status.
Definition: ripng.h:69
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
virtual uint32_t GetSerializedSize(void) const
Definition: udp-header.cc:177
Time m_startupDelay
Random delay before protocol startup.
Definition: ripng.h:380
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:253
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:345
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111
Time m_minTriggeredUpdateDelay
Min cooldown delay after a Triggered Update.
Definition: ripng.h:381
static TypeId LookupByName(std::string name)
Definition: type-id.cc:556
bool IsRouteChanged(void) const
Get the route changed status.
Definition: ripng.cc:1364
void SetPrefixLen(uint8_t prefixLen)
Set the prefix length.
Definition: ripng-header.cc:92