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