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