A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
global-route-manager-impl.cc
Go to the documentation of this file.
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"
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");
111  }
112  else if (lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA)
113  {
114  NS_LOG_LOGIC ("Setting m_vertexType to 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
286 {
287  NS_LOG_FUNCTION (this << exit);
288  SetRootExitDirection (exit.first, exit.second);
289 }
290 
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 
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
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);
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
479 {
480  NS_LOG_FUNCTION (this);
481  return m_extdatabase.size ();
482 }
483 
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 
534  :
535  m_spfroot (0)
536 {
537  NS_LOG_FUNCTION (this);
539 }
540 
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;
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
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 //
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
972  SPFVertex* v,
973  SPFVertex* w,
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  {
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...
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  {
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 //
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 //
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;
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
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);
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
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
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 ());
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
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 //
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  {
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
1660 {
1661  NS_LOG_FUNCTION (this << v);
1662  NS_LOG_LOGIC ("Processing stubs for " << v->GetVertexId ());
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");
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
1694 {
1695  NS_LOG_FUNCTION (this << l << v);
1696 
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 //
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  {
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
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 //
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
1921 {
1922  NS_LOG_FUNCTION (this << v);
1923 
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 //
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);
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  {
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
2066 {
2067  NS_LOG_FUNCTION (this << v);
2068 
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 //
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  {
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
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