A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
global-route-manager-impl.cc
1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright 2007 University of Washington
4  * Copyright (C) 1999, 2000 Kunihiro Ishiguro, Toshiaki Takada
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation;
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18  *
19  * Authors: Tom Henderson (tomhend@u.washington.edu)
20  *
21  * Kunihiro Ishigura, Toshiaki Takada (GNU Zebra) are attributed authors
22  * of the quagga 0.99.7/src/ospfd/ospf_spf.c code which was ported here
23  */
24 
25 #include <utility>
26 #include <vector>
27 #include <queue>
28 #include <algorithm>
29 #include <iostream>
30 #include "ns3/assert.h"
31 #include "ns3/fatal-error.h"
32 #include "ns3/log.h"
33 #include "ns3/node-list.h"
34 #include "ns3/ipv4.h"
35 #include "ns3/ipv4-routing-protocol.h"
36 #include "ns3/ipv4-list-routing.h"
37 #include "ns3/mpi-interface.h"
38 #include "global-router-interface.h"
39 #include "global-route-manager-impl.h"
40 #include "candidate-queue.h"
41 #include "ipv4-global-routing.h"
42 
43 NS_LOG_COMPONENT_DEFINE ("GlobalRouteManagerImpl");
44 
45 namespace ns3 {
46 
47 std::ostream&
48 operator<< (std::ostream& os, const SPFVertex::NodeExit_t& exit)
49 {
50  os << "(" << exit.first << " ," << exit.second << ")";
51  return os;
52 }
53 
54 std::ostream&
55 operator<< (std::ostream& os, const SPFVertex::ListOfSPFVertex_t& vs)
56 {
57  typedef SPFVertex::ListOfSPFVertex_t::const_iterator CIter_t;
58  os << "{";
59  for (CIter_t iter = vs.begin (); iter != vs.end ();)
60  {
61  os << (*iter)->m_vertexId;
62  if (++iter != vs.end ())
63  {
64  os << ", ";
65  }
66  else
67  {
68  break;
69  }
70  }
71  os << "}";
72  return os;
73 }
74 
75 // ---------------------------------------------------------------------------
76 //
77 // SPFVertex Implementation
78 //
79 // ---------------------------------------------------------------------------
80 
82  m_vertexType (VertexUnknown),
83  m_vertexId ("255.255.255.255"),
84  m_lsa (0),
85  m_distanceFromRoot (SPF_INFINITY),
86  m_rootOif (SPF_INFINITY),
87  m_nextHop ("0.0.0.0"),
88  m_parents (),
89  m_children (),
90  m_vertexProcessed (false)
91 {
92  NS_LOG_FUNCTION (this);
93 }
94 
96  m_vertexId (lsa->GetLinkStateId ()),
97  m_lsa (lsa),
98  m_distanceFromRoot (SPF_INFINITY),
99  m_rootOif (SPF_INFINITY),
100  m_nextHop ("0.0.0.0"),
101  m_parents (),
102  m_children (),
103  m_vertexProcessed (false)
104 {
105  NS_LOG_FUNCTION (this << lsa);
106 
107  if (lsa->GetLSType () == GlobalRoutingLSA::RouterLSA)
108  {
109  NS_LOG_LOGIC ("Setting m_vertexType to VertexRouter");
110  m_vertexType = SPFVertex::VertexRouter;
111  }
112  else if (lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA)
113  {
114  NS_LOG_LOGIC ("Setting m_vertexType to VertexNetwork");
115  m_vertexType = SPFVertex::VertexNetwork;
116  }
117 }
118 
120 {
121  NS_LOG_FUNCTION (this);
122 
123  NS_LOG_LOGIC ("Children vertices - " << m_children);
124  NS_LOG_LOGIC ("Parent verteices - " << m_parents);
125 
126  // find this node from all its parents and remove the entry of this node
127  // from all its parents
128  for (ListOfSPFVertex_t::iterator piter = m_parents.begin ();
129  piter != m_parents.end ();
130  piter++)
131  {
132  // remove the current vertex from its parent's children list. Check
133  // if the size of the list is reduced, or the child<->parent relation
134  // is not bidirectional
135  uint32_t orgCount = (*piter)->m_children.size ();
136  (*piter)->m_children.remove (this);
137  uint32_t newCount = (*piter)->m_children.size ();
138  if (orgCount > newCount)
139  {
140  NS_ASSERT_MSG (orgCount > newCount, "Unable to find the current vertex from its parents --- impossible!");
141  }
142  }
143 
144  // delete children
145  while (m_children.size () > 0)
146  {
147  // pop out children one by one. Some children may disapper
148  // when deleting some other children in the list. As a result,
149  // it is necessary to use pop to walk through all children, instead
150  // of using iterator.
151  //
152  // Note that m_children.pop_front () is not necessary as this
153  // p is removed from the children list when p is deleted
154  SPFVertex* p = m_children.front ();
155  // 'p' == 0, this child is already deleted by its other parent
156  if (p == 0) continue;
157  NS_LOG_LOGIC ("Parent vertex-" << m_vertexId << " deleting its child vertex-" << p->GetVertexId ());
158  delete p;
159  p = 0;
160  }
161  m_children.clear ();
162  // delete parents
163  m_parents.clear ();
164  // delete root exit direction
165  m_ecmpRootExits.clear ();
166 
167  NS_LOG_LOGIC ("Vertex-" << m_vertexId << " completed deleted");
168 }
169 
170 void
172 {
173  NS_LOG_FUNCTION (this << type);
174  m_vertexType = type;
175 }
176 
179 {
180  NS_LOG_FUNCTION (this);
181  return m_vertexType;
182 }
183 
184 void
186 {
187  NS_LOG_FUNCTION (this << id);
188  m_vertexId = id;
189 }
190 
193 {
194  NS_LOG_FUNCTION (this);
195  return m_vertexId;
196 }
197 
198 void
200 {
201  NS_LOG_FUNCTION (this << lsa);
202  m_lsa = lsa;
203 }
204 
206 SPFVertex::GetLSA (void) const
207 {
208  NS_LOG_FUNCTION (this);
209  return m_lsa;
210 }
211 
212 void
214 {
215  NS_LOG_FUNCTION (this << distance);
216  m_distanceFromRoot = distance;
217 }
218 
219 uint32_t
221 {
222  NS_LOG_FUNCTION (this);
223  return m_distanceFromRoot;
224 }
225 
226 void
228 {
229  NS_LOG_FUNCTION (this << parent);
230 
231  // always maintain only one parent when using setter/getter methods
232  m_parents.clear ();
233  m_parents.push_back (parent);
234 }
235 
236 SPFVertex*
237 SPFVertex::GetParent (uint32_t i) const
238 {
239  NS_LOG_FUNCTION (this << i);
240 
241  // If the index i is out-of-range, return 0 and do nothing
242  if (m_parents.size () <= i)
243  {
244  NS_LOG_LOGIC ("Index to SPFVertex's parent is out-of-range.");
245  return 0;
246  }
247  ListOfSPFVertex_t::const_iterator iter = m_parents.begin ();
248  while (i-- > 0)
249  {
250  iter++;
251  }
252  return *iter;
253 }
254 
255 void
257 {
258  NS_LOG_FUNCTION (this << v);
259 
260  NS_LOG_LOGIC ("Before merge, list of parents = " << m_parents);
261  // combine the two lists first, and then remove any duplicated after
262  m_parents.insert (m_parents.end (),
263  v->m_parents.begin (), v->m_parents.end ());
264  // remove duplication
265  m_parents.sort ();
266  m_parents.unique ();
267  NS_LOG_LOGIC ("After merge, list of parents = " << m_parents);
268 }
269 
270 void
272 {
273  NS_LOG_FUNCTION (this << nextHop << id);
274 
275  // always maintain only one root's exit
276  m_ecmpRootExits.clear ();
277  m_ecmpRootExits.push_back (NodeExit_t (nextHop, id));
278  // update the following in order to be backward compatitable with
279  // GetNextHop and GetOutgoingInterface methods
280  m_nextHop = nextHop;
281  m_rootOif = id;
282 }
283 
284 void
285 SPFVertex::SetRootExitDirection (SPFVertex::NodeExit_t exit)
286 {
287  NS_LOG_FUNCTION (this << exit);
288  SetRootExitDirection (exit.first, exit.second);
289 }
290 
291 SPFVertex::NodeExit_t
293 {
294  NS_LOG_FUNCTION (this << i);
295  typedef ListOfNodeExit_t::const_iterator CIter_t;
296 
297  NS_ASSERT_MSG (i < m_ecmpRootExits.size (), "Index out-of-range when accessing SPFVertex::m_ecmpRootExits!");
298  CIter_t iter = m_ecmpRootExits.begin ();
299  while (i-- > 0) { iter++; }
300 
301  return *iter;
302 }
303 
304 SPFVertex::NodeExit_t
306 {
307  NS_LOG_FUNCTION (this);
308 
309  NS_ASSERT_MSG (m_ecmpRootExits.size () <= 1, "Assumed there is at most one exit from the root to this vertex");
310  return GetRootExitDirection (0);
311 }
312 
313 void
315 {
316  NS_LOG_FUNCTION (this << vertex);
317 
318  // obtain the external list of exit directions
319  //
320  // Append the external list into 'this' and remove duplication afterward
321  const ListOfNodeExit_t& extList = vertex->m_ecmpRootExits;
322  m_ecmpRootExits.insert (m_ecmpRootExits.end (),
323  extList.begin (), extList.end ());
324  m_ecmpRootExits.sort ();
325  m_ecmpRootExits.unique ();
326 }
327 
328 void
330 {
331  NS_LOG_FUNCTION (this << vertex);
332 
333  // discard all exit direction currently associated with this vertex,
334  // and copy all the exit directions from the given vertex
335  if (m_ecmpRootExits.size () > 0)
336  {
337  NS_LOG_WARN ("x root exit directions in this vertex are going to be discarded");
338  }
339  m_ecmpRootExits.clear ();
340  m_ecmpRootExits.insert (m_ecmpRootExits.end (),
341  vertex->m_ecmpRootExits.begin (), vertex->m_ecmpRootExits.end ());
342 }
343 
344 uint32_t
346 {
347  NS_LOG_FUNCTION (this);
348  return m_ecmpRootExits.size ();
349 }
350 
351 uint32_t
353 {
354  NS_LOG_FUNCTION (this);
355  return m_children.size ();
356 }
357 
358 SPFVertex*
359 SPFVertex::GetChild (uint32_t n) const
360 {
361  NS_LOG_FUNCTION (this << n);
362  uint32_t j = 0;
363 
364  for ( ListOfSPFVertex_t::const_iterator i = m_children.begin ();
365  i != m_children.end ();
366  i++, j++)
367  {
368  if (j == n)
369  {
370  return *i;
371  }
372  }
373  NS_ASSERT_MSG (false, "Index <n> out of range.");
374  return 0;
375 }
376 
377 uint32_t
379 {
380  NS_LOG_FUNCTION (this << child);
381  m_children.push_back (child);
382  return m_children.size ();
383 }
384 
385 void
387 {
388  NS_LOG_FUNCTION (this << value);
389  m_vertexProcessed = value;
390 }
391 
392 bool
394 {
395  NS_LOG_FUNCTION (this);
396  return m_vertexProcessed;
397 }
398 
399 void
400 SPFVertex::ClearVertexProcessed (void)
401 {
402  NS_LOG_FUNCTION (this);
403  for (uint32_t i = 0; i < this->GetNChildren (); i++)
404  {
405  this->GetChild (i)->ClearVertexProcessed ();
406  }
407  this->SetVertexProcessed (false);
408 }
409 
410 // ---------------------------------------------------------------------------
411 //
412 // GlobalRouteManagerLSDB Implementation
413 //
414 // ---------------------------------------------------------------------------
415 
417  :
418  m_database (),
419  m_extdatabase ()
420 {
421  NS_LOG_FUNCTION (this);
422 }
423 
425 {
426  NS_LOG_FUNCTION (this);
427  LSDBMap_t::iterator i;
428  for (i= m_database.begin (); i!= m_database.end (); i++)
429  {
430  NS_LOG_LOGIC ("free LSA");
431  GlobalRoutingLSA* temp = i->second;
432  delete temp;
433  }
434  for (uint32_t j = 0; j < m_extdatabase.size (); j++)
435  {
436  NS_LOG_LOGIC ("free ASexternalLSA");
437  GlobalRoutingLSA* temp = m_extdatabase.at (j);
438  delete temp;
439  }
440  NS_LOG_LOGIC ("clear map");
441  m_database.clear ();
442 }
443 
444 void
446 {
447  NS_LOG_FUNCTION (this);
448  LSDBMap_t::iterator i;
449  for (i= m_database.begin (); i!= m_database.end (); i++)
450  {
451  GlobalRoutingLSA* temp = i->second;
453  }
454 }
455 
456 void
458 {
459  NS_LOG_FUNCTION (this << addr << lsa);
460  if (lsa->GetLSType () == GlobalRoutingLSA::ASExternalLSAs)
461  {
462  m_extdatabase.push_back (lsa);
463  }
464  else
465  {
466  m_database.insert (LSDBPair_t (addr, lsa));
467  }
468 }
469 
471 GlobalRouteManagerLSDB::GetExtLSA (uint32_t index) const
472 {
473  NS_LOG_FUNCTION (this << index);
474  return m_extdatabase.at (index);
475 }
476 
477 uint32_t
478 GlobalRouteManagerLSDB::GetNumExtLSAs () const
479 {
480  NS_LOG_FUNCTION (this);
481  return m_extdatabase.size ();
482 }
483 
484 GlobalRoutingLSA*
486 {
487  NS_LOG_FUNCTION (this << addr);
488 //
489 // Look up an LSA by its address.
490 //
491  LSDBMap_t::const_iterator i;
492  for (i= m_database.begin (); i!= m_database.end (); i++)
493  {
494  if (i->first == addr)
495  {
496  return i->second;
497  }
498  }
499  return 0;
500 }
501 
504 {
505  NS_LOG_FUNCTION (this << addr);
506 //
507 // Look up an LSA by its address.
508 //
509  LSDBMap_t::const_iterator i;
510  for (i= m_database.begin (); i!= m_database.end (); i++)
511  {
512  GlobalRoutingLSA* temp = i->second;
513 // Iterate among temp's Link Records
514  for (uint32_t j = 0; j < temp->GetNLinkRecords (); j++)
515  {
516  GlobalRoutingLinkRecord *lr = temp->GetLinkRecord (j);
518  lr->GetLinkData () == addr)
519  {
520  return temp;
521  }
522  }
523  }
524  return 0;
525 }
526 
527 // ---------------------------------------------------------------------------
528 //
529 // GlobalRouteManagerImpl Implementation
530 //
531 // ---------------------------------------------------------------------------
532 
533 GlobalRouteManagerImpl::GlobalRouteManagerImpl ()
534  :
535  m_spfroot (0)
536 {
537  NS_LOG_FUNCTION (this);
538  m_lsdb = new GlobalRouteManagerLSDB ();
539 }
540 
541 GlobalRouteManagerImpl::~GlobalRouteManagerImpl ()
542 {
543  NS_LOG_FUNCTION (this);
544  if (m_lsdb)
545  {
546  delete m_lsdb;
547  }
548 }
549 
550 void
552 {
553  NS_LOG_FUNCTION (this << lsdb);
554  if (m_lsdb)
555  {
556  delete m_lsdb;
557  }
558  m_lsdb = lsdb;
559 }
560 
561 void
563 {
564  NS_LOG_FUNCTION (this);
565  NodeList::Iterator listEnd = NodeList::End ();
566  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
567  {
568  Ptr<Node> node = *i;
569  Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
570  if (router == 0)
571  {
572  continue;
573  }
574  Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
575  uint32_t j = 0;
576  uint32_t nRoutes = gr->GetNRoutes ();
577  NS_LOG_LOGIC ("Deleting " << gr->GetNRoutes ()<< " routes from node " << node->GetId ());
578  // Each time we delete route 0, the route index shifts downward
579  // We can delete all routes if we delete the route numbered 0
580  // nRoutes times
581  for (j = 0; j < nRoutes; j++)
582  {
583  NS_LOG_LOGIC ("Deleting global route " << j << " from node " << node->GetId ());
584  gr->RemoveRoute (0);
585  }
586  NS_LOG_LOGIC ("Deleted " << j << " global routes from node "<< node->GetId ());
587  }
588  if (m_lsdb)
589  {
590  NS_LOG_LOGIC ("Deleting LSDB, creating new one");
591  delete m_lsdb;
592  m_lsdb = new GlobalRouteManagerLSDB ();
593  }
594 }
595 
596 //
597 // In order to build the routing database, we need to walk the list of nodes
598 // in the system and look for those that support the GlobalRouter interface.
599 // These routers will export a number of Link State Advertisements (LSAs)
600 // that describe the links and networks that are "adjacent" (i.e., that are
601 // on the other side of a point-to-point link). We take these LSAs and put
602 // add them to the Link State DataBase (LSDB) from which the routes will
603 // ultimately be computed.
604 //
605 void
607 {
608  NS_LOG_FUNCTION (this);
609 //
610 // Walk the list of nodes looking for the GlobalRouter Interface. Nodes with
611 // global router interfaces are, not too surprisingly, our routers.
612 //
613  NodeList::Iterator listEnd = NodeList::End ();
614  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
615  {
616  Ptr<Node> node = *i;
617 
618  Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter> ();
619 //
620 // Ignore nodes that aren't participating in routing.
621 //
622  if (!rtr)
623  {
624  continue;
625  }
626 //
627 // You must call DiscoverLSAs () before trying to use any routing info or to
628 // update LSAs. DiscoverLSAs () drives the process of discovering routes in
629 // the GlobalRouter. Afterward, you may use GetNumLSAs (), which is a very
630 // computationally inexpensive call. If you call GetNumLSAs () before calling
631 // DiscoverLSAs () will get zero as the number since no routes have been
632 // found.
633 //
634  Ptr<Ipv4GlobalRouting> grouting = rtr->GetRoutingProtocol ();
635  uint32_t numLSAs = rtr->DiscoverLSAs ();
636  NS_LOG_LOGIC ("Found " << numLSAs << " LSAs");
637 
638  for (uint32_t j = 0; j < numLSAs; ++j)
639  {
640  GlobalRoutingLSA* lsa = new GlobalRoutingLSA ();
641 //
642 // This is the call to actually fetch a Link State Advertisement from the
643 // router.
644 //
645  rtr->GetLSA (j, *lsa);
646  NS_LOG_LOGIC (*lsa);
647 //
648 // Write the newly discovered link state advertisement to the database.
649 //
650  m_lsdb->Insert (lsa->GetLinkStateId (), lsa);
651  }
652  }
653 }
654 
655 //
656 // For each node that is a global router (which is determined by the presence
657 // of an aggregated GlobalRouter interface), run the Dijkstra SPF calculation
658 // on the database rooted at that router, and populate the node forwarding
659 // tables.
660 //
661 // This function parallels RFC2328, Section 16.1.1, and quagga ospfd
662 //
663 // This calculation yields the set of intra-area routes associated
664 // with an area (called hereafter Area A). A router calculates the
665 // shortest-path tree using itself as the root. The formation
666 // of the shortest path tree is done here in two stages. In the
667 // first stage, only links between routers and transit networks are
668 // considered. Using the Dijkstra algorithm, a tree is formed from
669 // this subset of the link state database. In the second stage,
670 // leaves are added to the tree by considering the links to stub
671 // networks.
672 //
673 // The area's link state database is represented as a directed graph.
674 // The graph's vertices are routers, transit networks and stub networks.
675 //
676 // The first stage of the procedure (i.e., the Dijkstra algorithm)
677 // can now be summarized as follows. At each iteration of the
678 // algorithm, there is a list of candidate vertices. Paths from
679 // the root to these vertices have been found, but not necessarily
680 // the shortest ones. However, the paths to the candidate vertex
681 // that is closest to the root are guaranteed to be shortest; this
682 // vertex is added to the shortest-path tree, removed from the
683 // candidate list, and its adjacent vertices are examined for
684 // possible addition to/modification of the candidate list. The
685 // algorithm then iterates again. It terminates when the candidate
686 // list becomes empty.
687 //
688 void
690 {
691  NS_LOG_FUNCTION (this);
692 //
693 // Walk the list of nodes in the system.
694 //
695  NS_LOG_INFO ("About to start SPF calculation");
696  NodeList::Iterator listEnd = NodeList::End ();
697  for (NodeList::Iterator i = NodeList::Begin (); i != listEnd; i++)
698  {
699  Ptr<Node> node = *i;
700 //
701 // Look for the GlobalRouter interface that indicates that the node is
702 // participating in routing.
703 //
704  Ptr<GlobalRouter> rtr =
705  node->GetObject<GlobalRouter> ();
706 
707  // Ignore nodes that are not assigned to our systemId (distributed sim)
708  if (node->GetSystemId () != MpiInterface::GetSystemId ())
709  {
710  continue;
711  }
712 
713 //
714 // if the node has a global router interface, then run the global routing
715 // algorithms.
716 //
717  if (rtr && rtr->GetNumLSAs () )
718  {
719  SPFCalculate (rtr->GetRouterId ());
720  }
721  }
722  NS_LOG_INFO ("Finished SPF calculation");
723 }
724 
725 //
726 // This method is derived from quagga ospf_spf_next (). See RFC2328 Section
727 // 16.1 (2) for further details.
728 //
729 // We're passed a parameter <v> that is a vertex which is already in the SPF
730 // tree. A vertex represents a router node. We also get a reference to the
731 // SPF candidate queue, which is a priority queue containing the shortest paths
732 // to the networks we know about.
733 //
734 // We examine the links in v's LSA and update the list of candidates with any
735 // vertices not already on the list. If a lower-cost path is found to a
736 // vertex already on the candidate list, store the new (lower) cost.
737 //
738 void
739 GlobalRouteManagerImpl::SPFNext (SPFVertex* v, CandidateQueue& candidate)
740 {
741  NS_LOG_FUNCTION (this << v << &candidate);
742 
743  SPFVertex* w = 0;
744  GlobalRoutingLSA* w_lsa = 0;
746  uint32_t distance = 0;
747  uint32_t numRecordsInVertex = 0;
748 //
749 // V points to a Router-LSA or Network-LSA
750 // Loop over the links in router LSA or attached routers in Network LSA
751 //
753  {
754  numRecordsInVertex = v->GetLSA ()->GetNLinkRecords ();
755  }
757  {
758  numRecordsInVertex = v->GetLSA ()->GetNAttachedRouters ();
759  }
760 
761  for (uint32_t i = 0; i < numRecordsInVertex; i++)
762  {
763 // Get w_lsa: In case of V is Router-LSA
765  {
766  NS_LOG_LOGIC ("Examining link " << i << " of " <<
767  v->GetVertexId () << "'s " <<
768  v->GetLSA ()->GetNLinkRecords () << " link records");
769 //
770 // (a) If this is a link to a stub network, examine the next link in V's LSA.
771 // Links to stub networks will be considered in the second stage of the
772 // shortest path calculation.
773 //
774  l = v->GetLSA ()->GetLinkRecord (i);
775  if (l->GetLinkType () == GlobalRoutingLinkRecord::StubNetwork)
776  {
777  NS_LOG_LOGIC ("Found a Stub record to " << l->GetLinkId ());
778  continue;
779  }
780 //
781 // (b) Otherwise, W is a transit vertex (router or transit network). Look up
782 // the vertex W's LSA (router-LSA or network-LSA) in Area A's link state
783 // database.
784 //
785  if (l->GetLinkType () == GlobalRoutingLinkRecord::PointToPoint)
786  {
787 //
788 // Lookup the link state advertisement of the new link -- we call it <w> in
789 // the link state database.
790 //
791  w_lsa = m_lsdb->GetLSA (l->GetLinkId ());
792  NS_ASSERT (w_lsa);
793  NS_LOG_LOGIC ("Found a P2P record from " <<
794  v->GetVertexId () << " to " << w_lsa->GetLinkStateId ());
795  }
796  else if (l->GetLinkType () ==
798  {
799  w_lsa = m_lsdb->GetLSA (l->GetLinkId ());
800  NS_ASSERT (w_lsa);
801  NS_LOG_LOGIC ("Found a Transit record from " <<
802  v->GetVertexId () << " to " << w_lsa->GetLinkStateId ());
803  }
804  else
805  {
806  NS_ASSERT_MSG (0, "illegal Link Type");
807  }
808  }
809 // Get w_lsa: In case of V is Network-LSA
811  {
812  w_lsa = m_lsdb->GetLSAByLinkData
813  (v->GetLSA ()->GetAttachedRouter (i));
814  if (!w_lsa)
815  {
816  continue;
817  }
818  NS_LOG_LOGIC ("Found a Network LSA from " <<
819  v->GetVertexId () << " to " << w_lsa->GetLinkStateId ());
820  }
821 
822 // Note: w_lsa at this point may be either RouterLSA or NetworkLSA
823 //
824 // (c) If vertex W is already on the shortest-path tree, examine the next
825 // link in the LSA.
826 //
827 // If the link is to a router that is already in the shortest path first tree
828 // then we have it covered -- ignore it.
829 //
831  {
832  NS_LOG_LOGIC ("Skipping -> LSA "<<
833  w_lsa->GetLinkStateId () << " already in SPF tree");
834  continue;
835  }
836 //
837 // (d) Calculate the link state cost D of the resulting path from the root to
838 // vertex W. D is equal to the sum of the link state cost of the (already
839 // calculated) shortest path to vertex V and the advertised cost of the link
840 // between vertices V and W.
841 //
842  if (v->GetLSA ()->GetLSType () == GlobalRoutingLSA::RouterLSA)
843  {
844  distance = v->GetDistanceFromRoot () + l->GetMetric ();
845  }
846  else
847  {
848  distance = v->GetDistanceFromRoot ();
849  }
850 
851  NS_LOG_LOGIC ("Considering w_lsa " << w_lsa->GetLinkStateId ());
852 
853 // Is there already vertex w in candidate list?
855  {
856 // Calculate nexthop to w
857 // We need to figure out how to actually get to the new router represented
858 // by <w>. This will (among other things) find the next hop address to send
859 // packets destined for this network to, and also find the outbound interface
860 // used to forward the packets.
861 
862 // prepare vertex w
863  w = new SPFVertex (w_lsa);
864  if (SPFNexthopCalculation (v, w, l, distance))
865  {
867 //
868 // Push this new vertex onto the priority queue (ordered by distance from the
869 // root node).
870 //
871  candidate.Push (w);
872  NS_LOG_LOGIC ("Pushing " <<
873  w->GetVertexId () << ", parent vertexId: " <<
874  v->GetVertexId () << ", distance: " <<
875  w->GetDistanceFromRoot ());
876  }
877  else
878  NS_ASSERT_MSG (0, "SPFNexthopCalculation never "
879  << "return false, but it does now!");
880  }
881  else if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_CANDIDATE)
882  {
883 //
884 // We have already considered the link represented by <w>. What wse have to
885 // do now is to decide if this new router represents a route with a shorter
886 // distance metric.
887 //
888 // So, locate the vertex in the candidate queue and take a look at the
889 // distance.
890 
891 /* (quagga-0.98.6) W is already on the candidate list; call it cw.
892 * Compare the previously calculated cost (cw->distance)
893 * with the cost we just determined (w->distance) to see
894 * if we've found a shorter path.
895 */
896  SPFVertex* cw;
897  cw = candidate.Find (w_lsa->GetLinkStateId ());
898  if (cw->GetDistanceFromRoot () < distance)
899  {
900 //
901 // This is not a shorter path, so don't do anything.
902 //
903  continue;
904  }
905  else if (cw->GetDistanceFromRoot () == distance)
906  {
907 //
908 // This path is one with an equal cost.
909 //
910  NS_LOG_LOGIC ("Equal cost multiple paths found.");
911 
912 // At this point, there are two instances 'w' and 'cw' of the
913 // same vertex, the vertex that is currently being considered
914 // for adding into the shortest path tree. 'w' is the instance
915 // as seen from the root via vertex 'v', and 'cw' is the instance
916 // as seen from the root via some other vertices other than 'v'.
917 // These two instances are being merged in the following code.
918 // In particular, the parent nodes, the next hops, and the root's
919 // output interfaces of the two instances are being merged.
920 //
921 // Note that this is functionally equivalent to calling
922 // ospf_nexthop_merge (cw->nexthop, w->nexthop) in quagga-0.98.6
923 // (ospf_spf.c::859), although the detail implementation
924 // is very different from quagga (blame ns3::GlobalRouteManagerImpl)
925 
926 // prepare vertex w
927  w = new SPFVertex (w_lsa);
928  SPFNexthopCalculation (v, w, l, distance);
929  cw->MergeRootExitDirections (w);
930  cw->MergeParent (w);
931 // SPFVertexAddParent (w) is necessary as the destructor of
932 // SPFVertex checks if the vertex and its parent is linked
933 // bidirectionally
934  SPFVertexAddParent (w);
935  delete w;
936  }
937  else // cw->GetDistanceFromRoot () > w->GetDistanceFromRoot ()
938  {
939 //
940 // this path represents a new, lower-cost path to <w> (the vertex we found in
941 // the current link record of the link state advertisement of the current root
942 // (vertex <v>)
943 //
944 // N.B. the nexthop_calculation is conditional, if it finds a valid nexthop
945 // it will call spf_add_parents, which will flush the old parents
946 //
947  if (SPFNexthopCalculation (v, cw, l, distance))
948  {
949 //
950 // If we've changed the cost to get to the vertex represented by <w>, we
951 // must reorder the priority queue keyed to that cost.
952 //
953  candidate.Reorder ();
954  }
955  } // new lower cost path found
956  } // end W is already on the candidate list
957  } // end loop over the links in V's LSA
958 }
959 
960 //
961 // This method is derived from quagga ospf_nexthop_calculation() 16.1.1.
962 //
963 // Calculate nexthop from root through V (parent) to vertex W (destination)
964 // with given distance from root->W.
965 //
966 // As appropriate, set w's parent, distance, and nexthop information
967 //
968 // For now, this is greatly simplified from the quagga code
969 //
970 int
971 GlobalRouteManagerImpl::SPFNexthopCalculation (
972  SPFVertex* v,
973  SPFVertex* w,
974  GlobalRoutingLinkRecord* l,
975  uint32_t distance)
976 {
977  NS_LOG_FUNCTION (this << v << w << l << distance);
978 //
979 // If w is a NetworkVertex, l should be null
980 /*
981  if (w->GetVertexType () == SPFVertex::VertexNetwork && l)
982  {
983  NS_ASSERT_MSG (0, "Error: SPFNexthopCalculation parameter problem");
984  }
985 */
986 
987 //
988 // The vertex m_spfroot is a distinguished vertex representing the node at
989 // the root of the calculations. That is, it is the node for which we are
990 // calculating the routes.
991 //
992 // There are two distinct cases for calculating the next hop information.
993 // First, if we're considering a hop from the root to an "adjacent" network
994 // (one that is on the other side of a point-to-point link connected to the
995 // root), then we need to store the information needed to forward down that
996 // link. The second case is if the network is not directly adjacent. In that
997 // case we need to use the forwarding information from the vertex on the path
998 // to the destination that is directly adjacent [node 1] in both cases of the
999 // diagram below.
1000 //
1001 // (1) [root] -> [point-to-point] -> [node 1]
1002 // (2) [root] -> [point-to-point] -> [node 1] -> [point-to-point] -> [node 2]
1003 //
1004 // We call the propagation of next hop information down vertices of a path
1005 // "inheriting" the next hop information.
1006 //
1007 // The point-to-point link information is only useful in this calculation when
1008 // we are examining the root node.
1009 //
1010  if (v == m_spfroot)
1011  {
1012 //
1013 // In this case <v> is the root node, which means it is the starting point
1014 // for the packets forwarded by that node. This also means that the next hop
1015 // address of packets headed for some arbitrary off-network destination must
1016 // be the destination at the other end of one of the links off of the root
1017 // node if this root node is a router. We then need to see if this node <w>
1018 // is a router.
1019 //
1020  if (w->GetVertexType () == SPFVertex::VertexRouter)
1021  {
1022 //
1023 // In the case of point-to-point links, the link data field (m_linkData) of a
1024 // Global Router Link Record contains the local IP address. If we look at the
1025 // link record describing the link from the perspecive of <w> (the remote
1026 // node from the viewpoint of <v>) back to the root node, we can discover the
1027 // IP address of the router to which <v> is adjacent. This is a distinguished
1028 // address -- the next hop address to get from <v> to <w> and all networks
1029 // accessed through that path.
1030 //
1031 // SPFGetNextLink () is a little odd. used in this way it is just going to
1032 // return the link record describing the link from <w> to <v>. Think of it as
1033 // SPFGetLink.
1034 //
1035  NS_ASSERT (l);
1036  GlobalRoutingLinkRecord *linkRemote = 0;
1037  linkRemote = SPFGetNextLink (w, v, linkRemote);
1038 //
1039 // At this point, <l> is the Global Router Link Record describing the point-
1040 // to point link from <v> to <w> from the perspective of <v>; and <linkRemote>
1041 // is the Global Router Link Record describing that same link from the
1042 // perspective of <w> (back to <v>). Now we can just copy the next hop
1043 // address from the m_linkData member variable.
1044 //
1045 // The next hop member variable we put in <w> has the sense "in order to get
1046 // from the root node to the host represented by vertex <w>, you have to send
1047 // the packet to the next hop address specified in w->m_nextHop.
1048 //
1049  Ipv4Address nextHop = linkRemote->GetLinkData ();
1050 //
1051 // Now find the outgoing interface corresponding to the point to point link
1052 // from the perspective of <v> -- remember that <l> is the link "from"
1053 // <v> "to" <w>.
1054 //
1055  uint32_t outIf = FindOutgoingInterfaceId (l->GetLinkData ());
1056 
1057  w->SetRootExitDirection (nextHop, outIf);
1058  w->SetDistanceFromRoot (distance);
1059  w->SetParent (v);
1060  NS_LOG_LOGIC ("Next hop from " <<
1061  v->GetVertexId () << " to " << w->GetVertexId () <<
1062  " goes through next hop " << nextHop <<
1063  " via outgoing interface " << outIf <<
1064  " with distance " << distance);
1065  } // end W is a router vertes
1066  else
1067  {
1068  NS_ASSERT (w->GetVertexType () == SPFVertex::VertexNetwork);
1069 // W is a directly connected network; no next hop is required
1070  GlobalRoutingLSA* w_lsa = w->GetLSA ();
1071  NS_ASSERT (w_lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA);
1072 // Find outgoing interface ID for this network
1073  uint32_t outIf = FindOutgoingInterfaceId (w_lsa->GetLinkStateId (),
1074  w_lsa->GetNetworkLSANetworkMask () );
1075 // Set the next hop to 0.0.0.0 meaning "not exist"
1076  Ipv4Address nextHop = Ipv4Address::GetZero ();
1077  w->SetRootExitDirection (nextHop, outIf);
1078  w->SetDistanceFromRoot (distance);
1079  w->SetParent (v);
1080  NS_LOG_LOGIC ("Next hop from " <<
1081  v->GetVertexId () << " to network " << w->GetVertexId () <<
1082  " via outgoing interface " << outIf <<
1083  " with distance " << distance);
1084  return 1;
1085  }
1086  } // end v is the root
1087  else if (v->GetVertexType () == SPFVertex::VertexNetwork)
1088  {
1089 // See if any of v's parents are the root
1090  if (v->GetParent () == m_spfroot)
1091  {
1092 // 16.1.1 para 5. ...the parent vertex is a network that
1093 // directly connects the calculating router to the destination
1094 // router. The list of next hops is then determined by
1095 // examining the destination's router-LSA...
1096  NS_ASSERT (w->GetVertexType () == SPFVertex::VertexRouter);
1097  GlobalRoutingLinkRecord *linkRemote = 0;
1098  while ((linkRemote = SPFGetNextLink (w, v, linkRemote)))
1099  {
1100 /* ...For each link in the router-LSA that points back to the
1101  * parent network, the link's Link Data field provides the IP
1102  * address of a next hop router. The outgoing interface to
1103  * use can then be derived from the next hop IP address (or
1104  * it can be inherited from the parent network).
1105  */
1106  Ipv4Address nextHop = linkRemote->GetLinkData ();
1107  uint32_t outIf = v->GetRootExitDirection ().second;
1108  w->SetRootExitDirection (nextHop, outIf);
1109  NS_LOG_LOGIC ("Next hop from " <<
1110  v->GetVertexId () << " to " << w->GetVertexId () <<
1111  " goes through next hop " << nextHop <<
1112  " via outgoing interface " << outIf);
1113  }
1114  }
1115  else
1116  {
1117  w->SetRootExitDirection (v->GetRootExitDirection ());
1118  }
1119  }
1120  else
1121  {
1122 //
1123 // If we're calculating the next hop information from a node (v) that is
1124 // *not* the root, then we need to "inherit" the information needed to
1125 // forward the packet from the vertex closer to the root. That is, we'll
1126 // still send packets to the next hop address of the router adjacent to the
1127 // root on the path toward <w>.
1128 //
1129 // Above, when we were considering the root node, we calculated the next hop
1130 // address and outgoing interface required to get off of the root network.
1131 // At this point, we are further away from the root network along one of the
1132 // (shortest) paths. So the next hop and outoing interface remain the same
1133 // (are inherited).
1134 //
1135  w->InheritAllRootExitDirections (v);
1136  }
1137 //
1138 // In all cases, we need valid values for the distance metric and a parent.
1139 //
1140  w->SetDistanceFromRoot (distance);
1141  w->SetParent (v);
1142 
1143  return 1;
1144 }
1145 
1146 //
1147 // This method is derived from quagga ospf_get_next_link ()
1148 //
1149 // First search the Global Router Link Records of vertex <v> for one
1150 // representing a point-to point link to vertex <w>.
1151 //
1152 // What is done depends on prev_link. Contrary to appearances, prev_link just
1153 // acts as a flag here. If prev_link is NULL, we return the first Global
1154 // Router Link Record we find that describes a point-to-point link from <v>
1155 // to <w>. If prev_link is not NULL, we return a Global Router Link Record
1156 // representing a possible *second* link from <v> to <w>.
1157 //
1158 GlobalRoutingLinkRecord*
1159 GlobalRouteManagerImpl::SPFGetNextLink (
1160  SPFVertex* v,
1161  SPFVertex* w,
1162  GlobalRoutingLinkRecord* prev_link)
1163 {
1164  NS_LOG_FUNCTION (this << v << w << prev_link);
1165 
1166  bool skip = true;
1167  bool found_prev_link = false;
1168  GlobalRoutingLinkRecord* l;
1169 //
1170 // If prev_link is 0, we are really looking for the first link, not the next
1171 // link.
1172 //
1173  if (prev_link == 0)
1174  {
1175  skip = false;
1176  found_prev_link = true;
1177  }
1178 //
1179 // Iterate through the Global Router Link Records advertised by the vertex
1180 // <v> looking for records representing the point-to-point links off of this
1181 // vertex.
1182 //
1183  for (uint32_t i = 0; i < v->GetLSA ()->GetNLinkRecords (); ++i)
1184  {
1185  l = v->GetLSA ()->GetLinkRecord (i);
1186 //
1187 // The link ID of a link record representing a point-to-point link is set to
1188 // the router ID of the neighboring router -- the router to which the link
1189 // connects from the perspective of <v> in this case. The vertex ID is also
1190 // set to the router ID (using the link state advertisement of a router node).
1191 // We're just checking to see if the link <l> is actually the link from <v> to
1192 // <w>.
1193 //
1194  if (l->GetLinkId () == w->GetVertexId ())
1195  {
1196  if (!found_prev_link)
1197  {
1198  NS_LOG_LOGIC ("Skipping links before prev_link found");
1199  found_prev_link = true;
1200  continue;
1201  }
1202 
1203  NS_LOG_LOGIC ("Found matching link l: linkId = " <<
1204  l->GetLinkId () << " linkData = " << l->GetLinkData ());
1205 //
1206 // If skip is false, don't (not too surprisingly) skip the link found -- it's
1207 // the one we're interested in. That's either because we didn't pass in a
1208 // previous link, and we're interested in the first one, or because we've
1209 // skipped a previous link and moved forward to the next (which is then the
1210 // one we want).
1211 //
1212  if (skip == false)
1213  {
1214  NS_LOG_LOGIC ("Returning the found link");
1215  return l;
1216  }
1217  else
1218  {
1219 //
1220 // Skip is true and we've found a link from <v> to <w>. We want the next one.
1221 // Setting skip to false gets us the next point-to-point global router link
1222 // record in the LSA from <v>.
1223 //
1224  NS_LOG_LOGIC ("Skipping the found link");
1225  skip = false;
1226  continue;
1227  }
1228  }
1229  }
1230  return 0;
1231 }
1232 
1233 //
1234 // Used for unit tests.
1235 //
1236 void
1238 {
1239  NS_LOG_FUNCTION (this << root);
1240  SPFCalculate (root);
1241 }
1242 
1243 //
1244 // Used to test if a node is a stub, from an OSPF sense.
1245 // If there is only one link of type 1 or 2, then a default route
1246 // can safely be added to the next-hop router and SPF does not need
1247 // to be run
1248 //
1249 bool
1250 GlobalRouteManagerImpl::CheckForStubNode (Ipv4Address root)
1251 {
1252  NS_LOG_FUNCTION (this << root);
1253  GlobalRoutingLSA *rlsa = m_lsdb->GetLSA (root);
1254  Ipv4Address myRouterId = rlsa->GetLinkStateId ();
1255  int transits = 0;
1256  GlobalRoutingLinkRecord *transitLink = 0;
1257  for (uint32_t i = 0; i < rlsa->GetNLinkRecords (); i++)
1258  {
1259  GlobalRoutingLinkRecord *l = rlsa->GetLinkRecord (i);
1261  {
1262  transits++;
1263  transitLink = l;
1264  }
1266  {
1267  transits++;
1268  transitLink = l;
1269  }
1270  }
1271  if (transits == 0)
1272  {
1273  // This router is not connected to any router. Probably, global
1274  // routing should not be called for this node, but we can just raise
1275  // a warning here and return true.
1276  NS_LOG_WARN ("all nodes should have at least one transit link:" << root );
1277  return true;
1278  }
1279  if (transits == 1)
1280  {
1282  {
1283  // Install default route to next hop router
1284  // What is the next hop? We need to check all neighbors on the link.
1285  // If there is a single router that has two transit links, then
1286  // that is the default next hop. If there are more than one
1287  // routers on link with multiple transit links, return false.
1288  // Not yet implemented, so simply return false
1289  NS_LOG_LOGIC ("TBD: Would have inserted default for transit");
1290  return false;
1291  }
1292  else if (transitLink->GetLinkType () == GlobalRoutingLinkRecord::PointToPoint)
1293  {
1294  // Install default route to next hop
1295  // The link record LinkID is the router ID of the peer.
1296  // The Link Data is the local IP interface address
1297  GlobalRoutingLSA *w_lsa = m_lsdb->GetLSA (transitLink->GetLinkId ());
1298  uint32_t nLinkRecords = w_lsa->GetNLinkRecords ();
1299  for (uint32_t j = 0; j < nLinkRecords; ++j)
1300  {
1301  //
1302  // We are only concerned about point-to-point links
1303  //
1304  GlobalRoutingLinkRecord *lr = w_lsa->GetLinkRecord (j);
1305  if (lr->GetLinkType () != GlobalRoutingLinkRecord::PointToPoint)
1306  {
1307  continue;
1308  }
1309  // Find the link record that corresponds to our routerId
1310  if (lr->GetLinkId () == myRouterId)
1311  {
1312  // Next hop is stored in the LinkID field of lr
1313  Ptr<GlobalRouter> router = rlsa->GetNode ()->GetObject<GlobalRouter> ();
1314  NS_ASSERT (router);
1315  Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
1316  NS_ASSERT (gr);
1317  gr->AddNetworkRouteTo (Ipv4Address ("0.0.0.0"), Ipv4Mask ("0.0.0.0"), lr->GetLinkData (),
1318  FindOutgoingInterfaceId (transitLink->GetLinkData ()));
1319  NS_LOG_LOGIC ("Inserting default route for node " << myRouterId << " to next hop " <<
1320  lr->GetLinkData () << " via interface " <<
1321  FindOutgoingInterfaceId (transitLink->GetLinkData ()));
1322  return true;
1323  }
1324  }
1325  }
1326  }
1327  return false;
1328 }
1329 
1330 // quagga ospf_spf_calculate
1331 void
1332 GlobalRouteManagerImpl::SPFCalculate (Ipv4Address root)
1333 {
1334  NS_LOG_FUNCTION (this << root);
1335 
1336  SPFVertex *v;
1337 //
1338 // Initialize the Link State Database.
1339 //
1340  m_lsdb->Initialize ();
1341 //
1342 // The candidate queue is a priority queue of SPFVertex objects, with the top
1343 // of the queue being the closest vertex in terms of distance from the root
1344 // of the tree. Initially, this queue is empty.
1345 //
1346  CandidateQueue candidate;
1347  NS_ASSERT (candidate.Size () == 0);
1348 //
1349 // Initialize the shortest-path tree to only contain the router doing the
1350 // calculation. Each router (and corresponding network) is a vertex in the
1351 // shortest path first (SPF) tree.
1352 //
1353  v = new SPFVertex (m_lsdb->GetLSA (root));
1354 //
1355 // This vertex is the root of the SPF tree and it is distance 0 from the root.
1356 // We also mark this vertex as being in the SPF tree.
1357 //
1358  m_spfroot= v;
1359  v->SetDistanceFromRoot (0);
1360  v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE);
1361  NS_LOG_LOGIC ("Starting SPFCalculate for node " << root);
1362 
1363 //
1364 // Optimize SPF calculation, for ns-3.
1365 // We do not need to calculate SPF for every node in the network if this
1366 // node has only one interface through which another router can be
1367 // reached. Instead, short-circuit this computation and just install
1368 // a default route in the CheckForStubNode() method.
1369 //
1370  if (NodeList::GetNNodes () > 0 && CheckForStubNode (root))
1371  {
1372  NS_LOG_LOGIC ("SPFCalculate truncated for stub node " << root);
1373  delete m_spfroot;
1374  return;
1375  }
1376 
1377  for (;;)
1378  {
1379 //
1380 // The operations we need to do are given in the OSPF RFC which we reference
1381 // as we go along.
1382 //
1383 // RFC2328 16.1. (2).
1384 //
1385 // We examine the Global Router Link Records in the Link State
1386 // Advertisements of the current vertex. If there are any point-to-point
1387 // links to unexplored adjacent vertices we add them to the tree and update
1388 // the distance and next hop information on how to get there. We also add
1389 // the new vertices to the candidate queue (the priority queue ordered by
1390 // shortest path). If the new vertices represent shorter paths, we use them
1391 // and update the path cost.
1392 //
1393  SPFNext (v, candidate);
1394 //
1395 // RFC2328 16.1. (3).
1396 //
1397 // If at this step the candidate list is empty, the shortest-path tree (of
1398 // transit vertices) has been completely built and this stage of the
1399 // procedure terminates.
1400 //
1401  if (candidate.Size () == 0)
1402  {
1403  break;
1404  }
1405 //
1406 // Choose the vertex belonging to the candidate list that is closest to the
1407 // root, and add it to the shortest-path tree (removing it from the candidate
1408 // list in the process).
1409 //
1410 // Recall that in the previous step, we created SPFVertex structures for each
1411 // of the routers found in the Global Router Link Records and added tehm to
1412 // the candidate list.
1413 //
1414  NS_LOG_LOGIC (candidate);
1415  v = candidate.Pop ();
1416  NS_LOG_LOGIC ("Popped vertex " << v->GetVertexId ());
1417 //
1418 // Update the status field of the vertex to indicate that it is in the SPF
1419 // tree.
1420 //
1421  v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE);
1422 //
1423 // The current vertex has a parent pointer. By calling this rather oddly
1424 // named method (blame quagga) we add the current vertex to the list of
1425 // children of that parent vertex. In the next hop calculation called during
1426 // SPFNext, the parent pointer was set but the vertex has been orphaned up
1427 // to now.
1428 //
1429  SPFVertexAddParent (v);
1430 //
1431 // Note that when there is a choice of vertices closest to the root, network
1432 // vertices must be chosen before router vertices in order to necessarily
1433 // find all equal-cost paths.
1434 //
1435 // RFC2328 16.1. (4).
1436 //
1437 // This is the method that actually adds the routes. It'll walk the list
1438 // of nodes in the system, looking for the node corresponding to the router
1439 // ID of the root of the tree -- that is the router we're building the routes
1440 // for. It looks for the Ipv4 interface of that node and remembers it. So
1441 // we are only actually adding routes to that one node at the root of the SPF
1442 // tree.
1443 //
1444 // We're going to pop of a pointer to every vertex in the tree except the
1445 // root in order of distance from the root. For each of the vertices, we call
1446 // SPFIntraAddRouter (). Down in SPFIntraAddRouter, we look at all of the
1447 // point-to-point Global Router Link Records (the links to nodes adjacent to
1448 // the node represented by the vertex). We add a route to the IP address
1449 // specified by the m_linkData field of each of those link records. This will
1450 // be the *local* IP address associated with the interface attached to the
1451 // link. We use the outbound interface and next hop information present in
1452 // the vertex <v> which have possibly been inherited from the root.
1453 //
1454 // To summarize, we're going to look at the node represented by <v> and loop
1455 // through its point-to-point links, adding a *host* route to the local IP
1456 // address (at the <v> side) for each of those links.
1457 //
1458  if (v->GetVertexType () == SPFVertex::VertexRouter)
1459  {
1460  SPFIntraAddRouter (v);
1461  }
1462  else if (v->GetVertexType () == SPFVertex::VertexNetwork)
1463  {
1464  SPFIntraAddTransit (v);
1465  }
1466  else
1467  {
1468  NS_ASSERT_MSG (0, "illegal SPFVertex type");
1469  }
1470 //
1471 // RFC2328 16.1. (5).
1472 //
1473 // Iterate the algorithm by returning to Step 2 until there are no more
1474 // candidate vertices.
1475 
1476  } // end for loop
1477 
1478 // Second stage of SPF calculation procedure
1479  SPFProcessStubs (m_spfroot);
1480  for (uint32_t i = 0; i < m_lsdb->GetNumExtLSAs (); i++)
1481  {
1482  m_spfroot->ClearVertexProcessed ();
1483  GlobalRoutingLSA *extlsa = m_lsdb->GetExtLSA (i);
1484  NS_LOG_LOGIC ("Processing External LSA with id " << extlsa->GetLinkStateId ());
1485  ProcessASExternals (m_spfroot, extlsa);
1486  }
1487 
1488 //
1489 // We're all done setting the routing information for the node at the root of
1490 // the SPF tree. Delete all of the vertices and corresponding resources. Go
1491 // possibly do it again for the next router.
1492 //
1493  delete m_spfroot;
1494  m_spfroot = 0;
1495 }
1496 
1497 void
1498 GlobalRouteManagerImpl::ProcessASExternals (SPFVertex* v, GlobalRoutingLSA* extlsa)
1499 {
1500  NS_LOG_FUNCTION (this << v << extlsa);
1501  NS_LOG_LOGIC ("Processing external for destination " <<
1502  extlsa->GetLinkStateId () <<
1503  ", for router " << v->GetVertexId () <<
1504  ", advertised by " << extlsa->GetAdvertisingRouter ());
1505  if (v->GetVertexType () == SPFVertex::VertexRouter)
1506  {
1507  GlobalRoutingLSA *rlsa = v->GetLSA ();
1508  NS_LOG_LOGIC ("Processing router LSA with id " << rlsa->GetLinkStateId ());
1509  if ((rlsa->GetLinkStateId ()) == (extlsa->GetAdvertisingRouter ()))
1510  {
1511  NS_LOG_LOGIC ("Found advertising router to destination");
1512  SPFAddASExternal (extlsa,v);
1513  }
1514  }
1515  for (uint32_t i = 0; i < v->GetNChildren (); i++)
1516  {
1517  if (!v->GetChild (i)->IsVertexProcessed ())
1518  {
1519  NS_LOG_LOGIC ("Vertex's child " << i << " not yet processed, processing...");
1520  ProcessASExternals (v->GetChild (i), extlsa);
1521  v->GetChild (i)->SetVertexProcessed (true);
1522  }
1523  }
1524 }
1525 
1526 //
1527 // Adding external routes to routing table - modeled after
1528 // SPFAddIntraAddStub()
1529 //
1530 
1531 void
1532 GlobalRouteManagerImpl::SPFAddASExternal (GlobalRoutingLSA *extlsa, SPFVertex *v)
1533 {
1534  NS_LOG_FUNCTION (this << extlsa << v);
1535 
1536  NS_ASSERT_MSG (m_spfroot, "GlobalRouteManagerImpl::SPFAddASExternal (): Root pointer not set");
1537 // Two cases to consider: We are advertising the external ourselves
1538 // => No need to add anything
1539 // OR find best path to the advertising router
1540  if (v->GetVertexId () == m_spfroot->GetVertexId ())
1541  {
1542  NS_LOG_LOGIC ("External is on local host: "
1543  << v->GetVertexId () << "; returning");
1544  return;
1545  }
1546  NS_LOG_LOGIC ("External is on remote host: "
1547  << extlsa->GetAdvertisingRouter () << "; installing");
1548 
1549  Ipv4Address routerId = m_spfroot->GetVertexId ();
1550 
1551  NS_LOG_LOGIC ("Vertex ID = " << routerId);
1552 //
1553 // We need to walk the list of nodes looking for the one that has the router
1554 // ID corresponding to the root vertex. This is the one we're going to write
1555 // the routing information to.
1556 //
1557  NodeList::Iterator i = NodeList::Begin ();
1558  NodeList::Iterator listEnd = NodeList::End ();
1559  for (; i != listEnd; i++)
1560  {
1561  Ptr<Node> node = *i;
1562 //
1563 // The router ID is accessible through the GlobalRouter interface, so we need
1564 // to QI for that interface. If there's no GlobalRouter interface, the node
1565 // in question cannot be the router we want, so we continue.
1566 //
1567  Ptr<GlobalRouter> rtr = node->GetObject<GlobalRouter> ();
1568 
1569  if (rtr == 0)
1570  {
1571  NS_LOG_LOGIC ("No GlobalRouter interface on node " << node->GetId ());
1572  continue;
1573  }
1574 //
1575 // If the router ID of the current node is equal to the router ID of the
1576 // root of the SPF tree, then this node is the one for which we need to
1577 // write the routing tables.
1578 //
1579  NS_LOG_LOGIC ("Considering router " << rtr->GetRouterId ());
1580 
1581  if (rtr->GetRouterId () == routerId)
1582  {
1583  NS_LOG_LOGIC ("Setting routes for node " << node->GetId ());
1584 //
1585 // Routing information is updated using the Ipv4 interface. We need to QI
1586 // for that interface. If the node is acting as an IP version 4 router, it
1587 // should absolutely have an Ipv4 interface.
1588 //
1589  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
1590  NS_ASSERT_MSG (ipv4,
1591  "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
1592  "QI for <Ipv4> interface failed");
1593 //
1594 // Get the Global Router Link State Advertisement from the vertex we're
1595 // adding the routes to. The LSA will have a number of attached Global Router
1596 // Link Records corresponding to links off of that vertex / node. We're going
1597 // to be interested in the records corresponding to point-to-point links.
1598 //
1599  NS_ASSERT_MSG (v->GetLSA (),
1600  "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
1601  "Expected valid LSA in SPFVertex* v");
1602  Ipv4Mask tempmask = extlsa->GetNetworkLSANetworkMask ();
1603  Ipv4Address tempip = extlsa->GetLinkStateId ();
1604  tempip = tempip.CombineMask (tempmask);
1605 
1606 //
1607 // Here's why we did all of that work. We're going to add a host route to the
1608 // host address found in the m_linkData field of the point-to-point link
1609 // record. In the case of a point-to-point link, this is the local IP address
1610 // of the node connected to the link. Each of these point-to-point links
1611 // will correspond to a local interface that has an IP address to which
1612 // the node at the root of the SPF tree can send packets. The vertex <v>
1613 // (corresponding to the node that has these links and interfaces) has
1614 // an m_nextHop address precalculated for us that is the address to which the
1615 // root node should send packets to be forwarded to these IP addresses.
1616 // Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
1617 // which the packets should be send for forwarding.
1618 //
1619  Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
1620  if (router == 0)
1621  {
1622  continue;
1623  }
1624  Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
1625  NS_ASSERT (gr);
1626  // walk through all next-hop-IPs and out-going-interfaces for reaching
1627  // the stub network gateway 'v' from the root node
1628  for (uint32_t i = 0; i < v->GetNRootExitDirections (); i++)
1629  {
1630  SPFVertex::NodeExit_t exit = v->GetRootExitDirection (i);
1631  Ipv4Address nextHop = exit.first;
1632  int32_t outIf = exit.second;
1633  if (outIf >= 0)
1634  {
1635  gr->AddASExternalRouteTo (tempip, tempmask, nextHop, outIf);
1636  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1637  " add external network route to " << tempip <<
1638  " using next hop " << nextHop <<
1639  " via interface " << outIf);
1640  }
1641  else
1642  {
1643  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1644  " NOT able to add network route to " << tempip <<
1645  " using next hop " << nextHop <<
1646  " since outgoing interface id is negative");
1647  }
1648  }
1649  return;
1650  } // if
1651  } // for
1652 }
1653 
1654 
1655 // Processing logic from RFC 2328, page 166 and quagga ospf_spf_process_stubs ()
1656 // stub link records will exist for point-to-point interfaces and for
1657 // broadcast interfaces for which no neighboring router can be found
1658 void
1659 GlobalRouteManagerImpl::SPFProcessStubs (SPFVertex* v)
1660 {
1661  NS_LOG_FUNCTION (this << v);
1662  NS_LOG_LOGIC ("Processing stubs for " << v->GetVertexId ());
1663  if (v->GetVertexType () == SPFVertex::VertexRouter)
1664  {
1665  GlobalRoutingLSA *rlsa = v->GetLSA ();
1666  NS_LOG_LOGIC ("Processing router LSA with id " << rlsa->GetLinkStateId ());
1667  for (uint32_t i = 0; i < rlsa->GetNLinkRecords (); i++)
1668  {
1669  NS_LOG_LOGIC ("Examining link " << i << " of " <<
1670  v->GetVertexId () << "'s " <<
1671  v->GetLSA ()->GetNLinkRecords () << " link records");
1672  GlobalRoutingLinkRecord *l = v->GetLSA ()->GetLinkRecord (i);
1673  if (l->GetLinkType () == GlobalRoutingLinkRecord::StubNetwork)
1674  {
1675  NS_LOG_LOGIC ("Found a Stub record to " << l->GetLinkId ());
1676  SPFIntraAddStub (l, v);
1677  continue;
1678  }
1679  }
1680  }
1681  for (uint32_t i = 0; i < v->GetNChildren (); i++)
1682  {
1683  if (!v->GetChild (i)->IsVertexProcessed ())
1684  {
1685  SPFProcessStubs (v->GetChild (i));
1686  v->GetChild (i)->SetVertexProcessed (true);
1687  }
1688  }
1689 }
1690 
1691 // RFC2328 16.1. second stage.
1692 void
1693 GlobalRouteManagerImpl::SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v)
1694 {
1695  NS_LOG_FUNCTION (this << l << v);
1696 
1697  NS_ASSERT_MSG (m_spfroot,
1698  "GlobalRouteManagerImpl::SPFIntraAddStub (): Root pointer not set");
1699 
1700  // XXX simplifed logic for the moment. There are two cases to consider:
1701  // 1) the stub network is on this router; do nothing for now
1702  // (already handled above)
1703  // 2) the stub network is on a remote router, so I should use the
1704  // same next hop that I use to get to vertex v
1705  if (v->GetVertexId () == m_spfroot->GetVertexId ())
1706  {
1707  NS_LOG_LOGIC ("Stub is on local host: " << v->GetVertexId () << "; returning");
1708  return;
1709  }
1710  NS_LOG_LOGIC ("Stub is on remote host: " << v->GetVertexId () << "; installing");
1711 //
1712 // The root of the Shortest Path First tree is the router to which we are
1713 // going to write the actual routing table entries. The vertex corresponding
1714 // to this router has a vertex ID which is the router ID of that node. We're
1715 // going to use this ID to discover which node it is that we're actually going
1716 // to update.
1717 //
1718  Ipv4Address routerId = m_spfroot->GetVertexId ();
1719 
1720  NS_LOG_LOGIC ("Vertex ID = " << routerId);
1721 //
1722 // We need to walk the list of nodes looking for the one that has the router
1723 // ID corresponding to the root vertex. This is the one we're going to write
1724 // the routing information to.
1725 //
1726  NodeList::Iterator i = NodeList::Begin ();
1727  NodeList::Iterator listEnd = NodeList::End ();
1728  for (; i != listEnd; i++)
1729  {
1730  Ptr<Node> node = *i;
1731 //
1732 // The router ID is accessible through the GlobalRouter interface, so we need
1733 // to QI for that interface. If there's no GlobalRouter interface, the node
1734 // in question cannot be the router we want, so we continue.
1735 //
1736  Ptr<GlobalRouter> rtr =
1737  node->GetObject<GlobalRouter> ();
1738 
1739  if (rtr == 0)
1740  {
1741  NS_LOG_LOGIC ("No GlobalRouter interface on node " <<
1742  node->GetId ());
1743  continue;
1744  }
1745 //
1746 // If the router ID of the current node is equal to the router ID of the
1747 // root of the SPF tree, then this node is the one for which we need to
1748 // write the routing tables.
1749 //
1750  NS_LOG_LOGIC ("Considering router " << rtr->GetRouterId ());
1751 
1752  if (rtr->GetRouterId () == routerId)
1753  {
1754  NS_LOG_LOGIC ("Setting routes for node " << node->GetId ());
1755 //
1756 // Routing information is updated using the Ipv4 interface. We need to QI
1757 // for that interface. If the node is acting as an IP version 4 router, it
1758 // should absolutely have an Ipv4 interface.
1759 //
1760  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
1761  NS_ASSERT_MSG (ipv4,
1762  "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
1763  "QI for <Ipv4> interface failed");
1764 //
1765 // Get the Global Router Link State Advertisement from the vertex we're
1766 // adding the routes to. The LSA will have a number of attached Global Router
1767 // Link Records corresponding to links off of that vertex / node. We're going
1768 // to be interested in the records corresponding to point-to-point links.
1769 //
1770  NS_ASSERT_MSG (v->GetLSA (),
1771  "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
1772  "Expected valid LSA in SPFVertex* v");
1773  Ipv4Mask tempmask (l->GetLinkData ().Get ());
1774  Ipv4Address tempip = l->GetLinkId ();
1775  tempip = tempip.CombineMask (tempmask);
1776 //
1777 // Here's why we did all of that work. We're going to add a host route to the
1778 // host address found in the m_linkData field of the point-to-point link
1779 // record. In the case of a point-to-point link, this is the local IP address
1780 // of the node connected to the link. Each of these point-to-point links
1781 // will correspond to a local interface that has an IP address to which
1782 // the node at the root of the SPF tree can send packets. The vertex <v>
1783 // (corresponding to the node that has these links and interfaces) has
1784 // an m_nextHop address precalculated for us that is the address to which the
1785 // root node should send packets to be forwarded to these IP addresses.
1786 // Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
1787 // which the packets should be send for forwarding.
1788 //
1789 
1790  Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
1791  if (router == 0)
1792  {
1793  continue;
1794  }
1795  Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
1796  NS_ASSERT (gr);
1797  // walk through all next-hop-IPs and out-going-interfaces for reaching
1798  // the stub network gateway 'v' from the root node
1799  for (uint32_t i = 0; i < v->GetNRootExitDirections (); i++)
1800  {
1801  SPFVertex::NodeExit_t exit = v->GetRootExitDirection (i);
1802  Ipv4Address nextHop = exit.first;
1803  int32_t outIf = exit.second;
1804  if (outIf >= 0)
1805  {
1806  gr->AddNetworkRouteTo (tempip, tempmask, nextHop, outIf);
1807  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1808  " add network route to " << tempip <<
1809  " using next hop " << nextHop <<
1810  " via interface " << outIf);
1811  }
1812  else
1813  {
1814  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
1815  " NOT able to add network route to " << tempip <<
1816  " using next hop " << nextHop <<
1817  " since outgoing interface id is negative");
1818  }
1819  }
1820  return;
1821  } // if
1822  } // for
1823 }
1824 
1825 //
1826 // Return the interface number corresponding to a given IP address and mask
1827 // This is a wrapper around GetInterfaceForPrefix(), but we first
1828 // have to find the right node pointer to pass to that function.
1829 // If no such interface is found, return -1 (note: unit test framework
1830 // for routing assumes -1 to be a legal return value)
1831 //
1832 int32_t
1833 GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask)
1834 {
1835  NS_LOG_FUNCTION (this << a << amask);
1836 //
1837 // We have an IP address <a> and a vertex ID of the root of the SPF tree.
1838 // The question is what interface index does this address correspond to.
1839 // The answer is a little complicated since we have to find a pointer to
1840 // the node corresponding to the vertex ID, find the Ipv4 interface on that
1841 // node in order to iterate the interfaces and find the one corresponding to
1842 // the address in question.
1843 //
1844  Ipv4Address routerId = m_spfroot->GetVertexId ();
1845 //
1846 // Walk the list of nodes in the system looking for the one corresponding to
1847 // the node at the root of the SPF tree. This is the node for which we are
1848 // building the routing table.
1849 //
1850  NodeList::Iterator i = NodeList::Begin ();
1851  NodeList::Iterator listEnd = NodeList::End ();
1852  for (; i != listEnd; i++)
1853  {
1854  Ptr<Node> node = *i;
1855 
1856  Ptr<GlobalRouter> rtr =
1857  node->GetObject<GlobalRouter> ();
1858 //
1859 // If the node doesn't have a GlobalRouter interface it can't be the one
1860 // we're interested in.
1861 //
1862  if (rtr == 0)
1863  {
1864  continue;
1865  }
1866 
1867  if (rtr->GetRouterId () == routerId)
1868  {
1869 //
1870 // This is the node we're building the routing table for. We're going to need
1871 // the Ipv4 interface to look for the ipv4 interface index. Since this node
1872 // is participating in routing IP version 4 packets, it certainly must have
1873 // an Ipv4 interface.
1874 //
1875  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
1876  NS_ASSERT_MSG (ipv4,
1877  "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): "
1878  "GetObject for <Ipv4> interface failed");
1879 //
1880 // Look through the interfaces on this node for one that has the IP address
1881 // we're looking for. If we find one, return the corresponding interface
1882 // index, or -1 if not found.
1883 //
1884  int32_t interface = ipv4->GetInterfaceForPrefix (a, amask);
1885 
1886 #if 0
1887  if (interface < 0)
1888  {
1889  NS_FATAL_ERROR ("GlobalRouteManagerImpl::FindOutgoingInterfaceId(): "
1890  "Expected an interface associated with address a:" << a);
1891  }
1892 #endif
1893  return interface;
1894  }
1895  }
1896 //
1897 // Couldn't find it.
1898 //
1899  NS_LOG_LOGIC ("FindOutgoingInterfaceId():Can't find root node " << routerId);
1900  return -1;
1901 }
1902 
1903 //
1904 // This method is derived from quagga ospf_intra_add_router ()
1905 //
1906 // This is where we are actually going to add the host routes to the routing
1907 // tables of the individual nodes.
1908 //
1909 // The vertex passed as a parameter has just been added to the SPF tree.
1910 // This vertex must have a valid m_root_oid, corresponding to the outgoing
1911 // interface on the root router of the tree that is the first hop on the path
1912 // to the vertex. The vertex must also have a next hop address, corresponding
1913 // to the next hop on the path to the vertex. The vertex has an m_lsa field
1914 // that has some number of link records. For each point to point link record,
1915 // the m_linkData is the local IP address of the link. This corresponds to
1916 // a destination IP address, reachable from the root, to which we add a host
1917 // route.
1918 //
1919 void
1920 GlobalRouteManagerImpl::SPFIntraAddRouter (SPFVertex* v)
1921 {
1922  NS_LOG_FUNCTION (this << v);
1923 
1924  NS_ASSERT_MSG (m_spfroot,
1925  "GlobalRouteManagerImpl::SPFIntraAddRouter (): Root pointer not set");
1926 //
1927 // The root of the Shortest Path First tree is the router to which we are
1928 // going to write the actual routing table entries. The vertex corresponding
1929 // to this router has a vertex ID which is the router ID of that node. We're
1930 // going to use this ID to discover which node it is that we're actually going
1931 // to update.
1932 //
1933  Ipv4Address routerId = m_spfroot->GetVertexId ();
1934 
1935  NS_LOG_LOGIC ("Vertex ID = " << routerId);
1936 //
1937 // We need to walk the list of nodes looking for the one that has the router
1938 // ID corresponding to the root vertex. This is the one we're going to write
1939 // the routing information to.
1940 //
1941  NodeList::Iterator i = NodeList::Begin ();
1942  NodeList::Iterator listEnd = NodeList::End ();
1943  for (; i != listEnd; i++)
1944  {
1945  Ptr<Node> node = *i;
1946 //
1947 // The router ID is accessible through the GlobalRouter interface, so we need
1948 // to GetObject for that interface. If there's no GlobalRouter interface,
1949 // the node in question cannot be the router we want, so we continue.
1950 //
1951  Ptr<GlobalRouter> rtr =
1952  node->GetObject<GlobalRouter> ();
1953 
1954  if (rtr == 0)
1955  {
1956  NS_LOG_LOGIC ("No GlobalRouter interface on node " <<
1957  node->GetId ());
1958  continue;
1959  }
1960 //
1961 // If the router ID of the current node is equal to the router ID of the
1962 // root of the SPF tree, then this node is the one for which we need to
1963 // write the routing tables.
1964 //
1965  NS_LOG_LOGIC ("Considering router " << rtr->GetRouterId ());
1966 
1967  if (rtr->GetRouterId () == routerId)
1968  {
1969  NS_LOG_LOGIC ("Setting routes for node " << node->GetId ());
1970 //
1971 // Routing information is updated using the Ipv4 interface. We need to
1972 // GetObject for that interface. If the node is acting as an IP version 4
1973 // router, it should absolutely have an Ipv4 interface.
1974 //
1975  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
1976  NS_ASSERT_MSG (ipv4,
1977  "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
1978  "GetObject for <Ipv4> interface failed");
1979 //
1980 // Get the Global Router Link State Advertisement from the vertex we're
1981 // adding the routes to. The LSA will have a number of attached Global Router
1982 // Link Records corresponding to links off of that vertex / node. We're going
1983 // to be interested in the records corresponding to point-to-point links.
1984 //
1985  GlobalRoutingLSA *lsa = v->GetLSA ();
1986  NS_ASSERT_MSG (lsa,
1987  "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
1988  "Expected valid LSA in SPFVertex* v");
1989 
1990  uint32_t nLinkRecords = lsa->GetNLinkRecords ();
1991 //
1992 // Iterate through the link records on the vertex to which we're going to add
1993 // routes. To make sure we're being clear, we're going to add routing table
1994 // entries to the tables on the node corresping to the root of the SPF tree.
1995 // These entries will have routes to the IP addresses we find from looking at
1996 // the local side of the point-to-point links found on the node described by
1997 // the vertex <v>.
1998 //
1999  NS_LOG_LOGIC (" Node " << node->GetId () <<
2000  " found " << nLinkRecords << " link records in LSA " << lsa << "with LinkStateId "<< lsa->GetLinkStateId ());
2001  for (uint32_t j = 0; j < nLinkRecords; ++j)
2002  {
2003 //
2004 // We are only concerned about point-to-point links
2005 //
2006  GlobalRoutingLinkRecord *lr = lsa->GetLinkRecord (j);
2007  if (lr->GetLinkType () != GlobalRoutingLinkRecord::PointToPoint)
2008  {
2009  continue;
2010  }
2011 //
2012 // Here's why we did all of that work. We're going to add a host route to the
2013 // host address found in the m_linkData field of the point-to-point link
2014 // record. In the case of a point-to-point link, this is the local IP address
2015 // of the node connected to the link. Each of these point-to-point links
2016 // will correspond to a local interface that has an IP address to which
2017 // the node at the root of the SPF tree can send packets. The vertex <v>
2018 // (corresponding to the node that has these links and interfaces) has
2019 // an m_nextHop address precalculated for us that is the address to which the
2020 // root node should send packets to be forwarded to these IP addresses.
2021 // Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
2022 // which the packets should be send for forwarding.
2023 //
2024  Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
2025  if (router == 0)
2026  {
2027  continue;
2028  }
2029  Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
2030  NS_ASSERT (gr);
2031  // walk through all available exit directions due to ECMP,
2032  // and add host route for each of the exit direction toward
2033  // the vertex 'v'
2034  for (uint32_t i = 0; i < v->GetNRootExitDirections (); i++)
2035  {
2036  SPFVertex::NodeExit_t exit = v->GetRootExitDirection (i);
2037  Ipv4Address nextHop = exit.first;
2038  int32_t outIf = exit.second;
2039  if (outIf >= 0)
2040  {
2041  gr->AddHostRouteTo (lr->GetLinkData (), nextHop,
2042  outIf);
2043  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
2044  " adding host route to " << lr->GetLinkData () <<
2045  " using next hop " << nextHop <<
2046  " and outgoing interface " << outIf);
2047  }
2048  else
2049  {
2050  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
2051  " NOT able to add host route to " << lr->GetLinkData () <<
2052  " using next hop " << nextHop <<
2053  " since outgoing interface id is negative " << outIf);
2054  }
2055  } // for all routes from the root the vertex 'v'
2056  }
2057 //
2058 // Done adding the routes for the selected node.
2059 //
2060  return;
2061  }
2062  }
2063 }
2064 void
2065 GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v)
2066 {
2067  NS_LOG_FUNCTION (this << v);
2068 
2069  NS_ASSERT_MSG (m_spfroot,
2070  "GlobalRouteManagerImpl::SPFIntraAddTransit (): Root pointer not set");
2071 //
2072 // The root of the Shortest Path First tree is the router to which we are
2073 // going to write the actual routing table entries. The vertex corresponding
2074 // to this router has a vertex ID which is the router ID of that node. We're
2075 // going to use this ID to discover which node it is that we're actually going
2076 // to update.
2077 //
2078  Ipv4Address routerId = m_spfroot->GetVertexId ();
2079 
2080  NS_LOG_LOGIC ("Vertex ID = " << routerId);
2081 //
2082 // We need to walk the list of nodes looking for the one that has the router
2083 // ID corresponding to the root vertex. This is the one we're going to write
2084 // the routing information to.
2085 //
2086  NodeList::Iterator i = NodeList::Begin ();
2087  NodeList::Iterator listEnd = NodeList::End ();
2088  for (; i != listEnd; i++)
2089  {
2090  Ptr<Node> node = *i;
2091 //
2092 // The router ID is accessible through the GlobalRouter interface, so we need
2093 // to GetObject for that interface. If there's no GlobalRouter interface,
2094 // the node in question cannot be the router we want, so we continue.
2095 //
2096  Ptr<GlobalRouter> rtr =
2097  node->GetObject<GlobalRouter> ();
2098 
2099  if (rtr == 0)
2100  {
2101  NS_LOG_LOGIC ("No GlobalRouter interface on node " <<
2102  node->GetId ());
2103  continue;
2104  }
2105 //
2106 // If the router ID of the current node is equal to the router ID of the
2107 // root of the SPF tree, then this node is the one for which we need to
2108 // write the routing tables.
2109 //
2110  NS_LOG_LOGIC ("Considering router " << rtr->GetRouterId ());
2111 
2112  if (rtr->GetRouterId () == routerId)
2113  {
2114  NS_LOG_LOGIC ("setting routes for node " << node->GetId ());
2115 //
2116 // Routing information is updated using the Ipv4 interface. We need to
2117 // GetObject for that interface. If the node is acting as an IP version 4
2118 // router, it should absolutely have an Ipv4 interface.
2119 //
2120  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
2121  NS_ASSERT_MSG (ipv4,
2122  "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
2123  "GetObject for <Ipv4> interface failed");
2124 //
2125 // Get the Global Router Link State Advertisement from the vertex we're
2126 // adding the routes to. The LSA will have a number of attached Global Router
2127 // Link Records corresponding to links off of that vertex / node. We're going
2128 // to be interested in the records corresponding to point-to-point links.
2129 //
2130  GlobalRoutingLSA *lsa = v->GetLSA ();
2131  NS_ASSERT_MSG (lsa,
2132  "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
2133  "Expected valid LSA in SPFVertex* v");
2134  Ipv4Mask tempmask = lsa->GetNetworkLSANetworkMask ();
2135  Ipv4Address tempip = lsa->GetLinkStateId ();
2136  tempip = tempip.CombineMask (tempmask);
2137  Ptr<GlobalRouter> router = node->GetObject<GlobalRouter> ();
2138  if (router == 0)
2139  {
2140  continue;
2141  }
2142  Ptr<Ipv4GlobalRouting> gr = router->GetRoutingProtocol ();
2143  NS_ASSERT (gr);
2144  // walk through all available exit directions due to ECMP,
2145  // and add host route for each of the exit direction toward
2146  // the vertex 'v'
2147  for (uint32_t i = 0; i < v->GetNRootExitDirections (); i++)
2148  {
2149  SPFVertex::NodeExit_t exit = v->GetRootExitDirection (i);
2150  Ipv4Address nextHop = exit.first;
2151  int32_t outIf = exit.second;
2152 
2153  if (outIf >= 0)
2154  {
2155  gr->AddNetworkRouteTo (tempip, tempmask, nextHop, outIf);
2156  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
2157  " add network route to " << tempip <<
2158  " using next hop " << nextHop <<
2159  " via interface " << outIf);
2160  }
2161  else
2162  {
2163  NS_LOG_LOGIC ("(Route " << i << ") Node " << node->GetId () <<
2164  " NOT able to add network route to " << tempip <<
2165  " using next hop " << nextHop <<
2166  " since outgoing interface id is negative " << outIf);
2167  }
2168  }
2169  }
2170  }
2171 }
2172 
2173 // Derived from quagga ospf_vertex_add_parents ()
2174 //
2175 // This is a somewhat oddly named method (blame quagga). Although you might
2176 // expect it to add a parent *to* something, it actually adds a vertex
2177 // to the list of children *in* each of its parents.
2178 //
2179 // Given a pointer to a vertex, it links back to the vertex's parent that it
2180 // already has set and adds itself to that vertex's list of children.
2181 //
2182 void
2183 GlobalRouteManagerImpl::SPFVertexAddParent (SPFVertex* v)
2184 {
2185  NS_LOG_FUNCTION (this << v);
2186 
2187  for (uint32_t i=0;;)
2188  {
2189  SPFVertex* parent;
2190  // check if all parents of vertex v
2191  if ((parent = v->GetParent (i++)) == 0) break;
2192  parent->AddChild (v);
2193  }
2194 }
2195 
2196 } // namespace ns3
2197 
2198 
LSType GetLSType(void) const
Return the LSType field of the LSA.
GlobalRoutingLinkRecord * GetLinkRecord(uint32_t n) const
Return a pointer to the specified Global Routing Link Record.
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
GlobalRoutingLSA * GetLSAByLinkData(Ipv4Address addr) const
Look up the Link State Advertisement associated with the given link state ID (address). This is a variation of the GetLSA call to allow the LSA to be found by matching addr with the LinkData field of the TransitNetwork link record.
static uint32_t GetNNodes(void)
Definition: node-list.cc:198
virtual void DeleteGlobalRoutes()
Delete all static routes on all nodes that have a GlobalRouterInterface.
void SetParent(SPFVertex *parent)
Set the pointer to the SPFVector that is the parent of "this" SPFVertex.
~SPFVertex()
Destroy an SPFVertex (Shortest Path First Vertex).
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
#define NS_LOG_INFO(msg)
Definition: log.h:264
void InheritAllRootExitDirections(const SPFVertex *vertex)
Inherit all root exit directions from a given vertex to 'this' vertex.
void MergeParent(const SPFVertex *v)
Merge the Parent list from the v into this vertex.
Vertex used in shortest path first (SPF) computations. See RFC 2328, Section 16.
SPFVertex()
Construct an empty ("uninitialized") SPFVertex (Shortest Path First Vertex).
void SetDistanceFromRoot(uint32_t distance)
Set the distance from the root vertex to "this" SPFVertex object.
uint32_t GetSystemId(void) const
Definition: node.cc:112
#define NS_FATAL_ERROR(msg)
fatal error handling
Definition: fatal-error.h:72
ListOfNodeExit_t m_ecmpRootExits
store the multiple root's exits for supporting ECMP
A Candidate Queue used in static routing.
a Link State Advertisement (LSA) for a router, used in global routing.
uint32_t GetNChildren(void) const
Get the number of children of "this" SPFVertex.
void Initialize()
Set all LSA flags to an initialized state, for SPF computation.
~GlobalRouteManagerLSDB()
Destroy an empty Global Router Manager Link State Database.
static Iterator End(void)
Definition: node-list.cc:186
void DebugSPFCalculate(Ipv4Address root)
Debugging routine; call the core SPF from the unit tests.
uint32_t GetDistanceFromRoot(void) const
Get the distance from the root vertex to "this" SPFVertex object.
SPFStatus GetStatus(void) const
Get the SPF status of the advertisement.
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual void InitializeRoutes()
Compute routes using a Dijkstra SPF computation and populate per-node forwarding tables.
GlobalRoutingLSA * GetLSA(void) const
Get the Global Router Link State Advertisement returned by the Global Router represented by this SPFV...
std::ostream & operator<<(std::ostream &os, const Angles &a)
Definition: angles.cc:43
void Push(SPFVertex *vNew)
Push a Shortest Path First Vertex pointer onto the queue according to the priority scheme...
void SetVertexType(VertexType type)
Set the Vertex Type field of a SPFVertex object.
void SetStatus(SPFStatus status)
Set the SPF status of the advertisement.
void DebugUseLsdb(GlobalRouteManagerLSDB *)
Debugging routine; allow client code to supply a pre-built LSDB.
void SetLSA(GlobalRoutingLSA *lsa)
Set the Global Router Link State Advertisement returned by the Global Router represented by this SPFV...
void SetRootExitDirection(Ipv4Address nextHop, int32_t id=SPF_INFINITY)
Set the IP address and outgoing interface index that should be used to begin forwarding packets from ...
void SetVertexId(Ipv4Address id)
Set the Vertex ID field of a SPFVertex object.
uint32_t GetNAttachedRouters(void) const
Return the number of attached routers listed in the NetworkLSA.
uint32_t GetNLinkRecords(void) const
Return the number of Global Routing Link Records in the LSA.
GlobalRoutingLSA * GetLSA(Ipv4Address addr) const
Look up the Link State Advertisement associated with the given link state ID (address).
void Insert(Ipv4Address addr, GlobalRoutingLSA *lsa)
Insert an IP address / Link State Advertisement pair into the Link State Database.
static Ipv4Address GetZero(void)
An interface aggregated to a node to provide global routing info.
void MergeRootExitDirections(const SPFVertex *vertex)
Merge into 'this' vertex the list of exit directions from another vertex.
#define NS_ASSERT_MSG(condition, message)
Definition: assert.h:86
uint32_t GetNRootExitDirections() const
Get the number of exit directions from root for reaching 'this' vertex.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
SPFVertex * Find(const Ipv4Address addr) const
Searches the Candidate Queue for a Shortest Path First Vertex pointer that points to a vertex having ...
uint32_t GetId(void) const
Definition: node.cc:105
static uint32_t GetSystemId()
#define NS_LOG_WARN(msg)
Definition: log.h:246
static Iterator Begin(void)
Definition: node-list.cc:180
SPFVertex * GetParent(uint32_t i=0) const
Get a pointer to the SPFVector that is the parent of "this" SPFVertex.
NodeExit_t GetRootExitDirection() const
Obtain a pair indicating the exit direction from the root.
VertexType GetVertexType(void) const
Get the Vertex Type field of a SPFVertex object.
The Link State DataBase (LSDB) of the Global Route Manager.
void SetVertexProcessed(bool value)
Set the value of the VertexProcessed flag.
VertexType
Enumeration of the possible types of SPFVertex objects.
Ipv4Address GetAttachedRouter(uint32_t n) const
Return an Ipv4Address corresponding to the specified attached router.
virtual void BuildGlobalRoutingDatabase()
Build the routing database by gathering Link State Advertisements from each node exporting a GlobalRo...
Ptr< Node > GetNode(void) const
Get the Node pointer of the node that originated this LSA.
void Reorder(void)
Reorders the Candidate Queue according to the priority scheme.
GlobalRouteManagerLSDB()
Construct an empty Global Router Manager Link State Database.
bool IsVertexProcessed(void) const
Check the value of the VertexProcessed flag.
Ptr< T > GetObject(void) const
Definition: object.h:332
Ipv4Address GetVertexId(void) const
Get the Vertex ID field of a SPFVertex object.
SPFVertex * GetChild(uint32_t n) const
Get a borrowed SPFVertex pointer to the specified child of "this" SPFVertex.
Ipv4Address GetLinkStateId(void) const
Get the Link State ID as defined by the OSPF spec. We always set it to the router ID of the router ma...
uint32_t AddChild(SPFVertex *child)
Get a borrowed SPFVertex pointer to the specified child of "this" SPFVertex.