branch merge
authorTom Henderson <tomh@tomh.org>
Mon, 01 Dec 2008 21:33:52 -0800
changeset 3964 cb1f2beeee9c
parent 3963 8a40a7ab4744 (current diff)
parent 3961 a31b0b04a8ac (diff)
child 3965 1210035e1828
branch merge
src/internet-stack/ipv4-l3-protocol.cc
--- a/src/internet-stack/ipv4-l3-protocol.cc	Mon Dec 01 21:29:59 2008 -0800
+++ b/src/internet-stack/ipv4-l3-protocol.cc	Mon Dec 01 21:33:52 2008 -0800
@@ -522,8 +522,17 @@
       ipv4Interface = *i;
       if (ipv4Interface->GetDevice () == device)
         {
-          m_rxTrace (packet, index);
-          break;
+          if (ipv4Interface->IsUp ())
+            {
+              m_rxTrace (packet, index);
+              break;
+            } 
+          else
+            {
+              NS_LOG_LOGIC ("Dropping received packet-- interface is down");
+              m_dropTrace (packet);
+              return;
+            }
         }
       index++;
     }
@@ -1074,7 +1083,7 @@
   Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
   interface->SetDown ();
 
-  // Remove all routes that are going through this interface
+  // Remove all static routes that are going through this interface
   bool modified = true;
   while (modified)
     {
--- a/src/internet-stack/wscript	Mon Dec 01 21:29:59 2008 -0800
+++ b/src/internet-stack/wscript	Mon Dec 01 21:33:52 2008 -0800
@@ -131,6 +131,7 @@
         'ipv4-interface.cc',
         'ipv4-l3-protocol.cc',
         'ipv4-static-routing.cc',
+        'ipv4-global-routing.cc',
         'ipv4-end-point.cc',
         'udp-l4-protocol.cc',
         'tcp-l4-protocol.cc',
@@ -164,6 +165,7 @@
         'ipv4-interface.h',
         'ipv4-l3-protocol.h',
         'ipv4-static-routing.h',
+        'ipv4-global-routing.h',
         'icmpv4.h',
         ]
 
--- a/src/routing/global-routing/global-route-manager-impl.cc	Mon Dec 01 21:29:59 2008 -0800
+++ b/src/routing/global-routing/global-route-manager-impl.cc	Mon Dec 01 21:33:52 2008 -0800
@@ -30,6 +30,7 @@
 #include "ns3/log.h"
 #include "ns3/node-list.h"
 #include "ns3/ipv4.h"
+#include "ns3/ipv4-global-routing.h"
 #include "global-router-interface.h"
 #include "global-route-manager-impl.h"
 #include "candidate-queue.h"
@@ -52,7 +53,8 @@
   m_rootOif (SPF_INFINITY),
   m_nextHop ("0.0.0.0"),
   m_parent (0),
-  m_children ()
+  m_children (),
+  m_vertexProcessed (false)
 {
   NS_LOG_FUNCTION_NOARGS ();
 }
@@ -64,7 +66,8 @@
   m_rootOif (SPF_INFINITY),
   m_nextHop ("0.0.0.0"),
   m_parent (0),
-  m_children ()
+  m_children (),
+  m_vertexProcessed (false)
 {
   NS_LOG_FUNCTION_NOARGS ();
   if (lsa->GetLSType () == GlobalRoutingLSA::RouterLSA) 
@@ -226,6 +229,19 @@
   return m_children.size ();
 }
 
+void 
+SPFVertex::SetVertexProcessed (bool value)
+{
+  m_vertexProcessed = value;
+}
+
+bool 
+SPFVertex::IsVertexProcessed (void) const
+{
+  return m_vertexProcessed;
+}
+
+
 // ---------------------------------------------------------------------------
 //
 // GlobalRouteManagerLSDB Implementation
@@ -349,6 +365,35 @@
   m_lsdb = lsdb;
 }
 
