convert LSDB to class SPFVertex
authorTom Henderson <tomh@tomh.org>
Tue, 10 Jul 2007 10:56:27 -0700
changeset 1058 de579b1ff195
parent 1057 2620020dc72c
child 1059 2ebd3bb3da3e
convert LSDB to class SPFVertex
src/routing/static-route-manager.cc
src/routing/static-route-manager.h
--- a/src/routing/static-route-manager.cc	Tue Jul 10 09:31:07 2007 -0700
+++ b/src/routing/static-route-manager.cc	Tue Jul 10 10:56:27 2007 -0700
@@ -25,6 +25,13 @@
 NS_DEBUG_COMPONENT_DEFINE ("StaticRouteManager");
 
 namespace ns3 {
+
+SPFVertex::~SPFVertex ()
+{
+  delete m_lsa;
+}
+
+
 StaticRouteManagerLSDB::~StaticRouteManagerLSDB()
 {
   NS_DEBUG("StaticRouteManagerLSDB::~StaticRouteManagerLSDB ()");
@@ -32,8 +39,8 @@
   LSDBMap_t::iterator i;
   for (i= m_database.begin(); i!= m_database.end(); i++)
   {
-      NS_DEBUG("StaticRouteManagerLSDB::~StaticRouteManagerLSDB ():  free LSA");
-      StaticRouterLSA* temp = i->second;
+      NS_DEBUG("StaticRouteManagerLSDB::~StaticRouteManagerLSDB():free vertex");
+      SPFVertex* temp = i->second;
       delete temp;
     }
   NS_DEBUG("StaticRouteManagerLSDB::~StaticRouteManagerLSDB ():  clear map");
@@ -41,13 +48,13 @@
 }
 
 void
-StaticRouteManagerLSDB::Insert(Ipv4Address addr, StaticRouterLSA* lsa)
+StaticRouteManagerLSDB::Insert(Ipv4Address addr, SPFVertex* vertex)
 {
-    m_database.insert(LSDBPair_t(addr, lsa));
+    m_database.insert(LSDBPair_t(addr, vertex));
 }
 
-StaticRouterLSA*
-StaticRouteManagerLSDB::GetLSA (Ipv4Address addr)
+SPFVertex*
+StaticRouteManagerLSDB::GetVertex (Ipv4Address addr)
 {
   // Look up an LSA by its address
   LSDBMap_t::iterator i;
@@ -98,15 +105,148 @@
     }
 }
 
