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