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