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