+  void
+GlobalRouteManagerImpl::DeleteGlobalRoutes ()
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); i++)
+    {
+      Ptr<Node> node = *i;
+      Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
+      uint32_t j = 0;
+      uint32_t nRoutes = gr->GetNRoutes ();
+      NS_LOG_LOGIC ("Deleting " << gr->GetNRoutes ()<< " routes from node " << node->GetId ());
+      // Each time we delete route 0, the route index shifts downward
+      // We can delete all routes if we delete the route numbered 0
+      // nRoutes times
+      for (j = 0; j < nRoutes; j++)
+        {
+          NS_LOG_LOGIC ("Deleting global route " << j << " from node " << node->GetId ());
+          gr->RemoveRoute (0);        
+        }
+      NS_LOG_LOGIC ("Deleted " << j << " global routes from node "<< node->GetId ());
+    }
+  if (m_lsdb)
+    {
+      NS_LOG_LOGIC ("Deleting LSDB, creating new one");
+      delete m_lsdb;
+      m_lsdb = new GlobalRouteManagerLSDB ();
+    }
+}
+
 //
 // In order to build the routing database, we need at least one of the nodes
 // to participate as a router.  This is a convenience function that makes
@@ -362,11 +407,25 @@
   for (NodeList::Iterator i = NodeList::Begin (); i != NodeList::End (); i++)
     {
       Ptr<Node> node = *i;
-      NS_LOG_LOGIC ("Adding GlobalRouter interface to node " << 
-        node->GetId ());
+      NS_LOG_LOGIC ("Adding GlobalRouter interface to node " << node->GetId ());
 
       Ptr<GlobalRouter> globalRouter = CreateObject<GlobalRouter> ();
       node->AggregateObject (globalRouter);
+
+      NS_LOG_LOGIC ("Adding GlobalRouting Protocol to node " << node->GetId ());
+      Ptr<Ipv4GlobalRouting> globalRouting = CreateObject<Ipv4GlobalRouting> ();
+      // This is the object that will keep the global routes.  We insert it
+      // at slightly higher priority than static routing (which is at zero).
+      // This means that global routes (e.g. host routes) will be consulted
+      // before static routes
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): "
+        "GetObject for <Ipv4> interface failed");
+      // XXX make the below  priority value an attribute
+      ipv4->AddRoutingProtocol (globalRouting, 3);  
+      // Locally cache the globalRouting pointer; we'll need it later
+      // when we add routes
+      AddGlobalRoutingProtocol (node->GetId (), globalRouting);
     }
 }
 
@@ -382,6 +441,21 @@
 
       Ptr<GlobalRouter> globalRouter = CreateObject<GlobalRouter> ();
       node->AggregateObject (globalRouter);
+
+      NS_LOG_LOGIC ("Adding GlobalRouting Protocol to node " << node->GetId ());
+      Ptr<Ipv4GlobalRouting> globalRouting = CreateObject<Ipv4GlobalRouting> ();
+      // This is the object that will keep the global routes.  We insert it
+      // at slightly higher priority than static routing (which is at zero).
+      // This means that global routes (e.g. host routes) will be consulted
+      // before static routes
+      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
+      NS_ASSERT_MSG (ipv4, "GlobalRouteManagerImpl::SelectRouterNodes (): "
+        "GetObject for <Ipv4> interface failed");
+      // XXX make the below  priority value an attribute
+      ipv4->AddRoutingProtocol (globalRouting, 3);  
+      // Locally cache the globalRouting pointer; we'll need it later
+      // when we add routes
+      AddGlobalRoutingProtocol (node->GetId (), globalRouting);
     }
 }
 
@@ -1115,11 +1189,11 @@
 //
 // Iterate the algorithm by returning to Step 2 until there are no more
 // candidate vertices.
-//
-    }
-//
-// Second stage of SPF calculation procedure's  
-// NOTYET:  ospf_spf_process_stubs (area, area->spf, new_table);
+
+    }  // end for loop
+
+// Second stage of SPF calculation procedure  
+  SPFProcessStubs (m_spfroot);
 //
 // We're all done setting the routing information for the node at the root of
 // the SPF tree.  Delete all of the vertices and corresponding resources.  Go
@@ -1129,6 +1203,155 @@
   m_spfroot = 0;
 }
 
