This documentation is not the Latest Release.
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  .SetGroupName ("Internet")
61  .AddConstructor<RipNg> ()
62  .AddAttribute ("UnsolicitedRoutingUpdate", "The time between two Unsolicited Routing Updates.",
63  TimeValue (Seconds(30)),
65  MakeTimeChecker ())
66  .AddAttribute ("StartupDelay", "Maximum random delay for protocol startup (send route requests).",
67  TimeValue (Seconds(1)),
69  MakeTimeChecker ())
70  .AddAttribute ("TimeoutDelay", "The delay to invalidate a route.",
71  TimeValue (Seconds(180)),
73  MakeTimeChecker ())
74  .AddAttribute ("GarbageCollectionDelay", "The delay to delete an expired route.",
75  TimeValue (Seconds(120)),
77  MakeTimeChecker ())
78  .AddAttribute ("MinTriggeredCooldown", "Min cooldown delay after a Triggered Update.",
79  TimeValue (Seconds(1)),
81  MakeTimeChecker ())
82  .AddAttribute ("MaxTriggeredCooldown", "Max cooldown delay after a Triggered Update.",
83  TimeValue (Seconds(5)),
85  MakeTimeChecker ())
86  .AddAttribute ("SplitHorizon", "Split Horizon strategy.",
89  MakeEnumChecker (RipNg::NO_SPLIT_HORIZON, "NoSplitHorizon",
90  RipNg::SPLIT_HORIZON, "SplitHorizon",
91  RipNg::POISON_REVERSE, "PoisonReverse"))
92  ;
93  return tid;
94 }
95 
96 int64_t RipNg::AssignStreams (int64_t stream)
97 {
98  NS_LOG_FUNCTION (this << stream);
99 
100  m_rng->SetStream (stream);
101  return 1;
102 }
103 
105 {
106  NS_LOG_FUNCTION (this);
107 
108  bool addedGlobal = false;
109 
110  m_initialized = true;
111 
114 
115 
116  for (uint32_t i = 0 ; i < m_ipv6->GetNInterfaces (); i++)
117  {
118  bool activeInterface = false;
119  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
120  {
121  activeInterface = true;
122  }
123 
124  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
125  {
126  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
127  if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && activeInterface == true)
128  {
129  NS_LOG_LOGIC ("RIPng: adding socket to " << address.GetAddress ());
130  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
131  Ptr<Node> theNode = GetObject<Node> ();
132  Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
134  int ret = socket->Bind (local);
135  NS_ASSERT_MSG (ret == 0, "Bind unsuccessful");
136  socket->BindToNetDevice (m_ipv6->GetNetDevice (i));
137  socket->ShutdownRecv ();
138  socket->SetIpv6RecvHopLimit (true);
139  m_sendSocketList[socket] = i;
140  }
141  else if (m_ipv6->GetAddress (i, j).GetScope() == Ipv6InterfaceAddress::GLOBAL)
142  {
143  addedGlobal = true;
144  }
145  }
146  }
147 
148  if (!m_recvSocket)
149  {
150  NS_LOG_LOGIC ("RIPng: adding receiving socket");
151  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
152  Ptr<Node> theNode = GetObject<Node> ();
153  m_recvSocket = Socket::CreateSocket (theNode, tid);
155  m_recvSocket->Bind (local);
156  m_recvSocket->SetRecvCallback (MakeCallback (&RipNg::Receive, this));
157  m_recvSocket->SetIpv6RecvHopLimit (true);
158  m_recvSocket->SetRecvPktInfo (true);
159  }
160 
161 
162  if (addedGlobal)
163  {
166  }
167 
168  delay = Seconds (m_rng->GetValue (0.01, m_startupDelay.GetSeconds ()));
170 
172 }
173 
175 {
176  NS_LOG_FUNCTION (this << header << oif);
177 
178  Ipv6Address destination = header.GetDestinationAddress ();
179  Ptr<Ipv6Route> rtentry = 0;
180 
181  if (destination.IsMulticast ())
182  {
183  // Note: Multicast routes for outbound packets are stored in the
184  // normal unicast table. An implication of this is that it is not
185  // possible to source multicast datagrams on multiple interfaces.
186  // This is a well-known property of sockets implementation on
187  // many Unix variants.
188  // So, we just log it and fall through to LookupStatic ()
189  NS_LOG_LOGIC ("RouteOutput (): Multicast destination");
190  }
191 
192  rtentry = Lookup (destination, oif);
193  if (rtentry)
194  {
195  sockerr = Socket::ERROR_NOTERROR;
196  }
197  else
198  {
199  sockerr = Socket::ERROR_NOROUTETOHOST;
200  }
201  return rtentry;
202 }
203 
207 {
208  NS_LOG_FUNCTION (this << p << header << header.GetSourceAddress () << header.GetDestinationAddress () << idev);
209 
210  NS_ASSERT (m_ipv6 != 0);
211  // Check if input device supports IP
212  NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0);
213  uint32_t iif = m_ipv6->GetInterfaceForDevice (idev);
214  Ipv6Address dst = header.GetDestinationAddress ();
215 
216  if (dst.IsMulticast ())
217  {
218  NS_LOG_LOGIC ("Multicast route not supported by RIPng");
219  return false; // Let other routing protocols try to handle this
220  }
221 
223  // Right now, we will be permissive and allow a source to send us
224  // a packet to one of our other interface addresses; that is, the
225  // destination unicast address does not match one of the iif addresses,
226  // but we check our other interfaces. This could be an option
227  // (to remove the outer loop immediately below and just check iif).
228  for (uint32_t j = 0; j < m_ipv6->GetNInterfaces (); j++)
229  {
230  for (uint32_t i = 0; i < m_ipv6->GetNAddresses (j); i++)
231  {
232  Ipv6InterfaceAddress iaddr = m_ipv6->GetAddress (j, i);
233  Ipv6Address addr = iaddr.GetAddress ();
234  if (addr.IsEqual (header.GetDestinationAddress ()))
235  {
236  if (j == iif)
237  {
238  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
239  }
240  else
241  {
242  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestinationAddress ());
243  }
244  lcb (p, header, iif);
245  return true;
246  }
247  NS_LOG_LOGIC ("Address " << addr << " not a match");
248  }
249  }
250 
251  if (header.GetDestinationAddress ().IsLinkLocal () ||
252  header.GetSourceAddress ().IsLinkLocal ())
253  {
254  NS_LOG_LOGIC ("Dropping packet not for me and with src or dst LinkLocal");
255  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
256  return false;
257  }
258 
259  // Check if input device supports IP forwarding
260  if (m_ipv6->IsForwarding (iif) == false)
261  {
262  NS_LOG_LOGIC ("Forwarding disabled for this interface");
263  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
264  return false;
265  }
266  // Next, try to find a route
267  NS_LOG_LOGIC ("Unicast destination");
268  Ptr<Ipv6Route> rtentry = Lookup (header.GetDestinationAddress ());
269 
270  if (rtentry != 0)
271  {
272  NS_LOG_LOGIC ("Found unicast destination - calling unicast callback");
273  ucb (idev, rtentry, p, header); // unicast forwarding callback
274  return true;
275  }
276  else
277  {
278  NS_LOG_LOGIC ("Did not find unicast destination - returning false");
279  return false; // Let other routing protocols try to handle this
280  }
281 }
282 
283 void RipNg::NotifyInterfaceUp (uint32_t i)
284 {
285  NS_LOG_FUNCTION (this << i);
286 
287  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
288  {
289  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
290  Ipv6Prefix networkMask = address.GetPrefix ();
291  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (networkMask);
292 
293  if (address != Ipv6Address () && networkMask != Ipv6Prefix ())
294  {
295  AddNetworkRouteTo (networkAddress, networkMask, i);
296  }
297  }
298 
299  if (!m_initialized)
300  {
301  return;
302  }
303 
304 
305  bool sendSocketFound = false;
306  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
307  {
308  if (iter->second == i)
309  {
310  sendSocketFound = true;
311  break;
312  }
313  }
314 
315  bool activeInterface = false;
316  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
317  {
318  activeInterface = true;
319  }
320 
321  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
322  {
323  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
324 
325  if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && sendSocketFound == false && activeInterface == true)
326  {
327  NS_LOG_LOGIC ("RIPng: adding sending socket to " << address.GetAddress ());
328  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
329  Ptr<Node> theNode = GetObject<Node> ();
330  Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
332  socket->Bind (local);
333  socket->BindToNetDevice (m_ipv6->GetNetDevice (i));
334  socket->ShutdownRecv ();
335  socket->SetIpv6RecvHopLimit (true);
336  m_sendSocketList[socket] = i;
337  }
338  else if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
339  {
341  }
342  }
343 
344  if (!m_recvSocket)
345  {
346  NS_LOG_LOGIC ("RIPng: adding receiving socket");
347  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
348  Ptr<Node> theNode = GetObject<Node> ();
349  m_recvSocket = Socket::CreateSocket (theNode, tid);
351  m_recvSocket->Bind (local);
352  m_recvSocket->SetRecvCallback (MakeCallback (&RipNg::Receive, this));
353  m_recvSocket->SetIpv6RecvHopLimit (true);
354  m_recvSocket->SetRecvPktInfo (true);
355  }
356 }
357 
358 void RipNg::NotifyInterfaceDown (uint32_t interface)
359 {
360  NS_LOG_FUNCTION (this << interface);
361 
362  /* remove all routes that are going through this interface */
363  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
364  {
365  if (it->first->GetInterface () == interface)
366  {
367  InvalidateRoute (it->first);
368  }
369  }
370 
371  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
372  {
373  NS_LOG_INFO ("Checking socket for interface " << interface);
374  if (iter->second == interface)
375  {
376  NS_LOG_INFO ("Removed socket for interface " << interface);
377  iter->first->Close ();
378  m_sendSocketList.erase (iter);
379  break;
380  }
381  }
382 
383  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
384  {
386  }
387 }
388 
390 {
391  NS_LOG_FUNCTION (this << interface << address);
392 
393  if (!m_ipv6->IsUp (interface))
394  {
395  return;
396  }
397 
398  if (m_interfaceExclusions.find (interface) != m_interfaceExclusions.end ())
399  {
400  return;
401  }
402 
403  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
404  Ipv6Prefix networkMask = address.GetPrefix ();
405 
406  if (address.GetAddress () != Ipv6Address () && address.GetPrefix () != Ipv6Prefix ())
407  {
408  AddNetworkRouteTo (networkAddress, networkMask, interface);
409  }
410 
412 }
413 
415 {
416  NS_LOG_FUNCTION (this << interface << address);
417 
418  if (!m_ipv6->IsUp (interface))
419  {
420  return;
421  }
422 
423  if (address.GetScope() != Ipv6InterfaceAddress::GLOBAL)
424  {
425  return;
426  }
427 
428  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
429  Ipv6Prefix networkMask = address.GetPrefix ();
430 
431  // Remove all routes that are going through this interface
432  // which reference this network
433  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
434  {
435  if (it->first->GetInterface () == interface
436  && it->first->IsNetwork ()
437  && it->first->GetDestNetwork () == networkAddress
438  && it->first->GetDestNetworkPrefix () == networkMask)
439  {
440  InvalidateRoute (it->first);
441  }
442  }
443 
444  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
445  {
447  }
448 
449 }
450 
451 void RipNg::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
452 {
453  NS_LOG_INFO (this << dst << mask << nextHop << interface << prefixToUse);
454  // \todo this can be used to add delegate routes
455 }
456 
457 void RipNg::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
458 {
459  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
460  // \todo this can be used to delete delegate routes
461 }
462 
464 {
465  NS_LOG_FUNCTION (this << ipv6);
466 
467  NS_ASSERT (m_ipv6 == 0 && ipv6 != 0);
468  uint32_t i = 0;
469  m_ipv6 = ipv6;
470 
471  for (i = 0; i < m_ipv6->GetNInterfaces (); i++)
472  {
473  if (m_ipv6->IsUp (i))
474  {
475  NotifyInterfaceUp (i);
476  }
477  else
478  {
480  }
481  }
482 }
483 
485 {
486  NS_LOG_FUNCTION (this << stream);
487 
488  std::ostream* os = stream->GetStream ();
489 
490  *os << "Node: " << m_ipv6->GetObject<Node> ()->GetId ()
491  << ", Time: " << Now().As (Time::S)
492  << ", Local time: " << GetObject<Node> ()->GetLocalTime ().As (Time::S)
493  << ", IPv6 RIPng table" << std::endl;
494 
495  if (!m_routes.empty ())
496  {
497  *os << "Destination Next Hop Flag Met Ref Use If" << std::endl;
498  for (RoutesCI it = m_routes.begin (); it != m_routes.end (); it++)
499  {
500  RipNgRoutingTableEntry* route = it->first;
502 
504  {
505  std::ostringstream dest, gw, mask, flags;
506 
507  dest << route->GetDest () << "/" << int(route->GetDestNetworkPrefix ().GetPrefixLength ());
508  *os << std::setiosflags (std::ios::left) << std::setw (31) << dest.str ();
509  gw << route->GetGateway ();
510  *os << std::setiosflags (std::ios::left) << std::setw (27) << gw.str ();
511  flags << "U";
512  if (route->IsHost ())
513  {
514  flags << "H";
515  }
516  else if (route->IsGateway ())
517  {
518  flags << "G";
519  }
520  *os << std::setiosflags (std::ios::left) << std::setw (5) << flags.str ();
521  *os << std::setiosflags (std::ios::left) << std::setw (4) << int(route->GetRouteMetric ());
522  // Ref ct not implemented
523  *os << "-" << " ";
524  // Use not implemented
525  *os << "-" << " ";
526  if (Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ())) != "")
527  {
528  *os << Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ()));
529  }
530  else
531  {
532  *os << route->GetInterface ();
533  }
534  *os << std::endl;
535  }
536  }
537  }
538  *os << std::endl;
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:266
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:144
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
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:346
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:102
virtual void NotifyInterfaceDown(uint32_t interface)
Notify when specified interface goes DOWN.
Definition: ripng.cc:358
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:1164
bool IsLinkLocalMulticast() const
If the IPv6 address is link-local multicast (ff02::/16).
Definition: second.py:1
#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:822
void SetPrefix(Ipv6Address prefix)
Set the prefix.
Definition: ripng-header.cc:85
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:67
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)
second
Definition: nstime.h:114
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
#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
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:339
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:446
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:341
Ipv6Address GetDestNetwork() const
Get the destination network.
void DoInitialize()
Start protocol operation.
Definition: ripng.cc:104
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:451
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
static EventId Schedule(Time const &delay, MEM mem_ptr, OBJ obj)
Schedule an event to expire after delay.
Definition: simulator.h:1216
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:96
AttributeValue implementation for Time.
Definition: nstime.h:957
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:142
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:1480
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:71
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:645
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:414
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:174
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:204
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:389
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)
Get the next random value, as a double in 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:463
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:958
Ipv6Address GetGateway() const
Get the gateway.
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:283
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:90
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ripng-header.cc:55
uint8_t GetHopLimit(void) const
Get the tag's Hop Limit.
Definition: socket.cc:651
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 TypeId GetTypeId(void)
Get the type ID.
Definition: ripng.cc:56
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:388
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:484
Address GetAddress(void) const
Get the tag's address.
Definition: socket.cc:530
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:829
A network Node.
Definition: node.h:56
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:895
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:743
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 ?
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:330
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:457
Status_e m_status
route status
Definition: ripng.h:153
a unique identifier for an interface.
Definition: type-id.h:58
#define RIPNG_PORT
Definition: ripng.cc:37
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:826
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:178
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:255
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)
Get a TypeId by name.
Definition: type-id.cc:751
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:95