calcdest.cc

Go to the documentation of this file.
00001 extern "C" {
00002 #include <assert.h>
00003 #include <fcntl.h>
00004 #include <math.h>
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <string.h>
00008 #include <sys/time.h>
00009 #include <sys/types.h>
00010 #include <sys/uio.h>
00011 #include <unistd.h>
00012 /* #include <err.h>*/
00013 };
00014 #include "../../../tools/rng.h"
00015 #include "setdest.h"
00016 
00017 //#define       DEBUG
00018 #define     SANITY_CHECKS
00019 //#define       SHOW_SYMMETRIC_PAIRS
00020 
00021 
00022 #define GOD_FORMAT  "$ns_ at %.12f \"$god_ set-dist %d %d %d\"\n"
00023 #define GOD_FORMAT2 "$god_ set-dist %d %d %d\n"
00024 #define NODE_FORMAT "$ns_ at %.12f \"$node_(%d) setdest %.12f %.12f %.12f\"\n"
00025 #define NODE_FORMAT2    "$node_(%d) setdest %.12f %.12f %.12f\n"
00026 #define NODE_FORMAT3    "$node_(%d) set %c_ %.12f\n"
00027 
00028 #undef      INFINITY
00029 #define     INFINITY    0x00ffffff
00030 #define     min(x,y)    ((x) < (y) ? (x) : (y))
00031 #define     max(x,y)    ((x) > (y) ? (x) : (y))
00032 #define     ROUND_ERROR 1e-9
00033 
00034 static int count = 0;
00035 
00036 /* ======================================================================
00037    Function Prototypes
00038    ====================================================================== */
00039 void        usage(char**);
00040 void        init(void);
00041 double      uniform(void);
00042 
00043 void        dumpall(void);
00044 void        ComputeW(void);
00045 void        floyd_warshall(void);
00046 
00047 void        show_diffs(void);
00048 void        show_routes(void);
00049 void        show_counters(void);
00050 
00051 
00052 /* ======================================================================
00053    Global Variables
00054    ====================================================================== */
00055 double          RANGE = 250.0;      // transmitter range in meters
00056 double      TIME = 0.0;     // my clock;
00057 double      MAXTIME = 0.0;      // duration of simulation
00058 
00059 double      MAXX = 0.0;
00060 double      MAXY = 0.0;
00061 double      MAXSPEED = 0.0;
00062 double      PAUSE = 0.0;
00063 u_int32_t   NODES = 0;
00064 u_int32_t   RouteChangeCount = 0;
00065 u_int32_t       LinkChangeCount = 0;
00066 u_int32_t   DestUnreachableCount = 0;
00067 
00068 Node        *NodeList = 0;
00069 u_int32_t   *D1 = 0;
00070 u_int32_t   *D2 = 0;
00071 
00072 FILE            *in_file;
00073 FILE            *out_file;
00074 
00075 
00076 /* ======================================================================
00077    Random Number Generation
00078    ====================================================================== */
00079 #define M       2147483647L
00080 #define INVERSE_M   ((double)4.656612875e-10)
00081 
00082 char random_state[32];
00083 RNG *rng;
00084 
00085 double
00086 uniform()
00087 {
00088     count++;
00089     return rng->uniform_double();
00090 }
00091 
00092 
00093 /* ======================================================================
00094    Misc Functions...
00095    ====================================================================== */
00096 void
00097 usage(char **argv)
00098 {
00099     fprintf(stderr,
00100         "\nusage: %s\t[-n <nodes>] \n",
00101         argv[0]);
00102     fprintf(stderr,
00103         "\t\t[-t <simulation time>]\n");
00104     fprintf(stderr,
00105         "\t\t-i <input_file> -o <output file>\n");
00106     fprintf(stderr,
00107 "\t\t #nodes, max time, and range read from scenario file if possible\n\n");
00108     
00109 }
00110 
00111 void
00112 init()
00113 {
00114     /*
00115      * Initialized the Random Number Generation
00116      */
00117 
00118     /*
00119      * Allocate memory for globals
00120      */
00121     NodeList = new Node[NODES];
00122     if(NodeList == 0) {
00123         perror("new");
00124         exit(1);
00125     }
00126 
00127     D1 = new u_int32_t[NODES * NODES];
00128     if(D1 == 0) {
00129         perror("new");
00130         exit(1);
00131     }
00132     memset(D1, '\xff', sizeof(u_int32_t) * NODES * NODES);
00133 
00134     D2 = new u_int32_t[NODES * NODES];
00135     if(D2 == 0) {
00136         perror("new");
00137         exit(1);
00138     }
00139     memset(D2, '\xff', sizeof(u_int32_t) * NODES * NODES);
00140 }
00141 
00142 void
00143 OpenAndReadHeader(char *in_filename, char *out_filename)
00144   /* assumes all initialization comments are at top of file with no
00145      no lines that start with other than '#' */
00146 {
00147   char buf[256];
00148   
00149   in_file = fopen(in_filename,"r");
00150   out_file = fopen(out_filename,"w");
00151   
00152   if (NULL == in_file) 
00153     fprintf(stderr, "*** can't open inputfile %s",in_filename);
00154   if (NULL == out_file) 
00155     fprintf(stderr,"can't open outputfile %s",out_filename);
00156   
00157   while (!feof(in_file)) {
00158 
00159     *buf = fgetc(in_file);
00160     ungetc(*buf,in_file);
00161     if (*buf != '#') break;
00162 
00163     fgets(buf, sizeof(buf), in_file);
00164 
00165     /* check to see if we need data from the line */
00166     sscanf(buf, "# nodes: %d, max time: %lf", &NODES, &MAXTIME);
00167     sscanf(buf, "# nominal range: %lf", &RANGE);
00168     
00169     fprintf(out_file, "%s", buf);
00170   }
00171   NODES += 1;           // correct for 1-based indexs
00172   fflush(out_file);
00173 }
00174 
00175 void
00176 ReadInMovementPattern()
00177 {
00178   char buf[256];
00179   u_int n;
00180   double x,y,z,t,s;
00181   struct setdest *setdest;
00182 
00183   while (!feof(in_file)) {
00184 
00185     fgets(buf, sizeof(buf), in_file);
00186     fprintf(out_file, "%s", buf);
00187     if (*buf == '#') continue;
00188     if (*buf == '\n') continue;
00189 
00190     /* check to see if we need data from the line */
00191     if (2 == sscanf(buf,"$node_(%d) set Z_ %lf", &n, &z)) 
00192       {
00193     assert(n < NODES);
00194     NodeList[n].position.Z = z;
00195       }
00196     else if (2 == sscanf(buf,"$node_(%d) set X_ %lf", &n, &x)) 
00197       {
00198     assert(n < NODES);
00199     NodeList[n].position.X = x;
00200       }
00201     else if (2 == sscanf(buf,"$node_(%d) set Y_ %lf", &n, &y)) 
00202       {
00203     assert(n < NODES);
00204     NodeList[n].position.Y = y;
00205       }
00206     else if (5 == sscanf(buf,"$ns_ at %lf \"$node_(%d) setdest %lf %lf %lf\"", 
00207             &t, &n, &x, &y, &s)) 
00208       {
00209     assert(n < NODES);
00210     assert(t <= MAXTIME);
00211     setdest = (struct setdest *)malloc(sizeof(*setdest));
00212     assert(setdest);
00213     setdest->X = x; setdest->Y = y; setdest->Z = 0;
00214     setdest->time = t;
00215     setdest->speed = s;
00216     if (NodeList[n].traj.lh_first 
00217         && t > NodeList[n].traj.lh_first->time)
00218       {
00219         printf("setdest's must be in anti-chronological order in input file!\n");
00220         printf("failed on node %d\n",n);
00221         exit(-1);
00222       }
00223     LIST_INSERT_HEAD(&NodeList[n].traj,setdest,traj);
00224       }
00225     else 
00226       {
00227     printf("unparsable line: '%s'", buf);
00228     continue;
00229       }
00230   }  
00231   fflush(out_file);  
00232 }
00233 
00234 extern "C" char *optarg;
00235 int
00236 main(int argc, char **argv)
00237 {
00238     char ch;
00239     char *in_filename = NULL;
00240     char *out_filename = NULL;
00241 
00242     while ((ch = getopt(argc, argv, "n:t:i:o:")) != EOF) {       
00243 
00244         switch (ch) { 
00245 
00246         case 'n':
00247             NODES = atoi(optarg) + 1;
00248             break;
00249 
00250         case 't':
00251             MAXTIME = atof(optarg);
00252             break;
00253     
00254         case 'i':
00255             in_filename = optarg;
00256             break;
00257 
00258         case 'o':
00259             out_filename = optarg;
00260             break;
00261 
00262         default:
00263             usage(argv);
00264             exit(1);
00265         }
00266     }
00267 
00268     if (NULL == in_filename || NULL == out_filename) {
00269             usage(argv);
00270         exit(1);
00271     }
00272 
00273     OpenAndReadHeader(in_filename, out_filename);
00274 
00275     if(NODES == 0 || MAXTIME == 0.0) {
00276         usage(argv);
00277         exit(1);
00278     }
00279     // A more portable solution for random number generation
00280         rng = new RNG;
00281         rng->set_seed(RNG::HEURISTIC_SEED_SOURCE); 
00282     init();
00283 
00284     ReadInMovementPattern();
00285 
00286     while(TIME <= MAXTIME) {
00287         double nexttime = 0.0;
00288         u_int32_t i;
00289 
00290         for(i = 1; i < NODES; i++) {
00291             NodeList[i].Update();
00292         }
00293 
00294         for(i = 1; i < NODES; i++) {
00295             NodeList[i].UpdateNeighbors();
00296         }
00297 
00298         for(i = 1; i < NODES; i++) {
00299             Node *n = &NodeList[i];
00300     
00301             if(n->time_transition > 0.0) {
00302                 if(nexttime == 0.0)
00303                     nexttime = n->time_transition;
00304                 else
00305                     nexttime = min(nexttime, n->time_transition);
00306             }
00307 
00308             if(n->time_arrival > 0.0) {
00309                 if(nexttime == 0.0)
00310                     nexttime = n->time_arrival;
00311                 else
00312                     nexttime = min(nexttime, n->time_arrival);
00313             }
00314         }
00315 
00316         floyd_warshall();
00317 
00318 #ifdef DEBUG
00319         show_routes();
00320 #endif
00321 
00322         show_diffs();
00323 
00324 #ifdef DEBUG
00325         dumpall();
00326 #endif
00327 
00328         if (nexttime <= TIME + ROUND_ERROR) 
00329           TIME = MAXTIME + 1;   /* we're done */
00330         else 
00331           TIME = nexttime;
00332 #ifdef OLD
00333         assert(nexttime > TIME + ROUND_ERROR);
00334         TIME = nexttime;
00335 #endif
00336 
00337     }
00338 
00339     show_counters();
00340 
00341     int of;
00342     if ((of = open(".rand_state",O_WRONLY | O_TRUNC | O_CREAT, 0777)) < 0)
00343       fprintf(stderr,"open rand state");
00344     for (unsigned int i = 0; i < sizeof(random_state); i++)
00345       random_state[i] = 0xff & (int) (uniform() * 256);
00346     if (write(of,random_state, sizeof(random_state)) < 0)
00347       fprintf(stderr,"writing rand state");
00348     close(of);
00349 }
00350 
00351 
00352 /* ======================================================================
00353    Node Class Functions
00354    ====================================================================== */
00355 u_int32_t Node::NodeIndex = 0;
00356 
00357 Node::Node()
00358 {
00359     u_int32_t i;
00360 
00361     index = NodeIndex++;
00362 
00363     if(index == 0)
00364         return;
00365 
00366     route_changes = 0;
00367         link_changes = 0;
00368 
00369         /*
00370          * For the first PAUSE seconds of the simulation, all nodes
00371          * are stationary.
00372          */
00373     time_arrival = TIME;
00374     time_update = TIME;
00375     time_transition = 0.0;
00376 
00377     position.X = position.Y = position.Z = 0.0;
00378     destination.X = destination.Y = destination.Z = 0.0;
00379     direction.X = direction.Y = direction.Z = 0.0;
00380     speed = 0.0;
00381 
00382     neighbor = new Neighbor[NODES];
00383     if(neighbor == 0) {
00384         perror("new");
00385         exit(1);
00386     }
00387 
00388     LIST_INIT(&traj);
00389 
00390     for(i = 1; i < NODES; i++) {
00391         neighbor[i].index = i;
00392         neighbor[i].reachable = (index == i) ? 1 : 0;
00393         neighbor[i].time_transition = 0.0;
00394     }
00395 }
00396 
00397 
00398 
00399 void
00400 Node::RandomPosition()
00401 {
00402     position.X = uniform() * MAXX;
00403     position.Y = uniform() * MAXY;
00404     position.Z = 0.0;
00405 }
00406 
00407 
00408 void
00409 Node::RandomDestination()
00410 {
00411     destination.X = uniform() * MAXX;
00412     destination.Y = uniform() * MAXY;
00413     destination.Z = 0.0;
00414     assert(destination != position);
00415 }
00416 
00417 void
00418 Node::RandomSpeed()
00419 {
00420     speed = uniform() * MAXSPEED;
00421 
00422     assert(speed != 0.0);
00423 }
00424 
00425 
00426 void
00427 Node::Update()
00428 {
00429         struct setdest *setdest = traj.lh_first;
00430 
00431     position += (speed * (TIME - time_update)) * direction;
00432 
00433     if(TIME == time_arrival) {
00434 
00435       if (NULL == setdest) 
00436         {
00437           destination = position;
00438           direction.X = direction.Y = direction.Z = 0.0;
00439           speed = 0.0;
00440           time_arrival = MAXTIME + 1;
00441         } 
00442       else 
00443         {
00444           vector v;
00445           destination.X = setdest->X;
00446           destination.Y = setdest->Y;
00447           speed = setdest->speed;
00448           if (0.0 == speed)
00449         { // it's a pause at the current location
00450           if (LIST_NEXT(setdest,traj))
00451             time_arrival = LIST_NEXT(setdest,traj)->time;
00452           else
00453             time_arrival = MAXTIME + 1;
00454         }
00455           else 
00456         { // we're moving somewhere, when do we get there?
00457           v = destination - position;
00458           direction = v / v.length();
00459           time_arrival = TIME + v.length() / speed;
00460         }
00461           LIST_REMOVE(setdest,traj);
00462           free(setdest);
00463         }
00464     }
00465 
00466     time_update = TIME;
00467     time_transition = 0.0;
00468 }
00469 
00470 
00471 void
00472 Node::UpdateNeighbors()
00473 {
00474     static Node *n2;
00475     static Neighbor *m1, *m2;
00476     static vector D, B, v1, v2;
00477     static double a, b, c, t1, t2, Q;
00478     static u_int32_t i, reachable;
00479 
00480     v1 = speed * direction;
00481 
00482     /*
00483      *  Only need to go from INDEX --> N for each one since links
00484      *  are symmetric.
00485      */
00486     for(i = index+1; i < NODES; i++) {
00487 
00488         m1 = &neighbor[i];
00489         n2 = &NodeList[i];
00490         m2 = &n2->neighbor[index];
00491 
00492         assert(i == m1->index);
00493         assert(m1->index == n2->index);
00494         assert(index == m2->index);
00495                 assert(m1->reachable == m2->reachable);
00496 
00497                 reachable = m1->reachable;
00498 
00499         /* ==================================================
00500            Determine Reachability
00501            ================================================== */
00502         {   vector d = position - n2->position;
00503 
00504             if(d.length() < RANGE) {
00505 #ifdef SANITY_CHECKS
00506                 if(TIME > 0.0 && m1->reachable == 0)
00507                     assert(RANGE - d.length() < ROUND_ERROR);
00508 #endif
00509                 m1->reachable = m2->reachable = 1;
00510             }
00511             // Boundary condition handled below.
00512             else {
00513 #ifdef SANITY_CHECKS
00514                 if(TIME > 0.0 && m1->reachable == 1)
00515                     assert(d.length() - RANGE < ROUND_ERROR);
00516 #endif
00517                 m1->reachable = m2->reachable = 0;
00518             }
00519 #ifdef DEBUG
00520                         fprintf(stdout, "# %.6f (%d, %d) %.2fm\n",
00521                                 TIME, index, m1->index, d.length());
00522 #endif
00523         }
00524 
00525         /* ==================================================
00526            Determine Next Event Time
00527            ================================================== */
00528         v2 = n2->speed * n2->direction;
00529 
00530         D = v2 - v1;
00531         B = n2->position - position;
00532 
00533         a = (D.X * D.X) + (D.Y * D.Y) + (D.Z * D.Z);
00534         b = 2 * ((D.X * B.X) + (D.Y * B.Y) + (D.Z * B.Z));
00535         c = (B.X * B.X) + (B.Y * B.Y) + (B.Z * B.Z) - (RANGE * RANGE);
00536 
00537         if(a == 0.0) {
00538             /*
00539              *  No Finite Solution
00540              */
00541             m1->time_transition= 0.0;
00542             m2->time_transition= 0.0;
00543             goto  next;
00544         }
00545 
00546         Q = b * b - 4 * a * c;
00547         if(Q < 0.0) {
00548             /*
00549              *  No real roots.
00550              */
00551             m1->time_transition = 0.0;
00552             m2->time_transition = 0.0;
00553             goto next;
00554         }
00555         Q = sqrt(Q);
00556 
00557         t1 = (-b + Q) / (2 * a);
00558         t2 = (-b - Q) / (2 * a);
00559 
00560         // Stupid Rounding/Boundary Cases
00561         if(t1 > 0.0 && t1 < ROUND_ERROR) t1 = 0.0;
00562         if(t1 < 0.0 && -t1 < ROUND_ERROR) t1 = 0.0;
00563         if(t2 > 0.0 && t2 < ROUND_ERROR) t2 = 0.0;
00564         if(t2 < 0.0 && -t2 < ROUND_ERROR) t2 = 0.0;
00565 
00566         if(t1 < 0.0 && t2 < 0.0) {
00567             /*
00568              *  No "future" time solution.
00569              */
00570             m1->time_transition = 0.0;
00571             m2->time_transition = 0.0;
00572             goto next;
00573         }
00574 
00575         /*
00576          * Boundary conditions.
00577          */
00578         if((t1 == 0.0 && t2 > 0.0) || (t2 == 0.0 && t1 > 0.0)) {
00579             m1->reachable = m2->reachable = 1;
00580             m1->time_transition = m2->time_transition = TIME + max(t1, t2);
00581         }
00582         else if((t1 == 0.0 && t2 < 0.0) || (t2 == 0.0 && t1 < 0.0)) {
00583             m1->reachable = m2->reachable = 0;
00584             m1->time_transition = m2->time_transition = 0.0;
00585         }
00586 
00587         /*
00588          * Non-boundary conditions.
00589          */
00590         else if(t1 > 0.0 && t2 > 0.0) {
00591             m1->time_transition = TIME + min(t1, t2);
00592             m2->time_transition = TIME + min(t1, t2);
00593         }
00594         else if(t1 > 0.0) {
00595             m1->time_transition = TIME + t1;
00596             m2->time_transition = TIME + t1;
00597         }
00598         else {
00599             m1->time_transition = TIME + t2;
00600             m2->time_transition = TIME + t2;
00601         }
00602 
00603         /* ==================================================
00604            Update the transition times for both NODEs.
00605            ================================================== */
00606         if(time_transition == 0.0 || (m1->time_transition &&
00607            time_transition > m1->time_transition)) {
00608             time_transition = m1->time_transition;
00609         }
00610         if(n2->time_transition == 0.0 || (m2->time_transition &&
00611            n2->time_transition > m2->time_transition)) {
00612             n2->time_transition = m2->time_transition;
00613         }
00614         next:
00615                 if(reachable != m1->reachable && TIME > 0.0) {
00616                         LinkChangeCount++;
00617                         link_changes++;
00618                         n2->link_changes++;
00619                 }
00620     }
00621 }
00622 
00623 void
00624 Node::Dump()
00625 {
00626     Neighbor *m;
00627     u_int32_t i;
00628 
00629     fprintf(stdout,
00630         "Node: %d\tpos: (%.2f, %.2f, %.2f) dst: (%.2f, %.2f, %.2f)\n",
00631         index, position.X, position.Y, position.Z,
00632         destination.X, destination.Y, destination.Z);
00633     fprintf(stdout, "\tdir: (%.2f, %.2f, %.2f) speed: %.2f\n",
00634         direction.X, direction.Y, direction.Z, speed);
00635     fprintf(stdout, "\tArrival: %.2f, Update: %.2f, Transition: %.2f\n",
00636         time_arrival, time_update, time_transition);
00637 
00638     for(i = 1; i < NODES; i++) {
00639         m = &neighbor[i];
00640         fprintf(stdout, "\tNeighbor: %d (%lx), Reachable: %d, Transition Time: %.2f\n",
00641             m->index, (long) m, m->reachable, m->time_transition);
00642     }
00643 }
00644 
00645 
00646 /* ======================================================================
00647    Dijkstra's Shortest Path Algoritm
00648    ====================================================================== */
00649 void dumpall()
00650 {
00651     u_int32_t i;
00652 
00653     fprintf(stdout, "\nTime: %.2f\n", TIME);
00654 
00655     for(i = 1; i < NODES; i++) {
00656         NodeList[i].Dump();
00657     }
00658 }
00659 
00660 void
00661 ComputeW()
00662 {
00663     u_int32_t i, j;
00664     u_int32_t *W = D2;
00665 
00666     memset(W, '\xff', sizeof(int) * NODES * NODES);
00667 
00668     for(i = 1; i < NODES; i++) {
00669         for(j = i; j < NODES; j++) {
00670             Neighbor *m = &NodeList[i].neighbor[j];
00671             if(i == j)
00672                 W[i*NODES + j] = W[j*NODES + i] = 0;
00673             else
00674                 W[i*NODES + j] = W[j*NODES + i] = m->reachable ? 1 : INFINITY;  
00675         }
00676     }
00677 }
00678 
00679 void
00680 floyd_warshall()
00681 {
00682     u_int32_t i, j, k;
00683 
00684     ComputeW(); // the connectivity matrix
00685 
00686     for(i = 1; i < NODES; i++) {
00687         for(j = 1; j < NODES; j++) {
00688             for(k = 1; k < NODES; k++) {
00689                 D2[j*NODES + k] = min(D2[j*NODES + k], D2[j*NODES + i] + D2[i*NODES + k]);
00690             }
00691         }
00692     }
00693 
00694 #ifdef SANITY_CHECKS
00695     for(i = 1; i < NODES; i++)
00696         for(j = 1; j < NODES; j++) {
00697             assert(D2[i*NODES + j] == D2[j*NODES + i]);
00698             assert(D2[i*NODES + j] <= INFINITY);
00699         }
00700 #endif
00701 }
00702 
00703 
00704 /*
00705  *  Write the actual GOD entries to a TCL script.
00706  */
00707 void
00708 show_diffs()
00709 {
00710     u_int32_t i, j;
00711 
00712     for(i = 1; i < NODES; i++) {
00713         for(j = i + 1; j < NODES; j++) {
00714             if(D1[i*NODES + j] != D2[i*NODES + j]) {
00715 
00716                 if(D2[i*NODES + j] == INFINITY)
00717                     DestUnreachableCount++;
00718 
00719                                 if(TIME > 0.0) {
00720                                         RouteChangeCount++;
00721                                         NodeList[i].route_changes++;
00722                                         NodeList[j].route_changes++;
00723                                 }
00724 
00725                 if(TIME == 0.0) {
00726                     fprintf(out_file, GOD_FORMAT2,
00727                         i, j, D2[i*NODES + j]);
00728 #ifdef SHOW_SYMMETRIC_PAIRS
00729                     fprintf(out_file, GOD_FORMAT2,
00730                         j, i, D2[j*NODES + i]);
00731 #endif
00732                 }
00733                 else {
00734                     fprintf(out_file, GOD_FORMAT, 
00735                         TIME, i, j, D2[i*NODES + j]);
00736 #ifdef SHOW_SYMMETRIC_PAIRS
00737                     fprintf(out_file, GOD_FORMAT, 
00738                         TIME, j, i, D2[j*NODES + i]);
00739 #endif
00740                 }
00741             }
00742         }
00743     }
00744 
00745     memcpy(D1, D2, sizeof(int) * NODES * NODES);
00746 }
00747 
00748 
00749 void
00750 show_routes()
00751 {
00752     u_int32_t i, j;
00753 
00754     fprintf(stdout, "#\n# TIME: %.12f\n#\n", TIME);
00755     for(i = 1; i < NODES; i++) {
00756         fprintf(stdout, "# %2d) ", i);
00757         for(j = 1; j < NODES; j++)
00758             fprintf(stdout, "%3d ", D2[i*NODES + j] & 0xff);
00759         fprintf(stdout, "\n");
00760     }
00761     fprintf(stdout, "#\n");
00762 }
00763 
00764 void
00765 show_counters()
00766 {
00767     u_int32_t i;
00768 
00769     fprintf(out_file, "#\n# Destination Unreachables: %d\n#\n",
00770         DestUnreachableCount);
00771     fprintf(out_file, "# Route Changes: %d\n#\n", RouteChangeCount);
00772         fprintf(out_file, "# Link Changes: %d\n#\n", LinkChangeCount);
00773         fprintf(out_file, "# Node | Route Changes | Link Changes\n");
00774     for(i = 1; i < NODES; i++)
00775         fprintf(out_file, "# %4d |          %4d |         %4d\n",
00776                         i, NodeList[i].route_changes,
00777                         NodeList[i].link_changes);
00778     fprintf(out_file, "#\n");
00779 }
00780 

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