comerr-behave-like-the-rest-of-the-world-20010918
[openafs.git] / src / rxkad / test / stress.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* RX Authentication Stress test: server side code. */
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 RCSID("$Header$");
16
17 #include <afs/stds.h>
18 #include <sys/types.h>
19 #ifdef AFS_NT40_ENV
20 #include <winsock2.h>
21 #else
22 #include <netdb.h>
23 #include <netinet/in.h>
24 #endif
25 #include <stdio.h>
26 #include <lwp.h>
27 #include <rx/xdr.h>
28 #include <rx/rx.h>
29 #include <afs/com_err.h>
30 #include <afs/cmd.h>
31
32 #include <rx/rxkad.h>
33 #include "stress.h"
34 #include "stress_internal.h"
35 #include "rx/rx_globals.h"
36 #ifdef AFS_PTHREAD_ENV
37 #include <pthread.h>
38 #endif
39
40 int maxSkew = 5;
41
42
43 static char *whoami;
44
45 static int StringToAuth (authname)
46   IN char *authname;
47 {
48     int nonoauth = 0;
49     if (strcmp (authname, "rxkad") == 0) return rxkad_clear;
50     if (strcmp (authname, "rxkad_")) {
51         if (strncmp (authname, "rxkad_", 6) == 0)
52             nonoauth++, authname += 6;
53         if (strcmp (authname, "clear") == 0) return rxkad_clear;
54         if (strcmp (authname, "auth") == 0) return rxkad_auth;
55         if (strcmp (authname, "crypt") == 0) return rxkad_crypt;
56         if (strcmp (authname, "null") == 0) return -1;
57         if (strcmp (authname, "none") == 0) return -1;
58         if (strncmp (authname, "noauth", 6) == 0) return -1;
59         if (strncmp (authname, "unauth", 6) == 0) return -1;
60         /* error */
61     }
62     fprintf (stderr,
63              "Unknown authentication name %s, using rxkad_clear by default\n",
64              authname);
65     return rxkad_clear;
66 }
67
68 #define aSERVER         0
69 #define aCLIENT         1
70 #define aSENDLEN        2
71 #define aRECVLEN        3
72 #define aFASTCALLS      4
73 #define aSLOWCALLS      5
74 #define aCOPIOUSCALLS   6
75 #define aPRINTSTATS     7
76 #define aPRINTTIMING    8
77 #define aNOEXIT         9
78 #define aSTHREADS      10
79 #define aCTHREADS      11
80 #define aCALLTEST      12
81 #define aHIJACKTEST    13
82 #define aAUTHENTICATION 14
83 #define aMINSERVERAUTH 15
84 #define aREPEATINTERVAL 16
85 #define aREPEATCOUNT   17
86 #define aSTOPSERVER    18
87 #define aTRACE         19
88 #define aMELT1b    20
89 #define aRECLAIM     21
90 #define a2DCHOICE     22
91 #define aMAXSKEW        23
92
93 static int CommandProc (as, arock)
94   char *arock;
95   struct cmd_syndesc *as;
96 {
97     long code;
98     int startServer = (as->parms[aSERVER].items != 0);
99     int startClient = (as->parms[aCLIENT].items != 0);
100 #ifndef AFS_PTHREAD_ENV
101     PROCESS pid;
102 #endif
103     struct serverParms *sParms;
104     struct clientParms *cParms;
105
106     sParms = (struct serverParms *) osi_Alloc (sizeof(*sParms));
107     cParms = (struct clientParms *) osi_Alloc (sizeof(*cParms));
108     memset(sParms, 0, sizeof(*sParms));
109     memset(cParms, 0, sizeof(*cParms));
110     sParms->whoami = cParms->whoami = whoami;
111
112     if (!(startServer || startClient)) {
113         /* Default to "-server -client <localhost>" */
114         gethostname(cParms->server, sizeof(cParms->server));
115         startServer = startClient = 1;
116     }
117
118     /* get booleans */
119     cParms->printStats = (as->parms[aPRINTSTATS].items != 0);
120     cParms->printTiming = (as->parms[aPRINTTIMING].items != 0);
121     cParms->noExit = (as->parms[aNOEXIT].items != 0);
122     cParms->callTest = (as->parms[aCALLTEST].items != 0);
123     cParms->hijackTest = (as->parms[aHIJACKTEST].items != 0);
124     cParms->stopServer = (as->parms[aSTOPSERVER].items != 0);
125
126     if (as->parms[aMELT1b].items) 
127         meltdown_1pkt = 0; 
128     if (as->parms[aRECLAIM].items) 
129         rxi_doreclaim = 0; 
130     if (as->parms[a2DCHOICE].items) 
131         rxi_2dchoice = 0; 
132
133     if (startServer) {
134         if (as->parms[aTRACE].items) {
135           extern char rxi_tracename[];
136           strcpy (rxi_tracename, as->parms[aTRACE].items->data);
137         }
138
139         /* These options not compatible with -server */
140         if (cParms->stopServer) {
141             code = RXKST_BADARGS;
142             com_err (whoami, code, "stop server not compatible with -client");
143             return code;
144         }
145
146         /* process -server options */
147         sParms->threads = 3;            /* one less than channels/conn */
148         if (as->parms[aSTHREADS].items)
149             sParms->threads = atoi (as->parms[aSTHREADS].items->data);
150         sParms->authentication = 0;
151         if (as->parms[aMINSERVERAUTH].items)
152             sParms->authentication =
153                 StringToAuth (as->parms[aMINSERVERAUTH].items->data);
154
155 #ifdef AFS_PTHREAD_ENV
156         {
157             pthread_t serverID;
158             pthread_attr_t tattr;
159
160             code = pthread_attr_init(&tattr);
161             if (code) {
162                 com_err (whoami, code, "can't pthread_attr_init server process");
163                 return code;
164             }
165
166             code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
167             if (code) {
168                 com_err (whoami, code, "can't pthread_attr_setdetachstate server process");
169                 return code;
170             }
171
172             code = pthread_create(&serverID, &tattr, rxkst_StartServer,
173                                   (void*)sParms);
174         }
175 #else
176         code = LWP_CreateProcess(rxkst_StartServer, 16000, LWP_NORMAL_PRIORITY,
177                                  (opaque) sParms, "Server Process", &pid);
178 #endif
179         if (code) {
180             com_err (whoami, code, "can't create server process");
181             return code;
182         }
183     } else {
184         /* check for server-only args */
185     }
186
187     if (startClient) {
188         u_long calls;                   /* default number of calls */
189
190         /* process -client options */
191         if (as->parms[aCLIENT].items)
192             lcstring (cParms->server, as->parms[aCLIENT].items->data,
193                       sizeof(cParms->server));
194         cParms->threads = 6;            /* 150% of channels/conn */
195         if (as->parms[aCTHREADS].items)
196             cParms->threads = atoi (as->parms[aCTHREADS].items->data);
197         if (cParms->callTest || cParms->hijackTest ||
198             cParms->printTiming || cParms->stopServer)
199             calls = 0;
200         else calls = 1;
201         cParms->fastCalls = cParms->slowCalls = cParms->copiousCalls = calls;
202
203         cParms->sendLen = cParms->recvLen = 10000;
204         if (as->parms[aSENDLEN].items)
205             cParms->sendLen = atoi (as->parms[aSENDLEN].items->data);
206         if (as->parms[aRECVLEN].items)
207             cParms->recvLen = atoi (as->parms[aRECVLEN].items->data);
208         if (as->parms[aFASTCALLS].items)
209             cParms->fastCalls = atoi (as->parms[aFASTCALLS].items->data);
210         if (as->parms[aSLOWCALLS].items)
211             cParms->slowCalls = atoi (as->parms[aSLOWCALLS].items->data);
212         if (as->parms[aCOPIOUSCALLS].items)
213             cParms->copiousCalls = atoi (as->parms[aCOPIOUSCALLS].items->data);
214         cParms->repeatInterval = cParms->repeatCount = 0;
215         if (as->parms[aREPEATINTERVAL].items)
216             cParms->repeatInterval =
217                 atoi (as->parms[aREPEATINTERVAL].items->data);
218         if (as->parms[aREPEATCOUNT].items)
219             cParms->repeatCount =
220                 atoi (as->parms[aREPEATCOUNT].items->data);
221         if (as->parms[aMAXSKEW].items) {
222             maxSkew = 
223                 atoi (as->parms[aMAXSKEW].items->data);
224             if (maxSkew < 1) {
225                 printf("Minimum allowed maxSkew is 1, resetting.\n");
226                 maxSkew = 1;
227             }
228         }
229
230         cParms->authentication = 0;
231         if (as->parms[aAUTHENTICATION].items)
232             cParms->authentication =
233                 StringToAuth (as->parms[aAUTHENTICATION].items->data);
234
235         code = rxkst_StartClient (cParms);
236         if (code) {
237             com_err (whoami, code, "StartClient returned");
238             return code;
239         }
240     } else {
241         if (as->parms[aSENDLEN].items || as->parms[aRECVLEN].items ||
242             as->parms[aFASTCALLS].items || as->parms[aSLOWCALLS].items ||
243             as->parms[aCOPIOUSCALLS].items) {
244             code = RXKST_BADARGS;
245             com_err (whoami, code, "send/recv len and # calls are client options");
246             return code;
247         }
248
249         /* donate this LWP to server-side */
250         rx_ServerProc();
251     }
252
253     return 0;
254 }
255
256 void main (argc, argv)
257   IN int   argc;
258   IN char *argv[];
259 {
260     long  code;
261 #ifndef AFS_PTHREAD_ENV
262     PROCESS initialProcess;
263 #endif
264     struct cmd_syndesc *ts;
265
266     whoami = argv[0];
267
268     initialize_RXK_error_table();
269     initialize_RKS_error_table();
270     initialize_CMD_error_table();
271
272     code = rx_Init (0);
273     rx_SetRxDeadTime(120);
274     if (code < 0) {
275         com_err (whoami, code, "can't init Rx");
276         exit (1);
277     }
278 #ifndef AFS_PTHREAD_ENV
279     initialProcess = 0;
280     code = LWP_CurrentProcess (&initialProcess);
281     if (code) {
282         com_err (whoami, code, "LWP initialization failed");
283         exit (1);
284     }
285 #endif
286     ts = cmd_CreateSyntax((char *) 0, CommandProc, 0, "run Rx authentication stress test");
287     cmd_AddParm (ts, "-server", CMD_FLAG, CMD_OPTIONAL, "start server");
288     cmd_AddParm (ts, "-client", CMD_SINGLE, CMD_OPTIONAL, "start client");
289     cmd_AddParm (ts, "-sendlen", CMD_SINGLE, CMD_OPTIONAL, "bytes to send to server in Copious call");
290     cmd_AddParm (ts, "-recvlen", CMD_SINGLE, CMD_OPTIONAL, "bytes to request from server in Copious call");
291     cmd_AddParm (ts, "-fastcalls", CMD_SINGLE, CMD_OPTIONAL, "number of fast calls to make");
292     cmd_AddParm (ts, "-slowcalls", CMD_SINGLE, CMD_OPTIONAL, "number of slow calls to make (one second)");
293     cmd_AddParm (ts, "-copiouscalls", CMD_SINGLE, CMD_OPTIONAL, "number of fast calls to make");
294     cmd_AddParm (ts, "-printstatistics", CMD_FLAG, CMD_OPTIONAL, "print statistics before exiting");
295     cmd_AddParm (ts, "-printtimings", CMD_FLAG, CMD_OPTIONAL, "print timing information for calls");
296     cmd_AddParm (ts, "-noexit", CMD_FLAG, CMD_OPTIONAL, "don't exit after successful finish");
297     cmd_AddParm (ts, "-sthreads", CMD_SINGLE, CMD_OPTIONAL, "number server threads");
298     cmd_AddParm (ts, "-cthreads", CMD_SINGLE, CMD_OPTIONAL, "number client threads");
299     cmd_AddParm (ts, "-calltest", CMD_FLAG, CMD_OPTIONAL, "check server's call number verification (this takes about 30 seconds)");
300     cmd_AddParm (ts, "-hijacktest", CMD_FLAG, CMD_OPTIONAL, "check hijack prevention measures by making various modifications to incoming/outgoing packets");
301     cmd_AddParm (ts, "-authentication", CMD_SINGLE, CMD_OPTIONAL, "type of authentication to use; one of: none, clear, auth, crypt");
302     cmd_AddParm (ts, "-minserverauth", CMD_SINGLE, CMD_OPTIONAL, "minimum level of authentication permitted by server");
303     cmd_AddParm (ts, "-repeatinterval", CMD_SINGLE, CMD_OPTIONAL, "seconds between load test activity");
304     cmd_AddParm (ts, "-repeatcount", CMD_SINGLE, CMD_OPTIONAL, "repetitions of load test activity");
305     cmd_AddParm (ts, "-stopserver", CMD_FLAG, CMD_OPTIONAL, "send RPC to cause server to exit");
306     cmd_AddParm (ts, "-trace", CMD_SINGLE, CMD_OPTIONAL, "file for per-call trace info");
307     cmd_AddParm (ts, "-nomd1pkt", CMD_FLAG, CMD_OPTIONAL, "dont prefer one-packet calls");
308     cmd_AddParm (ts, "-noreclaim", CMD_FLAG, CMD_OPTIONAL, "dont aggressively reclaim packets");
309     cmd_AddParm (ts, "-no2dchoice", CMD_FLAG, CMD_OPTIONAL, "disable rx_getcall 2d choice code");
310     cmd_AddParm (ts, "-maxskew", CMD_SINGLE, CMD_OPTIONAL, "max client server skew in seconds");
311
312     code = cmd_Dispatch (argc, argv);
313     exit (code!=0);
314 }