A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ipv4-global-routing.cc
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
40 Ipv4GlobalRouting::GetTypeId (void)
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 
67 Ipv4GlobalRouting::~Ipv4GlobalRouting ()
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 
138 Ipv4GlobalRouting::LookupGlobal (Ipv4Address dest, Ptr<NetDevice> oif)
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 ());
233  // XXX handle multi-address case
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 
446 Ipv4GlobalRouting::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
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)");
492  // TODO: Local Deliver for broadcast
493  // TODO: Forward broadcast
494  }
495 
496  // TODO: Configurable option to enable RFC 1222 Strong End System Model
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
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.
Callback template class.
Definition: callback.h:369
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.
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
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
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.
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...
bool IsBroadcast(void) const
static void DeleteGlobalRoutes()
Delete all static routes on all nodes that have a GlobalRouterInterface.
#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)
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
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:179
void SetOutputDevice(Ptr< NetDevice > outputDevice)
Definition: ipv4-route.cc:77
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
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
bool IsHost(void) const
Ipv4Mask GetDestNetworkMask(void) const
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.