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