+// Processing logic from RFC 2328, page 166 and quagga ospf_spf_process_stubs ()
+// stub link records will exist for point-to-point interfaces and for
+// broadcast interfaces for which no neighboring router can be found
+void
+GlobalRouteManagerImpl::SPFProcessStubs (SPFVertex* v)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+  NS_LOG_LOGIC ("Processing stubs for " << v->GetVertexId ());
+  if (v->GetVertexType () == SPFVertex::VertexRouter)
+    {
+      GlobalRoutingLSA *rlsa = v->GetLSA ();
+      NS_LOG_LOGIC ("Processing router LSA with id " << rlsa->GetLinkStateId ());
+      for (uint32_t i = 0; i < rlsa->GetNLinkRecords (); i++)
+        {
+          NS_LOG_LOGIC ("Examining link " << i << " of " << 
+            v->GetVertexId () << "'s " <<
+            v->GetLSA ()->GetNLinkRecords () << " link records");
+          GlobalRoutingLinkRecord *l = v->GetLSA ()->GetLinkRecord (i);
+          if (l->GetLinkType () == GlobalRoutingLinkRecord::StubNetwork)
+            {
+              NS_LOG_LOGIC ("Found a Stub record to " << l->GetLinkId ());
+              SPFIntraAddStub (l, v);
+              continue;
+            }
+        }
+    }
+    for (uint32_t i = 0; i < v->GetNChildren (); i++)
+      {
+        if (!v->GetChild (i)->IsVertexProcessed ())
+          {
+            SPFProcessStubs (v->GetChild (i));
+            v->GetChild (i)->SetVertexProcessed (true);
+          }
+      }
+}
+
+// RFC2328 16.1. second stage. 
+void
+GlobalRouteManagerImpl::SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v)
+{
+  NS_LOG_FUNCTION_NOARGS ();
+
+  NS_ASSERT_MSG (m_spfroot, 
+    "GlobalRouteManagerImpl::SPFIntraAddStub (): Root pointer not set");
+
+  // XXX simplifed logic for the moment.  There are two cases to consider:
+  // 1) the stub network is on this router; do nothing for now
+  //    (already handled above)
+  // 2) the stub network is on a remote router, so I should use the
+  // same next hop that I use to get to vertex v
+  if (v->GetVertexId () == m_spfroot->GetVertexId ())
+    {
+      NS_LOG_LOGIC ("Stub is on local host: " << v->GetVertexId () << "; returning");
+      return;
+    }
+      NS_LOG_LOGIC ("Stub is on remote host: " << v->GetVertexId () << "; installing");
+//
+// 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_LOG_LOGIC ("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.
+//
+  NodeList::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->GetObject<GlobalRouter> ();
+
+      if (rtr == 0)
+        {
+          NS_LOG_LOGIC ("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_LOG_LOGIC ("Considering router " << rtr->GetRouterId ());
+
+      if (rtr->GetRouterId () == routerId)
+        {
+          NS_LOG_LOGIC ("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->GetObject<Ipv4> ();
+          NS_ASSERT_MSG (ipv4, 
+            "GlobalRouteManagerImpl::SPFIntraAddRouter (): "
+            "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::SPFIntraAddRouter (): "
+            "Expected valid LSA in SPFVertex* v");
+          //Address tempaddr = Address (l->GetLinkData);
+          Ipv4Mask tempmask ("255.255.255.0");
+          Ipv4Address tempip = l->GetLinkId ();
+          tempip = tempip.CombineMask (tempmask);
+
+          NS_LOG_LOGIC (" Node " << node->GetId () <<
+            " add route to " << tempip <<
+            " with mask " << tempmask <<
+            " using next hop " << v->GetNextHop () <<
+            " via interface " << v->GetOutgoingTypeId ());
+//
+// Here's why we did all of that work.  We're going to add a host route to the
+// host address found in the m_linkData field of the point-to-point link
+// record.  In the case of a point-to-point link, this is the local IP address
+// of the node connected to the link.  Each of these point-to-point links
+// will correspond to a local interface that has an IP address to which
+// the node at the root of the SPF tree can send packets.  The vertex <v> 
+// (corresponding to the node that has these links and interfaces) has 
+// an m_nextHop address precalculated for us that is the address to which the
+// root node should send packets to be forwarded to these IP addresses.
+// Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
+// which the packets should be send for forwarding.
+//
+          Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
+          NS_ASSERT (gr);
+          gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (), v->GetOutgoingTypeId ());
+          return;
+        } // if
+    } // for
+}
+
 //
 // Return the interface index corresponding to a given IP address
 // This is a wrapper around GetIfIndexByIpv4Address(), but we first
@@ -1289,6 +1512,8 @@
 // the local side of the point-to-point links found on the node described by
 // the vertex <v>.
 //
+          NS_LOG_LOGIC (" Node " << node->GetId () <<
+             " found " << nLinkRecords << " link records in LSA " << lsa << "with LinkStateId "<< lsa->GetLinkStateId ());
           for (uint32_t j = 0; j < nLinkRecords; ++j)
             {
 //
@@ -1317,7 +1542,9 @@
 // Similarly, the vertex <v> has an m_rootOif (outbound interface index) to
 // which the packets should be send for forwarding.
 //
-              ipv4->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (),
+              Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
+              NS_ASSERT (gr);
+              gr->AddHostRouteTo (lr->GetLinkData (), v->GetNextHop (),
                 v->GetOutgoingTypeId ());
             }
 //
@@ -1399,7 +1626,9 @@
           Ipv4Mask tempmask = lsa->GetNetworkLSANetworkMask ();
           Ipv4Address tempip = lsa->GetLinkStateId ();
           tempip = tempip.CombineMask (tempmask);
-          ipv4->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (),
+          Ptr<Ipv4GlobalRouting> gr = GetGlobalRoutingProtocol (node->GetId ());
+          NS_ASSERT (gr);
+          gr->AddNetworkRouteTo (tempip, tempmask, v->GetNextHop (),
             v->GetOutgoingTypeId ());
           NS_LOG_LOGIC ("Node " << node->GetId () <<
             " add network route to " << tempip <<
@@ -1427,6 +1656,29 @@
   v->GetParent ()->AddChild (v);
 }
 
+  void 
+GlobalRouteManagerImpl::AddGlobalRoutingProtocol (uint32_t nodeId, Ptr<Ipv4GlobalRouting> proto)
+{
+  NS_LOG_FUNCTION (nodeId);
+  m_routingProtocols.push_back
+    (std::pair<uint32_t, Ptr<Ipv4GlobalRouting> > (nodeId, proto));
+  m_routingProtocols.sort ();
+}
+
+  Ptr<Ipv4GlobalRouting>
+GlobalRouteManagerImpl::GetGlobalRoutingProtocol (uint32_t nodeId)
+{
+  for (Ipv4GlobalRoutingList::const_iterator rprotoIter = m_routingProtocols.begin (); rprotoIter != m_routingProtocols.end (); rprotoIter++)
+    {
+      if ((*rprotoIter).first == nodeId)
+        {
+          return (*rprotoIter).second;
+        }
+    }
+  return 0;
+}
+
+
 } // namespace ns3
 
 #ifdef RUN_SELF_TESTS
