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);
140  Inet6SocketAddress local = Inet6SocketAddress (address.GetAddress (), RIPNG_PORT);
141  socket->BindToNetDevice (m_ipv6->GetNetDevice (i));
142  int ret = socket->Bind (local);
143  NS_ASSERT_MSG (ret == 0, "Bind unsuccessful");
144  socket->SetRecvCallback (MakeCallback (&RipNg::Receive, this));
145  socket->SetIpv6RecvHopLimit (true);
146  socket->SetRecvPktInfo (true);
147  m_unicastSocketList[socket] = i;
148  }
149  else if (m_ipv6->GetAddress (i, j).GetScope() == Ipv6InterfaceAddress::GLOBAL)
150  {
151  addedGlobal = true;
152  }
153  }
154  }
155 
157  {
158  NS_LOG_LOGIC ("RIPng: adding receiving socket");
159  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
160  Ptr<Node> theNode = GetObject<Node> ();
163  m_multicastRecvSocket->Bind (local);
167  }
168 
169 
170  if (addedGlobal)
171  {
174  }
175 
176  delay = Seconds (m_rng->GetValue (0.01, m_startupDelay.GetSeconds ()));
178 
180 }
181 
183 {
184  NS_LOG_FUNCTION (this << header << oif);
185 
186  Ipv6Address destination = header.GetDestinationAddress ();
187  Ptr<Ipv6Route> rtentry = 0;
188 
189  if (destination.IsMulticast ())
190  {
191  // Note: Multicast routes for outbound packets are stored in the
192  // normal unicast table. An implication of this is that it is not
193  // possible to source multicast datagrams on multiple interfaces.
194  // This is a well-known property of sockets implementation on
195  // many Unix variants.
196  // So, we just log it and fall through to LookupStatic ()
197  NS_LOG_LOGIC ("RouteOutput (): Multicast destination");
198  }
199 
200  rtentry = Lookup (destination, oif);
201  if (rtentry)
202  {
203  sockerr = Socket::ERROR_NOTERROR;
204  }
205  else
206  {
207  sockerr = Socket::ERROR_NOROUTETOHOST;
208  }
209  return rtentry;
210 }
211 
215 {
216  NS_LOG_FUNCTION (this << p << header << header.GetSourceAddress () << header.GetDestinationAddress () << idev);
217 
218  NS_ASSERT (m_ipv6 != 0);
219  // Check if input device supports IP
220  NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0);
221  uint32_t iif = m_ipv6->GetInterfaceForDevice (idev);
222  Ipv6Address dst = header.GetDestinationAddress ();
223 
224  if (dst.IsMulticast ())
225  {
226  NS_LOG_LOGIC ("Multicast route not supported by RIPng");
227  return false; // Let other routing protocols try to handle this
228  }
229 
230  if (header.GetDestinationAddress ().IsLinkLocal () ||
231  header.GetSourceAddress ().IsLinkLocal ())
232  {
233  NS_LOG_LOGIC ("Dropping packet not for me and with src or dst LinkLocal");
234  if (!ecb.IsNull ())
235  {
236  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
237  }
238  return false;
239  }
240 
241  // Check if input device supports IP forwarding
242  if (m_ipv6->IsForwarding (iif) == false)
243  {
244  NS_LOG_LOGIC ("Forwarding disabled for this interface");
245  if (!ecb.IsNull ())
246  {
247  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
248  }
249  return true;
250  }
251  // Next, try to find a route
252  NS_LOG_LOGIC ("Unicast destination");
253  Ptr<Ipv6Route> rtentry = Lookup (header.GetDestinationAddress ());
254 
255  if (rtentry != 0)
256  {
257  NS_LOG_LOGIC ("Found unicast destination - calling unicast callback");
258  ucb (idev, rtentry, p, header); // unicast forwarding callback
259  return true;
260  }
261  else
262  {
263  NS_LOG_LOGIC ("Did not find unicast destination - returning false");
264  return false; // Let other routing protocols try to handle this
265  }
266 }
267 
268 void RipNg::NotifyInterfaceUp (uint32_t i)
269 {
270  NS_LOG_FUNCTION (this << i);
271 
272  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
273  {
274  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
275  Ipv6Prefix networkMask = address.GetPrefix ();
276  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (networkMask);
277 
278  if (address.GetScope () == Ipv6InterfaceAddress::GLOBAL)
279  {
280  AddNetworkRouteTo (networkAddress, networkMask, i);
281  }
282  }
283 
284  if (!m_initialized)
285  {
286  return;
287  }
288 
289 
290  bool sendSocketFound = false;
291  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
292  {
293  if (iter->second == i)
294  {
295  sendSocketFound = true;
296  break;
297  }
298  }
299 
300  bool activeInterface = false;
301  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
302  {
303  activeInterface = true;
304  m_ipv6->SetForwarding (i, true);
305  }
306 
307  for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++)
308  {
309  Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j);
310 
311  if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && sendSocketFound == false && activeInterface == true)
312  {
313  NS_LOG_LOGIC ("RIPng: adding sending socket to " << address.GetAddress ());
314  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
315  Ptr<Node> theNode = GetObject<Node> ();
316  Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
317  Inet6SocketAddress local = Inet6SocketAddress (address.GetAddress (), RIPNG_PORT);
318  socket->BindToNetDevice (m_ipv6->GetNetDevice (i));
319  socket->Bind (local);
320  socket->SetRecvCallback (MakeCallback (&RipNg::Receive, this));
321  socket->SetIpv6RecvHopLimit (true);
322  socket->SetRecvPktInfo (true);
323  m_unicastSocketList[socket] = i;
324  }
325  else if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
326  {
328  }
329  }
330 
332  {
333  NS_LOG_LOGIC ("RIPng: adding receiving socket");
334  TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
335  Ptr<Node> theNode = GetObject<Node> ();
338  m_multicastRecvSocket->Bind (local);
342  }
343 }
344 
345 void RipNg::NotifyInterfaceDown (uint32_t interface)
346 {
347  NS_LOG_FUNCTION (this << interface);
348 
349  /* remove all routes that are going through this interface */
350  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
351  {
352  if (it->first->GetInterface () == interface)
353  {
354  InvalidateRoute (it->first);
355  }
356  }
357 
358  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
359  {
360  NS_LOG_INFO ("Checking socket for interface " << interface);
361  if (iter->second == interface)
362  {
363  NS_LOG_INFO ("Removed socket for interface " << interface);
364  iter->first->Close ();
365  m_unicastSocketList.erase (iter);
366  break;
367  }
368  }
369 
370  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
371  {
373  }
374 }
375 
377 {
378  NS_LOG_FUNCTION (this << interface << address);
379 
380  if (!m_ipv6->IsUp (interface))
381  {
382  return;
383  }
384 
385  if (m_interfaceExclusions.find (interface) != m_interfaceExclusions.end ())
386  {
387  return;
388  }
389 
390  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
391  Ipv6Prefix networkMask = address.GetPrefix ();
392 
393  if (address.GetScope () == Ipv6InterfaceAddress::GLOBAL)
394  {
395  AddNetworkRouteTo (networkAddress, networkMask, interface);
396  }
397 
399 }
400 
402 {
403  NS_LOG_FUNCTION (this << interface << address);
404 
405  if (!m_ipv6->IsUp (interface))
406  {
407  return;
408  }
409 
410  if (address.GetScope() != Ipv6InterfaceAddress::GLOBAL)
411  {
412  return;
413  }
414 
415  Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ());
416  Ipv6Prefix networkMask = address.GetPrefix ();
417 
418  // Remove all routes that are going through this interface
419  // which reference this network
420  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
421  {
422  if (it->first->GetInterface () == interface
423  && it->first->IsNetwork ()
424  && it->first->GetDestNetwork () == networkAddress
425  && it->first->GetDestNetworkPrefix () == networkMask)
426  {
427  InvalidateRoute (it->first);
428  }
429  }
430 
431  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
432  {
434  }
435 
436 }
437 
438 void RipNg::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
439 {
440  NS_LOG_INFO (this << dst << mask << nextHop << interface << prefixToUse);
441  // \todo this can be used to add delegate routes
442 }
443 
444 void RipNg::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
445 {
446  NS_LOG_FUNCTION (this << dst << mask << nextHop << interface);
447  // \todo this can be used to delete delegate routes
448 }
449 
451 {
452  NS_LOG_FUNCTION (this << ipv6);
453 
454  NS_ASSERT (m_ipv6 == 0 && ipv6 != 0);
455  uint32_t i = 0;
456  m_ipv6 = ipv6;
457 
458  for (i = 0; i < m_ipv6->GetNInterfaces (); i++)
459  {
460  if (m_ipv6->IsUp (i))
461  {
462  NotifyInterfaceUp (i);
463  }
464  else
465  {
467  }
468  }
469 }
470 
472 {
473  NS_LOG_FUNCTION (this << stream);
474 
475  std::ostream* os = stream->GetStream ();
476 
477  *os << "Node: " << m_ipv6->GetObject<Node> ()->GetId ()
478  << ", Time: " << Now().As (unit)
479  << ", Local time: " << GetObject<Node> ()->GetLocalTime ().As (unit)
480  << ", IPv6 RIPng table" << std::endl;
481 
482  if (!m_routes.empty ())
483  {
484  *os << "Destination Next Hop Flag Met Ref Use If" << std::endl;
485  for (RoutesCI it = m_routes.begin (); it != m_routes.end (); it++)
486  {
487  RipNgRoutingTableEntry* route = it->first;
489 
491  {
492  std::ostringstream dest, gw, mask, flags;
493 
494  dest << route->GetDest () << "/" << int(route->GetDestNetworkPrefix ().GetPrefixLength ());
495  *os << std::setiosflags (std::ios::left) << std::setw (31) << dest.str ();
496  gw << route->GetGateway ();
497  *os << std::setiosflags (std::ios::left) << std::setw (27) << gw.str ();
498  flags << "U";
499  if (route->IsHost ())
500  {
501  flags << "H";
502  }
503  else if (route->IsGateway ())
504  {
505  flags << "G";
506  }
507  *os << std::setiosflags (std::ios::left) << std::setw (5) << flags.str ();
508  *os << std::setiosflags (std::ios::left) << std::setw (4) << int(route->GetRouteMetric ());
509  // Ref ct not implemented
510  *os << "-" << " ";
511  // Use not implemented
512  *os << "-" << " ";
513  if (Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ())) != "")
514  {
515  *os << Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ()));
516  }
517  else
518  {
519  *os << route->GetInterface ();
520  }
521  *os << std::endl;
522  }
523  }
524  }
525  *os << std::endl;
526 }
527 
529 {
530  NS_LOG_FUNCTION (this);
531 
532  for (RoutesI j = m_routes.begin (); j != m_routes.end (); j = m_routes.erase (j))
533  {
534  delete j->first;
535  }
536  m_routes.clear ();
537 
542 
543  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
544  {
545  iter->first->Close ();
546  }
547  m_unicastSocketList.clear ();
548 
551 
552  m_ipv6 = 0;
553 
555 }
556 
557 
559 {
560  NS_LOG_FUNCTION (this << dst << interface);
561 
562  Ptr<Ipv6Route> rtentry = 0;
563  uint16_t longestMask = 0;
564 
565  /* when sending on link-local multicast, there have to be interface specified */
566  if (dst.IsLinkLocalMulticast ())
567  {
568  NS_ASSERT_MSG (interface, "Try to send on link-local multicast address, and no interface index is given!");
569  rtentry = Create<Ipv6Route> ();
570  rtentry->SetSource (m_ipv6->SourceAddressSelection (m_ipv6->GetInterfaceForDevice (interface), dst));
571  rtentry->SetDestination (dst);
572  rtentry->SetGateway (Ipv6Address::GetZero ());
573  rtentry->SetOutputDevice (interface);
574  return rtentry;
575  }
576 
577  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
578  {
579  RipNgRoutingTableEntry* j = it->first;
580 
582  {
583  Ipv6Prefix mask = j->GetDestNetworkPrefix ();
584  uint16_t maskLen = mask.GetPrefixLength ();
585  Ipv6Address entry = j->GetDestNetwork ();
586 
587  NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen);
588 
589  if (mask.IsMatch (dst, entry))
590  {
591  NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen);
592 
593  /* if interface is given, check the route will output on this interface */
594  if (!interface || interface == m_ipv6->GetNetDevice (j->GetInterface ()))
595  {
596  if (maskLen < longestMask)
597  {
598  NS_LOG_LOGIC ("Previous match longer, skipping");
599  continue;
600  }
601 
602  longestMask = maskLen;
603 
604  Ipv6RoutingTableEntry* route = j;
605  uint32_t interfaceIdx = route->GetInterface ();
606  rtentry = Create<Ipv6Route> ();
607 
608  if (route->GetGateway ().IsAny ())
609  {
610  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ()));
611  }
612  else if (route->GetDest ().IsAny ()) /* default route */
613  {
614  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetPrefixToUse ().IsAny () ? dst : route->GetPrefixToUse ()));
615  }
616  else
617  {
618  rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ()));
619  }
620 
621  rtentry->SetDestination (route->GetDest ());
622  rtentry->SetGateway (route->GetGateway ());
623  rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interfaceIdx));
624  }
625  }
626  }
627  }
628 
629  if (rtentry)
630  {
631  NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (through " << rtentry->GetGateway () << ") at the end");
632  }
633  return rtentry;
634 }
635 
636 void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
637 {
638  NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface << prefixToUse);
639 
640  if (nextHop.IsLinkLocal())
641  {
642  NS_LOG_WARN ("Ripng::AddNetworkRouteTo - Next hop should be link-local");
643  }
644 
645  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, nextHop, interface, prefixToUse);
646  route->SetRouteMetric (1);
648  route->SetRouteChanged (true);
649 
650  m_routes.push_back (std::make_pair (route, EventId ()));
651 }
652 
653 void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
654 {
655  NS_LOG_FUNCTION (this << network << networkPrefix << interface);
656 
657  RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, interface);
658  route->SetRouteMetric (1);
660  route->SetRouteChanged (true);
661 
662  m_routes.push_back (std::make_pair (route, EventId ()));
663 }
664 
666 {
667  NS_LOG_FUNCTION (this << *route);
668 
669  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
670  {
671  if (it->first == route)
672  {
674  route->SetRouteMetric (m_linkDown);
675  route->SetRouteChanged (true);
676  if (it->second.IsRunning ())
677  {
678  it->second.Cancel ();
679  }
681  return;
682  }
683  }
684  NS_ABORT_MSG ("Ripng::InvalidateRoute - cannot find the route to update");
685 }
686 
688 {
689  NS_LOG_FUNCTION (this << *route);
690 
691  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
692  {
693  if (it->first == route)
694  {
695  delete route;
696  m_routes.erase (it);
697  return;
698  }
699  }
700  NS_ABORT_MSG ("Ripng::DeleteRoute - cannot find the route to delete");
701 }
702 
703 
705 {
706  NS_LOG_FUNCTION (this << socket);
707 
708  Address sender;
709  Ptr<Packet> packet = socket->RecvFrom (sender);
711  NS_LOG_INFO ("Received " << *packet << " from " << senderAddr);
712 
713  Ipv6Address senderAddress = senderAddr.GetIpv6 ();
714  uint16_t senderPort = senderAddr.GetPort ();
715 
716  Ipv6PacketInfoTag interfaceInfo;
717  if (!packet->RemovePacketTag (interfaceInfo))
718  {
719  NS_ABORT_MSG ("No incoming interface on RIPng message, aborting.");
720  }
721  uint32_t incomingIf = interfaceInfo.GetRecvIf ();
722  Ptr<Node> node = this->GetObject<Node> ();
723  Ptr<NetDevice> dev = node->GetDevice (incomingIf);
724  uint32_t ipInterfaceIndex = m_ipv6->GetInterfaceForDevice (dev);
725 
726  SocketIpv6HopLimitTag hoplimitTag;
727  if (!packet->RemovePacketTag (hoplimitTag))
728  {
729  NS_ABORT_MSG ("No incoming Hop Count on RIPng message, aborting.");
730  }
731  uint8_t hopLimit = hoplimitTag.GetHopLimit ();
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> sendingSocket;
782  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
783  {
784  if (iter->second == incomingInterface)
785  {
786  sendingSocket = iter->first;
787  }
788  }
789  NS_ASSERT_MSG (sendingSocket, "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  sendingSocket->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  sendingSocket->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> sendingSocket;
860  if (senderAddress.IsLinkLocal ())
861  {
862  for (SocketListI iter = m_unicastSocketList.begin (); iter != m_unicastSocketList.end (); iter++ )
863  {
864  if (iter->second == incomingInterface)
865  {
866  sendingSocket = iter->first;
867  }
868  }
869  }
870  else
871  {
872  sendingSocket = m_multicastRecvSocket;
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  sendingSocket->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_unicastSocketList.begin (); iter != m_unicastSocketList.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_unicastSocketList.begin (); iter != m_unicastSocketList.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 
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:202
#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
bool IsGateway() const
Is it the gateway ?
Status_e GetRouteStatus(void) const
Get the route status.
Definition: ripng.cc:1342
SplitHorizonType_e m_splitHorizonStrategy
Split Horizon strategy.
Definition: ripng.h:409
std::map< Ptr< Socket >, uint32_t >::iterator SocketListI
Socket list type iterator.
Definition: ripng.h:394
bool IsRouteChanged(void) const
Get the route changed status.
Definition: ripng.cc:1352
virtual void DoInitialize(void)
Initialize() implementation.
Definition: object.cc:353
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:345
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.
Callback template class.
Definition: callback.h:1273
Definition: second.py:1
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:50
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:636
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer...
Definition: socket.h:1163
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:45
Ipv6Address GetIpv6(void) const
Get the IPv6 address.
Ipv6Address GetPrefixToUse() const
Get the prefix to use (for multihomed link).
NS_ASSERT_MSG(false, "Ipv4AddressGenerator::MaskToIndex(): Impossible")
void SetInterfaceExclusions(std::set< uint32_t > exceptions)
Set the set of interface excluded from the protocol.
Definition: ripng.cc:1209
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:142
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:225
void SetPrefix(Ipv6Address prefix)
Set the prefix.
Definition: ripng-header.cc:85
double GetSeconds(void) const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:361
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print the Routing Table entries.
Definition: ripng.cc:471
EventId m_nextTriggeredUpdate
Next Triggered Update event.
Definition: ripng.h:402
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:205
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: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:401
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:281
void Receive(Ptr< Socket > socket)
Receive RIPng packets.
Definition: ripng.cc:704
virtual void DoDispose()
Dispose this object.
Definition: ripng.cc:528
virtual void DoDispose(void)
Destructor implementation.
Definition: object.cc:346
TimeWithUnit As(const enum Unit unit) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:389
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:1271
uint32_t GetRecvIf(void) const
Get the tag&#39;s receiving interface.
Ipv6Address GetDestNetwork() const
Get the destination network.
uint16_t m_tag
route tag
Definition: ripng.h:152
a polymophic address class
Definition: address.h:90
void InvalidateRoute(RipNgRoutingTableEntry *route)
Invalidate a route.
Definition: ripng.cc:665
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:449
RIPng Routing Protocol, defined in RFC 2080.
Definition: ripng.h:174
void SendTriggeredRouteUpdate()
Send Triggered Routing Updates on all interfaces.
Definition: ripng.cc:1159
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:358
std::set< uint32_t > m_interfaceExclusions
Set of excluded interfaces.
Definition: ripng.h:406
uint8_t GetInterfaceMetric(uint32_t interface) const
Get the metric for an interface.
Definition: ripng.cc:1216
void DoInitialize()
Start protocol operation.
Definition: ripng.cc:110
Status_e
Route status.
Definition: ripng.h:70
Definition: ripng.h:72
A record of an IPv6 route.
uint16_t GetRteNumber(void) const
Get the number of RTE included in the message.
virtual void NotifyAddRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero())
Notify a new route.
Definition: ripng.cc:438
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:1390
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
Ipv6Address GetDest() const
Get the destination.
AttributeValue implementation for Time.
Definition: nstime.h:1132
Ptr< Ipv6 > m_ipv6
IPv6 reference.
Definition: ripng.h:381
Poison Reverse Split Horizon.
Definition: ripng.h:210
bool IsHost() const
Is the route entry correspond to a host ?
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
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ipv6-header.cc:143
Time m_timeoutDelay
Delay before invalidating a route.
Definition: ripng.h:386
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
uint8_t GetRouteMetric(void) const
Get the route metric.
Definition: ripng.cc:1328
An Inet6 address class.
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
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:1610
Ipv6Address CombinePrefix(Ipv6Prefix const &prefix) const
Combine this address with a prefix.
void SetRecvCallback(Callback< void, Ptr< Socket > >)
Notify application when new data is available to be read.
Definition: socket.cc:128
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
Split Horizon.
Definition: ripng.h:209
Ipv6Address GetGateway() const
Get the gateway.
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:100
void SetHopLimit(uint8_t hopLimit)
Set the tag&#39;s Hop Limit.
Definition: socket.cc:665
RipNgHeader - see RFC 2080
Definition: ripng-header.h:146
virtual void NotifyRemoveAddress(uint32_t interface, Ipv6InterfaceAddress address)
Notify when specified interface add an address.
Definition: ripng.cc:401
void DeleteRoute(RipNgRoutingTableEntry *route)
Delete a route.
Definition: ripng.cc:687
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:182
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
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:212
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
Definition: ripng.h:385
address
Definition: first.py:44
virtual ~RipNgRoutingTableEntry()
Definition: ripng.cc:1300
virtual void NotifyAddAddress(uint32_t interface, Ipv6InterfaceAddress address)
Notify when specified interface add an address.
Definition: ripng.cc:376
virtual uint32_t GetSerializedSize(void) const
Definition: udp-header.cc:178
void HandleResponses(RipNgHeader hdr, Ipv6Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIPng responses.
Definition: ripng.cc:923
Command_e GetCommand(void) const
Get the command.
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
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:450
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:1133
uint8_t GetPrefixLength() const
Get prefix length.
Ptr< UniformRandomVariable > m_rng
Rng stream.
Definition: ripng.h:404
void SetRouteStatus(Status_e status)
Set the route status.
Definition: ripng.cc:1333
NS_LOG_LOGIC("Net device "<< nd<< " is not bridged")
virtual void NotifyInterfaceUp(uint32_t interface)
Notify when specified interface goes UP.
Definition: ripng.cc:268
bool IsLinkLocalMulticast() const
If the IPv6 address is link-local multicast (ff02::/16).
std::set< uint32_t > GetInterfaceExclusions() const
Get the set of interface excluded from the protocol.
Definition: ripng.cc:1204
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:180
Describes an IPv6 address.
Definition: ipv6-address.h:49
Definition: ripng.h:71
void SendRouteRequest()
Send Routing Request on all interfaces.
Definition: ripng.cc:1238
static TypeId GetTypeId(void)
Get the type ID.
Definition: ripng.cc:58
void SetIpv6RecvHopLimit(bool ipv6RecvHopLimit)
Tells a socket to pass information about IPv6 Hop Limit up the stack.
Definition: socket.cc:551
An identifier for simulation events.
Definition: event-id.h:53
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:863
SocketList m_unicastSocketList
list of sockets for unicast messages (socket, interface index)
Definition: ripng.h:398
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:265
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
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:870
A network Node.
Definition: node.h:56
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:273
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1070
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
std::list< RipNgRte > GetRteList(void) const
Get the list of the RTEs included in the message.
Routes m_routes
the forwarding table for network.
Definition: ripng.h:380
bool IsRunning(void) const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:65
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
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:817
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:558
Describes an IPv6 prefix.
Definition: ipv6-address.h:459
bool m_changed
route has been updated
Definition: ripng.h:155
virtual uint32_t GetSerializedSize(void) const
Get the serialized size of the packet.
Definition: ripng-header.cc:55
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
Time Now(void)
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:309
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:1283
Ipv6Prefix GetDestNetworkPrefix() const
Get the destination prefix.
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.
Ptr< Socket > m_multicastRecvSocket
multicast receive socket
Definition: ripng.h:399
Time m_maxTriggeredUpdateDelay
Max cooldown delay after a Triggered Update.
Definition: ripng.h:384
uint16_t GetPort(void) const
Get the port.
Time m_garbageCollectionDelay
Delay before deleting an INVALID route.
Definition: ripng.h:387
virtual int Close(void)=0
Close a socket.
bool IsNull(void) const
Check for null implementation.
Definition: callback.h:1372
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:110
Definition: first.py:1
uint16_t GetRouteTag(void) const
Get the route tag.
Definition: ripng.cc:1314
RipNg Routing Table Entry (RTE) - see RFC 2080
Definition: ripng-header.h:38
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:444
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
uint8_t GetHopLimit(void) const
Get the tag&#39;s Hop Limit.
Definition: socket.cc:671
Ipv6InterfaceAddress::Scope_e GetScope() const
Get address scope.
#define RIPNG_PORT
Definition: ripng.cc:39
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:923
std::ostream * GetStream(void)
Return a pointer to an ostream previously set in the wrapper.
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
Time m_minTriggeredUpdateDelay
Min cooldown delay after a Triggered Update.
Definition: ripng.h:383
bool IsAny() const
If the IPv6 address is the "Any" address.
uint32_t GetInterface() const
Get the interface index.
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:830
void SetPrefixLen(uint8_t prefixLen)
Set the prefix length.
Definition: ripng-header.cc:95