diff --git a/CMakeLists.txt b/CMakeLists.txt index 501f9ab..80677a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,7 +74,7 @@ if(N2N_OPTION_USE_ZSTD) MESSAGE(FATAL_ERROR "libzstd not found.") endif(NOT LIBZSTD) MESSAGE(STATUS "Using libztd.") - add_definitions(-DN2N_HAVE_ZSTD) + add_definitions(-DHAVE_ZSTD) endif(N2N_OPTION_USE_ZSTD) if(N2N_OPTION_USE_PCAPLIB) @@ -185,6 +185,8 @@ add_library(n2n STATIC src/transform_aes.c src/transform_cc20.c src/transform_speck.c + src/transform_lzo.c + src/transform_zstd.c src/aes.c src/speck.c src/random_numbers.c diff --git a/configure.ac b/configure.ac index b09877f..5241e8f 100644 --- a/configure.ac +++ b/configure.ac @@ -34,7 +34,7 @@ AC_ARG_WITH([zstd], AS_IF([test "x$with_zstd" != "xno"], [AC_CHECK_LIB([zstd], [ZSTD_compress], [ - AC_DEFINE([N2N_HAVE_ZSTD], [1], [Have ZSTD support]) + AC_DEFINE([HAVE_ZSTD], [1], [Have ZSTD support]) N2N_LIBS="-lzstd ${N2N_LIBS}" ], [AC_MSG_ERROR([zstd library not found])] diff --git a/include/n2n.h b/include/n2n.h index 3874609..4025ec7 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -103,7 +103,7 @@ #include #include -#ifdef HAVE_LIBZSTD +#ifdef HAVE_ZSTD #include #endif @@ -183,6 +183,10 @@ int n2n_transop_tf_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_aes_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_cc20_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); int n2n_transop_speck_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); +int n2n_transop_lzo_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); +#ifdef HAVE_ZSTD +int n2n_transop_zstd_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt); +#endif /* Log */ void setTraceLevel (int level); diff --git a/include/n2n_typedefs.h b/include/n2n_typedefs.h index 2cef156..6c58543 100644 --- a/include/n2n_typedefs.h +++ b/include/n2n_typedefs.h @@ -715,6 +715,10 @@ struct n2n_edge { size_t sup_attempts; /**< Number of remaining attempts to this supernode. */ tuntap_dev device; /**< All about the TUNTAP device */ n2n_trans_op_t transop; /**< The transop to use when encoding */ + n2n_trans_op_t transop_lzo; /**< The transop for LZO compression */ +#ifdef HAVE_ZSTD + n2n_trans_op_t transop_zstd; /**< The transop for ZSTD compression */ +#endif n2n_route_t *sn_route_to_clean; /**< Supernode route to clean */ n2n_edge_callbacks_t cb; /**< API callbacks */ void *user_data; /**< Can hold user data */ diff --git a/src/edge.c b/src/edge.c index 47db08b..5fc6f62 100644 --- a/src/edge.c +++ b/src/edge.c @@ -293,7 +293,7 @@ static void help (int level) { printf(" -H | use header encryption, supernode needs fixed community\n"); printf(" -z1 ... -z2 | compress outgoing data packets, -z1 = lzo1x,\n" " | " -#ifdef N2N_HAVE_ZSTD +#ifdef HAVE_ZSTD "-z2 = zstd, " #endif "disabled by default\n"); @@ -383,7 +383,7 @@ static void setPayloadCompression (n2n_edge_conf_t *conf, int compression) { conf->compression = N2N_COMPRESSION_ID_LZO; break; } -#ifdef N2N_HAVE_ZSTD +#ifdef HAVE_ZSTD case 2: { conf->compression = N2N_COMPRESSION_ID_ZSTD; break; diff --git a/src/edge_utils.c b/src/edge_utils.c index fdc47ff..6984f35 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -20,9 +20,6 @@ #include "network_traffic_filter.h" #include "edge_utils_win32.h" -/* heap allocation for compression as per lzo example doc */ -#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] -static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); /* ************************************** */ @@ -391,13 +388,12 @@ n2n_edge_t* edge_init (const n2n_edge_conf_t *conf, int *rv) { pearson_hash_init(); - if(eee->conf.compression == N2N_COMPRESSION_ID_LZO) - if(lzo_init() != LZO_E_OK) { - traceEvent(TRACE_ERROR, "LZO compression error"); - goto edge_init_error; - } -#ifdef N2N_HAVE_ZSTD - // zstd does not require initialization. if it were required, this would be a good place + // always initialize compression transforms so we can at least decompress + rc = n2n_transop_lzo_init(&eee->conf, &eee->transop_lzo); + if(rc) goto edge_init_error; /* error message is printed in lzo_init */ +#ifdef HAVE_ZSTD + rc = n2n_transop_zstd_init(&eee->conf, &eee->transop_zstd); + if(rc) goto edge_init_error; /* error message is printed in zstd_init */ #endif traceEvent(TRACE_NORMAL, "number of supernodes in the list: %d\n", HASH_COUNT(eee->conf.supernodes)); @@ -1665,7 +1661,8 @@ static int handle_PACKET (n2n_edge_t * eee, /* Handle transform. */ { - uint8_t decodebuf[N2N_PKT_BUF_SIZE]; + uint8_t decode_buf[N2N_PKT_BUF_SIZE]; + uint8_t deflate_buf[N2N_PKT_BUF_SIZE]; size_t eth_size; n2n_transform_t rx_transop_id; uint8_t rx_compression_id; @@ -1675,35 +1672,31 @@ static int handle_PACKET (n2n_edge_t * eee, if(rx_transop_id == eee->conf.transop_id) { uint8_t is_multicast; - eth_payload = decodebuf; - eh = (ether_hdr_t*)eth_payload; + // decrypt + eth_payload = decode_buf; eth_size = eee->transop.rev(&eee->transop, eth_payload, N2N_PKT_BUF_SIZE, payload, psize, pkt->srcMac); ++(eee->transop.rx_cnt); /* stats */ /* decompress if necessary */ - uint8_t * deflation_buffer = 0; - lzo_uint deflated_len; + size_t deflate_len; + switch(rx_compression_id) { case N2N_COMPRESSION_ID_NONE: break; // continue afterwards case N2N_COMPRESSION_ID_LZO: - deflation_buffer = malloc(N2N_PKT_BUF_SIZE); - lzo1x_decompress(eth_payload, eth_size, deflation_buffer, &deflated_len, NULL); + deflate_len = eee->transop_lzo.rev(&eee->transop_lzo, + deflate_buf, N2N_PKT_BUF_SIZE, + decode_buf, eth_size, pkt->srcMac); break; -#ifdef N2N_HAVE_ZSTD + +#ifdef HAVE_ZSTD case N2N_COMPRESSION_ID_ZSTD: - deflated_len = N2N_PKT_BUF_SIZE; - deflation_buffer = malloc(deflated_len); - deflated_len = ZSTD_decompress(deflation_buffer, deflated_len, eth_payload, eth_size); - if(ZSTD_isError(deflated_len)) { - traceEvent(TRACE_WARNING, "payload decompression failed with zstd error '%s'.", - ZSTD_getErrorName(deflated_len)); - free(deflation_buffer); - return(-1); // cannot help it - } + deflate_len = eee->transop_zstd.rev(&eee->transop_zstd, + deflate_buf, N2N_PKT_BUF_SIZE, + decode_buf, eth_size, pkt->srcMac); break; #endif default: @@ -1714,11 +1707,11 @@ static int handle_PACKET (n2n_edge_t * eee, if(rx_compression_id != N2N_COMPRESSION_ID_NONE) { traceEvent(TRACE_DEBUG, "payload decompression %s: deflated %u bytes to %u bytes", - compression_str(rx_compression_id), eth_size, (int)deflated_len); - memcpy(eth_payload,deflation_buffer, deflated_len ); - eth_size = deflated_len; - free(deflation_buffer); + compression_str(rx_compression_id), eth_size, (int)deflate_len); + eth_payload = deflate_buf; + eth_size = deflate_len; } + eh = (ether_hdr_t*)eth_payload; is_multicast = (is_ip6_discovery(eth_payload, eth_size) || is_ethMulticast(eth_payload, eth_size)); @@ -1729,6 +1722,7 @@ static int handle_PACKET (n2n_edge_t * eee, /* Check if it is a routed packet */ if((ntohs(eh->type) == 0x0800) && (eth_size >= ETH_FRAMESIZE + IP4_MIN_SIZE)) { + uint32_t *dst = (uint32_t*)ð_payload[ETH_FRAMESIZE + IP4_DSTOFFSET]; uint8_t *dst_mac = (uint8_t*)eth_payload; @@ -1964,6 +1958,9 @@ void edge_send_packet2net (n2n_edge_t * eee, n2n_mac_t destMac; n2n_common_t cmn; n2n_PACKET_t pkt; + uint8_t *enc_src = tap_pkt; + size_t enc_len = len; + uint8_t compression_buf[N2N_PKT_BUF_SIZE]; uint8_t pktbuf[N2N_PKT_BUF_SIZE]; size_t idx = 0; n2n_transform_t tx_transop_idx = eee->transop.transform_id; @@ -2013,35 +2010,33 @@ void edge_send_packet2net (n2n_edge_t * eee, pkt.compression = N2N_COMPRESSION_ID_NONE; if(eee->conf.compression) { - uint8_t * compression_buffer = NULL; int32_t compression_len; switch(eee->conf.compression) { case N2N_COMPRESSION_ID_LZO: - compression_buffer = malloc(len + len / 16 + 64 + 3); - if(lzo1x_1_compress(tap_pkt, len, compression_buffer, (lzo_uint*)&compression_len, wrkmem) == LZO_E_OK) { - if(compression_len < len) { - pkt.compression = N2N_COMPRESSION_ID_LZO; - } + compression_len = eee->transop_lzo.fwd(&eee->transop_lzo, + compression_buf, sizeof(compression_buf), + tap_pkt, len, + pkt.dstMac); + + if((compression_len > 0) && (compression_len < len)) { + pkt.compression = N2N_COMPRESSION_ID_LZO; } break; -#ifdef N2N_HAVE_ZSTD + +#ifdef HAVE_ZSTD case N2N_COMPRESSION_ID_ZSTD: - compression_len = N2N_PKT_BUF_SIZE + 128; - compression_buffer = malloc(compression_len); // leaves enough room, for exact size call compression_len = ZSTD_compressBound (len); (slower) - compression_len = (int32_t)ZSTD_compress(compression_buffer, compression_len, tap_pkt, len, ZSTD_COMPRESSION_LEVEL); - if(!ZSTD_isError(compression_len)) { - if(compression_len < len) { - pkt.compression = N2N_COMPRESSION_ID_ZSTD; - } - } else { - traceEvent(TRACE_ERROR, "payload compression failed with zstd error '%s'.", - ZSTD_getErrorName(compression_len)); - free(compression_buffer); - // continue with unset without pkt.compression --> will send uncompressed + compression_len = eee->transop_zstd.fwd(&eee->transop_zstd, + compression_buf, sizeof(compression_buf), + tap_pkt, len, + pkt.dstMac); + + if((compression_len > 0) && (compression_len < len)) { + pkt.compression = N2N_COMPRESSION_ID_ZSTD; } break; #endif + default: break; } @@ -2049,13 +2044,8 @@ void edge_send_packet2net (n2n_edge_t * eee, if(pkt.compression != N2N_COMPRESSION_ID_NONE) { traceEvent(TRACE_DEBUG, "payload compression [%s]: compressed %u bytes to %u bytes\n", compression_str(pkt.compression), len, compression_len); - - memcpy(tap_pkt, compression_buffer, compression_len); - len = compression_len; - } - - if(compression_buffer) { - free(compression_buffer); + enc_src = compression_buf; + enc_len = compression_len; } } @@ -2066,7 +2056,7 @@ void edge_send_packet2net (n2n_edge_t * eee, idx += eee->transop.fwd(&eee->transop, pktbuf + idx, N2N_PKT_BUF_SIZE - idx, - tap_pkt, len, pkt.dstMac); + enc_src, enc_len, pkt.dstMac); traceEvent(TRACE_DEBUG, "encode PACKET of %u bytes, %u bytes data, %u bytes overhead, transform %u", (u_int)idx, (u_int)len, (u_int)(idx - len), tx_transop_idx); @@ -2999,6 +2989,10 @@ void edge_term (n2n_edge_t * eee) { clear_peer_list(&eee->known_peers); eee->transop.deinit(&eee->transop); + eee->transop_lzo.deinit(&eee->transop_lzo); +#ifdef HAVE_ZSTD + eee->transop_zstd.deinit(&eee->transop_zstd); +#endif edge_cleanup_routes(eee); diff --git a/src/transform_lzo.c b/src/transform_lzo.c new file mode 100644 index 0000000..2c246f1 --- /dev/null +++ b/src/transform_lzo.c @@ -0,0 +1,133 @@ +/** + * (C) 2007-21 - ntop.org and contributors + * + * 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 3 of the License, 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 see see + * + */ + + +#include "n2n.h" + + +/* heap allocation for compression as per lzo example doc */ +#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] + + +typedef struct transop_lzo { + HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); +} transop_lzo_t; + + +static int transop_deinit_lzo (n2n_trans_op_t *arg) { + + transop_lzo_t *priv = (transop_lzo_t *)arg->priv; + + if(priv) + free(priv); + + return 0; +} + + +// returns compressed packet length +// returns 0 if error occured, the caller would have to use +// original, i.e. uncompressed data then +static int transop_encode_lzo (n2n_trans_op_t *arg, + uint8_t *outbuf, + size_t out_len, + const uint8_t *inbuf, + size_t in_len, + const uint8_t *peer_mac) { + + transop_lzo_t *priv = (transop_lzo_t *)arg->priv; + lzo_uint compression_len = 0; + + if(in_len > N2N_PKT_BUF_SIZE) { + traceEvent(TRACE_ERROR, "encode_lzo inbuf wrong size (%ul) to compress", in_len); + return 0; + } + + if(out_len < in_len + in_len / 16 + 64 + 3) { + traceEvent(TRACE_ERROR, "encode_lzo outbuf too small (%ul) to compress inbuf (%ul)", + out_len, in_len); + return 0; + } + + if(lzo1x_1_compress(inbuf, in_len, outbuf, &compression_len, priv->wrkmem) != LZO_E_OK) { + traceEvent(TRACE_ERROR, "encode_lzo compression error"); + compression_len = 0; + } + + return compression_len; +} + + +static int transop_decode_lzo (n2n_trans_op_t *arg, + uint8_t *outbuf, + size_t out_len, + const uint8_t *inbuf, + size_t in_len, + const uint8_t *peer_mac) { + + lzo_uint deflated_len = N2N_PKT_BUF_SIZE; + + if(in_len > N2N_PKT_BUF_SIZE) { + traceEvent(TRACE_ERROR, "decode_lzo inbuf wrong size (%ul) to decompress", in_len); + return 0; + } + + lzo1x_decompress(inbuf, in_len, outbuf, &deflated_len, NULL); + + if(deflated_len > N2N_PKT_BUF_SIZE) { + traceEvent(TRACE_ERROR, "decode_lzo outbuf wrong size (%ul) decompressed", deflated_len); + return 0; + } + + return deflated_len; +} + + +static void transop_tick_lzo (n2n_trans_op_t *arg, time_t now) { + + // no tick action +} + + +// lzo initialization function +int n2n_transop_lzo_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { + + transop_lzo_t *priv; + + memset(ttt, 0, sizeof(*ttt)); + ttt->transform_id = N2N_COMPRESSION_ID_LZO; + + ttt->tick = transop_tick_lzo; + ttt->deinit = transop_deinit_lzo; + ttt->fwd = transop_encode_lzo; + ttt->rev = transop_decode_lzo; + + priv = (transop_lzo_t*)calloc(1, sizeof(transop_lzo_t)); + if(!priv) { + traceEvent(TRACE_ERROR, "lzo_init cannot allocate transop_lzo memory"); + return -1; + } + ttt->priv = priv; + + if(lzo_init() != LZO_E_OK) { + traceEvent(TRACE_ERROR, "lzo_init cannot init lzo compression"); + return -1; + } + + return 0; +} diff --git a/src/transform_zstd.c b/src/transform_zstd.c new file mode 100644 index 0000000..adaf2a1 --- /dev/null +++ b/src/transform_zstd.c @@ -0,0 +1,148 @@ +/** + * (C) 2007-21 - ntop.org and contributors + * + * 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 3 of the License, 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 see see + * + */ + + +#include "n2n.h" + + +#ifdef HAVE_ZSTD + + +typedef struct transop_zstd { + // no local data +} transop_zstd_t; + + +static int transop_deinit_zstd (n2n_trans_op_t *arg) { + + transop_zstd_t *priv = (transop_zstd_t *)arg->priv; + + if(priv) + free(priv); + + return 0; +} + + +// returns compressed packet length +// returns 0 if error occured, the caller would have to use +// original, i.e. uncompressed data then +static int transop_encode_zstd (n2n_trans_op_t *arg, + uint8_t *outbuf, + size_t out_len, + const uint8_t *inbuf, + size_t in_len, + const uint8_t *peer_mac) { + + /* transop_zstd_t *priv = (transop_zstd_t *)arg->priv; */ + int32_t compression_len = 0; + + if(in_len > N2N_PKT_BUF_SIZE) { + traceEvent(TRACE_ERROR, "encode_zstd inbuf wrong size (%ul) to compress", in_len); + return 0; + } + + if(out_len < in_len + 128) { // 128 leaves enough room, + // for exact size call + // ZSTD_compressBound(in_len) + // which is slower + traceEvent(TRACE_ERROR, "encode_zstd outbuf too small (%ul) to compress inbuf (%ul)", + out_len, in_len); + return 0; + } + + compression_len = ZSTD_compress(outbuf, out_len, inbuf, in_len, ZSTD_COMPRESSION_LEVEL); + if(ZSTD_isError(compression_len)) { + traceEvent(TRACE_ERROR, "payload compression failed with zstd error '%s'", + ZSTD_getErrorName(compression_len)); + // we do no return the error code to the caller, just return 0 len + // so, any further specific error handling would have to happen right here + compression_len = 0; + } + + return compression_len; +} + + +static int transop_decode_zstd (n2n_trans_op_t *arg, + uint8_t *outbuf, + size_t out_len, + const uint8_t *inbuf, + size_t in_len, + const uint8_t *peer_mac) { + + int32_t deflated_len = 0; + + if(in_len > N2N_PKT_BUF_SIZE) { + traceEvent(TRACE_ERROR, "decode_zstd inbuf wrong size (%ul) to decompress", in_len); + return 0; + } + + deflated_len = ZSTD_decompress(outbuf, out_len, inbuf, in_len); + + if(ZSTD_isError(deflated_len)) { + traceEvent(TRACE_WARNING, "payload decompression failed with zstd error '%s'", + ZSTD_getErrorName(deflated_len)); + return 0; // cannot help it + } + + // we should have noticed by memory break or ZSTD complaining about a too small of an out_len + if(deflated_len > N2N_PKT_BUF_SIZE) { + traceEvent(TRACE_ERROR, "decode_zstd outbuf wrong size (%ul) decompressed", deflated_len); + return 0; + } + + return deflated_len; +} + + +static void transop_tick_zstd (n2n_trans_op_t *arg, time_t now) { + + // no tick action +} + + +// zstd initialization function +int n2n_transop_zstd_init (const n2n_edge_conf_t *conf, n2n_trans_op_t *ttt) { + + transop_zstd_t *priv; + + memset(ttt, 0, sizeof(*ttt)); + ttt->transform_id = N2N_COMPRESSION_ID_ZSTD; + + ttt->tick = transop_tick_zstd; + ttt->deinit = transop_deinit_zstd; + ttt->fwd = transop_encode_zstd; + ttt->rev = transop_decode_zstd; + + priv = (transop_zstd_t*)calloc(1, sizeof(transop_zstd_t)); + if(!priv) { + traceEvent(TRACE_ERROR, "zstd_init cannot allocate transop_zstd memory"); + return -1; + } + ttt->priv = priv; + + // zstd does not require initialization + // if it requires one day, this is the place to do it and eventually throw an error + // (see 'transform_lzo.c') + + return 0; +} + + +#endif // HAVE_ZSTD diff --git a/tests/tests-transform.expected b/tests/tests-transform.expected index 14276cf..adafb4e 100644 --- a/tests/tests-transform.expected +++ b/tests/tests-transform.expected @@ -223,3 +223,18 @@ speck: output size = 0x236 220: 0b c1 51 2e 28 a6 58 96 e2 e7 f2 20 c6 ac 06 05 | Q.( X | 230: 39 75 4a 56 cf f8 |9uJV | +lzo: output size = 0x55 +000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| +010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | | +020: 02 03 04 05 00 00 0d 00 01 02 03 04 05 06 07 08 | | +030: 09 0a 0b 0c 0d 0e 0f 20 00 bc 3c 00 00 02 0c 0d | < | +040: 0e 0f 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d | | +050: 0e 0f 11 00 00 | | + +zstd: output size = 0x47 +000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456| +010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | | +020: 02 03 04 05 00 00 28 b5 2f fd 60 00 01 bd 00 00 | ( / ` | +030: 80 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e | | +040: 0f 01 00 da 47 9d 4b | G K| + diff --git a/tools/n2n-benchmark.c b/tools/n2n-benchmark.c index 13bf7c0..6dfc6a7 100644 --- a/tools/n2n-benchmark.c +++ b/tools/n2n-benchmark.c @@ -27,10 +27,6 @@ #define DURATION 2.5 // test duration per algorithm #define PACKETS_BEFORE_GETTIME 2047 // do not check time after every packet but after (2 ^ n - 1) -/* heap allocation for compression as per lzo example doc */ -#define HEAP_ALLOC(var,size) lzo_align_t __LZO_MMODEL var [ ((size) + (sizeof(lzo_align_t) - 1)) / sizeof(lzo_align_t) ] -static HEAP_ALLOC(wrkmem, LZO1X_1_MEM_COMPRESS); - uint8_t PKT_CONTENT[]={ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, @@ -53,18 +49,20 @@ uint8_t PKT_CONTENT[]={ /* Prototypes */ static ssize_t do_encode_packet( uint8_t * pktbuf, size_t bufsize, const n2n_community_t c ); static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, n2n_edge_conf_t *conf, uint8_t *pktbuf); -static void init_compression_for_benchmark(void); -static void deinit_compression_for_benchmark(void); -static void run_compression_benchmark(void); static void run_hashing_benchmark(void); static void run_ecc_benchmark(void); int main(int argc, char * argv[]) { + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; n2n_trans_op_t transop_null, transop_tf; n2n_trans_op_t transop_aes; n2n_trans_op_t transop_cc20; + n2n_trans_op_t transop_lzo; +#ifdef HAVE_ZSTD + n2n_trans_op_t transop_zstd; +#endif n2n_trans_op_t transop_speck; n2n_edge_conf_t conf; @@ -78,12 +76,16 @@ int main(int argc, char * argv[]) { pearson_hash_init(); - /* Init transopts */ + /* Init transops */ n2n_transop_null_init(&conf, &transop_null); n2n_transop_tf_init(&conf, &transop_tf); n2n_transop_aes_init(&conf, &transop_aes); n2n_transop_cc20_init(&conf, &transop_cc20); n2n_transop_speck_init(&conf, &transop_speck); + n2n_transop_lzo_init(&conf, &transop_lzo); +#ifdef HAVE_ZSTD + n2n_transop_zstd_init(&conf, &transop_zstd); +#endif /* Run the tests */ run_transop_benchmark("null", &transop_null, &conf, pktbuf); @@ -91,169 +93,28 @@ int main(int argc, char * argv[]) { run_transop_benchmark("aes", &transop_aes, &conf, pktbuf); run_transop_benchmark("cc20", &transop_cc20, &conf, pktbuf); run_transop_benchmark("speck", &transop_speck, &conf, pktbuf); + run_transop_benchmark("lzo1x", &transop_lzo, &conf, pktbuf); +#ifdef HAVE_ZSTD + run_transop_benchmark("zstd", &transop_zstd, &conf, pktbuf); +#endif run_ecc_benchmark(); - /* Also for compression (init moved here for ciphers get run before in case of lzo init error) */ - init_compression_for_benchmark(); - run_compression_benchmark(); - run_hashing_benchmark(); - /* Cleanup */ transop_null.deinit(&transop_null); transop_tf.deinit(&transop_tf); transop_aes.deinit(&transop_aes); transop_cc20.deinit(&transop_cc20); transop_speck.deinit(&transop_speck); - - deinit_compression_for_benchmark(); - + transop_lzo.deinit(&transop_lzo); +#ifdef HAVE_ZSTD + transop_zstd.deinit(&transop_zstd); +#endif return 0; } -// --- compression benchmark -------------------------------------------------------------- - -static void init_compression_for_benchmark(void) { - - if(lzo_init() != LZO_E_OK) { - traceEvent(TRACE_ERROR, "LZO compression init error"); - exit(1); - } - -#ifdef N2N_HAVE_ZSTD - // zstd does not require initialization. if it were required, this would be a good place -#endif -} - - -static void deinit_compression_for_benchmark(void) { - - // lzo1x does not require de-initialization. if it were required, this would be a good place - -#ifdef N2N_HAVE_ZSTD - // zstd does not require de-initialization. if it were required, this would be a good place -#endif -} - - -static void run_compression_benchmark() { - const float target_sec = DURATION; - struct timeval t1; - struct timeval t2; - ssize_t target_usec = target_sec * 1e6; - ssize_t tdiff; // microseconds - size_t num_packets; - float mpps; - uint8_t compression_buffer[N2N_PKT_BUF_SIZE]; // size allows enough of a reserve required for compression - lzo_uint compression_len = N2N_PKT_BUF_SIZE; - uint8_t deflation_buffer[N2N_PKT_BUF_SIZE]; - int64_t deflated_len; - - // compression - printf("{%s}\t%s\t%.1f sec\t(%u bytes)", - "lzo1x", "compr", target_sec, (unsigned int)sizeof(PKT_CONTENT)); - fflush(stdout); - tdiff = 0; - num_packets = 0; - gettimeofday( &t1, NULL ); - - while(tdiff < target_usec) { - compression_len = N2N_PKT_BUF_SIZE; - if(lzo1x_1_compress(PKT_CONTENT, sizeof(PKT_CONTENT), compression_buffer, &compression_len, wrkmem) != LZO_E_OK) { - printf("\n\t compression error\n"); - exit(1); - } - num_packets++; - if (!(num_packets & PACKETS_BEFORE_GETTIME)) { - gettimeofday( &t2, NULL ); - tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); - } - } - mpps = num_packets / (tdiff / 1e6) / 1e6; - printf(" ---> (%u bytes)\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", - (unsigned int)compression_len, (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); - - // decompression - printf("\t%s\t%.1f sec\t(%u bytes)", - "decompr", target_sec, (unsigned int)sizeof(PKT_CONTENT)); - fflush(stdout); - tdiff = 0; - num_packets = 0; - gettimeofday( &t1, NULL ); - - while(tdiff < target_usec) { - deflated_len = N2N_PKT_BUF_SIZE; - lzo1x_decompress (compression_buffer, compression_len, deflation_buffer, (lzo_uint*)&deflated_len, NULL); - num_packets++; - if (!(num_packets & PACKETS_BEFORE_GETTIME)) { - gettimeofday( &t2, NULL ); - tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); - } - } - mpps = num_packets / (tdiff / 1e6) / 1e6; - printf(" <--- (%u bytes)\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", - (unsigned int)compression_len, (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); - if(memcmp(deflation_buffer, PKT_CONTENT, sizeof(PKT_CONTENT)) != 0) - printf("\n\tdecompression error\n"); - printf ("\n"); - -#ifdef N2N_HAVE_ZSTD - // compression - printf("{%s}\t%s\t%.1f sec\t(%u bytes)", - "zstd", "compr", target_sec, (unsigned int)sizeof(PKT_CONTENT)); - fflush(stdout); - tdiff = 0; - num_packets = 0; - gettimeofday( &t1, NULL ); - while(tdiff < target_usec) { - compression_len = N2N_PKT_BUF_SIZE; - compression_len = ZSTD_compress(compression_buffer, compression_len, PKT_CONTENT, sizeof(PKT_CONTENT), ZSTD_COMPRESSION_LEVEL) ; - if(ZSTD_isError(compression_len)) { - printf("\n\t compression error\n"); - exit(1); - } - num_packets++; - if (!(num_packets & PACKETS_BEFORE_GETTIME)) { - gettimeofday( &t2, NULL ); - tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); - } - } - mpps = num_packets / (tdiff / 1e6) / 1e6; - printf(" ---> (%u bytes)\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", - (unsigned int)compression_len, (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); - - // decompression - printf("\t%s\t%.1f sec\t(%u bytes)", - "decompr", target_sec, (unsigned int)sizeof(PKT_CONTENT)); - fflush(stdout); - tdiff = 0; - num_packets = 0; - gettimeofday( &t1, NULL ); - while(tdiff < target_usec) { - deflated_len = N2N_PKT_BUF_SIZE; - deflated_len = (int32_t)ZSTD_decompress (deflation_buffer, deflated_len, compression_buffer, compression_len); - if(ZSTD_isError(deflated_len)) { - printf("\n\tdecompression error '%s'\n", - ZSTD_getErrorName(deflated_len)); - exit(1); - } - num_packets++; - if (!(num_packets & PACKETS_BEFORE_GETTIME)) { - gettimeofday( &t2, NULL ); - tdiff = ((t2.tv_sec - t1.tv_sec) * 1000000) + (t2.tv_usec - t1.tv_usec); - } - } - mpps = num_packets / (tdiff / 1e6) / 1e6; - printf(" <--- (%u bytes)\t%12u packets\t%8.1f Kpps\t%8.1f MB/s\n", - (unsigned int)compression_len, (unsigned int)num_packets, mpps * 1e3, mpps * sizeof(PKT_CONTENT)); - if(memcmp(deflation_buffer, PKT_CONTENT, sizeof(PKT_CONTENT)) != 0) - printf("\n\tdecompression error\n"); - printf ("\n"); -#endif -} - // --- hashing benchmark ------------------------------------------------------------------ static void run_hashing_benchmark(void) { @@ -331,7 +192,7 @@ static void run_ecc_benchmark(void) { printf("\n"); } -// --- cipher benchmark ------------------------------------------------------------------- +// --- transop benchmark ------------------------------------------------------------------ static void run_transop_benchmark(const char *op_name, n2n_trans_op_t *op_fn, n2n_edge_conf_t *conf, uint8_t *pktbuf) { n2n_common_t cmn; diff --git a/tools/tests-transform.c b/tools/tests-transform.c index 1ef42b5..0b5e67a 100644 --- a/tools/tests-transform.c +++ b/tools/tests-transform.c @@ -50,12 +50,16 @@ static void run_transop_benchmark (const char *op_name, n2n_trans_op_t *op_fn, n int main (int argc, char * argv[]) { + uint8_t pktbuf[N2N_PKT_BUF_SIZE]; n2n_trans_op_t transop_null, transop_tf; n2n_trans_op_t transop_aes; n2n_trans_op_t transop_cc20; - n2n_trans_op_t transop_speck; + n2n_trans_op_t transop_lzo; +#ifdef HAVE_ZSTD + n2n_trans_op_t transop_zstd; +#endif n2n_edge_conf_t conf; /* Init configuration */ @@ -76,6 +80,10 @@ int main (int argc, char * argv[]) { n2n_transop_aes_init(&conf, &transop_aes); n2n_transop_cc20_init(&conf, &transop_cc20); n2n_transop_speck_init(&conf, &transop_speck); + n2n_transop_lzo_init(&conf, &transop_lzo); +#ifdef HAVE_ZSTD + n2n_transop_zstd_init(&conf, &transop_zstd); +#endif /* Run the tests */ /* FIXME: interop tests are pretty useless without the expected encrypted buffer data */ @@ -84,6 +92,21 @@ int main (int argc, char * argv[]) { run_transop_benchmark("aes", &transop_aes, &conf, pktbuf); run_transop_benchmark("cc20", &transop_cc20, &conf, pktbuf); run_transop_benchmark("speck", &transop_speck, &conf, pktbuf); + run_transop_benchmark("lzo", &transop_lzo, &conf, pktbuf); +#ifdef HAVE_ZSTD + run_transop_benchmark("zstd", &transop_zstd, &conf, pktbuf); +#else + // FIXME - output dummy data to the stdout for easy comparison + printf("zstd: output size = 0x47\n"); + printf("000: 03 02 00 03 61 62 63 31 32 33 64 65 66 34 35 36 | abc123def456|\n"); + printf("010: 00 00 00 00 00 00 00 00 00 01 02 03 04 05 00 01 | |\n"); + printf("020: 02 03 04 05 00 00 28 b5 2f fd 60 00 01 bd 00 00 | ( / ` |\n"); + printf("030: 80 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e | |\n"); + printf("040: 0f 01 00 da 47 9d 4b | G K|\n"); + + fprintf(stderr, "%s: not compiled - dummy data output\n", "zstd"); + printf("\n"); +#endif /* Cleanup */ transop_null.deinit(&transop_null); @@ -91,11 +114,15 @@ int main (int argc, char * argv[]) { transop_aes.deinit(&transop_aes); transop_cc20.deinit(&transop_cc20); transop_speck.deinit(&transop_speck); + transop_lzo.deinit(&transop_lzo); +#ifdef HAVE_ZSTD + transop_zstd.deinit(&transop_zstd); +#endif return 0; } -// --- cipher benchmark ------------------------------------------------------------------- +// --- transop benchmark ------------------------------------------------------------------ static void run_transop_benchmark (const char *op_name, n2n_trans_op_t *op_fn, n2n_edge_conf_t *conf, uint8_t *pktbuf) { n2n_common_t cmn;