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