A Discrete-Event Network Simulator
API
ripng.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Universita' di Firenze, Italy
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
18  */
19 
20 #include "ripng.h"
21 
22 #include "ipv6-packet-info-tag.h"
23 #include "ipv6-route.h"
24 #include "ripng-header.h"
25 #include "udp-header.h"
26 
27 #include "ns3/abort.h"
28 #include "ns3/assert.h"
29 #include "ns3/enum.h"
30 #include "ns3/log.h"
31 #include "ns3/names.h"
32 #include "ns3/node.h"
33 #include "ns3/random-variable-stream.h"
34 #include "ns3/simulator.h"
35 #include "ns3/uinteger.h"
36 
37 #include <iomanip>
38 
39 #define RIPNG_ALL_NODE "ff02::9"
40 #define RIPNG_PORT 521
41 
42 namespace ns3
43 {
44 
46 
48 
50  : m_ipv6(nullptr),
51  m_splitHorizonStrategy(RipNg::POISON_REVERSE),
52  m_initialized(false)
53 {
54  m_rng = CreateObject<UniformRandomVariable>();
55 }
56 
58 {
59 }
60 
61 TypeId
63 {
64  static TypeId tid =
65  TypeId("ns3::RipNg")
67  .SetGroupName("Internet")
68  .AddConstructor<RipNg>()
69  .AddAttribute("UnsolicitedRoutingUpdate",
70  "The time between two Unsolicited Routing Updates.",
71  TimeValue(Seconds(30)),
74  .AddAttribute("StartupDelay",
75  "Maximum random delay for protocol startup (send route requests).",
76  TimeValue(Seconds(1)),
79  .AddAttribute("TimeoutDelay",
80  "The delay to invalidate a route.",
81  TimeValue(Seconds(180)),
84  .AddAttribute("GarbageCollectionDelay",
85  "The delay to delete an expired route.",
86  TimeValue(Seconds(120)),
89  .AddAttribute("MinTriggeredCooldown",
90  "Min cooldown delay after a Triggered Update.",
91  TimeValue(Seconds(1)),
94  .AddAttribute("MaxTriggeredCooldown",
95  "Max cooldown delay after a Triggered Update.",
96  TimeValue(Seconds(5)),
99  .AddAttribute("SplitHorizon",
100  "Split Horizon strategy.",
102  MakeEnumAccessor<SplitHorizonType_e>(&RipNg::m_splitHorizonStrategy),
104  "NoSplitHorizon",
106  "SplitHorizon",
108  "PoisonReverse"))
109  .AddAttribute("LinkDownValue",
110  "Value for link down in count to infinity.",
111  UintegerValue(16),
113  MakeUintegerChecker<uint8_t>());
114  return tid;
115 }
116 
117 int64_t
118 RipNg::AssignStreams(int64_t stream)
119 {
120  NS_LOG_FUNCTION(this << stream);
121 
122  m_rng->SetStream(stream);
123  return 1;
124 }
125 
126 void
128 {
129  NS_LOG_FUNCTION(this);
130 
131  bool addedGlobal = false;
132 
133  m_initialized = true;
134 
135  Time delay =
138 
139  for (uint32_t i = 0; i < m_ipv6->GetNInterfaces(); i++)
140  {
141  bool activeInterface = false;
142  if (m_interfaceExclusions.find(i) == m_interfaceExclusions.end())
143  {
144  activeInterface = true;
145  m_ipv6->SetForwarding(i, true);
146  }
147 
148  for (uint32_t j = 0; j < m_ipv6->GetNAddresses(i); j++)
149  {
150  Ipv6InterfaceAddress address = m_ipv6->GetAddress(i, j);
151  if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && activeInterface)
152  {
153  NS_LOG_LOGIC("RIPng: adding socket to " << address.GetAddress());
154  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
155  Ptr<Node> theNode = GetObject<Node>();
156  Ptr<Socket> socket = Socket::CreateSocket(theNode, tid);
158  socket->BindToNetDevice(m_ipv6->GetNetDevice(i));
159  int ret = socket->Bind(local);
160  NS_ASSERT_MSG(ret == 0, "Bind unsuccessful");
162  socket->SetIpv6RecvHopLimit(true);
163  socket->SetRecvPktInfo(true);
164  m_unicastSocketList[socket] = i;
165  }
166  else if (m_ipv6->GetAddress(i, j).GetScope() == Ipv6InterfaceAddress::GLOBAL)
167  {
168  addedGlobal = true;
169  }
170  }
171  }
172 
174  {
175  NS_LOG_LOGIC("RIPng: adding receiving socket");
176  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
177  Ptr<Node> theNode = GetObject<Node>();
180  m_multicastRecvSocket->Bind(local);
184  }
185 
186  if (addedGlobal)
187  {
191  }
192 
193  delay = Seconds(m_rng->GetValue(0.01, m_startupDelay.GetSeconds()));
195 
197 }
198 
201  const Ipv6Header& header,
202  Ptr<NetDevice> oif,
203  Socket::SocketErrno& sockerr)
204 {
205  NS_LOG_FUNCTION(this << header << oif);
206 
207  Ipv6Address destination = header.GetDestination();
208  Ptr<Ipv6Route> rtentry = nullptr;
209 
210  if (destination.IsMulticast())
211  {
212  // Note: Multicast routes for outbound packets are stored in the
213  // normal unicast table. An implication of this is that it is not
214  // possible to source multicast datagrams on multiple interfaces.
215  // This is a well-known property of sockets implementation on
216  // many Unix variants.
217  // So, we just log it and fall through to LookupStatic ()
218  NS_LOG_LOGIC("RouteOutput (): Multicast destination");
219  }
220 
221  rtentry = Lookup(destination, true, oif);
222  if (rtentry)
223  {
224  sockerr = Socket::ERROR_NOTERROR;
225  }
226  else
227  {
228  sockerr = Socket::ERROR_NOROUTETOHOST;
229  }
230  return rtentry;
231 }
232 
233 bool
235  const Ipv6Header& header,
237  const UnicastForwardCallback& ucb,
238  const MulticastForwardCallback& mcb,
239  const LocalDeliverCallback& lcb,
240  const ErrorCallback& ecb)
241 {
242  NS_LOG_FUNCTION(this << p << header << header.GetSource() << header.GetDestination() << idev);
243 
244  NS_ASSERT(m_ipv6);
245  // Check if input device supports IP
246  NS_ASSERT(m_ipv6->GetInterfaceForDevice(idev) >= 0);
247  uint32_t iif = m_ipv6->GetInterfaceForDevice(idev);
248  Ipv6Address dst = header.GetDestination();
249 
250  if (dst.IsMulticast())
251  {
252  NS_LOG_LOGIC("Multicast route not supported by RIPng");
253  return false; // Let other routing protocols try to handle this
254  }
255 
256  if (header.GetDestination().IsLinkLocal() || header.GetSource().IsLinkLocal())
257  {
258  NS_LOG_LOGIC("Dropping packet not for me and with src or dst LinkLocal");
259  if (!ecb.IsNull())
260  {
261  ecb(p, header, Socket::ERROR_NOROUTETOHOST);
262  }
263  return false;
264  }
265 
266  // Check if input device supports IP forwarding
267  if (!m_ipv6->IsForwarding(iif))
268  {
269  NS_LOG_LOGIC("Forwarding disabled for this interface");
270  if (!ecb.IsNull())
271  {
272  ecb(p, header, Socket::ERROR_NOROUTETOHOST);
273  }
274  return true;
275  }
276  // Next, try to find a route
277  NS_LOG_LOGIC("Unicast destination");
278  Ptr<Ipv6Route> rtentry = Lookup(header.GetDestination(), false);
279 
280  if (rtentry)
281  {
282  NS_LOG_LOGIC("Found unicast destination - calling unicast callback");
283  ucb(idev, rtentry, p, header); // unicast forwarding callback
284  return true;
285  }
286  else
287  {
288  NS_LOG_LOGIC("Did not find unicast destination - returning false");
289  return false; // Let other routing protocols try to handle this
290  }
291 }
292 
293 void
295 {
296  NS_LOG_FUNCTION(this << i);
297 
298  for (uint32_t j = 0; j < m_ipv6->GetNAddresses(i); j++)
299  {
300  Ipv6InterfaceAddress address = m_ipv6->GetAddress(i, j);
301  Ipv6Prefix networkMask = address.GetPrefix();
302  Ipv6Address networkAddress = address.GetAddress().CombinePrefix(networkMask);
303 
304  if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
305  {
306  AddNetworkRouteTo(networkAddress, networkMask, i);
307  }
308  }
309 
310  if (!m_initialized)
311  {
312  return;
313  }
314 
315  bool sendSocketFound = false;
316  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
317  {
318  if (iter->second == i)
319  {
320  sendSocketFound = true;
321  break;
322  }
323  }
324 
325  bool activeInterface = false;
326  if (m_interfaceExclusions.find(i) == m_interfaceExclusions.end())
327  {
328  activeInterface = true;
329  m_ipv6->SetForwarding(i, true);
330  }
331 
332  for (uint32_t j = 0; j < m_ipv6->GetNAddresses(i); j++)
333  {
334  Ipv6InterfaceAddress address = m_ipv6->GetAddress(i, j);
335 
336  if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && !sendSocketFound &&
337  activeInterface)
338  {
339  NS_LOG_LOGIC("RIPng: adding sending socket to " << address.GetAddress());
340  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
341  Ptr<Node> theNode = GetObject<Node>();
342  Ptr<Socket> socket = Socket::CreateSocket(theNode, tid);
344  socket->BindToNetDevice(m_ipv6->GetNetDevice(i));
345  socket->Bind(local);
347  socket->SetIpv6RecvHopLimit(true);
348  socket->SetRecvPktInfo(true);
349  m_unicastSocketList[socket] = i;
350  }
351  else if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
352  {
354  }
355  }
356 
358  {
359  NS_LOG_LOGIC("RIPng: adding receiving socket");
360  TypeId tid = TypeId::LookupByName("ns3::UdpSocketFactory");
361  Ptr<Node> theNode = GetObject<Node>();
364  m_multicastRecvSocket->Bind(local);
368  }
369 }
370 
371 void
372 RipNg::NotifyInterfaceDown(uint32_t interface)
373 {
374  NS_LOG_FUNCTION(this << interface);
375 
376  /* remove all routes that are going through this interface */
377  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
378  {
379  if (it->first->GetInterface() == interface)
380  {
381  InvalidateRoute(it->first);
382  }
383  }
384 
385  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
386  {
387  NS_LOG_INFO("Checking socket for interface " << interface);
388  if (iter->second == interface)
389  {
390  NS_LOG_INFO("Removed socket for interface " << interface);
391  iter->first->Close();
392  m_unicastSocketList.erase(iter);
393  break;
394  }
395  }
396 
397  if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
398  {
400  }
401 }
402 
403 void
405 {
406  NS_LOG_FUNCTION(this << interface << address);
407 
408  if (!m_ipv6->IsUp(interface))
409  {
410  return;
411  }
412 
413  if (m_interfaceExclusions.find(interface) != m_interfaceExclusions.end())
414  {
415  return;
416  }
417 
418  Ipv6Address networkAddress = address.GetAddress().CombinePrefix(address.GetPrefix());
419  Ipv6Prefix networkMask = address.GetPrefix();
420 
421  if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL)
422  {
423  AddNetworkRouteTo(networkAddress, networkMask, interface);
424  }
425 
427 }
428 
429 void
431 {
432  NS_LOG_FUNCTION(this << interface << address);
433 
434  if (!m_ipv6->IsUp(interface))
435  {
436  return;
437  }
438 
439  if (address.GetScope() != Ipv6InterfaceAddress::GLOBAL)
440  {
441  return;
442  }
443 
444  Ipv6Address networkAddress = address.GetAddress().CombinePrefix(address.GetPrefix());
445  Ipv6Prefix networkMask = address.GetPrefix();
446 
447  // Remove all routes that are going through this interface
448  // which reference this network
449  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
450  {
451  if (it->first->GetInterface() == interface && it->first->IsNetwork() &&
452  it->first->GetDestNetwork() == networkAddress &&
453  it->first->GetDestNetworkPrefix() == networkMask)
454  {
455  InvalidateRoute(it->first);
456  }
457  }
458 
459  if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
460  {
462  }
463 }
464 
465 void
467  Ipv6Prefix mask,
468  Ipv6Address nextHop,
469  uint32_t interface,
470  Ipv6Address prefixToUse)
471 {
472  NS_LOG_INFO(this << dst << mask << nextHop << interface << prefixToUse);
473  // \todo this can be used to add delegate routes
474 }
475 
476 void
478  Ipv6Prefix mask,
479  Ipv6Address nextHop,
480  uint32_t interface,
481  Ipv6Address prefixToUse)
482 {
483  NS_LOG_FUNCTION(this << dst << mask << nextHop << interface);
484  // \todo this can be used to delete delegate routes
485 }
486 
487 void
489 {
490  NS_LOG_FUNCTION(this << ipv6);
491 
492  NS_ASSERT(!m_ipv6 && ipv6);
493  uint32_t i = 0;
494  m_ipv6 = ipv6;
495 
496  for (i = 0; i < m_ipv6->GetNInterfaces(); i++)
497  {
498  if (m_ipv6->IsUp(i))
499  {
501  }
502  else
503  {
505  }
506  }
507 }
508 
509 void
511 {
512  NS_LOG_FUNCTION(this << stream);
513 
514  std::ostream* os = stream->GetStream();
515  *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
516 
517  *os << "Node: " << m_ipv6->GetObject<Node>()->GetId() << ", Time: " << Now().As(unit)
518  << ", Local time: " << m_ipv6->GetObject<Node>()->GetLocalTime().As(unit)
519  << ", IPv6 RIPng table" << std::endl;
520 
521  if (!m_routes.empty())
522  {
523  *os << "Destination Next Hop Flag Met Ref Use If"
524  << std::endl;
525  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
526  {
527  RipNgRoutingTableEntry* route = it->first;
529 
531  {
532  std::ostringstream dest;
533  std::ostringstream gw;
534  std::ostringstream mask;
535  std::ostringstream flags;
536 
537  dest << route->GetDest() << "/"
538  << int(route->GetDestNetworkPrefix().GetPrefixLength());
539  *os << std::setw(31) << dest.str();
540  gw << route->GetGateway();
541  *os << std::setw(27) << gw.str();
542  flags << "U";
543  if (route->IsHost())
544  {
545  flags << "H";
546  }
547  else if (route->IsGateway())
548  {
549  flags << "G";
550  }
551  *os << std::setw(5) << flags.str();
552  *os << std::setw(4) << int(route->GetRouteMetric());
553  // Ref ct not implemented
554  *os << "-"
555  << " ";
556  // Use not implemented
557  *os << "-"
558  << " ";
559  if (!Names::FindName(m_ipv6->GetNetDevice(route->GetInterface())).empty())
560  {
561  *os << Names::FindName(m_ipv6->GetNetDevice(route->GetInterface()));
562  }
563  else
564  {
565  *os << route->GetInterface();
566  }
567  *os << std::endl;
568  }
569  }
570  }
571  *os << std::endl;
572 }
573 
574 void
576 {
577  NS_LOG_FUNCTION(this);
578 
579  for (auto j = m_routes.begin(); j != m_routes.end(); j = m_routes.erase(j))
580  {
581  delete j->first;
582  }
583  m_routes.clear();
584 
589 
590  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
591  {
592  iter->first->Close();
593  }
594  m_unicastSocketList.clear();
595 
597  m_multicastRecvSocket = nullptr;
598 
599  m_ipv6 = nullptr;
600 
602 }
603 
605 RipNg::Lookup(Ipv6Address dst, bool setSource, Ptr<NetDevice> interface)
606 {
607  NS_LOG_FUNCTION(this << dst << interface);
608 
609  Ptr<Ipv6Route> rtentry = nullptr;
610  uint16_t longestMask = 0;
611 
612  /* when sending on link-local multicast, there have to be interface specified */
613  if (dst.IsLinkLocalMulticast())
614  {
616  interface,
617  "Try to send on link-local multicast address, and no interface index is given!");
618  rtentry = Create<Ipv6Route>();
619  rtentry->SetSource(
620  m_ipv6->SourceAddressSelection(m_ipv6->GetInterfaceForDevice(interface), dst));
621  rtentry->SetDestination(dst);
622  rtentry->SetGateway(Ipv6Address::GetZero());
623  rtentry->SetOutputDevice(interface);
624  return rtentry;
625  }
626 
627  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
628  {
629  RipNgRoutingTableEntry* j = it->first;
630 
632  {
633  Ipv6Prefix mask = j->GetDestNetworkPrefix();
634  uint16_t maskLen = mask.GetPrefixLength();
635  Ipv6Address entry = j->GetDestNetwork();
636 
637  NS_LOG_LOGIC("Searching for route to " << dst << ", mask length " << maskLen);
638 
639  if (mask.IsMatch(dst, entry))
640  {
641  NS_LOG_LOGIC("Found global network route " << j << ", mask length " << maskLen);
642 
643  /* if interface is given, check the route will output on this interface */
644  if (!interface || interface == m_ipv6->GetNetDevice(j->GetInterface()))
645  {
646  if (maskLen < longestMask)
647  {
648  NS_LOG_LOGIC("Previous match longer, skipping");
649  continue;
650  }
651 
652  longestMask = maskLen;
653 
654  Ipv6RoutingTableEntry* route = j;
655  uint32_t interfaceIdx = route->GetInterface();
656  rtentry = Create<Ipv6Route>();
657 
658  if (setSource)
659  {
660  // GetGateway().IsAny() means that the destination is reachable without a
661  // gateway (is on-link). GetDest().IsAny() means that the route is the
662  // default route. Having both true is very strange, but possible.
663  // If the RT entry is specific for a destination, use that as a hint for the
664  // source address to be used. Else, use the destination or the prefix to be
665  // used stated in the RT entry.
666  if (!route->GetDest().IsAny())
667  {
668  rtentry->SetSource(
669  m_ipv6->SourceAddressSelection(interfaceIdx, route->GetDest()));
670  }
671  else
672  {
673  rtentry->SetSource(m_ipv6->SourceAddressSelection(
674  interfaceIdx,
675  route->GetPrefixToUse().IsAny() ? dst : route->GetPrefixToUse()));
676  }
677  }
678 
679  rtentry->SetDestination(route->GetDest());
680  rtentry->SetGateway(route->GetGateway());
681  rtentry->SetOutputDevice(m_ipv6->GetNetDevice(interfaceIdx));
682  }
683  }
684  }
685  }
686 
687  if (rtentry)
688  {
689  NS_LOG_LOGIC("Matching route via " << rtentry->GetDestination() << " (through "
690  << rtentry->GetGateway() << ") at the end");
691  }
692  return rtentry;
693 }
694 
695 void
697  Ipv6Prefix networkPrefix,
698  Ipv6Address nextHop,
699  uint32_t interface,
700  Ipv6Address prefixToUse)
701 {
702  NS_LOG_FUNCTION(this << network << networkPrefix << nextHop << interface << prefixToUse);
703 
704  if (nextHop.IsLinkLocal())
705  {
706  NS_LOG_WARN("Ripng::AddNetworkRouteTo - Next hop should be link-local");
707  }
708 
709  auto route =
710  new RipNgRoutingTableEntry(network, networkPrefix, nextHop, interface, prefixToUse);
711  route->SetRouteMetric(1);
712  route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
713  route->SetRouteChanged(true);
714 
715  m_routes.emplace_back(route, EventId());
716 }
717 
718 void
719 RipNg::AddNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface)
720 {
721  NS_LOG_FUNCTION(this << network << networkPrefix << interface);
722 
723  auto route = new RipNgRoutingTableEntry(network, networkPrefix, interface);
724  route->SetRouteMetric(1);
725  route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
726  route->SetRouteChanged(true);
727 
728  m_routes.emplace_back(route, EventId());
729 }
730 
731 void
733 {
734  NS_LOG_FUNCTION(this << *route);
735 
736  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
737  {
738  if (it->first == route)
739  {
741  route->SetRouteMetric(m_linkDown);
742  route->SetRouteChanged(true);
743  if (it->second.IsRunning())
744  {
745  it->second.Cancel();
746  }
747  it->second =
749  return;
750  }
751  }
752  NS_ABORT_MSG("Ripng::InvalidateRoute - cannot find the route to update");
753 }
754 
755 void
757 {
758  NS_LOG_FUNCTION(this << *route);
759 
760  for (auto it = m_routes.begin(); it != m_routes.end(); it++)
761  {
762  if (it->first == route)
763  {
764  delete route;
765  m_routes.erase(it);
766  return;
767  }
768  }
769  NS_ABORT_MSG("Ripng::DeleteRoute - cannot find the route to delete");
770 }
771 
772 void
774 {
775  NS_LOG_FUNCTION(this << socket);
776 
777  Address sender;
778  Ptr<Packet> packet = socket->RecvFrom(sender);
780  NS_LOG_INFO("Received " << *packet << " from " << senderAddr);
781 
782  Ipv6Address senderAddress = senderAddr.GetIpv6();
783  uint16_t senderPort = senderAddr.GetPort();
784 
785  Ipv6PacketInfoTag interfaceInfo;
786  if (!packet->RemovePacketTag(interfaceInfo))
787  {
788  NS_ABORT_MSG("No incoming interface on RIPng message, aborting.");
789  }
790  uint32_t incomingIf = interfaceInfo.GetRecvIf();
791  Ptr<Node> node = this->GetObject<Node>();
792  Ptr<NetDevice> dev = node->GetDevice(incomingIf);
793  uint32_t ipInterfaceIndex = m_ipv6->GetInterfaceForDevice(dev);
794 
795  SocketIpv6HopLimitTag hoplimitTag;
796  if (!packet->RemovePacketTag(hoplimitTag))
797  {
798  NS_ABORT_MSG("No incoming Hop Count on RIPng message, aborting.");
799  }
800  uint8_t hopLimit = hoplimitTag.GetHopLimit();
801 
802  int32_t interfaceForAddress = m_ipv6->GetInterfaceForAddress(senderAddress);
803  if (interfaceForAddress != -1)
804  {
805  NS_LOG_LOGIC("Ignoring a packet sent by myself.");
806  return;
807  }
808 
809  RipNgHeader hdr;
810  packet->RemoveHeader(hdr);
811 
812  if (hdr.GetCommand() == RipNgHeader::RESPONSE)
813  {
814  HandleResponses(hdr, senderAddress, ipInterfaceIndex, hopLimit);
815  }
816  else if (hdr.GetCommand() == RipNgHeader::REQUEST)
817  {
818  HandleRequests(hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
819  }
820  else
821  {
822  NS_LOG_LOGIC("Ignoring message with unknown command: " << int(hdr.GetCommand()));
823  }
824 }
825 
826 void
828  Ipv6Address senderAddress,
829  uint16_t senderPort,
830  uint32_t incomingInterface,
831  uint8_t hopLimit)
832 {
833  NS_LOG_FUNCTION(this << senderAddress << int(senderPort) << incomingInterface << int(hopLimit)
834  << requestHdr);
835 
836  std::list<RipNgRte> rtes = requestHdr.GetRteList();
837 
838  if (rtes.empty())
839  {
840  return;
841  }
842 
843  // check if it's a request for the full table from a neighbor
844  if (rtes.size() == 1 && senderAddress.IsLinkLocal())
845  {
846  if (rtes.begin()->GetPrefix() == Ipv6Address::GetAny() &&
847  rtes.begin()->GetPrefixLen() == 0 && rtes.begin()->GetRouteMetric() == m_linkDown)
848  {
849  // Output whole thing. Use Split Horizon
850  if (m_interfaceExclusions.find(incomingInterface) == m_interfaceExclusions.end())
851  {
852  // we use one of the sending sockets, as they're bound to the right interface
853  // and the local address might be used on different interfaces.
854  Ptr<Socket> sendingSocket;
855  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end();
856  iter++)
857  {
858  if (iter->second == incomingInterface)
859  {
860  sendingSocket = iter->first;
861  }
862  }
863  NS_ASSERT_MSG(sendingSocket,
864  "HandleRequest - Impossible to find a socket to send the reply");
865 
866  uint16_t mtu = m_ipv6->GetMtu(incomingInterface);
867  uint16_t maxRte =
871 
872  Ptr<Packet> p = Create<Packet>();
874  p->RemovePacketTag(tag);
875  tag.SetHopLimit(255);
876  p->AddPacketTag(tag);
877 
878  RipNgHeader hdr;
880 
881  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
882  {
883  bool splitHorizoning = (rtIter->first->GetInterface() == incomingInterface);
884 
885  Ipv6InterfaceAddress rtDestAddr =
886  Ipv6InterfaceAddress(rtIter->first->GetDestNetwork(),
887  rtIter->first->GetDestNetworkPrefix());
888 
889  bool isGlobal = (rtDestAddr.GetScope() == Ipv6InterfaceAddress::GLOBAL);
890  bool isDefaultRoute =
891  ((rtIter->first->GetDestNetwork() == Ipv6Address::GetAny()) &&
892  (rtIter->first->GetDestNetworkPrefix() == Ipv6Prefix::GetZero()) &&
893  (rtIter->first->GetInterface() != incomingInterface));
894 
895  if ((isGlobal || isDefaultRoute) &&
896  (rtIter->first->GetRouteStatus() == RipNgRoutingTableEntry::RIPNG_VALID))
897  {
898  RipNgRte rte;
899  rte.SetPrefix(rtIter->first->GetDestNetwork());
900  rte.SetPrefixLen(rtIter->first->GetDestNetworkPrefix().GetPrefixLength());
901  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
902  {
904  }
905  else
906  {
907  rte.SetRouteMetric(rtIter->first->GetRouteMetric());
908  }
909  rte.SetRouteTag(rtIter->first->GetRouteTag());
911  (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
912  {
913  hdr.AddRte(rte);
914  }
915  }
916  if (hdr.GetRteNumber() == maxRte)
917  {
918  p->AddHeader(hdr);
919  NS_LOG_DEBUG("SendTo: " << *p);
920  sendingSocket->SendTo(p, 0, Inet6SocketAddress(senderAddress, RIPNG_PORT));
921  p->RemoveHeader(hdr);
922  hdr.ClearRtes();
923  }
924  }
925  if (hdr.GetRteNumber() > 0)
926  {
927  p->AddHeader(hdr);
928  NS_LOG_DEBUG("SendTo: " << *p);
929  sendingSocket->SendTo(p, 0, Inet6SocketAddress(senderAddress, RIPNG_PORT));
930  }
931  }
932  }
933  }
934  else
935  {
936  // note: we got the request as a single packet, so no check is necessary for MTU limit
937 
938  // we use one of the sending sockets, as they're bound to the right interface
939  // and the local address might be used on different interfaces.
940  Ptr<Socket> sendingSocket;
941  if (senderAddress.IsLinkLocal())
942  {
943  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
944  {
945  if (iter->second == incomingInterface)
946  {
947  sendingSocket = iter->first;
948  }
949  }
950  }
951  else
952  {
953  sendingSocket = m_multicastRecvSocket;
954  }
955 
956  Ptr<Packet> p = Create<Packet>();
958  p->RemovePacketTag(tag);
959  tag.SetHopLimit(255);
960  p->AddPacketTag(tag);
961 
962  RipNgHeader hdr;
964 
965  for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
966  {
967  bool found = false;
968  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
969  {
970  Ipv6InterfaceAddress rtDestAddr =
971  Ipv6InterfaceAddress(rtIter->first->GetDestNetwork(),
972  rtIter->first->GetDestNetworkPrefix());
973  if ((rtDestAddr.GetScope() == Ipv6InterfaceAddress::GLOBAL) &&
974  (rtIter->first->GetRouteStatus() == RipNgRoutingTableEntry::RIPNG_VALID))
975  {
976  Ipv6Address requestedAddress = iter->GetPrefix();
977  requestedAddress.CombinePrefix(Ipv6Prefix(iter->GetPrefixLen()));
978  Ipv6Address rtAddress = rtIter->first->GetDestNetwork();
979  rtAddress.CombinePrefix(rtIter->first->GetDestNetworkPrefix());
980 
981  if (requestedAddress == rtAddress)
982  {
983  iter->SetRouteMetric(rtIter->first->GetRouteMetric());
984  iter->SetRouteTag(rtIter->first->GetRouteTag());
985  hdr.AddRte(*iter);
986  found = true;
987  break;
988  }
989  }
990  }
991  if (!found)
992  {
993  iter->SetRouteMetric(m_linkDown);
994  iter->SetRouteTag(0);
995  hdr.AddRte(*iter);
996  }
997  }
998  p->AddHeader(hdr);
999  NS_LOG_DEBUG("SendTo: " << *p);
1000  sendingSocket->SendTo(p, 0, Inet6SocketAddress(senderAddress, senderPort));
1001  }
1002 }
1003 
1004 void
1006  Ipv6Address senderAddress,
1007  uint32_t incomingInterface,
1008  uint8_t hopLimit)
1009 {
1010  NS_LOG_FUNCTION(this << senderAddress << incomingInterface << int(hopLimit) << hdr);
1011 
1012  if (m_interfaceExclusions.find(incomingInterface) != m_interfaceExclusions.end())
1013  {
1014  NS_LOG_LOGIC(
1015  "Ignoring an update message from an excluded interface: " << incomingInterface);
1016  return;
1017  }
1018 
1019  if (!senderAddress.IsLinkLocal())
1020  {
1021  NS_LOG_LOGIC("Ignoring an update message from a non-link-local source: " << senderAddress);
1022  return;
1023  }
1024 
1025  if (hopLimit != 255)
1026  {
1027  NS_LOG_LOGIC("Ignoring an update message with suspicious hop count: " << int(hopLimit));
1028  return;
1029  }
1030 
1031  std::list<RipNgRte> rtes = hdr.GetRteList();
1032 
1033  // validate the RTEs before processing
1034  for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
1035  {
1036  if (iter->GetRouteMetric() == 0 || iter->GetRouteMetric() > m_linkDown)
1037  {
1038  NS_LOG_LOGIC("Ignoring an update message with malformed metric: "
1039  << int(iter->GetRouteMetric()));
1040  return;
1041  }
1042  if (iter->GetPrefixLen() > 128)
1043  {
1044  NS_LOG_LOGIC("Ignoring an update message with malformed prefix length: "
1045  << int(iter->GetPrefixLen()));
1046  return;
1047  }
1048  if (iter->GetPrefix().IsLocalhost() || iter->GetPrefix().IsLinkLocal() ||
1049  iter->GetPrefix().IsMulticast())
1050  {
1051  NS_LOG_LOGIC("Ignoring an update message with wrong prefixes: " << iter->GetPrefix());
1052  return;
1053  }
1054  }
1055 
1056  bool changed = false;
1057 
1058  for (auto iter = rtes.begin(); iter != rtes.end(); iter++)
1059  {
1060  Ipv6Prefix rtePrefix = Ipv6Prefix(iter->GetPrefixLen());
1061  Ipv6Address rteAddr = iter->GetPrefix().CombinePrefix(rtePrefix);
1062 
1063  NS_LOG_LOGIC("Processing RTE " << *iter);
1064 
1065  uint8_t interfaceMetric = 1;
1066  if (m_interfaceMetrics.find(incomingInterface) != m_interfaceMetrics.end())
1067  {
1068  interfaceMetric = m_interfaceMetrics[incomingInterface];
1069  }
1070  uint16_t rteMetric = iter->GetRouteMetric() + interfaceMetric;
1071  if (rteMetric > m_linkDown)
1072  {
1073  rteMetric = m_linkDown;
1074  }
1075  RoutesI it;
1076  bool found = false;
1077  for (it = m_routes.begin(); it != m_routes.end(); it++)
1078  {
1079  if (it->first->GetDestNetwork() == rteAddr &&
1080  it->first->GetDestNetworkPrefix() == rtePrefix)
1081  {
1082  found = true;
1083  if (rteMetric < it->first->GetRouteMetric())
1084  {
1085  if (senderAddress != it->first->GetGateway())
1086  {
1087  auto route = new RipNgRoutingTableEntry(rteAddr,
1088  rtePrefix,
1089  senderAddress,
1090  incomingInterface,
1092  delete it->first;
1093  it->first = route;
1094  }
1095  it->first->SetRouteMetric(rteMetric);
1096  it->first->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1097  it->first->SetRouteTag(iter->GetRouteTag());
1098  it->first->SetRouteChanged(true);
1099  it->second.Cancel();
1100  it->second = Simulator::Schedule(m_timeoutDelay,
1102  this,
1103  it->first);
1104  changed = true;
1105  }
1106  else if (rteMetric == it->first->GetRouteMetric())
1107  {
1108  if (senderAddress == it->first->GetGateway())
1109  {
1110  it->second.Cancel();
1111  it->second = Simulator::Schedule(m_timeoutDelay,
1113  this,
1114  it->first);
1115  }
1116  else
1117  {
1118  if (Simulator::GetDelayLeft(it->second) < m_timeoutDelay / 2)
1119  {
1120  auto route = new RipNgRoutingTableEntry(rteAddr,
1121  rtePrefix,
1122  senderAddress,
1123  incomingInterface,
1125  route->SetRouteMetric(rteMetric);
1126  route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1127  route->SetRouteTag(iter->GetRouteTag());
1128  route->SetRouteChanged(true);
1129  delete it->first;
1130  it->first = route;
1131  it->second.Cancel();
1132  it->second = Simulator::Schedule(m_timeoutDelay,
1134  this,
1135  route);
1136  changed = true;
1137  }
1138  }
1139  }
1140  else if (rteMetric > it->first->GetRouteMetric() &&
1141  senderAddress == it->first->GetGateway())
1142  {
1143  it->second.Cancel();
1144  if (rteMetric < m_linkDown)
1145  {
1146  it->first->SetRouteMetric(rteMetric);
1147  it->first->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1148  it->first->SetRouteTag(iter->GetRouteTag());
1149  it->first->SetRouteChanged(true);
1150  it->second.Cancel();
1151  it->second = Simulator::Schedule(m_timeoutDelay,
1153  this,
1154  it->first);
1155  }
1156  else
1157  {
1158  InvalidateRoute(it->first);
1159  }
1160  changed = true;
1161  }
1162  }
1163  }
1164  if (!found && rteMetric != m_linkDown)
1165  {
1166  NS_LOG_LOGIC("Received a RTE with new route, adding.");
1167 
1168  auto route = new RipNgRoutingTableEntry(rteAddr,
1169  rtePrefix,
1170  senderAddress,
1171  incomingInterface,
1173  route->SetRouteMetric(rteMetric);
1174  route->SetRouteStatus(RipNgRoutingTableEntry::RIPNG_VALID);
1175  route->SetRouteChanged(true);
1176  m_routes.emplace_front(route, EventId());
1177  EventId invalidateEvent =
1179  (m_routes.begin())->second = invalidateEvent;
1180  changed = true;
1181  }
1182  }
1183 
1184  if (changed)
1185  {
1187  }
1188 }
1189 
1190 void
1192 {
1193  NS_LOG_FUNCTION(this << (periodic ? " periodic" : " triggered"));
1194 
1195  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
1196  {
1197  uint32_t interface = iter->second;
1198 
1199  if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
1200  {
1201  uint16_t mtu = m_ipv6->GetMtu(interface);
1202  uint16_t maxRte =
1206 
1207  Ptr<Packet> p = Create<Packet>();
1209  tag.SetHopLimit(255);
1210  p->AddPacketTag(tag);
1211 
1212  RipNgHeader hdr;
1214 
1215  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
1216  {
1217  bool splitHorizoning = (rtIter->first->GetInterface() == interface);
1218  Ipv6InterfaceAddress rtDestAddr =
1219  Ipv6InterfaceAddress(rtIter->first->GetDestNetwork(),
1220  rtIter->first->GetDestNetworkPrefix());
1221 
1222  NS_LOG_DEBUG("Processing RT " << rtDestAddr << " "
1223  << int(rtIter->first->IsRouteChanged()));
1224 
1225  bool isGlobal = (rtDestAddr.GetScope() == Ipv6InterfaceAddress::GLOBAL);
1226  bool isDefaultRoute =
1227  ((rtIter->first->GetDestNetwork() == Ipv6Address::GetAny()) &&
1228  (rtIter->first->GetDestNetworkPrefix() == Ipv6Prefix::GetZero()) &&
1229  (rtIter->first->GetInterface() != interface));
1230 
1231  if ((isGlobal || isDefaultRoute) && (periodic || rtIter->first->IsRouteChanged()))
1232  {
1233  RipNgRte rte;
1234  rte.SetPrefix(rtIter->first->GetDestNetwork());
1235  rte.SetPrefixLen(rtIter->first->GetDestNetworkPrefix().GetPrefixLength());
1236  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
1237  {
1239  }
1240  else
1241  {
1242  rte.SetRouteMetric(rtIter->first->GetRouteMetric());
1243  }
1244  rte.SetRouteTag(rtIter->first->GetRouteTag());
1245  if (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning)
1246  {
1247  hdr.AddRte(rte);
1248  }
1250  {
1251  hdr.AddRte(rte);
1252  }
1253  }
1254  if (hdr.GetRteNumber() == maxRte)
1255  {
1256  p->AddHeader(hdr);
1257  NS_LOG_DEBUG("SendTo: " << *p);
1258  iter->first->SendTo(p, 0, Inet6SocketAddress(RIPNG_ALL_NODE, RIPNG_PORT));
1259  p->RemoveHeader(hdr);
1260  hdr.ClearRtes();
1261  }
1262  }
1263  if (hdr.GetRteNumber() > 0)
1264  {
1265  p->AddHeader(hdr);
1266  NS_LOG_DEBUG("SendTo: " << *p);
1267  iter->first->SendTo(p, 0, Inet6SocketAddress(RIPNG_ALL_NODE, RIPNG_PORT));
1268  }
1269  }
1270  }
1271  for (auto rtIter = m_routes.begin(); rtIter != m_routes.end(); rtIter++)
1272  {
1273  rtIter->first->SetRouteChanged(false);
1274  }
1275 }
1276 
1277 void
1279 {
1280  NS_LOG_FUNCTION(this);
1281 
1283  {
1284  NS_LOG_LOGIC("Skipping Triggered Update due to cooldown");
1285  return;
1286  }
1287 
1288  // DoSendRouteUpdate (false);
1289 
1290  // note: The RFC states:
1291  // After a triggered
1292  // update is sent, a timer should be set for a random interval between 1
1293  // and 5 seconds. If other changes that would trigger updates occur
1294  // before the timer expires, a single update is triggered when the timer
1295  // expires. The timer is then reset to another random value between 1
1296  // and 5 seconds. Triggered updates may be suppressed if a regular
1297  // update is due by the time the triggered update would be sent.
1298  // Here we rely on this:
1299  // When an update occurs (either Triggered or Periodic) the "IsChanged ()"
1300  // route field will be cleared.
1301  // Hence, the following Triggered Update will be fired, but will not send
1302  // any route update.
1303 
1307 }
1308 
1309 void
1311 {
1312  NS_LOG_FUNCTION(this);
1313 
1315  {
1317  }
1318 
1319  DoSendRouteUpdate(true);
1320 
1321  Time delay =
1324 }
1325 
1326 std::set<uint32_t>
1328 {
1329  return m_interfaceExclusions;
1330 }
1331 
1332 void
1333 RipNg::SetInterfaceExclusions(std::set<uint32_t> exceptions)
1334 {
1335  NS_LOG_FUNCTION(this);
1336 
1337  m_interfaceExclusions = exceptions;
1338 }
1339 
1340 uint8_t
1341 RipNg::GetInterfaceMetric(uint32_t interface) const
1342 {
1343  NS_LOG_FUNCTION(this << interface);
1344 
1345  auto iter = m_interfaceMetrics.find(interface);
1346  if (iter != m_interfaceMetrics.end())
1347  {
1348  return iter->second;
1349  }
1350  return 1;
1351 }
1352 
1353 void
1354 RipNg::SetInterfaceMetric(uint32_t interface, uint8_t metric)
1355 {
1356  NS_LOG_FUNCTION(this << interface << int(metric));
1357 
1358  if (metric < m_linkDown)
1359  {
1360  m_interfaceMetrics[interface] = metric;
1361  }
1362 }
1363 
1364 void
1366 {
1367  NS_LOG_FUNCTION(this);
1368 
1369  Ptr<Packet> p = Create<Packet>();
1371  p->RemovePacketTag(tag);
1372  tag.SetHopLimit(255);
1373  p->AddPacketTag(tag);
1374 
1375  RipNgHeader hdr;
1377 
1378  RipNgRte rte;
1380  rte.SetPrefixLen(0);
1382 
1383  hdr.AddRte(rte);
1384  p->AddHeader(hdr);
1385 
1386  for (auto iter = m_unicastSocketList.begin(); iter != m_unicastSocketList.end(); iter++)
1387  {
1388  uint32_t interface = iter->second;
1389 
1390  if (m_interfaceExclusions.find(interface) == m_interfaceExclusions.end())
1391  {
1392  NS_LOG_DEBUG("SendTo: " << *p);
1393  iter->first->SendTo(p, 0, Inet6SocketAddress(RIPNG_ALL_NODE, RIPNG_PORT));
1394  }
1395  }
1396 }
1397 
1398 void
1399 RipNg::AddDefaultRouteTo(Ipv6Address nextHop, uint32_t interface)
1400 {
1401  NS_LOG_FUNCTION(this << interface);
1402 
1405  nextHop,
1406  interface,
1407  Ipv6Address("::"));
1408 }
1409 
1410 /*
1411  * RipNgRoutingTableEntry
1412  */
1413 
1415  : m_tag(0),
1416  m_metric(0),
1417  m_status(RIPNG_INVALID),
1418  m_changed(false)
1419 {
1420 }
1421 
1423  Ipv6Prefix networkPrefix,
1424  Ipv6Address nextHop,
1425  uint32_t interface,
1426  Ipv6Address prefixToUse)
1427  : Ipv6RoutingTableEntry(RipNgRoutingTableEntry::CreateNetworkRouteTo(network,
1428  networkPrefix,
1429  nextHop,
1430  interface,
1431  prefixToUse)),
1432  m_tag(0),
1433  m_metric(0),
1434  m_status(RIPNG_INVALID),
1435  m_changed(false)
1436 {
1437 }
1438 
1440  Ipv6Prefix networkPrefix,
1441  uint32_t interface)
1443  Ipv6RoutingTableEntry::CreateNetworkRouteTo(network, networkPrefix, interface)),
1444  m_tag(0),
1445  m_metric(0),
1446  m_status(RIPNG_INVALID),
1447  m_changed(false)
1448 {
1449 }
1450 
1452 {
1453 }
1454 
1455 void
1457 {
1458  if (m_tag != routeTag)
1459  {
1460  m_tag = routeTag;
1461  m_changed = true;
1462  }
1463 }
1464 
1465 uint16_t
1467 {
1468  return m_tag;
1469 }
1470 
1471 void
1473 {
1474  if (m_metric != routeMetric)
1475  {
1476  m_metric = routeMetric;
1477  m_changed = true;
1478  }
1479 }
1480 
1481 uint8_t
1483 {
1484  return m_metric;
1485 }
1486 
1487 void
1489 {
1490  if (m_status != status)
1491  {
1492  m_status = status;
1493  m_changed = true;
1494  }
1495 }
1496 
1499 {
1500  return m_status;
1501 }
1502 
1503 void
1505 {
1506  m_changed = changed;
1507 }
1508 
1509 bool
1511 {
1512  return m_changed;
1513 }
1514 
1515 std::ostream&
1516 operator<<(std::ostream& os, const RipNgRoutingTableEntry& rte)
1517 {
1518  os << static_cast<const Ipv6RoutingTableEntry&>(rte);
1519  os << ", metric: " << int(rte.GetRouteMetric()) << ", tag: " << int(rte.GetRouteTag());
1520 
1521  return os;
1522 }
1523 
1524 } // namespace ns3
a polymophic address class
Definition: address.h:101
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
Hold variables of type enum.
Definition: enum.h:62
An identifier for simulation events.
Definition: event-id.h:55
void Cancel()
This method is syntactic sugar for the ns3::Simulator::Cancel method.
Definition: event-id.cc:55
bool IsRunning() const
This method is syntactic sugar for !IsExpired().
Definition: event-id.cc:76
An Inet6 address class.
static Inet6SocketAddress ConvertFrom(const Address &addr)
Convert the address to a InetSocketAddress.
uint16_t GetPort() const
Get the port.
Ipv6Address GetIpv6() const
Get the IPv6 address.
Describes an IPv6 address.
Definition: ipv6-address.h:49
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
static Ipv6Address GetAny()
Get the "any" (::) Ipv6Address.
bool IsLinkLocalMulticast() const
If the IPv6 address is link-local multicast (ff02::/16).
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
bool IsMulticast() const
If the IPv6 address is multicast (ff00::/8).
bool IsAny() const
If the IPv6 address is the "Any" address.
Ipv6Address CombinePrefix(const Ipv6Prefix &prefix) const
Combine this address with a prefix.
Packet header for IPv6.
Definition: ipv6-header.h:35
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: ipv6-header.cc:159
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
IPv6 address associated with an interface.
Ipv6InterfaceAddress::Scope_e GetScope() const
Get address scope.
@ LINKLOCAL
Link-local address (fe80::/64)
@ GLOBAL
Global address (2000::/3)
This class implements a tag that carries socket ancillary data to the socket interface.
uint32_t GetRecvIf() const
Get the tag's receiving interface.
Describes an IPv6 prefix.
Definition: ipv6-address.h:455
uint8_t GetPrefixLength() const
Get prefix length.
static Ipv6Prefix GetZero()
Get the zero prefix ( /0).
bool IsMatch(Ipv6Address a, Ipv6Address b) const
If the Address match the type.
Abstract base class for IPv6 routing protocols.
A record of an IPv6 route.
Ipv6Address GetDest() const
Get the destination.
Ipv6Address GetDestNetwork() const
Get the destination network.
Ipv6Address GetPrefixToUse() const
Get the prefix to use (for multihomed link).
bool IsHost() const
Is the route entry correspond to a host ?
uint32_t GetInterface() const
Get the interface index.
Ipv6Prefix GetDestNetworkPrefix() const
Get the destination prefix.
Ipv6Address GetGateway() const
Get the gateway.
bool IsGateway() const
Is it the gateway ?
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:829
A network Node.
Definition: node.h:57
Ptr< NetDevice > GetDevice(uint32_t index) const
Retrieve the index-th NetDevice associated to this node.
Definition: node.cc:152
virtual void DoInitialize()
Initialize() implementation.
Definition: object.cc:359
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
bool RemovePacketTag(Tag &tag)
Remove a packet tag.
Definition: packet.cc:967
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
void AddPacketTag(const Tag &tag) const
Add a packet tag.
Definition: packet.cc:960
void SetStream(int64_t stream)
Specifies the stream number for the RngStream.
RipNgHeader - see RFC 2080
Definition: ripng-header.h:147
void SetCommand(Command_e command)
Set the command.
void ClearRtes()
Clear all the RTEs from the header.
uint16_t GetRteNumber() const
Get the number of RTE included in the message.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Command_e GetCommand() const
Get the command.
std::list< RipNgRte > GetRteList() const
Get the list of the RTEs included in the message.
void AddRte(RipNgRte rte)
Add a RTE to the message.
RIPng Routing Protocol, defined in RFC 2080.
Definition: ripng.h:178
Ptr< Socket > m_multicastRecvSocket
multicast receive socket
Definition: ripng.h:428
void NotifyInterfaceUp(uint32_t interface) override
Notify when specified interface goes UP.
Definition: ripng.cc:294
void NotifyAddAddress(uint32_t interface, Ipv6InterfaceAddress address) override
Notify when specified interface add an address.
Definition: ripng.cc:404
void NotifyAddRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero()) override
Notify a new route.
Definition: ripng.cc:466
void DoSendRouteUpdate(bool periodic)
Send Routing Updates on all interfaces.
Definition: ripng.cc:1191
Time m_startupDelay
Random delay before protocol startup.
Definition: ripng.h:410
void DoDispose() override
Dispose this object.
Definition: ripng.cc:575
SplitHorizonType_e m_splitHorizonStrategy
Split Horizon strategy.
Definition: ripng.h:438
@ SPLIT_HORIZON
Split Horizon.
Definition: ripng.h:226
@ POISON_REVERSE
Poison Reverse Split Horizon.
Definition: ripng.h:227
@ NO_SPLIT_HORIZON
No Split Horizon.
Definition: ripng.h:225
EventId m_nextTriggeredUpdate
Next Triggered Update event.
Definition: ripng.h:431
~RipNg() override
Definition: ripng.cc:57
void NotifyRemoveAddress(uint32_t interface, Ipv6InterfaceAddress address) override
Notify when specified interface add an address.
Definition: ripng.cc:430
Time m_minTriggeredUpdateDelay
Min cooldown delay after a Triggered Update.
Definition: ripng.h:411
void SetInterfaceExclusions(std::set< uint32_t > exceptions)
Set the set of interface excluded from the protocol.
Definition: ripng.cc:1333
Ptr< Ipv6Route > RouteOutput(Ptr< Packet > p, const Ipv6Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr) override
Query routing cache for an existing route, for an outbound packet.
Definition: ripng.cc:200
EventId m_nextUnsolicitedUpdate
Next Unsolicited Update event.
Definition: ripng.h:430
uint8_t m_linkDown
Link down value.
Definition: ripng.h:441
Time m_maxTriggeredUpdateDelay
Max cooldown delay after a Triggered Update.
Definition: ripng.h:412
void DoInitialize() override
Start protocol operation.
Definition: ripng.cc:127
bool m_initialized
flag to allow socket's late-creation.
Definition: ripng.h:440
SocketList m_unicastSocketList
list of sockets for unicast messages (socket, interface index)
Definition: ripng.h:427
uint8_t GetInterfaceMetric(uint32_t interface) const
Get the metric for an interface.
Definition: ripng.cc:1341
bool RouteInput(Ptr< const Packet > p, const Ipv6Header &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb) override
Route an input packet (to be forwarded or locally delivered)
Definition: ripng.cc:234
Time m_unsolicitedUpdate
time between two Unsolicited Routing Updates
Definition: ripng.h:413
std::set< uint32_t > m_interfaceExclusions
Set of excluded interfaces.
Definition: ripng.h:435
void SetInterfaceMetric(uint32_t interface, uint8_t metric)
Set the metric for an interface.
Definition: ripng.cc:1354
int64_t AssignStreams(int64_t stream)
Assign a fixed random variable stream number to the random variables used by this model.
Definition: ripng.cc:118
void DeleteRoute(RipNgRoutingTableEntry *route)
Delete a route.
Definition: ripng.cc:756
void AddNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse)
Add route to network.
Definition: ripng.cc:696
Time m_garbageCollectionDelay
Delay before deleting an INVALID route.
Definition: ripng.h:415
std::map< uint32_t, uint8_t > m_interfaceMetrics
Map of interface metrics.
Definition: ripng.h:436
RipNg()
Definition: ripng.cc:49
void SendRouteRequest()
Send Routing Request on all interfaces.
Definition: ripng.cc:1365
void NotifyInterfaceDown(uint32_t interface) override
Notify when specified interface goes DOWN.
Definition: ripng.cc:372
Ptr< Ipv6 > m_ipv6
IPv6 reference.
Definition: ripng.h:409
Routes m_routes
the forwarding table for network.
Definition: ripng.h:408
std::set< uint32_t > GetInterfaceExclusions() const
Get the set of interface excluded from the protocol.
Definition: ripng.cc:1327
void SendTriggeredRouteUpdate()
Send Triggered Routing Updates on all interfaces.
Definition: ripng.cc:1278
void HandleRequests(RipNgHeader hdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIPng requests.
Definition: ripng.cc:827
Ptr< UniformRandomVariable > m_rng
Rng stream.
Definition: ripng.h:433
void HandleResponses(RipNgHeader hdr, Ipv6Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
Handle RIPng responses.
Definition: ripng.cc:1005
void NotifyRemoveRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero()) override
Notify route removing.
Definition: ripng.cc:477
static TypeId GetTypeId()
Get the type ID.
Definition: ripng.cc:62
void InvalidateRoute(RipNgRoutingTableEntry *route)
Invalidate a route.
Definition: ripng.cc:732
std::list< std::pair< RipNgRoutingTableEntry *, EventId > >::iterator RoutesI
Iterator for container for the network routes.
Definition: ripng.h:296
void SetIpv6(Ptr< Ipv6 > ipv6) override
Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol.
Definition: ripng.cc:488
void Receive(Ptr< Socket > socket)
Receive RIPng packets.
Definition: ripng.cc:773
void AddDefaultRouteTo(Ipv6Address nextHop, uint32_t interface)
Add a default route to the router through the nextHop located on interface.
Definition: ripng.cc:1399
Time m_timeoutDelay
Delay before invalidating a route.
Definition: ripng.h:414
void SendUnsolicitedRouteUpdate()
Send Unsolicited Routing Updates on all interfaces.
Definition: ripng.cc:1310
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
Definition: ripng.cc:510
Ptr< Ipv6Route > Lookup(Ipv6Address dest, bool setSource, Ptr< NetDevice >=nullptr)
Lookup in the forwarding table for destination.
Definition: ripng.cc:605
RipNg Routing Table Entry.
Definition: ripng.h:65
bool IsRouteChanged() const
Get the route changed status.
Definition: ripng.cc:1510
RipNgRoutingTableEntry()
Definition: ripng.cc:1414
uint16_t GetRouteTag() const
Get the route tag.
Definition: ripng.cc:1466
bool m_changed
route has been updated
Definition: ripng.h:160
uint16_t m_tag
route tag
Definition: ripng.h:157
void SetRouteTag(uint16_t routeTag)
Set the route tag.
Definition: ripng.cc:1456
uint8_t GetRouteMetric() const
Get the route metric.
Definition: ripng.cc:1482
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
Definition: ripng.cc:1472
uint8_t m_metric
route metric
Definition: ripng.h:158
Status_e m_status
route status
Definition: ripng.h:159
Status_e GetRouteStatus() const
Get the route status.
Definition: ripng.cc:1498
void SetRouteChanged(bool changed)
Set the route as changed.
Definition: ripng.cc:1504
~RipNgRoutingTableEntry() override
Definition: ripng.cc:1451
Status_e
Route status.
Definition: ripng.h:71
@ RIPNG_INVALID
Definition: ripng.h:73
@ RIPNG_VALID
Definition: ripng.h:72
void SetRouteStatus(Status_e status)
Set the route status.
Definition: ripng.cc:1488
RipNg Routing Table Entry (RTE) - see RFC 2080
Definition: ripng-header.h:40
void SetPrefix(Ipv6Address prefix)
Set the prefix.
Definition: ripng-header.cc:97
void SetPrefixLen(uint8_t prefixLen)
Set the prefix length.
void SetRouteMetric(uint8_t routeMetric)
Set the route metric.
uint32_t GetSerializedSize() const override
Get the serialized size of the packet.
Definition: ripng-header.cc:64
void SetRouteTag(uint16_t routeTag)
Set the route tag.
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static Time GetDelayLeft(const EventId &id)
Get the remaining time until this event will execute.
Definition: simulator.cc:217
void SetRecvPktInfo(bool flag)
Enable/Disable receive packet information to socket.
Definition: socket.cc:354
void SetRecvCallback(Callback< void, Ptr< Socket >> receivedData)
Notify application when new data is available to be read.
Definition: socket.cc:128
virtual void BindToNetDevice(Ptr< NetDevice > netdevice)
Bind a socket to specific device.
Definition: socket.cc:327
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:72
virtual int Close()=0
Close a socket.
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
@ ERROR_NOROUTETOHOST
Definition: socket.h:95
@ ERROR_NOTERROR
Definition: socket.h:85
virtual int Bind(const Address &address)=0
Allocate a local endpoint for this socket.
void SetIpv6RecvHopLimit(bool ipv6RecvHopLimit)
Tells a socket to pass information about IPv6 Hop Limit up the stack.
Definition: socket.cc:548
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.
virtual int SendTo(Ptr< Packet > p, uint32_t flags, const Address &toAddress)=0
Send data to a specified peer.
This class implements a tag that carries the socket-specific HOPLIMIT of a packet to the IPv6 layer.
Definition: socket.h:1170
uint8_t GetHopLimit() const
Get the tag's Hop Limit.
Definition: socket.cc:674
void SetHopLimit(uint8_t hopLimit)
Set the tag's Hop Limit.
Definition: socket.cc:668
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Definition: time.cc:415
double GetSeconds() const
Get an approximation of the time stored in this instance in the indicated unit.
Definition: nstime.h:403
Unit
The unit to use to interpret a number representing time.
Definition: nstime.h:111
a unique identifier for an interface.
Definition: type-id.h:59
static TypeId LookupByName(std::string name)
Get a TypeId by name.
Definition: type-id.cc:835
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
Packet header for UDP packets.
Definition: udp-header.h:41
uint32_t GetSerializedSize() const override
Definition: udp-header.cc:159
Hold an unsigned integer type.
Definition: uinteger.h:45
double GetValue(double min, double max)
Get the next random value drawn from the distribution.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
Definition: assert.h:86
#define NS_ABORT_MSG(msg)
Unconditional abnormal program termination with a message.
Definition: abort.h:49
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Time Now()
create an ns3::Time instance which contains the current simulation time.
Definition: simulator.cc:305
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Definition: first.py:1
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Ptr< const AttributeAccessor > MakeTimeAccessor(T1 a1)
Definition: nstime.h:1414
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:704
Ptr< const AttributeChecker > MakeEnumChecker(T v, std::string n, Ts... args)
Make an EnumChecker pre-configured with a set of allowed values by name.
Definition: enum.h:194
Ptr< const AttributeChecker > MakeTimeChecker(const Time min, const Time max)
Helper to make a Time checker with bounded range.
Definition: time.cc:533
Ptr< const AttributeAccessor > MakeUintegerAccessor(T1 a1)
Definition: uinteger.h:46
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:159
Definition: second.py:1
#define RIPNG_ALL_NODE
Definition: ripng.cc:39
#define RIPNG_PORT
Definition: ripng.cc:40