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