A Discrete-Event Network Simulator
API
ipv6-static-routing.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2007-2009 Strasbourg University
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: Sebastien Vincent <vincent@clarinet.u-strasbg.fr>
18  */
19 
20 #include "ipv6-static-routing.h"
21 
22 #include "ipv6-route.h"
24 
25 #include "ns3/log.h"
26 #include "ns3/names.h"
27 #include "ns3/net-device.h"
28 #include "ns3/node.h"
29 #include "ns3/packet.h"
30 #include "ns3/simulator.h"
31 
32 #include <iomanip>
33 
34 namespace ns3
35 {
36 
37 NS_LOG_COMPONENT_DEFINE("Ipv6StaticRouting");
38 
39 NS_OBJECT_ENSURE_REGISTERED(Ipv6StaticRouting);
40 
41 TypeId
43 {
44  static TypeId tid = TypeId("ns3::Ipv6StaticRouting")
46  .SetGroupName("Internet")
47  .AddConstructor<Ipv6StaticRouting>();
48  return tid;
49 }
50 
52  : m_ipv6(nullptr)
53 {
54  NS_LOG_FUNCTION(this);
55 }
56 
58 {
59  NS_LOG_FUNCTION(this);
60 }
61 
62 void
64 {
65  NS_LOG_FUNCTION(this << ipv6);
66  NS_ASSERT(!m_ipv6 && ipv6);
67  uint32_t i = 0;
68  m_ipv6 = ipv6;
69 
70  for (i = 0; i < m_ipv6->GetNInterfaces(); i++)
71  {
72  if (m_ipv6->IsUp(i))
73  {
75  }
76  else
77  {
79  }
80  }
81 }
82 
83 // Formatted like output of "route -n" command
84 void
86 {
87  NS_LOG_FUNCTION(this << stream);
88  std::ostream* os = stream->GetStream();
89  // Copy the current ostream state
90  std::ios oldState(nullptr);
91  oldState.copyfmt(*os);
92 
93  *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
94 
95  *os << "Node: " << m_ipv6->GetObject<Node>()->GetId() << ", Time: " << Now().As(unit)
96  << ", Local time: " << m_ipv6->GetObject<Node>()->GetLocalTime().As(unit)
97  << ", Ipv6StaticRouting table" << std::endl;
98 
99  if (GetNRoutes() > 0)
100  {
101  *os << "Destination Next Hop Flag Met Ref Use If"
102  << std::endl;
103  for (uint32_t j = 0; j < GetNRoutes(); j++)
104  {
105  std::ostringstream dest;
106  std::ostringstream gw;
107  std::ostringstream mask;
108  std::ostringstream flags;
109  Ipv6RoutingTableEntry route = GetRoute(j);
110  dest << route.GetDest() << "/" << int(route.GetDestNetworkPrefix().GetPrefixLength());
111  *os << std::setw(31) << dest.str();
112  gw << route.GetGateway();
113  *os << std::setw(27) << gw.str();
114  flags << "U";
115  if (route.IsHost())
116  {
117  flags << "H";
118  }
119  else if (route.IsGateway())
120  {
121  flags << "G";
122  }
123  *os << std::setw(5) << flags.str();
124  *os << std::setw(4) << GetMetric(j);
125  // Ref ct not implemented
126  *os << "-"
127  << " ";
128  // Use not implemented
129  *os << "-"
130  << " ";
131  if (!Names::FindName(m_ipv6->GetNetDevice(route.GetInterface())).empty())
132  {
133  *os << Names::FindName(m_ipv6->GetNetDevice(route.GetInterface()));
134  }
135  else
136  {
137  *os << route.GetInterface();
138  }
139  *os << std::endl;
140  }
141  }
142  *os << std::endl;
143  // Restore the previous ostream state
144  (*os).copyfmt(oldState);
145 }
146 
147 void
149  Ipv6Address nextHop,
150  uint32_t interface,
151  Ipv6Address prefixToUse,
152  uint32_t metric)
153 {
154  NS_LOG_FUNCTION(this << dst << nextHop << interface << prefixToUse << metric);
155  if (nextHop.IsLinkLocal())
156  {
157  NS_LOG_WARN("Ipv6StaticRouting::AddHostRouteTo - Next hop should be link-local");
158  }
159 
160  AddNetworkRouteTo(dst, Ipv6Prefix::GetOnes(), nextHop, interface, prefixToUse, metric);
161 }
162 
163 void
164 Ipv6StaticRouting::AddHostRouteTo(Ipv6Address dst, uint32_t interface, uint32_t metric)
165 {
166  NS_LOG_FUNCTION(this << dst << interface << metric);
167  AddNetworkRouteTo(dst, Ipv6Prefix::GetOnes(), interface, metric);
168 }
169 
170 void
172  Ipv6Prefix networkPrefix,
173  Ipv6Address nextHop,
174  uint32_t interface,
175  uint32_t metric)
176 {
177  NS_LOG_FUNCTION(this << network << networkPrefix << nextHop << interface << metric);
178 
179  Ipv6RoutingTableEntry route =
180  Ipv6RoutingTableEntry::CreateNetworkRouteTo(network, networkPrefix, nextHop, interface);
181 
182  if (!LookupRoute(route, metric))
183  {
184  auto routePtr = new Ipv6RoutingTableEntry(route);
185  m_networkRoutes.emplace_back(routePtr, metric);
186  }
187 }
188 
189 void
191  Ipv6Prefix networkPrefix,
192  Ipv6Address nextHop,
193  uint32_t interface,
194  Ipv6Address prefixToUse,
195  uint32_t metric)
196 {
197  NS_LOG_FUNCTION(this << network << networkPrefix << nextHop << interface << prefixToUse
198  << metric);
199  if (nextHop.IsLinkLocal())
200  {
201  NS_LOG_WARN("Ipv6StaticRouting::AddNetworkRouteTo - Next hop should be link-local");
202  }
203 
205  networkPrefix,
206  nextHop,
207  interface,
208  prefixToUse);
209  if (!LookupRoute(route, metric))
210  {
211  auto routePtr = new Ipv6RoutingTableEntry(route);
212  m_networkRoutes.emplace_back(routePtr, metric);
213  }
214 }
215 
216 void
218  Ipv6Prefix networkPrefix,
219  uint32_t interface,
220  uint32_t metric)
221 {
222  NS_LOG_FUNCTION(this << network << networkPrefix << interface);
223 
224  Ipv6RoutingTableEntry route =
225  Ipv6RoutingTableEntry::CreateNetworkRouteTo(network, networkPrefix, interface);
226  if (!LookupRoute(route, metric))
227  {
228  auto routePtr = new Ipv6RoutingTableEntry(route);
229  m_networkRoutes.emplace_back(routePtr, metric);
230  }
231 }
232 
233 void
235  uint32_t interface,
236  Ipv6Address prefixToUse,
237  uint32_t metric)
238 {
239  NS_LOG_FUNCTION(this << nextHop << interface << prefixToUse);
242  nextHop,
243  interface,
244  prefixToUse,
245  metric);
246 }
247 
248 void
250  Ipv6Address group,
251  uint32_t inputInterface,
252  std::vector<uint32_t> outputInterfaces)
253 {
254  NS_LOG_FUNCTION(this << origin << group << inputInterface);
255  auto route = new Ipv6MulticastRoutingTableEntry();
257  group,
258  inputInterface,
259  outputInterfaces);
260  m_multicastRoutes.push_back(route);
261 }
262 
263 void
265 {
266  NS_LOG_FUNCTION(this << outputInterface);
267  auto route = new Ipv6RoutingTableEntry();
268  Ipv6Address network = Ipv6Address("ff00::"); /* RFC 3513 */
269  Ipv6Prefix networkMask = Ipv6Prefix(8);
270  *route = Ipv6RoutingTableEntry::CreateNetworkRouteTo(network, networkMask, outputInterface);
271  m_networkRoutes.emplace_back(route, 0);
272 }
273 
274 uint32_t
276 {
277  NS_LOG_FUNCTION(this);
278  return m_multicastRoutes.size();
279 }
280 
283 {
284  NS_LOG_FUNCTION(this << index);
285  NS_ASSERT_MSG(index < m_multicastRoutes.size(),
286  "Ipv6StaticRouting::GetMulticastRoute () : Index out of range");
287 
288  if (index < m_multicastRoutes.size())
289  {
290  uint32_t tmp = 0;
291  for (auto i = m_multicastRoutes.begin(); i != m_multicastRoutes.end(); i++)
292  {
293  if (tmp == index)
294  {
295  return *i;
296  }
297  tmp++;
298  }
299  }
300  return nullptr;
301 }
302 
303 bool
305  Ipv6Address group,
306  uint32_t inputInterface)
307 {
308  NS_LOG_FUNCTION(this << origin << group << inputInterface);
309  for (auto i = m_multicastRoutes.begin(); i != m_multicastRoutes.end(); i++)
310  {
311  Ipv6MulticastRoutingTableEntry* route = *i;
312  if (origin == route->GetOrigin() && group == route->GetGroup() &&
313  inputInterface == route->GetInputInterface())
314  {
315  delete *i;
316  m_multicastRoutes.erase(i);
317  return true;
318  }
319  }
320  return false;
321 }
322 
323 void
325 {
326  NS_LOG_FUNCTION(this << index);
327  uint32_t tmp = 0;
328 
329  for (auto i = m_multicastRoutes.begin(); i != m_multicastRoutes.end(); i++)
330  {
331  if (tmp == index)
332  {
333  delete *i;
334  m_multicastRoutes.erase(i);
335  return;
336  }
337  tmp++;
338  }
339 }
340 
341 bool
342 Ipv6StaticRouting::HasNetworkDest(Ipv6Address network, uint32_t interfaceIndex)
343 {
344  NS_LOG_FUNCTION(this << network << interfaceIndex);
345 
346  /* in the network table */
347  for (auto j = m_networkRoutes.begin(); j != m_networkRoutes.end(); j++)
348  {
349  Ipv6RoutingTableEntry* rtentry = j->first;
350  Ipv6Prefix prefix = rtentry->GetDestNetworkPrefix();
351  Ipv6Address entry = rtentry->GetDestNetwork();
352 
353  if (prefix.IsMatch(network, entry) && rtentry->GetInterface() == interfaceIndex)
354  {
355  return true;
356  }
357  }
358 
359  /* beuh!!! not route at all */
360  return false;
361 }
362 
363 bool
365 {
366  for (auto j = m_networkRoutes.begin(); j != m_networkRoutes.end(); j++)
367  {
368  Ipv6RoutingTableEntry* rtentry = j->first;
369 
370  if (rtentry->GetDest() == route.GetDest() &&
371  rtentry->GetDestNetworkPrefix() == route.GetDestNetworkPrefix() &&
372  rtentry->GetGateway() == route.GetGateway() &&
373  rtentry->GetInterface() == route.GetInterface() &&
374  rtentry->GetPrefixToUse() == route.GetPrefixToUse() && j->second == metric)
375  {
376  return true;
377  }
378  }
379  return false;
380 }
381 
384 {
385  NS_LOG_FUNCTION(this << dst << interface);
386  Ptr<Ipv6Route> rtentry = nullptr;
387  uint16_t longestMask = 0;
388  uint32_t shortestMetric = 0xffffffff;
389 
390  /* when sending on link-local multicast, there have to be interface specified */
391  if (dst.IsLinkLocalMulticast())
392  {
394  interface,
395  "Try to send on link-local multicast address, and no interface index is given!");
396  rtentry = Create<Ipv6Route>();
397  rtentry->SetSource(
398  m_ipv6->SourceAddressSelection(m_ipv6->GetInterfaceForDevice(interface), dst));
399  rtentry->SetDestination(dst);
400  rtentry->SetGateway(Ipv6Address::GetZero());
401  rtentry->SetOutputDevice(interface);
402  return rtentry;
403  }
404 
405  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end(); it++)
406  {
407  Ipv6RoutingTableEntry* j = it->first;
408  uint32_t metric = it->second;
409  Ipv6Prefix mask = j->GetDestNetworkPrefix();
410  uint16_t maskLen = mask.GetPrefixLength();
411  Ipv6Address entry = j->GetDestNetwork();
412 
413  NS_LOG_LOGIC("Searching for route to " << dst << ", mask length " << maskLen << ", metric "
414  << metric);
415 
416  if (mask.IsMatch(dst, entry))
417  {
418  NS_LOG_LOGIC("Found global network route " << *j << ", mask length " << maskLen
419  << ", metric " << metric);
420 
421  /* if interface is given, check the route will output on this interface */
422  if (!interface || interface == m_ipv6->GetNetDevice(j->GetInterface()))
423  {
424  if (maskLen < longestMask)
425  {
426  NS_LOG_LOGIC("Previous match longer, skipping");
427  continue;
428  }
429 
430  if (maskLen > longestMask)
431  {
432  shortestMetric = 0xffffffff;
433  }
434 
435  longestMask = maskLen;
436  if (metric > shortestMetric)
437  {
438  NS_LOG_LOGIC("Equal mask length, but previous metric shorter, skipping");
439  continue;
440  }
441 
442  shortestMetric = metric;
443  Ipv6RoutingTableEntry* route = j;
444  uint32_t interfaceIdx = route->GetInterface();
445  rtentry = Create<Ipv6Route>();
446 
447  if (route->GetGateway().IsAny())
448  {
449  rtentry->SetSource(
450  m_ipv6->SourceAddressSelection(interfaceIdx, route->GetDest()));
451  }
452  else if (route->GetDest().IsAny()) /* default route */
453  {
454  rtentry->SetSource(m_ipv6->SourceAddressSelection(
455  interfaceIdx,
456  route->GetPrefixToUse().IsAny() ? dst : route->GetPrefixToUse()));
457  }
458  else
459  {
460  rtentry->SetSource(
461  m_ipv6->SourceAddressSelection(interfaceIdx, route->GetDest()));
462  }
463 
464  rtentry->SetDestination(route->GetDest());
465  rtentry->SetGateway(route->GetGateway());
466  rtentry->SetOutputDevice(m_ipv6->GetNetDevice(interfaceIdx));
467  if (maskLen == 128)
468  {
469  break;
470  }
471  }
472  }
473  }
474 
475  if (rtentry)
476  {
477  NS_LOG_LOGIC("Matching route via " << rtentry->GetDestination() << " (Through "
478  << rtentry->GetGateway() << ") at the end");
479  }
480  return rtentry;
481 }
482 
483 void
485 {
486  NS_LOG_FUNCTION(this);
487 
488  for (auto j = m_networkRoutes.begin(); j != m_networkRoutes.end(); j = m_networkRoutes.erase(j))
489  {
490  delete j->first;
491  }
492  m_networkRoutes.clear();
493 
494  for (auto i = m_multicastRoutes.begin(); i != m_multicastRoutes.end();
495  i = m_multicastRoutes.erase(i))
496  {
497  delete (*i);
498  }
499  m_multicastRoutes.clear();
500 
501  m_ipv6 = nullptr;
503 }
504 
506 Ipv6StaticRouting::LookupStatic(Ipv6Address origin, Ipv6Address group, uint32_t interface)
507 {
508  NS_LOG_FUNCTION(this << origin << group << interface);
509  Ptr<Ipv6MulticastRoute> mrtentry = nullptr;
510 
511  for (auto i = m_multicastRoutes.begin(); i != m_multicastRoutes.end(); i++)
512  {
513  Ipv6MulticastRoutingTableEntry* route = *i;
514 
515  /*
516  We've been passed an origin address, a multicast group address and an
517  interface index. We have to decide if the current route in the list is
518  a match.
519 
520  The first case is the restrictive case where the origin, group and index
521  matches. This picks up exact routes during forwarded and exact routes from
522  the local node (in which case the ifIndex is a wildcard).
523  */
524 
525  if (origin == route->GetOrigin() && group == route->GetGroup())
526  {
527  /* skipping SSM case */
528  NS_LOG_LOGIC("Find source specific multicast route" << *i);
529  }
530 
531  if (group == route->GetGroup())
532  {
533  if (interface == Ipv6::IF_ANY || interface == route->GetInputInterface())
534  {
535  NS_LOG_LOGIC("Found multicast route" << *i);
536  mrtentry = Create<Ipv6MulticastRoute>();
537  mrtentry->SetGroup(route->GetGroup());
538  mrtentry->SetOrigin(route->GetOrigin());
539  mrtentry->SetParent(route->GetInputInterface());
540  for (uint32_t j = 0; j < route->GetNOutputInterfaces(); j++)
541  {
542  if (route->GetOutputInterface(j))
543  {
544  NS_LOG_LOGIC("Setting output interface index "
545  << route->GetOutputInterface(j));
546  mrtentry->SetOutputTtl(route->GetOutputInterface(j),
548  }
549  }
550  return mrtentry;
551  }
552  }
553  }
554  return mrtentry;
555 }
556 
557 uint32_t
559 {
560  return m_networkRoutes.size();
561 }
562 
565 {
566  NS_LOG_FUNCTION(this);
567  Ipv6Address dst("::");
568  uint32_t shortestMetric = 0xffffffff;
569  Ipv6RoutingTableEntry* result = nullptr;
570 
571  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end(); it++)
572  {
573  Ipv6RoutingTableEntry* j = it->first;
574  uint32_t metric = it->second;
575  Ipv6Prefix mask = j->GetDestNetworkPrefix();
576  uint16_t maskLen = mask.GetPrefixLength();
577  Ipv6Address entry = j->GetDestNetwork();
578 
579  if (maskLen)
580  {
581  continue;
582  }
583 
584  if (metric > shortestMetric)
585  {
586  continue;
587  }
588  shortestMetric = metric;
589  result = j;
590  }
591 
592  if (result)
593  {
594  return result;
595  }
596  else
597  {
598  return Ipv6RoutingTableEntry();
599  }
600 }
601 
603 Ipv6StaticRouting::GetRoute(uint32_t index) const
604 {
605  NS_LOG_FUNCTION(this << index);
606  uint32_t tmp = 0;
607 
608  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end(); it++)
609  {
610  if (tmp == index)
611  {
612  return it->first;
613  }
614  tmp++;
615  }
616  NS_ASSERT(false);
617  // quiet compiler.
618  return nullptr;
619 }
620 
621 uint32_t
622 Ipv6StaticRouting::GetMetric(uint32_t index) const
623 {
624  NS_LOG_FUNCTION(this << index);
625  uint32_t tmp = 0;
626 
627  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end(); it++)
628  {
629  if (tmp == index)
630  {
631  return it->second;
632  }
633  tmp++;
634  }
635  NS_ASSERT(false);
636  // quiet compiler.
637  return 0;
638 }
639 
640 void
642 {
643  NS_LOG_FUNCTION(this << index);
644  uint32_t tmp = 0;
645 
646  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end(); it++)
647  {
648  if (tmp == index)
649  {
650  delete it->first;
651  m_networkRoutes.erase(it);
652  return;
653  }
654  tmp++;
655  }
656  NS_ASSERT(false);
657 }
658 
659 void
661  Ipv6Prefix prefix,
662  uint32_t ifIndex,
663  Ipv6Address prefixToUse)
664 {
665  NS_LOG_FUNCTION(this << network << prefix << ifIndex);
666 
667  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end(); it++)
668  {
669  Ipv6RoutingTableEntry* rtentry = it->first;
670  if (network == rtentry->GetDest() && rtentry->GetInterface() == ifIndex &&
671  rtentry->GetPrefixToUse() == prefixToUse)
672  {
673  delete it->first;
674  m_networkRoutes.erase(it);
675  return;
676  }
677  }
678 }
679 
682  const Ipv6Header& header,
683  Ptr<NetDevice> oif,
684  Socket::SocketErrno& sockerr)
685 {
686  NS_LOG_FUNCTION(this << header << oif);
687  Ipv6Address destination = header.GetDestination();
688  Ptr<Ipv6Route> rtentry = nullptr;
689 
690  if (destination.IsMulticast())
691  {
692  // Note: Multicast routes for outbound packets are stored in the
693  // normal unicast table. An implication of this is that it is not
694  // possible to source multicast datagrams on multiple interfaces.
695  // This is a well-known property of sockets implementation on
696  // many Unix variants.
697  // So, we just log it and fall through to LookupStatic ()
698  NS_LOG_LOGIC("RouteOutput ()::Multicast destination");
699  }
700 
701  rtentry = LookupStatic(destination, oif);
702  if (rtentry)
703  {
704  sockerr = Socket::ERROR_NOTERROR;
705  }
706  else
707  {
708  sockerr = Socket::ERROR_NOROUTETOHOST;
709  }
710  return rtentry;
711 }
712 
713 bool
715  const Ipv6Header& header,
717  const UnicastForwardCallback& ucb,
718  const MulticastForwardCallback& mcb,
719  const LocalDeliverCallback& lcb,
720  const ErrorCallback& ecb)
721 {
722  NS_LOG_FUNCTION(this << p << header << header.GetSource() << header.GetDestination() << idev);
723  NS_ASSERT(m_ipv6);
724  // Check if input device supports IP
725  NS_ASSERT(m_ipv6->GetInterfaceForDevice(idev) >= 0);
726  uint32_t iif = m_ipv6->GetInterfaceForDevice(idev);
727  Ipv6Address dst = header.GetDestination();
728 
729  // Multicast recognition; handle local delivery here
730  if (dst.IsMulticast())
731  {
732  NS_LOG_LOGIC("Multicast destination");
733  Ptr<Ipv6MulticastRoute> mrtentry = LookupStatic(header.GetSource(),
734  header.GetDestination(),
735  m_ipv6->GetInterfaceForDevice(idev));
736 
737  // \todo check if we want to forward up the packet
738  if (mrtentry)
739  {
740  NS_LOG_LOGIC("Multicast route found");
741  mcb(idev, mrtentry, p, header); // multicast forwarding callback
742  return true;
743  }
744  else
745  {
746  NS_LOG_LOGIC("Multicast route not found");
747  return false; // Let other routing protocols try to handle this
748  }
749  }
750 
751  // Check if input device supports IP forwarding
752  if (!m_ipv6->IsForwarding(iif))
753  {
754  NS_LOG_LOGIC("Forwarding disabled for this interface");
755  if (!ecb.IsNull())
756  {
757  ecb(p, header, Socket::ERROR_NOROUTETOHOST);
758  }
759  return true;
760  }
761  // Next, try to find a route
762  NS_LOG_LOGIC("Unicast destination");
763  Ptr<Ipv6Route> rtentry = LookupStatic(header.GetDestination());
764 
765  if (rtentry)
766  {
767  NS_LOG_LOGIC("Found unicast destination- calling unicast callback");
768  ucb(idev, rtentry, p, header); // unicast forwarding callback
769  return true;
770  }
771  else
772  {
773  NS_LOG_LOGIC("Did not find unicast destination- returning false");
774  return false; // Let other routing protocols try to handle this
775  }
776 }
777 
778 void
780 {
781  for (uint32_t j = 0; j < m_ipv6->GetNAddresses(i); j++)
782  {
783  Ipv6InterfaceAddress addr = m_ipv6->GetAddress(i, j);
784 
785  if (addr.GetAddress() != Ipv6Address() && addr.GetPrefix() != Ipv6Prefix())
786  {
787  if (addr.GetPrefix() == Ipv6Prefix(128))
788  {
789  /* host route */
790  AddHostRouteTo(addr.GetAddress(), i);
791  }
792  else
793  {
794  if (addr.GetOnLink())
795  {
797  addr.GetPrefix(),
798  i);
799  }
800  }
801  }
802  }
803 }
804 
805 void
807 {
808  NS_LOG_FUNCTION(this << i);
809 
810  /* remove all static routes that are going through this interface */
811  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end();)
812  {
813  if (it->first->GetInterface() == i)
814  {
815  delete it->first;
816  it = m_networkRoutes.erase(it);
817  }
818  else
819  {
820  it++;
821  }
822  }
823 }
824 
825 void
827 {
828  if (!m_ipv6->IsUp(interface))
829  {
830  return;
831  }
832 }
833 
834 void
836 {
837  if (!m_ipv6->IsUp(interface))
838  {
839  return;
840  }
841 
842  Ipv6Address networkAddress = address.GetAddress().CombinePrefix(address.GetPrefix());
843  Ipv6Prefix networkMask = address.GetPrefix();
844 
845  // Remove all static routes that are going through this interface
846  // which reference this network
847  for (auto it = m_networkRoutes.begin(); it != m_networkRoutes.end();)
848  {
849  if (it->first->GetInterface() == interface && it->first->IsNetwork() &&
850  it->first->GetDestNetwork() == networkAddress &&
851  it->first->GetDestNetworkPrefix() == networkMask)
852  {
853  delete it->first;
854  it = m_networkRoutes.erase(it);
855  }
856  else
857  {
858  it++;
859  }
860  }
861 }
862 
863 void
865  Ipv6Prefix mask,
866  Ipv6Address nextHop,
867  uint32_t interface,
868  Ipv6Address prefixToUse)
869 {
870  NS_LOG_FUNCTION(this << dst << mask << nextHop << interface << prefixToUse);
871  if (nextHop == Ipv6Address::GetZero())
872  {
873  AddNetworkRouteTo(dst, mask, interface);
874  }
875  else if (dst != Ipv6Address::GetZero())
876  {
877  AddNetworkRouteTo(dst, mask, nextHop, interface);
878  }
879  else /* default route */
880  {
881  /* this case is mainly used by configuring default route following RA processing,
882  * in case of multiple prefix in RA, the first will configured default route
883  */
884 
885  /* for the moment, all default route has the same metric
886  * so according to the longest prefix algorithm,
887  * the default route chosen will be the last added
888  */
889  SetDefaultRoute(nextHop, interface, prefixToUse);
890  }
891 }
892 
893 void
895  Ipv6Prefix mask,
896  Ipv6Address nextHop,
897  uint32_t interface,
898  Ipv6Address prefixToUse)
899 {
900  NS_LOG_FUNCTION(this << dst << mask << nextHop << interface);
901  if (dst != Ipv6Address::GetZero())
902  {
903  for (auto j = m_networkRoutes.begin(); j != m_networkRoutes.end();)
904  {
905  Ipv6RoutingTableEntry* rtentry = j->first;
906  Ipv6Prefix prefix = rtentry->GetDestNetworkPrefix();
907  Ipv6Address entry = rtentry->GetDestNetwork();
908 
909  if (dst == entry && prefix == mask && rtentry->GetInterface() == interface)
910  {
911  delete j->first;
912  j = m_networkRoutes.erase(j);
913  }
914  else
915  {
916  ++j;
917  }
918  }
919  }
920  else
921  {
922  /* default route case */
923  RemoveRoute(dst, mask, interface, prefixToUse);
924  }
925 }
926 
927 } /* namespace ns3 */
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
Describes an IPv6 address.
Definition: ipv6-address.h:49
bool IsLinkLocal() const
If the IPv6 address is a link-local address (fe80::/64).
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
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
static const uint32_t IF_ANY
Any interface magic number.
Definition: ipv6.h:400
IPv6 address associated with an interface.
Ipv6Address GetAddress() const
Get the IPv6 address.
Ipv6Prefix GetPrefix() const
Get the IPv6 prefix.
bool GetOnLink() const
Get the on-link property.
static const uint32_t MAX_TTL
Maximum Time-To-Live (TTL).
Definition: ipv6-route.h:148
A record of an IPv6 multicast route.
uint32_t GetInputInterface() const
Get the input interface address.
uint32_t GetOutputInterface(uint32_t n) const
Get a specified output interface.
Ipv6Address GetGroup() const
Get the group.
static Ipv6MulticastRoutingTableEntry CreateMulticastRoute(Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector< uint32_t > outputInterfaces)
Create a multicast route.
uint32_t GetNOutputInterfaces() const
Get the number of output interfaces of this route.
Ipv6Address GetOrigin() const
Get the source of this route.
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.
static Ipv6Prefix GetOnes()
Get the "all-1" IPv6 mask (ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff).
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.
static Ipv6RoutingTableEntry CreateNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface)
Create a route to a network.
Ipv6Address GetGateway() const
Get the gateway.
bool IsGateway() const
Is it the gateway ?
Static routing protocol for IP version 6 stacks.
void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const override
Print the Routing Table entries.
Ipv6RoutingTableEntry GetRoute(uint32_t i) const
Get a specified route.
void NotifyAddAddress(uint32_t interface, Ipv6InterfaceAddress address) override
Notify when specified interface add an address.
void NotifyRemoveRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero()) override
Notify route removing.
void RemoveRoute(uint32_t i)
Remove a route from the routing table.
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.
void NotifyRemoveAddress(uint32_t interface, Ipv6InterfaceAddress address) override
Notify when specified interface add an address.
static TypeId GetTypeId()
The interface Id associated with this class.
Ptr< Ipv6Route > LookupStatic(Ipv6Address dest, Ptr< NetDevice >=nullptr)
Lookup in the forwarding table for destination.
void NotifyAddRoute(Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address::GetZero()) override
Notify a new route.
bool HasNetworkDest(Ipv6Address dest, uint32_t interfaceIndex)
If the destination is already present in network destination list.
bool LookupRoute(const Ipv6RoutingTableEntry &route, uint32_t metric)
Checks if a route is already present in the forwarding table.
void AddMulticastRoute(Ipv6Address origin, Ipv6Address group, uint32_t inputInterface, std::vector< uint32_t > outputInterfaces)
Add a multicast route for a given multicast source and group.
void AddHostRouteTo(Ipv6Address dest, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address("::"), uint32_t metric=0)
Add route to host.
uint32_t GetNRoutes() const
Get the number or entries in the routing table.
Ipv6MulticastRoutingTableEntry GetMulticastRoute(uint32_t i) const
Get the specified multicast route.
Ipv6RoutingTableEntry GetDefaultRoute()
Get the default route.
MulticastRoutes m_multicastRoutes
the forwarding table for multicast.
uint32_t GetNMulticastRoutes() const
Get the number of entries in the multicast routing table.
bool RemoveMulticastRoute(Ipv6Address origin, Ipv6Address group, uint32_t inputInterface)
Remove a static multicast route.
void NotifyInterfaceDown(uint32_t interface) override
Notify when specified interface goes DOWN.
void DoDispose() override
Dispose this object.
void AddNetworkRouteTo(Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, uint32_t metric=0)
Add route to network.
NetworkRoutes m_networkRoutes
the forwarding table for network.
void NotifyInterfaceUp(uint32_t interface) override
Notify when specified interface goes UP.
void SetDefaultMulticastRoute(uint32_t outputInterface)
Set the default multicast route.
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)
uint32_t GetMetric(uint32_t index) const
Get a metric for route from the static unicast routing table.
void SetIpv6(Ptr< Ipv6 > ipv6) override
Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol.
Ptr< Ipv6 > m_ipv6
Ipv6 reference.
void SetDefaultRoute(Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse=Ipv6Address("::"), uint32_t metric=0)
Set the default route.
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
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
std::ostream * GetStream()
Return a pointer to an ostream previously set in the wrapper.
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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
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
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
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
#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_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#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_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
address
Definition: first.py:47
Every class exported by the ns3 library is enclosed in the ns3 namespace.