-void
-StaticRouteManager::InitializeRoutes ()
-{
   // For each node that is a static router (which can be determined by
   // the presence of StaticRouter interface), run Dijkstra SPF calculation
   // on the database rooted at that router, and populate the node
   // forwarding tables
+  //
+void
+StaticRouteManager::InitializeRoutes ()
+{
+//      This function parallels RFC2328, Section 16.1.1, and quagga ospfd
+//
+//      This calculation yields the set of intra-area routes associated
+//      with an area (called hereafter Area A).  A router calculates the
+//      shortest-path tree using itself as the root.  The formation
+//      of the shortest path tree is done here in two stages.  In the
+//      first stage, only links between routers and transit networks are
+//      considered.  Using the Dijkstra algorithm, a tree is formed from
+//      this subset of the link state database.  In the second stage,
+//      leaves are added to the tree by considering the links to stub
+//      networks.
+
+//      The area's link state database is represented as a directed graph.  
+//      The graph's vertices are routers, transit networks and stub networks.  
+//      The first stage of the procedure (i.e., the Dijkstra algorithm)
+//      can now be summarized as follows. At each iteration of the
+//      algorithm, there is a list of candidate vertices.  Paths from
+//      the root to these vertices have been found, but not necessarily
+//      the shortest ones.  However, the paths to the candidate vertex
+//      that is closest to the root are guaranteed to be shortest; this
+//      vertex is added to the shortest-path tree, removed from the
+//      candidate list, and its adjacent vertices are examined for
+//      possible addition to/modification of the candidate list.  The
+//      algorithm then iterates again.  It terminates when the candidate
+//      list becomes empty. 
+
+    // For each node that is a router in the topology
+  typedef std::vector < Ptr<Node> >::iterator Iterator;
+  for (Iterator i = NodeList::Begin(); i != NodeList::End(); i++)
+    {
+      Ptr<Node> node = *i;
+      NS_DEBUG_UNCOND ("node="<< node->GetId () );
+      
+      Ptr<StaticRouter> rtr = 
+        node->QueryInterface<StaticRouter> (StaticRouter::iid);
+      NS_ASSERT_MSG(rtr, "QI for <StaticRouter> interface failed");
+      if (rtr && rtr->GetNumLSAs () )
+        {
+          SPFCalculate();
+        }
+    }
 }
 
+
+// quagga ospf_spf_next
+void
+StaticRouteManager::SPFNext()
+{
+  // if LSA == Router_LSA, examine links
+  // a) if link to stub, skip
+  // b) W is transit
+}
+
+void
+StaticRouteManager::SPFCalculate()
+{
+  NS_DEBUG("StaticRouteManager::SPFCalculate ()");
+  /*
+ *  struct pqueue* candidate;
+ *  struct vertex* v;
+ */
+  // Initialize the shortest-path tree to only the router doing the 
+  // calculation.
+  //
+  
+#if 0
+  ospf_spf_init (area);
+  v = area->spf;
+
+
+  /* Create a new heap for the candidates. */
+  candidate = pqueue_create();
+  candidate->cmp = cmp;
+  candidate->update = update_stat;
+
+  /* Set LSA position to LSA_SPF_IN_SPFTREE. This vertex is the root of the
+ *    * spanning tree. */
+  *(v->stat) = LSA_SPF_IN_SPFTREE;
+
+  /* Set Area A's TransitCapability to FALSE. */
+  area->transit = OSPF_TRANSIT_FALSE;
+  area->shortcut_capability = 1;
+
+  for (;;)
+    {
+      /* RFC2328 16.1. (2). */
+      ospf_spf_next (v, area, candidate);
+  
+      /* RFC2328 16.1. (3). */
+      /* If at this step the candidate list is empty, the shortest-
+ *          path tree (of transit vertices) has been completely built and
+ *                   this stage of the procedure terminates. */
+      if (candidate->size == 0)
+        break;
+  
+      /* Otherwise, choose the vertex belonging to the candidate list
+ *          that is closest to the root, and add it to the shortest-path
+ *                   tree (removing it from the candidate list in the
+ *                            process). */
+      /* Extract from the candidates the node with the lower key. */
+      v = (struct vertex *) pqueue_dequeue (candidate);
+      /* Update stat field in vertex. */
+      *(v->stat) = LSA_SPF_IN_SPFTREE;
+
+      ospf_vertex_add_parent (v);
+      /* Note that when there is a choice of vertices closest to the
+ *          root, network vertices must be chosen before router vertices
+ *                   in order to necessarily find all equal-cost paths. */
+      /* We don't do this at this moment, we should add the treatment
+ *          above codes. -- kunihiro. */
+
+      /* RFC2328 16.1. (4). */
+      if (v->type == OSPF_VERTEX_ROUTER)
+        ospf_intra_add_router (new_rtrs, v, area);
+      else
+        ospf_intra_add_transit (new_table, v, area);
+
+      /* RFC2328 16.1. (5). */
+      /* Iterate the algorithm by returning to Step 2. */
+
+    } /* end loop until no more candidate vertices */
+
+  /* Second stage of SPF calculation procedure's  */
+  ospf_spf_process_stubs (area, area->spf, new_table);
+  
+  /* Free candidate queue. */
+  pqueue_delete (candidate);
+
+#endif
+
+
+}
+
+
 } // namespace ns3
 
 #ifdef RUN_SELF_TESTS