--- a/src/routing/global-routing/global-route-manager-impl.h	Mon Dec 01 21:29:59 2008 -0800
+++ b/src/routing/global-routing/global-route-manager-impl.h	Mon Dec 01 21:33:52 2008 -0800
@@ -37,6 +37,7 @@
 const uint32_t SPF_INFINITY = 0xffffffff;
 
 class CandidateQueue;
+class Ipv4GlobalRouting;
 
 /**
  * @brief Vertex used in shortest path first (SPF) computations. See RFC 2328,
@@ -546,6 +547,23 @@
  */
   uint32_t AddChild (SPFVertex* child);
 
+  /**
+   * @brief Set the value of the VertexProcessed flag
+   *
+   * Flag to note whether vertex has been processed in stage two of 
+   * SPF computation
+   * @param value boolean value to set the flag
+   */ 
+  void SetVertexProcessed (bool value);
+
+  /**
+   * @brief Check the value of the VertexProcessed flag
+   *
+   * Flag to note whether vertex has been processed in stage two of 
+   * SPF computation
+   * @returns value of underlying flag
+   */ 
+  bool IsVertexProcessed (void) const;
 private:
   VertexType m_vertexType;
   Ipv4Address m_vertexId;
@@ -556,6 +574,7 @@
   SPFVertex* m_parent;
   typedef std::list<SPFVertex*> ListOfSPFVertex_t;
   ListOfSPFVertex_t m_children;
