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