From 05b8e1274dda430640ac12be4238730528867801 Mon Sep 17 00:00:00 2001 From: toddouska Date: Wed, 15 Apr 2015 13:17:33 -0700 Subject: [PATCH] add WOLFSSL_SESSION_STATS and optionally WOLFSSL_PEAK_SESSIONS which will slow down servers under load --- src/ssl.c | 148 ++++++++++++++++++++++++++++++++++++++++++++------ wolfssl/ssl.h | 8 ++- 2 files changed, 137 insertions(+), 19 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index 04a130a57..d6cdaff33 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2003,6 +2003,10 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify) static SessionRow SessionCache[SESSION_ROWS]; + #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) + static word32 PeakSessions; + #endif + static wolfSSL_Mutex session_mutex; /* SessionCache mutex */ #ifndef NO_CLIENT_CACHE @@ -5833,6 +5837,11 @@ int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) } +#ifdef WOLFSSL_SESSION_STATS +static int get_locked_session_stats(word32* active, word32* total, + word32* peak); +#endif + int AddSession(WOLFSSL* ssl) { word32 row, idx; @@ -5916,6 +5925,20 @@ int AddSession(WOLFSSL* ssl) SessionCache[row].Sessions[idx].idLen = 0; #endif /* NO_CLIENT_CACHE */ +#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) + if (error == 0) { + word32 active = 0; + + error = get_locked_session_stats(&active, NULL, NULL); + if (error == SSL_SUCCESS) { + error = 0; /* back to this function ok */ + + if (active > PeakSessions) + PeakSessions = active; + } + } +#endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */ + if (UnLockMutex(&session_mutex) != 0) return BAD_MUTEX_E; @@ -5979,33 +6002,124 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) #endif /* SESSION_INDEX && SESSION_CERTS */ +#ifdef WOLFSSL_SESSION_STATS + +/* requires session_mutex lock held, SSL_SUCCESS on ok */ +static int get_locked_session_stats(word32* active, word32* total, word32* peak){ + int result = SSL_SUCCESS; + int i; + int count; + int idx; + word32 now = 0; + word32 seen = 0; + word32 ticks = LowResTimer(); + + (void)peak; + + WOLFSSL_ENTER("get_locked_session_stats"); + + for (i = 0; i < SESSION_ROWS; i++) { + seen += SessionCache[i].totalCount; + + if (active == NULL) + continue; /* no need to calculate what we can't set */ + + count = min((word32)SessionCache[i].totalCount, SESSIONS_PER_ROW); + idx = SessionCache[i].nextIdx - 1; + if (idx < 0) + idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */ + + for(; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) { + if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */ + WOLFSSL_MSG("Bad idx"); + break; + } + + /* if not expried then good */ + if (ticks < (SessionCache[i].Sessions[idx].bornOn + + SessionCache[i].Sessions[idx].timeout) ) { + now++; + } + } + } + + if (active) + *active = now; + + if (total) + *total = seen; + +#ifdef WOLFSSL_PEAK_SESSIONS + if (peak) + *peak = PeakSessions; +#endif + + WOLFSSL_LEAVE("get_locked_session_stats", result); + + return result; +} + + +/* return SSL_SUCCESS on ok */ +int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, + word32* maxSessions) +{ + int result = SSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_get_session_stats"); + + if (maxSessions) { + *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS; + + if (active == NULL && total == NULL && peak == NULL) + return result; /* we're done */ + } + + /* user must provide at least one query value */ + if (active == NULL && total == NULL && peak == NULL) + return BAD_FUNC_ARG; + + if (LockMutex(&session_mutex) != 0) { + return BAD_MUTEX_E; + } + + result = get_locked_session_stats(active, total, peak); + + if (UnLockMutex(&session_mutex) != 0) + result = BAD_MUTEX_E; + + WOLFSSL_LEAVE("wolfSSL_get_session_stats", result); + + return result; +} + +#endif /* WOLFSSL_SESSION_STATS */ + + #ifdef PRINT_SESSION_STATS - WOLFSSL_API - void wolfSSL_PrintSessionStats(void) + /* SSL_SUCCESS on ok */ + int wolfSSL_PrintSessionStats(void) { word32 totalSessionsSeen = 0; word32 totalSessionsNow = 0; - word32 rowNow; + word32 peak = 0; + word32 maxSessions = 0; int i; + int ret; double E; /* expected freq */ double chiSquare = 0; - for (i = 0; i < SESSION_ROWS; i++) { - totalSessionsSeen += SessionCache[i].totalCount; - - if (SessionCache[i].totalCount >= SESSIONS_PER_ROW) - rowNow = SESSIONS_PER_ROW; - else if (SessionCache[i].nextIdx == 0) - rowNow = 0; - else - rowNow = SessionCache[i].nextIdx; - - totalSessionsNow += rowNow; - } - + ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen, + &peak, &maxSessions); + if (ret != SSL_SUCCESS) + return ret; printf("Total Sessions Seen = %d\n", totalSessionsSeen); printf("Total Sessions Now = %d\n", totalSessionsNow); +#ifdef WOLFSSL_PEAK_SESSIONS + printf("Peak Sessions = %d\n", peak); +#endif + printf("Max Sessions = %d\n", maxSessions); E = (double)totalSessionsSeen / SESSION_ROWS; @@ -6029,6 +6143,8 @@ WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) else if (SESSION_ROWS == 2861) printf(".05 p value = 2985.5, chi-square should be less\n"); printf("\n"); + + return ret; } #endif /* SESSION_STATS */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index dafa4b16b..2f72c4c65 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1375,9 +1375,11 @@ WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*, #define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */ #define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */ -WOLFSSL_API -void wolfSSL_PrintSessionStats(void); - +WOLFSSL_API int wolfSSL_PrintSessionStats(void); +WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active, + unsigned int* total, + unsigned int* peak, + unsigned int* maxSessions); /* External facing KDF */ WOLFSSL_API int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, unsigned int msLen,