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