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