+  bool m_vertexProcessed; 
 
 /**
  * @brief The SPFVertex copy construction is disallowed.  There's no need for
@@ -701,6 +720,16 @@
   GlobalRouteManagerImpl ();
   virtual ~GlobalRouteManagerImpl ();
 /**
+ * @brief Delete all static routes on all nodes that have a
+ * GlobalRouterInterface
+ *
+ * TODO:  separate manually assigned static routes from static routes that
+ * the global routing code injects, and only delete the latter
+ * @internal
+ *
+ */
+  virtual void DeleteGlobalRoutes ();
+/**
  * @brief Select which nodes in the system are to be router nodes and 
  * aggregate the appropriate interfaces onto those nodes.
  * @internal
@@ -760,6 +789,7 @@
   SPFVertex* m_spfroot;
   GlobalRouteManagerLSDB* m_lsdb;
   void SPFCalculate (Ipv4Address root);
+  void SPFProcessStubs (SPFVertex* v);
   void SPFNext (SPFVertex*, CandidateQueue&);
   int SPFNexthopCalculation (SPFVertex* v, SPFVertex* w, 
     GlobalRoutingLinkRecord* l, uint32_t distance);
@@ -768,8 +798,15 @@
     GlobalRoutingLinkRecord* prev_link);
   void SPFIntraAddRouter (SPFVertex* v);
   void SPFIntraAddTransit (SPFVertex* v);
+  void SPFIntraAddStub (GlobalRoutingLinkRecord *l, SPFVertex* v);
   uint32_t FindOutgoingTypeId (Ipv4Address a, 
     Ipv4Mask amask = Ipv4Mask("255.255.255.255"));
+
+  // Local cache of the Ipv4GlobalRouting objects, indexed by nodeId
+  typedef std::list< std::pair< uint32_t, Ptr<Ipv4GlobalRouting> > > Ipv4GlobalRoutingList;
+  void AddGlobalRoutingProtocol (uint32_t nodeId, Ptr<Ipv4GlobalRouting> proto);
+  Ptr<Ipv4GlobalRouting> GetGlobalRoutingProtocol (uint32_t nodeId);
+  Ipv4GlobalRoutingList m_routingProtocols;
 };
 
 } // namespace ns3
--- a/src/routing/global-routing/global-route-manager.cc	Mon Dec 01 21:29:59 2008 -0800
+++ b/src/routing/global-routing/global-route-manager.cc	Mon Dec 01 21:33:52 2008 -0800
@@ -50,6 +50,21 @@
 }
 
   void
+GlobalRouteManager::RecomputeRoutingTables ()
+{
+  DeleteGlobalRoutes ();
+  BuildGlobalRoutingDatabase ();
+  InitializeRoutes ();
+}
+
+  void
+GlobalRouteManager::DeleteGlobalRoutes ()
+{
+  SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
+    DeleteGlobalRoutes ();
+}
+
+  void
 GlobalRouteManager::SelectRouterNodes (void) 
 {
   SimulationSingleton<GlobalRouteManagerImpl>::Get ()->
--- a/src/routing/global-routing/global-route-manager.h	Mon Dec 01 21:29:59 2008 -0800
+++ b/src/routing/global-routing/global-route-manager.h	Mon Dec 01 21:33:52 2008 -0800
@@ -45,9 +45,11 @@
  * the nodes in the simulation.  Makes all nodes in the simulation into
  * routers.
  *
- * All this function does is call  BuildGlobalRoutingDatabase () and
+ * All this function does is call the three functions
+ * SelectRouterNodes (), BuildGlobalRoutingDatabase (), and
  * InitializeRoutes ().
  *
+ * @see SelectRouterNodes ();
  * @see BuildGlobalRoutingDatabase ();
  * @see InitializeRoutes ();
  */
@@ -58,20 +60,40 @@
  * the nodes in the simulation.  Makes the nodes in the provided container
  * into routers.
  *
- * All this function does is call  BuildGlobalRoutingDatabase () and
+ * All this function does is call the three functions
+ * SelectRouterNodes (), BuildGlobalRoutingDatabase (), and
  * InitializeRoutes ().
  *
+ * @see SelectRouterNodes (Node Container c);
  * @see BuildGlobalRoutingDatabase ();
  * @see InitializeRoutes ();
  */
   static void PopulateRoutingTables (NodeContainer c);
 
