From 6a65f16083f26a3f47a5b67b7b07d4d5dfda6e9f Mon Sep 17 00:00:00 2001 From: John Safranek Date: Mon, 22 Apr 2024 15:30:48 -0700 Subject: [PATCH] Static Memory 1. Modify the echoserver to use a static memory pool when using the flag WOLFSSH_STATIC_MEMORY. Uses NULL otherwise. The WOLFSSH_CTX is created with the pool and subsequent allocations for the WOLFSSH server use the same pool. 2. Add a configuration for the memory pool. Only works with SFTP enabled. 3. Add the memory pool use statistics to the echoserver. --- examples/echoserver/echoserver.c | 99 +++++++++++++++++++++++++++++++- src/internal.c | 33 +++++++++++ 2 files changed, 131 insertions(+), 1 deletion(-) diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 721eeda4..4548bc94 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -609,6 +609,76 @@ static int termios_show(int fd) #endif /* SHELL_DEBUG */ +#ifdef WOLFSSH_STATIC_MEMORY + #ifndef WOLFSSL_STATIC_MEMORY + #error Requires the static memory functions from wolfSSL + #endif + #if defined(WOLFSSH_SCP) || defined(WOLFSSH_SHELL) || defined(WOLFSSH_FWD) + #warning Static memory configuration for SFTP, results may vary. + #endif + typedef WOLFSSL_HEAP_HINT ES_HEAP_HINT; + + /* This static buffer is tuned for building with SFTP only. The static + * buffer size is calulated by multiplying the pairs of sizeList items + * and distList items and summing (32*64 + 128*118 + ...) and adding + * the sum of the distList values times the sizeof wc_Memory (rounded up + * to a word, 24). This total was 288kb plus change, rounded up to 289. */ + const word32 static_sizeList[] = + {32,128,384,800,3120,8400,17552,32846,131072}; + const word32 static_distList[] = {64,118,3,4,6,2,2,2,1}; + byte static_buffer[289*1024]; + + static void wolfSSH_MemoryPrintStats(ES_HEAP_HINT* hint) + { + if (hint != NULL) { + word16 i; + WOLFSSL_MEM_STATS stats; + + wolfSSL_GetMemStats(hint->memory, &stats); + + /* print to stderr so is on the same pipe as WOLFSSL_DEBUG */ + fprintf(stderr, "Total mallocs = %d\n", stats.totalAlloc); + fprintf(stderr, "Total frees = %d\n", stats.totalFr); + fprintf(stderr, "Current mallocs = %d\n", stats.curAlloc); + fprintf(stderr, "Available IO = %d\n", stats.avaIO); + fprintf(stderr, "Max con. handshakes = %d\n", stats.maxHa); + fprintf(stderr, "Max con. IO = %d\n", stats.maxIO); + fprintf(stderr, "State of memory blocks: size : available\n"); + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + fprintf(stderr, " %8d : %d\n", + stats.blockSz[i], stats.avaBlock[i]); + } + } + } + + static void wolfSSH_MemoryConnPrintStats(ES_HEAP_HINT* hint) + { + if (hint != NULL) { + WOLFSSL_MEM_CONN_STATS* stats = hint->stats; + + /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */ + if (hint->memory->flag & WOLFMEM_TRACK_STATS + && hint->stats != NULL) { + fprintf(stderr, "peak connection memory = %d\n", + stats->peakMem); + fprintf(stderr, "current memory in use = %d\n", + stats->curMem); + fprintf(stderr, "peak connection allocs = %d\n", + stats->peakAlloc); + fprintf(stderr, "current connection allocs = %d\n", + stats->curAlloc); + fprintf(stderr, "total connection allocs = %d\n", + stats->totalAlloc); + fprintf(stderr, "total connection frees = %d\n\n", + stats->totalFr); + } + } + } +#else + typedef void ES_HEAP_HINT; +#endif + + int ChildRunning = 0; #ifdef WOLFSSH_SHELL @@ -1419,6 +1489,11 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs) threadCtx->fwdCbCtx.originName = NULL; } #endif + +#ifdef WOLFSSH_STATIC_MEMORY + wolfSSH_MemoryConnPrintStats(threadCtx->ssh->ctx->heap); +#endif + wolfSSH_free(threadCtx->ssh); if (ret != 0) { @@ -2192,6 +2267,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) word32 defaultHighwater = EXAMPLE_HIGHWATER_MARK; word32 threadCount = 0; const char* keyList = NULL; + ES_HEAP_HINT* heap = NULL; int multipleConnections = 1; int userEcc = 0; int peerEcc = 0; @@ -2329,7 +2405,21 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) ES_ERROR("Couldn't initialize wolfSSH.\n"); } - ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL); + #ifdef WOLFSSH_STATIC_MEMORY + { + int ret; + + ret = wc_LoadStaticMemory_ex(&heap, + 9, static_sizeList, static_distList, + static_buffer, sizeof(static_buffer), + WOLFMEM_GENERAL|WOLFMEM_TRACK_STATS, 0); + if (ret != 0) { + ES_ERROR("Couldn't set up static memory pool.\n"); + } + } + #endif /* WOLFSSH_STATIC_MEMORY */ + + ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, heap); if (ctx == NULL) { ES_ERROR("Couldn't allocate SSH CTX data.\n"); } @@ -2573,6 +2663,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) WFREE(threadCtx, NULL, 0); ES_ERROR("Couldn't allocate SSH data.\n"); } + #ifdef WOLFSSH_STATIC_MEMORY + wolfSSH_MemoryConnPrintStats(heap); + #endif wolfSSH_SetUserAuthCtx(ssh, &pwMapList); /* Use the session object for its own highwater callback ctx */ if (defaultHighwater > 0) { @@ -2649,6 +2742,10 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args) wc_FreeMutex(&doneLock); PwMapListDelete(&pwMapList); wolfSSH_CTX_free(ctx); +#ifdef WOLFSSH_STATIC_MEMORY + wolfSSH_MemoryPrintStats(heap); +#endif + if (wolfSSH_Cleanup() != WS_SUCCESS) { ES_ERROR("Couldn't clean up wolfSSH.\n"); } diff --git a/src/internal.c b/src/internal.c index 4df48780..85238158 100644 --- a/src/internal.c +++ b/src/internal.c @@ -948,6 +948,30 @@ WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx) return ssh; heap = ctx->heap; +#ifdef WOLFSSH_STATIC_MEMORY + if (heap != NULL) { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + + if (hint->memory->flag & WOLFMEM_TRACK_STATS) { + WOLFSSL_MEM_CONN_STATS* stats = NULL; + + stats = (WOLFSSL_MEM_CONN_STATS*)WMALLOC( + sizeof(WOLFSSL_MEM_CONN_STATS), + heap, DYNTYPE_SSH); + if (stats == NULL) { + WLOG(WS_LOG_DEBUG, "SshInit: Cannot track memory stats.\n"); + return NULL; + } + + XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_CONN_STATS)); + if (hint->stats != NULL) { + WFREE(hint->stats, heap, DYNTYPE_SSH); + } + hint->stats = stats; + } + } +#endif /* WOLFSSH_STATIC_MEMORY */ + handshake = HandshakeInfoNew(heap); rng = (WC_RNG*)WMALLOC(sizeof(WC_RNG), heap, DYNTYPE_RNG); @@ -1125,6 +1149,15 @@ void SshResourceFree(WOLFSSH* ssh, void* heap) ssh->modesSz = 0; } #endif +#ifdef WOLFSSH_STATIC_MEMORY + if (heap) { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + if (hint->memory->flag & WOLFMEM_TRACK_STATS + && hint->stats != NULL) { + WFREE(hint->stats, heap, DYNTYPE_SSH); + } + } +#endif }