/* Output from p2c, the Pascal-to-C translator */ /* From input file "shn.pas" */ /* This program is available for research only. For commercial use, please check * with chow@cs.uccs.edu. */ /* Project : NetRestore Algorithm Name : Grover's Self Healing Network (SHN) Programmed by : Steve McCaughey Date : 17 NOV 1993 Version : 1.05 This program models the SHN digital network restoration algorithm using NETSIM and other library routines. Revision History: Date - Initials - Description of Modification --------------------------------------------- 12/13/93 chow ported to C 12/10/94 mccaughey expanded capacity of simulator 2/21/95 mccaughey included dr chow's fixes 3/7/95 chow add index tree trace and interactive debugging 3/25/95 chow add fast cancellation 3/26/95 chow fix SIGID_transit bug */ #include #include #include #include "math.h" #ifndef STRINGS_H #include "strings2.h" #endif #ifndef NETSIM_H #include "netsim2.h" #endif #ifndef LISTS_H #include "lists.h" #endif #include /* chow 4/28/2004: change above from to header file moved */ /* Chow: needed for GetTime and GetDate */ /* SHN-DATA.inc */ #define MSS 512 /* SM: Max String Size */ #define MAXREPEATS 10 #define IRV 1 #define NIL_NODE 0 #define MAXNODES 128 /* SM: 16 to 128, integer #nodes possible */ #define MAXPORTS 2048 /* SM: per node, 255 to 2k */ #define MAXSPANS MAXNODES /* SM: new, should be <= MAXNODES */ #define MAX_INT 0x7FFFFFFF /* SM: 16 to 32 bit integers */ /* Chow: Change MAXBUFFERS 4999 to 9999 due to out of RS buffers SM: For 100,000 channel network, increase to 100% ************************************************************************************ NOTE!!! max digits returned by int2str MUST allow for MAXBUFFERS array id's ************************************************************************************ */ #define MAXBUFFERS 500000 /* channel buffer array size */ #define BYTES_PER_NID 4 /* SM: 4 bytes per integer NID */ #define BYTES_PER_BW 2 /* SM: BW count up to 0xFFFF */ #define MAXPORTSET MAXPORTS/32+1 /* SM: new, more ports than spans? */ #define MAXSPANSET MAXSPANS/32+1 /* Chow: span > 32 now */ #define KMPERDEG 111.3194 /* km/deg */ #define LIGHTSPEED 299796.0 /* km/sec */ Static float REFRACINDEX = 1.5; /* index of refraction for glass -- lightspeed / index = lightspeed in material */ #define INTR_MSG " PORT INTR" #define TIMER_MSG "TIMER INTR" #define SIM_MSG " SIM MSG" typedef struct linkdata { long dest; boolean active; float delay; long work; long spare; } linkdata; /* SHN node states */ typedef enum { NORMAL, TANDEM, SENDER, CHOOSER } nodestates; typedef struct sig_reg { long NID; /* RS - node sending */ long source; /* sender */ long target; /* chooser */ long index; /* family ID of signature */ long repeats; /* # hops from sender */ long SIGID; /* unique ID for given comm path, set to value by sender */ boolean RA; /* return (echo) alarm, both dirs */ /* set by break procedure!!! */ } sig_reg; Static sig_reg INIT_SIGREG = { 0, 0, 0, 0, 0, 0, false }; typedef struct status_reg { boolean AIE; /* alarm interrupt enable */ boolean alarm; /* channel link alarm interrupt */ boolean SCIE; /* signature change interrupt enable */ boolean RSdel; /* signature delta interrupt */ boolean SIE; /* SIGID interrupt enable */ boolean IDdel; /* signature delta interrupt */ boolean spare; /* channel has spare status */ boolean conn; /* connected (xpoint active) traffic */ /* when false, assoc port */ long SIGID; /* unique ID for comm path.. live traffic */ long assoc_port; long link_port; /* port on connected DCS node that link entity connects to */ float link_delay; } status_reg; Static status_reg INIT_STATUSREG = { true, false, true, false, false, false, true, false, 0, 0, 0, 0.0 }; typedef struct card_hw { sig_reg TS, RS; status_reg PSR; } card_hw; typedef struct spanrec { long emp_set[MAXPORTSET]; long send_set[MAXPORTSET]; long rec_set[MAXPORTSET]; } spanrec; Static long null_set[MAXPORTSET]; /* node state information for SHN */ typedef struct portrec * prp; typedef struct node * np; typedef struct portrec { np node; long port; prp next; } portrec; typedef struct sigrec * sigp; typedef struct sigrec { long index; long source; long target; sigp next; } sigrec; typedef struct node { long id; float time; Char name[20]; float msg_process_delay; nodestates state; long repeatlimit; float latitude; float longitude; list links; long tofix; /* these down specific to SHN */ long spans[MAXSPANSET]; spanrec l_spans[MAXSPANS+1]; long nports; long workingports; long spareports; long internalports; long cports; card_hw *card; /* dynamically allocate ports */ long int_port; long affected_ports[MAXPORTSET]; long alarmed_ports[MAXPORTSET]; long indices_chosen[MAXPORTSET]; long alarm_span; long int_span; long restccts; long lostccts; boolean involved; boolean new_empty_port; sigp sigCancelList; /* the following fields are for simulation purpose */ np prev; np next; float recentEventTime; long referenceCount; long colno; /* column number when printing the index tree trace */ boolean visited; /* initialized as false, set true when first visited */ prp prlist; } node; np nodelist = NULL; Static long skipcount = 10; Static long eecount = 0; Static boolean INTERACTIVE = false; Static boolean DEBUG2 = false; Static float TIMEOUT = 10.000; Static float loadTS_time = 0.001; Static float newestNodeTime = 0.0; Static float NOISE_SIZE = 0.00001; /* multiplied by random 0..100 */ Static float PPTOVERRIDE = -1.0; /* fraction of node msg process delay */ Static float LINK_CHECK_SCALEFACTOR = 0.05; Static float transmit_delay = 0.001; /* time needed to transmit one byte of SIG */ Static float STOPTIME = 10.0; /* sec -- total run time of simulation */ Static long MSG_LENGTH = 8; Static long TX_SPEED = 8; /* default tx speed of 8k bps */ 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 CROSS_CONNECT_TIME = 0.01; /* default DCS connect time 10 ms */ Static long maxrepeats = 13; Static boolean overwriteRL = false; /* state display in via path printout */ Static Char statechar[4] = { ' ', ' ', ' ', ' ' }; Static sig_reg channel[MAXBUFFERS + 1]; Static Anyptr ExitSave; Static long sparesused, timer_seqnum; Static erec *ee; Static long i, j; Static long idx; Static boolean SaveEvents; Static list net; /* Static char netsize; */ /* Chow: replace char with long it messed up the nodename when read in data with fscanf(netdef, "%ld%*[^\n]", &netsize); */ Static long netsize; Static node *sender_node = NULL; Static node *chooser_node = NULL; Static symbol_node *nodename; Static FILE *log_; Static symbol_node *signals, *newsignals, *restorationTime; Static Char printstr[MSS]; Static node *nextnode; Static boolean stop; Static long pathcount; Static symbol_node *options; Static Char result[MSS]; Static Char outfilename[MSS], infilename[MSS]; Static long break1, break2; Static Char break1str[MSS], break2str[MSS]; Static linkdata *clink; Static long bw_needed, bw_found; Static long buffers_in_use = 0; Static float lastEventTime = 0.0; Static long spare_used; Static long msg_count; Static long rstr_msg_count = 0; Static float lastRestoreTime = 0.0; Static MY_FSM_LOGIC = true; boolean DEBUG = false; typedef enum { initial_value, bad_state, senderalarm, chooseralarm, repeatable_sig, nonrepeatable_sig, timer_int, return_sig, late_alarm, new_forward_sig, SIGID_arrive, better_sig, SIGID_transit, new_complement_sig, sig_vanish, overrange_sig, update_repeat, sig_cancel } events; char *eventnames[] = { "initial_value", "bad_state", "senderalarm", "chooseralarm", "repeatable_sig", "nonrepeatable_sig", "timer_int", "return_sig", "late_alarm", "new_forward_sig", "SIGID_arrive", "better_sig", "SIGID_transit", "new_complement_sig", "sig_vanish", "overrange_sig", "update_repeat", "sig_vanish" }; Void printshnevent(events e) { if (INTERACTIVE) printf(" shnevent=%s\n", eventnames[e]); } typedef enum { NULL_, OPPOSITE, SAME } senses; /* Local variables for process: */ struct LOC_process { long n; node *cnode; events shnevent; } ; boolean sigInCancelList(node *n, long source, long target, long index){ sigp s; s = n->sigCancelList; if (s == NULL) return false; while (s != NULL) { if (s->source == source && s->target == target && s->index == index) return true; s = s->next; } return false; } boolean inSigCancelList(node *n, long port) { long source; long target; long index; source = n->card[port].RS.source; target = n->card[port].RS.target; index = n->card[port].RS.index; return sigInCancelList(n, source, target, index); } Void insertSigCancelList(node *n, long source, long target, long index) { sigp s; if (sigInCancelList(n, source, target, index)) return; s = (sigp) Malloc(sizeof(sigrec)); s->source = source; s->target = target; s->index = index; s->next = n->sigCancelList; n->sigCancelList = s; } Void updateRecentList(node *n); boolean searchPortWithIndex(np node, long inport, long index) { long port; long FORLIM1; prp p; boolean found; found = false; node->prlist = (prp) NULL; FORLIM1 = node->nports; for (port = 1; port <= FORLIM1; port++) { if (inport == 0) { /* sender node */ if (node->card[port].TS.index == index) { found = true; p = (prp) Malloc(sizeof(portrec)); p->node = node; p->port = port; p->next = node->prlist; node->prlist = p; } } else if ( node->card[port].TS.index == index && node->card[port].PSR.assoc_port == inport && port != inport) { found = true; p = (prp) Malloc(sizeof(portrec)); p->node = node; p->port = port; p->next = node->prlist; node->prlist = p; } } return found; } Void printspace(long colno) { int i; for (i=1; i<=colno; i++) { putchar(' '); } } Void indexTree(np node, long inport, long index, long colno) { /* the recursive routine start with inport==0 colno==0 */ long port, p2, nid; prp p; if (inport == 0) { printf("%s(I%04d\n", node->name, index); } if (searchPortWithIndex(node, inport, index)){ do { p = node->prlist; node->prlist = p->next; port = p->port; printspace(colno+3); Free(p); nid = node->card[port].RS.NID; nextnode = (np) recall_list(&net, nid); p2 = node->card[port].PSR.link_port; printf("XP%04dI%04d)-%s(P%04dI%04d\n", port, node->card[port].TS.index, nextnode->name, p2, nextnode->card[p2].RS.index); indexTree(nextnode, p2, index, colno+3); } while (node->prlist != NULL); } } /* 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; } Static Char *simtime2str(Result, v) Char *Result; float v; { Char s[MSS]; sprintf(s, "%8.5f", v); return strcpy(Result, s); } Static Char *int2str_(Result, i) Char *Result; long i; { /* SM: NID or port# AND channel buffer size is 5 digits, etc */ Char s[10]; i %= 100000; sprintf(s, "%0.5ld", i); return strcpy(Result, s); } Static float noise() { /* return (_randint(100L) * NOISE_SIZE); */ /* _randint is pc function */ /* float n; n = ((1.0*random())/(pow((double)2, (double) 31)-1.0))*100.0*NOISE_SIZE; return (n); */ return 0.0; } Static Void simlog(s) Char *s; { if (DEBUG) fprintf(log_, "%s\n", s); } Local Char *btest(Result, f) Char *Result; boolean f; { if (f) return strcpy(Result, "T"); else return strcpy(Result, "F"); } Local Char *printSR(Result, r) Char *Result; sig_reg r; { Char line[MSS]; Char STR2[MSS]; Char STR3[MSS]; *line = '\0'; sprintf(line + strlen(line), " NID= %s", int2str_(STR2, (long)r.NID)); sprintf(line + strlen(line), " src= %s", int2str_(STR3, (long)r.source)); sprintf(line + strlen(line), " tar= %s", int2str_(STR2, (long)r.target)); sprintf(line + strlen(line), " idx= %s", int2str_(STR3, (long)r.index)); sprintf(line + strlen(line), " rpt= %s", int2str_(STR2, (long)r.repeats)); sprintf(line + strlen(line), " SIGID= %s", int2str_(STR3, r.SIGID)); sprintf(line + strlen(line), " RA= %s", btest(STR2, r.RA)); return strcpy(Result, line); } Local Char *printSSR(Result, r) Char *Result; status_reg r; { Char line[MSS]; Char STR2[MSS]; Char STR3[MSS], STR4[MSS]; *line = '\0'; sprintf(line + strlen(line), " AIE= %s%%%s", btest(STR2, r.AIE), btest(STR3, r.alarm)); sprintf(line + strlen(line), " SCIE= %s%%%s", btest(STR3, r.SCIE), btest(STR4, r.RSdel)); sprintf(line + strlen(line), " SIE= %s%%%s", btest(STR4, r.SIE), btest(STR2, r.IDdel)); sprintf(line + strlen(line), " s= %s", btest(STR2, r.spare)); sprintf(line + strlen(line), " c= %s", btest(STR3, r.conn)); sprintf(line + strlen(line), " ap= %s", int2str_(STR4, (long)r.assoc_port)); sprintf(line + strlen(line), " lp= %s", int2str_(STR2, (long)r.link_port)); return strcpy(Result, line); } Static Void dump_network(summary) boolean summary; { long loop; long workcount[MAXNODES + 1]; long sparecount[MAXNODES + 1]; node *node_; Char STR1[MSS]; Char STR2[MSS]; long FORLIM; Char STR3[MSS], STR4[MSS], STR6[MSS]; Char STR7[MSS]; node_ = (node *)head_list(&net); node_ = (node *)next_list(&net); /* skip "SIM" node at head of list */ do { sprintf(STR1, "FOR NODE: %s", node_->name); simlog(STR1); for (loop = 1; loop <= MAXNODES; loop++) { sparecount[loop] = 0; workcount[loop] = 0; } FORLIM = node_->nports; for (loop = 1; loop <= FORLIM; loop++) { if (node_->card[loop].RS.NID > 0 && node_->card[loop].RS.NID != node_->id) { if (node_->card[loop].PSR.conn) workcount[node_->card[loop].RS.NID]++; if (node_->card[loop].PSR.spare) sparecount[node_->card[loop].RS.NID]++; } if (!summary) { sprintf(STR3, " for card: %s@%s", int2str_(STR2, loop), node_->name); simlog(STR3); sprintf(STR3, " TS: %s", printSR(STR2, node_->card[loop].TS)); simlog(STR3); sprintf(STR3, " RS: %s", printSR(STR2, node_->card[loop].RS)); simlog(STR3); sprintf(STR3, " PSR: %s", printSSR(STR2, node_->card[loop].PSR)); simlog(STR3); } } for (loop = 1; loop <= MAXNODES; loop++) { if (workcount[loop] > 0 || sparecount[loop] > 0) { sprintf(STR7, " Span to node %s has %s/%s", find_symbol_def(STR2, nodename, int2str_(STR3, loop)), int2str_(STR4, (long)workcount[loop]), int2str_(STR6, (long)sparecount[loop])); simlog(STR7); } } node_ = (node *)next_list(&net); } while (node_ != NULL); } Void appendResTime(newsignals, restorationTime) symbol_node *newsignals; symbol_node *restorationTime; { Char STR1[MSS], STR2[MSS], STR3[MSS]; if (newsignals == NULL) /* make sure list is not empty */ return; do { find_symbol_def(STR2, restorationTime, newsignals->sstr); init_symbol(&restorationTime, newsignals->sstr, STR2); newsignals = newsignals->next; } while (newsignals != NULL); } Static Void log_network(header) boolean header; { unsigned short hr, min, sec, csec, yr, mon, day, dow; Char STR1[MSS], STR2[MSS], STR3[MSS], STR4[MSS]; Char STR5[MSS]; Char STR6[MSS]; FILE *stdOUT; /* dump initial network configuration */ if (header) { GetTime(&hr, &min, &sec, &csec); GetDate(&yr, &mon, &day, &dow); sprintf(STR4, "Run Date: %d/%d/%d", mon+1, day, yr); simlog(STR4); sprintf(STR3, "Run Time: %d:%d", hr, min); simlog(STR3); } simlog(" "); sprintf(STR2, "NETWORK DESCRIPTION for %s", P_argv[1]); simlog(STR2); simlog(" "); if (header) simlog(" *AT SIMULATION START* "); else simlog(" *AT SIMULATION STOP* "); simlog(" "); if (header) { /* dump simulation parameters */ simlog(" "); simlog(" "); sprintf(STR1, " STOPTIME=%s", simtime2str(STR2, STOPTIME)); simlog(STR1); sprintf(STR1, " LCS=%s", simtime2str(STR2, LINK_CHECK_SCALEFACTOR)); simlog(STR1); sprintf(STR1, " INDEX=%s", simtime2str(STR2, REFRACINDEX)); simlog(STR1); sprintf(STR1, " PPTOVERIDE=%s", simtime2str(STR2, PPTOVERRIDE)); simlog(STR1); sprintf(STR1, " NOISE=%s", simtime2str(STR2, NOISE_SIZE)); simlog(STR1); sprintf(STR5, " OUT= %s", outfilename); simlog(STR5); simlog(" "); simlog(" "); sprintf(STR6, " BREAK=%s-%s", break1str, break2str); simlog(STR6); simlog(" "); simlog("SIGNAL list in effect:"); show_symbols(&log_, signals, " ", 6, " is ", 50, 1); simlog(" "); if (DEBUG) /* detailed card status... */ dump_network(false); else dump_network(true); /* just summary... */ simlog(" "); simlog(" "); simlog("START OF SIMULATION RUN: "); simlog(" "); simlog(" EV-TIME Q-WAIT"); simlog(" "); return; } if (DEBUG) /* detailed card status... */ dump_network(false); else dump_network(true); /* just summary... */ simlog(" "); simlog("Restoration SIGNAL paths found:"); appendResTime(newsignals, restorationTime); show_symbols(&log_, restorationTime, " ", 6, " by ", 128, 1); simlog(" "); simlog("SHN event summary:"); sprintf(STR3, " *** %s events processed.", int2str_(STR2, msg_count)); simlog(STR3); sprintf(STR1, " *** %s events pending.", int2str_(STR2, event_count())); simlog(STR1); sprintf(STR1, " *** Last event time = %s", simtime2str(STR2, nextnode->time)); simlog(STR1); sprintf(STR1, " spare used = %d channels.\n", spare_used); simlog(STR1); } Local Void sendSIGID(pid, LINK) long pid; struct LOC_process *LINK; { long nextbuf; erec *ev; Char STR1[MSS], STR2[MSS], STR4[MSS], STR5[MSS], STR6[MSS], STR7[MSS]; Char STR8[MSS]; node *nps; node *npd; float pathDelay; long dstPort; long dstNodeId; node *n; long SIGID; if (DEBUG) simlog("sendSIGID"); nextbuf = 0; /* look for unused buffer */ while (channel[nextbuf].NID != 0 && nextbuf <= MAXBUFFERS) nextbuf++; if (nextbuf == MAXBUFFERS + 1) { /* bad news, adjust program parameters! */ printf("Out of RS channel buffer space. MAXBUFFERS=%d. ABORTING!!!\n", MAXBUFFERS); _Escape(0); } LINK->cnode->time += loadTS_time; /* assume it takes time to do following */ buffers_in_use++; channel[nextbuf] = LINK->cnode->card[pid].TS; SIGID = LINK->cnode->card[pid].TS.SIGID; channel[nextbuf].SIGID = SIGID; channel[nextbuf].source = LINK->cnode->id; /* pathDelay = findPropagationDelayInPath(pid); */ pathDelay = LINK->cnode->card[pid].PSR.link_delay; dstNodeId = LINK->cnode->card[pid].RS.NID; pid = LINK->cnode->card[pid].PSR.link_port; if (DEBUG) printf("SendSIGID=%d: %sP%d->", SIGID, LINK->cnode->name, pid); /* note that in this version, we did not simulate how SIGID mapping information got propagation through the immediate nodes of a restoration path */ while (dstNodeId != chooser_node->id) { n = (node *) recall_list(&net, dstNodeId); n->card[pid].RS.SIGID = SIGID; /* n->card[pid].TS.SIGID = SIGID; */ n->card[pid].PSR.SIGID = SIGID; if (DEBUG) printf("%s(P%d-", n->name, pid); pid = n->card[pid].PSR.assoc_port; if (DEBUG) printf("P%d)->", pid); n->card[pid].TS.SIGID = SIGID; /* n->card[pid].RS.SIGID = SIGID; */ n->card[pid].PSR.SIGID = SIGID; /* accumulate the propagation delay */ pathDelay += n->card[pid].PSR.link_delay; dstNodeId = n->card[pid].RS.NID; dstPort = n->card[pid].PSR.link_port; npd = (node *) recall_list(&net, dstNodeId); if (DEBUG) printf("%sNID%dP%d.RS.NID=%d->%sNID%dP%d.RS.NID=%d\n", n->name, n->id, pid, dstNodeId, npd->name, npd->id, dstPort, npd->card[dstPort].RS.NID); pid = dstPort; } /* this is a tricky bug, the NID field should be set to the id of the last node connected to the chooser, not the sender's id. Note that loadRS will copy .NID field in the channel to RS register. the following line fixes this bug */ channel[nextbuf].NID = n->id; if (DEBUG) printf("%sP%d\n", chooser_node->name, pid); if (DEBUG) printf("\tPath Delay=%fsec\n", pathDelay); ev = (erec *)Malloc(sizeof(erec)); ev->time = LINK->cnode->time + pathDelay + transmit_delay; ev->src = sender_node->id; ev->dst = chooser_node->id; ev->next = ev->dst; ev->msg = NULL; /* SM: @@@ nps = (node *) recall_list(&net, LINK->cnode->id); npd = (node *) recall_list(&net, LINK->cnode->card[pid].RS.NID); sprintf(STR8, " INTR_MSG FM: %s@%s TO: %s@%s IX: %s ID: %s CBUF=%d\n", int2str_(STR2, (long)pid), nps->name, int2str_(STR4, (long)LINK->cnode->card[pid].PSR.link_port), npd->name, int2str_(STR6, (long)LINK->cnode->card[pid].TS.index), int2str_(STR7, LINK->cnode->card[pid].TS.SIGID), nextbuf); simlog(STR8); */ /* !!! SM: here is where big problems occur if int2str truncates numbers */ init_symbol(&ev->msg, "CBUF", int2str_(STR2, nextbuf)); init_symbol(&ev->msg, "PORT", int2str_(STR2, (long) pid)); init_symbol(&ev->msg, "TYPE", INTR_MSG); if (DEBUG) printf("creating SIGID event for chooser, pid=%d\n", pid); queue_event(ev); } Local Void loadTS(pid, LINK) long pid; struct LOC_process *LINK; { long nextbuf; erec *ev; Char STR1[MSS], STR2[MSS], STR4[MSS], STR5[MSS], STR6[MSS], STR7[MSS]; Char STR8[MSS]; node *nps; node *npd; if (DEBUG) simlog("loadTS"); nextbuf = 0; /* look for unused buffer */ while (channel[nextbuf].NID != 0 && nextbuf <= MAXBUFFERS) nextbuf++; if (nextbuf == MAXBUFFERS + 1) { /* bad news, adjust program parameters! */ printf("Out of RS channel buffer space. MAXBUFFERS=%d. ABORTING!!!\n", MAXBUFFERS); _Escape(0); } LINK->cnode->time += loadTS_time; /* assume it takes time to do following */ buffers_in_use++; channel[nextbuf] = LINK->cnode->card[pid].TS; ev = (erec *)Malloc(sizeof(erec)); ev->time = LINK->cnode->time + LINK->cnode->card[pid].PSR.link_delay + transmit_delay; ev->src = LINK->cnode->id; ev->dst = LINK->cnode->card[pid].RS.NID; ev->next = ev->dst; ev->msg = NULL; nps = (node *) recall_list(&net, LINK->cnode->id); npd = (node *) recall_list(&net, LINK->cnode->card[pid].RS.NID); /* SM: @@@ sprintf(STR8, " INTR_MSG FM: %s@%s TO: %s@%s IX: %s ID: %s CBUF=%d\n", int2str_(STR2, (long)pid), nps->name, int2str_(STR4, (long)LINK->cnode->card[pid].PSR.link_port), npd->name, int2str_(STR6, (long)LINK->cnode->card[pid].TS.index), int2str_(STR7, LINK->cnode->card[pid].TS.SIGID), nextbuf); simlog(STR8); */ /* !!! SM: here is where big problems occur if int2str truncates numbers */ init_symbol(&ev->msg, "CBUF", int2str_(STR2, nextbuf)); init_symbol(&ev->msg, "PORT", int2str_(STR2, (long)LINK->cnode->card[pid].PSR.link_port)); init_symbol(&ev->msg, "TYPE", INTR_MSG); queue_event(ev); } Local Void nullout(r, LINK) sig_reg *r; struct LOC_process *LINK; { Char STR1[MSS]; Char STR2[MSS]; if (DEBUG) { simlog("nullout"); sprintf(STR2, "TO NID: %s", int2str_(STR1, (long)r->NID)); simlog(STR2); } r->source = 0; r->target = 0; r->index = 0; r->repeats = 0; r->RA = false; } Void tracePath(p1, p2, LINK) long p1, p2; struct LOC_process *LINK; { Char STR1[MSS], STR2[MSS], STR3[MSS], STR4[2*MSS], STR5[2*MSS]; node *np, *sp; long n; long SIGID; long spare_count; node *n1; long port1, port2; long hopcount; /* backtrace the restoration path with cross connect ports information */ hopcount = 0; spare_count = 0; port1 = p1; port2 = p2; np = LINK->cnode; n1 = np; n = np->id; /* test */ SIGID = np->card[p1].RS.SIGID; strcpy(STR4, ""); sprintf(STR4, "%s(P%sXP%s))", np->name, int2str_(STR2, p1), int2str_(STR3, p2)); if (DEBUG) printf("current path traced=%s\n", STR4); do { n = np->card[p1].RS.NID; p2 = np->card[p1].PSR.link_port; sp = np; np = (node *) recall_list(&net, n); if (DEBUG) printf("%s(P%s) SIGID=%d pathSIGID=%d; path so far=%s\n", np->name, int2str_(STR2, p2), np->card[p2].TS.SIGID, SIGID, STR4); if (DEBUG) printf("%sP%d.RS.NID=%d, ->name=%s\n", sp->name, p1, n, np->name); if (p2 ==0) { printf("Error in tracePath(p1=%d, p2=%d, N%s): p2==0, path=%s\n", port1, port2, n1->name, STR4); break; } if (np->card[p2].TS.SIGID != SIGID) { /* sanity check */ sprintf(STR5, "%s(P%s) SIGID=%d != %d; path so far=%s\n", np->name, int2str_(STR2, p2), np->card[p2].TS.SIGID, SIGID, STR4); printf("%s\n", STR5); return; } p1 = np->card[p2].PSR.assoc_port; if (p1 == 0 && np->id != sender_node->id) { printf("Error in tracePath(p1=%d, p2=%d, N%s): n=%d,(p1==0, xP%dI%dR%d, path=%s\n", port1, port2, n1->name, n, p2, np->card[p2].TS.index, np->card[p2].TS.repeats, STR4); indexTree(sender_node, 0, np->card[p2].TS.index, 0); break; } spare_count++; sprintf(STR5, "%s(P%sXP%s)-%s", np->name, int2str_(STR2, p1), int2str_(STR3, p2), STR4); strcpy(STR4, STR5); hopcount++; if (hopcount > maxrepeats) { printf("Error in tracePath(p1=%d, p2=%d, N%s): hopcount=%d exceeds maxrepeats=%d.\n trace so far = %s\n", port1, port2, n1->name, hopcount, maxrepeats, STR4); indexTree(sender_node, 0, np->card[p2].TS.index, 0); break; } if (DEBUG) printf("current path traced=%s\n", STR4); /* } while ((np->id != break2) && (np->id != break1)); */ } while (np->id != sender_node->id); bw_found++; if (DEBUG) printf("bw_found=%d, bw_needed=%d\n", bw_found, bw_needed); if (lastRestoreTime > LINK->cnode->time) lastRestoreTime += CROSS_CONNECT_TIME; /* connect got put off */ else lastRestoreTime = LINK->cnode->time+CROSS_CONNECT_TIME; if (DEBUG) printf("chooser time=%6.3f msec\n", LINK->cnode->time*1000.0); sprintf(STR5, "rstrd at %6.3f msec (%6.2f%%)---> \n (%s.", lastRestoreTime*1000.0, bw_found*100.0/bw_needed, STR4); int2str_(STR1, SIGID); init_symbol(&restorationTime, STR1, STR5); printf("signal %d %s\n", SIGID, STR5); spare_used += spare_count; rstr_msg_count = msg_count; } Void traceIndexPath(p1, n1) long p1; node *n1; { /* starting from a port's RS backtrace to the other break node used to find why index 0 was sent to chooser, it should be >= 1 in lataxa.net /b=n03-n08 */ Char STR1[MSS], STR2[MSS], STR3[MSS], STR4[2*MSS], STR5[2*MSS]; node *np, *sp; long n; long p2; long SIGID; long spare_count; long index; long port; long hopcount; hopcount = 0; port = p1; np = n1; n = np->id; /* test */ index = np->card[p1].RS.index; strcpy(STR4, ""); sprintf(STR4, "%s(P%sI%d))", np->name, int2str_(STR2, p1), index); if (DEBUG) printf("current index path traced=%s\n", STR4); do { n = np->card[p1].RS.NID; p2 = np->card[p1].PSR.link_port; np = (node *) recall_list(&net, n); if (DEBUG) printf("%s(P%s) SIGID=%d pathSIGID=%d; path so far=%s\n", np->name, int2str_(STR2, p2), np->card[p2].TS.SIGID, SIGID, STR4); if (p2 ==0) { printf("Error in traceIndexPath(p1=%d, N%s): p2==0, path=%s\n", port, n1->name, STR4); break; } p1 = np->card[p2].PSR.assoc_port; if (p1 == 0 && np->id != break2 && np->id !=break1) { printf("Error in traceIndexPath(p1=%d, N%s): n=%d,(p1==0, xP%dI%dR%d, path=%s\n", port, n1->name, n, p2, np->card[p2].TS.index, np->card[p2].TS.repeats, STR4); indexTree(sender_node, 0, index, 0); break; } sprintf(STR5, "%s(P%sI%dXP%sI%d)-%s", np->name, int2str_(STR2, p1), np->card[p1].RS.index, int2str_(STR3, p2), np->card[p2].TS.index, STR4); strcpy(STR4, STR5); hopcount++; if (hopcount > maxrepeats) { printf("Error in traceIndexPath(p1=%d, N%s): hopcount=%d exceeds maxrepeats=%d.\n trace so far = %s\n", port, n1->name, hopcount, maxrepeats, STR4); break; } if (DEBUG) printf("current path traced=%s\n", STR4); } while ((np->id != break2) && (np->id != break1)); if (INTERACTIVE) printf("Trace of index %d =%s\n", index, STR5); if (index == 0) { /* found out why index got changed to 0 */ indexTree(sender_node, 0, np->card[p2].TS.index, 0); } } Local Void xpoint(p1, p2, LINK) long p1, p2; struct LOC_process *LINK; { Char STR1[MSS]; Char STR2[MSS], STR4[MSS]; spanrec *WITH; long SET[MAXPORTSET]; status_reg *WITH1; Char STR5[MSS]; if (DEBUG) { simlog("xpoint"); sprintf(STR4, "P1: %s P2: %s", int2str_(STR1, (long)p1), int2str_(STR2, (long)p2)); simlog(STR4); } sprintf(STR2, "Xconnect at %s with clock of %s", LINK->cnode->name, simtime2str(STR1, LINK->cnode->time)); simlog(STR2); sprintf(STR5, " port %s to port %s", int2str_(STR1, (long)p1), int2str_(STR2, (long)p2)); simlog(STR5); find_symbol_def(STR1, nodename, int2str_(STR4, (long)LINK->cnode->card[p1].RS.NID)); find_symbol_def(STR2, nodename, int2str_(STR5, (long)LINK->cnode->card[p2].RS.NID)); sprintf(STR4, " Node %5s to Node %5s", STR1, STR2 ); simlog(STR4); sprintf(STR4, " Idx %s to Idx %s", int2str_(STR1, (long)LINK->cnode->card[p1].RS.index), int2str_(STR2, (long)LINK->cnode->card[p2].TS.index)); simlog(STR4); sprintf(STR5, " SIGID %s to SIGID %s", int2str_(STR1, LINK->cnode->card[p1].PSR.SIGID), int2str_(STR2, LINK->cnode->card[p2].PSR.SIGID)); simlog(STR5); WITH = &LINK->cnode->l_spans[LINK->cnode->card[p1].RS.NID]; P_remset(WITH->send_set, p1); P_remset(WITH->rec_set, p1); P_remset(WITH->emp_set, p1); WITH = &LINK->cnode->l_spans[LINK->cnode->card[p2].RS.NID]; P_remset(WITH->send_set, p2); P_remset(WITH->rec_set, p2); P_remset(WITH->emp_set, p2); nullout(&LINK->cnode->card[p1].TS, LINK); nullout(&LINK->cnode->card[p2].TS, LINK); nullout(&LINK->cnode->card[p1].RS, LINK); nullout(&LINK->cnode->card[p2].RS, LINK); WITH1 = &LINK->cnode->card[p1].PSR; WITH1->conn = true; WITH1->spare = false; WITH1->assoc_port = p2; WITH1->AIE = true; WITH1->alarm = false; WITH1->SCIE = true; WITH1->RSdel = false; WITH1->SIE = false; WITH1->IDdel = false; WITH1 = &LINK->cnode->card[p2].PSR; WITH1->conn = true; WITH1->spare = false; WITH1->assoc_port = p1; WITH1->AIE = true; WITH1->alarm = false; WITH1->SCIE = true; WITH1->RSdel = false; WITH1->SIE = false; WITH1->IDdel = false; if (LINK->cnode->card[p1].PSR.SIGID != 0 && LINK->cnode->card[p1].PSR.SIGID == LINK->cnode->card[p2].PSR.SIGID) { sprintf(STR2, " ******** Channel Restoration Complete ******** SIGID: %s", int2str_(STR1, LINK->cnode->card[p2].PSR.SIGID)); tracePath(p1, p2, LINK); simlog(STR2); } } /* part of same restoration... id of network fault */ Local long class_(r, LINK) sig_reg r; struct LOC_process *LINK; { return (imin((long)r.source, (long)r.target) + (MAXNODES + 1) * imax((long)r.source, (long)r.target)); } /* determines direction for the signature by order of source, target */ Local senses sense(r1, r2, LINK) sig_reg r1, r2; struct LOC_process *LINK; { if (class_(r1, LINK) == class_(r2, LINK)) { if (r1.source == r2.source) return SAME; else return OPPOSITE; } else return NULL_; } /* identical signatures with opposite sense */ Local boolean complement(r1, r2, LINK) sig_reg r1, r2; struct LOC_process *LINK; { if (((class_(r1, LINK) == class_(r2, LINK)) && (sense(r1, r2, LINK) == OPPOSITE)) && r1.index == r2.index) return true; else return false; } /* move port from one set to another */ Local Void move_(p, s1, s2, LINK) long p; long *s1, *s2; struct LOC_process *LINK; { P_remset(s1, p); P_addset(s2, p); } /* see if any free ports remain to be had in any span other than the present interrupt span... */ Local boolean avail_empties(intspan, LINK) long intspan; struct LOC_process *LINK; { boolean Result, ok; long span; ok = false; span = 0; while (!ok && span < MAXSPANS) { span++; if (span != intspan) ok = (!(P_setequal(null_set,LINK->cnode->l_spans[span].emp_set))); } Result = ok; if (!DEBUG) return Result; if (ok) simlog("avail_empties FOUND"); else simlog("avail_empties NONE"); return Result; } Local Void test_for_involved(LINK) struct LOC_process *LINK; { long span; LINK->cnode->involved = false; for (span = 1; span <= MAXSPANS; span++) { if (P_inset((int)span, LINK->cnode->spans) && !(P_setequal(null_set,LINK->cnode->l_spans[span].rec_set))) LINK->cnode->involved = true; } if (!DEBUG) return; if (LINK->cnode->involved) simlog("test_for_involved YES"); else simlog("test_for_involved NO"); } Local boolean sending_to_span(span, idx, LINK) long span, idx; struct LOC_process *LINK; { boolean Result, ok; long port; Char STR1[MSS], STR2[MSS]; Char STR4[MSS]; if (DEBUG) { simlog("sending_to_span"); sprintf(STR4, "SPAN: %s INDEX: %s", int2str_(STR1, span), int2str_(STR2, idx)); simlog(STR4); } ok = false; port = 0; while (!ok && port < LINK->cnode->nports) { port++; if (P_inset(port, LINK->cnode->l_spans[span].send_set) && LINK->cnode->card[port].TS.index == idx) ok = true; } Result = ok; if (DEBUG && ok) simlog("sending_to_span TRUE"); return Result; } Local Void sender_flood(LINK) struct LOC_process *LINK; { Static long index_stamp; long span; long port; long spancount; long FORLIM1; sig_reg *WITH; if (DEBUG) simlog("sender_flood"); index_stamp = 1; for (span = 1; span <= MAXSPANS; span++) { if (span != LINK->cnode->alarm_span && P_inset((int) span, LINK->cnode->spans)) { spancount = 1; FORLIM1 = LINK->cnode->nports; for (port = 1; port <= FORLIM1; port++) { if (P_inset(port, LINK->cnode->l_spans[span].emp_set) && spancount <= LINK->cnode->lostccts) { WITH = &LINK->cnode->card[port].TS; WITH->index = index_stamp; WITH->repeats = IRV; WITH->source = LINK->cnode->id; WITH->target = LINK->cnode->alarm_span; WITH->SIGID = 0; /* ??? */ loadTS(port, LINK); move_(port, LINK->cnode->l_spans[span].emp_set, LINK->cnode->l_spans[span].send_set, LINK); index_stamp++; spancount++; } } } } } Local Void sel_broadcast(iport, LINK) long iport; struct LOC_process *LINK; { long root_span, root_index, span; long port; Char STR1[MSS], STR2[MSS]; Char STR4[MSS]; sig_reg *WITH; node *n; if (DEBUG) simlog("sel_broadcast"); root_span = LINK->cnode->card[iport].RS.NID; root_index = LINK->cnode->card[iport].RS.index; if (DEBUG) { sprintf(STR4, " ROOTSPAN: %s ROOTINDEX: %s", int2str_(STR1, root_span), int2str_(STR2, root_index)); simlog(STR4); } for (span = 1; span <= MAXSPANS; span++) { if (span != root_span && P_inset((int)span, LINK->cnode->spans)) { if ((!P_setequal(null_set,LINK->cnode->l_spans[span].emp_set)) && (!sending_to_span(span, root_index, LINK))) { /* port = 1; it should start with port 0 */ port = 0; do { port++; } while (!P_inset(port, LINK->cnode->l_spans[span].emp_set)); WITH = &LINK->cnode->card[port].TS; /* if (LINK->cnode->id == 4 && port == 120) { printf("Error: sel_broad: %d->%dP%d-P%d,RS.index=%d, r=%d, source=%d, target=%d, SIGID=%d\n", LINK->cnode->card[iport].RS.NID, LINK->cnode->id, iport, port, LINK->cnode->card[iport].RS.index, LINK->cnode->card[iport].RS.repeats, LINK->cnode->card[iport].RS.source, LINK->cnode->card[iport].RS.target, LINK->cnode->card[iport].RS.SIGID); printf("\t TS.index=%d, r=%d, source=%d, target=%d, SIGID=%d\n", WITH->index, WITH->repeats, WITH->source, WITH->target, WITH->SIGID); } */ WITH->index = LINK->cnode->card[iport].RS.index; WITH->repeats = LINK->cnode->card[iport].RS.repeats + 1; WITH->source = LINK->cnode->card[iport].RS.source; WITH->target = LINK->cnode->card[iport].RS.target; WITH->SIGID = LINK->cnode->card[iport].RS.SIGID; /* Chow: add the following if to fix 8-6cut bug */ if (WITH->source == 0) LINK->cnode->card[port].PSR.assoc_port = 0; else LINK->cnode->card[port].PSR.assoc_port = iport; loadTS(port, LINK); move_(port, LINK->cnode->l_spans[span].emp_set, LINK->cnode->l_spans[span].send_set, LINK); if (INTERACTIVE) { n = (node *) recall_list(&net, span); printf("Sel_broadcast: P%d->P%dR%dI%dS%d->N%s\n", iport, port, WITH->repeats, WITH->index, WITH->SIGID, n->name); } } } } } Local Void build_affected_ports_table(LINK) struct LOC_process *LINK; { long port; long SET[MAXPORTSET]; long FORLIM; if (DEBUG) simlog("build_affected_ports_table"); LINK->cnode->lostccts = 0; P_expset(LINK->cnode->affected_ports, 0L); P_expset(LINK->cnode->alarmed_ports, 0L); FORLIM = LINK->cnode->nports; for (port = 1; port <= FORLIM; port++) { if (LINK->cnode->card[port].PSR.alarm && !LINK->cnode->card[port].PSR.spare && LINK->cnode->card[port].PSR.RSdel) { LINK->cnode->lostccts++; P_addset(LINK->cnode->affected_ports, LINK->cnode->card[port].PSR.assoc_port); P_addset(LINK->cnode->alarmed_ports, port); if (INTERACTIVE) printf("N%s, P%d->affected_ports, P%d->alarmed_ports, SIGID=%d\n", LINK->cnode->name, LINK->cnode->card[port].PSR.assoc_port, port, LINK->cnode->card[port].PSR.SIGID); LINK->cnode->card[port].PSR.RSdel = false; } } } /* My better signature routine... */ Local boolean betterSig(ip, LINK) long ip; struct LOC_process *LINK; { boolean better; long lport; Char STR1[MSS]; Char STR2[MSS]; if (DEBUG) { simlog("betterSig"); sprintf(STR2, "PORT: %s", int2str_(STR1, (long)LINK->n)); simlog(STR2); } better = false; if (complement(LINK->cnode->card[ip].TS, LINK->cnode->card[ip].RS, LINK)) { better = true; return better; } lport = 0; while (lport < LINK->cnode->nports && !better) { lport++; if (lport != ip && LINK->cnode->card[lport].RS.index == LINK->cnode->card[ip].RS.index) { if (LINK->cnode->card[ip].RS.repeats < LINK->cnode->card[lport].RS.repeats) better = true; } } return better; } Local boolean betterSigExists(ip, LINK) long ip; struct LOC_process *LINK; { boolean better; long lport; Char STR1[MSS]; Char STR2[MSS]; if (DEBUG) { simlog("betterSigExists"); sprintf(STR2, "PORT: %s", int2str_(STR1, (long)LINK->n)); simlog(STR2); } better = false; lport = 0; while (lport < LINK->cnode->nports && !better) { lport++; if (lport != ip && LINK->cnode->card[lport].RS.NID != LINK->cnode->id && LINK->cnode->card[lport].RS.index == LINK->cnode->card[ip].RS.index) { if (LINK->cnode->card[lport].RS.repeats < LINK->cnode->card[ip].RS.repeats) better = true; else { if ((LINK->cnode->card[lport].RS.repeats == LINK->cnode->card[ip].RS.repeats) && complement( LINK->cnode->card[ip].RS, LINK->cnode->card[ip].TS, LINK)) better = true; } } } return better; } Local Void cancel_tx_sigs(rootport, protport, newemptyport, LINK) long rootport, protport; boolean *newemptyport; struct LOC_process *LINK; { boolean skip; node *n; node *rn; node *pn; long rootspan, protspan, lspan; long lport; Char STR1[MSS], STR2[MSS]; Char STR4[MSS]; if (DEBUG) { simlog("cancel_tx_sigs"); sprintf(STR4, "RP: %s PP: %s", int2str_(STR1, (long)rootport), int2str_(STR2, (long)protport)); simlog(STR4); } /* if (rootport == protport) LINK->cnode->card[protport].PSR.assoc_port = 0; */ rootspan = LINK->cnode->card[rootport].RS.NID; protspan = LINK->cnode->card[protport].RS.NID; for (lspan = 1; lspan <= MAXSPANS; lspan++) { if (P_inset((int)lspan, LINK->cnode->spans) && lspan != protspan) { lport = 0; skip = false; while (!skip && lport < LINK->cnode->nports) { lport++; if ((P_inset(lport, LINK->cnode->l_spans[lspan].send_set) && LINK->cnode->card[lport].PSR.assoc_port == rootport)) { skip = true; if (INTERACTIVE) { n = (node *) recall_list(&net, lspan); rn = (node *) recall_list(&net, rootspan); pn = (node *) recall_list(&net, protspan); if (lspan != LINK->cnode->card[lport].RS.NID) printf("cancel_tx_sigs: lspan%d !=[lport%d].RS.NID\n", lspan, lport); printf("cancel_tx_sigs(N%s->P%dI%dR%d-P%dI%dR%d->N%s): P%dI%dR%d->N%s nullout\n", rn->name, rootport, LINK->cnode->card[rootport].RS.index, LINK->cnode->card[rootport].RS.repeats, protport, LINK->cnode->card[protport].TS.index, LINK->cnode->card[protport].TS.repeats, pn->name, lport, LINK->cnode->card[lport].TS.index, LINK->cnode->card[lport].TS.repeats, n->name); } nullout(&LINK->cnode->card[lport].TS, LINK); LINK->cnode->card[lport].PSR.assoc_port = 0; loadTS(lport, LINK); move_(lport, LINK->cnode->l_spans[lspan].send_set, LINK->cnode->l_spans[lspan].emp_set, LINK); *newemptyport = true; } } } } } Local Void cancel_tx_sigs_with_index_on(rootport, protport, newemptyport, LINK) long rootport, protport; boolean *newemptyport; struct LOC_process *LINK; { boolean skip; node *n; node *rn; node *pn; long rootspan, protspan, lspan; long lport; Char STR1[MSS], STR2[MSS]; Char STR4[MSS]; if (DEBUG) { simlog("cancel_tx_sigs_with_index_on"); sprintf(STR4, "RP: %s PP: %s", int2str_(STR1, (long)rootport), int2str_(STR2, (long)protport)); simlog(STR4); } /* if (rootport == protport) LINK->cnode->card[protport].PSR.assoc_port = 0; */ rootspan = LINK->cnode->card[rootport].RS.NID; protspan = LINK->cnode->card[protport].RS.NID; for (lspan = 1; lspan <= MAXSPANS; lspan++) { if (P_inset((int)lspan, LINK->cnode->spans) && lspan != protspan) { lport = 0; skip = false; while (!skip && lport < LINK->cnode->nports) { lport++; if ((P_inset(lport, LINK->cnode->l_spans[lspan].send_set) && LINK->cnode->card[lport].PSR.assoc_port == rootport)) { skip = true; if (INTERACTIVE) { n = (node *) recall_list(&net, lspan); rn = (node *) recall_list(&net, rootspan); pn = (node *) recall_list(&net, protspan); if (lspan != LINK->cnode->card[lport].RS.NID) printf("cancel_tx_sigs_w_index: lspan%d !=[lport%d].RS.NID\n", lspan, lport); printf("cancel_tx_sigs_w_index(N%s->P%dI%dR%d-P%dI%dR%d->N%s): P%dI%dR%d->N%s nullout\n", rn->name, rootport, LINK->cnode->card[rootport].RS.index, LINK->cnode->card[rootport].RS.repeats, protport, LINK->cnode->card[protport].TS.index, LINK->cnode->card[protport].TS.repeats, pn->name, lport, LINK->cnode->card[lport].TS.index, LINK->cnode->card[lport].TS.repeats, n->name); } nullout(&LINK->cnode->card[lport].TS, LINK); /* leave the index on */ LINK->cnode->card[lport].TS.index = LINK->cnode->card[rootport].RS.index; LINK->cnode->card[lport].PSR.assoc_port = 0; loadTS(lport, LINK); move_(lport, LINK->cnode->l_spans[lspan].send_set, LINK->cnode->l_spans[lspan].emp_set, LINK); *newemptyport = true; } } } } } Local Void start_timer(LINK) struct LOC_process *LINK; { erec *ev; if (DEBUG) simlog("start_timer"); ev = (erec *)Malloc(sizeof(erec)); ev->time = LINK->cnode->time + TIMEOUT; ev->src = LINK->cnode->id; ev->dst = LINK->cnode->id; ev->next = LINK->cnode->id; ev->msg = NULL; init_symbol(&ev->msg, "TYPE", TIMER_MSG); queue_event(ev); } Local Void tandemFSM(ip, involved, new_empty_port, LINK) long ip; boolean *involved, *new_empty_port; struct LOC_process *LINK; { long ispan; boolean was_empty, is_empty, new_sig, was_precursor, is_cancel; boolean better; long was_index, new_index; long was_source, was_target; long scanport, otherport; long otherspan; Char STR1[MSS], STR2[MSS]; card_hw *WITH; long SET[MAXPORTSET]; long SET1[MAXPORTSET]; sig_reg *WITH1; long FORLIM; node *n; if (DEBUG) { simlog("tandemFSM"); sprintf(STR2, "PORT: %s", int2str_(STR1, (long)ip)); simlog(STR2); } /* if (LINK->cnode->card[ip].PSR.conn && LINK->cnode->card[ip].PSR.SIGID != 0) LINK->shnevent = SIGID_transit; else { */ if (LINK->cnode->card[ip].RS.SIGID != 0) { if (!LINK->cnode->card[ip].PSR.conn) { n = (node *) recall_list(&net, LINK->cnode->card[ip].RS.NID); printf("Error tandemFSM: %sP%d->%sP%d-P%d with SIGID=%d but not connected\n", n->name, LINK->cnode->card[ip].PSR.link_port, LINK->cnode->name, ip, LINK->cnode->card[ip].PSR.assoc_port, LINK->cnode->card[ip].RS.SIGID); return; } else LINK->shnevent = SIGID_transit; } else { WITH = &LINK->cnode->card[ip]; ispan = WITH->RS.NID; was_empty = !P_inset(ip, LINK->cnode->l_spans[ispan].rec_set); new_sig = WITH->PSR.RSdel; is_empty = (WITH->RS.source == 0 && WITH->RS.index == 0); is_cancel = (WITH->RS.source == 0 && WITH->RS.index != 0); was_precursor = false; was_index = 0; new_index = WITH->RS.index; if (!was_empty) { scanport = 0; while (!was_precursor && scanport < LINK->cnode->nports) { scanport++; if (P_inset(scanport, LINK->cnode->l_spans[LINK->cnode->card[scanport].RS.NID].send_set) && LINK->cnode->card[scanport].PSR.assoc_port == ip) { was_precursor = true; was_index = LINK->cnode->card[scanport].TS.index; was_source = LINK->cnode->card[scanport].TS.source; was_target = LINK->cnode->card[scanport].TS.target; } } } if (MY_FSM_LOGIC) { if (WITH->RS.repeats <= maxrepeats) { if (!was_empty) { if (is_empty) LINK->shnevent = sig_vanish; else { /* not empty */ if (is_cancel) LINK->shnevent = sig_cancel; else if (new_sig) { if (complement(WITH->TS, WITH->RS, LINK)) LINK->shnevent = new_complement_sig; else { if (was_precursor && new_index == was_index) { if (WITH->RS.repeats + 1 != LINK->cnode->card[scanport].TS.repeats) LINK->shnevent = update_repeat; else LINK->shnevent = repeatable_sig; } else { if (betterSig(ip, LINK)) LINK->shnevent = better_sig; else LINK->shnevent = repeatable_sig; } } } else LINK->shnevent = repeatable_sig; } } else { /* was empty */ if (is_empty) LINK->shnevent = nonrepeatable_sig; else { /* not empty */ if (new_sig) { if (complement(WITH->TS, WITH->RS, LINK)) LINK->shnevent = new_complement_sig; else { if (betterSig(ip, LINK)) LINK->shnevent = better_sig; else LINK->shnevent = repeatable_sig; } } else LINK->shnevent = bad_state; } } } else LINK->shnevent = overrange_sig; } else { LINK->shnevent = nonrepeatable_sig; if (!was_empty && is_cancel) LINK->shnevent = sig_cancel; if (!was_empty && is_empty) LINK->shnevent = sig_vanish; if ((!is_empty) && (!betterSigExists(ip, LINK))) LINK->shnevent = repeatable_sig; if (new_sig && complement(WITH->RS, WITH->TS, LINK)) LINK->shnevent = new_complement_sig; if (!is_empty && !was_empty && new_index == was_index) LINK->shnevent = update_repeat; if (WITH->RS.repeats > maxrepeats) LINK->shnevent = overrange_sig; } } *involved = false; *new_empty_port = false; printshnevent(LINK->shnevent); switch (LINK->shnevent) { case SIGID_transit: /* if (DEBUG) */ sprintf(STR1, " ## Transit @ %s SIGID=%ld Ports:(%ld)%ld->%ld(%ld) Index=%ld", LINK->cnode->name, LINK->cnode->card[ip].PSR.SIGID, LINK->cnode->card[ip].PSR.link_port, ip, LINK->cnode->card[ip].PSR.assoc_port, LINK->cnode->card[LINK->cnode->card[ip].PSR.assoc_port].PSR.link_port, LINK->cnode->card[ip].RS.index ); simlog(STR1); LINK->cnode->card[LINK->cnode->card[ip].PSR.assoc_port].TS.SIGID = LINK->cnode->card[ip].PSR.SIGID; loadTS(LINK->cnode->card[ip].PSR.assoc_port, LINK); *involved = true; break; case sig_vanish: if (DEBUG) simlog("TS: sig_vanish"); P_setcpy(LINK->cnode->l_spans[ispan].rec_set, P_setdiff(SET1, LINK->cnode->l_spans[ispan].rec_set, P_addset(P_expset(SET, 0L), ip))); if (LINK->cnode->card[ip].RS.index != 0) cancel_tx_sigs_with_index_on(ip, ip, new_empty_port, LINK); else cancel_tx_sigs(ip, ip, new_empty_port, LINK); test_for_involved(LINK); break; case sig_cancel: if (DEBUG) simlog("TS: sig_cancel"); P_setcpy(LINK->cnode->l_spans[ispan].rec_set, P_setdiff(SET1, LINK->cnode->l_spans[ispan].rec_set, P_addset(P_expset(SET, 0L), ip))); insertSigCancelList(LINK->cnode, was_source, was_target, was_index); cancel_tx_sigs_with_index_on(ip, ip, new_empty_port, LINK); test_for_involved(LINK); break; case new_complement_sig: if (DEBUG) simlog("TS: new_complement_sig"); otherport = LINK->cnode->card[ip].PSR.assoc_port; otherspan = LINK->cnode->card[otherport].RS.NID; insertSigCancelList(LINK->cnode, was_source, was_target, was_index); cancel_tx_sigs_with_index_on(otherport, ip, new_empty_port, LINK); WITH1 = &LINK->cnode->card[otherport].TS; WITH1->source = LINK->cnode->card[ip].RS.source; WITH1->target = LINK->cnode->card[ip].RS.target; WITH1->index = LINK->cnode->card[ip].RS.index; WITH1->repeats = LINK->cnode->card[ip].RS.repeats + 1; LINK->cnode->card[otherport].PSR.assoc_port = ip; loadTS(otherport, LINK); P_setcpy(LINK->cnode->l_spans[otherspan].send_set, P_setunion(SET1, LINK->cnode->l_spans[otherspan].send_set, P_addset(P_expset(SET, 0L), otherport))); xpoint(ip, otherport, LINK); *involved = true; break; case update_repeat: if (DEBUG) simlog("TS: update_repeat"); if (!inSigCancelList(LINK->cnode, ip)){ FORLIM = LINK->cnode->nports; for (scanport = 1; scanport <= FORLIM; scanport++) { if (LINK->cnode->card[scanport].PSR.assoc_port == ip && LINK->cnode->card[scanport].RS.NID != ispan) { LINK->cnode->card[scanport].TS.repeats = LINK->cnode->card[ip].RS.repeats + 1; loadTS(scanport, LINK); } } } *involved = true; break; case better_sig: if (DEBUG) simlog("TS: better_sig"); if (!inSigCancelList(LINK->cnode, ip)){ /* Chow: replace the following code since at n07-n03cut latax.net we found case where scanport > LINK->cnode->nports scanport = 0; do { scanport++; } while ((scanport <= LINK->cnode->nports) && (LINK->cnode->card[scanport].TS.index != LINK->cnode->card[ip].RS.index)); cancel_tx_sigs(LINK->cnode->card[scanport].PSR.assoc_port, ip, new_empty_port, LINK); */ scanport = 0; better = false; while (scanport < LINK->cnode->nports && !better) { scanport++; if (scanport != ip && LINK->cnode->card[scanport].RS.index == LINK->cnode->card[ip].RS.index) { if (LINK->cnode->card[ip].RS.repeats < LINK->cnode->card[scanport].RS.repeats) better = true; } } if (scanport <= LINK->cnode->nports && better) cancel_tx_sigs(scanport, ip, new_empty_port, LINK); if (was_empty) P_setcpy(LINK->cnode->l_spans[ispan].rec_set, P_setunion(SET1, LINK->cnode->l_spans[ispan].rec_set, P_addset(P_expset(SET, 0L), ip))); sel_broadcast(ip, LINK); } *involved = true; break; case repeatable_sig: if (DEBUG) simlog("TS: repeatable_sig"); if (!inSigCancelList(LINK->cnode, ip)){ if (was_precursor && was_index != new_index) cancel_tx_sigs(ip, ip, new_empty_port, LINK); if (was_empty) P_setcpy(LINK->cnode->l_spans[ispan].rec_set, P_setunion(SET1, LINK->cnode->l_spans[ispan].rec_set, P_addset(P_expset(SET, 0L), ip))); sel_broadcast(ip, LINK); } *involved = true; break; case nonrepeatable_sig: if (DEBUG) simlog("TS: unrepeatable_sig"); if (was_precursor) cancel_tx_sigs(ip, ip, new_empty_port, LINK); if (was_empty) P_setcpy(LINK->cnode->l_spans[ispan].rec_set, P_setunion(SET1, LINK->cnode->l_spans[ispan].rec_set, P_addset(P_expset(SET, 0L), ip))); *involved = true; break; case overrange_sig: if (DEBUG) simlog("TS: overrange_sig"); test_for_involved(LINK); break; default: printf(" Bad Tandem FSM state.\n"); _Escape(0); break; } } Local Void loadRS(ev, LINK) erec *ev; struct LOC_process *LINK; { node *fromnode; Char tstr[MSS]; long buf; long pid; long error; boolean flag; Char STR1[MSS]; card_hw *WITH; Char STR2[MSS]; Char STR3[MSS], STR4[MSS]; if (DEBUG) simlog("loadRS"); find_symbol_def(tstr, ev->msg, "CBUF"); error = (sscanf(tstr, "%ld", &buf) == 0); find_symbol_def(tstr, ev->msg, "PORT"); error = (sscanf(tstr, "%d", &pid) == 0); buffers_in_use--; WITH = &LINK->cnode->card[pid]; /* RS (channel), TS, and PSR flag setting goes here!!! */ if (WITH->PSR.SCIE) { flag = false; flag = (flag || WITH->RS.source != channel[buf].source); flag = (flag || WITH->RS.target != channel[buf].target); flag = (flag || WITH->RS.index != channel[buf].index); flag = (flag || WITH->RS.repeats != channel[buf].repeats); flag = (flag || WITH->RS.RA != channel[buf].RA); flag = (flag || WITH->RS.SIGID != channel[buf].SIGID); WITH->PSR.RSdel = flag; } if (WITH->PSR.SIE) WITH->PSR.IDdel = (WITH->RS.SIGID != channel[buf].SIGID); /* WITH->RS = channel[buf]; */ WITH->RS.NID = channel[buf].NID; WITH->RS.source = channel[buf].source; WITH->RS.target = channel[buf].target; WITH->RS.index = channel[buf].index; WITH->RS.repeats = channel[buf].repeats; WITH->RS.SIGID = channel[buf].SIGID; WITH->RS.RA = channel[buf].RA; WITH->PSR.SIGID = channel[buf].SIGID; if (WITH->PSR.AIE) { WITH->PSR.alarm = LINK->cnode->card[pid].RS.RA; WITH->TS.RA = LINK->cnode->card[pid].RS.RA; } /* return channel buffer to unused status */ channel[buf].NID = 0; LINK->cnode->int_port = pid; LINK->cnode->int_span = LINK->cnode->card[LINK->cnode->int_port].RS.NID; if (INTERACTIVE) { fromnode = (node *) recall_list(&net, LINK->cnode->int_span); printf("loadRS: at %sP%d from %s", LINK->cnode->name, pid, fromnode->name); printf(" RS.index=%d, repeats=%d, SIGID=%d\n", WITH->RS.index, WITH->RS.repeats, WITH->RS.SIGID); } if (DEBUG) { sprintf(STR4, "PT: %s SP: %s", int2str_(STR1, (long)pid), int2str_(STR2, (long)LINK->cnode->int_span)); simlog(STR4); } if (DEBUG) { sprintf(STR3, "IX: %s ID: %s", int2str_(STR1, (long)LINK->cnode->card[pid].RS.index), int2str_(STR2, channel[buf].SIGID)); simlog(STR3); } } Local Void initialize_span_sets(LINK) struct LOC_process *LINK; { long port, FORLIM; long SET[MAXPORTSET]; long SET1[MAXPORTSET]; if (DEBUG) simlog("initialize_span_sets"); FORLIM = LINK->cnode->nports; for (port = 1; port <= FORLIM; port++) { if (LINK->cnode->card[port].PSR.spare && !LINK->cnode->card[port].PSR.alarm && LINK->cnode->id != LINK->cnode->card[port].RS.NID) { P_addset(LINK->cnode->spans, LINK->cnode->card[port].RS.NID); if (LINK->cnode->card[port].TS.SIGID == 0) P_setcpy(LINK->cnode->l_spans[LINK->cnode->card[port].RS.NID].emp_set, P_setunion(SET1, LINK->cnode->l_spans[LINK->cnode->card[port].RS.NID].emp_set, P_addset(P_expset(SET, 0L), port))); else P_setcpy(LINK->cnode->l_spans[LINK->cnode->card[port].RS.NID].send_set, P_setunion(SET1, LINK->cnode->l_spans[LINK->cnode->card[port].RS.NID].send_set, P_addset(P_expset(SET, 0L), port))); if (LINK->cnode->card[port].RS.SIGID != 0) P_setcpy(LINK->cnode->l_spans[LINK->cnode->card[port].RS.NID].rec_set, P_setunion(SET1, LINK->cnode->l_spans[LINK->cnode->card[port].RS.NID].rec_set, P_addset(P_expset(SET, 0L), port))); } if (LINK->cnode->card[port].PSR.alarm) LINK->cnode->alarm_span = LINK->cnode->card[port].RS.NID; } } Static Void process(ev, n_, cnode_) erec *ev; long n_; node *cnode_; { struct LOC_process V; Char tempstr[MSS]; node *hold; Char mtype[MSS]; long iport; long index; long cspan; long cport; boolean flag; long minrepeats, currentSIGID; Char STR1[MSS], STR2[MSS]; long FORLIM; Char STR4[MSS]; card_hw *WITH; Char STR5[MSS]; Char STR6[MSS]; Char STR7[MSS]; long SET[MAXPORTSET], SET1[MAXPORTSET]; long FORLIM1; sig_reg *WITH1; V.n = n_; V.cnode = cnode_; V.shnevent = initial_value; /* check for simulation end */ if (ev->time >= STOPTIME) { stop = true; simlog(" "); sprintf(STR2, "Unrestored channels remaining: %s", int2str_(STR1, V.cnode->tofix)); simlog(STR2); return; } /* determine msg type */ find_symbol_def(mtype, ev->msg, "TYPE"); if (strcmp(mtype, TIMER_MSG)) lastEventTime = ev->time; /* check for update of node local time */ if (ev->time > V.cnode->time && ev->time < 3600.0) V.cnode->time = ev->time; if (V.cnode->time > newestNodeTime) newestNodeTime = V.cnode->time; V.cnode->referenceCount++; V.cnode->recentEventTime = ev->time; updateRecentList(V.cnode); /* check if "SIM" control messages */ if (!strcmp(mtype, SIM_MSG)) { find_symbol_def(tempstr, ev->msg, "ACTION"); if (strcmp(tempstr, "BREAK")) /* set state & deactivate link */ return; if (V.n == break1) { FORLIM = V.cnode->nports; bw_needed = 0; bw_found = 0; spare_used = 0; for (idx = 1; idx <= FORLIM; idx++) { if (V.cnode->card[idx].RS.NID == break2 && V.cnode->card[idx].TS.SIGID != 0) { /* Chow: on checking 04-02 break, besides the ports with SIGID=150-3, the next two ports with SIGID = 0 This is a temporary fix which rules out those with SIGID=0 */ V.cnode->card[idx].TS.RA = true; bw_needed++; if (DEBUG) printf(" bw_needed=%d, SIGID=%d, idx=%d\n", bw_needed, V.cnode->card[idx].TS.SIGID, idx); V.cnode->card[idx].TS.SIGID = 0; /* SM: fix ??? */ hold = (node *)recall_list(&net, (long)V.cnode->card[idx].RS.NID); hold->card[V.cnode->card[idx].PSR.link_port].PSR.alarm = true; hold->card[V.cnode->card[idx].PSR.link_port].PSR.RSdel = true; loadTS((int)idx, &V); sprintf(STR2, " Node: %s --> ALARM on port %s", hold->name, int2str_(STR1, (long)V.cnode->card[idx].PSR.link_port)); simlog(STR2); } } if (bw_needed == 0) { printf("There is no span from %s to %s\n", break1str, break2str); exit(3); } else printf(" bw_needed = %d\n", bw_needed); return; } FORLIM = V.cnode->nports; for (idx = 1; idx <= FORLIM; idx++) { if (V.cnode->card[idx].RS.NID == break1 && V.cnode->card[idx].TS.SIGID != 0) { V.cnode->card[idx].TS.RA = true; V.cnode->card[idx].TS.SIGID = 0; /* SM: fix ??? */ hold = (node *)recall_list(&net, (long)V.cnode->card[idx].RS.NID); hold->card[V.cnode->card[idx].PSR.link_port].PSR.alarm = true; hold->card[V.cnode->card[idx].PSR.link_port].PSR.RSdel = true; loadTS((int)idx, &V); sprintf(STR2, " Node: %s --> ALARM on port %s", hold->name, int2str_(STR1, (long)V.cnode->card[idx].PSR.link_port)); simlog(STR2); } } return; /* don't need to process normal states */ } /* start of normal message processing... */ msg_count++; if (!strcmp(mtype, INTR_MSG)) { loadRS(ev, &V); iport = V.cnode->int_port; if (!(V.cnode->card[iport].PSR.alarm || V.cnode->card[iport].PSR.RSdel || V.cnode->card[iport].PSR.IDdel)) return; if (DEBUG) { WITH = &V.cnode->card[iport]; sprintf(STR7, " Fault: %s*%s IndexID: %s Repeat: %s SIGID: %s", int2str_(STR1, (long)WITH->RS.source), int2str_(STR2, (long)WITH->RS.target), int2str_(STR4, (long)WITH->RS.index), int2str_(STR5, (long)WITH->RS.repeats), int2str_(STR6, WITH->RS.SIGID)); simlog(STR7); } /* time it takes to process incoming msg */ /* if (chooser_node != NULL) { if (V.cnode->id == chooser_node->id) { printf("chooser time before processing the incoming msg=%6.3f msec\n", V.cnode->time*1000.0); printf("msg_process_delay=%f sec\n", V.cnode->msg_process_delay); printf("V.cnode->card[iport].RS.source=%d\n", V.cnode->card[iport].RS.source); } } */ if (V.cnode->card[iport].RS.source != 0) { if (PPTOVERRIDE >= 0.0) V.cnode->time += PPTOVERRIDE + noise(); else V.cnode->time += V.cnode->msg_process_delay + noise(); } else { currentSIGID = V.cnode->card[iport].RS.SIGID; if (currentSIGID > 0) { find_symbol_def(tempstr, newsignals, int2str_(STR2, currentSIGID)); if (!strcmp(tempstr, NOT_FOUND)) *tempstr = '\0'; sprintf(tempstr + strlen(tempstr), " %s-%s", find_symbol_def(STR1, nodename, int2str_(STR4, (long)ee->src)), find_symbol_def(STR5, nodename, int2str_(STR6, (long)ee->next))); /* chow: add restoration time at the end of tempstr */ /* printf("Signal %s is restored with segment %s at %s sec.\n", int2str_(STR4, currentSIGID), tempstr, simtime2str(STR1, V.cnode->time)); int2str_(STR4, currentSIGID); sprintf(STR5, "%s", STR4); init_symbol(&restorationTime, STR5, simtime2str(STR1, V.cnode->time)); */ init_symbol(&newsignals, int2str_(STR4, currentSIGID), tempstr); } } /* if (chooser_node != NULL) { if (V.cnode->id == chooser_node->id) { printf("chooser time after processing the incoming msg=%6.3f msec\n", V.cnode->time*1000.0); } } */ } if (V.cnode->state == NORMAL) { if (V.cnode->card[iport].PSR.SIGID != 0 && V.cnode->card[iport].PSR.conn) { V.shnevent = SIGID_transit; } else if (V.cnode->card[iport].RS.source == 0 && !V.cnode->card[iport].RS.RA) { /* Chow: it is possible to receive cancel signature */ V.shnevent = sig_vanish; } else { initialize_span_sets(&V); if (V.cnode->card[iport].PSR.alarm) { /* chow: use the break1str as sender since us.net use node specific repeat limit, which one is sender matter. if (V.cnode->id > V.cnode->card[iport].RS.NID) */ if (strcmp(V.cnode->name, break1str) == 0) V.shnevent = senderalarm; else V.shnevent = chooseralarm; } else { /* assume tandem node */ if (V.cnode->card[iport].RS.repeats < V.cnode->repeatlimit) V.shnevent = repeatable_sig; else V.shnevent = nonrepeatable_sig; } } switch (V.shnevent) { case SIGID_transit: V.cnode->card[V.cnode->card[iport].PSR.assoc_port].TS.SIGID = V.cnode->card[iport].PSR.SIGID; loadTS(V.cnode->card[iport].PSR.assoc_port, &V); break; case senderalarm: if (DEBUG) simlog("NS: senderalarm"); build_affected_ports_table(&V); V.cnode->restccts = 0; sender_flood(&V); start_timer(&V); V.cnode->state = SENDER; maxrepeats = V.cnode->repeatlimit; sender_node = V.cnode; break; case chooseralarm: if (DEBUG) simlog("NS: chooseralarm"); build_affected_ports_table(&V); V.cnode->restccts = 0; P_expset(V.cnode->indices_chosen, 0L); V.cnode->state = CHOOSER; chooser_node = V.cnode; break; case repeatable_sig: if (DEBUG) simlog("NS: repeatable_sig"); sel_broadcast(iport, &V); P_setcpy(V.cnode->l_spans[V.cnode->card[iport].RS.NID].rec_set, P_setunion(SET1, V.cnode->l_spans[V.cnode->card[iport].RS.NID].rec_set, P_addset(P_expset(SET, 0L), iport))); V.cnode->state = TANDEM; break; case nonrepeatable_sig: if (DEBUG) simlog("NS: nonrepeatable_sig"); V.cnode->state = NORMAL; break; } printshnevent(V.shnevent); return; } if (V.cnode->state == SENDER) { if (!strcmp(mtype, TIMER_MSG)) V.shnevent = timer_int; else { if (V.cnode->card[iport].RS.target == V.cnode->id && V.cnode->card[iport].PSR.spare && !V.cnode->card[iport].PSR.alarm) V.shnevent = return_sig; else { if (V.cnode->card[iport].PSR.alarm && !V.cnode->card[iport].PSR.spare) V.shnevent = late_alarm; } } switch (V.shnevent) { case timer_int: if (DEBUG) simlog("SS: timer_int"); printf( "***************** TIMEOUT TIMER received at %s\n", simtime2str(STR1,V.cnode->time) ); for (cspan = 1; cspan <= MAXSPANS; cspan++) { if (P_inset((int)cspan, V.cnode->spans) && cspan != V.cnode->alarm_span) { FORLIM1 = V.cnode->nports; for (cport = 1; cport <= FORLIM1; cport++) { if (P_inset(cport, V.cnode->l_spans[cspan].send_set) && (!complement(V.cnode->card[cport].RS, V.cnode->card[cport].TS, &V))) { nullout(&V.cnode->card[cport].TS, &V); V.cnode->card[cport].PSR.assoc_port = 0; loadTS(cport, &V); move_(cport, V.cnode->l_spans[cspan].send_set, V.cnode->l_spans[cspan].emp_set, &V); } } } } break; case return_sig: if (DEBUG) simlog("SS: return_sig"); if (complement(V.cnode->card[iport].RS, V.cnode->card[iport].TS, &V)) { V.cnode->restccts++; cport = 0; flag = true; if (INTERACTIVE) printf("return_sig: sender receives complement sig from P%d\n", iport); while (flag && cport < V.cnode->nports) { cport++; if (!P_inset(cport, V.cnode->affected_ports)) continue; P_remset(V.cnode->affected_ports, cport); nullout(&V.cnode->card[iport].TS, &V); V.cnode->card[iport].PSR.assoc_port = 0; V.cnode->card[iport].TS.SIGID = V.cnode->card[cport].RS.SIGID; /* simulation can be speed up by sending SIGID directly to the Chooser without using the SIGID_transit simualtion loadTS(iport, &V); xpoint(iport, cport, &V); if (INTERACTIVE) printf("return_sig: sender P%d send SIGID=%d\n", iport, V.cnode->card[iport].TS.SIGID); */ xpoint(iport, cport, &V); /* V.cnode->time += CROSS_CONNECT_TIME; */ sendSIGID(iport, &V); flag = false; } if (flag && INTERACTIVE) { printf("return_sig: can not find any port in affected_ports\n"); if (P_setequal(null_set,V.cnode->affected_ports)) printf(" N%s->affected_ports is empty\n", V.cnode->name); else printf(" N%s->affected_ports is not empty\n", V.cnode->name); } if (V.cnode->lostccts == V.cnode->restccts) { for (cspan = 1; cspan <= MAXNODES; cspan++) { if (P_inset((int)cspan, V.cnode->spans) && cspan != V.cnode->alarm_span) { FORLIM1 = V.cnode->nports; for (cport = 1; cport <= FORLIM1; cport++) { if (P_inset(cport, V.cnode->l_spans[cspan].send_set) && (!complement(V.cnode->card[cport].RS, V.cnode->card[cport].TS, &V))) { /* Chow: remove the following cancel msgs, reduce msg count, and dramatically improve the ending time index = V.cnode->card[cport].TS.index; nullout(&V.cnode->card[cport].TS, &V); V.cnode->card[cport].TS.index = index; V.cnode->card[iport].PSR.assoc_port = 0; loadTS(cport, &V); */ move_(cport, V.cnode->l_spans[cspan].send_set, V.cnode->l_spans[cspan].emp_set, &V); } } } } /* cnode^.state := NORMAL; */ return; } } break; case late_alarm: if (DEBUG) simlog("SS: late_alarm"); if (!P_inset(iport, V.cnode->alarmed_ports)) { V.cnode->lostccts++; P_addset(V.cnode->affected_ports, V.cnode->card[iport].PSR.assoc_port); P_addset(V.cnode->alarmed_ports, iport); } break; } V.cnode->state = SENDER; printshnevent(V.shnevent); return; } if (V.cnode->state == CHOOSER) { if (V.cnode->card[iport].PSR.alarm && !V.cnode->card[iport].PSR.spare) V.shnevent = late_alarm; else { if (V.cnode->card[iport].PSR.RSdel && V.cnode->card[iport].RS.target == V.cnode->id && V.cnode->card[iport].RS.source == V.cnode->alarm_span) V.shnevent = new_forward_sig; else { if (V.cnode->card[iport].PSR.IDdel) V.shnevent = SIGID_arrive; } } switch (V.shnevent) { case new_forward_sig: if (DEBUG) simlog("CS: new_forward_sig"); cspan = V.cnode->card[iport].RS.NID; move_(iport, V.cnode->l_spans[cspan].emp_set, V.cnode->l_spans[cspan].rec_set, &V); if (V.cnode->restccts < V.cnode->lostccts) { if (V.cnode->card[iport].RS.index == 0) { printf("At Chooser, index should not be 0 when it arrives\n"); traceIndexPath(iport, V.cnode); /* Chow: we need to figure why index got changed to 0 */ /* this temporay fix achieve 100% restoration but it will not terminate!!! */ } else { if (!P_inset(V.cnode->card[iport].RS.index, V.cnode->indices_chosen)) { sprintf(STR1, " && Index arrived @ %s Index=%ld", V.cnode->name, V.cnode->card[iport].RS.index ); simlog(STR1); traceIndexPath(iport, V.cnode); P_addset(V.cnode->indices_chosen, V.cnode->card[iport].RS.index); WITH1 = &V.cnode->card[iport].TS; WITH1->target = V.cnode->alarm_span; WITH1->source = V.cnode->id; WITH1->repeats = IRV; WITH1->index = V.cnode->card[iport].RS.index; loadTS(iport, &V); move_(iport, V.cnode->l_spans[cspan].emp_set, V.cnode->l_spans[cspan].send_set, &V); V.cnode->card[iport].PSR.SIE = true; V.cnode->card[iport].PSR.SCIE = false; V.cnode->restccts++; } } } break; case SIGID_arrive: if (DEBUG) { simlog("CS: SIGID_arrive"); printf("SIGID_arrive, SIGID=%d, Port=%d\n", V.cnode->card[iport].RS.SIGID, iport); } flag = true; cport = 0; while (flag && cport < V.cnode->nports) { cport++; if (P_inset(cport, V.cnode->affected_ports) && V.cnode->card[cport].RS.SIGID == V.cnode->card[iport].RS.SIGID) { flag = false; } } if (flag) { printf(" cannot found affected port with SIGID=%d at N%s\n", V.cnode->card[iport].RS.SIGID, V.cnode->name); } P_remset(V.cnode->affected_ports, cport); xpoint(iport, cport, &V); if (*V.cnode->affected_ports == 0L) return; /* cnode^.state := NORMAL; */ break; case late_alarm: if (DEBUG) simlog("CS: late_alarm"); if (!P_inset(iport, V.cnode->alarmed_ports)) { V.cnode->lostccts++; P_addset(V.cnode->affected_ports, V.cnode->card[iport].PSR.assoc_port); P_addset(V.cnode->alarmed_ports, iport); /* procedure to handle late alarm ?? */ } break; } V.cnode->state = CHOOSER; printshnevent(V.shnevent); return; } if (V.cnode->state != TANDEM) return; V.cnode->involved = false; V.cnode->new_empty_port = false; tandemFSM(iport, &V.cnode->involved, &V.cnode->new_empty_port, &V); if (V.cnode->new_empty_port && V.cnode->involved) { minrepeats = V.cnode->repeatlimit; for (cspan = 1; cspan <= MAXNODES; cspan++) { if (P_inset((int)cspan, V.cnode->spans)) { FORLIM1 = V.cnode->nports; for (cport = 1; cport <= FORLIM1; cport++) { if (P_inset(cport, V.cnode->l_spans[cspan].rec_set)) { if (V.cnode->card[cport].RS.repeats < minrepeats) minrepeats = V.cnode->card[cport].RS.repeats; } } } } if (INTERACTIVE) printf("minrepeats =%d\n", minrepeats); for (idx = minrepeats; idx < V.cnode->repeatlimit; idx++) { cport = 0; while (cport < V.cnode->nports) { cport++; if ((P_inset(cport, V.cnode->l_spans[V.cnode->card[cport].RS.NID].rec_set) && V.cnode->card[cport].RS.repeats == idx) && avail_empties((long)V.cnode->card[cport].RS.NID, &V)) { hold=(node *) recall_list(&net, V.cnode->card[cport].RS.NID); tandemFSM(cport, &V.cnode->involved, &V.cnode->new_empty_port, &V); } } } } if (V.cnode->involved) V.cnode->state = TANDEM; else V.cnode->state = NORMAL; } #define LONGEST_PATH 20 /* Local variables for init_nodes: */ struct LOC_init_nodes { long SIGID; } ; /* Local variables for init_path_link: */ struct LOC_init_path_link { struct LOC_init_nodes *LINK; } ; Local long nextfree(c, id, LINK) node *c; long id; struct LOC_init_path_link *LINK; { long Result; long scanport; boolean search; scanport = 0; search = true; while (search && scanport < c->nports) { scanport++; if (c->card[scanport].RS.NID == id && !c->card[scanport].PSR.conn) { Result = scanport; search = false; } } if (!search) return Result; printf("Insufficent channel connectivity for specified SIGNAL path.\n"); printf(" NODE = %s #Ports/Node = %d SIGID = %12ld\n", c->name, c->nports, LINK->LINK->SIGID); printf(" ABORTING SHN !!!!\n"); _Escape(0); return Result; } Local long matchSIGID(c, id, LINK) node *c; long id; struct LOC_init_path_link *LINK; { long Result; long scanport; boolean search; scanport = 0; search = true; while (search && scanport < c->nports) { scanport++; if (c->card[scanport].PSR.SIGID == id) { Result = scanport; search = false; } } if (!search) return Result; printf("Could not find associated SIGNAL path.\n"); printf(" NODE = %s SIGID = %12ld\n", c->name, LINK->LINK->SIGID); printf(" ABORTING SHN !!!!\n"); _Escape(0); return Result; } Local Void init_path_link(ID, prev, current, next, LINK) long ID; node *prev, *current, *next; struct LOC_init_nodes *LINK; { struct LOC_init_path_link V; long cport, nport; card_hw *WITH; /* will not handle case of prev == current == next */ V.LINK = LINK; if (prev == current) { /* create local path initiation channel port */ current->cports++; cport = current->cports; WITH = ¤t->card[cport]; WITH->TS.NID = current->id; WITH->RS.NID = current->id; WITH->TS.SIGID = ID; WITH->RS.SIGID = ID; WITH->PSR.spare = false; WITH->PSR.conn = true; WITH->PSR.SIGID = ID; WITH->PSR.assoc_port = 0; /*next step backpatches this field */ } if (next == current) { /* create local path terminus channel port */ /* why the termination channel port and initiationg channel port have different initialization? This may be the reason why 293 signature is not fully restored. */ current->cports++; cport = current->cports; current->card[cport].TS.NID = current->id; current->card[cport].RS.NID = current->id; /*next step backpatches this field */ } cport = nextfree(current, next->id, &V); WITH = ¤t->card[cport]; /* note: must find assoc before setting SIGID!!! */ WITH->PSR.assoc_port = matchSIGID(current, ID, &V); /* backpatching required here! */ current->card[WITH->PSR.assoc_port].PSR.assoc_port = cport; WITH->TS.SIGID = ID; WITH->RS.SIGID = ID; WITH->PSR.spare = false; WITH->PSR.conn = true; WITH->PSR.SIGID = ID; if (next == current) return; nport = current->card[cport].PSR.link_port; WITH = &next->card[nport]; WITH->TS.SIGID = ID; WITH->RS.SIGID = ID; WITH->PSR.spare = false; WITH->PSR.conn = true; WITH->PSR.SIGID = ID; WITH->PSR.assoc_port = 0; /* needs backpatching since next dest unknown */ } Void insertRecentList(np n) { n->prev = NULL; n->next = nodelist; if (nodelist != NULL) nodelist->prev = n; nodelist = n; } Void updateRecentList(np n) { np prev; np next; if (n == nodelist) return; prev = n->prev; next = n->next; if (prev != NULL) prev->next = next; if (next != NULL) next->prev = prev; n->prev = NULL; n->next = nodelist; if (nodelist != NULL) nodelist->prev = n; nodelist = n; } Void printRecentList() { long i; np n; n = nodelist; if (nodelist == NULL) { printf("nodelist = NULL\n"); return; } printf("\nnode "); for (i=0; i< 7; i++) { printf("%6s ", n->name); if (n->next == NULL) { printf("\n! node %s's next is NULL in printRecentList!\n", n->name); return; } n = n->next; } printf("\nrecenttime"); n = nodelist; for (i=0; i< 7; i++) { printf("%9.7f ", n->recentEventTime); if (n->next == NULL) { printf("\n! node %s's next is NULL in printRecentList!\n", n->name); return; } n = n->next; } n = nodelist; printf("\nreferCount"); for (i=0; i< 7; i++) { printf("%6d ", n->referenceCount); if (n->next == NULL) { printf("\n! node %s's next is NULL in printRecentList!\n", n->name); return; } n = n->next; } printf("\n\n"); } Static Void init_nodes(s) Char *s; { struct LOC_init_nodes V; FILE *netdef; Char line[MSS], tline[MSS]; long idx, jdx, kdx, ldx, err, linkcount, pathsize, nodecount; char pathnode[LONGEST_PATH]; float distance; float linkdistance; node *cnode, *idxnode, *jdxnode; Char STR2[MSS]; long TEMP; long FORLIM; Char *TEMP1; long FORLIM1; long SET[MAXPORTSET]; double TEMP2, TEMP3; char type[20]; long V_Hcoord = 0; long nports; long workingports; long spareports; long internalports; netdef = NULL; printf("NODES initialization started. \n"); netdef = fopen(to_lower(STR2,s), "r"); /* define SIM node, mainly for logging purposes as source */ cnode = (node *)Malloc(sizeof(node)); strcpy(cnode->name, "SIM"); init_symbol(&nodename, int2str_(STR2, 0L), cnode->name); add_list(&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); if (netsize > MAXNODES) { printf(" Number of specified nodes exceeds program limits!\n"); printf(" SHN ABOORTING!!! \n"); _Escape(0); } FORLIM = netsize; /* for all nodes ... */ for (idx = 1; idx <= FORLIM; idx++) { cnode = (node *)Malloc(sizeof(node)); cnode->time = 0.0; cnode->tofix = 0; cnode->recentEventTime = 0.0; cnode->referenceCount = 0; cnode->sigCancelList = NULL; insertRecentList(cnode); fgets(line, 256, netdef); TEMP1 = strchr(line, '\n'); if (TEMP1 != NULL) *TEMP1 = 0; tokenize(tline, line); get_token(cnode->name, tline); init_symbol(&nodename, int2str_(STR2, idx), cnode->name); cnode->id = idx; err = (sscanf(get_token(STR2, tline), "%d", &linkcount) == 0); err = (sscanf(get_token(STR2, tline), "%g", &cnode->msg_process_delay) == 0); /* this field is now used for node specific repeat limit err = (sscanf(get_token(STR2, tline), "%d", (int *)(&cnode->state)) == 0); */ err = (sscanf(get_token(STR2, tline), "%d", &cnode->repeatlimit) == 0); if (overwriteRL) { cnode->repeatlimit = maxrepeats; if (INTERACTIVE) printf("repeat limit of %s is overwritten to %d.\n", cnode->name, cnode->repeatlimit); } else if (cnode->repeatlimit == 0) { cnode->repeatlimit = maxrepeats; if (INTERACTIVE) printf("repeat limit of %s is set to default value %d.\n", cnode->name, cnode->repeatlimit); } else { if (INTERACTIVE) 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(STR2, tline), "%g", &cnode->latitude) == 0); err = (sscanf(get_token(STR2, tline), "%g", &cnode->longitude) == 0); err = (sscanf(get_token(STR2, tline), "%d", &cnode->workingports) == 0); err = (sscanf(get_token(STR2, tline), "%d", &cnode->spareports) == 0); err = (sscanf(get_token(STR2, tline), "%d", &cnode->internalports) == 0); err = (sscanf(get_token(STR2, tline), "%d", &cnode->nports) == 0); init_list(&cnode->links); /* for all links... */ workingports = 0; spareports = 0; for (jdx = 1; jdx <= linkcount; jdx++) { clink = (linkdata *)Malloc(sizeof(linkdata)); fgets(line, 256, netdef); TEMP1 = strchr(line, '\n'); if (TEMP1 != NULL) *TEMP1 = 0; tokenize(tline, line); err = (sscanf(get_token(STR2, tline), "%d", &clink->dest) == 0); clink->active = (strcmp(get_token(STR2, tline), "1") == 0); clink->delay = 0.0; err = (sscanf(get_token(STR2, tline), "%d", &clink->work) == 0); err = (sscanf(get_token(STR2, tline), "%d", &clink->spare) == 0); workingports += clink->work; spareports += clink->spare; if (!OVERWRITE_LINK_DISTANCE) { if (LINK_DISTANCE_IN_MILES != 0) err = (sscanf(get_token(STR2, 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 (INTERACTIVE) { 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_list(&cnode->links, (Anyptr)clink, jdx); } if (workingports != cnode->workingports) { printf("the total working channel number, %d, in spans \n It is not the same as specified, %d, in node %s specification line\n", workingports, cnode->workingports, cnode->name); exit(3); } if (spareports != cnode->spareports) { printf("the total spare channel number, %d, in spans \n It is not the same as specified, %d, in node %s specification line\n", spareports, cnode->spareports, cnode->name); exit(3); } if (INTERACTIVE) printf("node %s has %d ports\n", cnode->name, cnode->nports); add_list(&net, (Anyptr)cnode, idx); } printf("NODES: Phase 1 complete... basic read & build links.\n"); FORLIM = netsize; /* initialize nodes and calculate link delays based on relative distances */ for (idx = 1; idx <= FORLIM; idx++) { idxnode = (node *)recall_list(&net, idx); /* %%% initialize all SHN data structures */ P_expset(idxnode->spans, 0L); for (jdx = 1; jdx <= MAXNODES; jdx++) { P_setcpy(idxnode->l_spans[jdx].emp_set, P_expset(SET, 0L)); P_setcpy(idxnode->l_spans[jdx].send_set, P_expset(SET, 0L)); P_setcpy(idxnode->l_spans[jdx].rec_set, P_expset(SET, 0L)); } /* initialized ports for this node */ idxnode->card = (card_hw *) Malloc((idxnode->nports+1)*sizeof(card_hw)); for (jdx = 1; jdx <= idxnode->nports; jdx++) { idxnode->card[jdx].TS = INIT_SIGREG; idxnode->card[jdx].RS = INIT_SIGREG; idxnode->card[jdx].PSR = INIT_STATUSREG; } idxnode->int_port = 0; P_expset(idxnode->affected_ports, 0L); P_expset(idxnode->alarmed_ports, 0L); P_expset(idxnode->indices_chosen, 0L); idxnode->alarm_span = 0; idxnode->int_span = 0; idxnode->restccts = 0; idxnode->lostccts = 0; idxnode->involved = false; idxnode->new_empty_port = false; FORLIM1 = idxnode->links.count; nports = 0; for (jdx = 1; jdx <= FORLIM1; jdx++) { clink = (linkdata *)recall_list(&idxnode->links, jdx); jdxnode = (node *)recall_list(&net, (long)clink->dest); TEMP2 = idxnode->latitude - jdxnode->latitude; TEMP3 = idxnode->longitude - jdxnode->longitude; if (OVERWRITE_LINK_DISTANCE) { if (V_Hcoord == 1) { distance = sqrt((TEMP2*TEMP2+TEMP3*TEMP3)/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 + TEMP3 * TEMP3); clink->delay = distance * KMPERDEG / (LIGHTSPEED / REFRACINDEX); } if (INTERACTIVE) { printf("link %s-%s delay is overwritten/set to %f seconds.\n", cnode->name, jdxnode->name, clink->delay); } } linkcount = clink->work + clink->spare; for (kdx = 1; kdx <= linkcount; kdx++) { nports++; idxnode->card[nports].TS.NID = idxnode->id; idxnode->card[nports].RS.NID = clink->dest; idxnode->card[nports].PSR.link_delay = clink->delay; } } idxnode->cports = nports; } printf("NODES: Phase 2 complete... init all node structures.\n"); FORLIM = netsize; /* determine and assign card to card connectivities for event delivery */ for (idx = 1; idx <= FORLIM; idx++) { idxnode = (node *)recall_list(&net, idx); FORLIM1 = netsize; for (jdx = 1; jdx <= FORLIM1; jdx++) { if (idx != jdx) { jdxnode = (node *)recall_list(&net, jdx); kdx = 0; ldx = 0; do { do { kdx++; } while (kdx <= idxnode->nports && idxnode->card[kdx].RS.NID != jdxnode->id); do { ldx++; } while (ldx <= jdxnode->nports && jdxnode->card[ldx].RS.NID != idxnode->id); if (kdx <= idxnode->nports && ldx <= jdxnode->nports) { idxnode->card[kdx].PSR.link_port = ldx; jdxnode->card[ldx].PSR.link_port = kdx; } } while (kdx <= idxnode->nports && ldx <= jdxnode->nports); } } } printf("NODES: Phase 3 complete... connectivities defined.\n"); pathsize = -1; fscanf(netdef, "%ld%*[^\n]", &pathsize); printf( "Number of paths = %ld\n", pathsize ); getc(netdef); if (pathsize <= 0) { printf("Signal path connectivity not defined for this network!\n"); printf(" Please examine signal path segment of NET file.\n"); _Escape(0); } /* for all paths ... set up connectivity through network... may ignore working/spare of initial network definition */ for (ldx = 1; ldx <= pathsize; ldx++) { fscanf(netdef, "%ld", &V.SIGID); fgets(line, 256, netdef); TEMP1 = strchr(line, '\n'); if (TEMP1 != NULL) *TEMP1 = 0; if (DEBUG) printf("Path %4ld%8ld = %s\n", ldx, V.SIGID, line); if (false) init_symbol(&signals, int2str_(STR2, V.SIGID), line); /* uses too much memory? */ tokenize(tline, line); get_token(line, tline); nodecount = 0; while (strcmp(line, "\032")) { nodecount++; cnode = (node *)head_list(&net); while (cnode != NULL && strcmp(cnode->name, line)) cnode = (node *)next_list(&net); if (cnode == NULL) { printf("Specified node NAME if signal path not found!\n"); _Escape(0); } pathnode[nodecount - 1] = cnode->id; get_token(line, tline); } if (nodecount == 0) { printf("No node IDs for signal path found!\n"); _Escape(0); } for (kdx = 1; kdx <= nodecount; kdx++) { idx = kdx - 1; jdx = kdx + 1; if (kdx == 1) idx = kdx; if (kdx == nodecount) jdx = kdx; idxnode = (node *)recall_list(&net, (long)pathnode[idx - 1]); /* get node data */ cnode = (node *)recall_list(&net, (long)pathnode[kdx - 1]); /* get node data */ jdxnode = (node *)recall_list(&net, (long)pathnode[jdx - 1]); /* get node data */ init_path_link(V.SIGID, idxnode, cnode, jdxnode, &V); } } printf("NODES: Phase 4 complete... signal paths built.\n"); FORLIM = netsize; /* determine and assign card to card connectivities for event delivery */ for (idx = 1; idx <= FORLIM; idx++) { idxnode = (node *)recall_list(&net, idx); if (INTERACTIVE) printf("node %s has %d ports, cports=%d\n", idxnode->name, idxnode->nports, idxnode->cports); } if (netdef != NULL) fclose(netdef); netdef = NULL; if (netdef != NULL) fclose(netdef); } #undef LONGEST_PATH main(argc, argv) long argc; Char *argv[]; { FILE *fp; _PROCEDURE HeapError; _PROCEDURE ExitProc; Char STR1[MSS], STR2[MSS]; char FORLIM; Char STR3[MSS], STR4[MSS], STR5[MSS]; Char STR6[MSS]; Char STR7[MSS]; Char STR8[MSS]; Char STR9[MSS]; Char *cp; long opt_bw_found, opt_spare_used; boolean found; _strings_init(); _netsim_init(); _math_init(); PASCAL_MAIN(argc, argv); log_ = NULL; SaveEvents = false; stop = false; msg_count = 0; sparesused = 0; timer_seqnum = 0; sender_node = NULL; chooser_node = NULL; P_expset(null_set, 0L); options = NULL; init_symbol(&options, "FIRST_PARAM", NOT_FOUND); init_symbol(&options, "STOPTIME=", "10.0"); init_symbol(&options, "INTERACTIVE", NOT_FOUND); init_symbol(&options, "TIMEOUT=", "10.0"); init_symbol(&options, "1TSTIME=", "0.0"); 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, "WRITE_LINK=", NOT_FOUND); init_symbol(&options, "CROSS_CONNECT_TIME=", "0.01"); init_symbol(&options, "REPEATS=", NOT_FOUND); init_symbol(&options, "GROVERLOGIC", NOT_FOUND); *result = '\0'; cli(result, &options, '/'); if (*result != '\0') puts(result); find_symbol_def(result, options, "FIRST_PARAM"); if (!strcmp(result, NOT_FOUND)) { printf("Required net definition filename not found on command line!\n"); _Escape(0); } find_symbol_def(infilename, options, "FIRST_PARAM"); 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)); /* start write of screen's header message... (completed by process()) */ printf("SHN algorithm results... with %s\n", infilename); printf("Break occurred 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; idx = (sscanf(find_symbol_def(STR2, options, "REPEATS="), "%d", &maxrepeats) == 0); printf("MAXREPEATS (longest explored signature path length) set to %d\n", maxrepeats); } else { printf("NODE SPECIFIC REPEAT LIMIT or default value (13) is used.\n"); } find_symbol_def(result, options, "GROVERLOGIC"); if (strcmp(result, NOT_FOUND) == 0) { printf("TANDEMFSM LOGIC is set to that of UCCS' \n"); MY_FSM_LOGIC = true; } else { printf("TANDEMFSM LOGIC is set to that of GROVER's\n"); MY_FSM_LOGIC = false; } find_symbol_def(result, options, "INTERACTIVE"); if (!strcmp(result, NOT_FOUND)) { printf("INTERACTIVE is set to false\n"); } else { INTERACTIVE = true; printf("INTERACTIVE is set to true\n"); } 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"); } idx = (sscanf(find_symbol_def(STR2, options, "1TSTIME="), "%g",&loadTS_time) == 0); idx = (sscanf(find_symbol_def(STR2, options, "STOPTIME="), "%g", &STOPTIME) == 0); idx = (sscanf(find_symbol_def(STR2, options, "TIMEOUT="), "%g", &TIMEOUT) == 0); idx = (sscanf(find_symbol_def(STR2, options, "LCS="), "%g", &LINK_CHECK_SCALEFACTOR) == 0); idx = (sscanf(find_symbol_def(STR2, options, "2INDEX="), "%g", &REFRACINDEX) == 0); printf("Refraction Index is set at %f.\n", REFRACINDEX); idx = (sscanf(find_symbol_def(STR2, options, "PPTOVERRIDE="), "%g", &PPTOVERRIDE) == 0); idx = (sscanf(find_symbol_def(STR2, options, "NOISE="), "%g", &NOISE_SIZE) == 0); idx = (sscanf(find_symbol_def(STR2, options, "X_SPEED="), "%d", &TX_SPEED) == 0); idx = (sscanf(find_symbol_def(STR2, options, "MSG_LENGTH="), "%d", &MSG_LENGTH) == 0); transmit_delay = MSG_LENGTH*8/(TX_SPEED*1000.0); printf("Message length is set at %d bytes\n", MSG_LENGTH); printf("Transmission speed is set at %d Kbps\n", TX_SPEED); idx = (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); strcpy(outfilename, "OUT"); find_symbol_def(outfilename, options, "OUT="); /* find_symbol_def(STR2, options, "DEBUG="); if (strcmp(STR2, "Y") == 0) { printf("DEBUG MODE is set\n"); DEBUG = true; } */ log_ = fopen(outfilename, "w"); if (log_ != NULL) /* rewind(log_); */; else log_ = tmpfile(); if (log_ == NULL) _EscIO(FileNotFound); nodename = NULL; if (SaveEvents) set_save_mode(); pathcount = 1; init_list(&net); signals = NULL; newsignals = NULL; restorationTime = NULL; init_nodes(infilename); FORLIM = netsize; for (i = 1; i <= FORLIM; i++) { find_symbol_def(result, nodename, int2str_(STR1, (long)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(true); 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_(STR2, (long)break1)); init_symbol(&ee->msg, "ACTION", "BREAK"); init_symbol(&ee->msg, "TYPE", SIM_MSG); 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_(STR2, (long)break2)); init_symbol(&ee->msg, "ACTION", "BREAK"); init_symbol(&ee->msg, "TYPE", SIM_MSG); queue_event(ee); for (idx = 0; idx <= MAXBUFFERS; idx++) channel[idx].NID = 0; eecount = 0; do { ee = next_event(); eecount++; if (ee != NULL) { nextnode = (node *)recall_list(&net, (long)ee->next); if (DEBUG) { /* print event info */ sprintf(STR9, "%s %s %s -> %s of Type: %s", simtime2str(STR2, ee->time), simtime2str(STR3, bounds(0.0, nextnode->time - ee->time, 1.0e30)), find_symbol_def(STR4, nodename, int2str_(STR5, (long)ee->src)), find_symbol_def(STR6, nodename, int2str_(STR7, (long)ee->next)), find_symbol_def(STR8, ee->msg, "TYPE")); simlog(STR9); } /* do event processing at node */ process(ee, ee->next, nextnode); if (INTERACTIVE && eecount % skipcount == 0) { printf("eecount=%d, continue? (y, n, q, or for skiping events before stop)\n", eecount); gets(STR2); if (!strcmp(STR2, "n")) exit(0); if (!strcmp(STR2, "q")) exit(0); if (strcmp(STR2, "y")) { if (strlen(STR2) != 0) { idx = atoi(STR2); if (idx != INT_MAX || idx != INT_MIN) skipcount = idx; } } } if (msg_count % 100 == 0 && sender_node != NULL && chooser_node != NULL) { msg_count = msg_count; printf("msg_count=%.5ld@%s sec Buf#=%.5ld bwRes=%d SenderRes=%.4ld ChooserRes=%.4ld\n", msg_count, simtime2str(STR3, ee->time), buffers_in_use, bw_found, sender_node->restccts, chooser_node->restccts ); if (INTERACTIVE) printRecentList(); } if (!SaveEvents) { /* release dynamic memeory */ release_all_symbols(&ee->msg); Free(ee); } } else stop = true; } while (!stop); printf("Last Non Time Out Event Time = %f\n", lastEventTime); printf("Total msg_count=%d\n", msg_count); 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); } fclose(fp); printf("%s", STR1); fprintf(stderr, "%s", STR1); fp = fopen("netres.shn.res", "a"); if (fp == NULL) { fprintf(stderr, "can not open netres.shn.res\n"); } fprintf(fp, "%s", STR1); log_network(false); putchar('\n'); fflush(log_); P_ioresult = 0; if (log_ != NULL) fclose(log_); log_ = NULL; if (log_ != NULL) fclose(log_); exit(0); } /* End. */