//===================================================== file = lb_csim.c ===== //= A CSIM18 simulation of a byte-based leaky bucket for packet traffic = //============================================================================ //= Notes: 1) Assumes an input file with pairs with = //= delta_time in real seconds and pkt_len in integer bytes = //= 2) Assumes MEDIA_RATE is in bits per second = //= 3) The trace file is TRACE_FILE and no error checking is = //= performed on the opened file = //= 4) Shaped traffic is output to SHAPE_FILE = //= 5) Must manually set MEDIA_RATE, BYTE_RATE, and BUCKET_SIZE = //=--------------------------------------------------------------------------= //= History: KJC (06/14/00) - Genesis = //============================================================================ //----- Includes ------------------------------------------------------------- #include // Needed for printf(), feof(), and fscanf() #include // Needed for exit() and ato*() #include "csim.h" // Needed for CSIM18 stuff //----- Defines --------------------------------------------------------------- #define FALSE 0 // Boolean false #define TRUE 1 // Boolean true #define TRACE_FILE "trace.dat" // Name of trace file #define SHAPE_FILE "shape.dat" // Name of shaped traffic file #define MEDIA_RATE 10.0e6 // Output Media rate in bits per sec #define BYTE_RATE 1000 // Rate of bytes per sec to token bucket #define BUCKET_SIZE 2000 // Token bucket size in bytes //----- Globals --------------------------------------------------------------- FILE *Tf; // Trace file pointer FILE *Sf; // Shaped file pointer FACILITY Server; // Server facility EVENT Done; // Done event EVENT Pkt_release_event; // Packet release event int Eof_flag; // End-of-file flag for trace file int Total_count; // Total count of packets int Byte_count; // Byte counter for token bucket double Last_clock; // Clock value at last transmit //----- Prototypes ------------------------------------------------------------ void generate(void); // Trace file traffic generator void byte_gen(void); // Byte generator void leaky_bucket(int pkt_len); // Leaky bucket shaper //============================================================================= //== Main program == //============================================================================= void sim(void) { // Create the simulation create("sim"); // Increase max_processes max_processes(10000L); // Open the trace and shape files (clobbers any existing shape file) Tf = fopen(TRACE_FILE, "r"); if (Tf == NULL) { printf(" >>> ERROR in opening trace file '%s' \n", TRACE_FILE); exit(1); } Sf = fopen(SHAPE_FILE, "w"); if (Sf == NULL) { printf(" >>> ERROR in opening shape file '%s' \n", SHAPE_FILE); exit(1); } // CSIM initializations Server = facility("Server"); Done = event("Done event"); Pkt_release_event = event("Packet release event"); // Variable initializations (always start with a full token bucket) Total_count = 0; Byte_count = BUCKET_SIZE; Last_clock = 0.0; // Initiate byte_gen() and generate() and wait for Done event to be set byte_gen(); generate(); wait(Done); // Output results printf("============================================================= \n"); printf("== *** CSIM18 leaky bucket simulation *** == \n"); printf("============================================================= \n"); printf("= >>> Shaped traffic output to file %s \n", SHAPE_FILE); printf("= Media rate = %f bits/sec \n", MEDIA_RATE); printf("= Token byte rate = %f bytes/sec \n", BYTE_RATE); printf("= Token bucket size = %f bytes \n", BUCKET_SIZE); printf("============================================================= \n"); printf("= Total CPU time = %f sec \n", cputime()); printf("= Total sim time = %f sec \n", clock); printf("= Total packets = %9d pkts \n", Total_count); printf("============================================================= \n"); printf("= Mean throughput = %f pkts/sec \n", tput(Server)); printf("= Mean service time = %f sec \n", serv(Server)); printf("= Mean queue len = %f pkts \n", qlen(Server)); printf("= Mean response time = %f sec \n", resp(Server)); printf("============================================================= \n"); } //============================================================================= //== Function to generate packets from a trace file == //============================================================================= void generate(void) { char in_string1[256]; // Input string #1 char in_string2[256]; // Input string #2 double time_stamp; // Delta time in seconds from trace file int pkt_len; // Packet length in bytes from trace file create("generate"); // Read and generate packets until end-of-file // - A negative length packet is the artificial Done event packet Eof_flag = FALSE; while(1) { fscanf(Tf, "%s %s \n", in_string1, in_string2); if (feof(Tf)) { Eof_flag = TRUE; break; } time_stamp = atof(in_string1); pkt_len = atoi(in_string2); hold(time_stamp); leaky_bucket(pkt_len); } return; } //============================================================================= //== Leaky bucket process == //============================================================================= void leaky_bucket(int pkt_len) { create("leaky_bucket"); // Increment total arriving packets counter Total_count++; // Reserve the server reserve(Server); // Do the "token matching" by bytes Byte_count = Byte_count - pkt_len; if (Byte_count < 0) { clear(Pkt_release_event); queue(Pkt_release_event); } // Transmit the matched packet hold((8.0 * pkt_len) / MEDIA_RATE); // Release the server release(Server); // Output to shape file fprintf(Sf, "%f %d \n", (clock - Last_clock), pkt_len); Last_clock = clock; // Check for Done condition if ((Eof_flag == TRUE) && (status(Server) == FREE)) set(Done); return; } //============================================================================= //== Token generation process == //============================================================================= void byte_gen(void) { create("byte_gen"); // Increment Byte_count up to BUCKET SIZE while(1) { hold(1.0 / BYTE_RATE); if (Byte_count >= 0) set(Pkt_release_event); if (Byte_count < BUCKET_SIZE) Byte_count++; } return; }