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