/* $Id: simple_traffic.c,v 10.1 92/10/06 23:07:07 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. */ /* * Application/Transport module with SMPLTRFC traffic pattern * */ #include #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 "simple_traffic.h" #include "perf.h" #ifdef DEBUG extern Log debug_log; #endif static caddr_t SmplTrfc_source_create(), SmplTrfc_sink_create(), SmplTrfc_neighbor(), SmplTrfc_uneighbor(), SmplTrfc_source_start(), SmplTrfc_sink_start(), SmplTrfc_reset(), SmplTrfc_produce(), SmplTrfc_retransmit(), SmplTrfc_receive(), SmplTrfc_mk_peer(); caddr_t SmplTrfc_source_action(src, g, type, pkt, arg) Component *src; register SmplTrfct *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 = SmplTrfc_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, "SMPLTRFC Generator initialization called with non-null pointer."); #endif result = SmplTrfc_source_create((char *)arg); break; case EV_DEL: free(g->peer->u.p); comp_delete((Component *)g); result = (caddr_t)g; break; case EV_NEIGHBOR: result = SmplTrfc_neighbor(g, (Component *)arg); break; case EV_UNEIGHBOR: result = SmplTrfc_uneighbor(g, (Component *)arg); break; case EV_MK_PEER: result = SmplTrfc_mk_peer(g, (Component *)arg, SMPLTRFC_SINK); break; case EV_START: result = SmplTrfc_source_start(g); break; case EV_STOP: result = (caddr_t) g; break; /********** The preceding were the commands. Following are the actual events that the application/transport module expects to receive. */ case EV_APTR_PRODUCE: result = SmplTrfc_produce(g); break; case EV_APTR_RECEIVE: result = SmplTrfc_receive(g, src, pkt); break; case EV_APTR_RETRANSMIT: result = SmplTrfc_retransmit(g, pkt); break; default: #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)g, "got unexpected event of type %x", type); #endif break; } return(result); } caddr_t SmplTrfc_sink_action(src, g, type, pkt, arg) Component *src; register SmplTrfct *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 = SmplTrfc_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, "SMPLTRFC Generator initialization called with non-null pointer."); #endif result = SmplTrfc_sink_create((char *)arg); break; case EV_DEL: free(g->peer->u.p); comp_delete((Component *)g); result = (caddr_t)g; break; case EV_NEIGHBOR: result = SmplTrfc_neighbor(g, (Component *)arg); break; case EV_UNEIGHBOR: result = SmplTrfc_uneighbor(g, (Component *)arg); break; case EV_MK_PEER: result = SmplTrfc_mk_peer(g, (Component *)arg, SMPLTRFC_SOURCE); break; case EV_START: result = SmplTrfc_sink_start(g); break; case EV_STOP: result = (caddr_t) g; break; /********** The preceding were the commands. Following are the actual events that the application/transport module expects to receive. */ case EV_APTR_PRODUCE: result = SmplTrfc_produce(g); break; case EV_APTR_RECEIVE: result = SmplTrfc_receive(g, src, pkt); break; case EV_APTR_RETRANSMIT: result = SmplTrfc_retransmit(g, pkt); 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 SmplTrfc_source_create(name) register char *name; { SmplTrfct *g; /* Memory for the component structure. */ g = (SmplTrfct *)sim_malloc(sizeof(SmplTrfct)); /* First things first-- copy name into the new structure. */ strncpy(g->name, name, 40); /* have to create a neighbor list */ g->neighbors = l_create(); g->params = q_create(); g->class = APTR_CLASS; g->type = SMPLTRFC_SOURCE; g->action = SmplTrfc_source_action; g->menu_up = FALSE; g->source_socket.so_port = (Component *) g; g->source_socket.so_host = (Component *) NULL; g->dest_socket.so_port = (Component *) NULL; g->dest_socket.so_host = (Component *) NULL; /* Initialize the parameters */ (void)param_init((Component *)g, "Name", (PFD)NULL, make_name_text, make_short_name_text, param_input_name, 0, DisplayMask | InputMask, 0.0); g->peer = param_init((Component *)g, "Peer", (PFD)NULL, make_str_text, make_short_str_text, (PFI)NULL, 0, DisplayMask, 0.0); pval(g, peer)->u.p = sim_malloc(40); strcpy(g->peer->u.p, "unknown"); g->simple_select = param_init((Component *)g, "Not select(0), select(1) ", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, DisplayMask | ModifyMask, 0.0); g->simple_select->u.i = 0; g->packet_length = param_init((Component *)g, "Ave Packet length", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, DisplayMask | ModifyMask, 0.0); g->packet_length->u.i = 512; g->packet_delay = param_init((Component *)g, "Ave delay btw packets (uSec)", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, DisplayMask | ModifyMask, 0.0); g->packet_delay->u.i = 100000; g->dist_chosen = param_init((Component *)g, "Choose dist (0=>EXP, 1=>UNIF)", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, DisplayMask | ModifyMask, 0.0); pval(g, dist_chosen)->u.i = 0; g->sd = param_init((Component *)g, "Enter standard deviation if UNIF", (PFD)NULL, make_double_text, make_short_double_text, param_input_double, 0, DisplayMask | ModifyMask, 0.0); pval(g, sd)->u.d = 0; g->window_size = param_init((Component *)g, "Window size (-1 for inf)", int_calc, make_int_text, make_short_int_text, param_input_int, TIME_HISTORY, DisplayMask | ModifyMask, 0.0); pval(g, window_size)->u.i = 20; g->packets_sent = param_init((Component *)g, "Packets Sent", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, DisplayMask | CanHaveMeterMask | CanHaveLogMask,0.0); pval(g, packets_sent)->u.i = 0; g->packets_acked = param_init((Component *)g, "Packets Acked", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, DisplayMask | CanHaveMeterMask | CanHaveLogMask, 0.0); pval(g, packets_acked)->u.i = 0; g->packets_recvd = param_init((Component *)g, "Packets Received", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, 0, 0.0); pval(g, packets_recvd)->u.i = 0; g->packets_dropped = param_init((Component *)g, "Packets Lost", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, DisplayMask | CanHaveMeterMask | CanHaveLogMask, 0.0); pval(g, packets_dropped)->u.i = 0; g->last_pkt_delay = 0; g->data_acked = 0; g->last_bytes_acked = 0; #ifdef DEBUG dbg_write(debug_log, DBG_INFO, (Component *)g, "SmplTrfc generator initialized"); #endif return((caddr_t)g); } static caddr_t SmplTrfc_sink_create(name) register char *name; { SmplTrfct *g; /* Memory for the component structure. */ g = (SmplTrfct *)sim_malloc(sizeof(SmplTrfct)); /* First things first-- copy name into the new structure. */ strncpy(g->name, name, 40); /* have to create a neighbor list */ g->neighbors = l_create(); g->params = q_create(); g->class = APTR_CLASS; g->type = SMPLTRFC_SINK; g->action = SmplTrfc_sink_action; g->menu_up = FALSE; g->source_socket.so_port = (Component *) g; g->source_socket.so_host = (Component *) NULL; g->dest_socket.so_port = (Component *) NULL; g->dest_socket.so_host = (Component *) NULL; /* Initialize the parameters */ (void)param_init((Component *)g, "Name", (PFD)NULL, make_name_text, make_short_name_text, param_input_name, 0, DisplayMask | InputMask, 0.0); g->peer = param_init((Component *)g, "Peer", (PFD)NULL, make_str_text, make_short_str_text, (PFI)NULL, 0, DisplayMask, 0.0); pval(g, peer)->u.p = sim_malloc(40); strcpy(g->peer->u.p, "unknown"); g->simple_select = param_init((Component *)g, "Not select(0), select(1) ", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, 0, 0.0); g->simple_select->u.i = 0; g->packet_length = param_init((Component *)g, "Ave Packet length", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, 0, 0.0); g->packet_length->u.i = 512; g->packet_delay = param_init((Component *)g, "Ave delay btw packets (uSec)", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, 0, 0.0); g->packet_delay->u.i = 2000; g->dist_chosen = param_init((Component *)g, "Choose dist (0=>EXP, 1=>UNIF)", (PFD)NULL, make_int_text, make_short_int_text, param_input_int, 0, 0, 0.0); pval(g, dist_chosen)->u.i = 0; g->sd = param_init((Component *)g, "Enter standard deviation if UNIF", (PFD)NULL, make_double_text, make_short_double_text, param_input_double, 0, 0, 0.0); pval(g, sd)->u.d = 0; g->window_size = param_init((Component *)g, "Window size (-1 for inf)", int_calc, make_int_text, make_short_int_text, param_input_int, TIME_HISTORY, 0, 0.0); pval(g, window_size)->u.i = 20; g->packets_sent = param_init((Component *)g, "Packets Sent", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, 0, 0.0); pval(g, packets_sent)->u.i = 0; g->packets_acked = param_init((Component *)g, "Packets Acked", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, 0, 0.0); pval(g, packets_acked)->u.i = 0; g->packets_recvd = param_init((Component *)g, "Packets Received", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, DisplayMask | CanHaveMeterMask | CanHaveLogMask, 0.0); pval(g, packets_recvd)->u.i = 0; g->packets_dropped = param_init((Component *)g, "Ack Packets Lost", int_calc, make_int_text, make_short_int_text, (PFI)NULL, TIME_HISTORY, 0, 0.0); pval(g, packets_dropped)->u.i = 0; g->last_pkt_delay = 0; g->data_acked = 0; g->last_bytes_acked = 0; #ifdef DEBUG dbg_write(debug_log, DBG_INFO, (Component *)g, "SmplTrfc generator initialized"); #endif return((caddr_t)g); } static caddr_t SmplTrfc_reset(g) SmplTrfct *g; { g->packets_sent->u.i = 0; g->packets_acked->u.i = 0; g->packets_recvd->u.i = 0; g->packets_dropped->u.i = 0; g->last_pkt_delay = 0; g->data_acked = 0; g->last_bytes_acked = 0; log_param((Component *)g, g->packets_sent); log_param((Component *)g, g->packets_acked); log_param((Component *)g, g->packets_recvd); log_param((Component *)g, g->packets_dropped); return((caddr_t)g); } static caddr_t SmplTrfc_neighbor(g, c) register SmplTrfct *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->source_socket.so_host = c; return result; } static caddr_t SmplTrfc_uneighbor(g, c) register SmplTrfct *g; register Component *c; { return((caddr_t)remove_neighbor((Component *)g, c)); } static caddr_t SmplTrfc_mk_peer(g, c, peer_type) register SmplTrfct *g; register Component *c; int peer_type; { 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) NULL; if (c->co_type == peer_type) if (((SmplTrfct *)c)->source_socket.so_host != (Component *) NULL) { g->dest_socket.so_host = ((SmplTrfct *)c)->source_socket.so_host; g->dest_socket.so_port = ((SmplTrfct *)c)->source_socket.so_port; strcpy(g->peer->u.p, ((Component *)((SmplTrfct *)c)->source_socket.so_host)->co_name); strcat(g->peer->u.p, "."); strcat(g->peer->u.p, c->co_name); log_param((Component *)g, g->peer); result = (caddr_t) g; } #ifdef DEBUG else dbg_write(debug_log, DBG_ERR, (Component *)g, "Source socket in destination not yet initialized"); else dbg_write(debug_log, DBG_ERR, (Component *)g, "Incompatible peer"); #endif return result; } static caddr_t SmplTrfc_source_start(g) register SmplTrfct *g; { Packet *pkt; Component *c; if (g->neighbors->l_len != 1) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)g, "can't generate packets-- no neighbors."); #endif return((caddr_t)NULL); } if (g->dest_socket.so_host == (Component *)NULL) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)g, "can't generate packets-- no peer."); #endif return((caddr_t)NULL); } /* produce first packet */ ev_enqueue(EV_APTR_PRODUCE, (Component *)g, (Component *)g, ev_now(), g->action, (Packet *)NULL, (caddr_t)NULL); pm((Component *)g, SMPLTRFC_SOURCE, NEW_COMPONENT, 0, 0, 0, 0); pm((Component *)g, SMPLTRFC_SOURCE, CONN_UP, 0, 0, 0, g->simple_select->u.i); /* Something non-NULL to return */ return((caddr_t)g); } static caddr_t SmplTrfc_sink_start(g) register SmplTrfct *g; { if (g->neighbors->l_len != 1) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)g, "can't receive packets-- no neighbors."); #endif return((caddr_t)NULL); } if (g->dest_socket.so_host == (Component *)NULL) { #ifdef DEBUG dbg_write(debug_log, DBG_ERR, (Component *)g, "can't generate packets-- no peer."); #endif return((caddr_t)NULL); } pm((Component *)g, SMPLTRFC_SINK, NEW_COMPONENT, 0, 0, 0, 0); /* Something non-NULL to return */ return((caddr_t)g); } #define time_btw_packets(g) random_no(g->dist_chosen->u.i, \ (double)g->packet_delay->u.i, \ g->sd->u.d, \ (unsigned) 1, \ (unsigned) 10000000) #define car_length(g) g->packet_length->u.i static caddr_t SmplTrfc_produce(g) /* Send out a packet */ register SmplTrfct *g; { register Component *c; register Packet *pkt; register unsigned int ticks, time_now; if (g->packets_sent->u.i - g->packets_acked->u.i - g->packets_dropped->u.i < g->window_size->u.i || g->window_size->u.i == -1) { g->packets_sent->u.i ++; log_param((Component *) g, g->packets_sent); pkt = pk_alloc(); pkt->pk_sent_time = ev_now(); pkt->pk_length = car_length(g) + 32; pkt->pk_type = TR_PACKET; pkt->tr_pk.tr_type = TR_DATA; pkt->tr_pk.response = 0; pkt->tr_pk.data_size = pkt->pk_length - 32; pkt->pk_source_socket.so_host = g->source_socket.so_host; pkt->pk_source_socket.so_port = g->source_socket.so_port; pkt->pk_dest_socket.so_host = g->dest_socket.so_host; pkt->pk_dest_socket.so_port = g->dest_socket.so_port; c = (Component *)(((Neighbor *)g->neighbors->l_head)->n_c); ev_call(EV_NODE_PRODUCE, (Component *)g, c, c->co_action, pkt, (caddr_t)NULL); } ev_enqueue(EV_APTR_PRODUCE, (Component *)g, (Component *)g, ev_now() + (time_btw_packets(g) / USECS_PER_TICK), g->action, (Packet *)NULL, (caddr_t)NULL); #ifdef DEBUG dbg_write(debug_log, DBG_INFO, (Component *)g, "sent a packet"); #endif return((caddr_t)g); } static caddr_t SmplTrfc_retransmit(g, pkt) register SmplTrfct *g; Packet *pkt; { g->packets_dropped->u.i ++; log_param((Component *) g, g->packets_dropped); pk_free(pkt); #ifdef DEBUG dbg_write(debug_log, DBG_INFO, (Component *)g, "dropped a packet"); #endif pm((Component *)g, g->type, PKT_RETRANSMITTED, 0, 0, 0, g->simple_select->u.i); return((caddr_t)g); } static caddr_t SmplTrfc_receive(g, c, pkt) /* receive a packet */ register SmplTrfct *g; register Component *c; register Packet *pkt; { register unsigned int time_now; unsigned int sentTime, DataSize; if (pkt->tr_pk.tr_type == TR_DATA) { g->packets_recvd->u.i ++; ((SmplTrfct *) (g->dest_socket.so_port))->packets_acked->u.i ++; log_param((Component *) g, g->packets_recvd); log_param((Component *)(g->dest_socket.so_port), ((SmplTrfct *) (g->dest_socket.so_port))->packets_acked); g->data_acked += pkt->tr_pk.data_size; g->last_bytes_acked = pkt->tr_pk.data_size; pm((Component *)g, SMPLTRFC_SINK, ACK_RECEIVED, pkt->tr_pk.data_size, g->last_pkt_delay, 0, g->simple_select->u.i); g->last_pkt_delay = (ev_now() - pkt->pk_sent_time); } pk_free(pkt); return((caddr_t)g); }