branch merge
authorCraig Dowell <craigdo@ee.washington.edu>
Sun, 12 Aug 2007 22:43:25 -0700
changeset 1431 3760d52ef5d1
parent 1430 25fa26a6533e (current diff)
parent 1279 03ab1b7ad2d0 (diff)
child 1432 3aef7d7a71c2
branch merge
examples/wscript
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/mixed-global-routing.cc	Sun Aug 12 22:43:25 2007 -0700
@@ -0,0 +1,199 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+// This script exercises global routing code in a mixed point-to-point
+// and csma/cd environment
+//
+// Network topology
+//
+//  n0
+//     \ p-p
+//      \          (shared csma/cd)
+//       n2 -------------------------n3
+//      /            |        | 
+//     / p-p        n4        n5 ---------- n6
+//   n1                             p-p
+//
+// - CBR/UDP flows from n0 to n6
+// - Tracing of queues and packet receptions to file "mixed-global-routing.tr"
+
+#include <iostream>
+#include <fstream>
+#include <string>
+#include <cassert>
+
+#include "ns3/debug.h"
+
+#include "ns3/command-line.h"
+#include "ns3/default-value.h"
+#include "ns3/ptr.h"
+#include "ns3/random-variable.h"
+
+#include "ns3/simulator.h"
+#include "ns3/nstime.h"
+#include "ns3/data-rate.h"
+
+#include "ns3/ascii-trace.h"
+#include "ns3/pcap-trace.h"
+#include "ns3/internet-node.h"
+#include "ns3/point-to-point-channel.h"
+#include "ns3/point-to-point-net-device.h"
+#include "ns3/csma-channel.h"
+#include "ns3/csma-net-device.h"
+#include "ns3/csma-topology.h"
+#include "ns3/csma-ipv4-topology.h"
+#include "ns3/eui48-address.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/ipv4.h"
+#include "ns3/socket.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/point-to-point-topology.h"
+#include "ns3/onoff-application.h"
+#include "ns3/global-route-manager.h"
+
+using namespace ns3;
+
+int main (int argc, char *argv[])
+{
+
+  // Users may find it convenient to turn on explicit debugging
+  // for selected modules; the below lines suggest how to do this
+#if 0 
+  DebugComponentEnable ("Object");
+  DebugComponentEnable ("Queue");
+  DebugComponentEnable ("DropTailQueue");
+  DebugComponentEnable ("Channel");
+  DebugComponentEnable ("PointToPointChannel");
+  DebugComponentEnable ("PointToPointNetDevice");
+  DebugComponentEnable ("GlobalRouter");
+  DebugComponentEnable ("GlobalRouteManager");
+#endif
+
+  // Set up some default values for the simulation.  Use the Bind ()
+  // technique to tell the system what subclass of Queue to use,
+  // and what the queue limit is
+
+  // The below DefaultValue::Bind command tells the queue factory which 
+  // class to instantiate, when the queue factory is invoked in the 
+  // topology code
+  DefaultValue::Bind ("Queue", "DropTailQueue");
+
+  DefaultValue::Bind ("OnOffApplicationPacketSize", "210");
+  DefaultValue::Bind ("OnOffApplicationDataRate", "448kb/s");
+
+  //DefaultValue::Bind ("DropTailQueue::m_maxPackets", 30);   
+
+  // Allow the user to override any of the defaults and the above
+  // Bind ()s at run-time, via command-line arguments
+  CommandLine::Parse (argc, argv);
+
+  Ptr<Node> n0 = Create<InternetNode> ();
+  Ptr<Node> n1 = Create<InternetNode> (); 
+  Ptr<Node> n2 = Create<InternetNode> (); 
+  Ptr<Node> n3 = Create<InternetNode> ();
+  Ptr<Node> n4 = Create<InternetNode> (); 
+  Ptr<Node> n5 = Create<InternetNode> (); 
+  Ptr<Node> n6 = Create<InternetNode> ();
+
+  // We create the channels first without any IP addressing information
+  Ptr<PointToPointChannel> channel0 = 
+    PointToPointTopology::AddPointToPointLink (
+      n0, n2, DataRate (5000000), MilliSeconds (2));
+
+  Ptr<PointToPointChannel> channel1 = 
+    PointToPointTopology::AddPointToPointLink (
+      n1, n2, DataRate (5000000), MilliSeconds (2));
+  
+  Ptr<PointToPointChannel> channel2 = 
+    PointToPointTopology::AddPointToPointLink (
+      n5, n6, DataRate (1500000), MilliSeconds (10));
+
+  // We create the channels first without any IP addressing information
+  Ptr<CsmaChannel> channelc0 = 
+    CsmaTopology::CreateCsmaChannel(
+      DataRate(5000000), MilliSeconds(2));
+
+  uint32_t n2ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n2, channelc0,
+                                         Eui48Address("10:54:23:54:23:50"));
+  uint32_t n3ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n3, channelc0,
+                                         Eui48Address("10:54:23:54:23:51"));
+  uint32_t n4ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n4, channelc0,
+                                         Eui48Address("10:54:23:54:23:52"));
+  uint32_t n5ifIndex = CsmaIpv4Topology::AddIpv4CsmaNode (n5, channelc0,
+                                         Eui48Address("10:54:23:54:23:53"));
+
+  // Later, we add IP addresses.  
+  PointToPointTopology::AddIpv4Addresses (
+      channel0, n0, Ipv4Address ("10.1.1.1"),
+      n2, Ipv4Address ("10.1.1.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel1, n1, Ipv4Address ("10.1.2.1"),
+      n2, Ipv4Address ("10.1.2.2"));
+  
+  PointToPointTopology::AddIpv4Addresses (
+      channel2, n5, Ipv4Address ("10.1.3.1"),
+      n6, Ipv4Address ("10.1.3.2"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n2, n2ifIndex, Ipv4Address("10.250.1.1"), Ipv4Mask("255.255.255.0"));
+
+  CsmaIpv4Topology::AddIpv4Address (
+      n3, n3ifIndex, Ipv4Address("10.250.1.2"), Ipv4Mask("255.255.255.0"));
+  
+  CsmaIpv4Topology::AddIpv4Address (
+      n4, n4ifIndex, Ipv4Address("10.250.1.3"), Ipv4Mask("255.255.255.0"));
+  
+  CsmaIpv4Topology::AddIpv4Address (
+      n5, n5ifIndex, Ipv4Address("10.250.1.4"), Ipv4Mask("255.255.255.0"));
+
+  // Create router nodes, initialize routing database and set up the routing
+  // tables in the nodes.
+  GlobalRouteManager::PopulateRoutingTables ();
+
+  // Create the OnOff application to send UDP datagrams of size
+  // 210 bytes at a rate of 448 Kb/s
+  Ptr<OnOffApplication> ooff = Create<OnOffApplication> (
+    n0, 
+    InetSocketAddress ("10.1.3.2", 80), 
+    "Udp",
+    ConstantVariable (1), 
+    ConstantVariable (0),
+    DataRate("300bps"),
+    50);
+  // Start the application
+  ooff->Start (Seconds (1.0));
+  ooff->Stop (Seconds (10.0));
+
+  // Configure tracing of all enqueue, dequeue, and NetDevice receive events
+  // Trace output will be sent to the simple-global-routing.tr file
+  AsciiTrace asciitrace ("mixed-global-routing.tr");
+  asciitrace.TraceAllQueues ();
+  asciitrace.TraceAllNetDeviceRx ();
+
+  // Also configure some tcpdump traces; each interface will be traced
+  // The output files will be named simple-p2p.pcap-<nodeId>-<interfaceId>
+  // and can be read by the "tcpdump -r" command (use "-tt" option to
+  // display timestamps correctly)
+  PcapTrace pcaptrace ("mixed-global-routing.pcap");
+  pcaptrace.TraceAllIp ();
+
+  Simulator::Run ();
+    
+  Simulator::Destroy ();
+}
--- a/examples/wscript	Sun Aug 12 22:41:24 2007 -0700
+++ b/examples/wscript	Sun Aug 12 22:43:25 2007 -0700
@@ -22,3 +22,6 @@
         ['csma', 'internet-node'])
     obj.source = 'csma-multicast.cc'
 
+    obj = bld.create_ns3_program( 'mixed-global-routing',
+        ['point-to-point', 'internet-node', 'global-routing' , 'csma-cd'])
+    obj.source = 'mixed-global-routing.cc'
--- a/src/devices/csma/csma-net-device.cc	Sun Aug 12 22:41:24 2007 -0700
+++ b/src/devices/csma/csma-net-device.cc	Sun Aug 12 22:43:25 2007 -0700
@@ -133,7 +133,6 @@
 
   EnableBroadcast (Eui48Address ("ff:ff:ff:ff:ff:ff"));
   EnableMulticast();
-  EnablePointToPoint();
 
   SetSendEnable (sendEnable);
   SetReceiveEnable (receiveEnable);
--- a/src/routing/global-routing/global-route-manager-impl.cc	Sun Aug 12 22:41:24 2007 -0700
+++ b/src/routing/global-routing/global-route-manager-impl.cc	Sun Aug 12 22:43:25 2007 -0700
@@ -48,8 +48,7 @@
 {
 }
 
-SPFVertex::SPFVertex (GlobalRouterLSA* lsa) : 
-  m_vertexType (VertexRouter), 
+SPFVertex::SPFVertex (GlobalRoutingLSA* lsa) : 
   m_vertexId (lsa->GetLinkStateId ()),
   m_lsa (lsa),
   m_distanceFromRoot (SPF_INFINITY), 
@@ -58,6 +57,16 @@
   m_parent (0),
   m_children ()
 {
+  if (lsa->GetLSType () == GlobalRoutingLSA::RouterLSA) 
+    {
+      NS_DEBUG ("SPFVertex:: setting m_vertexType to VertexRouter");
+      m_vertexType = SPFVertex::VertexRouter;
+    }
+  else if (lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA) 
+    { 
+      NS_DEBUG ("SPFVertex:: setting m_vertexType to VertexNetwork");
+      m_vertexType = SPFVertex::VertexNetwork;
+    }
 }
 
 SPFVertex::~SPFVertex ()
@@ -99,12 +108,12 @@
 }
 
   void 
-SPFVertex::SetLSA (GlobalRouterLSA* lsa)
+SPFVertex::SetLSA (GlobalRoutingLSA* lsa)
 {
   m_lsa = lsa;
 }
 
-  GlobalRouterLSA* 
+  GlobalRoutingLSA* 
 SPFVertex::GetLSA (void) const
 {
   return m_lsa;
@@ -210,7 +219,7 @@
   for (i= m_database.begin (); i!= m_database.end (); i++)
     {
       NS_DEBUG ("GlobalRouteManagerLSDB::~GlobalRouteManagerLSDB ():free LSA");
-      GlobalRouterLSA* temp = i->second;
+      GlobalRoutingLSA* temp = i->second;
       delete temp;
     }
   NS_DEBUG ("GlobalRouteManagerLSDB::~GlobalRouteManagerLSDB ():  clear map");
@@ -225,19 +234,19 @@
   LSDBMap_t::iterator i;
   for (i= m_database.begin (); i!= m_database.end (); i++)
     {
-      GlobalRouterLSA* temp = i->second;
-      temp->SetStatus (GlobalRouterLSA::LSA_SPF_NOT_EXPLORED);
+      GlobalRoutingLSA* temp = i->second;
+      temp->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
     }
 }
 
   void
-GlobalRouteManagerLSDB::Insert (Ipv4Address addr, GlobalRouterLSA* lsa)
+GlobalRouteManagerLSDB::Insert (Ipv4Address addr, GlobalRoutingLSA* lsa)
 {
   NS_DEBUG ("GlobalRouteManagerLSDB::Insert ()");
   m_database.insert (LSDBPair_t (addr, lsa));
 }
 
-  GlobalRouterLSA*
+  GlobalRoutingLSA*
 GlobalRouteManagerLSDB::GetLSA (Ipv4Address addr) const
 {
   NS_DEBUG ("GlobalRouteManagerLSDB::GetLSA ()");
@@ -255,6 +264,31 @@
   return 0;
 }
 
+  GlobalRoutingLSA*
+GlobalRouteManagerLSDB::GetLSAByLinkData (Ipv4Address addr) const
+{
+  NS_DEBUG ("GlobalRouteManagerLSDB::GetLSAByLinkData ()");
+//
+// Look up an LSA by its address.
+//
+  LSDBMap_t::const_iterator i;
+  for (i= m_database.begin (); i!= m_database.end (); i++)
+    {
+      GlobalRoutingLSA* temp = i->second;
+// Iterate among temp's Link Records
+      for (uint32_t j = 0; j < temp->GetNLinkRecords (); j++)
+        {
+          GlobalRoutingLinkRecord *lr = temp->GetLinkRecord (j);
+          if ( lr->GetLinkType () == GlobalRoutingLinkRecord::TransitNetwork &&
+               lr->GetLinkData () == addr)
+            {
+              return temp;
+            }
+        }
+    }
+  return 0;
+}
+
 // ---------------------------------------------------------------------------
 //
 // GlobalRouteManagerImpl Implementation