@@ -242,16 +382,26 @@
   lsa3->AddLinkRecord(lr2);
   lsa3->AddLinkRecord(lr3);
 
+  // Create four vertices to store these four LSAs
+  SPFVertex* v0 = new SPFVertex ();
+  v0->m_lsa = lsa0;
+  SPFVertex* v1 = new SPFVertex ();
+  v1->m_lsa = lsa1;
+  SPFVertex* v2 = new SPFVertex ();
+  v2->m_lsa = lsa2;
+  SPFVertex* v3 = new SPFVertex ();
+  v3->m_lsa = lsa3;
+  
   // Test the database 
   StaticRouteManagerLSDB* srmlsdb = new StaticRouteManagerLSDB();
-  srmlsdb->Insert(lsa0->m_linkStateId, lsa0);
-  srmlsdb->Insert(lsa1->m_linkStateId, lsa1);
-  srmlsdb->Insert(lsa2->m_linkStateId, lsa2);
-  srmlsdb->Insert(lsa3->m_linkStateId, lsa3);
-  NS_ASSERT(lsa2 == srmlsdb->GetLSA(lsa2->m_linkStateId));
+  srmlsdb->Insert(lsa0->m_linkStateId, v0);
+  srmlsdb->Insert(lsa1->m_linkStateId, v1);
+  srmlsdb->Insert(lsa2->m_linkStateId, v2);
+  srmlsdb->Insert(lsa3->m_linkStateId, v3);
+  NS_ASSERT(v2 == srmlsdb->GetVertex(lsa2->m_linkStateId));
 
-  // This delete clears the LSDB, which clears the LSAs, which destroy
-  // the LinkRecords.
+  // This delete clears the LSDB, which clears the vertices, which deletes
+  // the matching LSAs, which destroys the LinkRecords.
   delete srmlsdb;
 
   // XXX next, calculate routes based on the manually created LSDB
--- a/src/routing/static-route-manager.h	Tue Jul 10 09:31:07 2007 -0700
+++ b/src/routing/static-route-manager.h	Tue Jul 10 10:56:27 2007 -0700
@@ -34,6 +34,8 @@
 class SPFVertex
 {
 public:
+  ~SPFVertex();
+
   enum VertexType {
     VertexRouter = 1,
     VertexNetwork
@@ -41,12 +43,14 @@
 
   Ipv4Address m_vertexId;
 
-  uint32_t m_distanceFromRoot;
+  StaticRouterLSA* m_lsa;  // This pointer owns LSA for mem. mgmt purposes
 
   typedef std::list<SPFVertex> type_listOfSPFVertex;
   type_listOfSPFVertex m_parents;
   type_listOfSPFVertex m_children;
   type_listOfSPFVertex::iterator m_iter;
+
+  uint32_t m_distanceFromRoot;
 };
 
 /**
@@ -56,11 +60,11 @@
 {
 public:
   ~StaticRouteManagerLSDB ();
-  void Insert(Ipv4Address addr, StaticRouterLSA* lsa);
-  StaticRouterLSA* GetLSA (Ipv4Address addr);
+  void Insert(Ipv4Address addr, SPFVertex* vertex);
+  SPFVertex* GetVertex (Ipv4Address addr);
 
-  typedef std::map<Ipv4Address, StaticRouterLSA*> LSDBMap_t;
-  typedef std::pair<Ipv4Address, StaticRouterLSA*> LSDBPair_t;
+  typedef std::map<Ipv4Address, SPFVertex*> LSDBMap_t;
+  typedef std::pair<Ipv4Address, SPFVertex*> LSDBPair_t;
   LSDBMap_t m_database;
 };
 
@@ -96,6 +100,8 @@
 
 private:
   StaticRouteManagerLSDB m_lsdb;
+  void SPFCalculate ();
+  void SPFNext ();
 };
 
 } // namespace ns3