/* $Id: segal.c,v 10.1 92/10/06 23:07:03 ca Exp $ */ /* * MaRS Maryland Routing Simulator * Copyright (c) 1991 University of Maryland * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. U.M. makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: Cengiz Alaettinoglu, Klaudia Dussa-Zieger, Ibrahim Matta * Systems Design and Analysis Group * Department of Computer Science * University of Maryland at College Park. */ /* * Routing Module - Merlin and Segall Algorithm * */ #include #include #include "sim.h" #include "q.h" #include "list.h" #include "component.h" #include "log.h" #include "comptypes.h" #include "packet.h" #include "eventdefs.h" #include "event.h" #include "node.h" #include "segal.h" #include "link.h" #include "perf.h" #ifdef DEBUG extern Log debug_log; #endif #define IT(g) (*((InfoTable *)(g->info_table->u.p))) static caddr_t segal_create(), segal_delete(), segal_neighbor(), segal_uneighbor(), segal_start(), segal_reset(), segal_start_computation(), segal_processing(); static int routing_processing_time(); static int broadcast_pkt(), sendnd(), add_new_node(); void fr_space(), events_of_sink(), recv_events_of_i(), req_events_of_i(); void wake_up_event(), shutdown_event(); static void sendndp(), readyupall(); char *make_it_text(); static int index_at_IT(), recv11(), recv12(), recv121(), recv13(), recv132(), recv1321(), recv22(), recv21(), recv22nc(), recv22nc1(), recv33(), recv32or321(), recv2020(), get_cycle_no(), fail11(), fail13(), fail132(), fail1321(); caddr_t segal_action(src, g, type, pkt, arg) Component *src; register Segalt *g; int type; Packet *pkt; caddr_t arg; { caddr_t result = NULL; dbg_set_level(DBG_ERR); /* Just a big switch on type of event */ switch (type) { case EV_RESET: #ifdef DEBUG dbg_write(debug_log, DBG_INFO, (Component *)g, "reset"); #endif result = segal_reset(g); break; case EV_CREATE: /* Minor sanity check first-- g should be NULL when initializing. */ #ifdef DEBUG if (g) dbg_write(debug_log, DBG_INFO, (Component *)NULL, "SEGAL Generator initialization called with non-null pointer."); #endif result = segal_create((char *)arg); break; case EV_DEL: result = segal_delete(g); break; case EV_NEIGHBOR: result = segal_neighbor(g, (Component *)arg); break; case EV_UNEIGHBOR: result = segal_uneighbor(g, (Component *)arg); break; case EV_MK_PEER: result = (caddr_t) g; break; case EV_START: result = segal_start(g); break; case EV_STOP: result = (caddr_t) g; break; /* The preceding were the commands. Now the actual events */ case EV_ROUTE_PROCESSING: result = segal_processing(g, pkt); break; case EV_START_COMPUTATION: result = segal_start_computation(g); break; default: #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)g, "got unexpected event of type %x", type); #endif break; } return(result); } static caddr_t segal_create(name) register char *name; { Segalt *newg; /* Memory for the component structure. */ newg = (Segalt *)sim_malloc(sizeof(Segalt)); /* First things first-- copy name into the new structure. */ strncpy(newg->segal_name, name, 40); /* have to create a neighbor list */ newg->segal_neighbors = l_create(); newg->segal_params = q_create(); newg->segal_class = ROUTE_CLASS; newg->segal_type = SEGAL; newg->segal_action = segal_action; newg->segal_menu_up = FALSE; /* Initialize the parameters */ (void)param_init((Component *)newg, "Name", (PFD)NULL, make_name_text, make_short_name_text, param_input_name, 0, DisplayMask | InputMask, 0.0); newg->brdcast_period = param_init((Component *)newg, "Time btw new cycle starts (msec)", int_calc, make_int_text, make_short_int_text, param_input_int, 0, DisplayMask | ModifyMask, 0.0); pval(newg, brdcast_period)->u.i = 10000; newg->sd = param_init((Component *)newg, "Standard deviation", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, DisplayMask | ModifyMask, 0.0); pval(newg, sd)->u.i = 1000; newg->info_table = param_init((Component *)newg, "Information table", (PFD)NULL, make_text, make_it_text, (PFI)NULL, TEXT_METER, DisplayMask | CanHaveLogMask | CanHaveMeterMask, 0.0); pval(newg, info_table)->u.p = sim_malloc(sizeof(InfoTable)); newg->local_top = param_init((Component *)newg, "Local topology table", (PFD)NULL, make_text, make_ltt_text, (PFI)NULL, TEXT_METER, DisplayMask | CanHaveLogMask | CanHaveMeterMask, 0.0); pval(newg, local_top)->u.p = (caddr_t) NULL; newg->routing_table = param_init((Component *)newg, "Routing table", (PFD)NULL, make_text, make_rt_text, (PFI)NULL, TEXT_METER, DisplayMask | CanHaveLogMask | CanHaveMeterMask, 0.0); pval(newg, routing_table)->u.p = sim_malloc(sizeof(RoutingTable)); newg->processing_time = routing_processing_time; newg->no_of_nodes = 0; newg->node = (Component *) NULL; #ifdef DEBUG dbg_write(debug_log, DBG_INFO, (Component *)newg, "segal generator initialized"); #endif return((caddr_t)newg); } static caddr_t segal_delete(g) register Segalt *g; { free(g->routing_table->u.p); free(g->info_table->u.p); comp_delete((Component *) g); return (caddr_t) g; } static caddr_t segal_reset(g) Segalt *g; { g->no_of_nodes = 0; g->link_cost_time = 0; if (g->segal_neighbors->l_len) add_new_node(g, g->node, (Component *) NULL); return (caddr_t) g; } static caddr_t segal_neighbor(g, c) register Segalt *g; register Component *c; { caddr_t result; /* Put the passed neighbor into my neighbor list, but only if it is a legal neighbor (a node). Also can only have one neighbor. */ result = (caddr_t)add_neighbor((Component *)g, c, 1, 1, NODE_CLASS); if (result != (caddr_t)NULL) { g->local_top->u.p = (caddr_t)((Nodee *)c)->loc_topology_table; g->node = c; add_new_node(g, c, (Component *)NULL); } return result; } static caddr_t segal_uneighbor(g, c) register Segalt *g; register Component *c; { caddr_t result; result = (caddr_t)remove_neighbor((Component *)g, c); if (result != (caddr_t)NULL) { g->local_top->u.p = (caddr_t) NULL; g->node = (Component *) NULL; g->no_of_nodes = 0; } return result; } static caddr_t segal_start(g) register Segalt *g; { int i; if (g->segal_neighbors->l_len != 1) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)g, "Segal Module not connected to a node"); #endif return((caddr_t)NULL); } if (!lcostfcn_adr) { printf("LINK_COST_FUNC typed component not found...\n"); return((caddr_t)NULL); } /* get initial link status */ for (i = 0; LTT(g)[i].n_nd != (Component *)NULL; i++) { IT(g)[0].link_status [i] = *LTT(g)[i].l_status; } /* start a new cycle */ ev_enqueue(EV_START_COMPUTATION, (Component *)g, (Component *)g, ev_now(), g->segal_action, (Packet *)NULL, (caddr_t)NULL); /* Something non-NULL to return */ return((caddr_t)g); } static int routing_processing_time(g, pkt) register Segalt *g; register Packet *pkt; { switch (pkt->rt_pk.rt_type) { case RT_LINK_SHUTDOWN : return 2000; case RT_LINK_WAKEUP : return 2000; case RT_NODE_SHUTDOWN : return 10; case RT_NODE_WAKEUP : return 10; case RT_MSG : return 3000; case RT_REQ : return 2000; default : ; } return 10; } static int add_new_node(g, c, told_by) register Segalt *g; Component *c; Component *told_by; { int ind; int i; ind = g->no_of_nodes; g->no_of_nodes++; RT(g)[ind].dest = c; RT(g)[ind].cost = 0; RT(g)[ind].hop = (ind) ? LTT(g)[index_at_LTT_by_node((Routet *)g, told_by)].n_link : (Component *) NULL; IT(g)[ind].dest = c; IT(g)[ind].cost = 0; IT(g)[ind].hop = told_by; IT(g)[ind].max_no = 0; IT(g)[ind].cycle_no = 0; IT(g)[ind].state = 1; for (i = 0; LTT(g)[i].n_nd != (Component *)NULL; i++) { IT(g)[ind].cost_via [i] = MARS_INFINITY; IT(g)[ind].link_status [i] = *LTT(g)[i].l_status; } for (; i < MAX_LINKS; i++) { IT(g)[ind].cost_via [i] = MARS_INFINITY; IT(g)[ind].link_status [i] = 'D'; } log_param((Component *)g, g->routing_table); return ind; } static caddr_t segal_start_computation(g) register Segalt *g; { unsigned int time_now, ticks; /* schedule next computation */ time_now = ev_now(); ticks = time_btw_broadcast(g) / USECS_PER_TICK; ev_enqueue(EV_START_COMPUTATION, (Component *)g, (Component *)g, time_now + ticks, g->segal_action, (Packet *)NULL, (caddr_t)NULL); if (*(char *)((Nodee *)g->node)->nd_status->u.p == 'D') #ifdef SEGAL_DEBUG { printf("%s : node is down cant start a new cycle at %d ticks\n", g->segal_name, time_now); #endif return((caddr_t)g); #ifdef SEGAL_DEBUG } #endif /* node is UP */ compute_link_cost_metrics((Routet*)g); if (IT(g)[0].state != 1) /* node is not ready */ #ifdef SEGAL_DEBUG { printf("%s : sink not in state 1, cant start a new cycle at %d ticks\n", g->segal_name, time_now); #endif return ((caddr_t)g); #ifdef SEGAL_DEBUG } #endif /* start a new cycle */ IT(g)[0].cycle_no ++; /* 0 means sink == g->node */ if (sendnd(g, 0, (Component *) NULL)) /* returns true if it could transmit */ IT(g)[0].state = 2; return((caddr_t)g); } static int sendnd(g, sink_ind, avoid) /* will broadcast the pkt to every neighbor but avoid, will return true if it could transmit smthing */ register Segalt *g; register int sink_ind; register Component *avoid; { Packet *pkt; int status; pkt = pk_alloc(); pkt->pk_length = MSG_PKT_SIZE; pkt->pk_type = ROUTE_PACKET; pkt->rt_pk.rt_type = RT_MSG; pkt->rt_pk.rt.msg.cycle_no = IT(g)[sink_ind].cycle_no; pkt->rt_pk.rt.msg.d = IT(g)[sink_ind].cost; pkt->rt_pk.rt.msg.sink = IT(g)[sink_ind].dest; pkt->rt_pk.rt.msg.sender = g->node; status = broadcast_pkt(g, pkt, sink_ind, avoid); pk_free(pkt); return status; } static int broadcast_pkt(g, pkt, sink_ind, avoid) /* will broadcast the pkt to every neighbor but , avoid, will return true if it could transmit smthing */ register Segalt *g; register Packet *pkt; register int sink_ind; register Component *avoid; { Packet *p; int i; int status; int rt_pkts_count; status = 0; rt_pkts_count = 0; for (i = 0; LTT(g)[i].n_nd != (Component *)NULL; i++) { if (IT(g)[sink_ind].link_status [i] == 'U' && LTT(g)[i].n_nd != avoid) { status = 1; p = pk_alloc(); p->pk_length = pkt->pk_length; p->pk_type = pkt->pk_type; p->rt_pk.rt_type = pkt->rt_pk.rt_type; p->rt_pk.rt.msg.cycle_no = pkt->rt_pk.rt.msg.cycle_no; p->rt_pk.rt.msg.d = pkt->rt_pk.rt.msg.d; p->rt_pk.rt.msg.sink = pkt->rt_pk.rt.msg.sink; p->rt_pk.rt.msg.sender = pkt->rt_pk.rt.msg.sender; p->pk_dest_socket.so_host = LTT(g)[i].n_nd; p->pk_dest_socket.so_port = (Component *)NULL; p->pk_source_socket.so_host = (Component *)NULL; p->pk_source_socket.so_port = (Component *)NULL; ev_call(EV_NODE_PRODUCE, (Component *)g, g->node, g->node->co_action, p, (caddr_t)LTT(g)[i].n_link); rt_pkts_count ++; } } pm((Component *)g, SEGAL, ROUTING_PKT, rt_pkts_count, 0, 0, 0); return status; } static void sendndp(g, sink_ind, p) register Segalt *g; register int sink_ind; Component *p; { Packet *pkt; int i; i = index_at_LTT_by_node((Routet *)g, p); pkt = pk_alloc(); pkt->pk_length = MSG_PKT_SIZE; pkt->pk_type = ROUTE_PACKET; pkt->rt_pk.rt_type = RT_MSG; pkt->rt_pk.rt.msg.cycle_no = IT(g)[sink_ind].cycle_no; pkt->rt_pk.rt.msg.d = IT(g)[sink_ind].cost; pkt->rt_pk.rt.msg.sink = IT(g)[sink_ind].dest; pkt->rt_pk.rt.msg.sender = g->node; pkt->pk_dest_socket.so_host = LTT(g)[i].n_nd; pkt->pk_dest_socket.so_port = (Component *)NULL; pkt->pk_source_socket.so_host = (Component *)NULL; pkt->pk_source_socket.so_port = (Component *)NULL; pm((Component *)g, SEGAL, ROUTING_PKT, 1, 0, 0, 0); ev_call(EV_NODE_PRODUCE, (Component *)g, g->node, g->node->co_action, pkt, LTT(g)[i].n_link); } static int index_at_IT(g, sink) register Segalt *g; register Component *sink; { register int i; for (i=0; IT(g)[i].dest != sink && i < g->no_of_nodes; i++) ; if ( i == g->no_of_nodes) return -1; /* This is the first time we hear about that node */ else return i; } static caddr_t segal_processing(g, pkt) register Segalt *g; register Packet *pkt; { register int sender_ind, sink_ind; unsigned int ticks; free_routing_queue((Routet *)g, pkt); /* standard */ /* do I know the sender and/or the sink*/ if (pkt->rt_pk.rt_type == RT_MSG) { if ((sender_ind = index_at_LTT_by_node((Routet *)g, pkt->rt_pk.rt.msg.sender)) == -1) sender_ind = add_new_node (g, pkt->rt_pk.rt.msg.sender, pkt->rt_pk.rt.msg.sender); if ((sink_ind = index_at_IT(g, pkt->rt_pk.rt.msg.sink)) == -1) sink_ind = add_new_node (g, pkt->rt_pk.rt.msg.sink, pkt->rt_pk.rt.msg.sender); } if (pkt->rt_pk.rt_type == RT_REQ) { if ((sender_ind = index_at_LTT_by_node((Routet *)g, pkt->rt_pk.rt.req.sender)) == -1) sender_ind = add_new_node (g, pkt->rt_pk.rt.req.sender, pkt->rt_pk.rt.req.sender); if ((sink_ind = index_at_IT(g, pkt->rt_pk.rt.req.sink)) == -1) sink_ind = add_new_node (g, pkt->rt_pk.rt.req.sink, pkt->rt_pk.rt.req.sender); } switch (pkt->rt_pk.rt_type) { case RT_MSG : if (pkt->rt_pk.rt.msg.sink == g->node) /* I am the sink */ events_of_sink(g, pkt); else recv_events_of_i(g, pkt); break; case RT_REQ : if (pkt->rt_pk.rt.req.sink == g->node) /* I am the sink */ events_of_sink(g, pkt); else req_events_of_i(g, pkt); break; case RT_LINK_WAKEUP : wake_up_event(g, pkt); break; case RT_LINK_SHUTDOWN : shutdown_event(g, pkt); break; default : ; #ifdef SEGAL_DEBUG printf("%s : invalid packet type at %d ticks\n", g->segal_name, ev_now()); #endif } log_param((Component *)g, g->info_table); schedule_next_EV_ROUTE_PROCESSING((Routet *)g); /* standard */ return ((caddr_t) g); } void events_of_sink(g, pkt) register Segalt *g; register Packet *pkt; { int sender_ind, x, found; sender_ind = index_at_LTT_by_node((Routet *)g, pkt->rt_pk.rt.msg.sender); switch (pkt->rt_pk.rt_type) { case RT_MSG : IT(g)[0].last_no_via[sender_ind] = pkt->rt_pk.rt.msg.cycle_no; found = 0; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) if (IT(g)[0].link_status [x] == 'U' && IT(g)[0].last_no_via [x] != IT(g)[0].cycle_no) found = 1; if (!found) IT(g)[0].state = 1; break; case RT_REQ : if (pkt->rt_pk.rt.req.cycle_no == IT(g)[0].cycle_no) { IT(g)[0].cycle_no ++; sendnd(g, 0, (Component *) NULL); IT(g)[0].state = 2; } break; default : ; #ifdef SEGAL_DEBUG printf("%s : invalid packet type for sink at %d ticks\n", g->segal_name, ev_now()); #endif } pk_free(pkt); } void recv_events_of_i(g, pkt) /* Receive events of node i */ register Segalt *g; register Packet *pkt; { int sink_ind, sender_ind; sink_ind = index_at_IT(g, pkt->rt_pk.rt.msg.sink); sender_ind = index_at_LTT_by_node((Routet *)g, pkt->rt_pk.rt.msg.sender); switch (IT(g)[sink_ind].state) { case 1 : if (recv11 (g, pkt, sender_ind, sink_ind)) break; if (recv12 (g, pkt, sender_ind, sink_ind)) break; if (recv121 (g, pkt, sender_ind, sink_ind)) break; if (recv13 (g, pkt, sender_ind, sink_ind)) break; if (recv132 (g, pkt, sender_ind, sink_ind)) break; if (recv1321 (g, pkt, sender_ind, sink_ind)) break; #ifdef SEGAL_DEBUG printf("%s : invalid packet at state 1 for i at %d ticks\n", g->segal_name, ev_now()); #endif break; case 2 : if (recv22 (g, pkt, sender_ind, sink_ind)) break; if (recv21 (g, pkt, sender_ind, sink_ind)) break; if (recv22nc (g, pkt, sender_ind, sink_ind)) break; if (recv22nc1 (g, pkt, sender_ind, sink_ind)) break; if (recv13 (g, pkt, sender_ind, sink_ind)) break; /* recv23 */ if (recv132 (g, pkt, sender_ind, sink_ind)) break; /* recv232 */ if (recv1321 (g, pkt, sender_ind, sink_ind)) break; #ifdef SEGAL_DEBUG printf("%s : invalid packet at state 2 for i at %d ticks\n", g->segal_name, ev_now()); #endif break; case 3 : if (recv33 (g, pkt, sender_ind, sink_ind)) break; if (recv32or321(g, pkt, sender_ind, sink_ind)) break; #ifdef SEGAL_DEBUG printf("%s : invalid packet at state 3 for i at %d ticks\n", g->segal_name, ev_now()); #endif break; case 20 : if (recv2020 (g, pkt, sender_ind, sink_ind)) break; /* recv20 20 */ if (recv22nc (g, pkt, sender_ind, sink_ind)) break; /* recv20 2nc */ if (recv22nc1 (g, pkt, sender_ind, sink_ind)) break; /* recv20 2nc1*/ if (recv13 (g, pkt, sender_ind, sink_ind)) break; /* recv20 3 */ if (recv132 (g, pkt, sender_ind, sink_ind)) break; /* recv20 32 */ if (recv1321 (g, pkt, sender_ind, sink_ind)) break; #ifdef SEGAL_DEBUG printf("%s : invalid packet at state 20 for i at %d ticks\n", g->segal_name, ev_now()); #endif break; } pk_free(pkt); } void req_events_of_i(g, pkt) /* request event at node i */ register Segalt *g; register Packet *pkt; { /* am i suppose to put my id or dest id in it ? */ int sink_ind, link; sink_ind = index_at_IT(g, pkt->rt_pk.rt.req.sink); if (pkt->rt_pk.rt.req.cycle_no >= IT(g)[sink_ind].max_no && IT(g)[sink_ind].hop != (Component *)NULL) { IT(g)[sink_ind].lastreqno = pkt->rt_pk.rt.req.cycle_no; link = index_at_LTT_by_node((Routet *)g, IT(g)[sink_ind].hop); pkt->pk_dest_socket.so_host = LTT(g)[link].n_nd; pkt->rt_pk.rt.req.sender = g->node; ev_call(EV_NODE_PRODUCE, (Component *)g, g->node, g->node->co_action, pkt, LTT(g)[link].n_link); pm((Component *)g, SEGAL, ROUTING_PKT, 1, 0, 0, 0); } else pk_free(pkt); } void wake_up_event(g, pkt) register Segalt *g; register Packet *pkt; { int ind, n, m, x, rt_pkts_count; Component *link; link = pkt->pk_source_socket.so_host; ind = index_at_LTT_by_link((Routet *)g, pkt->pk_source_socket.so_host); pk_free(pkt); link_repair_init_LTT((Routet *)g, ind); IT(g)[0].link_status [ind] = 'U'; IT(g)[0].cycle_no ++; sendnd(g, 0, (Component *) NULL); IT(g)[0].state = 2; rt_pkts_count = 0; for (n = 1; n < g->no_of_nodes; n++) { if (IT(g)[n].link_status [ind] == 'D') { IT(g)[n].link_status [ind] = 'R'; m = get_cycle_no(g, (Link *)link, IT(g)[n].dest); IT(g)[n].last_no_via [ind] = IT(g)[n].cycle_no - 1; IT(g)[n].open_after [ind] = max (IT(g)[n].cycle_no, m); if (IT(g)[n].hop != (Component *)NULL) { pkt = pk_alloc(); pkt->pk_type = ROUTE_PACKET; pkt->rt_pk.rt_type = RT_REQ; pkt->rt_pk.rt.req.sink = IT(g)[n].dest; pkt->pk_length = REQ_PKT_SIZE; pkt->rt_pk.rt.req.cycle_no = max (IT(g)[n].cycle_no, m); pkt->rt_pk.rt.req.sender = g->node; x = index_at_LTT_by_node((Routet *)g, IT(g)[n].hop); rt_pkts_count ++; ev_call(EV_NODE_PRODUCE, (Component *)g, g->node, g->node->co_action, pkt, LTT(g)[x].n_link); } IT(g)[n].lastreqno = max (IT(g)[n].cycle_no, m); } } pm((Component *)g, SEGAL, ROUTING_PKT, rt_pkts_count, 0, 0, 0); } void shutdown_event(g, pkt) register Segalt *g; register Packet *pkt; { int link_ind, sink_ind; link_ind = index_at_LTT_by_link((Routet *)g, pkt->pk_source_socket.so_host); /* Failure event of SINK */ link_failure_init_LTT((Routet *)g, link_ind); IT(g)[0].link_status[link_ind] = 'D'; IT(g)[0].cycle_no ++; if (sendnd(g, 0, (Component *) NULL)) IT(g)[0].state = 2; /* Failure events of node i */ for (sink_ind = 1; sink_ind < g->no_of_nodes; sink_ind++) { if (fail11 (g, link_ind, sink_ind)) continue; if (fail13 (g, link_ind, sink_ind)) continue; if (fail132 (g, link_ind, sink_ind)) continue; if (fail1321(g, link_ind, sink_ind)) continue; } pk_free(pkt); } static void readyupall(g, sink_ind) register Segalt *g; register int sink_ind; { /* take care of local topologu table */ register int x; for (x = 0; LTT(g) [x].n_nd != (Component *)NULL; x++) if (IT(g)[sink_ind].link_status [x] == 'R' && IT(g)[sink_ind].open_after [x] < IT(g)[sink_ind].cycle_no) IT(g)[sink_ind].link_status [x] = 'U'; } static int get_cycle_no(g, l, dest) register Segalt *g; register Link *l; register Component *dest; { Neighbor *temp; Nodee *other_node; int i; Segalt *gg; temp = (Neighbor *)(l->link_neighbors->l_head); if (g->node == (Component *)(temp->n_c)) temp = temp->n_next; other_node = (Nodee *)(temp->n_c); /* Get the node at the other end */ temp = (Neighbor *)(other_node->nd_neighbors->l_head); /* Get its routing module */ while ( ((Component *)(temp->n_c))->co_class != ROUTE_CLASS ) temp = temp->n_next; i = 0; gg = (Segalt *)(temp->n_c); while ( (IT(gg) [i].dest != dest) && (i < gg->no_of_nodes) ) i++; if (i == gg->no_of_nodes) return 0; return IT(gg) [i].cycle_no; } #define EnablingCondition(g) if (!(g)) return 0 #define ReadyUpOne if (IT(g) [sink_ind].link_status [sender_ind] == 'R') \ IT(g) [sink_ind].link_status [sender_ind] = 'U' #define NewCycle (pkt->rt_pk.rt.msg.cycle_no > IT(g)[sink_ind].max_no || \ (pkt->rt_pk.rt.msg.cycle_no == IT(g)[sink_ind].max_no && \ IT(g)[sink_ind].max_no > IT(g)[sink_ind].cycle_no)) static int recv11(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { EnablingCondition((LTT(g) [sender_ind].n_nd != IT(g) [sink_ind].hop) || (pkt->rt_pk.rt.msg.cycle_no < IT(g) [sink_ind].max_no && pkt->rt_pk.rt.msg.d < MARS_INFINITY)); IT(g) [sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g) [sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g) [sink_ind].max_no = max(IT(g)[sink_ind].max_no, pkt->rt_pk.rt.msg.cycle_no); ReadyUpOne; return 1; } static int recv12(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x; unsigned int minD; EnablingCondition(LTT(g)[sender_ind].n_nd == IT(g)[sink_ind].hop && pkt->rt_pk.rt.msg.d < MARS_INFINITY && NewCycle); found = 0; minD = MARS_INFINITY; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) { if (IT(g)[sink_ind].link_status [x] == 'U' && sender_ind != x) { if (IT(g)[sink_ind].last_no_via [x] != pkt->rt_pk.rt.msg.cycle_no) found = 1; else if (IT(g)[sink_ind].cost_via [x] < minD) minD = IT(g)[sink_ind].cost_via [x]; } } EnablingCondition(found); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].max_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cycle_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].state = 2; IT(g)[sink_ind].cost = min (minD, IT(g)[sink_ind].cost_via [sender_ind]); RT(g)[sink_ind].cost = IT(g)[sink_ind].cost; ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, IT(g)[sink_ind].hop); return 1; } static int recv121(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x, minx, old_pi; unsigned int minD; EnablingCondition(LTT(g)[sender_ind].n_nd == IT(g)[sink_ind].hop && pkt->rt_pk.rt.msg.d < MARS_INFINITY && NewCycle); minx = -1; found = 0; minD = MARS_INFINITY; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) { if (IT(g)[sink_ind].link_status [x] == 'U' && sender_ind != x) { if (IT(g)[sink_ind].last_no_via [x] != pkt->rt_pk.rt.msg.cycle_no) found = 1; else if (IT(g)[sink_ind].cost_via [x] < minD) { minD = IT(g)[sink_ind].cost_via [x]; minx = x; } } } EnablingCondition(!found); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); if (minD > IT(g)[sink_ind].cost_via [sender_ind]) { minx = sender_ind; minD = IT(g)[sink_ind].cost_via [sender_ind]; } old_pi = index_at_LTT_by_link((Routet *)g, RT(g)[sink_ind].hop); if (minD == IT(g)[sink_ind].cost_via[old_pi]) minx = old_pi; IT(g)[sink_ind].max_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cycle_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost = minD; IT(g)[sink_ind].hop = LTT(g)[minx].n_nd; if (minx != old_pi || RT(g)[sink_ind].cost != IT(g)[sink_ind].cost) { RT(g)[sink_ind].cost = IT(g)[sink_ind].cost; RT(g)[sink_ind].hop = LTT(g)[minx].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[sink_ind].dest->co_name, ev_now(), RT(g)[sink_ind].hop->co_name, RT(g)[sink_ind].cost); #endif } ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, (Component *) NULL); return 1; } static int recv13(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x; EnablingCondition(LTT(g)[sender_ind].n_nd == IT(g)[sink_ind].hop && pkt->rt_pk.rt.msg.d >= MARS_INFINITY); found = 0; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) { if ((IT(g)[sink_ind].link_status [x] == 'U') && x != sender_ind && (IT(g)[sink_ind].cost_via [x] < MARS_INFINITY) && (IT(g)[sink_ind].last_no_via [x] == IT(g)[sink_ind].max_no) && (IT(g)[sink_ind].max_no > IT(g)[sink_ind].cycle_no) && (IT(g)[sink_ind].max_no > pkt->rt_pk.rt.msg.cycle_no)) found = 1; } EnablingCondition(!found); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = MARS_INFINITY; IT(g)[sink_ind].cost = MARS_INFINITY; IT(g)[sink_ind].max_no = max(IT(g)[sink_ind].max_no, pkt->rt_pk.rt.msg.cycle_no); IT(g)[sink_ind].cycle_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].hop = (Component *)NULL; IT(g)[sink_ind].state = 3; RT(g)[sink_ind].cost = MARS_INFINITY; RT(g)[sink_ind].hop = (Component *) NULL; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop NULL cost %d\n", g->segal_name, RT(g)[sink_ind].dest->co_name, ev_now(), RT(g)[sink_ind].cost); #endif ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, LTT(g)[sender_ind].n_nd); return 1; } static int recv132(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x, minx; unsigned int minD; EnablingCondition(LTT(g)[sender_ind].n_nd == IT(g)[sink_ind].hop && pkt->rt_pk.rt.msg.d >= MARS_INFINITY); found = 0; minD = MARS_INFINITY; minx = -1; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) { if ((IT(g)[sink_ind].link_status [x] == 'U') && x != sender_ind && (IT(g)[sink_ind].cost_via [x] < MARS_INFINITY) && (IT(g)[sink_ind].max_no == IT(g)[sink_ind].last_no_via [x]) && (IT(g)[sink_ind].max_no > IT(g)[sink_ind].cycle_no) && (IT(g)[sink_ind].max_no > pkt->rt_pk.rt.msg.cycle_no)) { found = 1; if (IT(g)[sink_ind].cost_via [x] < minD) { minD = IT(g)[sink_ind].cost_via [x]; minx = x; } } } EnablingCondition(found); found = 0; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) if (!(IT(g)[sink_ind].link_status [x] == 'U' && x != sender_ind && IT(g)[sink_ind].max_no == IT(g)[sink_ind].last_no_via [x])) found = 1; EnablingCondition(found); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = MARS_INFINITY; IT(g)[sink_ind].cost = minD; IT(g)[sink_ind].cycle_no = IT(g)[sink_ind].max_no; IT(g)[sink_ind].hop = LTT(g)[minx].n_nd; IT(g)[sink_ind].state = 2; RT(g)[sink_ind].cost = IT(g)[sink_ind].cost; RT(g)[sink_ind].hop = LTT(g)[minx].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[sink_ind].dest->co_name, ev_now(), RT(g)[sink_ind].hop->co_name, RT(g)[sink_ind].cost); #endif ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, IT(g)[sink_ind].hop); return 1; } static int recv1321(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x, minx; unsigned int minD; EnablingCondition(LTT(g)[sender_ind].n_nd == IT(g)[sink_ind].hop && pkt->rt_pk.rt.msg.d >= MARS_INFINITY); found = 0; minD = MARS_INFINITY; minx = -1; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) { if ((IT(g)[sink_ind].link_status [x] == 'U') && x != sender_ind && (IT(g)[sink_ind].cost_via [x] < MARS_INFINITY) && (IT(g)[sink_ind].max_no == IT(g)[sink_ind].last_no_via [x]) && (IT(g)[sink_ind].max_no > IT(g)[sink_ind].cycle_no) && (IT(g)[sink_ind].max_no > pkt->rt_pk.rt.msg.cycle_no)) { found = 1; if (IT(g)[sink_ind].cost_via [x] < minD) { minD = IT(g)[sink_ind].cost_via [x]; minx = x; } } } EnablingCondition(found); found = 0; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) if (!(IT(g)[sink_ind].link_status [x] == 'U' && x != sender_ind && IT(g)[sink_ind].max_no == IT(g)[sink_ind].last_no_via [x])) found = 1; EnablingCondition(!found); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = MARS_INFINITY; IT(g)[sink_ind].cost = minD; IT(g)[sink_ind].cycle_no = IT(g)[sink_ind].max_no; IT(g)[sink_ind].hop = LTT(g)[minx].n_nd; IT(g)[sink_ind].state = 1; RT(g)[sink_ind].cost = IT(g)[sink_ind].cost; RT(g)[sink_ind].hop = LTT(g)[minx].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[sink_ind].dest->co_name, ev_now(), RT(g)[sink_ind].hop->co_name, RT(g)[sink_ind].cost); #endif ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, (Component *) NULL); return 1; } static int recv22(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x; EnablingCondition(LTT(g)[sender_ind].n_nd != IT(g)[sink_ind].hop); found = 0; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) { if ((IT(g)[sink_ind].link_status [x] == 'U') && sender_ind != x && (IT(g)[sink_ind].last_no_via [x] != IT(g)[sink_ind].cycle_no)) found = 1; } EnablingCondition(found || pkt->rt_pk.rt.msg.cycle_no != IT(g)[sink_ind].cycle_no); ReadyUpOne; IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].max_no = max(IT(g)[sink_ind].max_no, pkt->rt_pk.rt.msg.cycle_no); return 1; } static int recv21(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x, minx, old_pi; unsigned int minD; EnablingCondition(LTT(g)[sender_ind].n_nd != IT(g)[sink_ind].hop && IT(g)[sink_ind].cycle_no == pkt->rt_pk.rt.msg.cycle_no && IT(g)[sink_ind].max_no == IT(g)[sink_ind].cycle_no); found = 0; x = 0; minD = MARS_INFINITY; minx = -1; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) { if (IT(g)[sink_ind].link_status [x] == 'U' && sender_ind != x) { if ((IT(g)[sink_ind].last_no_via [x] != IT(g)[sink_ind].cycle_no) || (IT(g)[sink_ind].cycle_no != IT(g)[sink_ind].max_no)) found = 1; else if (IT(g)[sink_ind].cost_via [x] < minD) { minD = IT(g)[sink_ind].cost_via [x]; minx = x; } } } EnablingCondition(!found); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].state = 1; if (minD > IT(g)[sink_ind].cost_via [sender_ind]) { minx = sender_ind; minD = IT(g)[sink_ind].cost_via [sender_ind]; } old_pi = index_at_LTT_by_link((Routet *)g, RT(g)[sink_ind].hop); if (minD == IT(g)[sink_ind].cost_via[old_pi]) minx = old_pi; IT(g)[sink_ind].hop = LTT(g)[minx].n_nd; if (minx != old_pi || RT(g)[sink_ind].cost != IT(g)[sink_ind].cost) { RT(g)[sink_ind].cost = IT(g)[sink_ind].cost; RT(g)[sink_ind].hop = LTT(g)[minx].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[sink_ind].dest->co_name, ev_now(), RT(g)[sink_ind].hop->co_name, RT(g)[sink_ind].cost); #endif } ReadyUpOne; readyupall(g, sink_ind); sendndp(g, sink_ind, LTT(g)[old_pi].n_nd); return 1; } static int recv22nc(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x; unsigned int minD; EnablingCondition(LTT(g)[sender_ind].n_nd == IT(g)[sink_ind].hop && pkt->rt_pk.rt.msg.d < MARS_INFINITY && NewCycle); found = 0; minD = MARS_INFINITY; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) { if ((IT(g)[sink_ind].link_status [x] == 'U') && sender_ind != x && (IT(g)[sink_ind].last_no_via [x] != pkt->rt_pk.rt.msg.cycle_no)) { found = 1; if (IT(g)[sink_ind].cost_via [x] < minD) minD = IT(g)[sink_ind].cost_via [x]; } } EnablingCondition(found); IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].max_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cycle_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].state = 2; IT(g)[sink_ind].cost = min (minD, IT(g)[sink_ind].cost_via [sender_ind]); ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, IT(g)[sink_ind].hop); return 1; } static int recv22nc1(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x, minx, old_pi; unsigned int minD; EnablingCondition(LTT(g)[sender_ind].n_nd == IT(g)[sink_ind].hop && pkt->rt_pk.rt.msg.d < MARS_INFINITY && NewCycle); found = 0; minD = MARS_INFINITY; minx = -1; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) { if ((IT(g)[sink_ind].link_status [x] == 'U') && sender_ind != x) { if (IT(g)[sink_ind].last_no_via [x] != pkt->rt_pk.rt.msg.cycle_no) found = 1; else if (IT(g)[sink_ind].cost_via [x] < minD) { minD = IT(g)[sink_ind].cost_via [x]; minx = x; } } } EnablingCondition(!found); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); if (minD > IT(g)[sink_ind].cost_via [sender_ind]) { minx = sender_ind; minD = IT(g)[sink_ind].cost_via [sender_ind]; } old_pi = index_at_LTT_by_link((Routet *)g, RT(g)[sink_ind].hop); if (minD == IT(g)[sink_ind].cost_via[old_pi]) minx = old_pi; IT(g)[sink_ind].max_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cycle_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost = minD; IT(g)[sink_ind].state = 1; IT(g)[sink_ind].hop = LTT(g)[minx].n_nd; if (minx != old_pi || RT(g)[sink_ind].cost != IT(g)[sink_ind].cost) { RT(g)[sink_ind].cost = IT(g)[sink_ind].cost; RT(g)[sink_ind].hop = LTT(g)[minx].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[sink_ind].dest->co_name, ev_now(), RT(g)[sink_ind].hop->co_name, RT(g)[sink_ind].cost); #endif } ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, (Component *) NULL); return 1; } static int recv2020(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { EnablingCondition((LTT(g) [sender_ind].n_nd != IT(g) [sink_ind].hop) || (pkt->rt_pk.rt.msg.cycle_no < IT(g) [sink_ind].max_no)); ReadyUpOne; IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].max_no = max(IT(g)[sink_ind].max_no, pkt->rt_pk.rt.msg.cycle_no); return 1; } static int recv33(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { EnablingCondition(!(pkt->rt_pk.rt.msg.d < MARS_INFINITY && NewCycle)); IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].max_no = max(IT(g)[sink_ind].max_no, pkt->rt_pk.rt.msg.cycle_no); ReadyUpOne; return 1; } static int recv32or321(g, pkt, sender_ind, sink_ind) register Segalt *g; register Packet *pkt; register int sender_ind, sink_ind; { int found, x; EnablingCondition(pkt->rt_pk.rt.msg.d < MARS_INFINITY && NewCycle); IT(g)[sink_ind].cost_via [sender_ind] = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].cost = pkt->rt_pk.rt.msg.d + link_cost((Routet *)g, sender_ind); IT(g)[sink_ind].cycle_no = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].last_no_via [sender_ind] = pkt->rt_pk.rt.msg.cycle_no; IT(g)[sink_ind].hop = LTT(g)[sender_ind].n_nd; IT(g)[sink_ind].max_no = max(IT(g)[sink_ind].max_no, pkt->rt_pk.rt.msg.cycle_no); RT(g)[sink_ind].cost = IT(g)[sink_ind].cost; RT(g)[sink_ind].hop = LTT(g)[sender_ind].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[sink_ind].dest->co_name, ev_now(), RT(g)[sink_ind].hop->co_name, RT(g)[sink_ind].cost); #endif ReadyUpOne; readyupall(g, sink_ind); sendnd(g, sink_ind, IT(g)[sink_ind].hop); found = 0; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) if (IT(g)[sink_ind].link_status [x] == 'U' && IT(g)[sink_ind].last_no_via [x] != IT(g)[sink_ind].cycle_no) found = 1; if (found) IT(g)[sink_ind].state = 2; else { sendndp(g, sink_ind, IT(g)[sink_ind].hop); IT(g)[sink_ind].state = 1; } return 1; } static int fail11(g, ind, n) /* fail33, fail2 20, and fail20 20 are like fail11 */ register Segalt *g; register int ind, n; { int link_ind; Packet *pkt; EnablingCondition(LTT(g)[ind].n_nd != IT(g)[n].hop); IT(g)[n].link_status [ind] = 'D'; IT(g)[n].lastreqno = IT(g)[n].cycle_no; if (IT(g)[n].hop) { pkt = pk_alloc(); pkt->pk_type = ROUTE_PACKET; pkt->rt_pk.rt_type = RT_REQ; pkt->rt_pk.rt.req.sink = IT(g)[n].dest; pkt->rt_pk.rt.req.cycle_no = IT(g)[n].cycle_no; pkt->rt_pk.rt.req.sender = g->node; pkt->pk_length = REQ_PKT_SIZE; pm((Component *)g, SEGAL, ROUTING_PKT, 1, 0, 0, 0); link_ind = index_at_LTT_by_node((Routet *)g, IT(g)[n].hop); ev_call(EV_NODE_PRODUCE, (Component *)g, g->node, g->node->co_action, pkt, LTT(g)[link_ind].n_link); } if (IT(g)[n].state == 2) IT(g)[n].state = 20; return 1; } static int fail13(g, ind, n) register Segalt *g; register int ind, n; { int found, x; EnablingCondition(LTT(g)[ind].n_nd == IT(g)[n].hop); for (found = x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) { if (IT(g)[n].link_status [x] == 'U' && x != ind && IT(g)[n].cost_via [x] < MARS_INFINITY && IT(g)[n].max_no == IT(g)[n].last_no_via [x] && IT(g)[n].max_no > IT(g)[n].cycle_no) found = 1; } EnablingCondition(!found); IT(g)[n].link_status [ind] = 'D'; IT(g)[n].cost = MARS_INFINITY; IT(g)[n].hop = (Component *)NULL; IT(g)[n].state = 3; IT(g)[n].lastreqno = IT(g)[n].cycle_no; RT(g)[n].cost = MARS_INFINITY; RT(g)[n].hop = (Component *) NULL; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop NULL cost %d\n", g->segal_name, RT(g)[n].dest->co_name, ev_now(), RT(g)[n].cost); #endif sendnd(g, n, (Component *)NULL); return 1; } static int fail132(g, ind, n) register Segalt *g; register int ind, n; { int found, x, minx; unsigned int minD; EnablingCondition(LTT(g)[ind].n_nd == IT(g)[n].hop); for (found = x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) { if (IT(g)[n].link_status [x] == 'U' && x != ind && IT(g)[n].cost_via [x] < MARS_INFINITY && IT(g)[n].max_no == IT(g)[n].last_no_via [x] && IT(g)[n].max_no > IT(g)[n].cycle_no) found = 1; } EnablingCondition(found); found = 0; minD = MARS_INFINITY; minx = -1; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL; x++) { if (IT(g)[n].link_status [x] == 'U' && x != ind) { if ((IT(g)[n].max_no == IT(g)[n].last_no_via [x]) && (IT(g)[n].max_no > IT(g)[n].cycle_no)) { if (IT(g)[n].cost_via [x] < minD) { minD = IT(g)[n].cost_via [x]; minx = x; } } else found = 1; } } EnablingCondition(found); IT(g)[n].link_status [ind] = 'D'; IT(g)[n].cost = minD; IT(g)[n].cycle_no = IT(g)[n].max_no; IT(g)[n].hop = LTT(g)[minx].n_nd; IT(g)[n].state = 2; IT(g)[n].lastreqno = IT(g)[n].cycle_no; RT(g)[n].cost = IT(g)[n].cost; RT(g)[n].hop = LTT(g)[minx].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[n].dest->co_name, ev_now(), RT(g)[n].hop->co_name, RT(g)[n].cost); #endif sendnd(g, n, IT(g)[n].hop); return 1; } static int fail1321(g, ind, n) register Segalt *g; register int ind, n; { int found, x, minx; unsigned int minD; EnablingCondition(LTT(g)[ind].n_nd == IT(g)[n].hop); for (found = x = 0; LTT(g)[x].n_nd != (Component *)NULL && !found; x++) { if (IT(g)[n].link_status [x] == 'U' && x != ind && IT(g)[n].cost_via [x] < MARS_INFINITY && IT(g)[n].max_no == IT(g)[n].last_no_via [x] && IT(g)[n].max_no > IT(g)[n].cycle_no) found = 1; } EnablingCondition(found); found = 0; minD = MARS_INFINITY; minx = -1; for (x = 0; LTT(g)[x].n_nd != (Component *)NULL && found == 0; x++) { if (IT(g)[n].link_status [x] == 'U' && x != ind) { if ((IT(g)[n].max_no == IT(g)[n].last_no_via [x]) && (IT(g)[n].max_no > IT(g)[n].cycle_no)) { if (IT(g)[n].cost_via [x] < minD) { minD = IT(g)[n].cost_via [x]; minx = x; } } else found = 1; } } EnablingCondition(!found); IT(g)[n].link_status [ind] = 'D'; IT(g)[n].cost = minD; IT(g)[n].hop = LTT(g)[minx].n_nd; IT(g)[n].cycle_no = IT(g)[n].max_no; IT(g)[n].state = 1; IT(g)[n].lastreqno = IT(g)[n].cycle_no; RT(g)[n].cost = IT(g)[n].cost; RT(g)[n].hop = LTT(g)[minx].n_link; log_param((Component *)g, g->routing_table); #ifdef SEGAL_DEBUG printf("Routing table change in %s for dest %s at %d hop %s cost %d\n", g->segal_name, RT(g)[n].dest->co_name, ev_now(), RT(g)[n].hop->co_name, RT(g)[n].cost); #endif sendnd(g, n, (Component *) NULL); return 1; } extern char line[100], text[]; char *make_it_text(g, rt) Segalt *g; Param *rt; { int i, j; sprintf(text, "Information Table of %s$Destination State Cycle Hop Cost$", g->segal_name); if (!g->routing_table->u.p) return text; for (i = 0; i < g->no_of_nodes; i++){ sprintf(line, "%-11s %1d %2d %-10s %2d ", IT(g)[i].dest->co_name, IT(g)[i].state, IT(g)[i].cycle_no, (IT(g)[i].hop) ? IT(g)[i].hop->co_name : "NULL", IT(g)[i].cost); strncat(text, line, sizeof(line)); for (j=0; LTT(g)[j].n_nd != (Component *) NULL; j++) { sprintf(line,"%2d ",IT(g)[i].cost_via[j]); strncat(text, line, sizeof(line)); } strcat(text, "$"); } return text; }