@@ -359,13 +393,12 @@
 
       for (uint32_t j = 0; j < numLSAs; ++j)
         {
-          GlobalRouterLSA* lsa = new GlobalRouterLSA ();
+          GlobalRoutingLSA* lsa = new GlobalRoutingLSA ();
 //
 // This is the call to actually fetch a Link State Advertisement from the 
 // router.
 //
           rtr->GetLSA (j, *lsa);
-          NS_DEBUG ("LSA " << j);
           NS_DEBUG (*lsa);
 //
 // Write the newly discovered link state advertisement to the database.
@@ -453,52 +486,86 @@
 GlobalRouteManagerImpl::SPFNext (SPFVertex* v, CandidateQueue& candidate)
 {
   SPFVertex* w = 0;
-  GlobalRouterLSA* w_lsa = 0;
+  GlobalRoutingLSA* w_lsa = 0;
+  GlobalRoutingLinkRecord *l = 0;
   uint32_t distance = 0;
+  uint32_t numRecordsInVertex = 0;
 
   NS_DEBUG ("GlobalRouteManagerImpl::SPFNext ()");
-//
-// Always true for now, since all our LSAs are RouterLSAs.
-//
-  if (v->GetVertexType () == SPFVertex::VertexRouter) 
+
+// V points to a Router-LSA or Network-LSA
+// Loop over the links in router LSA or attached routers in Network LSA
+  if (v->GetVertexType () == SPFVertex::VertexRouter)
     {
-      if (true)
+      numRecordsInVertex = v->GetLSA ()->GetNLinkRecords (); 
+    }
+  if (v->GetVertexType () == SPFVertex::VertexNetwork)
+    {
+      numRecordsInVertex = v->GetLSA ()->GetNAttachedRouters (); 
+    }
+
+  for (uint32_t i = 0; i < numRecordsInVertex; i++)
+    {
+// Get w_lsa:  In case of V is Router-LSA
+      if (v->GetVertexType () == SPFVertex::VertexRouter) 
         {
           NS_DEBUG ("SPFNext: Examining " << v->GetVertexId () << "'s " <<
             v->GetLSA ()->GetNLinkRecords () << " link records");
 //
-// Walk the list of link records in the link state advertisement associated 
-// with the "current" router (represented by vertex <v>).
-//
-          for (uint32_t i = 0; i < v->GetLSA ()->GetNLinkRecords (); ++i)
-            {
-//
 // (a) If this is a link to a stub network, examine the next link in V's LSA.
 // Links to stub networks will be considered in the second stage of the
 // shortest path calculation.
 //
-              GlobalRouterLinkRecord *l = v->GetLSA ()->GetLinkRecord (i);
-              if (l->GetLinkType () == GlobalRouterLinkRecord::StubNetwork)
-                {
-                  NS_DEBUG ("SPFNext: Found a Stub record to " << 
-                    l->GetLinkId ());
-                  continue;
-                }
+          l = v->GetLSA ()->GetLinkRecord (i);
+          if (l->GetLinkType () == GlobalRoutingLinkRecord::StubNetwork)
+            {
+              NS_DEBUG ("SPFNext: Found a Stub record to " << 
+                l->GetLinkId ());
+              continue;
+            }
 //
 // (b) Otherwise, W is a transit vertex (router or transit network).  Look up
 // the vertex W's LSA (router-LSA or network-LSA) in Area A's link state
 // database. 
 //
-              if (l->GetLinkType () == GlobalRouterLinkRecord::PointToPoint)
-                {
+          if (l->GetLinkType () == GlobalRoutingLinkRecord::PointToPoint)
+            {
 //
 // Lookup the link state advertisement of the new link -- we call it <w> in
 // the link state database.
 //
-                  w_lsa = m_lsdb->GetLSA (l->GetLinkId ());
-                  NS_ASSERT (w_lsa);
-                  NS_DEBUG ("SPFNext:  Found a P2P record from " << 
-                    v->GetVertexId () << " to " << w_lsa->GetLinkStateId ());
+              w_lsa = m_lsdb->GetLSA (l->GetLinkId ());
+              NS_ASSERT (w_lsa);
+              NS_DEBUG ("SPFNext:  Found a P2P record from " << 
+                v->GetVertexId () << " to " << w_lsa->GetLinkStateId ());
+            }
+          else if (l->GetLinkType () == 
+            GlobalRoutingLinkRecord::TransitNetwork)
+            {
+              w_lsa = m_lsdb->GetLSA (l->GetLinkId ());
+              NS_ASSERT (w_lsa);
+              NS_DEBUG ("SPFNext:  Found a Transit record from " << 
+                v->GetVertexId () << " to " << w_lsa->GetLinkStateId ());
+            }
+          else 
+            {
+              NS_ASSERT_MSG (0, "illegal Link Type");
+            }
+        }
+// Get w_lsa:  In case of V is Network-LSA
+      if (v->GetVertexType () == SPFVertex::VertexNetwork) 
+        {
+          w_lsa = m_lsdb->GetLSAByLinkData 
+            (v->GetLSA ()->GetAttachedRouter (i)); 
+          if (!w_lsa)
+            {
+              continue;
+            }
+          NS_DEBUG ("SPFNext:  Found a Network LSA from " << 
+            v->GetVertexId () << " to " << w_lsa->GetLinkStateId ());
+        }
+
+// Note:  w_lsa at this point may be either RouterLSA or NetworkLSA
 //
 // (c) If vertex W is already on the shortest-path tree, examine the next
 // link in the LSA.
@@ -506,57 +573,56 @@
 // If the link is to a router that is already in the shortest path first tree
 // then we have it covered -- ignore it.
 //
-                  if (w_lsa->GetStatus () == 
-                      GlobalRouterLSA::LSA_SPF_IN_SPFTREE) 
-                    {
-                      NS_DEBUG ("SPFNext: Skipping->  LSA "<< 
-                        w_lsa->GetLinkStateId () << " already in SPF tree");
-                      continue;
-                    }
-//
-// The link is to a router we haven't dealt with yet.
+      if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_IN_SPFTREE) 
+        {
+          NS_DEBUG ("SPFNext: Skipping->  LSA "<< 
+            w_lsa->GetLinkStateId () << " already in SPF tree");
+          continue;
+        }
 //
 // (d) Calculate the link state cost D of the resulting path from the root to 
 // vertex W.  D is equal to the sum of the link state cost of the (already 
 // calculated) shortest path to vertex V and the advertised cost of the link
 // between vertices V and W.  
 //
-                  distance = v->GetDistanceFromRoot () + l->GetMetric ();
-
-                  NS_DEBUG ("SPFNext: Considering w_lsa " << 
-                    w_lsa->GetLinkStateId ());
+      if (v->GetLSA ()->GetLSType () == GlobalRoutingLSA::RouterLSA)
+        {
+          distance = v->GetDistanceFromRoot () + l->GetMetric ();
+        }
+      else
+        {
+          distance = v->GetDistanceFromRoot ();
+        }
 
-                  if (w_lsa->GetStatus () == 
-                      GlobalRouterLSA::LSA_SPF_NOT_EXPLORED)
-                    {
-//
-// If we haven't yet considered the link represented by <w> we have to create 
-// a new SPFVertex to represent it.
-//
-                        w = new SPFVertex (w_lsa);
-//
+      NS_DEBUG ("SPFNext: Considering w_lsa " << w_lsa->GetLinkStateId ());
+
+// Is there already vertex w in candidate list?
+      if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED)
+        {
+
+// prepare vertex w
+          w = new SPFVertex (w_lsa);
+// Calculate nexthop to w
 // We need to figure out how to actually get to the new router represented
 // by <w>.  This will (among other things) find the next hop address to send
 // packets destined for this network to, and also find the outbound interface
 // used to forward the packets.
 //
-                      if (SPFNexthopCalculation (v, w, l, distance))
-                        {
-                          w_lsa->SetStatus (
-                            GlobalRouterLSA::LSA_SPF_CANDIDATE);
+          if (SPFNexthopCalculation (v, w, l, distance))
+            {
+              w_lsa->SetStatus (GlobalRoutingLSA::LSA_SPF_CANDIDATE);
 //
 // Push this new vertex onto the priority queue (ordered by distance from the
 // root node).
 //
-                          candidate.Push (w);
-                          NS_DEBUG ("SPFNext:  Pushing " << 
-                            w->GetVertexId () << ", parent vertexId: " << 
-                                    v->GetVertexId ());
-                        }
-                    }
-                } else if (w_lsa->GetStatus () == 
-                           GlobalRouterLSA::LSA_SPF_CANDIDATE)
-                    {
+              candidate.Push (w);
+              NS_DEBUG ("SPFNext:  Pushing " << 
+                w->GetVertexId () << ", parent vertexId: " << 
+                v->GetVertexId ());
+            }
+        }
+      else if (w_lsa->GetStatus () == GlobalRoutingLSA::LSA_SPF_CANDIDATE)
+        {
 //
 // We have already considered the link represented by <w>.  What wse have to
 // do now is to decide if this new router represents a route with a shorter
@@ -564,23 +630,23 @@
 //
 // So, locate the vertex in the candidate queue and take a look at the 
 // distance.
-                      w = candidate.Find (w_lsa->GetLinkStateId ());
-                      if (w->GetDistanceFromRoot () < distance)
-                        {
+          w = candidate.Find (w_lsa->GetLinkStateId ());
+          if (w->GetDistanceFromRoot () < distance)
+            {
 //
 // This is not a shorter path, so don't do anything.
 //
-                          continue;
-                        }
-                      else if (w->GetDistanceFromRoot () == distance)
-                        {
+              continue;
+            }
+          else if (w->GetDistanceFromRoot () == distance)
+            {
 //
 // This path is one with an equal cost.  Do nothing for now -- we're not doing
 // equal-cost multipath cases yet.
 //
-                        }
-                      else
-                        {
+            }
+          else
+            {
 // 
 // this path represents a new, lower-cost path to <w> (the vertex we found in
 // the current link record of the link state advertisement of the current root
@@ -589,27 +655,26 @@
 // N.B. the nexthop_calculation is conditional, if it finds a valid nexthop
 // it will call spf_add_parents, which will flush the old parents
 //
-                          if (SPFNexthopCalculation (v, w, l, distance))
-                            {
+              if (SPFNexthopCalculation (v, w, l, distance))
+                {
 //
 // If we've changed the cost to get to the vertex represented by <w>, we 
 // must reorder the priority queue keyed to that cost.
 //
-                              candidate.Reorder ();
-                            }
-                        }    
-                    }  // point-to-point
-            } // for loop
-        } 
-    }
+                  candidate.Reorder ();
+                }
+            } // new lower cost path found   
+        } // end W is already on the candidate list
+    } // end loop over the links in V's LSA
 }
 
 //
 // This method is derived from quagga ospf_next_hop_calculation() 16.1.1.  
 //
-// Calculate the next hop IP address and the outgoing interface required to
-// get packets from the root through <v> (parent) to vertex <w> (destination),
-// over a given distance.
+// Calculate nexthop from root through V (parent) to vertex W (destination)
+// with given distance from root->W.
+//
+// As appropriate, set w's parent, distance, and nexthop information
 //
 // For now, this is greatly simplified from the quagga code
 //                  
@@ -617,10 +682,19 @@
 GlobalRouteManagerImpl::SPFNexthopCalculation (
   SPFVertex* v, 
   SPFVertex* w,
-  GlobalRouterLinkRecord* l,
+  GlobalRoutingLinkRecord* l,
   uint32_t distance)
 {
   NS_DEBUG ("GlobalRouteManagerImpl::SPFNexthopCalculation ()");
+
+// If w is a NetworkVertex, l should be null
+/*
+  if (w->GetVertexType () == SPFVertex::VertexNetwork && l)
+    {
+        NS_ASSERT_MSG(0, "Error:  SPFNexthopCalculation parameter problem");
+    }
+*/
+
 //
 // The vertex m_spfroot is a distinguished vertex representing the node at
 // the root of the calculations.  That is, it is the node for which we are
@@ -669,7 +743,8 @@
 // return the link record describing the link from <w> to <v>.  Think of it as
 // SPFGetLink.
 //
-          GlobalRouterLinkRecord *linkRemote = 0;
+          NS_ASSERT(l);
+          GlobalRoutingLinkRecord *linkRemote = 0;
           linkRemote = SPFGetNextLink (w, v, linkRemote);
 // 
 // At this point, <l> is the Global Router Link Record describing the point-
@@ -695,6 +770,56 @@
             v->GetVertexId () << " to " << w->GetVertexId () << 
             " goes through next hop " << w->GetNextHop () <<
             " via outgoing interface " << w->GetOutgoingInterfaceId ());
