/*************************************************************************** * DBS: Distributed Benchmark System * Copyright (c) 1995, 1996, 1997 Yukio Murayama * Copyright (c) 1995, 1996, 1997 Nara Institute of Science and Technology * All rights reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided only with the following * conditions are satisfied: * * 1. Both the copyright notice and this permission notice appear in * all copies of the software, derivative works or modified versions, * and any portions thereof, and that both notices appear in * supporting documentation. * 2. All advertising materials mentioning features or use of this * software must display the following acknowledgement: * This product includes software developed by Nara Institute of * Science and Technology and its contributors. * 3. Neither the name of Nara Institute of Science and Technology nor * the names of its contributors may be used to endorse or promote * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND NARA * INSTITUTE OF SCIENCE AND TECHNOLOGY DISCLAIMS ANY LIABILITY OF * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF * THIS SOFTWARE. ALSO, THERE IS NO WARRANTY IMPLIED OR OTHERWISE, * NOR IS SUPPORT PROVIDED. * * Feedback of the results generated from any improvements or * extensions made to this software would be much appreciated. * Any such feedback should be sent to: * * Yukio Murayama * E-mail: * URL: * Address: Graduate School of Information Science, * Nara Institute of Science and Technology, * Takayama 8916-5, Ikoma, Nara, Japan * * Nara Institute of Science and Technology has the rights to * redistribute these changes. ***************************************************************************/ /***************************************************************** * Distributed Benchmark System * Scan Command File * $Revision: 1.22 $ * $Date: 1997/07/11 00:54:12 $ * $Author: yukio-m $ *****************************************************************/ #ifdef HAVE_SYS_PARAM_H #include #endif #include #include #if !defined(sony_news) && !defined(__sun) #include #else #include #endif #if (!defined(BSD) || (BSD < 199306)) #error BSD #include #endif #include #include "dbs.h" #include "dbsc.h" /* * Prototype Definition */ int ffgetc __P((FILE *fp)); int uungetc __P((int c, FILE *fp)); void p_error __P((char *s)); void skip __P((char *str, FILE *f)); int getword __P((char *buf, char *str, FILE *fp)); void init_sendrecv_param __P((struct send_recv *sr)); void init_scan_param __P((struct scan_cmd *scan)); void check_sendrecv_param __P((struct send_recv *sr)); void check_scan __P((struct scan_cmd *scan)); int scan_sub_out __P((char *word, struct scan_cmd **scan)); int scan_sub_root __P((FILE *fp, char *word, struct scan_cmd **scan)); int scan_sub_sendrecv __P((FILE *fp, char *word, struct send_recv *sr, int state)); int total_size __P((struct scan_cmd *scan)); int get_pattern __P((struct scan_traffic **traffic, FILE *fp)); int total_message __P((struct scan_cmd *scan)); /* * Grobal Variable for error messages Setting */ static int line = 1; static int column = 1; static int bcolumn = 1; static char error_buf[MAX_COLUMN+1]=""; static int cmd_n = 0; /* * Grobal Variable for automaton */ enum state { OUT=0, ROOT=1, SENDER=2, RECEIVER=3 } state; /***************************************************************** * Scan MAIN-ROUTINE * * Parser Command file *****************************************************************/ int scan(scan, fp) struct scan_cmd **scan; FILE *fp; { char word[CHAR_ARRAY]; int c; state = OUT; DEBUGMSG2(8, fprintf(stderr, "State %d\n",state)); DEBUGMSG2(8, fprintf(stderr, "Scan File ----------------------------------------------\n")); /* * Scan Main Routine */ while (1) { skip(" \n\t;", fp); if (getword(word, " \n\t;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", fp) == EOF) return cmd_n; while (1) { DEBUGMSG2(8, fprintf(stderr, "State %d\n",state)); switch (state) { case OUT: state = scan_sub_out(word, scan); break; case ROOT: state = scan_sub_root(fp, word, scan); break; case SENDER: state = scan_sub_sendrecv(fp, word, &((*scan)->sender), SENDER); break; case RECEIVER: state = scan_sub_sendrecv(fp, word, &((*scan)->receiver), RECEIVER); break; default: p_error("Internal Error!! (scan)"); exit(1); } skip(" \n\t;", fp); if (getword(word, " {=\n\t;}", fp) == EOF) break; if (state == OUT) break; if (strcmp(word, "") == 0) { c=ffgetc(fp); DEBUGMSG2(8, fprintf(stderr, "(G:%c:G)",c)); if (c == '}') strcpy(word, "}"); else if (c == '{') strcpy(word, "{"); else { p_error("missing '}' or '{'"); exit(1); } } } check_scan(*scan); /* out:; GOTO LABEL */ (*scan)->total_size = total_size(*scan); (*scan)->total_message = total_message(*scan); if (debug >= 8) { fprintf(stderr, "Command Data -------------------------------------------\n"); fprintf(stderr, "Host Name = %-12s %-12s\n", (*scan)->sender.hostname, (*scan)->receiver.hostname); fprintf(stderr, "Host Name Command= %-12s %-12s\n", (*scan)->sender.hostname_cmd, (*scan)->receiver.hostname_cmd); fprintf(stderr, "Transport = %-12d\n", (*scan)->transport); fprintf(stderr, "Port Number = %-12d %-12d\n", (*scan)->sender.port, (*scan)->receiver.port); fprintf(stderr, "Start Time =(%-12d %-12d)\n",(*scan)->start_time.tv_sec, (*scan)->start_time.tv_usec); fprintf(stderr, "End Time =(%-12d %-12d)\n",(*scan)->end_time.tv_sec, (*scan)->start_time.tv_usec); fprintf(stderr, "Send Times = %-12d \n", (*scan)->send_times); fprintf(stderr, "Traffic Number = %-12d %-12d\n", (*scan)->sender.traffic_n, (*scan)->receiver.traffic_n); fprintf(stderr, "Total Size = %-12d\n", (*scan)->total_size); fprintf(stderr, "Total Message = %-12d\n", (*scan)->total_message); fprintf(stderr, "Output File Name = %-12s\n", (*scan)->filename); fprintf(stderr, "Connection Mode = %-12d\n", (*scan)->connection_mode); fprintf(stderr, "Send Buffer Size = %-12d %-12d\n", (*scan)->sender.send_buff, (*scan)->sender.recv_buff); fprintf(stderr, "Recv Buffer Size = %-12d %-12d\n", (*scan)->receiver.send_buff, (*scan)->receiver.recv_buff); fprintf(stderr, "Soket Debug Mode = %-12d %-12d\n", (*scan)->sender.so_debug, (*scan)->receiver.so_debug); fprintf(stderr, "TCP Trace Mode = %-12d %-12d\n", (*scan)->sender.tcp_trace, (*scan)->receiver.tcp_trace); fprintf(stderr, "TCP No Delay = %-12d %-12d\n", (*scan)->sender.no_delay, (*scan)->receiver.no_delay); fprintf(stderr, "--------------------------------------------------------\n"); } scan = &((*scan)->next); } } /***************************************************************** * Scan subroutine *****************************************************************/ /* * state == OUT */ int scan_sub_out(word, scan) char *word; struct scan_cmd **scan; { if (strcmp(word, "{") == 0) { /* * Create Scan_Cmd */ if ((*scan = (struct scan_cmd *)malloc(sizeof(struct scan_cmd))) == NULL) { perror("malloc: scan_cmd"); exit(1); } cmd_n++; init_scan_param(*scan); return ROOT; } p_error("syntax error."); exit(1); } /* * state == ROOT */ int scan_sub_root(fp, word, scan) FILE *fp; char *word; struct scan_cmd **scan; { double a; if (strcmp(word, "sender") == 0) { skip(" \n\t{", fp); return SENDER; } if (strcmp(word, "receiver") == 0) { skip(" \n\t{", fp); return RECEIVER; } if (strcmp(word, "file") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); strcpy((*scan)->filename, word); } else if (strcmp(word, "protocol") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); if (strcmp("TCP", word) == 0) { (*scan)->transport = TCP; } else if (strcmp("UDP", word) == 0) { (*scan)->transport = UDP; } else { p_error("Parameter error. You can set TCP or UDP."); exit(1); } } else if (strcmp(word, "connection_mode") == 0 || strcmp(word, "connect_mode") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); if (strcmp("BEFORE", word) == 0) { (*scan)->connection_mode = BEFORE; } else if (strcmp("AFTER", word) == 0) { (*scan)->connection_mode = AFTER; } else { p_error("Parameter error. You can set BEFORE or AFTER."); exit(1); } } else if (strcmp(word, "server") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); if (strcmp("RECEIVER", word) == 0) { (*scan)->serverflg = RECEIVE; } else if (strcmp("SENDER", word) == 0) { (*scan)->serverflg = SEND; } else { p_error("Parameter error. You can set SENDER or RECEIVER."); exit(1); } } else if (strcmp(word, "start_time") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); timeval_put(&((*scan)->start_time), (a = (double)atof((char *)word))); if (a < - 0.1) { p_error("start_time error. start_time must be greater or equal than 0.0"); exit(1); } } else if (strcmp(word, "end_time") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); timeval_put(&((*scan)->end_time), (a = (double)atof((char *)word))); if (a < 0.0) { p_error("end_time error. end_time must be greater than 0.0"); exit(1); } if (a > WARN_END_TIME) fprintf(stderr, "WARNING:end_time = %f is large\n",a ); if (a > MAX_END_TIME) { /* XXX You can modify MAX_END_TIME in dbs.h */ p_error("end_time error. end_time must be less than 3600.0"); exit(1); } } else if (strcmp(word, "send_times") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); (*scan)->send_times = atoi(word); if ((*scan)->send_times < 0) { p_error("send_times error. send_times must be greater or equal than 0"); exit(1); } } else if (strcmp(word, "}") == 0) { return OUT; /* GGG GOTO OUT */ } else { p_error("Unknown keyword."); exit(1); } return ROOT; } /* * state == SEND or RECV */ int scan_sub_sendrecv(fp, word, sr, state) FILE *fp; char *word; struct send_recv *sr; int state; { if (strcmp(word, "hostname_cmd") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); strcpy(sr->hostname_cmd, word); } else if (strcmp(word, "hostname") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); strcpy(sr->hostname, word); } else if (strcmp(word, "port") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->port = atoi(word); if (sr->port < 0 || sr->port > 0xffff) { p_error("port number error."); exit(1); } } else if (strcmp(word, "send_buff") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->send_buff = atoi(word); } else if (strcmp(word, "recv_buff") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->recv_buff = atoi(word); } else if (strcmp(word, "mem_align") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->mem_align = atoi(word); } else if (strcmp(word, "align_offset") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->align_offset = atoi(word); } else if (strcmp(word, "align_pad") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->align_pad = atoi(word); } else if (strcmp(word, "no_delay") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); if (strcmp(word, "ON") == 0) { sr->no_delay = ON; } else if (strcmp(word, "OFF") == 0) { sr->no_delay = OFF; } else { p_error("Parameter error. You can set ON or OFF."); exit(1); } } else if (strcmp(word, "mss") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->mss = atoi(word); } else if (strcmp(word, "so_debug") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); if (strcmp(word, "ON") == 0) { sr->so_debug = ON; } else if (strcmp(word, "OFF") == 0) { sr->so_debug = OFF; } else { p_error("Parameter error. You can set ON or OFF."); exit(1); } } else if (strcmp(word, "tcp_trace") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); if (strcmp(word, "ON") == 0) sr->tcp_trace = ON; else if (strcmp(word, "OFF") == 0) sr->tcp_trace = OFF; else if (strcmp(word, "AFTER") == 0) sr->tcp_trace = AFTER; else { p_error("Parameter error. You can set ON, OFF or AFTER."); exit(1); } } else if (strcmp(word, "record_buff") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->record_buff = atoi(word); } else if (strcmp(word, "trace_buff") == 0) { skip(" =\n\t", fp); getword(word, " \n\t;", fp); sr->trace_buff = atoi(word); } else if (strcmp(word, "pattern") == 0) sr->traffic_n = get_pattern(&sr->traffic, fp); else if (strcmp(word, "}") == 0) { check_sendrecv_param(sr); return ROOT; } else { p_error("Unknown Keyword."); exit(1); } return state; } /***************************************************************** * Get traffic pattern *****************************************************************/ /* * Calculate Sending Total Size (byte) */ int total_size(scan) struct scan_cmd *scan; { int i, sum; struct scan_traffic **traffic; traffic = &(scan->sender.traffic); sum=0; for (i=0; i < scan->sender.traffic_n; i++, traffic = &(*traffic)->next) sum += (*traffic)->size; return sum*scan->send_times; } /* * Calculate Sending Message (Times) */ int total_message(scan) struct scan_cmd *scan; { int i, sum; struct scan_traffic **traffic; traffic = &(scan->sender.traffic); sum = 0; for (i=0; i < scan->sender.traffic_n; i++, traffic = &(*traffic)->next) { sum += ((int)ceil((double)((*traffic)->size)/(double)((*traffic)->packet))); } return sum*scan->send_times; } /* * Get Traffic pattern */ int get_pattern(traffic_org, fp) struct scan_traffic **traffic_org; FILE *fp; { struct scan_traffic **traffic; int n=0, i, s=OFF; char word[256]; traffic = traffic_org; skip(" =\n\t{", fp); while(1) { if (getword(word, " \n\t,;}", fp) == EOF) { fprintf(stderr, "ERROR \'%s\'\n",word); fprintf(stderr, "line %d column %d\n", line, column); exit(1); } if (strcmp(word, "") == 0) { if (ffgetc(fp) == '}') break; else { fprintf(stderr, "ERROR \'%s\'\n",word); fprintf(stderr, "line %d column %d\n", line, column); exit(1); } } if ((*traffic = (struct scan_traffic *)malloc(sizeof(struct scan_traffic))) == NULL) { p_error("Memory Allocation Error"); perror("malloc:traffic"); exit(1); } (*traffic)->next = (struct scan_traffic *) NULL; (*traffic)->size = atoi(word); if ((*traffic)->size <= 0) { p_error("Data Size must be greater then 0"); exit(1); } skip(" \n\t,", fp); getword(word, " \n\t,;}", fp); (*traffic)->packet = atoi(word); if ((*traffic)->packet < 0) { if (state == RECEIVER) { s = ON; } else { p_error("Sender's Packet Size must be greater then 0"); exit(1); } } skip(" \n\t,", fp); getword(word, " \n\t,;}", fp); (*traffic)->esleep = atof(word); skip(" \n\t,", fp); getword(word, " \n\t,;}", fp); (*traffic)->isleep = atof(word); skip(" =\n\t;", fp); traffic = &(*traffic)->next; n++; if (s == ON && n != 1) { p_error("When you set stream mode, you can set one traffic pattern only."); exit(1); } } if (debug >= 8) { traffic = traffic_org; fprintf(stderr, "\n"); fprintf(stderr, "Traffic Pattern-----------------------------------------\n"); fprintf(stderr, "%8s %8s %8s %8s\n", "SIZE", "PAKET", "ESLEEP", "ISLEEP"); for (i=0; isize, (*traffic)->packet, (*traffic)->esleep, (*traffic)->isleep); traffic = &(*traffic)->next; } fprintf(stderr, "--------------------------------------------------------\n"); } return n; } /***************************************************************** * Initializeatoin of Parameter *****************************************************************/ /* * Initialize struct scan_cmd */ void init_scan_param(scan) struct scan_cmd *scan; { init_sendrecv_param(&scan->sender); init_sendrecv_param(&scan->receiver); timeval_put(&(scan->start_time), 0.0); timeval_put(&(scan->end_time), 10.0); strcpy(scan->filename, ""); scan->transport = 0; scan->connection_mode = BEFORE; scan->serverflg = RECEIVE; scan->next = (struct scan_cmd *) NULL; } /* * Initialize struct send_recv */ void init_sendrecv_param(sr) struct send_recv *sr; { strcpy(sr->hostname, ""); strcpy(sr->hostname_cmd, ""); sr->traffic_n = 0; sr->port = 0; sr->send_buff = 0; sr->recv_buff = 0; sr->mss = 0; sr->mem_align = 0; sr->align_offset= 0; sr->align_pad = 0; sr->record_buff = 0; sr->trace_buff = 0; sr->so_debug = OFF; sr->tcp_trace = OFF; sr->no_delay = OFF; sr->status = S_CLOSE; } /***************************************************************** * Check Parameter *****************************************************************/ /* * Check send_recv */ void check_sendrecv_param(sr) struct send_recv *sr; { if (strcmp(sr->hostname_cmd, "") == 0) { if (strcmp(sr->hostname, "") != 0) { strcpy(sr->hostname_cmd, sr->hostname); } else { p_error("'hostname' is not defined."); exit(1); } } if (sr->traffic_n == 0) { p_error("'pattern' is not defined."); exit(1); } } /* * Check scan_cmd */ void check_scan(scan) struct scan_cmd *scan; { if (strcmp(scan->sender.hostname, "") == 0) { p_error("'sender' is not defined."); exit(1); } if (strcmp(scan->receiver.hostname, "") == 0) { p_error("'receiver' is not defined."); exit(1); } if (strcmp(scan->filename, "") == 0) { p_error("'file' is not defined."); exit(1); } if (scan->transport == 0) { p_error("'protocol' is not defined."); exit(1); } if (scan->transport == UDP) { scan->sender.so_debug = OFF; scan->sender.tcp_trace = OFF; scan->sender.no_delay = OFF; scan->receiver.so_debug = OFF; scan->receiver.tcp_trace = OFF; scan->receiver.no_delay = OFF; } if (((scan->transport == UDP || scan->serverflg == RECEIVE) && scan->receiver.port == 0)|| ((scan->transport == UDP || scan->serverflg == SEND ) && scan->sender.port == 0)) { p_error("server 'port = 0' error."); exit(1); } } /***************************************************************** * Parser *****************************************************************/ /* * skip "Strings" */ void skip(str, fp) char *str; FILE *fp; { char *p; int c; DEBUGMSG2(8, fprintf(stderr, "(S:")); while ((c=ffgetc(fp)) != EOF) { if (c == '#') { /* # */ if (debug >= 8) { fprintf(stderr, "(C:"); while (c != EOF && c != '\n') { fputc(c, stderr); c = ffgetc(fp); } fprintf(stderr, ":C)\n"); } else { while (c != EOF && c != '\n') c = ffgetc(fp); } } else { p = str; while (*p != c) { if (*p == '\0') { DEBUGMSG2(8, fprintf(stderr, ":S)")); uungetc(c, fp); return; } p++; } DEBUGMSG2(8, fputc(c, stderr)); } } } /* * get a word before "str" -> buf */ int getword(buf, str, fp) char *buf, *str; FILE *fp; { int c, l=0; char *p; if (feof(fp) != 0) return EOF; DEBUGMSG2(8, fprintf(stderr, "(G:")); while ((c = *buf = ffgetc(fp)) != EOF) { /* * '#' is a mark meaning the beginning of comments. * */ if (c == '#') { /* # */ if (debug >= 8) { fprintf(stderr, "(C:"); while (c != EOF && c != '\n') { fputc(c, stderr); c = ffgetc(fp); } fprintf(stderr, ":C)\n"); } else { while(c != EOF && c != '\n') c = ffgetc(fp); } } else { for (p = str; *p != '\0'; p++) { if (*p == c) { uungetc(c, fp); *buf = '\0'; DEBUGMSG2(8, fprintf(stderr, ":G)")); return !EOF; } } DEBUGMSG2(8, fputc(c, stderr)); if (l >= CHAR_ARRAY-1) { p_error("word is too long"); exit(1); } l++; buf++; } } DEBUGMSG2(8, (fprintf(stderr, ":G)"),fputc('\n', stderr))); *buf = '\0'; return !EOF; } /***************************************************************** * mini subroutine *****************************************************************/ /* * fgetc + count(line, column) * Size of error_buf is MAX_COLUMN + 1. */ int ffgetc(fp) FILE *fp; { int c,i; c = fgetc(fp); if (c == '\n') { line++; bcolumn = column; column = 1; error_buf[column-1] = c; error_buf[column] = '\0'; } else if (c == '\t') { for (i = column; i <= (column/8+1)*8; i++) { if (i >= CHAR_ARRAY) { p_error("line is too long"); exit(1); } error_buf[i-1] = ' '; } error_buf[i-1] = '\0'; column = i; } else { if (column >= CHAR_ARRAY) { p_error("line is too long"); exit(1); } error_buf[column-1] = c; error_buf[column] = '\0'; column++; } return c; } /* * ungetc + uncount(line, column) */ int uungetc(c, fp) int c; FILE *fp; { if (c == '\n') { line--; column = bcolumn; } else { column--; } return ungetc(c, fp); } /* * print error(line, column) */ void p_error(s) char *s; { int i; fprintf(stderr, "Error: line %d column %d (or before):\n %s\n", line, column, s); fprintf(stderr, "%s\n", error_buf); for (i=1; i < column; i++) { printf(" "); } printf("^\n"); }