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