+        }  // end W is a router vertes
+      else 
+        {
+          NS_ASSERT (w->GetVertexType () == SPFVertex::VertexNetwork);
+// W is a directly connected network; no next hop is required
+          GlobalRoutingLSA* w_lsa = w->GetLSA ();
+          NS_ASSERT (w_lsa->GetLSType () == GlobalRoutingLSA::NetworkLSA);
+// Find outgoing interface ID for this network
+          w->SetOutgoingInterfaceId (
+            FindOutgoingInterfaceId (w_lsa->GetLinkStateId (), 
+            w_lsa->GetNetworkLSANetworkMask () ));
+          w->SetDistanceFromRoot (distance);
+          w->SetParent (v);
+          NS_DEBUG ("SPFNexthopCalculation: Next hop from " << 
+            v->GetVertexId () << " to network " << w->GetVertexId () << 
+            " via outgoing interface " << w->GetOutgoingInterfaceId ());
+          return 1;
+        }
+    } // end v is the root
+  else if (v->GetVertexType () == SPFVertex::VertexNetwork) 
+    {
+// See if any of v's parents are the root
+      if (v->GetParent () == m_spfroot)
+        {
+// 16.1.1 para 5. ...the parent vertex is a network that
+// directly connects the calculating router to the destination
+// router.  The list of next hops is then determined by
+// examining the destination's router-LSA...
+          NS_ASSERT (w->GetVertexType () == SPFVertex::VertexRouter);
+          GlobalRoutingLinkRecord *linkRemote = 0;
+          while ((linkRemote = SPFGetNextLink (w, v, linkRemote)))
+            {
+/* ...For each link in the router-LSA that points back to the
+ * parent network, the link's Link Data field provides the IP
+ * address of a next hop router.  The outgoing interface to
+ * use can then be derived from the next hop IP address (or 
+ * it can be inherited from the parent network).
+ */
+                w->SetNextHop(linkRemote->GetLinkData ());
+                w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
+                NS_DEBUG ("SPFNexthopCalculation: Next hop from " << 
+                  v->GetVertexId () << " to " << w->GetVertexId () << 
+                  " goes through next hop " << w->GetNextHop () <<
+                  " via outgoing interface " << w->GetOutgoingInterfaceId ());
+            }
+        }
+      else 
+        {
+          w->SetNextHop (v->GetNextHop ());
+          w->SetOutgoingInterfaceId (v->GetOutgoingInterfaceId ());
         }
     }
   else 
@@ -736,19 +861,17 @@
 // to <w>.  If prev_link is not NULL, we return a Global Router Link Record
 // representing a possible *second* link from <v> to <w>.
 //
-// BUGBUG FIXME:  This seems to be a bug.  Shouldn't this function look for
-// any link records after pre_link and not just after the first?
-//
-  GlobalRouterLinkRecord* 
+  GlobalRoutingLinkRecord* 
 GlobalRouteManagerImpl::SPFGetNextLink (
   SPFVertex* v,
   SPFVertex* w,
-  GlobalRouterLinkRecord* prev_link) 
+  GlobalRoutingLinkRecord* prev_link) 
 {
   NS_DEBUG ("GlobalRouteManagerImpl::SPFGetNextLink ()");
 
   bool skip = true;
-  GlobalRouterLinkRecord* l;
+  bool found_prev_link = false;
+  GlobalRoutingLinkRecord* l;
 //
 // If prev_link is 0, we are really looking for the first link, not the next 
 // link.
@@ -756,6 +879,7 @@
   if (prev_link == 0)
     {
       skip = false;
+      found_prev_link = true;
     }
 //  
 // Iterate through the Global Router Link Records advertised by the vertex
@@ -765,10 +889,6 @@
   for (uint32_t i = 0; i < v->GetLSA ()->GetNLinkRecords (); ++i)
     {
       l = v->GetLSA ()->GetLinkRecord (i);
-      if (l->GetLinkType () != GlobalRouterLinkRecord::PointToPoint)
-        {
-          continue;
-        }
 //
 // The link ID of a link record representing a point-to-point link is set to
 // the router ID of the neighboring router -- the router to which the link
@@ -777,8 +897,16 @@
 // We're just checking to see if the link <l> is actually the link from <v> to
 // <w>.
 //
-      if (l->GetLinkId () == w->GetVertexId ()) {
-        NS_DEBUG ("SPFGetNextLink: Found matching link l:  linkId = " <<
+      if (l->GetLinkId () == w->GetVertexId ()) 
+        {
+          if (!found_prev_link)
+            {
+              NS_DEBUG ("SPFGetNextLink: Skipping links before prev_link found");
+              found_prev_link = true;
+              continue;
+            }
+        
+          NS_DEBUG ("SPFGetNextLink: Found matching link l:  linkId = " <<
           l->GetLinkId () << " linkData = " << l->GetLinkData ());
 //
 // If skip is false, don't (not too surprisingly) skip the link found -- it's 
@@ -849,7 +977,7 @@
 //
   m_spfroot= v;
   v->SetDistanceFromRoot (0);
-  v->GetLSA ()->SetStatus (GlobalRouterLSA::LSA_SPF_IN_SPFTREE);
+  v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE);
 
   for (;;)
     {
@@ -894,7 +1022,7 @@
 // Update the status field of the vertex to indicate that it is in the SPF
 // tree.
 //
-      v->GetLSA ()->SetStatus (GlobalRouterLSA::LSA_SPF_IN_SPFTREE);
+      v->GetLSA ()->SetStatus (GlobalRoutingLSA::LSA_SPF_IN_SPFTREE);
 //
 // The current vertex has a parent pointer.  By calling this rather oddly 
 // named method (blame quagga) we add the current vertex to the list of 
@@ -932,7 +1060,18 @@
 // through its point-to-point links, adding a *host* route to the local IP
 // address (at the <v> side) for each of those links.
 //
-      SPFIntraAddRouter (v);
+      if (v->GetVertexType () == SPFVertex::VertexRouter)
+        {
+          SPFIntraAddRouter (v);
+        }
+      else if (v->GetVertexType () == SPFVertex::VertexNetwork)
+        {
+          SPFIntraAddTransit (v);
+        }
+      else
+        {
+          NS_ASSERT_MSG(0, "illegal SPFVertex type");
+        }
 //
 // RFC2328 16.1. (5). 
 //
@@ -1026,6 +1165,80 @@
 }
 
 //
+// XXX This should probably be a method on Ipv4
+//
+// Return the interface index corresponding to a given IP address
+//
+  uint32_t
+GlobalRouteManagerImpl::FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask)
+{
+//
+// We have an IP address <a> and a vertex ID of the root of the SPF tree.  
+// The question is what interface index does this address correspond to.
+// The answer is a little complicated since we have to find a pointer to
+// the node corresponding to the vertex ID, find the Ipv4 interface on that
+// node in order to iterate the interfaces and find the one corresponding to
+// the address in question.
+//
+  Ipv4Address routerId = m_spfroot->GetVertexId ();
+//
+// Walk the list of nodes in the system looking for the one corresponding to
+// the node at the root of the SPF tree.  This is the node for which we are
+// building the routing table.
+//
+  std::vector<Ptr<Node> >::iterator i = NodeList::Begin (); 
+  for (; i != NodeList::End (); i++)
+    {
+      Ptr<Node> node = *i;
+
+      Ptr<GlobalRouter> rtr = 
+        node->QueryInterface<GlobalRouter> (GlobalRouter::iid);
+//
+// If the node doesn't have a GlobalRouter interface it can't be the one
+// we're interested in.
+//
+      if (rtr == 0)
+        {
+          continue;
+        }
+
+      if (rtr->GetRouterId () == routerId)
+        {
+//
+// This is the node we're building the routing table for.  We're going to need
+// the Ipv4 interface to look for the ipv4 interface index.  Since this node
+// is participating in routing IP version 4 packets, it certainly must have 
+// an Ipv4 interface.
+//
+          Ptr<Ipv4> ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
+          NS_ASSERT_MSG (ipv4, 
+            "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): "
+            "QI for <Ipv4> interface failed");
+//
+// Look through the interfaces on this node for one that has the IP address
+// we're looking for.  If we find one, return the corresponding interface
+// index.
+//
+          for (uint32_t i = 0; i < ipv4->GetNInterfaces (); i++)
+            {
+              if (ipv4->GetAddress (i).CombineMask(amask) == 
+                  a.CombineMask(amask) )
+                {
+                  NS_DEBUG (
+                    "GlobalRouteManagerImpl::FindOutgoingInterfaceId (): "
+                    "Interface match for " << a);
+                  return i;
+                }
+            }
+        }
+    }
+//
+// Couldn't find it.
+//
+  return 0;
+}
+
+//
 // This method is derived from quagga ospf_intra_add_router ()
 //
 // This is where we are actually going to add the host routes to the routing
@@ -1109,7 +1322,7 @@
 // Link Records corresponding to links off of that vertex / node.  We're going
 // to be interested in the records corresponding to point-to-point links.
 //
-          GlobalRouterLSA *lsa = v->GetLSA ();
+          GlobalRoutingLSA *lsa = v->GetLSA ();
           NS_ASSERT_MSG (lsa, 
             "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
             "Expected valid LSA in SPFVertex* v");
@@ -1128,8 +1341,8 @@
 //
 // We are only concerned about point-to-point links
 //
-              GlobalRouterLinkRecord *lr = lsa->GetLinkRecord (j);
-              if (lr->GetLinkType () != GlobalRouterLinkRecord::PointToPoint)
+              GlobalRoutingLinkRecord *lr = lsa->GetLinkRecord (j);
+              if (lr->GetLinkType () != GlobalRoutingLinkRecord::PointToPoint)
                 {
                   continue;
                 }
@@ -1162,6 +1375,91 @@
         }
     }
 }
+  void
+GlobalRouteManagerImpl::SPFIntraAddTransit (SPFVertex* v)
+{
+  NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit ()");
+
+  NS_ASSERT_MSG (m_spfroot, 
+    "GlobalRouteManagerImpl::SPFIntraAddTransit (): Root pointer not set");
+//
+// The root of the Shortest Path First tree is the router to which we are 
+// going to write the actual routing table entries.  The vertex corresponding
+// to this router has a vertex ID which is the router ID of that node.  We're
+// going to use this ID to discover which node it is that we're actually going
+// to update.
+//
+  Ipv4Address routerId = m_spfroot->GetVertexId ();
+
+  NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+    "Vertex ID = " << routerId);
+//
+// We need to walk the list of nodes looking for the one that has the router
+// ID corresponding to the root vertex.  This is the one we're going to write
+// the routing information to.
+//
+  std::vector<Ptr<Node> >::iterator i = NodeList::Begin (); 
+  for (; i != NodeList::End (); i++)
+    {
+      Ptr<Node> node = *i;
+//
+// The router ID is accessible through the GlobalRouter interface, so we need
+// to QI for that interface.  If there's no GlobalRouter interface, the node
+// in question cannot be the router we want, so we continue.
+// 
+      Ptr<GlobalRouter> rtr = 
+        node->QueryInterface<GlobalRouter> (GlobalRouter::iid);
+
+      if (rtr == 0)
+        {
+          NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+            "No GlobalRouter interface on node " << node->GetId ());
+          continue;
+        }
+//
+// If the router ID of the current node is equal to the router ID of the 
+// root of the SPF tree, then this node is the one for which we need to 
+// write the routing tables.
+//
+      NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+        "Considering router " << rtr->GetRouterId ());
+
+      if (rtr->GetRouterId () == routerId)
+        {
+          NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+            "setting routes for node " << node->GetId ());
+//
+// Routing information is updated using the Ipv4 interface.  We need to QI
+// for that interface.  If the node is acting as an IP version 4 router, it
+// should absolutely have an Ipv4 interface.
+//
+          Ptr<Ipv4> ipv4 = node->QueryInterface<Ipv4> (Ipv4::iid);
+          NS_ASSERT_MSG (ipv4, 
+            "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+            "QI for <Ipv4> interface failed");
+//
+// Get the Global Router Link State Advertisement from the vertex we're
+// adding the routes to.  The LSA will have a number of attached Global Router
+// Link Records corresponding to links off of that vertex / node.  We're going
+// to be interested in the records corresponding to point-to-point links.
+//
+          GlobalRoutingLSA *lsa = v->GetLSA ();
+          NS_ASSERT_MSG (lsa, 
+            "GlobalRouteManagerImpl::SPFIntraAddTransit (): "
+            "Expected valid LSA in SPFVertex* v");
+          Ipv4Mask tempmask = lsa->GetNetworkLSANetworkMask ();
+          Ipv4Address tempip = lsa->GetLinkStateId ();
+          tempip = tempip.CombineMask (tempmask);
+          ipv4->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (),
+            v->GetOutgoingInterfaceId ());
+          NS_DEBUG ("GlobalRouteManagerImpl::SPFIntraAddNetwork (): "
+            " Node " << node->GetId () <<
+            " add network route to " << tempip <<
+            " using next hop " << v->GetNextHop () <<
+            " via interface " << v->GetOutgoingInterfaceId ());
+        }
+    } 
+}
 
 // Derived from quagga ospf_vertex_add_parents ()
 //
@@ -1275,81 +1573,81 @@
   //  link2:  10.1.3.1/30, 10.1.3.2/30
   //
   // Router 0
-  GlobalRouterLinkRecord* lr0 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::PointToPoint, 
+  GlobalRoutingLinkRecord* lr0 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::PointToPoint, 
     "0.0.0.2",  // router ID 0.0.0.2
     "10.1.1.1", // local ID
     1);         // metric
 
