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