/* $Id: route.c,v 10.1 92/10/06 23:07:01 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. */ /* * Includes routines common to routing modules * * */ #include #include #include #include "route.h" #include "node.h" unsigned int link_cost_hop_count(), link_cost_hndly(), link_cost_by_delay(), link_cost_by_util(); void compute_link_cost_metrics(g) register Routet *g; { register int i; double tmp; for (i = 0; LTT(g)[i].n_nd != NULL; i++) if (*LTT(g)[i].l_status != 'D') { /* Hop Normalized delay */ (void) link_cost_hndly(g, i); LTT(g)[i].total_tr_delay = 0; LTT(g)[i].total_trans_queuing_delay = 0; /* utilization */ tmp = (ev_now() <= g->link_cost_time) ? 0.0 : (double) (LTT(g)[i].total_util + ((LTT(g)[i].queue_size) ? (ev_now() - LTT(g)[i].last_op_time) : 0)) / (double) (ev_now() - g->link_cost_time); LTT(g)[i].total_util = 0; LTT(g)[i].ave_util = 0.5 * (tmp + LTT(g)[i].ave_util); (void) link_cost_by_util(g, i); /* queue_size */ LTT(g)[i].avg_queue_size = (ev_now() <= g->link_cost_time) ? 0 : (int) ((LTT(g)[i].tot_queue_size + LTT(g)[i].queue_size * (ev_now() - LTT(g)[i].last_op_time)) / (double) (ev_now() - g->link_cost_time)); LTT(g)[i].tot_queue_size = 0; /* delay */ tmp = ((ev_now() <= g->link_cost_time || LTT(g)[i].no_of_packets == 0) ? ((Nodee *)g->node)->nd_delay->u.i : LTT(g)[i].total_delay / LTT(g)[i].no_of_packets) + LTT(g)[i].l_delay; LTT(g)[i].total_delay = 0; LTT(g)[i].no_of_packets = 0; LTT(g)[i].ave_delay = 0.5 * (tmp + LTT(g)[i].ave_delay); (void) link_cost_by_delay(g, i); LTT(g)[i].last_op_time = ev_now(); switch (lcostfcn_adr->link_cost_function->u.i) { case 1: LTT(g)[i].l_cost = LTT(g)[i].hndly_cost; break; case 2: LTT(g)[i].l_cost = LTT(g)[i].delay_cost; break; case 3: LTT(g)[i].l_cost = LTT(g)[i].util_cost; break; case 4: LTT(g)[i].l_cost = link_cost_hop_count(g, i); break; default : LTT(g)[i].l_cost = LTT(g)[i].util_cost; break; } } g->link_cost_time = ev_now(); log_param((Component *)g, g->local_top); } unsigned int link_cost_hop_count(g, i) register Routet *g; register int i; { LTT(g)[i].l_cost = (*LTT(g)[i].l_status == 'D') ? MARS_INFINITY : 1; return(LTT(g)[i].l_cost); } unsigned int link_cost_by_util(g, i) register Routet *g; register int i; { double cost; if (*LTT(g)[i].l_status == 'D') LTT(g)[i].util_cost = MARS_INFINITY; else { cost = lcostfcn_adr->slope->u.i * LTT(g)[i].ave_util + lcostfcn_adr->offset->u.i; if (fabs(cost - LTT(g)[i].util_cost) > lcostfcn_adr->movement_limit->u.i && LTT(g)[i].util_cost != MARS_INFINITY) cost = LTT(g)[i].util_cost + lcostfcn_adr->movement_limit->u.i * (cost > LTT(g)[i].util_cost ? 1 : -1); LTT(g)[i].util_cost = max(min((int) cost, lcostfcn_adr->maximum->u.i), lcostfcn_adr->minimum->u.i); } return(LTT(g)[i].util_cost); } unsigned int link_cost_by_delay(g, i) register Routet *g; register int i; { double cost; if (*LTT(g)[i].l_status == 'D') LTT(g)[i].delay_cost = MARS_INFINITY; else { if (LTT(g)[i].ave_delay >= lcostfcn_adr->max_delay->u.i) cost = lcostfcn_adr->maximum->u.i; else if (LTT(g)[i].ave_delay <= lcostfcn_adr->min_delay->u.i) cost = lcostfcn_adr->minimum->u.i; else cost = (LTT(g)[i].ave_delay - lcostfcn_adr->min_delay->u.i) * (lcostfcn_adr->maximum->u.i - lcostfcn_adr->minimum->u.i) / (lcostfcn_adr->max_delay->u.i - lcostfcn_adr->min_delay->u.i) + lcostfcn_adr->offset->u.i; if (fabs(cost - LTT(g)[i].delay_cost) > lcostfcn_adr->movement_limit->u.i && LTT(g)[i].delay_cost != MARS_INFINITY) cost = LTT(g)[i].delay_cost + lcostfcn_adr->movement_limit->u.i * (cost > LTT(g)[i].delay_cost ? 1 : -1); LTT(g)[i].delay_cost = max(min((int) cost, lcostfcn_adr->maximum->u.i), lcostfcn_adr->minimum->u.i); } return(LTT(g)[i].delay_cost); } unsigned int link_cost_hndly(g, i) register Routet *g; register int i; { double total_delay; double sample_utilization, utilization, cost; if (*LTT(g)[i].l_status == 'D') LTT(g)[i].hndly_cost = MARS_INFINITY; else { /* Average delay includes node processing and propagation delays, we need the queueing delay only to get the server utilization */ if (LTT(g)[i].total_delay > 0) sample_utilization = 1.0 - LTT(g)[i].total_tr_delay / LTT(g)[i].total_trans_queuing_delay; else sample_utilization = 0.0; sample_utilization = sample_utilization < 0 ? 0 : sample_utilization; utilization = 0.5 * (sample_utilization + LTT(g)[i].last_utilization); LTT(g)[i].last_utilization = utilization; cost = lcostfcn_adr->slope->u.i * utilization + lcostfcn_adr->offset->u.i; if (fabs(cost -LTT(g)[i].hndly_cost) > lcostfcn_adr->movement_limit->u.i && LTT(g)[i].hndly_cost != MARS_INFINITY) cost = LTT(g)[i].hndly_cost + lcostfcn_adr->movement_limit->u.i * (cost>LTT(g)[i].hndly_cost ?1:-1); LTT(g)[i].hndly_cost = max(min((int) cost, lcostfcn_adr->maximum->u.i), lcostfcn_adr->minimum->u.i); } return(LTT(g)[i].hndly_cost); } unsigned int link_cost(g, i) register Routet *g; register int i; { return LTT(g)[i].l_cost; } void link_failure_init_LTT(g, i) Routet *g; int i; { LTT(g)[i].l_status = "Down"; LTT(g)[i].l_cost = MARS_INFINITY; LTT(g)[i].delay_cost = MARS_INFINITY; LTT(g)[i].util_cost = MARS_INFINITY; LTT(g)[i].hndly_cost = MARS_INFINITY; LTT(g)[i].queue_size = 0; LTT(g)[i].tot_queue_size = 0; LTT(g)[i].last_op_time = ev_now(); LTT(g)[i].total_delay = 0.0; LTT(g)[i].no_of_packets = 0; LTT(g)[i].total_util = 0; LTT(g)[i].ave_util = 0.0; LTT(g)[i].avg_queue_size = 0; LTT(g)[i].last_utilization = 0.0; LTT(g)[i].total_tr_delay = 0.0; LTT(g)[i].total_trans_queuing_delay = 0.0; LTT(g)[i].ave_delay = LTT(g)[i].l_delay + ((Nodee *)g->node)->nd_delay->u.i; log_param((Component *)g, g->local_top); } void link_repair_init_LTT(g, i) Routet *g; int i; { LTT(g)[i].l_status = "Up"; LTT(g)[i].l_cost = lcostfcn_adr->minimum->u.i; LTT(g)[i].delay_cost = lcostfcn_adr->minimum->u.i; LTT(g)[i].util_cost = lcostfcn_adr->minimum->u.i; LTT(g)[i].hndly_cost = lcostfcn_adr->minimum->u.i; LTT(g)[i].queue_size = 0; LTT(g)[i].tot_queue_size = 0; LTT(g)[i].last_op_time = ev_now(); LTT(g)[i].total_delay = 0.0; LTT(g)[i].no_of_packets = 0; LTT(g)[i].total_util = 0; LTT(g)[i].ave_util = 0.0; LTT(g)[i].avg_queue_size = 0; LTT(g)[i].last_utilization = 0.0; LTT(g)[i].total_tr_delay = 0.0; LTT(g)[i].total_trans_queuing_delay = 0.0; LTT(g)[i].ave_delay = LTT(g)[i].l_delay + ((Nodee *)g->node)->nd_delay->u.i; log_param((Component *)g, g->local_top); } char text[16000]; char line[800]; char *make_ltt_text(g, ltt) Routet *g; Param *ltt; { int i; sprintf(text, "Local Topology Table of %s$Link Neighbour Av QSize Av Delay Av Util Util Stat Hn Dl Ut Cost$", g->route_name); if (!g->local_top->u.p) return text; for (i = 0; LTT(g)[i].n_nd != (Component *) NULL; i++){ sprintf(line, "%-11s %-11s %7d %8.0lf %6.2f %6.2f %4s %2d %2d %2d : %2d$", ((Component *)(LTT(g)[i].n_link))->co_name, ((Component *)(LTT(g)[i].n_nd))->co_name, LTT(g)[i].avg_queue_size, LTT(g)[i].ave_delay, LTT(g)[i].ave_util, LTT(g)[i].last_utilization, LTT(g)[i].l_status, LTT(g)[i].hndly_cost, LTT(g)[i].delay_cost, LTT(g)[i].util_cost, LTT(g)[i].l_cost); strncat(text, line, sizeof(line)); } return text; } char *make_rt_text(g, rt) Routet *g; Param *rt; { int i; sprintf(text, "Routing Table of %s$Destination Next Hop Cost$", g->route_name); if (!g->routing_table->u.p) return text; for (i = 0; i < g->no_of_nodes; i++){ if (RT(g)[i].hop) sprintf(line, "%-11s %-10s %5d$", RT(g)[i].dest->co_name, RT(g)[i].hop->co_name, RT(g)[i].cost); else sprintf(line, "%-11s nil$", RT(g)[i].dest->co_name); strncat(text, line, sizeof(line)); } return text; } void free_routing_queue(comp, pkt) Routet *comp; register Packet *pkt; { (void) q_deq((queue *)(((Nodee *)comp->node)->nd_pq->u.p)); fr_space((Nodee *)comp->node, pkt); } void schedule_next_EV_ROUTE_PROCESSING(comp) Routet *comp; { Packet *pkt; /* schedule next occurance if there is smt waiting to be processed */ if (((queue *)((Nodee *)comp->node)->nd_pq->u.p)->q_len > 0) { pkt = (Packet *) (((queue *)((Nodee *)comp->node)->nd_pq->u.p)->q_head->qe_data); ev_enqueue(EV_ROUTE_PROCESSING, (Component *)comp, (Component *)comp, pkt->pk_time, comp->route_action, pkt, (caddr_t)NULL); } } int index_at_LTT_by_node(g, node) register Routet *g; register Component *node; { register int i; for (i=0; node != LTT(g)[i].n_nd && LTT(g)[i].n_nd !=(Component *)NULL; i++) ; if (LTT(g)[i].n_nd == (Component *)NULL) return -1; else return i; } int index_at_LTT_by_link(g, link) register Routet *g; register Component *link; { register int i; for (i=0; link!=LTT(g)[i].n_link && LTT(g)[i].n_nd!=(Component *)NULL; i++) ; if (LTT(g)[i].n_nd == (Component *)NULL) return -1; else return i; }