nixnode.cc

Go to the documentation of this file.
00001 
00002 /*
00003  * nixnode.cc
00004  * Copyright (C) 2000 by the University of Southern California
00005  * $Id: nixnode.cc,v 1.9 2005/09/22 07:44:42 lacage Exp $
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License along
00017  * with this program; if not, write to the Free Software Foundation, Inc.,
00018  * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  *
00020  *
00021  * The copyright of this module includes the following
00022  * linking-with-specific-other-licenses addition:
00023  *
00024  * In addition, as a special exception, the copyright holders of
00025  * this module give you permission to combine (via static or
00026  * dynamic linking) this module with free software programs or
00027  * libraries that are released under the GNU LGPL and with code
00028  * included in the standard release of ns-2 under the Apache 2.0
00029  * license or under otherwise-compatible licenses with advertising
00030  * requirements (or modified versions of such code, with unchanged
00031  * license).  You may copy and distribute such a system following the
00032  * terms of the GNU GPL for this module and the licenses of the
00033  * other code concerned, provided that you include the source code of
00034  * that other code when and as the GNU GPL requires distribution of
00035  * source code.
00036  *
00037  * Note that people who make modified versions of this module
00038  * are not obligated to grant this special exception for their
00039  * modified versions; it is their choice whether to do so.  The GNU
00040  * General Public License gives permission to release a modified
00041  * version without this exception; this exception also makes it
00042  * possible to release a modified version which carries forward this
00043  * exception.
00044  *
00045  */
00046 
00047 /*
00048  * Nix-Vector routing capable node
00049  * contributed to ns from 
00050  * George F. Riley, Georgia Tech, Spring 2000
00051  *
00052  */
00053 
00054 #include "config.h"
00055 #ifdef HAVE_STL
00056 
00057 // STL includes
00058 #include <vector>
00059 
00060 #include "nix/nixnode.h"
00061 #include "routealgo/bfs.h"
00062 #include "nix/nixvec.h"
00063 #include "routealgo/routealgo.h"
00064 #include "nix/hdr_nv.h"
00065 
00066 static RNodeVec_t Nodes; // Vector of known nodes
00067 static int NVCount = 0;  // Number of nix vectors
00068 static Nixl_t NVMin = 0;    // Smallest nv
00069 static Nixl_t NVMax = 0;    // Largest nv
00070 static Nixl_t NVTot = 0;    // Total bitcount for all nv's (to compute avg)
00071 
00072 NixNode::NixNode() : RNode(), m_Map(-1), m_pNixVecs(0)
00073 {
00074     if(0)printf("Hello from NixNode Constructor\n");
00075   Nodes.push_back(this); // And save it
00076 
00077 }
00078 
00079 #ifdef MOVED_TO_NODE
00080 int NixNode::command(int argc, const char*const* argv)
00081 {
00082     if(0)printf("Hello from NixNode::Command argc %d argv[0] %s argv[1] %s\n", 
00083                  argc, argv[0], argv[1]);
00084   if (argc == 2)
00085     {
00086       Tcl& tcl = Tcl::instance();
00087       if(strcmp(argv[1], "address?") == 0)
00088                 {
00089                     tcl.resultf("%d", address_);
00090                     return TCL_OK;
00091                 }
00092       if(strcmp(argv[1], "report-id") == 0)
00093                 {
00094                     printf("Id is %ld\n", m_id);
00095                     return TCL_OK;
00096                 }
00097       if(strcmp(argv[1], "populate-objects") == 0)
00098                 {
00099                     PopulateObjects();
00100                     return TCL_OK;
00101                 }
00102     }
00103     if (argc == 3)
00104         {
00105       if (strcmp(argv[1], "get-nix-vector") == 0)
00106         {
00107                     GetNixVector(atol(argv[2]));
00108                     return TCL_OK;
00109                 }
00110       if (strcmp(argv[1], "set-neighbor") == 0)
00111         {
00112           if(0)printf("Setting neighbor node %ld neighbor %s\n",
00113                  m_id, argv[2]);
00114           AddAdj(atol(argv[2]));
00115           return(TCL_OK);
00116         }
00117       if (strcmp(argv[1], "map-to") == 0)
00118         {
00119           m_Map = atol(argv[2]);
00120           return(TCL_OK);
00121         }
00122         }
00123   return Node::command(argc,argv);
00124 }
00125 #endif
00126 
00127 void NixNode::AddAdj( // Add a new neighbor bit
00128     nodeid_t WhichN)
00129 {    
00130   Edge* pE;
00131 
00132   if (0)
00133     {
00134       printf("Node %ld adding neighbor %ld\n", m_id, WhichN);
00135       fflush(stdout);
00136     }
00137   pE= new Edge(WhichN);
00138   m_Adj.push_back(pE);
00139 }
00140 
00141 int NixNode::IsNeighbor( // TRUE neighbor bit set
00142     nodeid_t WhichN)
00143 {    
00144   for (EdgeVec_it i = m_Adj.begin(); i != m_Adj.end(); i++)
00145     {
00146       if ((*i)->m_n == WhichN) return(1); // Found it
00147     }
00148   return(0);
00149 }
00150 
00151 const NodeWeight_t NixNode::NextAdj( const NodeWeight_t& last)
00152 {
00153 Edge* pE;
00154 
00155   static EdgeVec_it prev;
00156   if (last.first == NODE_NONE)
00157     {
00158       prev = m_Adj.begin();
00159       if (prev == (EdgeVec_it) NULL) // ! How can this happen?
00160         return(NodeWeight_t(NODE_NONE, 0));
00161       pE = *prev;
00162       if(0)printf("NextAdj returning first edge %ld\n",
00163              pE->m_n);
00164       return(NodeWeight_t(pE->m_n, 1));
00165     }
00166   else
00167     { // See if last is prev
00168       if (last.first == (*prev)->m_n)
00169         { //Yep, just advance iterator
00170           prev++;
00171           if (prev == m_Adj.end())
00172             { // No more
00173               return(NodeWeight_t(NODE_NONE, 0));
00174             }
00175           else
00176             {
00177               pE = *prev;
00178               if(0)printf("NextAdj returning next edge %ld w %d\n",
00179                      pE->m_n, 1);
00180               return(NodeWeight_t(pE->m_n, 1));
00181             }
00182         }
00183       else
00184         { // Need to code this
00185           printf("Non-linear advance of NextAdj\n");
00186           exit(5);
00187         }
00188     }
00189 }
00190 
00191 NixVec* NixNode::ComputeNixVector(nodeid_t t)
00192 { // Compute the NixVector to a target
00193 RoutingVec_t Parent;
00194 RoutingVec_t NextHop;
00195 
00196   if(0)printf("Computing nixvector from %ld to %ld\n", m_id,  t); 
00197   BFS(Nodes, m_id, NextHop, Parent);
00198   NixVec* pNv = new NixVec;
00199   NixRoute(m_id, t, Parent, Nodes, *pNv);
00200   return pNv;
00201 }
00202 
00203 NixPair_t NixNode::GetNix(nodeid_t t)  // Get neighbor index/length
00204 {
00205   if(0)printf("Node %ld Getnix to target %ld, adjsize %lu\n",
00206          m_id, t, (unsigned long)m_Adj.size());
00207   Nixl_t l = GetNixl();
00208   for (unsigned long i = 0; i < m_Adj.size(); i++)
00209     {
00210       if(0)printf("Node %ld checking nb %ld\n", m_id, m_Adj[i]->m_n);
00211       if (m_Adj[i]->m_n == t)
00212         return(NixPair_t(i, l));  // Found it
00213     }
00214   return(NixPair_t(NIX_NONE, 0)); // Did not find it
00215 }
00216 
00217 Nixl_t NixNode::GetNixl()         // Get bits needed for nix entry
00218 {
00219   return NixVec::GetBitl(m_Adj.size() - 1);
00220 }
00221 
00222 nodeid_t NixNode::GetNeighbor( Nix_t n, NixVec* pNv)
00223 { // Reconstruct a neighbor from the neighbor index
00224     if (n >= m_Adj.size())
00225         { // Foulup of some sort, print stuff out and abort
00226             printf("Nix %ld out of range (0 - %lu\n", n, (unsigned long)m_Adj.size());
00227             pNv->DBDump();
00228             exit(0);
00229         }
00230   return(m_Adj[n]->m_n);
00231 }
00232 
00233 
00234 NsObject* NixNode::GetNsNeighbor(Nix_t n)   // Get the ns nexthop neighbor
00235 {
00236     if (n >= m_AdjObj.size()) return(NULL);   // Out of range
00237   return(m_AdjObj[n]);
00238 }
00239 
00240 NixVec* NixNode::GetNixVector(nodeid_t t) // Get a nix vector for a target
00241 {
00242 NVMap_it i;
00243 
00244  if (!m_pNixVecs)
00245      { // No current list
00246          m_pNixVecs = new NVMap_t;
00247      }
00248  
00249  i = m_pNixVecs->find(t);
00250  if (i == m_pNixVecs->end())
00251      { // Does not exist, compute it and add to the hash-map
00252          NixVec* pNv = ComputeNixVector(t);
00253          // Debug statistics follow
00254          if (NVCount == 0)
00255              { // First one
00256                  NVMin = pNv->ALth();
00257                  NVMax = pNv->ALth();
00258              }
00259          else
00260              {
00261                  NVMin = (pNv->ALth() < NVMin) ? pNv->ALth() : NVMin;
00262                  NVMax = (pNv->ALth() > NVMax) ? pNv->ALth() : NVMax;
00263              }
00264          NVCount++;
00265          NVTot += pNv->ALth();
00266          // End debug stats
00267 #ifdef TRY_DIFFERENT
00268          m_pNixVecs[(const nodeid_t)t] = (const NixVec const *)pNv;
00269 #else
00270          NVPair_t p = NVPair_t(t, pNv);
00271                  //const pair <const nodeid_t, NixVec*> p1 = new pair<const nodeid_t, NixVec*>(t,pNv);
00272          m_pNixVecs->insert(p);
00273 #endif
00274          pNv->Reset();
00275          // debug follows
00276 #ifdef DEBUG_VERBOSE        
00277          printf("Nixvec from %ld to %ld\n", m_id, t);
00278          pNv->DBDump();
00279 #endif
00280          return(pNv); // Return a the vector
00281      }
00282  (*i).second->Reset();
00283  return((*i).second); // Return the vector
00284 }
00285 
00286 void NixNode::PopulateObjects(void)
00287 {
00288 Edge*      pEdge;
00289 EdgeVec_it it;
00290 Tcl& tcl = Tcl::instance();
00291 
00292   for (it = m_Adj.begin(); it != m_Adj.end(); it++)
00293         {
00294             pEdge = *it;
00295             if(0)printf("Node %ld processing edge %ld\n", m_id, pEdge->m_n);
00296             tcl.evalf("[Simulator instance] get-link-head %d %d", m_id, pEdge->m_n);
00297             NsObject* pHead = (NsObject*)TclObject::lookup(tcl.result());
00298             if(0)printf("Found head at %s\n", pHead->name());
00299             m_AdjObj.push_back(pHead); // And add it to vector
00300             if(0)tcl.evalf("%s info class", pHead->name());
00301             if(0)printf("Class is %s\n", tcl.result());
00302         } 
00303 }
00304 
00305 // Static functions
00306 NixNode*   NixNode::GetNodeObject(nodeid_t n) // Get a node obj. based on id
00307 {
00308     if (n >= Nodes.size()) return(NULL); // Does not exist
00309     return((NixNode*)Nodes[n]);
00310 }
00311 
00312 void NixNode::PopulateAllObjects(void)
00313 {  // Called after $ns run, populates the next hop NS objects
00314 NixNode*    pN;
00315 RNodeVec_it it;
00316 
00317   for (it = Nodes.begin(); it != Nodes.end(); it++)
00318         {
00319             pN = (NixNode*)*it;
00320             pN->PopulateObjects();
00321         }
00322 }
00323 
00324 // Global function (debug only)
00325 void ReportNixStats()
00326 {
00327     printf("Total NV %d Min %ld Max %ld Avg %f\n", 
00328                  NVCount, NVMin, NVMax, (double)NVTot/(double)NVCount);
00329 }
00330 
00331 #endif /* STL */

Generated on Tue Mar 6 16:47:47 2007 for ns2 Network Simulator 2.29 by  doxygen 1.4.6