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: " << Simulator::Now ().GetSeconds () << "s "
492  << "Ipv6 RIPng table" << std::endl;
493 
494  if (!m_routes.empty ())
495  {
496  *os << "Destination Next Hop Flag Met Ref Use If" << std::endl;
497  for (RoutesCI it = m_routes.begin (); it != m_routes.end (); it++)
498  {
499  RipNgRoutingTableEntry* route = it->first;
501 
503  {
504  std::ostringstream dest, gw, mask, flags;
505 
506  dest << route->GetDest () << "/" << int(route->GetDestNetworkPrefix ().GetPrefixLength ());
507  *os << std::setiosflags (std::ios::left) << std::setw (31) << dest.str ();
508  gw << route->GetGateway ();
509  *os << std::setiosflags (std::ios::left) << std::setw (27) << gw.str ();
510  flags << "U";
511  if (route->IsHost ())
512  {
513  flags << "H";
514  }
515  else if (route->IsGateway ())
516  {
517  flags << "G";
518  }
519  *os << std::setiosflags (std::ios::left) << std::setw (5) << flags.str ();
520  *os << std::setiosflags (std::ios::left) << std::setw (4) << int(route->GetRouteMetric ());
521  // Ref ct not implemented
522  *os << "-" << " ";
523  // Use not implemented
524  *os << "-" << " ";
525  if (Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ())) != "")
526  {
527  *os << Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ()));
528  }
529  else
530  {
531  *os << route->GetInterface ();
532  }
533  *os << std::endl;
534  }
535  }
536  }
537 }
538 
540 {
541  NS_LOG_FUNCTION (this);
542 
543  for (RoutesI j = m_routes.begin (); j != m_routes.end (); j = m_routes.erase (j))
544  {
545  delete j->first;
546  }
547  m_routes.clear ();
548 
553 
554  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
555  {
556  iter->first->Close ();
557  }
558  m_sendSocketList.clear ();
559 
560  m_recvSocket->Close ();
561  m_recvSocket = 0;
562 
563  m_ipv6 = 0;
564 
566 }
567 
568 
570 {
571  NS_LOG_FUNCTION (this << dst << interface);
572 
573  Ptr<Ipv6Route> rtentry = 0;
574  uint16_t longestMask = 0;
575 
576  /* when sending on link-local multicast, there have to be interface specified */
577  if (dst.IsLinkLocalMulticast ())
578  {
579  NS_ASSERT_MSG (interface, "Try to send on link-local multicast address, and no interface index is given!");
580  rtentry = Create<Ipv6Route> ();
581  rtentry->SetSource (m_ipv6->SourceAddressSelection (m_ipv6->GetInterfaceForDevice (interface), dst));
582  rtentry->SetDestination (dst);
583  rtentry->SetGateway (Ipv6Address::GetZero ());
584  rtentry->SetOutputDevice (interface);
585  return rtentry;
586  }
587 
588  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
589  {
590  RipNgRoutingTableEntry* j = it->first;
591 
593  {
594  Ipv6Prefix mask = j->GetDestNetworkPrefix ();
595  uint16_t maskLen = mask.GetPrefixLength ();
596  Ipv6Address entry = j->GetDestNetwork ();
597 
598  NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen);
599 
600  if (mask.IsMatch (dst, entry))
601  {
602  NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen);
603 
604  /* if interface is given, check the route will output on this interface */
605  if (!interface || interface == m_ipv6->GetNetDevice (j->GetInterface ()))
606  {
607  if (maskLen < longestMask)
608  {
609  NS_LOG_LOGIC ("Previous match longer, skipping");
610  continue;
611  }
612 
613  longestMask = maskLen;
614 
615  Ipv6RoutingTableEntry* route = j;
616  uint32_t interfaceIdx = route->GetInterface ();
617  rtentry = Create<Ipv6Route> ();
618 
619  if (route->GetGateway ().IsAny ())
620  {
621  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ()));
622  }
623  else if (route->GetDest ().IsAny ()) /* default route */
624  {
625  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetPrefixToUse ().IsAny () ? dst : route->GetPrefixToUse ()));
626  }
627  else
628  {
629  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ()));
630  }
631 
632  rtentry->SetDestination (route->GetDest ());
633  rtentry->SetGateway (route->GetGateway ());
634  rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interfaceIdx));
635  }
636  }
637  }
638  }
639 
640  if (rtentry)
641  {
642  NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (through " << rtentry->GetGateway () << ") at the end");
643  }
644  return rtentry;
645 }
646 
647 void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
648 {
649  NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface << prefixToUse);
650 
651  if (nextHop.IsLinkLocal())
652  {
653  NS_LOG_WARN ("Ripng::AddNetworkRouteTo - Next hop should be link-local");
654  }
655 
656  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, nextHop, interface, prefixToUse);
657  route->SetRouteMetric (1);
659  route->SetRouteChanged (true);
660 
661  m_routes.push_back (std::make_pair (route, EventId ()));
662 }
663 
664 void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
665 {
666  NS_LOG_FUNCTION (this << network << networkPrefix << interface);
667 
668  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, interface);
669  route->SetRouteMetric (1);
671  route->SetRouteChanged (true);
672 
673  m_routes.push_back (std::make_pair (route, EventId ()));
674 }
675 
677 {
678  NS_LOG_FUNCTION (this << *route);
679 
680  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
681  {
682  if (it->first == route)
683  {
685  route->SetRouteMetric (16);
686  route->SetRouteChanged (true);
687  if (it->second.IsRunning ())
688  {
689  it->second.Cancel ();
690  }
692  return;
693  }
694  }
695  NS_ABORT_MSG ("Ripng::InvalidateRoute - cannot find the route to update");
696 }
697 
699 {
700  NS_LOG_FUNCTION (this << *route);
701 
702  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
703  {
704  if (it->first == route)
705  {
706  delete route;
707  m_routes.erase (it);
708  return;
709  }
710  }
711  NS_ABORT_MSG ("Ripng::DeleteRoute - cannot find the route to delete");
712 }
713 
714 
716 {
717  NS_LOG_FUNCTION (this << socket);
718 
719  Ptr<Packet> packet = socket->Recv ();
720  NS_LOG_INFO ("Received " << *packet);
721 
722  Ipv6PacketInfoTag interfaceInfo;
723  if (!packet->RemovePacketTag (interfaceInfo))
724  {
725  NS_ABORT_MSG ("No incoming interface on RIPng message, aborting.");
726  }
727  uint32_t incomingIf = interfaceInfo.GetRecvIf ();
728  Ptr<Node> node = this->GetObject<Node> ();
729  Ptr<NetDevice> dev = node->GetDevice (incomingIf);
730  uint32_t ipInterfaceIndex = m_ipv6->GetInterfaceForDevice (dev);
731 
732  SocketIpv6HopLimitTag hoplimitTag;
733  if (!packet->RemovePacketTag (hoplimitTag))
734  {
735  NS_ABORT_MSG ("No incoming Hop Count on RIPng message, aborting.");
736  }
737  uint8_t hopLimit = hoplimitTag.GetHopLimit ();
738 
739  SocketAddressTag tag;
740  if (!packet->RemovePacketTag (tag))
741  {
742  NS_ABORT_MSG ("No incoming sender address on RIPng message, aborting.");
743  }
744  Ipv6Address senderAddress = Inet6SocketAddress::ConvertFrom (tag.GetAddress ()).GetIpv6 ();
745  uint16_t senderPort = Inet6SocketAddress::ConvertFrom (tag.GetAddress ()).GetPort ();
746 
747  int32_t interfaceForAddress = m_ipv6->GetInterfaceForAddress (senderAddress);
748  if (interfaceForAddress != -1)
749  {
750  NS_LOG_LOGIC ("Ignoring a packet sent by myself.");
751  return;
752  }
753 
754  RipNgHeader hdr;
755  packet->RemoveHeader (hdr);
756 
757  if (hdr.GetCommand () == RipNgHeader::RESPONSE)
758  {
759  HandleResponses (hdr, senderAddress, ipInterfaceIndex, hopLimit);
760  }
761  else if (hdr.GetCommand () == RipNgHeader::REQUEST)
762  {
763  HandleRequests (hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
764  }
765  else
766  {
767  NS_LOG_LOGIC ("Ignoring message with unknown command: " << int (hdr.GetCommand ()));
768  }
769  return;
770 }
771 
772 void RipNg::HandleRequests (RipNgHeader requestHdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
773 {
774  NS_LOG_FUNCTION (this << senderAddress << int (senderPort) << incomingInterface << int (hopLimit) << requestHdr);
775 
776  std::list<RipNgRte> rtes = requestHdr.GetRteList ();
777 
778  if (rtes.empty ())
779  {
780  return;
781  }
782 
783  // check if it's a request for the full table from a neighbor
784  if (rtes.size () == 1 && senderAddress.IsLinkLocal ())
785  {
786  if (rtes.begin ()->GetPrefix () == Ipv6Address::GetAny () &&
787  rtes.begin ()->GetPrefixLen () == 0 &&
788  rtes.begin ()->GetRouteMetric () == 16)
789  {
790  // Output whole thing. Use Split Horizon
791  if (m_interfaceExclusions.find (incomingInterface) == m_interfaceExclusions.end ())
792  {
793  // we use one of the sending sockets, as they're bound to the right interface
794  // and the local address might be used on different interfaces.
795  Ptr<Socket> sendingSoket;
796  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
797  {
798  if (iter->second == incomingInterface)
799  {
800  sendingSoket = iter->first;
801  }
802  }
803  NS_ASSERT_MSG (sendingSoket, "HandleRequest - Impossible to find a socket to send the reply");
804 
805  uint16_t mtu = m_ipv6->GetMtu (incomingInterface);
806  uint16_t maxRte = (mtu - Ipv6Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipNgHeader ().GetSerializedSize ()) / RipNgRte ().GetSerializedSize ();
807 
808  Ptr<Packet> p = Create<Packet> ();
810  p->RemovePacketTag (tag);
811  tag.SetHopLimit (255);
812  p->AddPacketTag (tag);
813 
814  RipNgHeader hdr;
816 
817  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
818  {
819  bool splitHorizoning = (rtIter->first->GetInterface () == incomingInterface);
820 
821  Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ());
822 
823  bool isGlobal = (rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL);
824  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv6Address::GetAny ()) &&
825  (rtIter->first->GetDestNetworkPrefix () == Ipv6Prefix::GetZero ()) &&
826  (rtIter->first->GetInterface () != incomingInterface));
827 
828  if ((isGlobal || isDefaultRoute) &&
829  (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID) )
830  {
831  RipNgRte rte;
832  rte.SetPrefix (rtIter->first->GetDestNetwork ());
833  rte.SetPrefixLen (rtIter->first->GetDestNetworkPrefix ().GetPrefixLength ());
834  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
835  {
836  rte.SetRouteMetric (16);
837  }
838  else
839  {
840  rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
841  }
842  rte.SetRouteTag (rtIter->first->GetRouteTag ());
844  (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
845  {
846  hdr.AddRte (rte);
847  }
848  }
849  if (hdr.GetRteNumber () == maxRte)
850  {
851  p->AddHeader (hdr);
852  NS_LOG_DEBUG ("SendTo: " << *p);
853  sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, RIPNG_PORT));
854  p->RemoveHeader (hdr);
855  hdr.ClearRtes ();
856  }
857  }
858  if (hdr.GetRteNumber () > 0)
859  {
860  p->AddHeader (hdr);
861  NS_LOG_DEBUG ("SendTo: " << *p);
862  sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, RIPNG_PORT));
863  }
864  }
865  }
866  }
867  else
868  {
869  // note: we got the request as a single packet, so no check is necessary for MTU limit
870 
871  // we use one of the sending sockets, as they're bound to the right interface
872  // and the local address might be used on different interfaces.
873  Ptr<Socket> sendingSoket;
874  if (senderAddress.IsLinkLocal ())
875  {
876  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
877  {
878  if (iter->second == incomingInterface)
879  {
880  sendingSoket = iter->first;
881  }
882  }
883  }
884  else
885  {
886  sendingSoket = m_recvSocket;
887  }
888 
889  Ptr<Packet> p = Create<Packet> ();
891  p->RemovePacketTag (tag);
892  tag.SetHopLimit (255);
893  p->AddPacketTag (tag);
894 
895  RipNgHeader hdr;
897 
898  for (std::list<RipNgRte>::iterator iter = rtes.begin ();
899  iter != rtes.end (); iter++)
900  {
901  bool found = false;
902  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
903  {
904  Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ());
905  if ((rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL) &&
906  (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID))
907  {
908  Ipv6Address requestedAddress = iter->GetPrefix ();
909  requestedAddress.CombinePrefix (Ipv6Prefix (iter->GetPrefixLen ()));
910  Ipv6Address rtAddress = rtIter->first->GetDestNetwork ();
911  rtAddress.CombinePrefix (rtIter->first->GetDestNetworkPrefix ());
912 
913  if (requestedAddress == rtAddress)
914  {
915  iter->SetRouteMetric (rtIter->first->GetRouteMetric ());
916  iter->SetRouteTag (rtIter->first->GetRouteTag ());
917  hdr.AddRte (*iter);
918  found = true;
919  break;
920  }
921  }
922  }
923  if (!found)
924  {
925  iter->SetRouteMetric (16);
926  iter->SetRouteTag (0);
927  hdr.AddRte (*iter);
928  }
929  }
930  p->AddHeader (hdr);
931  NS_LOG_DEBUG ("SendTo: " << *p);
932  sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, senderPort));
933  }
934 
935 }
936 
937 void RipNg::HandleResponses (RipNgHeader hdr, Ipv6Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
938 {
939  NS_LOG_FUNCTION (this << senderAddress << incomingInterface << int (hopLimit) << hdr);
940 
941  if (m_interfaceExclusions.find (incomingInterface) != m_interfaceExclusions.end ())
942  {
943  NS_LOG_LOGIC ("Ignoring an update message from an excluded interface: " << incomingInterface);
944  return;
945  }
946 
947  if (!senderAddress.IsLinkLocal ())
948  {
949  NS_LOG_LOGIC ("Ignoring an update message from a non-link-local source: " << senderAddress);
950  return;
951  }
952 
953  if (hopLimit != 255)
954  {
955  NS_LOG_LOGIC ("Ignoring an update message with suspicious hop count: " << int (hopLimit));
956  return;
957  }
958 
959  std::list<RipNgRte> rtes = hdr.GetRteList ();
960 
961  // validate the RTEs before processing
962  for (std::list<RipNgRte>::iterator iter = rtes.begin ();
963  iter != rtes.end (); iter++)
964  {
965  if (iter->GetRouteMetric () == 0 || iter->GetRouteMetric () > 16)
966  {
967  NS_LOG_LOGIC ("Ignoring an update message with malformed metric: " << int (iter->GetRouteMetric ()));
968  return;
969  }
970  if (iter->GetPrefixLen () > 128)
971  {
972  NS_LOG_LOGIC ("Ignoring an update message with malformed prefix length: " << int (iter->GetPrefixLen ()));
973  return;
974  }
975  if (iter->GetPrefix ().IsLocalhost () ||
976  iter->GetPrefix ().IsLinkLocal () ||
977  iter->GetPrefix ().IsMulticast ())
978  {
979  NS_LOG_LOGIC ("Ignoring an update message with wrong prefixes: " << iter->GetPrefix ());
980  return;
981  }
982  }
983 
984  bool changed = false;
985 
986  for (std::list<RipNgRte>::iterator iter = rtes.begin ();
987  iter != rtes.end (); iter++)
988  {
989  Ipv6Prefix rtePrefix = Ipv6Prefix (iter->GetPrefixLen ());
990  Ipv6Address rteAddr = iter->GetPrefix ().CombinePrefix (rtePrefix);
991 
992  NS_LOG_LOGIC ("Processing RTE " << *iter);
993 
994  uint8_t interfaceMetric = 1;
995  if (m_interfaceMetrics.find (incomingInterface) != m_interfaceMetrics.end ())
996  {
997  interfaceMetric = m_interfaceMetrics[incomingInterface];
998  }
999  uint8_t rteMetric = std::min (iter->GetRouteMetric () + interfaceMetric, 16);
1000  RoutesI it;
1001  bool found = false;
1002  for (it = m_routes.begin (); it != m_routes.end (); it++)
1003  {
1004  if (it->first->GetDestNetwork () == rteAddr &&
1005  it->first->GetDestNetworkPrefix () == rtePrefix)
1006  {
1007  found = true;
1008  if (rteMetric < it->first->GetRouteMetric ())
1009  {
1010  if (senderAddress != it->first->GetGateway ())
1011  {
1012  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
1013  delete it->first;
1014  it->first = route;
1015  }
1016  it->first->SetRouteMetric (rteMetric);
1017  it->first->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID);
1018  it->first->SetRouteTag (iter->GetRouteTag ());
1019  it->first->SetRouteChanged (true);
1020  it->second.Cancel ();
1021  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first);
1022  changed = true;
1023  }
1024  else if (rteMetric == it->first->GetRouteMetric ())
1025  {
1026  if (senderAddress == it->first->GetGateway ())
1027  {
1028  it->second.Cancel ();
1029  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first);
1030  }
1031  else
1032  {
1033  if (Simulator::GetDelayLeft (it->second) < m_timeoutDelay/2)
1034  {
1035  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
1036  route->SetRouteMetric (rteMetric);
1038  route->SetRouteTag (iter->GetRouteTag ());
1039  route->SetRouteChanged (true);
1040  delete it->first;
1041  it->first = route;
1042  it->second.Cancel ();
1043  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, route);
1044  changed = true;
1045  }
1046  }
1047  }
1048  else if (rteMetric > it->first->GetRouteMetric () && senderAddress == it->first->GetGateway ())
1049  {
1050  it->second.Cancel ();
1051  if (rteMetric < 16)
1052  {
1053  it->first->SetRouteMetric (rteMetric);
1054  it->first->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID);
1055  it->first->SetRouteTag (iter->GetRouteTag ());
1056  it->first->SetRouteChanged (true);
1057  it->second.Cancel ();
1058  it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first);
1059  }
1060  else
1061  {
1062  InvalidateRoute (it->first);
1063  }
1064  changed = true;
1065  }
1066  }
1067  }
1068  if (!found && rteMetric != 16)
1069  {
1070  NS_LOG_LOGIC ("Received a RTE with new route, adding.");
1071 
1072  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ());
1073  route->SetRouteMetric (rteMetric);
1075  route->SetRouteChanged (true);
1076  m_routes.push_front (std::make_pair (route, EventId ()));
1077  EventId invalidateEvent = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, route);
1078  (m_routes.begin ())->second = invalidateEvent;
1079  changed = true;
1080  }
1081  }
1082 
1083  if (changed)
1084  {
1086  }
1087 }
1088 
1089 void RipNg::DoSendRouteUpdate (bool periodic)
1090 {
1091  NS_LOG_FUNCTION (this << (periodic ? " periodic" : " triggered"));
1092 
1093  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
1094  {
1095  uint32_t interface = iter->second;
1096 
1097  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1098  {
1099  uint16_t mtu = m_ipv6->GetMtu (interface);
1100  uint16_t maxRte = (mtu - Ipv6Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipNgHeader ().GetSerializedSize ()) / RipNgRte ().GetSerializedSize ();
1101 
1102  Ptr<Packet> p = Create<Packet> ();
1104  tag.SetHopLimit (255);
1105  p->AddPacketTag (tag);
1106 
1107  RipNgHeader hdr;
1109 
1110  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1111  {
1112  bool splitHorizoning = (rtIter->first->GetInterface () == interface);
1113  Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ());
1114 
1115  NS_LOG_DEBUG ("Processing RT " << rtDestAddr << " " << int(rtIter->first->IsRouteChanged ()));
1116 
1117  bool isGlobal = (rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL);
1118  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv6Address::GetAny ()) &&
1119  (rtIter->first->GetDestNetworkPrefix () == Ipv6Prefix::GetZero ()) &&
1120  (rtIter->first->GetInterface () != interface));
1121 
1122  if ((isGlobal || isDefaultRoute) &&
1123  (periodic || rtIter->first->IsRouteChanged ()))
1124  {
1125  RipNgRte rte;
1126  rte.SetPrefix (rtIter->first->GetDestNetwork ());
1127  rte.SetPrefixLen (rtIter->first->GetDestNetworkPrefix ().GetPrefixLength ());
1128  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
1129  {
1130  rte.SetRouteMetric (16);
1131  }
1132  else
1133  {
1134  rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
1135  }
1136  rte.SetRouteTag (rtIter->first->GetRouteTag ());
1137  if (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning)
1138  {
1139  hdr.AddRte (rte);
1140  }
1142  {
1143  hdr.AddRte (rte);
1144  }
1145  }
1146  if (hdr.GetRteNumber () == maxRte)
1147  {
1148  p->AddHeader (hdr);
1149  NS_LOG_DEBUG ("SendTo: " << *p);
1150  iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT));
1151  p->RemoveHeader (hdr);
1152  hdr.ClearRtes ();
1153  }
1154  }
1155  if (hdr.GetRteNumber () > 0)
1156  {
1157  p->AddHeader (hdr);
1158  NS_LOG_DEBUG ("SendTo: " << *p);
1159  iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT));
1160  }
1161  }
1162  }
1163  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1164  {
1165  rtIter->first->SetRouteChanged (false);
1166  }
1167 }
1168 
1170 {
1171  NS_LOG_FUNCTION (this);
1172 
1174  {
1175  NS_LOG_LOGIC ("Skipping Triggered Update due to cooldown");
1176  return;
1177  }
1178 
1179  // DoSendRouteUpdate (false);
1180 
1181  // note: The RFC states:
1182  // After a triggered
1183  // update is sent, a timer should be set for a random interval between 1
1184  // and 5 seconds. If other changes that would trigger updates occur
1185  // before the timer expires, a single update is triggered when the timer
1186  // expires. The timer is then reset to another random value between 1
1187  // and 5 seconds. Triggered updates may be suppressed if a regular
1188  // update is due by the time the triggered update would be sent.
1189  // Here we rely on this:
1190  // When an update occurs (either Triggered or Periodic) the "IsChanged ()"
1191  // route field will be cleared.
1192  // Hence, the following Triggered Update will be fired, but will not send
1193  // any route update.
1194 
1197 }
1198 
1200 {
1201  NS_LOG_FUNCTION (this);
1202 
1204  {
1206  }
1207 
1208  DoSendRouteUpdate (true);
1209 
1212 }
1213 
1214 std::set<uint32_t> RipNg::GetInterfaceExclusions () const
1215 {
1216  return m_interfaceExclusions;
1217 }
1218 
1219 void RipNg::SetInterfaceExclusions (std::set<uint32_t> exceptions)
1220 {
1221  NS_LOG_FUNCTION (this);
1222 
1223  m_interfaceExclusions = exceptions;
1224 }
1225 
1226 uint8_t RipNg::GetInterfaceMetric (uint32_t interface) const
1227 {
1228  NS_LOG_FUNCTION (this << interface);
1229 
1230  std::map<uint32_t, uint8_t>::const_iterator iter = m_interfaceMetrics.find (interface);
1231  if (iter != m_interfaceMetrics.end ())
1232  {
1233  return iter->second;
1234  }
1235  return 1;
1236 }
1237 
1238 void RipNg::SetInterfaceMetric (uint32_t interface, uint8_t metric)
1239 {
1240  NS_LOG_FUNCTION (this << interface << int (metric));
1241 
1242  if (metric < 16)
1243  {
1244  m_interfaceMetrics[interface] = metric;
1245  }
1246 }
1247 
1249 {
1250  NS_LOG_FUNCTION (this);
1251 
1252  Ptr<Packet> p = Create<Packet> ();
1254  p->RemovePacketTag (tag);
1255  tag.SetHopLimit (255);
1256  p->AddPacketTag (tag);
1257 
1258  RipNgHeader hdr;
1260 
1261  RipNgRte rte;
1262  rte.SetPrefix (Ipv6Address::GetAny ());
1263  rte.SetPrefixLen (0);
1264  rte.SetRouteMetric (16);
1265 
1266  hdr.AddRte (rte);
1267  p->AddHeader (hdr);
1268 
1269  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
1270  {
1271  uint32_t interface = iter->second;
1272 
1273  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1274  {
1275  NS_LOG_DEBUG ("SendTo: " << *p);
1276  iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT));
1277  }
1278  }
1279 }
1280 
1281 void RipNg::AddDefaultRouteTo (Ipv6Address nextHop, uint32_t interface)
1282 {
1283  NS_LOG_FUNCTION (this << interface);
1284 
1285  AddNetworkRouteTo (Ipv6Address ("::"), Ipv6Prefix::GetZero (), nextHop, interface, Ipv6Address ("::"));
1286 }
1287 
1288 
1289 /*
1290  * RipNgRoutingTableEntry
1291  */
1292 
1294  : m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false)
1295 {
1296 }
1297 
1298 RipNgRoutingTableEntry::RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
1299  : Ipv6RoutingTableEntry ( RipNgRoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, nextHop, interface, prefixToUse) ),
1300  m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false)
1301 {
1302 }
1303 
1304 RipNgRoutingTableEntry::RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
1305  : Ipv6RoutingTableEntry ( Ipv6RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, interface) ),
1306  m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false)
1307 {
1308 }
1309 
1311 {
1312 }
1313 
1314 
1315 void RipNgRoutingTableEntry::SetRouteTag (uint16_t routeTag)
1316 {
1317  if (m_tag != routeTag)
1318  {
1319  m_tag = routeTag;
1320  m_changed = true;
1321  }
1322 }
1323 
1325 {
1326  return m_tag;
1327 }
1328 
1329 void RipNgRoutingTableEntry::SetRouteMetric (uint8_t routeMetric)
1330 {
1331  if (m_metric != routeMetric)
1332  {
1333  m_metric = routeMetric;
1334  m_changed = true;
1335  }
1336 }
1337 
1339 {
1340  return m_metric;
1341 }
1342 
1344 {
1345  if (m_status != status)
1346  {
1347  m_status = status;
1348  m_changed = true;
1349  }
1350 }
1351 
1353 {
1354  return m_status;
1355 }
1356 
1358 {
1359  m_changed = changed;
1360 }
1361 
1363 {
1364  return m_changed;
1365 }
1366 
1367 
1368 std::ostream & operator << (std::ostream& os, const RipNgRoutingTableEntry& rte)
1369 {
1370  os << static_cast<const Ipv6RoutingTableEntry &>(rte);
1371  os << ", metric: " << int (rte.GetRouteMetric ()) << ", tag: " << int (rte.GetRouteTag ());
1372 
1373  return os;
1374 }
1375 
1376 
1377 }
1378 
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:1315
void AddNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
Add route to network.
Definition: ripng.cc:647
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:1219
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)
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:1238
void SendUnsolicitedRouteUpdate(void)
Send Unsolicited Routing Updates on all interfaces.
Definition: ripng.cc:1199
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:715
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:539
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:1281
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:676
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:1169
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:1329
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:1226
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:135
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:1089
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:1357
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:698
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:1352
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
Definition: ripng.h:383
virtual ~RipNgRoutingTableEntry()
Definition: ripng.cc:1310
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:1338
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:937
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:772
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.
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:1214
void SetRouteStatus(Status_e status)
Set the route status.
Definition: ripng.cc:1343
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:1324
#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:1248
Ipv6InterfaceAddress::Scope_e GetScope() const
Get address scope.
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: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: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: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:569
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:1293
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:1362
void SetPrefixLen(uint8_t prefixLen)
Set the prefix length.
Definition: ripng-header.cc:95