-  GlobalRouterLinkRecord* lr1 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::StubNetwork,
+  GlobalRoutingLinkRecord* lr1 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::StubNetwork,
     "10.1.1.1",
     "255.255.255.252",
     1);
 
-  GlobalRouterLSA* lsa0 = new GlobalRouterLSA ();
+  GlobalRoutingLSA* lsa0 = new GlobalRoutingLSA ();
   lsa0->SetLinkStateId ("0.0.0.0");
   lsa0->SetAdvertisingRouter ("0.0.0.0");
   lsa0->AddLinkRecord (lr0);
   lsa0->AddLinkRecord (lr1);
 
   // Router 1
-  GlobalRouterLinkRecord* lr2 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::PointToPoint,
+  GlobalRoutingLinkRecord* lr2 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::PointToPoint,
     "0.0.0.2",
     "10.1.2.1",
     1);
 
-  GlobalRouterLinkRecord* lr3 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::StubNetwork,
+  GlobalRoutingLinkRecord* lr3 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::StubNetwork,
     "10.1.2.1",
     "255.255.255.252",
     1);
 
-  GlobalRouterLSA* lsa1 = new GlobalRouterLSA ();
+  GlobalRoutingLSA* lsa1 = new GlobalRoutingLSA ();
   lsa1->SetLinkStateId ("0.0.0.1");
   lsa1->SetAdvertisingRouter ("0.0.0.1");
   lsa1->AddLinkRecord (lr2);
   lsa1->AddLinkRecord (lr3);
   
   // Router 2 
-  GlobalRouterLinkRecord* lr4 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::PointToPoint,
+  GlobalRoutingLinkRecord* lr4 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::PointToPoint,
     "0.0.0.0",
     "10.1.1.2",
     1);
 
-  GlobalRouterLinkRecord* lr5 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::StubNetwork,
+  GlobalRoutingLinkRecord* lr5 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::StubNetwork,
     "10.1.1.2",
     "255.255.255.252",
     1);
 
-  GlobalRouterLinkRecord* lr6 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::PointToPoint,
+  GlobalRoutingLinkRecord* lr6 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::PointToPoint,
     "0.0.0.1",
     "10.1.2.2",
     1);
 
-  GlobalRouterLinkRecord* lr7 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::StubNetwork,
+  GlobalRoutingLinkRecord* lr7 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::StubNetwork,
     "10.1.2.2",
     "255.255.255.252",
     1);
 
-  GlobalRouterLinkRecord* lr8 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::PointToPoint,
+  GlobalRoutingLinkRecord* lr8 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::PointToPoint,
     "0.0.0.3",
     "10.1.3.2",
     1);
 
-  GlobalRouterLinkRecord* lr9 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::StubNetwork,
+  GlobalRoutingLinkRecord* lr9 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::StubNetwork,
     "10.1.3.2",
     "255.255.255.252",
     1);
 
-  GlobalRouterLSA* lsa2 = new GlobalRouterLSA ();
+  GlobalRoutingLSA* lsa2 = new GlobalRoutingLSA ();
   lsa2->SetLinkStateId ("0.0.0.2");
   lsa2->SetAdvertisingRouter ("0.0.0.2");
   lsa2->AddLinkRecord (lr4);
@@ -1360,19 +1658,19 @@
   lsa2->AddLinkRecord (lr9);
 
   // Router 3
-  GlobalRouterLinkRecord* lr10 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::PointToPoint,
+  GlobalRoutingLinkRecord* lr10 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::PointToPoint,
     "0.0.0.2",
     "10.1.2.1",
     1);
 