-/**
- * @brief Allocate a 32-bit router ID from monotonically increasing counter.
+ /**
+  *@brief Remove all routes that were previously installed in a prior call
+ * to either PopulateRoutingTables() or RecomputeRoutingTables(), and 
+ * add a new set of routes.  
+ * 
+ * This method does not change the set of nodes
+ * over which GlobalRouting is being used, but it will dynamically update
+ * its representation of the global topology before recomputing routes.
+ * Users must first call PopulateRoutingTables() and then may subsequently
+ * call RecomputeRoutingTables() at any later time in the simulation.
+ *
+ * @see DeleteGlobalRoutes ();
+ * @see BuildGlobalRoutingDatabase ();
+ * @see InitializeRoutes ();
  */
-  static uint32_t AllocateRouterId ();
+ static void RecomputeRoutingTables ();
 
-private:
+/**
+ * @brief Delete all static routes on all nodes that have a 
+ * GlobalRouterInterface
+ *
+ */
+  static void DeleteGlobalRoutes ();
+
 /**
  * @brief Select which nodes in the system are to be router nodes and 
  * aggregate the appropriate interfaces onto those nodes.
@@ -89,6 +111,13 @@
   static void SelectRouterNodes (NodeContainer c);
 
 /**
+ * @brief Allocate a 32-bit router ID from monotonically increasing counter.
+ */
+  static uint32_t AllocateRouterId ();
+
+private:
+
+/**
  * @brief Build the routing database by gathering Link State Advertisements
  * from each node exporting a GlobalRouter interface.
  * @internal
--- a/src/routing/global-routing/global-router-interface.cc	Mon Dec 01 21:29:59 2008 -0800
+++ b/src/routing/global-routing/global-router-interface.cc	Mon Dec 01 21:33:52 2008 -0800
@@ -413,23 +413,30 @@
 
           os << "---------- RouterLSA Link Record ----------" << std::endl;
           os << "m_linkType = " << p->m_linkType;
-          if (p->m_linkType == GlobalRoutingLinkRecord::TransitNetwork)
+          if (p->m_linkType == GlobalRoutingLinkRecord::PointToPoint)
+            {
+              os << " (GlobalRoutingLinkRecord::PointToPoint)" << std::endl;
+              os << "m_linkId = " << p->m_linkId << std::endl;
+              os << "m_linkData = " << p->m_linkData << std::endl;
+              os << "m_metric = " << p->m_metric << std::endl;
+            }
+          else if (p->m_linkType == GlobalRoutingLinkRecord::TransitNetwork)
             {
               os << " (GlobalRoutingLinkRecord::TransitNetwork)" << std::endl;
               os << "m_linkId = " << p->m_linkId << " (Designated router for network)" << std::endl;
               os << "m_linkData = " << p->m_linkData << " (This router's IP address)" << std::endl;
               os << "m_metric = " << p->m_metric << std::endl;
             }
-          else if (p->GetLinkType () == GlobalRoutingLinkRecord::StubNetwork)
+          else if (p->m_linkType == GlobalRoutingLinkRecord::StubNetwork)
             {
-              os << "(GlobalRoutingLinkRecord::StubNetwork)" << std::endl;
+              os << " (GlobalRoutingLinkRecord::StubNetwork)" << std::endl;
               os << "m_linkId = " << p->m_linkId << " (Network number of attached network)" << std::endl;
               os << "m_linkData = " << p->m_linkData << " (Network mask of attached network)" << std::endl;
               os << "m_metric = " << p->m_metric << std::endl;
             }
           else
             {
-              os << "(Unknown LinkType)" << std::endl;
+              os << " (Unknown LinkType)" << std::endl;
               os << "m_linkId = " << p->m_linkId << std::endl;
               os << "m_linkData = " << p->m_linkData << std::endl;
               os << "m_metric = " << p->m_metric << std::endl;
@@ -513,7 +520,7 @@
 
       *i = 0;
     }
-  NS_LOG_LOGIC ("Clear list");
+  NS_LOG_LOGIC ("Clear list of LSAs");
   m_LSAs.clear();
 }
 
@@ -599,9 +606,9 @@
       // IP addresses in routing.
       //
       bool isIp = false;
-      for (uint32_t i = 0; i < ipv4Local->GetNInterfaces (); ++i )
+      for (uint32_t j = 0; j < ipv4Local->GetNInterfaces (); ++j )
         {
-          if (ipv4Local->GetNetDevice (i) == ndLocal) 
+          if (ipv4Local->GetNetDevice (j) == ndLocal && ipv4Local->IsUp (j)) 
             {
               isIp = true;
               break;
@@ -621,7 +628,7 @@
       // the segment.  We add the appropriate link record to the LSA.
       //
       // If the device is a point to point link, we treat it separately.  In
-      // that case, there always two link records added.
+      // that case, there may be one or two link records added.
       //
       if (ndLocal->IsBroadcast () && !ndLocal->IsPointToPoint () )
         {
@@ -1020,15 +1027,22 @@
   // 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.
   //
-  GlobalRoutingLinkRecord *plr = new GlobalRoutingLinkRecord;
-  NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
-  plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
-  plr->SetLinkId (rtrIdRemote);
-  plr->SetLinkData (addrLocal);
-  plr->SetMetric (metricLocal);
-  pLSA->AddLinkRecord (plr);
-  plr = 0;
+  GlobalRoutingLinkRecord *plr;
+  if (ipv4Remote->IsUp (ifIndexRemote))
+    {
+      NS_LOG_LOGIC ("Remote side interface " << ifIndexRemote << " is up-- add a type 1 link");
+ 
+      plr  = new GlobalRoutingLinkRecord;
+      NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
+      plr->SetLinkType (GlobalRoutingLinkRecord::PointToPoint);
+      plr->SetLinkId (rtrIdRemote);
+      plr->SetLinkData (addrLocal);
+      plr->SetMetric (metricLocal);
+      pLSA->AddLinkRecord (plr);
+      plr = 0;
+    }
 
+  // Regardless of state of peer, add a type 3 link (RFC 2328: 12.4.1.1)
   plr = new GlobalRoutingLinkRecord;
   NS_ABORT_MSG_IF (plr == 0, "GlobalRouter::ProcessPointToPointLink(): Can't alloc link record");
   plr->SetLinkType (GlobalRoutingLinkRecord::StubNetwork);
@@ -1108,8 +1122,15 @@
             {
               Ptr<Ipv4> tempIpv4 = tempNode->GetObject<Ipv4> ();
               NS_ASSERT (tempIpv4);
-              Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex);
-              pLSA->AddAttachedRouter (tempAddr);
+              if (!tempIpv4->IsUp (tempIfIndex))
+                {
+                  NS_LOG_LOGIC ("Remote side interface " << tempIfIndex << " not up");
+                }
+              else 
+                {
+                  Ipv4Address tempAddr = tempIpv4->GetAddress(tempIfIndex);
+                  pLSA->AddAttachedRouter (tempAddr);
+                }
             }
         }
       m_LSAs.push_back (pLSA);
@@ -1180,6 +1201,11 @@
               if (FindIfIndexForDevice(nodeOther, bnd, ifIndexOther))
                 {
                   NS_LOG_LOGIC ("Found router on bridge net device " << bnd);
+                  if (!ipv4->IsUp (ifIndexOther))
+                    {
+                      NS_LOG_LOGIC ("Remote side interface " << ifIndexOther << " not up");
+                      continue;
+                    }
                   Ipv4Address addrOther = ipv4->GetAddress (ifIndexOther);
                   desigRtr = addrOther < desigRtr ? addrOther : desigRtr;
                   NS_LOG_LOGIC ("designated router now " << desigRtr);
@@ -1223,6 +1249,11 @@
               uint32_t ifIndexOther;
               if (FindIfIndexForDevice(nodeOther, ndOther, ifIndexOther))
                 {
+                  if (!ipv4->IsUp (ifIndexOther))
+                    {
+                      NS_LOG_LOGIC ("Remote side interface " << ifIndexOther << " not up");
+                      continue;
+                    }
                   NS_LOG_LOGIC ("Found router on net device " << ndOther);
                   Ipv4Address addrOther = ipv4->GetAddress (ifIndexOther);
                   desigRtr = addrOther < desigRtr ? addrOther : desigRtr;