summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorslavomir.katuscak%sun.com <devnull@localhost>2008-03-18 14:35:19 +0000
committerslavomir.katuscak%sun.com <devnull@localhost>2008-03-18 14:35:19 +0000
commit018326c1b708e3a3e0303d327946e30aa9544fd7 (patch)
tree85ba2c1decc6389739badba782cbec5b2c9cf6df
parentefa1f811f74a585c82eb47afe941bb03bb235429 (diff)
downloadnss-hg-018326c1b708e3a3e0303d327946e30aa9544fd7.tar.gz
Bug 266941: Selfserv patch to print throughput.
r=nelson
-rw-r--r--security/nss/cmd/selfserv/selfserv.c229
1 files changed, 199 insertions, 30 deletions
diff --git a/security/nss/cmd/selfserv/selfserv.c b/security/nss/cmd/selfserv/selfserv.c
index 1ea1cd499..664554379 100644
--- a/security/nss/cmd/selfserv/selfserv.c
+++ b/security/nss/cmd/selfserv/selfserv.c
@@ -93,9 +93,23 @@ static int handle_connection( PRFileDesc *, PRFileDesc *, int );
static const char envVarName[] = { SSL_ENV_VAR_NAME };
static const char inheritableSockName[] = { "SELFSERV_LISTEN_SOCKET" };
-static PRBool logStats = PR_FALSE;
+#define DEFAULT_BULK_TEST 16384
+#define MAX_BULK_TEST 1048576 /* 1 MB */
+static PRBool testBulk;
+static PRUint32 testBulkSize = DEFAULT_BULK_TEST;
+static PRUint32 testBulkTotal;
+static char* testBulkBuf;
+static PRDescIdentity log_layer_id = PR_INVALID_IO_LAYER;
+static PRFileDesc *loggingFD;
+static PRIOMethods loggingMethods;
+
+static PRBool logStats;
+static PRBool loggingLayer;
static int logPeriod = 30;
-static PRUint32 loggerOps = 0;
+static PRUint32 loggerOps;
+static PRUint32 loggerBytes;
+static PRUint32 loggerBytesTCP;
+static PRUint32 bulkSentChunks;
const int ssl2CipherSuites[] = {
SSL_EN_RC4_128_WITH_MD5, /* A */
@@ -175,21 +189,21 @@ Usage(const char *progName)
{
fprintf(stderr,
-"Usage: %s -n rsa_nickname -p port [-3BDENRSTblmrsvx] [-w password] [-t threads]\n"
-#ifdef NSS_ENABLE_ECC
-" [-i pid_file] [-c ciphers] [-d dbdir] [-e ec_nickname] \n"
+"Usage: %s -n rsa_nickname -p port [-3BDENRSTbjlmrsuvx] [-w password]\n"
+" [-t threads] [-i pid_file] [-c ciphers] [-d dbdir] [-g numblocks]\n"
" [-f fortezza_nickname] [-L [seconds]] [-M maxProcs] [-P dbprefix]\n"
+#ifdef NSS_ENABLE_ECC
+" [-C SSLCacheEntries] [-e ec_nickname]\n"
#else
-" [-i pid_file] [-c ciphers] [-d dbdir] [-f fortezza_nickname] \n"
-" [-L [seconds]] [-M maxProcs] [-P dbprefix] [-C SSLCacheEntries]\n"
+" [-C SSLCacheEntries]\n"
#endif /* NSS_ENABLE_ECC */
"-S means disable SSL v2\n"
"-3 means disable SSL v3\n"
+"-T means disable TLS\n"
"-B bypasses the PKCS11 layer for SSL encryption and MACing\n"
"-q checks for bypassability\n"
"-D means disable Nagle delays in TCP\n"
"-E means disable export ciphersuites and SSL step down key gen\n"
-"-T means disable TLS\n"
"-R means disable detection of rollback from TLS to SSL3\n"
"-b means try binding to the port and exit\n"
"-m means test the model-socket feature of SSL_ImportFD.\n"
@@ -208,7 +222,11 @@ Usage(const char *progName)
"-t threads -- specify the number of threads to use for connections.\n"
"-i pid_file file to write the process id of selfserve\n"
"-l means use local threads instead of global threads\n"
-"-C SSLCacheEntries sets the maximum number of entries in the SSL session cache\n"
+"-g numblocks means test throughput by sending total numblocks chunks\n"
+" of size 16kb to the client, 0 means unlimited (default=0)\n"
+"-j means measure TCP throughput (for use with -g option)\n"
+"-C SSLCacheEntries sets the maximum number of entries in the SSL\n"
+" session cache\n"
"-c ciphers Letter(s) chosen from the following list\n"
"A SSL2 RC4 128 WITH MD5\n"
"B SSL2 RC4 128 EXPORT40 WITH MD5\n"
@@ -632,20 +650,63 @@ logger(void *arg)
PRIntervalTime latestTime;
PRUint32 previousOps;
PRUint32 ops;
- PRIntervalTime logPeriodTicks = PR_SecondsToInterval(logPeriod);
- PRFloat64 secondsPerTick = 1.0 / (PRFloat64)PR_TicksPerSecond();
+ PRIntervalTime logPeriodTicks = PR_TicksPerSecond();
+ PRFloat64 secondsPerTick = 1.0 / (PRFloat64)logPeriodTicks;
+ int iterations = 0;
+ int secondsElapsed = 0;
+ static PRUint64 totalPeriodBytes = 0;
+ static PRUint64 totalPeriodBytesTCP = 0;
previousOps = loggerOps;
previousTime = PR_IntervalNow();
for (;;) {
- PR_Sleep(logPeriodTicks);
+ /* OK, implementing a new sleep algorithm here... always sleep
+ * for 1 second but print out info at the user-specified interval.
+ * This way, we don't overflow all of our PR_Atomic* functions and
+ * we don't have to use locks.
+ */
+ PR_Sleep(logPeriodTicks);
+ secondsElapsed++;
+ totalPeriodBytes += PR_AtomicSet(&loggerBytes, 0);
+ totalPeriodBytesTCP += PR_AtomicSet(&loggerBytesTCP, 0);
+ if (secondsElapsed != logPeriod) {
+ continue;
+ }
+ /* when we reach the user-specified logging interval, print out all
+ * data
+ */
+ secondsElapsed = 0;
latestTime = PR_IntervalNow();
ops = loggerOps;
period = latestTime - previousTime;
seconds = (PRFloat64) period*secondsPerTick;
opsPerSec = (ops - previousOps) / seconds;
- printf("%.2f ops/second, %d threads\n", opsPerSec, threadCount);
+
+ if (testBulk) {
+ if (iterations == 0) {
+ if (loggingLayer == PR_TRUE) {
+ printf("Conn.--------App Data--------TCP Data\n");
+ } else {
+ printf("Conn.--------App Data\n");
+ }
+ }
+ if (loggingLayer == PR_TRUE) {
+ printf("%4.d %5.3f MB/s %5.3f MB/s\n", ops,
+ totalPeriodBytes / (seconds * 1048576.0),
+ totalPeriodBytesTCP / (seconds * 1048576.0));
+ } else {
+ printf("%4.d %5.3f MB/s\n", ops,
+ totalPeriodBytes / (seconds * 1048576.0));
+ }
+ totalPeriodBytes = 0;
+ totalPeriodBytesTCP = 0;
+ /* Print the "legend" every 20 iterations */
+ iterations = (iterations + 1) % 20;
+ } else {
+ printf("%.2f ops/second, %d threads\n", opsPerSec, threadCount);
+ }
+
fflush(stdout);
previousOps = ops;
previousTime = latestTime;
@@ -939,6 +1000,7 @@ handle_connection(
char buf[10240];
char fileName[513];
char proto[128];
+ PRDescIdentity aboveLayer = PR_INVALID_IO_LAYER;
pBuf = buf;
bufRem = sizeof buf;
@@ -965,6 +1027,23 @@ handle_connection(
ssl_sock = tcp_sock;
}
+ if (loggingLayer) {
+ /* find the layer where our new layer is to be pushed */
+ aboveLayer = PR_GetLayersIdentity(ssl_sock->lower);
+ if (aboveLayer == PR_INVALID_IO_LAYER) {
+ errExit("PRGetUniqueIdentity");
+ }
+ /* create the new layer - this is a very cheap operation */
+ loggingFD = PR_CreateIOLayerStub(log_layer_id, &loggingMethods);
+ if (!loggingFD)
+ errExit("PR_CreateIOLayerStub");
+ /* push the layer below ssl but above TCP */
+ rv = PR_PushIOLayer(ssl_sock, aboveLayer, loggingFD);
+ if (rv != PR_SUCCESS) {
+ errExit("PR_PushIOLayer");
+ }
+ }
+
if (noDelay) {
opt.option = PR_SockOpt_NoDelay;
opt.value.no_delay = PR_TRUE;
@@ -1182,19 +1261,37 @@ handle_connection(
iovs[numIOVs].iov_base = buf;
iovs[numIOVs].iov_len = reqLen;
numIOVs++;
-
-/* printSecurityInfo(ssl_sock); */
}
- iovs[numIOVs].iov_base = (char *)EOFmsg;
- iovs[numIOVs].iov_len = sizeof EOFmsg - 1;
- numIOVs++;
+ /* Don't add the EOF if we want to test bulk encryption */
+ if (!testBulk) {
+ iovs[numIOVs].iov_base = (char *)EOFmsg;
+ iovs[numIOVs].iov_len = sizeof EOFmsg - 1;
+ numIOVs++;
+ }
rv = PR_Writev(ssl_sock, iovs, numIOVs, PR_INTERVAL_NO_TIMEOUT);
if (rv < 0) {
errWarn("PR_Writev");
break;
}
+
+ /* Send testBulkTotal chunks to the client. Unlimited if 0. */
+ if (testBulk) {
+ while (0 < (rv = PR_Write(ssl_sock, testBulkBuf, testBulkSize))) {
+ PR_AtomicAdd(&loggerBytes, rv);
+ PR_AtomicIncrement(&bulkSentChunks);
+ if ((bulkSentChunks > testBulkTotal) && (testBulkTotal != 0))
+ break;
+ }
+
+ /* There was a write error, so close this connection. */
+ if (bulkSentChunks <= testBulkTotal) {
+ errWarn("PR_Write");
+ }
+ PR_AtomicDecrement(&loggerOps);
+ break;
+ }
} while (0);
cleanup:
@@ -1277,7 +1374,7 @@ do_accepts(
VLOG(("selfserv: do_accept: Got connection\n"));
if (logStats) {
- loggerOps++;
+ PR_AtomicIncrement(&loggerOps);
}
PZ_Lock(qLock);
@@ -1380,6 +1477,65 @@ getBoundListenSocket(unsigned short port)
return listen_sock;
}
+PRInt32 PR_CALLBACK
+logWritev (
+ PRFileDesc *fd,
+ const PRIOVec *iov,
+ PRInt32 size,
+ PRIntervalTime timeout )
+{
+ PRInt32 rv = (fd->lower->methods->writev)(fd->lower, iov, size,
+ timeout);
+ /* Add the amount written, but not if there's an error */
+ if (rv > 0)
+ PR_AtomicAdd(&loggerBytesTCP, rv);
+ return rv;
+}
+
+PRInt32 PR_CALLBACK
+logWrite (
+ PRFileDesc *fd,
+ const void *buf,
+ PRInt32 amount)
+{
+ PRInt32 rv = (fd->lower->methods->write)(fd->lower, buf, amount);
+ /* Add the amount written, but not if there's an error */
+ if (rv > 0)
+ PR_AtomicAdd(&loggerBytesTCP, rv);
+
+ return rv;
+}
+
+PRInt32 PR_CALLBACK
+logSend (
+ PRFileDesc *fd,
+ const void *buf,
+ PRInt32 amount,
+ PRIntn flags,
+ PRIntervalTime timeout)
+{
+ PRInt32 rv = (fd->lower->methods->send)(fd->lower, buf, amount,
+ flags, timeout);
+ /* Add the amount written, but not if there's an error */
+ if (rv > 0)
+ PR_AtomicAdd(&loggerBytesTCP, rv);
+ return rv;
+}
+
+void initLoggingLayer(void)
+{
+ /* get a new layer ID */
+ log_layer_id = PR_GetUniqueIdentity("Selfserv Logging");
+ if (log_layer_id == PR_INVALID_IO_LAYER)
+ errExit("PR_GetUniqueIdentity");
+
+ /* setup the default IO methods with my custom write methods */
+ memcpy(&loggingMethods, PR_GetDefaultIOMethods(), sizeof(PRIOMethods));
+ loggingMethods.writev = logWritev;
+ loggingMethods.write = logWrite;
+ loggingMethods.send = logSend;
+}
+
void
server_main(
PRFileDesc * listen_sock,
@@ -1409,18 +1565,11 @@ server_main(
}
/* do SSL configuration. */
- /* all suites except RSA_NULL_MD5 are enabled by default */
-
-#if 0
- /* This is supposed to be true by default.
- ** Setting it explicitly should not be necessary.
- ** Let's test and make sure that's true.
- */
- rv = SSL_OptionSet(model_sock, SSL_SECURITY, 1);
+ rv = SSL_OptionSet(model_sock, SSL_SECURITY,
+ !(disableSSL2 && disableSSL3 && disableTLS));
if (rv < 0) {
errExit("SSL_OptionSet SSL_SECURITY");
}
-#endif
rv = SSL_OptionSet(model_sock, SSL_ENABLE_SSL3, !disableSSL3);
if (rv != SECSuccess) {
@@ -1710,8 +1859,9 @@ main(int argc, char **argv)
PRBool debugCache = PR_FALSE; /* bug 90518 */
char emptyString[] = { "" };
char* certPrefix = emptyString;
- PRUint32 protos = 0;
+ PRUint32 protos = 0;
SSL3Statistics *ssl3stats;
+ int i;
tmp = strrchr(argv[0], '/');
tmp = tmp ? tmp + 1 : argv[0];
@@ -1724,7 +1874,7 @@ main(int argc, char **argv)
** numbers, then capital letters, then lower case, alphabetical.
*/
optstate = PL_CreateOptState(argc, argv,
- "2:3BC:DEL:M:NP:RSTbc:d:e:f:hi:lmn:op:qrst:uvw:xy");
+ "2:3BC:DEL:M:NP:RSTbc:d:e:f:g:hi:jlmn:op:qrst:uvw:xy");
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
++optionsFound;
switch(optstate->option) {
@@ -1775,10 +1925,20 @@ main(int argc, char **argv)
case 'f': fNickName = PORT_Strdup(optstate->value); break;
+ case 'g':
+ testBulk = PR_TRUE;
+ testBulkTotal = PORT_Atoi(optstate->value);
+ break;
+
case 'h': Usage(progName); exit(0); break;
case 'i': pidFile = optstate->value; break;
+ case 'j':
+ initLoggingLayer();
+ loggingLayer = PR_TRUE;
+ break;
+
case 'l': useLocalThreads = PR_TRUE; break;
case 'm': useModelSocket = PR_TRUE; break;
@@ -1877,6 +2037,15 @@ main(int argc, char **argv)
}
}
+ /* allocate and initialize app data for bulk encryption testing */
+ if (testBulk) {
+ testBulkBuf = PORT_Malloc(testBulkSize);
+ if (testBulkBuf == NULL)
+ errExit("Out of memory: testBulkBuf");
+ for (i = 0; i < testBulkSize; i++)
+ testBulkBuf[i] = i;
+ }
+
envString = getenv(envVarName);
tmp = getenv("TMP");
if (!tmp)