-  GlobalRouterLinkRecord* lr11 = new GlobalRouterLinkRecord (
-    GlobalRouterLinkRecord::StubNetwork,
+  GlobalRoutingLinkRecord* lr11 = new GlobalRoutingLinkRecord (
+    GlobalRoutingLinkRecord::StubNetwork,
     "10.1.2.1",
     "255.255.255.252",
     1);
 
-  GlobalRouterLSA* lsa3 = new GlobalRouterLSA ();
+  GlobalRoutingLSA* lsa3 = new GlobalRoutingLSA ();
   lsa3->SetLinkStateId ("0.0.0.3");
   lsa3->SetAdvertisingRouter ("0.0.0.3");
   lsa3->AddLinkRecord (lr10);
--- a/src/routing/global-routing/global-route-manager-impl.h	Sun Aug 12 22:41:24 2007 -0700
+++ b/src/routing/global-routing/global-route-manager-impl.h	Sun Aug 12 22:43:25 2007 -0700
@@ -102,10 +102,10 @@
  *
  * @see SPFVertex::SPFVertex ()
  * @see VertexType
- * @see GlobalRouterLSA
+ * @see GlobalRoutingLSA
  * @param lsa The Link State Advertisement used for finding initial values.
  */
-  SPFVertex(GlobalRouterLSA* lsa);
+  SPFVertex(GlobalRoutingLSA* lsa);
 
 /**
  * @brief Destroy an SPFVertex (Shortest Path First Vertex).
@@ -181,12 +181,12 @@
  * @internal
  *
  * @see GlobalRouter
- * @see GlobalRouterLSA
+ * @see GlobalRoutingLSA
  * @see GlobalRouter::DiscoverLSAs ()
- * @returns A pointer to the GlobalRouterLSA found by the router represented
+ * @returns A pointer to the GlobalRoutingLSA found by the router represented
  * by this SPFVertex object.
  */
-  GlobalRouterLSA* GetLSA (void) const;
+  GlobalRoutingLSA* GetLSA (void) const;
 
 /**
  * @brief Set the Global Router Link State Advertisement returned by the 
@@ -196,13 +196,13 @@
  *
  * @see SPFVertex::GetLSA ()
  * @see GlobalRouter
- * @see GlobalRouterLSA
+ * @see GlobalRoutingLSA
  * @see GlobalRouter::DiscoverLSAs ()
  * @warning Ownership of the LSA is transferred to the "this" SPFVertex.  You
  * must not delete the LSA after calling this method.
- * @param lsa A pointer to the GlobalRouterLSA.
+ * @param lsa A pointer to the GlobalRoutingLSA.
  */
-  void SetLSA (GlobalRouterLSA* lsa);
+  void SetLSA (GlobalRoutingLSA* lsa);
 
 /**
  * @brief Get the distance from the root vertex to "this" SPFVertex object.
@@ -283,8 +283,8 @@
  * SPFVertex."
  *
  * @see GlobalRouter
- * @see GlobalRouterLSA
- * @see GlobalRouterLinkRecord
+ * @see GlobalRoutingLSA
+ * @see GlobalRoutingLinkRecord
  * @returns The interface index to use when forwarding packets to the host
  * or network represented by "this" SPFVertex.
  */
@@ -325,8 +325,8 @@
  * by "this" SPFVertex.
  *
  * @see GlobalRouter
- * @see GlobalRouterLSA
- * @see GlobalRouterLinkRecord
+ * @see GlobalRoutingLSA
+ * @see GlobalRoutingLinkRecord
  * @param id The interface index to use when forwarding packets to the host or
  * network represented by "this" SPFVertex.
  */
@@ -368,8 +368,8 @@
  * by 'this' SPFVertex."
  *
  * @see GlobalRouter
- * @see GlobalRouterLSA
- * @see GlobalRouterLinkRecord
+ * @see GlobalRoutingLSA
+ * @see GlobalRoutingLinkRecord
  * @returns The IP address to use when forwarding packets to the host
  * or network represented by "this" SPFVertex.
  */
@@ -411,8 +411,8 @@
  * host represented by 'this' SPFVertex."
  *
  * @see GlobalRouter
- * @see GlobalRouterLSA
- * @see GlobalRouterLinkRecord
+ * @see GlobalRoutingLSA
+ * @see GlobalRoutingLinkRecord
  * @param nextHop The IP address to use when forwarding packets to the host
  * or network represented by "this" SPFVertex.
  */
@@ -543,7 +543,7 @@
 private:
   VertexType m_vertexType;
   Ipv4Address m_vertexId;
-  GlobalRouterLSA* m_lsa;
+  GlobalRoutingLSA* m_lsa;
   uint32_t m_distanceFromRoot;
   uint32_t m_rootOif;
   Ipv4Address m_nextHop;
@@ -604,33 +604,47 @@
  * State Database.
  * @internal
  *
- * The IPV4 address and the GlobalRouterLSA given as parameters are converted
+ * The IPV4 address and the GlobalRoutingLSA given as parameters are converted
  * to an STL pair and are inserted into the database map.
  *
- * @see GlobalRouterLSA
+ * @see GlobalRoutingLSA
  * @see Ipv4Address
  * @param addr The IP address associated with the LSA.  Typically the Router 
  * ID.
  * @param lsa A pointer to the Link State Advertisement for the router.
  */
-  void Insert(Ipv4Address addr, GlobalRouterLSA* lsa);
+  void Insert(Ipv4Address addr, GlobalRoutingLSA* lsa);
 
 /**
  * @brief Look up the Link State Advertisement associated with the given
- * IP Address.
+ * link state ID (address).
  * @internal
  *
  * The database map is searched for the given IPV4 address and corresponding
- * GlobalRouterLSA is returned.
+ * GlobalRoutingLSA is returned.
  *
- * @see GlobalRouterLSA
+ * @see GlobalRoutingLSA
  * @see Ipv4Address
  * @param addr The IP address associated with the LSA.  Typically the Router 
  * ID.
  * @returns A pointer to the Link State Advertisement for the router specified
  * by the IP address addr.
  */
-  GlobalRouterLSA* GetLSA (Ipv4Address addr) const;
+  GlobalRoutingLSA* GetLSA (Ipv4Address addr) const;
+/**
+ * @brief Look up the Link State Advertisement associated with the given
+ * link state ID (address).  This is a variation of the GetLSA call
+ * to allow the LSA to be found by matching addr with the LinkData field
+ * of the TransitNetwork link record.
+ * @internal
+ *
+ * @see GetLSA
+ * @param addr The IP address associated with the LSA.  Typically the Router 
+ * @returns A pointer to the Link State Advertisement for the router specified
+ * by the IP address addr.
+ * ID.
+ */
+  GlobalRoutingLSA* GetLSAByLinkData (Ipv4Address addr) const;
 
 /**
  * @brief Set all LSA flags to an initialized state, for SPF computation
@@ -641,14 +655,14 @@
  * prior to each SPF calculation to reset the state of the SPFVertex structures
  * that will reference the LSAs during the calculation.
  *
- * @see GlobalRouterLSA
+ * @see GlobalRoutingLSA
  * @see SPFVertex
  */
   void Initialize ();
 
 private:
-  typedef std::map<Ipv4Address, GlobalRouterLSA*> LSDBMap_t;
-  typedef std::pair<Ipv4Address, GlobalRouterLSA*> LSDBPair_t;
+  typedef std::map<Ipv4Address, GlobalRoutingLSA*> LSDBMap_t;
+  typedef std::pair<Ipv4Address, GlobalRoutingLSA*> LSDBPair_t;
 
   LSDBMap_t m_database;
 /**
@@ -734,12 +748,14 @@
   void SPFCalculate (Ipv4Address root);
   void SPFNext (SPFVertex*, CandidateQueue&);
   int SPFNexthopCalculation (SPFVertex* v, SPFVertex* w, 
-    GlobalRouterLinkRecord* l, uint32_t distance);
+    GlobalRoutingLinkRecord* l, uint32_t distance);
   void SPFVertexAddParent (SPFVertex* v);
-  GlobalRouterLinkRecord* SPFGetNextLink (SPFVertex* v, SPFVertex* w, 
-    GlobalRouterLinkRecord* prev_link);
+  GlobalRoutingLinkRecord* SPFGetNextLink (SPFVertex* v, SPFVertex* w, 
+    GlobalRoutingLinkRecord* prev_link);
   void SPFIntraAddRouter (SPFVertex* v);
+  void SPFIntraAddTransit (SPFVertex* v);
   uint32_t FindOutgoingInterfaceId (Ipv4Address a);
+  uint32_t FindOutgoingInterfaceId (Ipv4Address a, Ipv4Mask amask);
 };
 
 } // namespace ns3
--- a/src/routing/global-routing/global-router-interface.cc	Sun Aug 12 22:41:24 2007 -0700
+++ b/src/routing/global-routing/global-router-interface.cc	Sun Aug 12 22:43:25 2007 -0700
@@ -28,21 +28,21 @@
 
 // ---------------------------------------------------------------------------
 //
-// GlobalRouterLinkRecord Implementation
+// GlobalRoutingLinkRecord Implementation
 //
 // ---------------------------------------------------------------------------
 
-GlobalRouterLinkRecord::GlobalRouterLinkRecord ()
+GlobalRoutingLinkRecord::GlobalRoutingLinkRecord ()
 :
   m_linkId ("0.0.0.0"),
   m_linkData ("0.0.0.0"),
   m_linkType (Unknown),
   m_metric (0)
 {
-  NS_DEBUG("GlobalRouterLinkRecord::GlobalRouterLinkRecord ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::GlobalRoutingLinkRecord ()");
 }
 
-GlobalRouterLinkRecord::GlobalRouterLinkRecord (
+GlobalRoutingLinkRecord::GlobalRoutingLinkRecord (
   LinkType    linkType, 
   Ipv4Address linkId, 
   Ipv4Address linkData, 
@@ -53,116 +53,126 @@
   m_linkType (linkType),
   m_metric (metric)
 {
-  NS_DEBUG("GlobalRouterLinkRecord::GlobalRouterLinkRecord (" <<
+  NS_DEBUG("GlobalRoutingLinkRecord::GlobalRoutingLinkRecord (" <<
     linkType << ", " << linkId << ", " << linkData << ", " << metric << ")");
 }
 
-GlobalRouterLinkRecord::~GlobalRouterLinkRecord ()
+GlobalRoutingLinkRecord::~GlobalRoutingLinkRecord ()
 {
-  NS_DEBUG("GlobalRouterLinkRecord::~GlobalRouterLinkRecord ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::~GlobalRoutingLinkRecord ()");
 }
 
   Ipv4Address
-GlobalRouterLinkRecord::GetLinkId (void) const
+GlobalRoutingLinkRecord::GetLinkId (void) const
 {
-  NS_DEBUG("GlobalRouterLinkRecord::GetLinkId ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::GetLinkId ()");
   return m_linkId;
 }
 
   void
-GlobalRouterLinkRecord::SetLinkId (Ipv4Address addr)
+GlobalRoutingLinkRecord::SetLinkId (Ipv4Address addr)
 {
-  NS_DEBUG("GlobalRouterLinkRecord::SetLinkId ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::SetLinkId ()");
   m_linkId = addr;
 }
 
   Ipv4Address
-GlobalRouterLinkRecord::GetLinkData (void) const
+GlobalRoutingLinkRecord::GetLinkData (void) const
 {
-  NS_DEBUG("GlobalRouterLinkRecord::GetLinkData ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::GetLinkData ()");
   return m_linkData;
 }
 
   void
-GlobalRouterLinkRecord::SetLinkData (Ipv4Address addr)
+GlobalRoutingLinkRecord::SetLinkData (Ipv4Address addr)
 {
-  NS_DEBUG("GlobalRouterLinkRecord::SetLinkData ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::SetLinkData ()");
   m_linkData = addr;
 }
 
-  GlobalRouterLinkRecord::LinkType
-GlobalRouterLinkRecord::GetLinkType (void) const
+  GlobalRoutingLinkRecord::LinkType
+GlobalRoutingLinkRecord::GetLinkType (void) const
 {
-  NS_DEBUG("GlobalRouterLinkRecord::GetLinkType ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::GetLinkType ()");
   return m_linkType;
 }
 
   void
-GlobalRouterLinkRecord::SetLinkType (
-  GlobalRouterLinkRecord::LinkType linkType)
+GlobalRoutingLinkRecord::SetLinkType (
+  GlobalRoutingLinkRecord::LinkType linkType)
 {
-  NS_DEBUG("GlobalRouterLinkRecord::SetLinkType ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::SetLinkType ()");
   m_linkType = linkType;
 }
 
   uint32_t
-GlobalRouterLinkRecord::GetMetric (void) const
+GlobalRoutingLinkRecord::GetMetric (void) const
 {
-  NS_DEBUG("GlobalRouterLinkRecord::GetMetric ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::GetMetric ()");
   return m_metric;
 }
 
   void
-GlobalRouterLinkRecord::SetMetric (uint32_t metric)
+GlobalRoutingLinkRecord::SetMetric (uint32_t metric)
 {
-  NS_DEBUG("GlobalRouterLinkRecord::SetMetric ()");
+  NS_DEBUG("GlobalRoutingLinkRecord::SetMetric ()");
   m_metric = metric;
 }
 
 // ---------------------------------------------------------------------------
 //
-// GlobalRouterLSA Implementation
+// GlobalRoutingLSA Implementation
 //
 // ---------------------------------------------------------------------------
 
-GlobalRouterLSA::GlobalRouterLSA()
+GlobalRoutingLSA::GlobalRoutingLSA()
   : 
+  m_lsType (GlobalRoutingLSA::Unknown),
   m_linkStateId("0.0.0.0"),
   m_advertisingRtr("0.0.0.0"),
   m_linkRecords(),
-  m_status(GlobalRouterLSA::LSA_SPF_NOT_EXPLORED)
+  m_networkLSANetworkMask("0.0.0.0"),
+  m_attachedRouters(),
+  m_status(GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED)
 {
-  NS_DEBUG("GlobalRouterLSA::GlobalRouterLSA ()");
+  NS_DEBUG("GlobalRoutingLSA::GlobalRoutingLSA ()");
 }
 
-GlobalRouterLSA::GlobalRouterLSA (
-  GlobalRouterLSA::SPFStatus status,
+GlobalRoutingLSA::GlobalRoutingLSA (
+  GlobalRoutingLSA::SPFStatus status,
   Ipv4Address linkStateId, 
   Ipv4Address advertisingRtr)
 :
+  m_lsType (GlobalRoutingLSA::Unknown),
   m_linkStateId(linkStateId),
   m_advertisingRtr(advertisingRtr),
   m_linkRecords(),
+  m_networkLSANetworkMask("0.0.0.0"),
+  m_attachedRouters(),
   m_status(status)
 {
-  NS_DEBUG("GlobalRouterLSA::GlobalRouterLSA (" << status << ", " <<
+  NS_DEBUG("GlobalRoutingLSA::GlobalRoutingLSA (" << status << ", " <<
     linkStateId << ", " << advertisingRtr << ")");
 }
 
-GlobalRouterLSA::GlobalRouterLSA (GlobalRouterLSA& lsa)
-  : m_linkStateId(lsa.m_linkStateId), m_advertisingRtr(lsa.m_advertisingRtr),
+GlobalRoutingLSA::GlobalRoutingLSA (GlobalRoutingLSA& lsa)
+  : m_lsType(lsa.m_lsType), m_linkStateId(lsa.m_linkStateId), 
+    m_advertisingRtr(lsa.m_advertisingRtr), 
+    m_networkLSANetworkMask(lsa.m_networkLSANetworkMask), 
     m_status(lsa.m_status)
 {
   NS_ASSERT_MSG(IsEmpty(), 
-    "GlobalRouterLSA::GlobalRouterLSA (): Non-empty LSA in constructor");
+    "GlobalRoutingLSA::GlobalRoutingLSA (): Non-empty LSA in constructor");
   CopyLinkRecords (lsa);
 }
 
-  GlobalRouterLSA&
-GlobalRouterLSA::operator= (const GlobalRouterLSA& lsa)
+  GlobalRoutingLSA&
+GlobalRoutingLSA::operator= (const GlobalRoutingLSA& lsa)
 {
+  m_lsType = lsa.m_lsType;
   m_linkStateId = lsa.m_linkStateId;
   m_advertisingRtr = lsa.m_advertisingRtr;
+  m_networkLSANetworkMask = lsa.m_networkLSANetworkMask, 
   m_status = lsa.m_status;
 
   ClearLinkRecords ();
@@ -171,14 +181,14 @@
 }
 
   void
-GlobalRouterLSA::CopyLinkRecords (const GlobalRouterLSA& lsa)
+GlobalRoutingLSA::CopyLinkRecords (const GlobalRoutingLSA& lsa)
 {
   for (ListOfLinkRecords_t::const_iterator i = lsa.m_linkRecords.begin ();
        i != lsa.m_linkRecords.end (); 
        i++)
     {
-      GlobalRouterLinkRecord *pSrc = *i;
-      GlobalRouterLinkRecord *pDst = new GlobalRouterLinkRecord;
+      GlobalRoutingLinkRecord *pSrc = *i;
+      GlobalRoutingLinkRecord *pDst = new GlobalRoutingLinkRecord;
 
       pDst->SetLinkType (pSrc->GetLinkType ());
       pDst->SetLinkId (pSrc->GetLinkId ());
@@ -187,48 +197,50 @@
       m_linkRecords.push_back(pDst);
       pDst = 0;
     }
+
+   m_attachedRouters = lsa.m_attachedRouters;
 }
 
-GlobalRouterLSA::~GlobalRouterLSA()
+GlobalRoutingLSA::~GlobalRoutingLSA()
 {
-  NS_DEBUG("GlobalRouterLSA::~GlobalRouterLSA ()");
+  NS_DEBUG("GlobalRoutingLSA::~GlobalRoutingLSA ()");
   ClearLinkRecords ();
 }
 
   void
-GlobalRouterLSA::ClearLinkRecords(void)
+GlobalRoutingLSA::ClearLinkRecords(void)
 {
   for ( ListOfLinkRecords_t::iterator i = m_linkRecords.begin ();
         i != m_linkRecords.end (); 
         i++)
     {
-      NS_DEBUG("GlobalRouterLSA::ClearLinkRecords ():  free link record");
+      NS_DEBUG("GlobalRoutingLSA::ClearLinkRecords ():  free link record");
 
-      GlobalRouterLinkRecord *p = *i;
+      GlobalRoutingLinkRecord *p = *i;
       delete p;
       p = 0;
 
       *i = 0;
     }
-  NS_DEBUG("GlobalRouterLSA::ClearLinkRecords():  clear list");
+  NS_DEBUG("GlobalRoutingLSA::ClearLinkRecords():  clear list");
   m_linkRecords.clear();
 }
 
   uint32_t
-GlobalRouterLSA::AddLinkRecord (GlobalRouterLinkRecord* lr)
+GlobalRoutingLSA::AddLinkRecord (GlobalRoutingLinkRecord* lr)
 {
   m_linkRecords.push_back (lr);
   return m_linkRecords.size ();
 }
 
   uint32_t
-GlobalRouterLSA::GetNLinkRecords (void) const
+GlobalRoutingLSA::GetNLinkRecords (void) const
 {
   return m_linkRecords.size ();
 }
 
-  GlobalRouterLinkRecord *
-GlobalRouterLSA::GetLinkRecord (uint32_t n) const
+  GlobalRoutingLinkRecord *
+GlobalRoutingLSA::GetLinkRecord (uint32_t n) const
 {
   uint32_t j = 0;
   for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
@@ -240,70 +252,146 @@
           return *i;
         }
     }
-  NS_ASSERT_MSG(false, "GlobalRouterLSA::GetLinkRecord (): invalid index");
+  NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetLinkRecord (): invalid index");
   return 0;
 }
 
   bool
-GlobalRouterLSA::IsEmpty (void) const
+GlobalRoutingLSA::IsEmpty (void) const
 {
   return m_linkRecords.size () == 0;
 }
 
+  GlobalRoutingLSA::LSType
+GlobalRoutingLSA::GetLSType (void) const
+{
+  return m_lsType;
+}
+
+  void 
+GlobalRoutingLSA::SetLSType (GlobalRoutingLSA::LSType typ) 
+{
+  m_lsType = typ;
+}
+
   Ipv4Address
-GlobalRouterLSA::GetLinkStateId (void) const
+GlobalRoutingLSA::GetLinkStateId (void) const
 {
   return m_linkStateId;
 }
 
   void
-GlobalRouterLSA::SetLinkStateId (Ipv4Address addr)
+GlobalRoutingLSA::SetLinkStateId (Ipv4Address addr)
 {
   m_linkStateId = addr;
 }
 
   Ipv4Address
-GlobalRouterLSA::GetAdvertisingRouter (void) const
+GlobalRoutingLSA::GetAdvertisingRouter (void) const
 {
   return m_advertisingRtr;
 }
 
   void
-GlobalRouterLSA::SetAdvertisingRouter (Ipv4Address addr)
+GlobalRoutingLSA::SetAdvertisingRouter (Ipv4Address addr)
 {
   m_advertisingRtr = addr;
 }
 
-  GlobalRouterLSA::SPFStatus
-GlobalRouterLSA::GetStatus (void) const
+  void 
+GlobalRoutingLSA::SetNetworkLSANetworkMask (Ipv4Mask mask)
+{
+  m_networkLSANetworkMask = mask;
+}
+
+  Ipv4Mask 
+GlobalRoutingLSA::GetNetworkLSANetworkMask (void) const
+{
+  return m_networkLSANetworkMask;
+}
+
+  GlobalRoutingLSA::SPFStatus
+GlobalRoutingLSA::GetStatus (void) const
 {
   return m_status;
 }
 
+  uint32_t 
+GlobalRoutingLSA::AddAttachedRouter (Ipv4Address addr)
+{
+  m_attachedRouters.push_back (addr);
+  return m_attachedRouters.size ();
+}
+
+  uint32_t 
+GlobalRoutingLSA::GetNAttachedRouters (void) const
+{
+  return m_attachedRouters.size (); 
+}
+
+  Ipv4Address 
+GlobalRoutingLSA::GetAttachedRouter (uint32_t n) const
+{
+  uint32_t j = 0;
+  for ( ListOfAttachedRouters_t::const_iterator i = m_attachedRouters.begin ();
+        i != m_attachedRouters.end (); 
+        i++, j++)
+    {
+      if (j == n) 
+        {
+          return *i;
+        }
+    }
+  NS_ASSERT_MSG(false, "GlobalRoutingLSA::GetAttachedRouter (): invalid index");
+  return Ipv4Address("0.0.0.0");
+}
+
   void
-GlobalRouterLSA::SetStatus (GlobalRouterLSA::SPFStatus status)
+GlobalRoutingLSA::SetStatus (GlobalRoutingLSA::SPFStatus status)
 {
   m_status = status;
 }
 
   void 
-GlobalRouterLSA::Print (std::ostream &os) const
+GlobalRoutingLSA::Print (std::ostream &os) const
 {
-  os << "m_linkStateId = " << m_linkStateId << std::endl <<
+  os << "m_lsType = " << m_lsType << std::endl <<
+        "m_linkStateId = " << m_linkStateId << std::endl <<
         "m_advertisingRtr = " << m_advertisingRtr << std::endl;
 
-  for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
-        i != m_linkRecords.end (); 
-        i++)
+  if (m_lsType == GlobalRoutingLSA::RouterLSA) 
+    {
+      for ( ListOfLinkRecords_t::const_iterator i = m_linkRecords.begin ();
+            i != m_linkRecords.end (); 
+            i++)
+        {
+          GlobalRoutingLinkRecord *p = *i;
+          os << "----------" << std::endl;
+          os << "m_linkId = " << p->GetLinkId () << std::endl;
+          os << "m_linkData = " << p->GetLinkData () << std::endl;
+        }
+    }
+  else if (m_lsType == GlobalRoutingLSA::NetworkLSA) 
     {
-      GlobalRouterLinkRecord *p = *i;
       os << "----------" << std::endl;
-      os << "m_linkId = " << p->GetLinkId () << std::endl;
-      os << "m_linkData = " << p->GetLinkData () << std::endl;
+      os << "m_networkLSANetworkMask = " << m_networkLSANetworkMask 
+         << std::endl;
+      for ( ListOfAttachedRouters_t::const_iterator i = 
+            m_attachedRouters.begin ();
+            i != m_attachedRouters.end (); 
+            i++)
+        {
+          Ipv4Address p = *i;
+          os << "attachedRouter = " << p << std::endl;
+        }
+    }
+  else 
+    {
+      NS_ASSERT_MSG(0, "Illegal LSA LSType: " << m_lsType);
     }
 }
 
-std::ostream& operator<< (std::ostream& os, GlobalRouterLSA& lsa)
+std::ostream& operator<< (std::ostream& os, GlobalRoutingLSA& lsa)
 {
   lsa.Print (os);
   return os;
@@ -350,7 +438,7 @@
     {
       NS_DEBUG("GlobalRouter::ClearLSAs ():  free LSA");
 
-      GlobalRouterLSA *p = *i;
+      GlobalRoutingLSA *p = *i;
       delete p;
       p = 0;
 
@@ -373,11 +461,16 @@
   uint32_t 
 GlobalRouter::DiscoverLSAs (void)
 {
-  NS_DEBUG("GlobalRouter::DiscoverLSAs ()");
+  NS_DEBUG("GlobalRouter::DiscoverLSAs () for node " << m_node->GetId () );
   NS_ASSERT_MSG(m_node, 
     "GlobalRouter::DiscoverLSAs (): <Node> interface not set");
 
   ClearLSAs ();
+
+// While building the router-LSA, keep a list of those NetDevices for
+// which I am the designated router and need to later build a NetworkLSA
+  std::list<Ptr<NetDevice> > listOfDRInterfaces;
+
 //
 // We're aggregated to a node.  We need to ask the node for a pointer to its
 // Ipv4 interface.  This is where the information regarding the attached 
@@ -387,118 +480,252 @@
   NS_ASSERT_MSG(ipv4Local, 
     "GlobalRouter::DiscoverLSAs (): QI for <Ipv4> interface failed");
 //
-// We are, for now at least, only going to report RouterLSAs in this method.
-// What this means is that there is going to be one advertisement with some
-// number of link records.  This means that GetNumLSAs will actually always
-// return exactly one.
+// Each node originates a Router-LSA
 //
-  GlobalRouterLSA *pLSA = new GlobalRouterLSA;
+  GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
+  pLSA->SetLSType (GlobalRoutingLSA::RouterLSA);
   pLSA->SetLinkStateId (m_routerId);
   pLSA->SetAdvertisingRouter (m_routerId);
-  pLSA->SetStatus (GlobalRouterLSA::LSA_SPF_NOT_EXPLORED);
+  pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
 //
 // We need to ask the node for the number of net devices attached. This isn't
 // necessarily equal to the number of links to adjacent nodes (other routers)
 // as the number of devices may include those for stub networks (e.g., 
-// ethernets, etc.).  So we have to walk through the list of net devices and
-// pay attention to those that are directly connected to another router through
-// a point-to-point channel.
+// ethernets, etc.).  
 //
   uint32_t numDevices = m_node->GetNDevices();
   NS_DEBUG("GlobalRouter::DiscoverLSAs (): numDevices = " << numDevices);
-//
-// Loop through the devices looking for those connected to a point-to-point
-// channel.
-//
   for (uint32_t i = 0; i < numDevices; ++i)
     {
       Ptr<NetDevice> ndLocal = m_node->GetDevice(i);
 
-      if (!ndLocal->IsPointToPoint ())
+      if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () )
         {
-          NS_DEBUG("GlobalRouter::DiscoverLSAs (): non-point-to-point device");
-          continue;
+          NS_DEBUG("GlobalRouter::DiscoverLSAs (): broadcast link");
+          GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
+//
+// We need to determine whether we are on a transit or stub network
+// If we find at least one more router on this channel, we are a transit
+//
+//
+// Now, we have to find the Ipv4 interface whose netdevice is the one we 
+// just found.  This is still the IP on the local side of the channel.  There 
+// is a function to do this used down in the guts of the stack, but it's not 
+// exported so we had to whip up an equivalent.
+//
+          uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal);
+          Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+          Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+          NS_DEBUG("Working with local address " << addrLocal);
+//
+// Now, we're going to walk over to the remote net device on the other end of 
+// the point-to-point channel we now know we have.  This is where our adjacent 
+// router (to use OSPF lingo) is running.  
+//
+          Ptr<Channel> ch = ndLocal->GetChannel();
+          uint32_t nDevices = ch->GetNDevices();
+          if (nDevices == 1)
+            {
+              // This is a stub broadcast interface
+              NS_DEBUG("GlobalRouter::DiscoverLSAs (): Router-LSA stub broadcast link");
+              // XXX in future, need to consider if >1 includes other routers
+              plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
+              // Link ID is IP network number of attached network
+              plr->SetLinkId (addrLocal.CombineMask(maskLocal));
+              // Link Data is network mask; convert to Ipv4Address
+              Ipv4Address maskLocalAddr;
+              maskLocalAddr.Set(maskLocal.GetHostOrder ());
+              plr->SetLinkData (maskLocalAddr);
+              // Cost is interface's configured output cost (NOTYET)
+              plr->SetMetric (1);
+              pLSA->AddLinkRecord(plr);
+              plr = 0;
+              continue;
+            }
+          else
+            {
+              NS_DEBUG("GlobalRouter::DiscoverLSAs (): Router-LSA Broadcast link");
+              // multiple routers on a broadcast interface
+              // lowest IP address is designated router
+              plr->SetLinkType (GlobalRoutingLinkRecord::TransitNetwork);
+              // Link ID is IP interface address of designated router
+              Ipv4Address desigRtr = 
+                FindDesignatedRouterForLink (m_node, ndLocal);
+              if (desigRtr == addrLocal) 
+                {
+                  listOfDRInterfaces.push_back (ndLocal);
+                  NS_DEBUG("GlobalRouter::DiscoverLSAs (): " << 
+                    m_node->GetId () << " is a DR");
+                }
+              plr->SetLinkId (desigRtr);
+              // Link Data is router's own IP address
+              plr->SetLinkData (addrLocal);
+              // Cost is interface's configured output cost (NOTYET)
+              plr->SetMetric (1);
+              pLSA->AddLinkRecord (plr);
+              plr = 0;
+              continue;
+            }
         }
-
-      NS_DEBUG("GlobalRouter::DiscoverLSAs (): Point-to-point device");
+      else if (ndLocal->IsPointToPoint () )
+        {
+          NS_DEBUG("GlobalRouter::DiscoverLSAs (): Router-LSA Point-to-point device");
 //
 // Now, we have to find the Ipv4 interface whose netdevice is the one we 
 // just found.  This is still the IP on the local side of the channel.  There 
 // is a function to do this used down in the guts of the stack, but it's not 
 // exported so we had to whip up an equivalent.
 //
-      uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal);
+          uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal);
 //
 // Now that we have the Ipv4 interface index, we can get the address and mask
 // we need.
 //
-      Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
-      Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
-      NS_DEBUG("Working with local address " << addrLocal);
+          Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+          Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+          NS_DEBUG("Working with local address " << addrLocal);
 //
 // Now, we're going to walk over to the remote net device on the other end of 
 // the point-to-point channel we now know we have.  This is where our adjacent 
 // router (to use OSPF lingo) is running.  
 //
-      Ptr<Channel> ch = ndLocal->GetChannel();
-      Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch);
+          Ptr<Channel> ch = ndLocal->GetChannel();
+          Ptr<NetDevice> ndRemote = GetAdjacent(ndLocal, ch);
 //
 // The adjacent net device is aggregated to a node.  We need to ask that net 
 // device for its node, then ask that node for its Ipv4 interface.
 //
-      Ptr<Node> nodeRemote = ndRemote->GetNode();
-      Ptr<Ipv4> ipv4Remote = nodeRemote->QueryInterface<Ipv4> (Ipv4::iid);
-      NS_ASSERT_MSG(ipv4Remote, 
-        "GlobalRouter::DiscoverLSAs (): QI for remote <Ipv4> failed");
+          Ptr<Node> nodeRemote = ndRemote->GetNode();
+          Ptr<Ipv4> ipv4Remote = nodeRemote->QueryInterface<Ipv4> (Ipv4::iid);
+          NS_ASSERT_MSG(ipv4Remote, 
+            "GlobalRouter::DiscoverLSAs (): QI for remote <Ipv4> failed");
 //
 // Per the OSPF spec, we're going to need the remote router ID, so we might as
 // well get it now.
 //
-      Ptr<GlobalRouter> srRemote = 
-        nodeRemote->QueryInterface<GlobalRouter> (GlobalRouter::iid);
-      NS_ASSERT_MSG(srRemote, 
-        "GlobalRouter::DiscoverLSAs (): QI for remote <GlobalRouter> failed");
-      Ipv4Address rtrIdRemote = srRemote->GetRouterId();
-      NS_DEBUG("Working with remote router " << rtrIdRemote);
+          Ptr<GlobalRouter> srRemote = 
+            nodeRemote->QueryInterface<GlobalRouter> (GlobalRouter::iid);
+          NS_ASSERT_MSG(srRemote, 
+            "GlobalRouter::DiscoverLSAs():QI for remote <GlobalRouter> failed");
+          Ipv4Address rtrIdRemote = srRemote->GetRouterId();
+          NS_DEBUG("Working with remote router " << rtrIdRemote);
 //
 // Now, just like we did above, we need to get the IP interface index for the 
 // net device on the other end of the point-to-point channel.
 //
-      uint32_t ifIndexRemote = FindIfIndexForDevice(nodeRemote, ndRemote);
+          uint32_t ifIndexRemote = FindIfIndexForDevice(nodeRemote, ndRemote);
 //
 // Now that we have the Ipv4 interface, we can get the (remote) address and
 // mask we need.
 //
-      Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote);
-      Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote);
-      NS_DEBUG("Working with remote address " << addrRemote);
+          Ipv4Address addrRemote = ipv4Remote->GetAddress(ifIndexRemote);
+          Ipv4Mask maskRemote = ipv4Remote->GetNetworkMask(ifIndexRemote);
+          NS_DEBUG("Working with remote address " << addrRemote);
 //
 // Now we can fill out the link records for this link.  There are always two
 // link records; the first is a point-to-point record describing the link and
 // the second is a stub network record with the network number.
 //
-      GlobalRouterLinkRecord *plr = new GlobalRouterLinkRecord;
-      plr->SetLinkType (GlobalRouterLinkRecord::PointToPoint);
-      plr->SetLinkId (rtrIdRemote);
-      plr->SetLinkData (addrLocal);
-      pLSA->AddLinkRecord(plr);
-      plr = 0;
+          GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
+          plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
+          plr->SetLinkId (rtrIdRemote);
+          plr->SetLinkData (addrLocal);
+          pLSA->AddLinkRecord (plr);
+          plr = 0;
 
-      plr = new GlobalRouterLinkRecord;
-      plr->SetLinkType (GlobalRouterLinkRecord::StubNetwork);
-      plr->SetLinkId (addrRemote);
-      plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder()));  // Frown
-      pLSA->AddLinkRecord(plr);
-      plr = 0;
+          plr = new GlobalRoutingLinkRecord;
+          plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
+          plr->SetLinkId (addrRemote);
+          plr->SetLinkData (Ipv4Address(maskRemote.GetHostOrder()));  // Frown
+          pLSA->AddLinkRecord (plr);
+          plr = 0;
+        }
+      else
+        {
+          NS_ASSERT_MSG(0, "GlobalRouter::DiscoverLSAs (): unknown link type");
+        }
+
     }
 //
 // The LSA goes on a list of LSAs in case we want to begin exporting other
 // kinds of advertisements (than Router LSAs).
   m_LSAs.push_back (pLSA);
   NS_DEBUG(*pLSA);
+
+
+// Now, determine whether we need to build a NetworkLSA
+  if (listOfDRInterfaces.size () > 0)
+    {
+      for (std::list<Ptr<NetDevice> >::iterator i = listOfDRInterfaces.begin ();
+        i != listOfDRInterfaces.end (); i++)
+        {
+// Build one NetworkLSA for each interface that is a DR
+          Ptr<NetDevice> ndLocal = *i;
+          uint32_t ifIndexLocal = FindIfIndexForDevice(m_node, ndLocal);
+          Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+          Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+
+          GlobalRoutingLSA *pLSA = new GlobalRoutingLSA;
+          pLSA->SetLSType (GlobalRoutingLSA::NetworkLSA);
+          pLSA->SetLinkStateId (addrLocal);
+          pLSA->SetAdvertisingRouter (m_routerId);
+          pLSA->SetNetworkLSANetworkMask (maskLocal);
+          pLSA->SetStatus (GlobalRoutingLSA::LSA_SPF_NOT_EXPLORED);
+// Build list of AttachedRouters
+          Ptr<Channel> ch = ndLocal->GetChannel();
+          uint32_t nDevices = ch->GetNDevices();
+          NS_ASSERT (nDevices);
+          for (uint32_t i = 0; i < nDevices; i++)
+            {
+              Ptr<NetDevice> tempNd = ch->GetDevice (i);
+              NS_ASSERT (tempNd);
+              Ptr<Node> tempNode = tempNd->GetNode ();
+              uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd);
+              Ptr<Ipv4> tempIpv4 = tempNode->QueryInterface<Ipv4> (Ipv4::iid);
+              NS_ASSERT (tempIpv4);
+              Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex);
+              pLSA->AddAttachedRouter (tempAddr);
+            }
+          m_LSAs.push_back (pLSA);
+          NS_DEBUG(*pLSA);
+        }
+    }
+
   return m_LSAs.size ();
 }
 
+  Ipv4Address
+GlobalRouter::FindDesignatedRouterForLink (Ptr<Node> node, 
+  Ptr<NetDevice> ndLocal) const
+{
+  uint32_t ifIndexLocal = FindIfIndexForDevice(node, ndLocal);
+  Ptr<Ipv4> ipv4Local = m_node->QueryInterface<Ipv4> (Ipv4::iid);
+  NS_ASSERT (ipv4Local);
+  Ipv4Address addrLocal = ipv4Local->GetAddress(ifIndexLocal);
+  Ipv4Mask maskLocal = ipv4Local->GetNetworkMask(ifIndexLocal);
+
+  Ptr<Channel> ch = ndLocal->GetChannel();
+  uint32_t nDevices = ch->GetNDevices();
+  NS_ASSERT (nDevices);
+  Ipv4Address lowest = addrLocal;
+  // iterate all NetDevices and return the lowest numbered IP address 
+  for (uint32_t i = 0; i < nDevices; i++)
+    {
+      Ptr<NetDevice> tempNd = ch->GetDevice (i);
+      NS_ASSERT (tempNd);
+      Ptr<Node> tempNode = tempNd->GetNode ();
+      uint32_t tempIfIndex = FindIfIndexForDevice (tempNode, tempNd);
+      Ptr<Ipv4> tempIpv4 = tempNode->QueryInterface<Ipv4> (Ipv4::iid);
+      NS_ASSERT (tempIpv4);
+      Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex);
+      if (tempAddr < addrLocal)
+        {
+          addrLocal = tempAddr;
+        }
+    }
+  return addrLocal;
+}
+
   uint32_t 
 GlobalRouter::GetNumLSAs (void) const
 {
@@ -510,7 +737,7 @@
 // Get the nth link state advertisement from this router.
 //
   bool
-GlobalRouter::GetLSA (uint32_t n, GlobalRouterLSA &lsa) const
+GlobalRouter::GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const
 {
   NS_ASSERT_MSG(lsa.IsEmpty(), "GlobalRouter::GetLSA (): Must pass empty LSA");
 //
@@ -525,7 +752,7 @@
     {
       if (j == n)
         {
-          GlobalRouterLSA *p = *i;
+          GlobalRoutingLSA *p = *i;
           lsa = *p;
           return true;
         }
--- a/src/routing/global-routing/global-router-interface.h	Sun Aug 12 22:41:24 2007 -0700
+++ b/src/routing/global-routing/global-router-interface.h	Sun Aug 12 22:43:25 2007 -0700
@@ -31,16 +31,16 @@
 /**
  * @brief A single link record for a link state advertisement.
  *
- * The GlobalRouterLinkRecord is modeled after the OSPF link record field of
+ * The GlobalRoutingLinkRecord is modeled after the OSPF link record field of
  * a Link State Advertisement.  Right now we will only see two types of link
  * records corresponding to a stub network and a point-to-point link (channel).
  */
-class GlobalRouterLinkRecord
+class GlobalRoutingLinkRecord
 {
 public:
 /**
  * @enum LinkType
- * @brief Enumeration of the possible types of Global Router Link Records.
+ * @brief Enumeration of the possible types of Global Routing Link Records.
  *
  * These values are defined in the OSPF spec.  We currently only use 
  * PointToPoint and StubNetwork types.
@@ -54,16 +54,16 @@
   };
 
 /**
- * @brief Construct an empty ("uninitialized") Global Router Link Record.
+ * @brief Construct an empty ("uninitialized") Global Routing Link Record.
  *
  * The Link ID and Link Data Ipv4 addresses are set to "0.0.0.0";
  * The Link Type is set to Unknown;
  * The metric is set to 0.
  */
-  GlobalRouterLinkRecord ();
+  GlobalRoutingLinkRecord ();
 
 /**
- * Construct an initialized Global Router Link Record.
+ * Construct an initialized Global Routing Link Record.
  *
  * @param linkType The type of link record to construct.
  * @param linkId The link ID for the record.
@@ -73,21 +73,21 @@
  * @see SetLinkId
  * @see SetLinkData
  */
-  GlobalRouterLinkRecord (
+  GlobalRoutingLinkRecord (
     LinkType    linkType, 
     Ipv4Address linkId, 
     Ipv4Address linkData, 
     uint32_t    metric);
 
 /**
- * @brief Destroy a Global Router Link Record.
+ * @brief Destroy a Global Routing Link Record.
  *
  * Currently does nothing.  Here as a placeholder only.
  */
-  ~GlobalRouterLinkRecord ();
+  ~GlobalRoutingLinkRecord ();
 
 /**
- * Get the Link ID field of the Global Router Link Record.
+ * Get the Link ID field of the Global Routing Link Record.
  *
  * For an OSPF type 1 link (PointToPoint) the Link ID will be the Router ID
  * of the neighboring router.
@@ -100,7 +100,7 @@
   Ipv4Address GetLinkId(void) const;
 
 /**
- * @brief Set the Link ID field of the Global Router Link Record.
+ * @brief Set the Link ID field of the Global Routing Link Record.
  *
  * For an OSPF type 1 link (PointToPoint) the Link ID must be the Router ID
  * of the neighboring router.
@@ -113,7 +113,7 @@
   void SetLinkId(Ipv4Address addr);
 
 /**
- * @brief Get the Link Data field of the Global Router Link Record.
+ * @brief Get the Link Data field of the Global Routing Link Record.
  *
  * For an OSPF type 1 link (PointToPoint) the Link Data will be the IP
  * address of the node of the local side of the link.
@@ -126,7 +126,7 @@
   Ipv4Address GetLinkData(void) const;
 
 /**
- * @brief Set the Link Data field of the Global Router Link Record.
+ * @brief Set the Link Data field of the Global Routing Link Record.
  *
  * For an OSPF type 1 link (PointToPoint) the Link Data must be the IP
  * address of the node of the local side of the link.
@@ -139,29 +139,29 @@
   void SetLinkData(Ipv4Address addr);
 
 /**
- * @brief Get the Link Type field of the Global Router Link Record.
+ * @brief Get the Link Type field of the Global Routing Link Record.
  *
  * The Link Type describes the kind of link a given record represents.  The
  * values are defined by OSPF.
  *
  * @see LinkType
- * @returns The LinkType of the current Global Router Link Record.
+ * @returns The LinkType of the current Global Routing Link Record.
  */
   LinkType GetLinkType(void) const;
 
 /**
- * @brief Set the Link Type field of the Global Router Link Record.
+ * @brief Set the Link Type field of the Global Routing Link Record.
  *
  * The Link Type describes the kind of link a given record represents.  The
  * values are defined by OSPF.
  *
  * @see LinkType
- * @param linkType The new LinkType for the current Global Router Link Record.
+ * @param linkType The new LinkType for the current Global Routing Link Record.
  */
   void SetLinkType(LinkType linkType);
 
 /**
- * @brief Get the Metric Data field of the Global Router Link Record.
+ * @brief Get the Metric Data field of the Global Routing Link Record.
  *
  * The metric is an abstract cost associated with forwarding a packet across
  * a link.  A sum of metrics must have a well-defined meaning.  That is, you
@@ -169,12 +169,12 @@
  * two hops relate to the cost of sending a packet); rather you should use
  * something like delay.
  *
- * @returns The metric field of the Global Router Link Record.
+ * @returns The metric field of the Global Routing Link Record.
  */
   uint32_t GetMetric(void) const;
 
 /**
- * @brief Set the Metric Data field of the Global Router Link Record.
+ * @brief Set the Metric Data field of the Global Routing Link Record.
  *
  * The metric is an abstract cost associated with forwarding a packet across
  * a link.  A sum of metrics must have a well-defined meaning.  That is, you
@@ -182,7 +182,7 @@
  * two hops relate to the cost of sending a packet); rather you should use
  * something like delay.
  *
- * @param metric The new metric for the current Global Router Link Record.
+ * @param metric The new metric for the current Global Routing Link Record.
  */
   void SetMetric(uint32_t metric);
 
@@ -211,7 +211,7 @@
   Ipv4Address m_linkData;    // for links to RouterLSA, 
 
 /**
- * The type of the Global Router Link Record.  Defined in the OSPF spec.  
+ * The type of the Global Routing Link Record.  Defined in the OSPF spec.  
  * We currently only use PointToPoint and StubNetwork types.
  */
   LinkType m_linkType;
@@ -236,12 +236,24 @@
  * combined with a list of Link Records.  Since it's global, there's
  * no need for age or sequence number.  See RFC 2328, Appendix A.
  */
-class GlobalRouterLSA
+class GlobalRoutingLSA
 {
 public:
 /**
+ * @enum LSType
+ * @brief corresponds to LS type field of RFC 2328 OSPF LSA header
+ */
+  enum LSType {
+    Unknown = 0,        /**< Uninitialized Type */
+    RouterLSA,
+    NetworkLSA,
+    SummaryLSA,
+    SummaryLSA_ASBR,
+    ASExternalLSAs
+  };
+/**
  * @enum SPFStatus
- * @brief Enumeration of the possible values of the status flag in the Router 
+ * @brief Enumeration of the possible values of the status flag in the Routing 
  * Link State Advertisements.
  */
   enum SPFStatus {
@@ -249,17 +261,16 @@
     LSA_SPF_CANDIDATE,		/**< Vertex is in the SPF candidate queue */
     LSA_SPF_IN_SPFTREE		/**< Vertex is in the SPF tree */
   };
-
 /**
- * @brief Create a blank Global Router Link State Advertisement.  
+ * @brief Create a blank Global Routing Link State Advertisement.  
  *
  * On completion Ipv4Address variables initialized to 0.0.0.0 and the 
  * list of Link State Records is empty.
  */
-  GlobalRouterLSA();
+  GlobalRoutingLSA();
 
 /**
- * @brief Create an initialized Global Router Link State Advertisement.  
+ * @brief Create an initialized Global Routing Link State Advertisement.  
  *
  * On completion the list of Link State Records is empty.
  *
@@ -267,42 +278,42 @@
  * @param linkStateId The Ipv4Address for the link state ID field.
  * @param advertisingRtr The Ipv4Address for the advertising router field.
  */
-  GlobalRouterLSA(SPFStatus status, Ipv4Address linkStateId, 
+  GlobalRoutingLSA(SPFStatus status, Ipv4Address linkStateId, 
     Ipv4Address advertisingRtr);
 
 /**
- * @brief Copy constructor for a Global Router Link State Advertisement.
+ * @brief Copy constructor for a Global Routing Link State Advertisement.
  *
  * Takes a piece of memory and constructs a semantically identical copy of
  * the given LSA.
  *
  * @param lsa The existing LSA to be used as the source.
  */
-  GlobalRouterLSA (GlobalRouterLSA& lsa);
+  GlobalRoutingLSA (GlobalRoutingLSA& lsa);
 
 /**
- * @brief Destroy an existing Global Router Link State Advertisement.
+ * @brief Destroy an existing Global Routing Link State Advertisement.
  *
- * Any Global Router Link Records present in the list are freed.
+ * Any Global Routing Link Records present in the list are freed.
  */
-  ~GlobalRouterLSA();
+  ~GlobalRoutingLSA();
 
 /**
- * @brief Assignment operator for a Global Router Link State Advertisement.
+ * @brief Assignment operator for a Global Routing Link State Advertisement.
  *
- * Takes an existing Global Router Link State Advertisement and overwrites
+ * Takes an existing Global Routing Link State Advertisement and overwrites
  * it to make a semantically identical copy of a given prototype LSA.
  *
- * If there are any Global Router Link Records present in the existing 
+ * If there are any Global Routing Link Records present in the existing 
  * LSA, they are freed before the assignment happens.
  *
  * @param lsa The existing LSA to be used as the source.
  * @returns Reference to the overwritten LSA.
  */
-  GlobalRouterLSA& operator= (const GlobalRouterLSA& lsa);
+  GlobalRoutingLSA& operator= (const GlobalRoutingLSA& lsa);
 
 /**
- * @brief Copy any Global Router Link Records in a given Global Router Link
+ * @brief Copy any Global Routing Link Records in a given Global Routing Link
  * State Advertisement to the current LSA.  
  * 
  * Existing Link Records are not deleted -- this is a concatenation of Link 
@@ -311,57 +322,66 @@
  * @see ClearLinkRecords ()
  * @param lsa The LSA to copy the Link Records from.
  */
-  void CopyLinkRecords (const GlobalRouterLSA& lsa);
+  void CopyLinkRecords (const GlobalRoutingLSA& lsa);
 
 /**
- * @brief Add a given Global Router Link Record to the LSA.
+ * @brief Add a given Global Routing Link Record to the LSA.
  *
- * @param lr The Global Router Link Record to be added.
+ * @param lr The Global Routing Link Record to be added.
  * @returns The number of link records in the list.
  */
-  uint32_t AddLinkRecord (GlobalRouterLinkRecord* lr);
+  uint32_t AddLinkRecord (GlobalRoutingLinkRecord* lr);
 
 /**
- * @brief Return the number of Global Router Link Records in the LSA.
+ * @brief Return the number of Global Routing Link Records in the LSA.
  *
  * @returns The number of link records in the list.
  */
   uint32_t GetNLinkRecords (void) const;
 
 /**
- * @brief Return a pointer to the specified Global Router Link Record.
+ * @brief Return a pointer to the specified Global Routing Link Record.
  *
  * @param n The LSA number desired.
  * @returns The number of link records in the list.
  */
-  GlobalRouterLinkRecord* GetLinkRecord (uint32_t n) const;
+  GlobalRoutingLinkRecord* GetLinkRecord (uint32_t n) const;
 
 /**
- * @brief Release all of the Global Router Link Records present in the Global
- * Router Link State Advertisement and make the list of link records empty.
+ * @brief Release all of the Global Routing Link Records present in the Global
+ * Routing Link State Advertisement and make the list of link records empty.
  */
   void ClearLinkRecords(void);
 
 /**
- * @brief Check to see if the list of Global Router Link Records present in the
- * Global Router Link State Advertisement is empty.
+ * @brief Check to see if the list of Global Routing Link Records present in the
+ * Global Routing Link State Advertisement is empty.
  *
  * @returns True if the list is empty, false otherwise.
  */
   bool IsEmpty(void) const;
 
 /**
- * @brief Print the contents of the Global Router Link State Advertisement and
- * any Global Router Link Records present in the list.  Quite verbose.
+ * @brief Print the contents of the Global Routing Link State Advertisement and
+ * any Global Routing Link Records present in the list.  Quite verbose.
  */
   void Print (std::ostream &os) const;
 
 /**
+ * @brief Return the LSType field of the LSA 
+ */
+  LSType GetLSType (void) const;
+/**
+ * @brief Set the LS type field of the LSA
+ */
+  void SetLSType (LSType typ);
+
+/**
  * @brief Get the Link State ID as defined by the OSPF spec.  We always set it
  * to the router ID of the router making the advertisement.
  *
  * @see RoutingEnvironment::AllocateRouterId ()
- * @see GlobalRouter::GetRouterId ()
+ * @see GlobalRouting::GetRouterId ()
  * @returns The Ipv4Address stored as the link state ID.
  */
   Ipv4Address GetLinkStateId (void) const;
@@ -371,7 +391,7 @@
  * to the router ID of the router making the advertisement.
  *
  * @see RoutingEnvironment::AllocateRouterId ()
- * @see GlobalRouter::GetRouterId ()
+ * @see GlobalRouting::GetRouterId ()
  */
   void SetLinkStateId (Ipv4Address addr);
 
@@ -380,7 +400,7 @@
  * set it to the router ID of the router making the advertisement.
  *
  * @see RoutingEnvironment::AllocateRouterId ()
- * @see GlobalRouter::GetRouterId ()
+ * @see GlobalRouting::GetRouterId ()
  * @returns The Ipv4Address stored as the advetising router.
  */
   Ipv4Address GetAdvertisingRouter (void) const;
@@ -390,11 +410,48 @@
  * set it to the router ID of the router making the advertisement.
  *
  * @see RoutingEnvironment::AllocateRouterId ()
- * @see GlobalRouter::GetRouterId ()
+ * @see GlobalRouting::GetRouterId ()
  */
   void SetAdvertisingRouter (Ipv4Address  rtr);
 
 /**
+ * @brief For a Network LSA, set the Network Mask field that precedes
+ * the list of attached routers.
+ */
+  void SetNetworkLSANetworkMask (Ipv4Mask mask);
+
+/**
+ * @brief For a Network LSA, get the Network Mask field that precedes
+ * the list of attached routers.
+ * 
+ * @returns the NetworkLSANetworkMask 
+ */
+  Ipv4Mask GetNetworkLSANetworkMask (void) const;
+
+/**
+ * @brief Add an attached router to the list in the NetworkLSA
+ *
+ * @param address The Ipv4Address of the interface on the network link
+ * @returns The number of addresses in the list.
+ */
+  uint32_t AddAttachedRouter (Ipv4Address addr);
+
+/**
+ * @brief Return the number of attached routers listed in the NetworkLSA
+ *
+ * @returns The number of attached routers.
+ */
+  uint32_t GetNAttachedRouters (void) const;
+
+/**
+ * @brief Return an Ipv4Address corresponding to the specified attached router
+ *
+ * @param n The attached router number desired (number in the list).
+ * @returns The Ipv4Address of the requested router
+ */
+  Ipv4Address GetAttachedRouter (uint32_t n) const;
+
+/**
  * @brief Get the SPF status of the advertisement.
  *
  * @see SPFStatus
@@ -411,11 +468,16 @@
 
 private:
 /**
+ * The type of the LSA.  Each LSA type has a separate advertisement
+ * format.
+ */
+  LSType m_lsType;
+/**
  * The Link State ID is defined by the OSPF spec.  We always set it to the
  * router ID of the router making the advertisement.
  *
  * @see RoutingEnvironment::AllocateRouterId ()
- * @see GlobalRouter::GetRouterId ()
+ * @see GlobalRouting::GetRouterId ()
  */
   Ipv4Address  m_linkStateId;
 
@@ -424,14 +486,14 @@
  * the router ID of the router making the advertisement.
  *
  * @see RoutingEnvironment::AllocateRouterId ()
- * @see GlobalRouter::GetRouterId ()
+ * @see GlobalRouting::GetRouterId ()
  */
   Ipv4Address  m_advertisingRtr;
 
 /**
  * A convenience typedef to avoid too much writers cramp.
  */
-  typedef std::list<GlobalRouterLinkRecord*> ListOfLinkRecords_t;
+  typedef std::list<GlobalRoutingLinkRecord*> ListOfLinkRecords_t;
 
 /**
  * Each Link State Advertisement contains a number of Link Records that
@@ -441,11 +503,31 @@
  * m_linkRecords is an STL list container to hold the Link Records that have
  * been discovered and prepared for the advertisement.
  *
- * @see GlobalRouter::DiscoverLSAs ()
+ * @see GlobalRouting::DiscoverLSAs ()
  */
   ListOfLinkRecords_t m_linkRecords;
 
 /**
+ * Each Network LSA contains the network mask of the attached network
+ */
+  Ipv4Mask m_networkLSANetworkMask;
+
+/**
+ * A convenience typedef to avoid too much writers cramp.
+ */
+  typedef std::list<Ipv4Address> ListOfAttachedRouters_t;
+
+/**
+ * Each Network LSA contains a list of attached routers
+ *
+ * m_attachedRouters is an STL list container to hold the addresses that have
+ * been discovered and prepared for the advertisement.
+ *
+ * @see GlobalRouting::DiscoverLSAs ()
+ */
+  ListOfAttachedRouters_t m_attachedRouters;
+
+/**
  * This is a tristate flag used internally in the SPF computation to mark
  * if an SPFVertex (a data structure representing a vertex in the SPF tree
  * -- a router) is new, is a candidate for a shortest path, or is in its
@@ -454,7 +536,7 @@
   SPFStatus m_status;
 };
 
-std::ostream& operator<< (std::ostream& os, GlobalRouterLSA& lsa);
+std::ostream& operator<< (std::ostream& os, GlobalRoutingLSA& lsa);
 
 /**
  * @brief An interface aggregated to a node to provide global routing info
@@ -496,7 +578,7 @@
 
 /**
  * @brief Walk the connected channels, discover the adjacent routers and build
- * the associated number of Global Router Link State Advertisements that 
+ * the associated number of Global Routing Link State Advertisements that 
  * this router can export.
  *
  * This is a fairly expensive operation in that every time it is called
@@ -507,14 +589,14 @@
  * advertisements after a network topology change by calling DiscoverLSAs 
  * and then by reading those advertisements.
  *
- * @see GlobalRouterLSA
+ * @see GlobalRoutingLSA
  * @see GlobalRouter::GetLSA ()
- * @returns The number of Global Router Link State Advertisements.
+ * @returns The number of Global Routing Link State Advertisements.
  */
   uint32_t DiscoverLSAs (void);
 
 /**
- * @brief Get the Number of Global Router Link State Advertisements that this
+ * @brief Get the Number of Global Routing Link State Advertisements that this
  * router can export.
  *
  * To get meaningful information you must have previously called DiscoverLSAs.
@@ -522,19 +604,19 @@
  * GetLSA () to retrieve the actual advertisement.
  *
  * @see GlobalRouterLSA
- * @see GlobalRouter::DiscoverLSAs ()
- * @see GlobalRouter::GetLSA ()
- * @returns The number of Global Router Link State Advertisements.
+ * @see GlobalRouting::DiscoverLSAs ()
+ * @see GlobalRouting::GetLSA ()
+ * @returns The number of Global Routing Link State Advertisements.
  */
   uint32_t GetNumLSAs (void) const;
 
 /**
- * @brief Get a Global Router Link State Advertisements that this router has 
+ * @brief Get a Global Routing Link State Advertisements that this router has 
  * said that it can export.
  *
  * This is a fairly inexpensive expensive operation in that the hard work
- * was done in GetNumLSAs.  We just copy the indicated Global Router Link
- * State Advertisement into the requested GlobalRouterLSA object.
+ * was done in GetNumLSAs.  We just copy the indicated Global Routing Link
+ * State Advertisement into the requested GlobalRoutingLSA object.
  *
  * You must call GlobalRouter::GetNumLSAs before calling this method in 
  * order to discover the adjacent routers and build the advertisements.
@@ -542,13 +624,13 @@
  * The parameter n (requested LSA number) must be in the range 0 to 
  * GetNumLSAs() - 1.
  *
- * @see GlobalRouterLSA
- * @see GlobalRouter::GetNumLSAs ()
+ * @see GlobalRoutingLSA
+ * @see GlobalRouting::GetNumLSAs ()
  * @param n The index number of the LSA you want to read.
- * @param lsa The GlobalRouterLSA class to receive the LSA information.
+ * @param lsa The GlobalRoutingLSA class to receive the LSA information.
  * @returns The number of Global Router Link State Advertisements.
  */
-  bool GetLSA (uint32_t n, GlobalRouterLSA &lsa) const;
+  bool GetLSA (uint32_t n, GlobalRoutingLSA &lsa) const;
 
 private:
   virtual ~GlobalRouter ();
@@ -556,10 +638,12 @@
 
   Ptr<NetDevice> GetAdjacent(Ptr<NetDevice> nd, Ptr<Channel> ch) const;
   uint32_t FindIfIndexForDevice(Ptr<Node> node, Ptr<NetDevice> nd) const;
+  Ipv4Address FindDesignatedRouterForLink (Ptr<Node> node,   
+    Ptr<NetDevice> ndLocal) const;
 
   Ptr<Node>     m_node;
 
-  typedef std::list<GlobalRouterLSA*> ListOfLSAs_t;
+  typedef std::list<GlobalRoutingLSA*> ListOfLSAs_t;
   ListOfLSAs_t m_LSAs;
 
   Ipv4Address m_routerId;