/* $Id: maxrw_cps.C,v 1.3 2000/08/30 07:53:53 fubob Exp $ */ /* Use this program to simulate a herd of SFSRW clients. You can then test the maximum number of sustainable connections per second to an SFSRW server */ /* * * Copyright (C) 2000 Kevin Fu (fubob@mit.edu) * * 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, 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA * */ #include "maxrw_cps.h" #include "parseopt.h" unsigned long count = 0; unsigned long attempted = 0; u_int64_t bytecount = 0; u_int64_t starttime; char *opt_name = NULL; bool opt_verbose = false; int opt_test = 0; in_addr addr; ptr client_key; char *hostid; int sfsrw_port; sfs_connectarg carg; diropargs3 lookuparg; nfs_fh3 readlinkarg; inline u_int64_t gettime () { timeval tv; gettimeofday (&tv, NULL); return tv.tv_sec * INT64(1000000) + tv.tv_usec; } void init () { kc = client_key; srvcon::connect (); } void connect () { tcpconnect (*ia, sfsrw_port, wrap (getsockres)); } void getsockres (int fd) { if (fd < 0) timecb (timenow + 1, wrap (connect)); else { s = axprt_crypt::alloc (fd); sfsc = aclnt::alloc (s, sfs_program_1); sfsc->call (SFSPROC_CONNECT, &carg, &conres, wrap (sfsconres)); } } void srvcon::sfsconres (clnt_stat err) { if (err) fail (EIO); else if (conres.status) fail (conres.status); else { sfs_client_crypt (sfsc, kc, carg, *conres.reply, wrap (cryptres)); } } void srvcon::cryptres (const sfs_hash *sessid) { if (sessid) { // s->authinfo.sessid = *sessid; sfsc->call (SFSPROC_GETFSINFO, NULL, &fsires, wrap (getfsinfores)); } else fail (EIO); } void srvcon::getfsinfores (clnt_stat err) { if (err) fail (EIO); else if (fsires.prog != ex_NFS_PROGRAM || fsires.nfs->vers != ex_NFS_V3) fail (EPROTONOSUPPORT); else { sfsrwc = aclnt::alloc (s, ex_nfs_program_3); sfsrwc->call (ex_NFSPROC3_LOOKUP, &lookuparg, &lres, wrap (lookupres)); } } void srvcon::lookupres (clnt_stat err) { if (err) fail (EIO); else { /* sfsrwcd: ACLNT_TRACE: call ex_nfs_program_3:ex_NFSPROC3_GETATTR x=3 nfs_fh3 ARGS = { opaque data<64> = [32] { e1, 86, 8e, 80, dc, 20, fa, 38, 93, c5, 09, bc, 44, a6, 01, e0, 6b, 36, c8, 26, 55, 0b, 22, 97, 66, 3e, 23, cd, 18, 6e, 85, 69 }; }; */ sfsrwc->call (ex_NFSPROC3_READLINK, &readlinkarg, &rres, wrap (this, &srvcon::readlinkres)); } } void readlinkres (clnt_stat err) { // Handle readlink of the symlink "foo" /* sfsrwcd: ACLNT_TRACE: call ex_nfs_program_3:ex_NFSPROC3_LOOKUP x=5 diropargs3 ARGS = { nfs_fh3 dir = { opaque data<64> = [32] { e1, 86, 8e, 80, dc, 20, fa, 38, 93, c5, 09, bc, 44, a6, 01, e0, 6b, 36, c8, 26, 55, 0b, 22, 97, 66, 3e, 23, cd, 18, 6e, 85, 69 }; }; string name<> = "ny"; */ } void accressres (clnt_stat err) { /* sfsrwcd: ACLNT_TRACE: call ex_nfs_program_3:ex_NFSPROC3_ACCESS x=6 access3args ARGS = { nfs_fh3 object = { opaque data<64> = [32] { e1, 86, 8e, 80, dc, 20, fa, 38, 93, c5, 09, bc, 44, a6, 01, e0, 6b, 36, c8, 26, 55, 0b, 22, 97, 66, 3e, 23, cd, 18, 6e, 85, 69 }; }; u_int32_t access = 0x3f; }; */ } /* sfsrwcd: ACLNT_TRACE: call ex_nfs_program_3:ex_NFSPROC3_FSINFO x=7 nfs_fh3 ARGS = { opaque data<64> = [32] { e1, 86, 8e, 80, dc, 20, fa, 38, 93, c5, 09, bc, 44, a6, 01, e0, aa, 02, 6d, 88, 6b, 9b, 24, 2b, 1f, 60, 4c, 7c, 7d, c3, b3, 50 }; }; */ /* sfsrwcd: ACLNT_TRACE: call ex_nfs_program_3:ex_NFSPROC3_READLINK x=8 nfs_fh3 ARGS = { opaque data<64> = [32] { e1, 86, 8e, 80, dc, 20, fa, 38, 93, c5, 09, bc, 44, a6, 01, e0, aa, 02, 6d, 88, 6b, 9b, 24, 2b, 1f, 60, 4c, 7c, 7d, c3, b3, 50 }; }; */ void usage () { warnx << "Trace numbers are:\n\n"; fatal << "\nusage: " << progname << " [-p trigger-port] [-n num-clients]\n" << " [-t seconds] [-l label] [-v] -r trace-num server\n\n" << "Remember to set SFS_PORT\n"; } int main (int argc, char **argv) { setprogname (argv[0]); sfsconst_init (); // warn ("pid %d\n", getpid ()); if (argc < 6 || argc > 7) fatal ("usage: %s []\n", progname.cstr ()); int numconn = atoi (argv[1]); sfsrw_port = atoi (argv[2]); hostname = argv[3]; hostid = argv[4]; u_int64_t duration_tm = atoi(argv[5]); if (duration_tm>= 1000000) { warn << "Duration too long. Go away.\n"; exit (-1); } const int pubkeybits = 768; // sfs_pubkeysize; client_key = New refcounted (rabin_keygen (pubkeybits)); warn << "Making " << duration_tm << " seconds worth of calls in windows of " << numconn << " connections to " << hostname << ":" << hostid << "\n"; struct hostent *h; if ((h = gethostbyname (hostname)) == NULL) { warn << "gethostbyname failed\n"; exit(-1); } ia = (struct in_addr *) h->h_addr; lookuparg.dir.data.setsize (32); memcpy (lookuparg.dir.data.base (), "\xe1\x86\x8e\x80\xdc\x20\xfa\x38\x93\xc5\x09\xbc\x44\xa6\x01\xe0\x71\x48\xc6\x50\x75\xd2\xdd\xda\x7f\xd7\xc8\x5e\xc1\xe1\x14\x06", 32); lookuparg.name = "bar"; readlinkarg.data.setsize (32); memcpy (readlinkarg.data.base (), "\x7a\x8a\x25\xbb\x89\xaf\x6e\xda\xe9\x8d\x38\x05\x4b\x98\x80\x25\x80\xec\x50\xfc\xc4\x68\xd1\x81\xac\xf8\x25\x6d\x5b\xb2\x15\x77\xae\x29\xb5\xcf\xba\xa3\x4e\x2b", 32); carg.release = SFS_RELEASE; carg.service = SFS_SFS; carg.name = hostname; if (!sfs_ascii2hostid (&carg.hostid, hostid)) { warn << "Can't decode hostid\n"; exit (-1); } sigcb (SIGALRM, wrap (handler)); sigcb (SIGINT, wrap (handler)); sigcb (SIGTERM, wrap (handler)); struct itimerval itv; itv.it_value.tv_sec = duration_tm; itv.it_value.tv_usec = 0; // Trigger for remote synchronization if (argc == 7) { int udpsock = inetsocket (SOCK_DGRAM, atoi (argv[6])); if (udpsock < 0) { fatal ("socket"); } int broadcast = 1; if (setsockopt (udpsock, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof (broadcast)) < 0) fatal ("setsockopt: %m\n"); char buf[1]; // Block until triggered if (recvfrom (udpsock, buf, 1, 0, NULL, NULL) < 0) { fatal ("sendto: %m\n"); } } int err; if ((err = setitimer (ITIMER_REAL, &itv, NULL)) != 0) { warn << "setitimer failed " << strerror (errno) << "\n"; exit (-1); } start_tm = get_time(); for (int i=0; i< numconn; i++) vNew srvcon (); amain (); }