A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ipv4-global-routing.cc
Go to the documentation of this file.
1 // -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*-
2 //
3 // Copyright (c) 2008 University of Washington
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 
19 #include <vector>
20 #include <iomanip>
21 #include "ns3/names.h"
22 #include "ns3/log.h"
23 #include "ns3/simulator.h"
24 #include "ns3/object.h"
25 #include "ns3/packet.h"
26 #include "ns3/net-device.h"
27 #include "ns3/ipv4-route.h"
28 #include "ns3/ipv4-routing-table-entry.h"
29 #include "ns3/boolean.h"
30 #include "ipv4-global-routing.h"
31 #include "global-route-manager.h"
32 
33 NS_LOG_COMPONENT_DEFINE ("Ipv4GlobalRouting");
34 
35 namespace ns3 {
36 
37 NS_OBJECT_ENSURE_REGISTERED (Ipv4GlobalRouting);
38 
39 TypeId
41 {
42  static TypeId tid = TypeId ("ns3::Ipv4GlobalRouting")
43  .SetParent<Object> ()
44  .AddAttribute ("RandomEcmpRouting",
45  "Set to true if packets are randomly routed among ECMP; set to false for using only one route consistently",
46  BooleanValue (false),
47  MakeBooleanAccessor (&Ipv4GlobalRouting::m_randomEcmpRouting),
48  MakeBooleanChecker ())
49  .AddAttribute ("RespondToInterfaceEvents",
50  "Set to true if you want to dynamically recompute the global routes upon Interface notification events (up/down, or add/remove address)",
51  BooleanValue (false),
52  MakeBooleanAccessor (&Ipv4GlobalRouting::m_respondToInterfaceEvents),
53  MakeBooleanChecker ())
54  ;
55  return tid;
56 }
57 
59  : m_randomEcmpRouting (false),
60  m_respondToInterfaceEvents (false)
61 {
62  NS_LOG_FUNCTION (this);
63 
64  m_rand = CreateObject<UniformRandomVariable> ();
65 }
66 
68 {
69  NS_LOG_FUNCTION (this);
70 }
71 
72 void
74  Ipv4Address nextHop,
75  uint32_t interface)
76 {
77  NS_LOG_FUNCTION (this << dest << nextHop << interface);
79  *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, nextHop, interface);
80  m_hostRoutes.push_back (route);
81 }
82 
83 void
85  uint32_t interface)
86 {
87  NS_LOG_FUNCTION (this << dest << interface);
89  *route = Ipv4RoutingTableEntry::CreateHostRouteTo (dest, interface);
90  m_hostRoutes.push_back (route);
91 }
92 
93 void
95  Ipv4Mask networkMask,
96  Ipv4Address nextHop,
97  uint32_t interface)
98 {
99  NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
102  networkMask,
103  nextHop,
104  interface);
105  m_networkRoutes.push_back (route);
106 }
107 
108 void
110  Ipv4Mask networkMask,
111  uint32_t interface)
112 {
113  NS_LOG_FUNCTION (this << network << networkMask << interface);
116  networkMask,
117  interface);
118  m_networkRoutes.push_back (route);
119 }
120 
121 void
123  Ipv4Mask networkMask,
124  Ipv4Address nextHop,
125  uint32_t interface)
126 {
127  NS_LOG_FUNCTION (this << network << networkMask << nextHop << interface);
130  networkMask,
131  nextHop,
132  interface);
133  m_ASexternalRoutes.push_back (route);
134 }
135 
136 
139 {
140  NS_LOG_FUNCTION (this << dest << oif);
141  NS_LOG_LOGIC ("Looking for route for destination " << dest);
142  Ptr<Ipv4Route> rtentry = 0;
143  // store all available routes that bring packets to their destination
144  typedef std::vector<Ipv4RoutingTableEntry*> RouteVec_t;
145  RouteVec_t allRoutes;
146 
147  NS_LOG_LOGIC ("Number of m_hostRoutes = " << m_hostRoutes.size ());
148  for (HostRoutesCI i = m_hostRoutes.begin ();
149  i != m_hostRoutes.end ();
150  i++)
151  {
152  NS_ASSERT ((*i)->IsHost ());
153  if ((*i)->GetDest ().IsEqual (dest))
154  {
155  if (oif != 0)
156  {
157  if (oif != m_ipv4->GetNetDevice ((*i)->GetInterface ()))
158  {
159  NS_LOG_LOGIC ("Not on requested interface, skipping");
160  continue;
161  }
162  }
163  allRoutes.push_back (*i);
164  NS_LOG_LOGIC (allRoutes.size () << "Found global host route" << *i);
165  }
166  }
167  if (allRoutes.size () == 0) // if no host route is found
168  {
169  NS_LOG_LOGIC ("Number of m_networkRoutes" << m_networkRoutes.size ());
170  for (NetworkRoutesI j = m_networkRoutes.begin ();
171  j != m_networkRoutes.end ();
172  j++)
173  {
174  Ipv4Mask mask = (*j)->GetDestNetworkMask ();
175  Ipv4Address entry = (*j)->GetDestNetwork ();
176  if (mask.IsMatch (dest, entry))
177  {
178  if (oif != 0)
179  {
180  if (oif != m_ipv4->GetNetDevice ((*j)->GetInterface ()))
181  {
182  NS_LOG_LOGIC ("Not on requested interface, skipping");
183  continue;
184  }
185  }
186  allRoutes.push_back (*j);
187  NS_LOG_LOGIC (allRoutes.size () << "Found global network route" << *j);
188  }
189  }
190  }
191  if (allRoutes.size () == 0) // consider external if no host/network found
192  {
193  for (ASExternalRoutesI k = m_ASexternalRoutes.begin ();
194  k != m_ASexternalRoutes.end ();
195  k++)
196  {
197  Ipv4Mask mask = (*k)->GetDestNetworkMask ();
198  Ipv4Address entry = (*k)->GetDestNetwork ();
199  if (mask.IsMatch (dest, entry))
200  {
201  NS_LOG_LOGIC ("Found external route" << *k);
202  if (oif != 0)
203  {
204  if (oif != m_ipv4->GetNetDevice ((*k)->GetInterface ()))
205  {
206  NS_LOG_LOGIC ("Not on requested interface, skipping");
207  continue;
208  }
209  }
210  allRoutes.push_back (*k);
211  break;
212  }
213  }
214  }
215  if (allRoutes.size () > 0 ) // if route(s) is found
216  {
217  // pick up one of the routes uniformly at random if random
218  // ECMP routing is enabled, or always select the first route
219  // consistently if random ECMP routing is disabled
220  uint32_t selectIndex;
222  {
223  selectIndex = m_rand->GetInteger (0, allRoutes.size ()-1);
224  }
225  else
226  {
227  selectIndex = 0;
228  }
229  Ipv4RoutingTableEntry* route = allRoutes.at (selectIndex);
230  // create a Ipv4Route object from the selected routing table entry
231  rtentry = Create<Ipv4Route> ();
232  rtentry->SetDestination (route->GetDest ());
234  rtentry->SetSource (m_ipv4->GetAddress (route->GetInterface (), 0).GetLocal ());
235  rtentry->SetGateway (route->GetGateway ());
236  uint32_t interfaceIdx = route->GetInterface ();
237  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
238  return rtentry;
239  }
240  else
241  {
242  return 0;
243  }
244 }
245 
246 uint32_t
248 {
249  NS_LOG_FUNCTION (this);
250  uint32_t n = 0;
251  n += m_hostRoutes.size ();
252  n += m_networkRoutes.size ();
253  n += m_ASexternalRoutes.size ();
254  return n;
255 }
256 
258 Ipv4GlobalRouting::GetRoute (uint32_t index) const
259 {
260  NS_LOG_FUNCTION (this << index);
261  if (index < m_hostRoutes.size ())
262  {
263  uint32_t tmp = 0;
264  for (HostRoutesCI i = m_hostRoutes.begin ();
265  i != m_hostRoutes.end ();
266  i++)
267  {
268  if (tmp == index)
269  {
270  return *i;
271  }
272  tmp++;
273  }
274  }
275  index -= m_hostRoutes.size ();
276  uint32_t tmp = 0;
277  if (index < m_networkRoutes.size ())
278  {
279  for (NetworkRoutesCI j = m_networkRoutes.begin ();
280  j != m_networkRoutes.end ();
281  j++)
282  {
283  if (tmp == index)
284  {
285  return *j;
286  }
287  tmp++;
288  }
289  }
290  index -= m_networkRoutes.size ();
291  tmp = 0;
292  for (ASExternalRoutesCI k = m_ASexternalRoutes.begin ();
293  k != m_ASexternalRoutes.end ();
294  k++)
295  {
296  if (tmp == index)
297  {
298  return *k;
299  }
300  tmp++;
301  }
302  NS_ASSERT (false);
303  // quiet compiler.
304  return 0;
305 }
306 void
308 {
309  NS_LOG_FUNCTION (this << index);
310  if (index < m_hostRoutes.size ())
311  {
312  uint32_t tmp = 0;
313  for (HostRoutesI i = m_hostRoutes.begin ();
314  i != m_hostRoutes.end ();
315  i++)
316  {
317  if (tmp == index)
318  {
319  NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_hostRoutes.size ());
320  delete *i;
321  m_hostRoutes.erase (i);
322  NS_LOG_LOGIC ("Done removing host route " << index << "; host route remaining size = " << m_hostRoutes.size ());
323  return;
324  }
325  tmp++;
326  }
327  }
328  index -= m_hostRoutes.size ();
329  uint32_t tmp = 0;
330  for (NetworkRoutesI j = m_networkRoutes.begin ();
331  j != m_networkRoutes.end ();
332  j++)
333  {
334  if (tmp == index)
335  {
336  NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_networkRoutes.size ());
337  delete *j;
338  m_networkRoutes.erase (j);
339  NS_LOG_LOGIC ("Done removing network route " << index << "; network route remaining size = " << m_networkRoutes.size ());
340  return;
341  }
342  tmp++;
343  }
344  index -= m_networkRoutes.size ();
345  tmp = 0;
346  for (ASExternalRoutesI k = m_ASexternalRoutes.begin ();
347  k != m_ASexternalRoutes.end ();
348  k++)
349  {
350  if (tmp == index)
351  {
352  NS_LOG_LOGIC ("Removing route " << index << "; size = " << m_ASexternalRoutes.size ());
353  delete *k;
354  m_ASexternalRoutes.erase (k);
355  NS_LOG_LOGIC ("Done removing network route " << index << "; network route remaining size = " << m_networkRoutes.size ());
356  return;
357  }
358  tmp++;
359  }
360  NS_ASSERT (false);
361 }
362 
363 int64_t
365 {
366  NS_LOG_FUNCTION (this << stream);
367  m_rand->SetStream (stream);
368  return 1;
369 }
370 
371 void
373 {
374  NS_LOG_FUNCTION (this);
375  for (HostRoutesI i = m_hostRoutes.begin ();
376  i != m_hostRoutes.end ();
377  i = m_hostRoutes.erase (i))
378  {
379  delete (*i);
380  }
381  for (NetworkRoutesI j = m_networkRoutes.begin ();
382  j != m_networkRoutes.end ();
383  j = m_networkRoutes.erase (j))
384  {
385  delete (*j);
386  }
387  for (ASExternalRoutesI l = m_ASexternalRoutes.begin ();
388  l != m_ASexternalRoutes.end ();
389  l = m_ASexternalRoutes.erase (l))
390  {
391  delete (*l);
392  }
393 
395 }
396 
397 // Formatted like output of "route -n" command
398 void
400 {
401  NS_LOG_FUNCTION (this << stream);
402  std::ostream* os = stream->GetStream ();
403  if (GetNRoutes () > 0)
404  {
405  *os << "Destination Gateway Genmask Flags Metric Ref Use Iface" << std::endl;
406  for (uint32_t j = 0; j < GetNRoutes (); j++)
407  {
408  std::ostringstream dest, gw, mask, flags;
409  Ipv4RoutingTableEntry route = GetRoute (j);
410  dest << route.GetDest ();
411  *os << std::setiosflags (std::ios::left) << std::setw (16) << dest.str ();
412  gw << route.GetGateway ();
413  *os << std::setiosflags (std::ios::left) << std::setw (16) << gw.str ();
414  mask << route.GetDestNetworkMask ();
415  *os << std::setiosflags (std::ios::left) << std::setw (16) << mask.str ();
416  flags << "U";
417  if (route.IsHost ())
418  {
419  flags << "H";
420  }
421  else if (route.IsGateway ())
422  {
423  flags << "G";
424  }
425  *os << std::setiosflags (std::ios::left) << std::setw (6) << flags.str ();
426  // Metric not implemented
427  *os << "-" << " ";
428  // Ref ct not implemented
429  *os << "-" << " ";
430  // Use not implemented
431  *os << "-" << " ";
432  if (Names::FindName (m_ipv4->GetNetDevice (route.GetInterface ())) != "")
433  {
434  *os << Names::FindName (m_ipv4->GetNetDevice (route.GetInterface ()));
435  }
436  else
437  {
438  *os << route.GetInterface ();
439  }
440  *os << std::endl;
441  }
442  }
443 }
444 
447 {
448  NS_LOG_FUNCTION (this << p << &header << oif << &sockerr);
449 //
450 // First, see if this is a multicast packet we have a route for. If we
451 // have a route, then send the packet down each of the specified interfaces.
452 //
453  if (header.GetDestination ().IsMulticast ())
454  {
455  NS_LOG_LOGIC ("Multicast destination-- returning false");
456  return 0; // Let other routing protocols try to handle this
457  }
458 //
459 // See if this is a unicast packet we have a route for.
460 //
461  NS_LOG_LOGIC ("Unicast destination- looking up");
462  Ptr<Ipv4Route> rtentry = LookupGlobal (header.GetDestination (), oif);
463  if (rtentry)
464  {
465  sockerr = Socket::ERROR_NOTERROR;
466  }
467  else
468  {
469  sockerr = Socket::ERROR_NOROUTETOHOST;
470  }
471  return rtentry;
472 }
473 
474 bool
477 {
478  NS_LOG_FUNCTION (this << p << header << header.GetSource () << header.GetDestination () << idev << &lcb << &ecb);
479  // Check if input device supports IP
480  NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
481  uint32_t iif = m_ipv4->GetInterfaceForDevice (idev);
482 
483  if (header.GetDestination ().IsMulticast ())
484  {
485  NS_LOG_LOGIC ("Multicast destination-- returning false");
486  return false; // Let other routing protocols try to handle this
487  }
488 
489  if (header.GetDestination ().IsBroadcast ())
490  {
491  NS_LOG_LOGIC ("For me (Ipv4Addr broadcast address)");
494  }
495 
497  // Right now, we will be permissive and allow a source to send us
498  // a packet to one of our other interface addresses; that is, the
499  // destination unicast address does not match one of the iif addresses,
500  // but we check our other interfaces. This could be an option
501  // (to remove the outer loop immediately below and just check iif).
502  for (uint32_t j = 0; j < m_ipv4->GetNInterfaces (); j++)
503  {
504  for (uint32_t i = 0; i < m_ipv4->GetNAddresses (j); i++)
505  {
506  Ipv4InterfaceAddress iaddr = m_ipv4->GetAddress (j, i);
507  Ipv4Address addr = iaddr.GetLocal ();
508  if (addr.IsEqual (header.GetDestination ()))
509  {
510  if (j == iif)
511  {
512  NS_LOG_LOGIC ("For me (destination " << addr << " match)");
513  }
514  else
515  {
516  NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestination ());
517  }
518  lcb (p, header, iif);
519  return true;
520  }
521  if (header.GetDestination ().IsEqual (iaddr.GetBroadcast ()))
522  {
523  NS_LOG_LOGIC ("For me (interface broadcast address)");
524  lcb (p, header, iif);
525  return true;
526  }
527  NS_LOG_LOGIC ("Address "<< addr << " not a match");
528  }
529  }
530  // Check if input device supports IP forwarding
531  if (m_ipv4->IsForwarding (iif) == false)
532  {
533  NS_LOG_LOGIC ("Forwarding disabled for this interface");
534  ecb (p, header, Socket::ERROR_NOROUTETOHOST);
535  return false;
536  }
537  // Next, try to find a route
538  NS_LOG_LOGIC ("Unicast destination- looking up global route");
539  Ptr<Ipv4Route> rtentry = LookupGlobal (header.GetDestination ());
540  if (rtentry != 0)
541  {
542  NS_LOG_LOGIC ("Found unicast destination- calling unicast callback");
543  ucb (rtentry, p, header);
544  return true;
545  }
546  else
547  {
548  NS_LOG_LOGIC ("Did not find unicast destination- returning false");
549  return false; // Let other routing protocols try to handle this
550  // route request.
551  }
552 }
553 void
555 {
556  NS_LOG_FUNCTION (this << i);
557  if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events
558  {
562  }
563 }
564 
565 void
567 {
568  NS_LOG_FUNCTION (this << i);
569  if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events
570  {
574  }
575 }
576 
577 void
579 {
580  NS_LOG_FUNCTION (this << interface << address);
581  if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events
582  {
586  }
587 }
588 
589 void
591 {
592  NS_LOG_FUNCTION (this << interface << address);
593  if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events
594  {
598  }
599 }
600 
601 void
603 {
604  NS_LOG_FUNCTION (this << ipv4);
605  NS_ASSERT (m_ipv4 == 0 && ipv4 != 0);
606  m_ipv4 = ipv4;
607 }
608 
609 
610 } // namespace ns3
std::list< Ipv4RoutingTableEntry * >::iterator HostRoutesI
virtual void NotifyInterfaceUp(uint32_t interface)
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
void SetStream(int64_t stream)
Specifies the stream number for this RNG stream.
static void InitializeRoutes()
Compute routes using a Dijkstra SPF computation and populate per-node forwarding tables.
Hold a bool native type.
Definition: boolean.h:38
Callback template class.
Definition: callback.h:920
Ipv4GlobalRouting()
Construct an empty Ipv4GlobalRouting routing protocol,.
uint32_t GetInteger(uint32_t min, uint32_t max)
Returns a random unsigned integer from a uniform distribution over the interval [min,max] including both ends.
bool IsMatch(Ipv4Address a, Ipv4Address b) const
Ipv4Address GetLocal(void) const
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:210
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
#define NS_ASSERT(condition)
Definition: assert.h:64
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream) const
Print the Routing Table entries.
virtual bool RouteInput(Ptr< const Packet > p, const Ipv4Header &header, Ptr< const NetDevice > idev, UnicastForwardCallback ucb, MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb)
Route an input packet (to be forwarded or locally delivered)
bool IsMulticast(void) const
virtual void DoDispose(void)
Definition: object.cc:335
virtual void NotifyInterfaceDown(uint32_t interface)
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
void RemoveRoute(uint32_t i)
Remove a route from the global unicast routing table.
Ipv4RoutingTableEntry * GetRoute(uint32_t i) const
Get a route from the global unicast routing table.
std::list< Ipv4RoutingTableEntry * >::const_iterator ASExternalRoutesCI
ASExternalRoutes m_ASexternalRoutes
void SetSource(Ipv4Address src)
Definition: ipv4-route.cc:49
uint32_t GetInterface(void) const
Packet header for IPv4.
Definition: ipv4-header.h:31
Ptr< UniformRandomVariable > m_rand
A uniform random number generator for randomly routing packets among ECMP.
bool IsGateway(void) const
static Ipv4RoutingTableEntry CreateHostRouteTo(Ipv4Address dest, Ipv4Address nextHop, uint32_t interface)
void SetGateway(Ipv4Address gw)
Definition: ipv4-route.cc:63
static Ipv4RoutingTableEntry CreateNetworkRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
bool m_respondToInterfaceEvents
Set to true if this interface should respond to interface events by globallly recomputing routes...
NS_OBJECT_ENSURE_REGISTERED(AntennaModel)
bool IsBroadcast(void) const
static void DeleteGlobalRoutes()
Delete all static routes on all nodes that have a GlobalRouterInterface.
std::list< Ipv4RoutingTableEntry * >::const_iterator NetworkRoutesCI
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
bool m_randomEcmpRouting
Set to true if packets are randomly routed among ECMP; set to false for using only one route consiste...
int64_t AssignStreams(int64_t stream)
Ptr< Ipv4Route > LookupGlobal(Ipv4Address dest, Ptr< NetDevice > oif=0)
bool IsEqual(const Ipv4Address &other) const
Comparison operation between two Ipv4Addresses.
Definition: ipv4-address.h:81
static void BuildGlobalRoutingDatabase()
Build the routing database by gathering Link State Advertisements from each node exporting a GlobalRo...
Ipv4Address GetDest(void) const
NS_LOG_COMPONENT_DEFINE("Ipv4GlobalRouting")
std::list< Ipv4RoutingTableEntry * >::const_iterator HostRoutesCI
virtual Ptr< Ipv4Route > RouteOutput(Ptr< Packet > p, const Ipv4Header &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
static Time Now(void)
Definition: simulator.cc:180
void SetOutputDevice(Ptr< NetDevice > outputDevice)
Definition: ipv4-route.cc:77
std::list< Ipv4RoutingTableEntry * >::iterator ASExternalRoutesI
void AddNetworkRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
Add a network route to the global routing table.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
std::list< Ipv4RoutingTableEntry * >::iterator NetworkRoutesI
Ipv4Address GetBroadcast(void) const
a class to store IPv4 address information on an interface
Ipv4Address GetGateway(void) const
virtual void SetIpv4(Ptr< Ipv4 > ipv4)
static std::string FindName(Ptr< Object > object)
Definition: names.cc:664
a base class which provides memory management and object aggregation
Definition: object.h:63
tuple address
Definition: first.py:37
bool IsHost(void) const
static TypeId GetTypeId(void)
Ipv4Mask GetDestNetworkMask(void) const
a unique identifier for an interface.
Definition: type-id.h:49
TypeId SetParent(TypeId tid)
Definition: type-id.cc:610
virtual void NotifyAddAddress(uint32_t interface, Ipv4InterfaceAddress address)
std::ostream * GetStream(void)
uint32_t GetNRoutes(void) const
Get the number of individual unicast routes that have been added to the routing table.
void SetDestination(Ipv4Address dest)
Definition: ipv4-route.cc:35
void AddASExternalRouteTo(Ipv4Address network, Ipv4Mask networkMask, Ipv4Address nextHop, uint32_t interface)
Add an external route to the global routing table.
virtual void NotifyRemoveAddress(uint32_t interface, Ipv4InterfaceAddress address)
void AddHostRouteTo(Ipv4Address dest, Ipv4Address nextHop, uint32_t interface)
Add a host route to the global routing table.