/* $Header: /server/users/students/chow/mci/netrestoreW/sparcsrc/RCS/fitness.c,v 1.2 1995/07/09 17:10:19 chow Exp chow $ */ /* Output from p2c, the Pascal-to-C translator */ /* From input file "fitprint.pas" */ /* This program is available for research only. For commercial use, please check * with chow@cs.uccs.edu. */ /* Project : NetRestore Algorithm Name : FITNESS Programmed by : Steve McCaughey Date : 14 July 1992 Version : 1.0 This program models the FITNESS digital network restoration algorithm using NETSIM and other library routines. Date - Initials - Description of Modification --------------------------------------------- Revision History: 14 Jul SCM Added comments & fixed minor errors re: SPREAD entry selection & CHOOSER T.O. calculation. Marked by ????. 5 Nov Chow replace assign by fopen; replace GetTime and GetDate; remove release(heap..) add _strings_init(); _netsim_init(); _math_init(); remove pc specific function ClrScr(); _randomize(); replace int2str_ it causes segmentation fault replace the format string form ld, lg to d, g. change work spare in linkdata from uchar to int to avoid alignment warning. replace the condition expr in event processing loop change the fields in tablerec from uchar to int save pick->hop in hopcount because the value got corrupted before new timeout value is calculated in Chooser. 6/10/93 Chow add transmission delay 7/11/95 Chow add repeat limit and additional parameter settings. */ #include #include #ifndef STRINGS_H #include "strings.h" #endif #ifndef NETSIM_H #include "netsim.h" #endif #ifndef LISTS_H #include "lists1.h" #endif #ifndef MATH_H #include "math.h" #endif #include /* #include */ /* Chow: needed for GetTime and GetDate */ /* Chow 4/28/2004 change to just time.h header file got relocated */ #define KMPERDEG 111.3194 /* km/deg */ #define LIGHTSPEED 299796.0 /* km/sec */ /* index of refraction for glass -- lightspeed / index = lightspeed in material */ /* link description */ typedef struct linkdata { long dest; boolean active; float delay; long work, spare; } linkdata; /* table data maintained by FITNESS algorithm */ typedef struct tablerec { long from; long hop, bw, connected; } tablerec; /* FITNESS node states */ typedef enum { IDLE, SENDER, SPREAD, CHOOSER } nodestates; /* node state information for fitness */ typedef struct node { long id; float time; list links; Char name[16]; float msg_process_delay; nodestates state; float lat, long_; long tofix; /* these down specific to FITNESS */ long wave; list table; long repeatlimit; } node; Static long maxrepeats = 13; /* to avoid looping */ Static boolean overwriteRL = false; Static float connectTime = 0.0; /* in sec */ Static boolean OVERWRITE_LINK_DISTANCE; Static long LINK_DISTANCE_IN_MILES = 0; /* 1 for link distance in miles 2 for link distance in km 0 for link distance field not used */ Static float NOISE_SIZE = 0.00001; /* multiplied by random 0..100 */ Static float PPTOVERRIDE = -1.0; static int PARALLEL_DCS = 0;/*default parallel DCS connection all in one batch*/ /* 1 for connecting one path at CROSS_CONNECT_TIME time */ /* k for connecting k paths at CROSS_CONNECT_TIME time */ Static int MSG_LENGTH = 8; /* assume fixed length 8 byte messages */ Static int TX_SPEED = 8; /* default transmission speed is 8 kbps */ Static float CROSS_CONNECT_TIME = 0.01; /*default DCS connection time 10msec*/ Static float transmit_delay = 0.0; Static float LINK_CHECK_SCALEFACTOR = 0.05; /* fraction of node msg process delay */ Static float TIMEOUT = 0.25; /* sec -- CHOOSER timeout value */ Static float STOP_TIME = 5.0; /* sec -- total run time of simulation */ Static uchar MAXHOPS = 3; /* not used! */ Static float REFRACINDEX = 1.5; Static boolean DEBUG = false; /* state display in via path printout */ Static Char statechar[4] = { ' ', ' ', ' ', ' ' }; Static erec *ee; Static long i, j; Static boolean SaveEvents; Static list net; Static long netsize; Static symbol_node *nodename; Static FILE *log_; Static Char pathlist[256]; Static node *nextnode; Static boolean stop; Static symbol_node *options; Static Char result[256]; Static Char outfilename[81], infilename[81]; Static long break1 = 0; Static long break2 = 0; Static Char break1str[21], break2str[21]; Static long path_count; Static boolean print_flag; Static long bw_needed, bw_found; Static long spare_used; Static long rstr_msg_count; Static long msg_count; Static float lastRestoreTime = 0.0; /* GetTime and GetDate probably are Turbo Pascal library routines */ /* replace that with the equivalent unix c library */ Void GetTime(hr, min, sec, csec) unsigned short hr, min, sec, csec; { struct timeval t; struct tm *local; /* note that tm_hour tm_min tm_sec are all int type, not short */ gettimeofday(&t, 0); local = localtime((time_t *)&t.tv_sec); hr = local->tm_hour; min = local->tm_min; sec = local->tm_sec; csec = t.tv_usec/10000L; } Void GetDate(yr, mon, day, dow) unsigned short yr, mon, day, dow; { struct timeval t; struct tm *local; gettimeofday(&t, 0); local = localtime((time_t *)&t.tv_sec); yr = local->tm_year; mon = local->tm_mon; day = local->tm_mday; dow = local->tm_wday; } tablerec *find_best_path(cnode) node *cnode; { long i, FORLIM; tablerec *pick, *entry_; /* find "best" path -- max BW, min HC */ pick = (tablerec *)head(&cnode->table); if (pick == NULL) return NULL; FORLIM = cnode->table.count; for (i = 1; i <= FORLIM; i++) { entry_ = (tablerec *)recall(&cnode->table, i); if (entry_->bw > pick->bw || entry_->bw == pick->bw && entry_->hop < pick->hop) pick = entry_; } return pick; } /* another version of find_best_path hc = 255; FORLIM = cnode->table.count; pick = NULL; for (i = 1; i <= FORLIM; i++) { entry_ = (tablerec *)recall(&cnode->table, i); if (entry_->bw >= bw && entry_->hop < hc) { pick = entry_; hc = pick->hop; } } if (pick == NULL) { j = 0; for (i = 1; i <= FORLIM; i++) { entry_ = (tablerec *)recall(&cnode->table, i); if (entry_->bw >= j && entry_->hop < hc) { pick = entry_; j = entry_->bw; hc = pick->hop; } } bw = j; if (pick == NULL) return; } */ long countSpare(path) Char *path; { long i; Char *p; i = 0; p = path; while (*p != 0) { if (*p == ' ') i++; p++; } return i; } Static Char *simtime2str(Result, v) Char *Result; float v; { Char s[256]; sprintf(s, "%8.5f", v); return strcpy(Result, s); } Static Char *int2str_(Result, i) Char *Result; long i; { Char s[6]; i %= 1000; sprintf(s, "%0.3ld", i); return strcpy(Result, s); } Static float noise() { /* avoid nonBSD system , should be replaced by equivalent random() call return (_randint(100L) * NOISE_SIZE); float n; n = random()*100.0*NOISE_SIZE/(pow((double)2, (double) 32)-1.0); return (n); */ return 0.0; } Static Void simlog(s) Char *s; { fprintf(log_, "%s\n", s); } Static Void process(ev, n, cnode) erec *ev; long n; node *cnode; { Char value[256]; long v, err, i; long sent, bw, hc; boolean NewBW_gt_All; erec *hold; Char mtype[21]; linkdata *clink; tablerec *entry_, *pick; Char STR1[256], STR2[256], STR3[256], STR4[256]; long FORLIM; long hopcount; /* check for simulation end */ if (ev->time == STOP_TIME) { stop = true; simlog(" "); sprintf(STR2, "Unrestored lines remaining: %s", int2str_(STR1, cnode->tofix)); simlog(STR2); return; } /* check for update of node local time */ if (ev->time > cnode->time) cnode->time = ev->time; /* time it takes to process incoming msg */ if (PPTOVERRIDE >= 0.0) cnode->time += PPTOVERRIDE + noise(); else cnode->time += cnode->msg_process_delay + noise(); /* determine msg type */ find_symbol_def(mtype, ev->msg, "TYPE"); /* check if "SIM" control messages */ if (!strcmp(mtype, " SIM")) { find_symbol_def(value, ev->msg, "ACTION"); if (strcmp(value, "BREAK")) /* set state & deactivate link */ return; /*which broke? */ err = (sscanf(find_symbol_def(STR1, ev->msg, "ID"), "%ld", &v) == 0); /* set SENDER or CHOOSER */ if (v <= n) { cnode->state = SENDER; maxrepeats = cnode->repeatlimit; printf("Maximum repeat limit is set to %d\n", maxrepeats); /* init common msg fields */ init_symbol(&ev->msg, "TYPE", "HELP"); init_symbol(&ev->msg, "WAVE", int2str_(STR1, cnode->wave)); sprintf(STR4, "%s@%s", int2str_(STR1, v), int2str_(STR3, n)); init_symbol(&ev->msg, "ID", STR4); /* queue event to stop simulation to sender */ hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", "STOP"); init_symbol(&hold->msg, "PATH", " SIMULATION TIMEOUT"); hold->time = STOP_TIME; hold->next = n; hold->src = 0; hold->dst = n; queue_event(hold); } else { cnode->state = CHOOSER; /* queue event to TIMEOUT when chooser */ hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", "T.O."); init_symbol(&hold->msg, "WAVE", int2str_(STR1, cnode->wave)); init_symbol(&hold->msg, "PATH", " INTERNAL TIMEOUT"); hold->time = cnode->time + TIMEOUT; hold->next = n; hold->src = n + 1000; hold->dst = n; queue_event(hold); } /* deactivate link & set channels to restore */ clink = (linkdata *)head(&cnode->links); if (clink == NULL) { printf("There is no span from %s to %s\n", break1str, break2str); exit(3); } while (clink->dest != v) { clink = (linkdata *)next(&cnode->links); if (clink == NULL) { printf("There is no span from %s to %s\n", break1str, break2str); exit(3); } } clink->active = false; cnode->tofix = clink->work; bw_needed = cnode->tofix; if (cnode->state == SENDER) printf("(%3d working channels lost)\n\n", bw_needed); /* flood help msg if sender */ if (cnode->state != SENDER) return; /* init common msg fields */ init_symbol(&ev->msg, "HOPS", int2str_(STR1, 1L)); sprintf(STR4, " %s%c", int2str_(STR1, n), statechar[(long)cnode->state]); if (strlen(STR4)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", STR4); /* do flood to "reasonable" nodes */ sent = 0; FORLIM = cnode->links.count; for (i = 1; i <= FORLIM; i++) { clink = (linkdata *)recall(&cnode->links, i); if (clink->active && clink->spare != 0) { /* send HELP msg */ sent++; /* new msg creation */ hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + sent * cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "BW", int2str_(STR1, imin(cnode->tofix, (long)clink->spare))); hold->next = clink->dest; hold->src = n; hold->dst = clink->dest; queue_event(hold); msg_count++; } } /* update node time */ cnode->time += sent * cnode->msg_process_delay + i * cnode->msg_process_delay * LINK_CHECK_SCALEFACTOR; return; /* don't need to process normal states */ } switch (cnode->state) { case SPREAD: if (!strcmp(mtype, "HELP")) { err = (sscanf(find_symbol_def(STR1, ev->msg, "WAVE"), "%ld", &v) == 0); if (v != cnode->wave) { /* new wave -> re-init */ cnode->wave = v; kill(&cnode->table); /* build new msg entry in table */ entry_ = (tablerec *)Malloc(sizeof(tablerec)); entry_->from = ev->src; err = (sscanf(find_symbol_def(STR1, ev->msg, "HOPS"), "%d", &entry_->hop) == 0); err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%d", &entry_->bw) == 0); entry_->connected = 0; add(&cnode->table, (Anyptr)entry_, cnode->table.count + 1L); /* init common msg fields */ init_symbol(&ev->msg, "HOPS", int2str_(STR1, entry_->hop + 1)); find_symbol_def(value, ee->msg, "PATH"); sprintf(STR3, "%s%s%c", value, int2str_(STR1, n), statechar[(long)cnode->state]); if (strlen(STR3)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", STR3); /* flood out msg */ sent = 0; FORLIM = cnode->links.count; for (i = 1; i <= FORLIM; i++) { clink = (linkdata *)recall(&cnode->links, i); if (clink->active && clink->spare != 0 && clink->dest != entry_->from) { sent++; hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + sent * cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "BW", int2str_(STR1, imin((long)entry_->bw, (long)clink->spare))); hold->next = clink->dest; hold->src = n; hold->dst = clink->dest; queue_event(hold); msg_count++; } } /* update node time */ cnode->time += sent * cnode->msg_process_delay + i * cnode->msg_process_delay * LINK_CHECK_SCALEFACTOR; } else { err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%d", &bw) == 0); err = (sscanf(find_symbol_def(STR1, ev->msg, "HOPS"), "%d", &hc) == 0); /* determine if we propagate help msg */ NewBW_gt_All = true; entry_ = (tablerec *)head(&cnode->table); while (entry_ != NULL) { if (bw == entry_->bw && hc < entry_->hop) { entry_->from = ev->src; entry_->hop = hc; } if (bw <= entry_->bw) NewBW_gt_All = false; entry_ = (tablerec *)next(&cnode->table); } if (NewBW_gt_All) { /* add to table */ entry_ = (tablerec *)Malloc(sizeof(tablerec)); entry_->from = ev->src; entry_->hop = hc; entry_->bw = bw; entry_->connected = 0; add(&cnode->table, (Anyptr)entry_, cnode->table.count + 1L); /* init common msg fields */ init_symbol(&ev->msg, "HOPS", int2str_(STR1, entry_->hop + 1)); find_symbol_def(value, ee->msg, "PATH"); sprintf(STR4, "%s%s%c", value, int2str_(STR1, n), statechar[(long)cnode->state]); if (strlen(STR4)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", STR4); /* flood out msg */ sent = 0; FORLIM = cnode->links.count; for (i = 1; i <= FORLIM; i++) { clink = (linkdata *)recall(&cnode->links, i); if (clink->active && clink->spare != 0 && clink->dest != entry_->from) { sent++; hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + sent * cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "BW", int2str_(STR1, imin((long)entry_->bw, (long)clink->spare))); hold->next = clink->dest; hold->src = n; hold->dst = clink->dest; queue_event(hold); msg_count++; } } cnode->time += sent * cnode->msg_process_delay + i * cnode->msg_process_delay * LINK_CHECK_SCALEFACTOR; } } } if (!strcmp(mtype, " ACK")) { err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%d", &bw) == 0); pick = find_best_path(cnode); pick->connected = bw; /* find & update link information */ /* incoming... */ clink = (linkdata *)head(&cnode->links); while (clink->dest != ev->src) clink = (linkdata *)next(&cnode->links); clink->work += pick->connected; clink->spare -= pick->connected; sprintf(STR3, "%d", bw); init_symbol(&ev->msg, "BW", STR3); /* build & send confirmation msg */ hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "TYPE", " CON"); /* capture value for later ack msg */ find_symbol_def(value, ee->msg, "PATH"); sprintf(STR3, " %s%c", int2str_(STR1, n), statechar[(long)cnode->state]); if (strlen(STR3)/4 > maxrepeats) return; init_symbol(&hold->msg, "PATH", STR3); hold->next = ev->src; hold->src = n; hold->dst = ev->src; queue_event(hold); msg_count++; /* find & update link information */ /* outgoing... */ clink = (linkdata *)head(&cnode->links); while (clink->dest != pick->from) clink = (linkdata *)next(&cnode->links); clink->work += pick->connected; clink->spare -= pick->connected; /* pass on acknowledge msg */ hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + cnode->msg_process_delay * 2.0 + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "TYPE", " ACK"); /* replacing the following path info by putting the whole restored path in the ACK message, to facilitate the printing of the path when sender receive it sprintf(STR4, "%s%s%c", value, int2str_(STR1, n), statechar[(long)cnode->state]); */ find_symbol_def(value, ev->msg, "PATH"); sprintf(STR4, "%s %s", value, cnode->name); if (strlen(STR4)/4 > maxrepeats) return; init_symbol(&hold->msg, "PATH", STR4); hold->next = pick->from; hold->src = n; hold->dst = pick->from; queue_event(hold); msg_count++; cnode->time += cnode->msg_process_delay * 2.0; } /* extract essential info from ACK msg */ break; case IDLE: if (!strcmp(mtype, "HELP")) { err = (sscanf(find_symbol_def(STR1, ev->msg, "WAVE"), "%ld", &v) == 0); if (v != cnode->wave) { /* re-init */ cnode->wave = v; kill(&cnode->table); } /* build table entry for help msg */ entry_ = (tablerec *)Malloc(sizeof(tablerec)); entry_->from = ev->src; err = (sscanf(find_symbol_def(STR1, ev->msg, "HOPS"), "%d", &entry_->hop) == 0); err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%d", &entry_->bw) == 0); entry_->connected = 0; add(&cnode->table, (Anyptr)entry_, cnode->table.count + 1L); cnode->state = SPREAD; /* init common msg fields */ init_symbol(&ev->msg, "HOPS", int2str_(STR1, entry_->hop + 1)); find_symbol_def(value, ee->msg, "PATH"); sprintf(STR3, "%s%s%c", value, int2str_(STR1, n), statechar[(long)cnode->state]); if (strlen(STR3)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", STR3); /* flood out msg */ sent = 0; FORLIM = cnode->links.count; for (i = 1; i <= FORLIM; i++) { clink = (linkdata *)recall(&cnode->links, i); if (clink->active && clink->spare != 0 && clink->dest != entry_->from) { sent++; hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + sent * cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "BW", int2str_(STR1, imin((long)entry_->bw, (long)clink->spare))); hold->next = clink->dest; hold->src = n; hold->dst = clink->dest; queue_event(hold); msg_count++; } } cnode->time += sent * cnode->msg_process_delay + i * cnode->msg_process_delay * LINK_CHECK_SCALEFACTOR; } /* check if wave in sync */ break; case CHOOSER: if (!strcmp(mtype, "HELP")) { err = (sscanf(find_symbol_def(STR1, ev->msg, "WAVE"), "%ld", &v) == 0); if (v == cnode->wave) { /* add msg info to table */ entry_ = (tablerec *)Malloc(sizeof(tablerec)); entry_->from = ev->src; err = (sscanf(find_symbol_def(STR1, ev->msg, "HOPS"), "%d", &entry_->hop) == 0); err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%d", &entry_->bw) == 0); entry_->connected = 0; add(&cnode->table, (Anyptr)entry_, cnode->table.count + 1L); } } /* check wave sync */ if (!strcmp(mtype, "T.O.")) { /* pick best entry & send ack */ if (cnode->table.count > 0) { /* table not empty */ /* find "best" path -- max BW, min HC */ pick = find_best_path(cnode); /* update connect field & fix amount */ pick->connected = imin(cnode->tofix, (long)pick->bw); cnode->tofix -= pick->connected; /* update link information */ clink = (linkdata *)head(&cnode->links); while (clink->dest != pick->from) clink = (linkdata *)next(&cnode->links); clink->work += pick->connected; clink->spare -= pick->connected; /* build & send acknowledgement msg */ hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "TYPE", " ACK"); init_symbol(&hold->msg, "BW", int2str_(STR1, (long)pick->connected)); init_symbol(&hold->msg, "WAVE", int2str_(STR1, cnode->wave)); /* replace with a path name sprintf(STR4, " %s%c", int2str_(STR1, n), statechar[(long)cnode->state]); */ sprintf(STR4, "(%s", cnode->name); init_symbol(&hold->msg, "PATH", STR4); hold->next = pick->from; hold->src = n; hold->dst = pick->from; queue_event(hold); msg_count++; cnode->time += cnode->msg_process_delay; /* if not done, expect new wave */ if (cnode->tofix > 0) { cnode->wave++; kill(&cnode->table); /*???? move here?*/ hopcount = pick->hop; hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; /* what is this statement mean in C */ copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", "T.O."); init_symbol(&hold->msg, "PATH", " INTERNAL TIMEOUT"); init_symbol(&hold->msg, "WAVE", int2str_(STR1, cnode->wave)); printf("wave number in the new internal timeout=%s\n", int2str_(STR1, cnode->wave)); hold->time = cnode->time + TIMEOUT + hopcount * cnode->msg_process_delay * 2.0 + hopcount * transmit_delay; /*???? improvement*/ hold->next = n; hold->src = n + 1000; hold->dst = n; queue_event(hold); } } else { /* no request come in */ /* wait for sender to time out and send another request */ /* if (cnode->tofix > 0) { hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); init_symbol(&hold->msg, "TYPE", "T.O."); init_symbol(&hold->msg, "PATH", " INTERNAL TIMEOUT"); init_symbol(&hold->msg, "WAVE", int2str_(STR1, cnode->wave)); printf("wave number in the new internal timeout=%s\n", int2str_(STR1, cnode->wave)); hold->time = cnode->time + TIMEOUT + hopcount * cnode->msg_process_delay * 2.0 + hopcount * transmit_delay; hold->next = n; hold->src = n + 1000; hold->dst = n; queue_event(hold); } */ } } break; case SENDER: if (!strcmp(mtype, " ACK")) { err = (sscanf(find_symbol_def(STR1, ev->msg, "BW"), "%d", &bw) == 0); find_symbol_def(value, ee->msg, "PATH"); if (cnode->tofix != 0) { path_count++; printf("Path %2ld ", path_count); /* update fix info */ if (cnode->tofix > bw) { cnode->tofix -= bw; bw_found += bw; printf("(%2d bw)", bw); } else { printf("(%2d bw)", cnode->tofix); bw_found = bw_needed; bw = cnode->tofix; cnode->tofix = 0; } } if (PARALLEL_DCS == 0) connectTime = CROSS_CONNECT_TIME; else if (bw%PARALLEL_DCS) { connectTime = (bw/PARALLEL_DCS+1)*CROSS_CONNECT_TIME; } else { connectTime = (bw/PARALLEL_DCS)*CROSS_CONNECT_TIME; } if (cnode->time > lastRestoreTime) lastRestoreTime = cnode->time + connectTime; else lastRestoreTime = lastRestoreTime + connectTime; /* connect to be put off */ printf("%6.2f%% rstrd at ", bw_found * 100.0 / bw_needed); printf("%3.2f msec ---> ", lastRestoreTime*1000); sprintf(STR1, "%s %s)", value, cnode->name); i=countSpare(STR1); printf("%s\n", STR1); spare_used +=i*bw; rstr_msg_count = msg_count; /* find_symbol_def(pathlist, ee->msg, "PATH"); FORLIM = netsize; for (i = 0; i <= FORLIM; i++) strcpy(pathlist, replace_strs(STR3, pathlist, int2str_(STR4, i), find_symbol_def(STR1, nodename, int2str_(STR2, i)))); printf("%s%s\n", pathlist, cnode->name); */ /* update link information */ clink = (linkdata *)head(&cnode->links); while (clink->dest != ev->src) clink = (linkdata *)next(&cnode->links); clink->work += bw; clink->spare -= bw; /* build & send confirmation msg */ hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "TYPE", " CON"); sprintf(STR3, " %s%c", int2str_(STR4, n), statechar[(long)cnode->state]); init_symbol(&hold->msg, "PATH", STR3); hold->next = ev->src; hold->src = n; hold->dst = ev->src; queue_event(hold); msg_count++; /* update node time */ cnode->time += cnode->msg_process_delay; /* check if another wave required */ if (cnode->tofix > 0) { cnode->wave++; /* init common msg fields */ init_symbol(&ev->msg, "TYPE", "HELP"); init_symbol(&ev->msg, "WAVE", int2str_(STR4, cnode->wave)); sprintf(STR2, "%s@%s", int2str_(STR4, v), int2str_(STR1, n)); init_symbol(&ev->msg, "ID", STR2); init_symbol(&ev->msg, "HOPS", int2str_(STR4, 1L)); find_symbol_def(value, ee->msg, "PATH"); /*???? */ sprintf(STR2, " %s%c", int2str_(STR4, n), statechar[(long)cnode->state]); if (strlen(STR2)/4 > maxrepeats) return; init_symbol(&ev->msg, "PATH", STR2); /* flood out msg */ sent = 0; FORLIM = cnode->links.count; for (i = 1; i <= FORLIM; i++) { clink = (linkdata *)recall(&cnode->links, i); if (clink->active && clink->spare != 0) { sent++; hold = (erec *)Malloc(sizeof(erec)); *hold = *ev; copy_symbols(&ev->msg, &hold->msg); hold->time = cnode->time + sent * cnode->msg_process_delay + transmit_delay + clink->delay + noise(); init_symbol(&hold->msg, "BW", int2str_(STR4, imin(cnode->tofix, (long)clink->spare))); hold->next = clink->dest; hold->src = n; hold->dst = clink->dest; queue_event(hold); msg_count++; } } cnode->time += sent * cnode->msg_process_delay + i * cnode->msg_process_delay * LINK_CHECK_SCALEFACTOR; } } /* extract essential information */ break; default: sprintf(STR1, "Illegal node state in Node(%s).", int2str_(STR4, n)); simlog(STR1); break; } /* extract essential info */ } Static Void init_nodes(s) Char *s; { FILE *netdef; Char line[256], tline[256]; long idx, jdx, err, linkcount; float distance; node *cnode, *idxnode, *jdxnode; linkdata *clink; Char STR1[256]; long FORLIM; Char *TEMP; long FORLIM1; double TEMP1, TEMP2; char type[20]; long V_Hcoord = 0; float linkdistance; /* get net file ready for read */ /* p2c: fitprint.pas, line 778: Warning: * Don't know how to ASSIGN to a non-explicit file variable [207] netdef = NULL; assign(netdef, s); rewind(netdef); */ netdef = fopen( to_lower(STR1,s), "r"); /* define SIM node, mainly for logding purposes as source */ cnode = (node *)Malloc(sizeof(node)); strcpy(cnode->name, "SIM"); init_symbol(&nodename, int2str_(STR1, 0L), cnode->name); add(&net, (Anyptr)cnode, 0L); fscanf(netdef, "%ld %s%*[^\n]", &netsize, type); if (strcmp(type, "V_H2") == 0) { OVERWRITE_LINK_DISTANCE = true; V_Hcoord = 1; } else if (strcmp(type, "L_L2") == 0) { OVERWRITE_LINK_DISTANCE = true; V_Hcoord = 0; } else if (strcmp(type, "V_H2wSpanMiles") == 0) { LINK_DISTANCE_IN_MILES = 1; V_Hcoord = 1; printf("Overwrite Propagation delay using the span miles specified in each link.\n"); } else if (strcmp(type, "L_L2wSpanKms") == 0) { LINK_DISTANCE_IN_MILES = 2; V_Hcoord = 0; printf("Overwrite Propagation delay using the span km specified in each link.\n"); } else { printf("unrecongized file type=%s\n This program recognizes V_H2, L_L2, V_H2wSpanMiles, and L_L2wSpanKms.\n", type); } getc(netdef); FORLIM = netsize; /* for all nodes ... */ for (idx = 1; idx <= FORLIM; idx++) { cnode = (node *)Malloc(sizeof(node)); init_list(&cnode->links); init_list(&cnode->table); cnode->time = 0.0; cnode->tofix = 0; cnode->wave = 0; fgets(line, 256, netdef); TEMP = strchr(line, '\n'); if (TEMP != NULL) *TEMP = 0; tokenize(tline, line); get_token(cnode->name, tline); init_symbol(&nodename, int2str_(STR1, idx), cnode->name); cnode->id = idx; err = (sscanf(get_token(STR1, tline), "%d", &linkcount) == 0); err = (sscanf(get_token(STR1, tline), "%g", &cnode->msg_process_delay) == 0); cnode->state = 0; /* this field is now used for node specific repeat limit err = (sscanf(get_token(STR1, tline), "%d", (int *)(&cnode->state)) == 0); */ err = (sscanf(get_token(STR1, tline), "%d", &cnode->repeatlimit) == 0); if (overwriteRL) { cnode->repeatlimit = maxrepeats; if (DEBUG) printf("repeat limit of %s is overwritten to %d.\n", cnode->name, cnode->repeatlimit); } else if (cnode->repeatlimit == 0) { cnode->repeatlimit = maxrepeats; if (DEBUG) printf("repeat limit of %s is set to default value %d.\n", cnode->name, cnode->repeatlimit); } else { if (DEBUG) printf("repeat limit of %s is set to %d.\n", cnode->name, cnode->repeatlimit); if (cnode->repeatlimit > maxrepeats) maxrepeats = cnode->repeatlimit; } err = (sscanf(get_token(STR1, tline), "%g", &cnode->lat) == 0); err = (sscanf(get_token(STR1, tline), "%g", &cnode->long_) == 0); /* for all links... */ for (jdx = 1; jdx <= linkcount; jdx++) { clink = (linkdata *)Malloc(sizeof(linkdata)); fgets(line, 256, netdef); TEMP = strchr(line, '\n'); if (TEMP != NULL) *TEMP = 0; tokenize(tline, line); err = (sscanf(get_token(STR1, tline), "%d", &clink->dest) == 0); clink->active = (strcmp(get_token(STR1, tline), "1") == 0); clink->delay = 0.0; err = (sscanf(get_token(STR1, tline), "%d", &clink->work) == 0); err = (sscanf(get_token(STR1, tline), "%d", &clink->spare) == 0); if (!OVERWRITE_LINK_DISTANCE) { if (LINK_DISTANCE_IN_MILES != 0) err = (sscanf(get_token(STR1, tline), "%f", &linkdistance) == 0); if (err) { clink->delay = 0.0; printf("Error: the net file does not have link distance field\n" ); exit(1); } else { if (LINK_DISTANCE_IN_MILES == 1) { /* linkdistance field in miles, 1 mile = 1.6093km */ clink->delay = (linkdistance*1.6093)/(LIGHTSPEED/REFRACINDEX); } else { /* linkdistance field in km */ clink->delay = linkdistance / (LIGHTSPEED/REFRACINDEX); } if (DEBUG) { printf("linkdistance =%f, LIGHTSPEED=%f, REFRACINDEX=%f\n", linkdistance, LIGHTSPEED, REFRACINDEX); printf("link %d-%d (internalIDs) delay is set to %f seconds.\n", cnode->id, clink->dest, clink->delay); } } } else clink->delay = 0.0; add(&cnode->links, (Anyptr)clink, jdx); } add(&net, (Anyptr)cnode, idx); } FORLIM = netsize; /* calculate link delays based on relative distances */ for (idx = 1; idx <= FORLIM; idx++) { idxnode = (node *)recall(&net, idx); FORLIM1 = idxnode->links.count; for (jdx = 1; jdx <= FORLIM1; jdx++) { clink = (linkdata *)recall(&idxnode->links, jdx); if (clink->active) { jdxnode = (node *)recall(&net, clink->dest); TEMP1 = idxnode->lat - jdxnode->lat; TEMP2 = idxnode->long_ - jdxnode->long_; if (OVERWRITE_LINK_DISTANCE) { if (V_Hcoord == 1) { distance = sqrt((TEMP2*TEMP2+TEMP1*TEMP1)/10)*1.6; /* from Kershenbaum's Telecom. design text instrution manual */ clink->delay = distance / (LIGHTSPEED / REFRACINDEX); } else if (V_Hcoord == 0) { /* use longitude latitude */ distance = sqrt(TEMP2 * TEMP2 + TEMP1 * TEMP1); clink->delay = distance * KMPERDEG / (LIGHTSPEED / REFRACINDEX); } if (DEBUG) { printf("link %s-%s delay is overwritten/set to %f seconds.\n", cnode->name, jdxnode->name, clink->delay); } } } else clink->delay = 0.0; } } if (netdef != NULL) fclose(netdef); netdef = NULL; if (netdef != NULL) fclose(netdef); } Static Void log_network() { long idx, jdx; node *cnode; linkdata *outlink; node *endnode; linkdata *inlink; unsigned short hr, min, sec, csec, yr, mon, day, dow; Char STR1[256], STR2[256], STR3[256], STR4[256]; long FORLIM; Char STR5[24]; long FORLIM1; Char STR6[256]; Char STR7[256]; Char STR8[94]; Char STR9[56]; /* dump initial network configuration */ GetTime(&hr, &min, &sec, &csec); GetDate(&yr, &mon, &day, &dow); sprintf(STR4, "Run Date: %s/%s", int2str_(STR1, (long)mon), int2str_(STR2, (long)day)); simlog(STR4); sprintf(STR3, "Run Time: %s:%s", int2str_(STR1, (long)hr), int2str_(STR2, (long)min)); simlog(STR3); simlog(" "); sprintf(STR2, "NETWORK DESCRIPTION for %s", P_argv[1]); simlog(STR2); simlog(" "); FORLIM = netsize; for (idx = 1; idx <= FORLIM; idx++) { cnode = (node *)recall(&net, idx); sprintf(STR5, "* FROM: %s", cnode->name); simlog(STR5); FORLIM1 = cnode->links.count; for (jdx = 1; jdx <= FORLIM1; jdx++) { outlink = (linkdata *)recall(&cnode->links, jdx); endnode = (node *)recall(&net, outlink->dest); inlink = (linkdata *)head(&endnode->links); while (inlink->dest != idx) inlink = (linkdata *)next(&endnode->links); sprintf(STR6, " TO: %s OUT: %s/%s IN: %s/%s", endnode->name, int2str_(STR2, (long)outlink->work), int2str_(STR1, (long)outlink->spare), int2str_(STR3, (long)inlink->work), int2str_(STR7, (long)inlink->spare)); simlog(STR6); } simlog(" "); } /* dump simulation parameters */ simlog(" "); simlog(" "); sprintf(STR1, " STOPTIME=%s", simtime2str(STR2, STOP_TIME)); simlog(STR1); sprintf(STR1, " TIMEOUT=%s", simtime2str(STR2, TIMEOUT)); simlog(STR1); sprintf(STR1, " TX_SPEED=%s", simtime2str(STR2, TX_SPEED)); simlog(STR1); sprintf(STR1, " LCS=%s", simtime2str(STR2, LINK_CHECK_SCALEFACTOR)); simlog(STR1); sprintf(STR1, " INDEX=%s", simtime2str(STR2, REFRACINDEX)); simlog(STR1); sprintf(STR1, " NOISE=%s", simtime2str(STR2, NOISE_SIZE)); simlog(STR1); sprintf(STR8, " OUT=%s", outfilename); simlog(STR8); simlog(" "); simlog(" "); sprintf(STR9, " BREAK=%s-%s", break1str, break2str); simlog(STR9); simlog(" "); simlog(" "); simlog(" "); simlog("START OF SIMULATION RUN: "); simlog(" "); simlog(" EV-TIME Q-WAIT"); simlog(" "); } main(argc, argv) int argc; Char *argv[]; { FILE *fp; Char STR1[256], STR2[256]; long FORLIM; Char STR3[256]; Char STR4[256]; Char STR5[256], STR6[256]; Char STR7[256]; Char STR8[256], STR9[256], STR10[256], STR11[256]; Char STR12[256]; long opt_bw_found, opt_spare_used; boolean found; Char *cp; _strings_init(); _netsim_init(); _math_init(); PASCAL_MAIN(argc, argv); log_ = NULL; SaveEvents = false; stop = false; options = NULL; init_symbol(&options, "FIRST_PARAM", NOT_FOUND); init_symbol(&options, "STOPTIME=", "10.0"); init_symbol(&options, "TIMEOUT=", "0.25"); init_symbol(&options, "LCS=", "0.05"); init_symbol(&options, "2INDEX=", "1.5"); init_symbol(&options, "NOISE=", "0.00001"); init_symbol(&options, "MSG_LENGTH=", "8"); init_symbol(&options, "PPTOVERRIDE=", "-1.0"); init_symbol(&options, "OUT=", "NETSIM.OUT"); init_symbol(&options, "BREAK=", NOT_FOUND); init_symbol(&options, "DEBUG", NOT_FOUND); init_symbol(&options, "X_SPEED=", "8"); init_symbol(&options, "YPARALLEL_DCS=", "0"); init_symbol(&options, "WRITE_LINK=", NOT_FOUND); init_symbol(&options, "CROSS_CONNECT_TIME=", "0.01"); init_symbol(&options, "REPEATS=", NOT_FOUND); *result = '\0'; cli(result, &options, '/'); if (*result != '\0') puts(result); find_symbol_def(infilename, options, "FIRST_PARAM"); if (!strcmp(infilename, NOT_FOUND) || strlen(infilename) == 0) { printf("Required net definition filename found on command line!\n"); _Escape(0); } find_symbol_def(result, options, "BREAK="); if (!strcmp(result, NOT_FOUND)) { printf("Required field /BREAK= not found on command line!\n"); _Escape(0); } sprintf(break1str, "%.*s", strpos2(result, "-", 1) - 1, result); strsub(break2str, result, strpos2(result, "-", 1) + 1, strlen(result)); printf("FITNESS simulation result...with %s\n", infilename); printf("Break ocurred between node %s and node %s.\n", break1str, break2str); find_symbol_def(result, options, "REPEATS="); if (strcmp(result, NOT_FOUND)) { /* REPEAT LIMIT OVERWRITE option is specified in command line */ overwriteRL = true; i = (sscanf(find_symbol_def(STR2, options, "REPEATS="), "%d", &maxrepeats) == 0); printf("MAXREPEATS (longest explored signature path length) set to %d\n", maxrepeats); } i = (sscanf(find_symbol_def(STR2, options, "CROSS_CONNECT_TIME="), "%g", &CROSS_CONNECT_TIME) == 0); printf("CROSS_CONNECT_TIME is set to %g sec.\n", CROSS_CONNECT_TIME); i = (sscanf(find_symbol_def(result, options, "YPARALLEL_DCS="), "%d", &PARALLEL_DCS) == 0); if (PARALLEL_DCS == 0) printf("DCS is set to connect all found spare paths in %3.2f msec.\n", CROSS_CONNECT_TIME*1000); else if (PARALLEL_DCS == 1) printf("DCS is set to connect one spare path at a time in %3.2f msec.\n", CROSS_CONNECT_TIME*1000); else printf("DCS is set to connect %d spare path at in %3.2f msec.\n", PARALLEL_DCS, CROSS_CONNECT_TIME*1000); find_symbol_def(result, options, "WRITE_LINK"); if (!strcmp(result, NOT_FOUND)) { printf("Propagation delay is calculated using link distance specified in net file\n or using node location when link distance field not present.\n"); OVERWRITE_LINK_DISTANCE = false; } else { OVERWRITE_LINK_DISTANCE = true; printf("Propagation delay is calculated using distance between nodes\n"); } find_symbol_def(result, options, "DEBUG"); if (!strcmp(result, NOT_FOUND)) { printf("DEBUG is set to false\n"); } else { DEBUG = true; printf("DEBUG mode is turned on\n"); } i = (sscanf(find_symbol_def(STR2, options, "STOPTIME="), "%g", &STOP_TIME) == 0); i = (sscanf(find_symbol_def(STR2, options, "TIMEOUT="), "%g", &TIMEOUT) == 0); i = (sscanf(find_symbol_def(STR2, options, "LCS="), "%g", &LINK_CHECK_SCALEFACTOR) == 0); i = (sscanf(find_symbol_def(STR2, options, "2INDEX="), "%g", &REFRACINDEX) == 0); printf("Refraction Index is set at %f.\n", REFRACINDEX); i = (sscanf(find_symbol_def(STR2, options, "PPTOVERRIDE="), "%g", &PPTOVERRIDE) == 0); if (PPTOVERRIDE != -1.0) printf("Protocol/Message processing time is overwritten/set to %f.\n", PPTOVERRIDE); i = (sscanf(find_symbol_def(STR2, options, "MSG_LENGTH="), "%d", &MSG_LENGTH) == 0); printf("Message length is set at %d bytes\n", MSG_LENGTH); i = (sscanf(find_symbol_def(result, options, "X_SPEED="), "%d", &TX_SPEED) == 0); printf("Transmission speed is set at %dKbps\n", TX_SPEED); transmit_delay = MSG_LENGTH*8/(TX_SPEED*1000.0); i = (sscanf(find_symbol_def(STR2, options, "NOISE="), "%g", &NOISE_SIZE) == 0); find_symbol_def(outfilename, options, "OUT="); log_ = fopen(outfilename, "w"); if (log_ != NULL) /* rewind(log_); */; else log_ = tmpfile(); if (log_ == NULL) _EscIO(FileNotFound); nodename = NULL; if (SaveEvents) set_save_mode(); init_list(&net); init_nodes(infilename); FORLIM = netsize; for (i = 1; i <= FORLIM; i++) { find_symbol_def(result, nodename, int2str_(STR1, i)); if (!strcmp(result, break1str)) break1 = i; if (!strcmp(result, break2str)) break2 = i; } if (break1 == 0) { printf("There is no such node %s in node1 of break specification.\n", break1str); exit(3); } if (break2 == 0) { printf("There is no such node %s in node2 of break specification.\n", break2str); exit(3); } log_network(); ee = (erec *)Malloc(sizeof(erec)); ee->time = 0.0; ee->src = 0; ee->dst = break2; ee->next = break2; ee->msg = NULL; init_symbol(&ee->msg, "ID", int2str_(STR1, break1)); init_symbol(&ee->msg, "ACTION", "BREAK"); init_symbol(&ee->msg, "TYPE", " SIM"); init_symbol(&ee->msg, "WAVE", "---"); init_symbol(&ee->msg, "HOPS", "---"); init_symbol(&ee->msg, "BW", "---"); init_symbol(&ee->msg, "PATH", " INTERNAL FAULT DETECTION"); queue_event(ee); ee = (erec *)Malloc(sizeof(erec)); ee->time = 0.0; ee->src = 0; ee->dst = break1; ee->next = break1; ee->msg = NULL; init_symbol(&ee->msg, "ID", int2str_(STR1, break2)); init_symbol(&ee->msg, "ACTION", "BREAK"); init_symbol(&ee->msg, "TYPE", " SIM"); init_symbol(&ee->msg, "WAVE", "---"); init_symbol(&ee->msg, "HOPS", "---"); init_symbol(&ee->msg, "BW", "---"); init_symbol(&ee->msg, "PATH", " INTERNAL FAULT DETECTION"); queue_event(ee); path_count = 0; bw_found = 0; print_flag = true; do { ee = next_event(); if (ee != NULL) { nextnode = (node *)recall(&net, ee->next); sprintf(STR12, "%s %s %s -> %s of Type: %s HC: %s BW: %s WAVE: %s", simtime2str(STR1, ee->time), simtime2str(STR2, bounds(0.0, nextnode->time - ee->time, 1.0e30)), find_symbol_def(STR5, nodename, int2str_(STR4, ee->src)), find_symbol_def(STR6, nodename, int2str_(STR7, ee->next)), find_symbol_def(STR8, ee->msg, "TYPE"), find_symbol_def(STR9, ee->msg, "HOPS"), find_symbol_def(STR10, ee->msg, "BW"), find_symbol_def(STR11, ee->msg, "WAVE")); /* print event info */ simlog(STR12); /* extract & print path info */ find_symbol_def(pathlist, ee->msg, "PATH"); FORLIM = netsize; for (i = 0; i <= FORLIM; i++) strcpy(pathlist, replace_strs(STR1, pathlist, int2str_(STR2, i), find_symbol_def(STR5, nodename, int2str_(STR4, i)))); sprintf(STR1, " by%s", pathlist); simlog(STR1); /* do event processing at node */ process(ee, ee->next, nextnode); if (!SaveEvents) { /* release dynamic memeory */ release_all_symbols(&ee->msg); Free(ee); } } else stop = true; } while (!stop); to_lower(STR2, infilename); cp = STR2; while (*cp != '.' && cp < STR2 + strlen(STR2)) cp++; *cp = '\0'; /* got the prefix */ sprintf(STR3, "%s.dat.ls/%s_%scut.l", STR2, break1str, break2str); if (access(STR3, R_OK) == 0) { printf("access file %s\n", STR3); found = true; } else { sprintf(STR3, "%s.dat.ls/%s_%scut.l", STR2, break2str, break1str); printf("access file %s\n", STR3); if (access(STR3, R_OK) == 0) { found = true; } else { found = false; printf("optimal spare usage file not found\n"); } } if (found) { fp = fopen(STR3, "r"); while (fgets(STR4, 255, fp)!=NULL) { sscanf(STR4, "%s", STR5); STR5[24]='\0'; if (strcmp(STR5, "TOTAL_BANDWIDTH_RESTORED") == 0) { sscanf(STR5+25, "%d", &opt_bw_found); printf("optimal bandwidth that can be restored=%d\n", opt_bw_found); fgets(STR4, 255, fp); sscanf(STR4, "%s %d", STR5, &opt_spare_used); printf("optimal spare used =%d\n", opt_spare_used); break; } } sprintf(STR1, "%s-%s %d/%d=%6.2f%% @%f msgs=%d/%d PNE=%d/%d PLE=%d/%d\n", break1str, break2str, bw_found, bw_needed, bw_found*100.0/bw_needed, lastRestoreTime, rstr_msg_count, msg_count, bw_found, opt_bw_found, opt_spare_used, spare_used); } else { sprintf(STR1, "%s-%s %d/%d=%6.2f%% @%f msgs=%d/%d spares=%d\n", break1str, break2str, bw_found, bw_needed, bw_found*100.0/bw_needed, lastRestoreTime, rstr_msg_count, msg_count, spare_used); } printf("%s", STR1); fprintf(stderr, "%s", STR1); fp = fopen("netres.fit.res", "a"); if (fp == NULL) { fprintf(stderr, "can not open netres.fit.res\n"); } fprintf(fp, "%s", STR1); fflush(log_); P_ioresult = 0; if (log_ != NULL) fclose(log_); log_ = NULL; if (log_ != NULL) fclose(log_); exit(0); } /* End. */