From: Paul B. S. <pa...@us...> - 2001-09-03 18:41:10
|
Update of /cvsroot/linux-atm/linux-atm/src/test In directory usw-pr-cvs1:/tmp/cvs-serv10656/test Added Files: Tag: V2_4_0 br.c bw.c isp.c isp.h awrite.c Makefile.am mkerrnos.pl README.isp window.c ispl_l.l ispl_y.y ttcp.c align.c aping.c aread.c Log Message: --- NEW FILE: br.c --- /* br.c - block read */ /* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <atm.h> #define BSIZE 8192 static void usage(const char *name) { fprintf(stderr,"usage: %s [itf.]vpi.vci\n",name); exit(1); } int main(int argc,char **argv) { struct sockaddr_atmpvc addr; struct atm_qos qos; int s; if (argc != 2) usage(argv[0]); if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); return 1; } memset(&addr,0,sizeof(addr)); if (text2atm(argv[1],(struct sockaddr *) &addr,sizeof(addr),T2A_PVC) < 0) usage(argv[0]); memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.rxtp.traffic_class = ATM_UBR; qos.rxtp.max_sdu = BSIZE; if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) { perror("bind"); return 1; } while (1) { unsigned char buf[BSIZE+4096]; unsigned char *start; ssize_t size; start = (unsigned char *) (((unsigned long) buf+4095) & ~4095U); size = read(s,start,BSIZE); if (size > 0 && write(1,start,size) != size) return 1; } } --- NEW FILE: bw.c --- /* bw.c - block write */ /* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <atm.h> #define BSIZE 8192 static void usage(const char *name) { fprintf(stderr,"usage: %s [itf.]vpi.vci [ blocks ]\n",name); exit(1); } int main(int argc,char **argv) { struct sockaddr_atmpvc addr; struct atm_qos qos; char buffer[BSIZE]; int blocks,s; ssize_t size; if (argc != 2 && argc != 3) usage(argv[0]); if (argc == 2) blocks = 0; else blocks = atoi(argv[2]); if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); return 1; } memset(&addr,0,sizeof(addr)); if (text2atm(argv[1],(struct sockaddr *) &addr,sizeof(addr),T2A_PVC) < 0) usage(argv[0]); memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.txtp.traffic_class = ATM_UBR; qos.txtp.max_sdu = BSIZE; if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (connect(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) { perror("bind"); return 1; } if (blocks) while (blocks--) (void) write(s,buffer,BSIZE); else while ((size = read(0,buffer,BSIZE)) > 0) (void) write(s,buffer,size); return 0; } --- NEW FILE: isp.c --- /* isp.c - Internal Signaling Protocol test generator */ /* Written 1997-2000 by Werner Almesberger, EPFL-ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <atm.h> #include <atmd.h> #include <linux/atmsvc.h> #include "isp.h" extern int yyparse(void); int quiet = 0; int verbose = 0; VAR *variables = NULL; static int sock; void send_msg(const struct atmsvc_msg *msg) { int wrote; wrote = write(sock,msg,sizeof(*msg)); if (wrote == sizeof(*msg)) return; if (wrote < 0) perror("write"); else fprintf(stderr,"bad write: %d != %d\n",wrote,sizeof(*msg)); exit(1); } void recv_msg(struct atmsvc_msg *msg) { int got; got = read(sock,msg,sizeof(*msg)); if (got == sizeof(*msg)) return; if (got < 0) perror("read"); else fprintf(stderr,"bad read: %d != %d\n",got,sizeof(*msg)); exit(1); } static struct errno_table { const char *name; int value; } table[] = { #include "errnos.inc" { NULL, 0 } }; static const char *errno2str(int code) { static char buf[30]; /* probably large enough :) */ const struct errno_table *walk; for (walk = table; walk->name; walk++) { if (walk->value == code) return walk->name; if (walk->value == -code) { sprintf(buf,"-%s",walk->name); return buf; } } sprintf(buf,"%d (0x%x)",code,code); return buf; } /* Synchronized with include/linux/atmsvc.h:enum atmsvc_msg_type */ static struct { const char *name; int fields; } types[] = { { "<invalid>", 0 }, { "bind", F_VCC | F_SVC | F_SAP }, { "connect", F_VCC | F_PVC | F_LOCAL | F_QOS | F_SVC | F_SAP }, { "accept", F_VCC | F_LISTEN_VCC }, { "reject", F_VCC | F_LISTEN_VCC | F_REPLY }, { "listen", F_VCC | F_QOS | F_SVC | F_SAP }, { "okay", F_VCC | F_PVC | F_LOCAL | F_QOS | F_SVC | F_SAP }, { "error", F_VCC | F_REPLY }, { "indicate", F_LISTEN_VCC | F_PVC | F_LOCAL | F_QOS | F_SVC | F_SAP}, { "close", F_VCC | F_REPLY }, { "itf_notify", F_PVC }, { "modify", F_VCC | F_REPLY | F_QOS }, { "identify", F_VCC | F_LISTEN_VCC | F_PVC }, { "terminate", 0 }}; #define MSG_TYPES (sizeof(types)/sizeof(*types)) void print_value(VALUE val) { char buf[1000]; /* bigger than any MAX_ATM_*_LEN */ switch (val.type) { case vt_text: printf("\"%s\"",val.u.text); return; case vt_vcc: printf("%s",kptr_print(&val.u.id)); return; case vt_error: printf("%s",errno2str(val.u.num)); return; case vt_pvc: if (atm2text(buf,sizeof(buf),(struct sockaddr *) &val.u.pvc, A2T_PRETTY | A2T_NAME) < 0) strcpy(buf,"<invalid>"); printf("%s",buf); return; case vt_svc: if (atm2text(buf,sizeof(buf),(struct sockaddr *) &val.u.svc, A2T_PRETTY | A2T_NAME) < 0) strcpy(buf,"<invalid>"); printf("%s",buf); return; case vt_qos: if (qos2text(buf,sizeof(buf),&val.u.qos,0) < 0) strcpy(buf,"<invalid>"); printf("%s",buf); return; case vt_sap: if (sap2text(buf,sizeof(buf),&val.u.sap,S2T_NAME) < 0) strcpy(buf,"<invalid>"); printf("%s",buf); return; default: fprintf(stderr,"\ninvalid value type %d\n",val.type); exit(1); } } #define FIELD(FLD,MSG) \ if (fields & FLD) { \ printf("%s",MSG); \ print_value(pick(msg,FLD)); \ putchar('\n'); \ } void dump_msg(const char *prefix,const struct atmsvc_msg *msg) { int fields; if (msg->type >= MSG_TYPES) { printf("%s: unknown message type %d\n",prefix,msg->type); return; } fields = types[msg->type].fields; printf("%s: %s\n",prefix,types[msg->type].name); FIELD(F_VCC, " vcc = "); FIELD(F_LISTEN_VCC, " listen_vcc = "); FIELD(F_REPLY, " reply = "); FIELD(F_PVC, " pvc = "); FIELD(F_LOCAL, " local = "); FIELD(F_QOS, " qos = "); FIELD(F_SVC, " svc = "); FIELD(F_SAP, " sap = "); } #undef FIELD VAR *create_var(const char *name) { VAR *var,**walk; var = malloc(sizeof(VAR)); if (!var) { perror("malloc"); exit(1); } var->name = name; /* strdup'ed */ var->value.type = vt_none; for (walk = &variables; *walk; walk = &(*walk)->next) if (strcmp(name,(*walk)->name) > 0) break; var->next = *walk; *walk = var; return var; } VAR *lookup(const char *name) { VAR *var; for (var = variables; var; var = var->next) if (!strcmp(var->name,name)) break; return var; } static void destroy(VALUE value) { if (value.type == vt_text) free((char *) value.u.text); } void assign(VAR *var,VALUE value) { destroy(var->value); var->value = value; } static int str2errno(const char *str) { const struct errno_table *walk; for (walk = table; walk->name; walk++) if (!strcmp(walk->name,str)) break; return walk->value; } static VALUE convert(VALUE in,VALUE_TYPE type) { VALUE out; char *end; if (in.type == type) { if (type == vt_text) { in.u.text = strdup(in.u.text); if (!in.u.text) { perror("strdup"); exit(1); } } return in; } if (in.type != vt_text) yyerror("type conflict"); out.type = type; switch (type) { case vt_vcc: memset(&out.u.id,0,sizeof(out.u.id)); *(unsigned long *) &out.u.id = strtoul(in.u.text,&end,0); if (*end) yyerror("invalid number"); break; case vt_error: out.u.num = strtoul(in.u.text,&end,0); if (*end) { out.u.num = str2errno(*in.u.text == '-' ? in.u.text+1 : in.u.text); if (!out.u.num) yyerror("invalid error code"); if (*in.u.text == '-') out.u.num = -out.u.num; } break; case vt_svc: if (text2atm(in.u.text,(struct sockaddr *) &out.u.svc, sizeof(out.u.svc), T2A_SVC | T2A_NAME) < 0) yyerror("invalid SVC address"); break; case vt_pvc: if (text2atm(in.u.text,(struct sockaddr *) &out.u.pvc, sizeof(out.u.pvc),T2A_PVC | T2A_NNI | T2A_NAME) < 0) yyerror("invalid PVC address"); break; case vt_qos: if (text2qos(in.u.text,&out.u.qos,0) < 0) yyerror("invalid QOS"); break; case vt_sap: if (text2sap(in.u.text,&out.u.sap,T2S_NAME) < 0) yyerror("invalid SAP address"); break; default: fprintf(stderr,"unexpected conversion type %d\n",type); exit(1); } return out; } void check(VALUE a,VALUE b) { if (a.type == vt_text) a = convert(a,b.type); if (b.type == vt_text) b = convert(b,a.type); if (a.type != b.type) yyerror("type conflict"); switch (a.type) { case vt_vcc: case vt_error: if (kptr_eq(&a.u.id,&b.u.id)) return; break; case vt_svc: if (atm_equal((struct sockaddr *) &a.u.svc, (struct sockaddr *) &b.u.svc,0,0)) return; break; case vt_pvc: if (atm_equal((struct sockaddr *) &a.u.pvc, (struct sockaddr *) &b.u.pvc,0,0)) return; break; case vt_qos: if (qos_equal(&a.u.qos,&b.u.qos)) return; break; case vt_sap: if (sap_equal(&a.u.sap,&b.u.sap,0)) return; break; default: fprintf(stderr,"unexpected conversion type %d\n",a.type); exit(1); } printf("Expected "); print_value(b); printf(",\nbut message contains "); print_value(a); printf("\n"); exit(1); } #define COPY_MSG_VAL(V) \ switch (field) { \ case F_VCC: _COPY(V.u.id,msg->vcc); break; \ case F_LISTEN_VCC: _COPY(V.u.id,msg->listen_vcc); break; \ case F_REPLY: _COPY(V.u.num,msg->reply); break; \ case F_PVC: _COPY(V.u.pvc,msg->pvc); break; \ case F_LOCAL: _COPY(V.u.svc,msg->local); break; \ case F_QOS: _COPY(V.u.qos,msg->qos); break; \ case F_SVC: _COPY(V.u.svc,msg->svc); break; \ case F_SAP: _COPY(V.u.sap,msg->sap); break; \ default: fprintf(stderr,"unexpected field type 0x%x\n",field); \ exit(1); \ } VALUE pick(const struct atmsvc_msg *msg,int field) { VALUE out; if (msg->type >= MSG_TYPES) { fprintf(stderr,"invalid message type %d",msg->type); exit(1); } if (!(types[msg->type].fields & field)) yyerror("no such field in message"); out.type = type_of(field); #define _COPY(V,M) V = M COPY_MSG_VAL(out) #undef _COPY return out; } void store(struct atmsvc_msg *msg,int field,VALUE val) { if (msg->type >= MSG_TYPES) { fprintf(stderr,"invalid message type %d",msg->type); exit(1); } if (!(types[msg->type].fields & field)) yyerror("no such field in message"); if (val.type != type_of(field)) yyerror("type conflict"); #define _COPY(V,M) M = V COPY_MSG_VAL(val) #undef _COPY } #undef COPY_MSG_VAL VALUE eval(VALUE_TYPE type,const char *str) { VALUE a,b; a.type = vt_text; a.u.text = strdup(str); if (!a.u.text) { perror("strdup"); exit(1); } b = convert(a,type); destroy(a); return b; } void cast(VAR *var,VALUE_TYPE type) { VALUE old; if (var->value.type == type) return; old = var->value; var->value = convert(var->value,type); destroy(old); } VALUE_TYPE type_of(int field) { switch (field) { case F_VCC: case F_LISTEN_VCC: return vt_vcc; case F_REPLY: return vt_error; case F_PVC: return vt_pvc; case F_LOCAL: case F_SVC: return vt_svc; case F_QOS: return vt_qos; case F_SAP: return vt_sap; default: fprintf(stderr,"unexpected field type 0x%x\n",field); exit(1); } } int main(int argc,char **argv) { const char *name; name = *argv; if (argc > 2 && !strcmp(argv[1],"-q")) { quiet = 1; argc--; argv++; } if (argc > 2 && !strcmp(argv[1],"-v")) { verbose = 1; argc--; argv++; } if (argc != 2 || (quiet && verbose)) { fprintf(stderr,"usage: %s [-q | -v] socket\n",name); return 1; } sock = un_attach(argv[1]); if (sock < 0) { perror(argv[1]); return 1; } return yyparse(); } --- NEW FILE: isp.h --- /* isp.h - Internal Signaling Protocol test generator */ /* Written 1997-2000 by Werner Almesberger, EPFL-ICA */ #ifndef ISP_H #define ISP_H #include <atm.h> #include <linux/atmsvc.h> /* Field type values */ #define F_VCC 0x00000001 #define F_LISTEN_VCC 0x00000002 #define F_REPLY 0x00000004 #define F_PVC 0x00000008 #define F_LOCAL 0x00000010 #define F_QOS 0x00000020 #define F_SVC 0x00000040 #define F_SAP 0x00000080 typedef enum { vt_none,vt_text,vt_vcc,vt_error,vt_svc,vt_pvc,vt_qos,vt_sap } VALUE_TYPE; typedef struct { VALUE_TYPE type; union { const char *text; atm_kptr_t id; int num; struct sockaddr_atmsvc svc; struct sockaddr_atmpvc pvc; struct atm_qos qos; struct atm_sap sap; } u; } VALUE; typedef struct _var { const char *name; VALUE value; struct _var *next; } VAR; extern int quiet,verbose; extern VAR *variables; void yyerror(const char *s); void print_value(VALUE val); VAR *create_var(const char *name); VAR *lookup(const char *name); void assign(VAR *var,VALUE value); void check(VALUE a,VALUE b); VALUE pick(const struct atmsvc_msg *msg,int field); void store(struct atmsvc_msg *msg,int field,VALUE val); VALUE eval(VALUE_TYPE type,const char *str); void cast(VAR *var,VALUE_TYPE type); VALUE_TYPE type_of(int field); void send_msg(const struct atmsvc_msg *msg); void recv_msg(struct atmsvc_msg *msg); void dump_msg(const char *prefix,const struct atmsvc_msg *msg); #endif --- NEW FILE: awrite.c --- /* awrite.c - send AAL5 PDU */ /* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <atm.h> static void usage(const char *name) { fprintf(stderr,"usage: %s [itf.]vpi.vci data [ offset ] \n",name); exit(1); } int main(int argc,char **argv) { struct sockaddr_atmpvc addr; struct atm_qos qos; int s,size,offset; if (argc != 3 && argc != 4) usage(argv[0]); if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); return 1; } memset(&addr,0,sizeof(addr)); if (text2atm(argv[1],(struct sockaddr *) &addr,sizeof(addr),T2A_PVC) < 0) usage(argv[0]); offset = argc == 3 ? 0 : atoi(argv[3]); memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.txtp.traffic_class = ATM_UBR; qos.txtp.max_sdu = strlen(argv[2])-offset; if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (connect(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) { perror("connect"); return 1; } size = write(s,argv[2]+offset,strlen(argv[2])-offset); printf("%d",size); if (size < 0) printf(" (%s)",strerror(errno)); putchar('\n'); return 0; } --- NEW FILE: Makefile.am --- USRPGMS = aread awrite ttcp_atm PGMS = align aping br bw isp window bin_PROGRAMS = $(USRPGMS) noinst_PROGRAMS = $(PGMS) LDADD = $(top_builddir)/src/lib/libatm.la aread_SOURCES = aread.c awrite_SOURCES = awrite.c ttcp_atm_SOURCES = ttcp.c align_SOURCES = align.c aping_SOURCES = aping.c br_SOURCES = br.c bw_SOURCES = bw.c isp_SOURCES = isp.c isp.h ispl_y.y ispl_l.l isp_XTRAS = $(LDADD) $(top_builddir)/src/lib/libatmd.la isp_LDADD = $(isp_XTRAS) -lfl isp_DEPENDENCIES = $(isp_XTRAS) errnos.inc window_SOURCES = window.c CLEANFILES = errnos.inc EXTRA_DIST = ispl_y.h README.isp mkerrnos.pl isp.o: errnos.inc errnos.inc: mkerrnos.pl @PERL@ ./mkerrnos.pl </usr/include/asm/errno.h \ >errnos.inc || { rm -f errnos.inc; exit 1; } --- NEW FILE: mkerrnos.pl --- #!/usr/bin/perl while (<>) { next unless /^#define\s+(E\S+)\s*/; printf(" { \"%s\", %s },\n",$1,$1) || die "print: $!"; } --- NEW FILE: README.isp --- No man page yet. "isp" is a tool for sending and receiving ISP messages, e.g. to test atmsigd. Although it can be used interactively, its poor error handling makes it more suitable for script use. Commands: send msg_type [field=value|field=$var ...] receive [msg_type [field=value|field=$var|$var=field ...]] set $var=value show echo value help where msg_type: bind, connect, accept, reject, listen, okay, error, indicate, close, itf_notify, modify, identify, terminate field: vcc, listen_vcc, reply, pvc, local, qos, svc, sap Variable syntax is like in Perl, i.e. a variable is always prefixed by a dollar sign, even where it is not expanded. Fields and variables are typed. Fields with compatible input have the same type (e.g. "svc" and "local", and "vcc" and "listen_vcc"). The type of variables which are set with "set" is determined the first time they're used in a "send" or "receive" command. Fields which do not exist in a message cannot be accessed (see isp.c, types[] for all valid combinations). Unspecified fields are set to zero. isp does not enforce setting of mandatory fields (yet). "receive" accepts three types of arguments: field=value field must be equal to the value field=$var field must be equal to the content of the variable $var=field content of field is assigned to variable Values can contain pretty much any characters except for whitespace, and they must not begin with dollar, equal, or hash signs. ispl.l contains some hacks (e.g. {tail}) to make things work anyway. There is no way to include whitespace in a value, so things like echo it works don't work (but echo ?$\=# does). Examples: receive bind $VCC=vcc send okay vcc=$VCC set $SAP = blli:l3=tr9577,ipi=snap,oui=0x00A03E,pid=0x0002 send indicate listen_vcc=$VCC svc=+1007 qos=ubr:pcr=123kcps sap=$SAP isp normally pretty-prints all messages. This can be suppressed with -q. A hint for regression test development: To test for pass, put echo PASSED after the command To test for fail, put echo PASSED before and echo FAILED after Check the last echo'ed string for PASSED (or nothing) The absence of conditional execution in isp's language is considered a feature. --- NEW FILE: window.c --- /* window.c, M. Welsh (md...@cl...) * A simple bandwidth/latency benchmark for Linux/ATM. Usage: * window [send | recv] <addr-data> <addr-ack> <num> <msg_size> <window_size> * where * <addr-data> is the VPI/VCI to transmit data on * <addr-ack> is the VPI/VCI to transmit ACKs on * <num> is the number of iterations to run * <msg_size> is the size of each message to send * <window_size> is the number of messages to send between ACKs * * Two VC's are used so that the program can be run between two processes * on the same machine. * * Example: * apple% window recv 0.32 0.33 1000 1024 10 * banana% window send 0.32 0.33 1000 1024 10 * * Copyright (c) 1996 University of Cambridge Computer Laboratory * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * M. Welsh, 6 July 1996 * */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/time.h> #include <sys/uio.h> #include <unistd.h> #include <stdio.h> #include <fcntl.h> #include <assert.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <atm.h> #undef MDW_DEBUG #undef TERSE_OUTPUT #define REPLY_SIZE 40 #define MAX_WINDOW_SIZE 100 static double get_seconds(void) { struct timeval t; gettimeofday(&t,NULL); return (double)t.tv_sec+((double)t.tv_usec/(double)1e6); } int main(int argc, char **argv) { struct sockaddr_atmpvc addr1, addr2; struct atm_qos qos1, qos2; char *buffer; char buffer2[REPLY_SIZE]; int s1, s2; ssize_t size; char *theaddr1, *theaddr2; int NUM_WINDOWS; int PINGPONG_SIZE; int WINDOW_SIZE; int i, w; int sending = 0; double t1, t2; if (argc != 7) { fprintf(stderr,"Usage: window [send | recv] <addr-data> <addr-ack> <num_windows> <message_size> <window_size>\n"); exit(-1); } if (!strcmp(argv[1],"send")) sending = 1; theaddr1 = argv[2]; theaddr2 = argv[3]; NUM_WINDOWS = atoi(argv[4]); PINGPONG_SIZE = atoi(argv[5]); WINDOW_SIZE = atoi(argv[6]); if (WINDOW_SIZE > MAX_WINDOW_SIZE) { fprintf(stderr,"Maximum window size is %d.\n",MAX_WINDOW_SIZE); exit(-1); } if ((s1 = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); exit(-1); } if ((s2 = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); exit(-1); } memset(&addr1, 0, sizeof(addr1)); memset(&addr2, 0, sizeof(addr2)); if (text2atm(theaddr1, (struct sockaddr *)&addr1, sizeof(addr1), T2A_PVC | T2A_UNSPEC | T2A_WILDCARD) < 0) { fprintf(stderr,"window: invalid address syntax\n"); exit(-1); } if (text2atm(theaddr2, (struct sockaddr *)&addr2, sizeof(addr2), T2A_PVC | T2A_UNSPEC | T2A_WILDCARD) < 0) { fprintf(stderr,"window: invalid address syntax\n"); exit(-1); } /* Do a lot of them */ if (sending) { buffer = (char *)malloc(PINGPONG_SIZE); if (!buffer) { fprintf(stderr,"Can't malloc buffer\n"); exit(-1); } for (i = 0; i < PINGPONG_SIZE; i++) { buffer[i] = i&0xff; } memset(&qos1,0,sizeof(qos1)); memset(&qos2,0,sizeof(qos2)); qos1.aal = ATM_AAL5; qos1.txtp.traffic_class = ATM_UBR; qos1.txtp.max_sdu = PINGPONG_SIZE; qos2.aal = ATM_AAL5; qos2.rxtp.traffic_class = ATM_UBR; qos2.rxtp.max_sdu = REPLY_SIZE; if (setsockopt(s1,SOL_ATM,SO_ATMQOS,&qos1,sizeof(qos1)) < 0) { perror("setsockopt SO_ATMQOS1"); exit(-1); } if (setsockopt(s2,SOL_ATM,SO_ATMQOS,&qos2,sizeof(qos2)) < 0) { perror("setsockopt SO_ATMQOS2"); exit(-1); } if (connect(s1, (struct sockaddr *)&addr1, sizeof(addr1)) < 0) { perror("connect"); exit(-1); } if (bind(s2, (struct sockaddr *)&addr2, sizeof(addr1)) < 0) { perror("bind"); exit(-1); } #ifndef TERSE_OUTPUT fprintf(stderr,"Sending %d %d-byte messages, window size %d.\n", NUM_WINDOWS*WINDOW_SIZE,PINGPONG_SIZE,WINDOW_SIZE); #endif t1 = get_seconds(); for (i = 0; i < NUM_WINDOWS; i++) { #ifdef MDW_DEBUG fprintf(stderr,"Sending %d...",i); #endif for (w = 0; w < WINDOW_SIZE; w++) { (void)write(s1, buffer, PINGPONG_SIZE); } #ifdef MDW_DEBUG fprintf(stderr,"sent!..."); #endif #if 1 /* XXX mdw testing! XXX XXX */ /* Get a reply */ size = read(s2, buffer2, REPLY_SIZE); if (size != REPLY_SIZE) { fprintf(stderr,"Received reply of length %d, should be %d.\n", size,REPLY_SIZE); } #endif } t2 = get_seconds(); #ifdef TERSE_OUTPUT fprintf(stderr,"%d %d %d %f %f %f\n", NUM_WINDOWS, PINGPONG_SIZE, WINDOW_SIZE, (t2-t1), ((t2-t1)*1e6)/(NUM_WINDOWS*WINDOW_SIZE), (NUM_WINDOWS*WINDOW_SIZE*PINGPONG_SIZE*8)/(1e6*(t2-t1))); #else fprintf(stderr,"Sent %d %d-byte messages (window size %d) in %f seconds.\n", NUM_WINDOWS*WINDOW_SIZE,PINGPONG_SIZE,WINDOW_SIZE,(t2-t1)); fprintf(stderr,"%f usec/message or %f Mbit/sec\n", ((t2-t1)*1e6)/(NUM_WINDOWS*WINDOW_SIZE), (NUM_WINDOWS*WINDOW_SIZE*PINGPONG_SIZE*8)/(1e6*(t2-t1))); #endif } else { buffer = (char *)malloc(PINGPONG_SIZE); if (!buffer) { fprintf(stderr,"Can't malloc buffer\n"); exit(-1); } memset(&qos1,0,sizeof(qos1)); memset(&qos2,0,sizeof(qos2)); qos1.rxtp.traffic_class = ATM_UBR; qos1.rxtp.max_sdu = PINGPONG_SIZE; qos2.txtp.traffic_class = ATM_UBR; qos2.txtp.max_sdu = REPLY_SIZE; if (setsockopt(s1,SOL_ATM,SO_ATMQOS,&qos1,sizeof(qos1)) < 0) { perror("setsockopt SO_ATMQOS1"); exit(-1); } if (setsockopt(s2,SOL_ATM,SO_ATMQOS,&qos2,sizeof(qos2)) < 0) { perror("setsockopt SO_ATMQOS2"); exit(-1); } if (bind(s1, (struct sockaddr *)&addr1, sizeof(addr1)) < 0) { perror("bind"); exit(-1); } if (connect(s2, (struct sockaddr *)&addr2, sizeof(addr2)) < 0) { perror("connect"); exit(-1); } i = 0; while (i < NUM_WINDOWS*WINDOW_SIZE) { #ifdef MDW_DEBUG fprintf(stderr,"Receiving %d... ",i); #endif size = read(s1, buffer, PINGPONG_SIZE); #ifdef MDW_DEBUG fprintf(stderr,"received!\n"); #endif if (size == PINGPONG_SIZE) { i++; if ((i % WINDOW_SIZE) == 0) { /* Send reply */ #ifdef MDW_DEBUG fprintf(stderr,"Sending reply..."); #endif (void)write(s2, buffer2, REPLY_SIZE); #ifdef MDW_DEBUG fprintf(stderr,"sent!\n"); #endif } } else { fprintf(stderr,"Received message of length %d, should be %d.\n", size,PINGPONG_SIZE); } } } return 0; } --- NEW FILE: ispl_l.l --- %{ /* isp.l - Internal Signaling Protocol test generator language */ /* Written 1997,1998 by Werner Almesberger, EPFL-ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdint.h> #include <linux/atmsvc.h> #include "isp.h" #include "ispl_y.h" static int lineno = 1; %} tail ([^a-zA-Z0-9]|$|[ \t\n]*=.*) %% send return TOK_SEND; wait return TOK_WAIT; receive return TOK_RECEIVE; help return TOK_HELP; set return TOK_SET; show return TOK_SHOW; echo return TOK_ECHO; vcc/{tail} return TOK_VCC; listen_vcc/{tail} return TOK_LISTEN_VCC; reply/{tail} return TOK_REPLY; pvc/{tail} return TOK_PVC; local/{tail} return TOK_LOCAL; qos/{tail} return TOK_QOS; svc/{tail} return TOK_SVC; sap/{tail} return TOK_SAP; listen return TOK_LISTEN; bind return TOK_BIND; connect return TOK_CONNECT; accept return TOK_ACCEPT; reject return TOK_REJECT; okay return TOK_OKAY; error return TOK_ERROR; indicate return TOK_INDICATE; close return TOK_CLOSE; itf_notify return TOK_ITF_NOTIFY; modify return TOK_MODIFY; identify return TOK_IDENTIFY; terminate return TOK_TERMINATE; \\[\t ]*\n lineno++; #[^\n]*\n lineno++; [^ \t\n\$=][^ \t\n]* { yylval.str = strdup(yytext); if (!yylval.str) { perror("strdup"); exit(1); } return TOK_VALUE; } \$[0-9a-zA-Z_]+ { yylval.str = strdup(yytext+1); if (!yylval.str) { perror("strdup"); exit(1); } return TOK_VARIABLE; } \n { lineno++; return TOK_EOL; } [\t ]* ; . return *yytext; %% void yyerror(const char *s) { fprintf(stderr,"line %d: %s near \"%s\"\n",lineno,s,yytext); exit(1); } --- NEW FILE: ispl_y.y --- %{ /* isp.y - Internal Signaling Protocol test generator language */ /* Written 1997,1998 by Werner Almesberger, EPFL-ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <atm.h> #include <linux/atmsvc.h> #include "isp.h" static struct atmsvc_msg msg; %} %union { char *str; int num; enum atmsvc_msg_type type; VAR *var; }; %token TOK_SEND TOK_WAIT TOK_RECEIVE TOK_HELP TOK_SET TOK_SHOW TOK_ECHO %token TOK_VCC TOK_LISTEN TOK_LISTEN_VCC TOK_REPLY TOK_PVC %token TOK_LOCAL TOK_QOS TOK_SVC TOK_BIND TOK_CONNECT TOK_ACCEPT %token TOK_REJECT TOK_LISTEN TOK_OKAY TOK_ERROR TOK_INDICATE %token TOK_CLOSE TOK_ITF_NOTIFY TOK_MODIFY TOK_SAP %token TOK_IDENTIFY TOK_TERMINATE TOK_EOL %token <str> TOK_VALUE TOK_VARIABLE %type <type> type %type <num> field_type number %type <var> new_var old_var %% all: | command all ; command: TOK_SEND type { memset(&msg,0,sizeof(msg)); msg.type = $2; } values { send_msg(&msg); if (verbose) dump_msg("SENT",&msg); } | TOK_RECEIVE { recv_msg(&msg); if (!quiet) dump_msg("RECV",&msg); } opt_recv | TOK_WAIT number { sleep($2); } | TOK_SET new_var '=' TOK_VALUE { assign($2,eval(vt_text,$4)); free($4); } | TOK_SHOW { VAR *var; for (var = variables; var; var = var->next) { printf("%s = ",var->name); print_value(var->value); putchar('\n'); } } | TOK_ECHO TOK_VALUE { printf("%s\n",$2); free($2); } | help { fprintf(stderr, "Commands:\n" " send msg_type [field=value|field=$var ...]\n" " receive [msg_type [field=value|field=$var|$var=field ...]]\n" " set $var=value\n" " show\n" " echo value\n" " help\n\n" "msg_type: bind, connect, accept, reject, listen, okay, error, indicate,\n" " close, itf_notify, modify, identify, terminate\n" "field: vcc, listen_vcc, reply, pvc, local, qos, svc, sap\n"); } | TOK_EOL ; type: TOK_BIND { $$ = as_bind; } | TOK_CONNECT { $$ = as_connect; } | TOK_ACCEPT { $$ = as_accept; } | TOK_REJECT { $$ = as_reject; } | TOK_LISTEN { $$ = as_listen; } | TOK_OKAY { $$ = as_okay; } | TOK_ERROR { $$ = as_error; } | TOK_INDICATE { $$ = as_indicate; } | TOK_CLOSE { $$ = as_close; } | TOK_ITF_NOTIFY { $$ = as_itf_notify; } | TOK_MODIFY { $$ = as_modify; } | TOK_IDENTIFY { $$ = as_identify; } | TOK_TERMINATE { $$ = as_terminate; } ; values: | value values ; value: field_type '=' old_var { cast($3,type_of($1)); store(&msg,$1,$3->value); } | field_type '=' TOK_VALUE { store(&msg,$1,eval(type_of($1),$3)); free($3); } ; number: TOK_VALUE { char *end; $$ = strtol($1,&end,10); if (*end) yyerror("invalid number"); free($1); } ; opt_recv: | type { if (msg.type != $1) yyerror("wrong message type"); } fields ; fields: | field fields ; field: new_var '=' field_type { assign($1,pick(&msg,$3)); } | field_type '=' old_var { cast($3,type_of($1)); check(pick(&msg,$1),$3->value); } | field_type '=' TOK_VALUE { check(pick(&msg,$1),eval(type_of($1),$3)); free($3); } ; field_type: TOK_VCC { $$ = F_VCC; } | TOK_LISTEN_VCC { $$ = F_LISTEN_VCC; } | TOK_REPLY { $$ = F_REPLY; } | TOK_PVC { $$ = F_PVC; } | TOK_LOCAL { $$ = F_LOCAL; } | TOK_QOS { $$ = F_QOS; } | TOK_SVC { $$ = F_SVC; } | TOK_SAP { $$ = F_SAP; } ; help: TOK_HELP | '?' ; new_var: TOK_VARIABLE { $$ = lookup($1); if ($$) free($1); else $$ = create_var($1); } ; old_var: TOK_VARIABLE { $$ = lookup($1); if (!$$) yyerror("no such variable"); free($1); } ; --- NEW FILE: ttcp.c --- /* * T T C P . C * * Test TCP connection. Makes a connection on port 5013 * and transfers fabricated buffers or data copied from stdin. * * Usable on 4.2, 4.3, and 4.1a systems by defining one of * BSD42 BSD43 (BSD41a) * Machines using System V with BSD sockets should define SYSV. * * Modified for operation under 4.2BSD, 18 Dec 84 * T.C. Slattery, USNA * Minor improvements, Mike Muuss and Terry Slattery, 16-Oct-85. * Modified in 1989 at Silicon Graphics, Inc. * catch SIGPIPE to be able to print stats when receiver has died * for tcp, don't look for sentinel during reads to allow small transfers * increased default buffer size to 8K, nbuf to 2K to transfer 16MB * moved default port to 5013, beyond IPPORT_USERRESERVED * make sinkmode default because it is more popular, [...1025 lines suppressed...] unsigned n; { register unsigned count = 0; register int nread; do { nread = read(fd, bufp, n-count); numCalls++; if(nread < 0) { perror("ttcp_mread"); return(-1); } if(nread == 0) return((int)count); count += (unsigned)nread; bufp += nread; } while(count < n); return((int)count); } --- NEW FILE: align.c --- /* align.c - Exercise PDU mis-alignment handling by the NIC */ /* Written 1997,1998 by Werner Almesberger, EPFL-LRC/ICA */ /* * This program requires a kernel modification: if the first byte of the PDU * to send is a small decimal digit N < 8, the first N bytes of the PDU are * removed and the start address is shifted accordingly. This forces * mis-alignment of the PDU. * * The expected network configuration is a loopback between the TXer and the * RXer of the NIC under test. */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <signal.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/errno.h> #include <atm.h> #define MAX_SDU 20000 #define MAX_OFFSET 8 static void handler(int dummy) { (void) signal(SIGALRM,&handler); } static void torture(int s) { static unsigned long done[MAX_SDU*MAX_OFFSET/8/sizeof(unsigned long)]; unsigned char in[MAX_SDU],out[MAX_SDU]; unsigned char ch; int todo; todo = MAX_SDU*MAX_OFFSET-(MAX_OFFSET+1)*MAX_OFFSET/2; handler(0); while (todo) { int length,offset; int word,bit; int i,sent,got; length = (random() % MAX_SDU)+1; offset = random() % MAX_OFFSET; ch = random() & 0xff; bit = (length-1)*MAX_OFFSET+offset; word = bit/sizeof(unsigned long)/8; bit &= sizeof(unsigned long)*8-1; if (length <= offset || (done[word] & (1 << bit))) continue; out[0] = offset+'0'; for (i = 1; i < length; i++) out[i] = ch++; sent = write(s,out,length); if (sent < 0) { perror("write"); exit(1); } if (sent != length) { fprintf(stderr,"bad write: %d != %d\n",sent,length); exit(1); } alarm(1); got = read(s,in,length); alarm(0); if (got < 0 && errno == EINTR) { fprintf(stderr,"timed out at length %d, offset %d\n",length,offset); continue; } if (got < 0) { perror("read"); exit(1); } if (got != length-offset) { fprintf(stderr,"bad read: %d != %d-%d\n",got,length,offset); exit(1); } if (memcmp(out+offset,in,length-offset)) { fprintf(stderr,"bad compare: length %d, offset %d\n",length, offset); exit(1); } done[word] |= 1 << bit; todo--; if (!(todo % 100)) fprintf(stderr,"%6d\r",todo); } } static void usage(const char *name) { fprintf(stderr,"usage: %s [itf.]vpi.vci\n",name); exit(1); } int main(int argc,char **argv) { struct sockaddr_atmpvc addr; struct atm_qos qos; int s; if (argc != 2) usage(argv[0]); if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); return 1; } memset(&addr,0,sizeof(addr)); if (text2atm(argv[1],(struct sockaddr *) &addr,sizeof(addr),T2A_PVC) < 0) usage(argv[0]); memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR; qos.txtp.max_sdu = qos.rxtp.max_sdu = MAX_SDU; if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (connect(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) { perror("connect"); return 1; } srandom(0); /* we want it to be deterministic */ torture(s); return 0; } --- NEW FILE: aping.c --- /* aping.c - simple round-trip tester */ /* Written 1996,1997 by Werner Almesberger, EPFL-LRC */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> #include <atm.h> #define SEND 25*1000 #define RECV 70*1000 #define RECOVER 10 static const char *rotor[] = { "|\r","/\r","-\r","\\\r" }; static void usage(const char *name) { fprintf(stderr,"usage: %s [itf.]vpi.vci\n",name); exit(1); } int main(int argc,char **argv) { struct timeval delta,now,next,fail; struct sockaddr_atmpvc addr; struct atm_qos qos; int s,i,len; if (argc != 2) usage(argv[0]); if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); return 1; } memset(&addr,0,sizeof(addr)); if (text2atm(argv[1],(struct sockaddr *) &addr,sizeof(addr), T2A_PVC | T2A_UNSPEC | T2A_WILDCARD) < 0) usage(argv[0]); memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.txtp.traffic_class = ATM_UBR; qos.txtp.traffic_class = ATM_UBR; qos.txtp.max_sdu = 1; qos.rxtp = qos.txtp; if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) { perror("bind"); return 1; } if (gettimeofday(&next,NULL) < 0) { perror("gettimeofday"); return 1; } fail = next; fail.tv_sec += RECOVER; delta.tv_sec = delta.tv_usec = 0; i = 0; len = 1; /* length varies to make losses more visible in the kernel */ while (1) { fd_set set; FD_ZERO(&set); FD_SET(s,&set); (void) select(s+1,&set,NULL,NULL,&delta); if (gettimeofday(&now,NULL) < 0) { perror("gettimeofday"); return 1; } if (FD_ISSET(s,&set)) { char dummy[2]; int size; size = read(s,dummy,2); if (size < 0) { perror("read"); return 1; } if (size != 1) { fprintf(stderr,"bad RX (%d)\n",size); #if 0 if (size > 1) return 1; #endif } fail = now; fail.tv_usec += RECV; while (fail.tv_usec >= 1000000) { fail.tv_usec -= 1000000; fail.tv_sec++; } (void) write(1,rotor[i = (i+1) & 3],2); len = 1; } if (fail.tv_sec < now.tv_sec || (fail.tv_sec == now.tv_sec && fail.tv_usec < now.tv_usec)) { fprintf(stderr,"RX timed out\n"); fail.tv_sec += RECOVER; #if 0 #if 1 len++; #else len = 2 /*1+(len % 3)*/; #endif #endif } while (next.tv_sec < now.tv_sec || (next.tv_sec == now.tv_sec && next.tv_usec < now.tv_usec)) { if (write(s,"XYZ...",len) != len) { perror("write"); return 1; } next.tv_usec += SEND; while (next.tv_usec >= 1000000) { next.tv_usec -= 1000000; next.tv_sec++; } } delta.tv_sec = next.tv_sec-now.tv_sec; delta.tv_usec = next.tv_usec-now.tv_usec; while (delta.tv_usec < 0) { delta.tv_sec--; delta.tv_usec += 1000000; } } return 0; } --- NEW FILE: aread.c --- /* aread.c - receive AAL5 PDU */ /* Written 1995-1998 by Werner Almesberger, EPFL-LRC/ICA */ #if HAVE_CONFIG_H #include <config.h> #endif #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <errno.h> #include <sys/types.h> #include <sys/socket.h> #include <atm.h> #define BSIZE 1024 static void usage(const char *name) { fprintf(stderr,"usage: %s [-c] [itf.]vpi.vci\n",name); exit(1); } int main(int argc,char **argv) { const char *name; struct sockaddr_atmpvc addr; struct atm_qos qos; int chars,s; name = argv[0]; chars = argc == 3 && !strcmp(argv[1],"-c"); if (chars) { argc--; argv++; } if (argc != 2) usage(name); if ((s = socket(PF_ATMPVC,SOCK_DGRAM,0)) < 0) { perror("socket"); return 1; } memset(&addr,0,sizeof(addr)); if (text2atm(argv[1],(struct sockaddr *) &addr,sizeof(addr), T2A_PVC | T2A_UNSPEC | T2A_WILDCARD) < 0) usage(name); memset(&qos,0,sizeof(qos)); qos.aal = ATM_AAL5; qos.rxtp.traffic_class = ATM_UBR; qos.rxtp.max_sdu = BSIZE; if (setsockopt(s,SOL_ATM,SO_ATMQOS,&qos,sizeof(qos)) < 0) { perror("setsockopt SO_ATMQOS"); return 1; } if (bind(s,(struct sockaddr *) &addr,sizeof(addr)) < 0) { perror("bind"); return 1; } while (1) { unsigned char buf[BSIZE+4096]; unsigned char *start; int size,i; /* Make sure the buffer is aligned. This can be trivially extended to play with alignments. */ start = (unsigned char *) (((unsigned long) buf+4095) & ~4095UL); size = read(s,start,BSIZE); printf("%d",size); if (size < 0) printf(" (%s)",strerror(errno)); printf(": "); for (i = 0; i < size; i++) if (chars) if (start[i] > ' ' && start[i] < 127) printf(" %c",start[i]); else printf(" \\%03o",start[i]); else printf(" %02X",start[i]); putchar('\n'); } } |