From 7c87cfa7c9efe4ff70c023278129b9de09014be9 Mon Sep 17 00:00:00 2001 From: Kirill Isakov Date: Tue, 20 Jul 2021 13:29:31 +0600 Subject: [PATCH] LZ4: try system library first, fallback to builtin --- doc/tinc.texi | 17 +++++--- m4/lz4.m4 | 109 +++++++++++++++++------------------------------ src/net_packet.c | 86 ++++++++++++++++++------------------- 3 files changed, 94 insertions(+), 118 deletions(-) diff --git a/doc/tinc.texi b/doc/tinc.texi index 9921cda0..e3eff868 100644 --- a/doc/tinc.texi +++ b/doc/tinc.texi @@ -468,13 +468,18 @@ default). @cindex LZ4 Another form of compression is offered using the LZ4 library. -The LZ4 codec is bundled with Tinc and built-in by default as -compression level 12. Tinc can be linked to an external liblz4 -library by using the "--disable-lz4-builtin" configure switch. +Tinc has support for the LZ4 compression algorithm as compression level 12. -If LZ4 support is entirely disabled by passing "--disable-lz4" to the -configure script, then the resulting binary will not work correctly -on VPNs where LZ4 compression is used. +By default, tinc will try to link to an external LZ4 library. If it is not +found on your system or its version is older than r129, then tinc falls back to +the built-in copy of the library. + +You can force the use of the built-in copy by passing `--enable-lz4-builtin`, +or disable it completely with `--disable-lz4-builtin`. + +LZ4 support can be completely disabled with `--disable-lz4`. Note that the +resulting binary will not work correctly on VPNs where LZ4 compression is used +by other peers. @c ================================================================== diff --git a/m4/lz4.m4 b/m4/lz4.m4 index f1128857..9d79d2ec 100644 --- a/m4/lz4.m4 +++ b/m4/lz4.m4 @@ -19,87 +19,58 @@ dnl 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. AC_DEFUN([tinc_LZ4], [ AC_ARG_ENABLE([lz4], - AS_HELP_STRING([--disable-lz4], [disable all lz4 compression support]) - ) + AS_HELP_STRING([--disable-lz4], [disable lz4 compression support])) AC_ARG_ENABLE([lz4-builtin], - AS_HELP_STRING([--disable-lz4-builtin], [required to link an lz4 library]) - ) + AS_HELP_STRING([--disable-lz4-builtin], [do not use lz4 builtin])) - AC_ARG_WITH(lz4, - AS_HELP_STRING([--with-lz4=DIR], [lz4 shared library prefix (eg: /usr/local)]), - [lz4="$withval" CPPFLAGS="$CPPFLAGS -I$withval/include" LDFLAGS="$LDFLAGS -L$withval/lib"] - ) + AS_IF([test "x$enable_lz4" != "xno"], [ + AC_DEFINE(HAVE_LZ4, 1, [enable lz4 compression support]) - AC_ARG_WITH(lz4-include, - AS_HELP_STRING([--with-lz4-include=DIR], [lz4 shared header directory]), - [lz4_include="$withval" CPPFLAGS="$CPPFLAGS -I$withval"] - ) - - AC_ARG_WITH(lz4-lib, - AS_HELP_STRING([--with-lz4-lib=DIR], [lz4 shared object directory]), - [lz4_lib="$withval" LDFLAGS="$LDFLAGS -L$withval"] - ) - - dnl Calling this early prevents autoconf lint. - AM_CONDITIONAL([CONFIGURE_LZ4_BUILTIN], [test "$enable_lz4_builtin" != 'no']) - - AS_IF([test "$enable_lz4" != 'no' -a "$enable_lz4_builtin" != 'no' ], [ - AC_DEFINE(HAVE_LZ4, 1, [Enable lz4 support.]) - AC_DEFINE(HAVE_LZ4_BUILTIN, 1, [Enable lz4 builtin.]) - AC_DEFINE(HAVE_LZ4_STATE, 1, [Enable lz4 external state features.]) - AC_DEFINE( - [LZ4_compress_shim(a, b, c, d)], - [LZ4_compress_fast_extState(lz4_wrkmem, a, b, c, d, 0)], - [This is the best interface for the lz4 builtin.] + AC_ARG_WITH(lz4, + AS_HELP_STRING([--with-lz4=DIR], [lz4 shared library prefix (eg: /usr/local)]), + [lz4="$withval" + CPPFLAGS="$CPPFLAGS-I$withval/include" + LDFLAGS="$LDFLAGS -L$withval/lib"] ) - ],[ - AS_IF([test "$enable_lz4" != 'no'], [ - AC_CHECK_HEADERS(lz4.h, [ - AC_DEFINE(LZ4_H, [], [Location of lz4.h]) - AC_CHECK_LIB(lz4, LZ4_compress_fast_extState, [ - LIBS="$LIBS -llz4" - AC_DEFINE(HAVE_LZ4, 1, [Enable lz4 compression support.]) - AC_DEFINE(HAVE_LZ4_STATE, 1, [Enable lz4 external state features.]) - AC_DEFINE( - [LZ4_compress_shim(a, b, c, d)], - [LZ4_compress_fast_extState(lz4_wrkmem, a, b, c, d, 0)], - [The lz4-r129 library interface.] - ) - break - ]) - - AC_CHECK_LIB(lz4, LZ4_compress_default, [ - LIBS="$LIBS -llz4" - AC_DEFINE(HAVE_LZ4, 1, [Enable lz4 compression support.]) - AC_DEFINE( - [LZ4_compress_shim(a, b, c, d)], - [LZ4_compress_default(a, b, c, d)], - [The lz4-r128 library interface.] - ) - break - ]) + AC_ARG_WITH(lz4-include, + AS_HELP_STRING([--with-lz4-include=DIR], [lz4 shared header directory]), + [lz4_include="$withval" + CPPFLAGS="$CPPFLAGS -I$withval"] + ) - AC_CHECK_LIB(lz4, LZ4_compress_limitedOutput, [ - LIBS="$LIBS -llz4" - AC_DEFINE(HAVE_LZ4, 1, [Enable lz4 compression support.]) - AC_DEFINE( - [LZ4_compress_shim(a, b, c, d)], - [LZ4_compress_limitedOutput(a, b, c, d)], - [The lz4-r59 library interface.] - ) - AC_MSG_WARN("Using deprecated lz4-r59 interface.") - break - ]) + AC_ARG_WITH(lz4-lib, + AS_HELP_STRING([--with-lz4-lib=DIR], [lz4 shared object directory]), + [lz4_lib="$withval" + LDFLAGS="$LDFLAGS -L$withval"] + ) - ],[ - AC_MSG_ERROR("lz4.h header file not found.") - break + dnl First we check the system copy of the library + AS_IF([test "x$enable_lz4_builtin" != 'xyes'], [ + AC_CHECK_HEADERS(lz4.h, [ + AC_CHECK_LIB(lz4, LZ4_compress_fast_extState, + [lz4_header='' + LIBS="$LIBS -llz4"]) ]) + ]) + + dnl If it was not found or is too old, fallback to the built-in copy + AS_IF([test "x$enable_lz4_builtin" != 'xno' -a "x$lz4_header" = 'x'], [ + lz4_header='"lib/lz4/lz4.h"' + lz4_builtin=1 + AC_DEFINE(HAVE_LZ4_BUILTIN, 1, [Enable lz4 builtin.]) + ]) + dnl If the first one failed and the second one is disabled, there's nothing more we can do + AS_IF([test "x$lz4_header" = 'x'], [ + AC_MSG_ERROR("lz4 library was not found and fallback to builtin is disabled."); ]) ]) + AC_DEFINE_UNQUOTED(LZ4_H, [$lz4_header], [Location of lz4.h]) + + AM_CONDITIONAL([CONFIGURE_LZ4_BUILTIN], [test "x$lz4_builtin" = 'x1']) + ]) diff --git a/src/net_packet.c b/src/net_packet.c index b8997e51..417c74ec 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -25,6 +25,8 @@ #ifdef HAVE_ZLIB #define ZLIB_CONST #include +#include + #endif #ifdef HAVE_LZO @@ -35,10 +37,6 @@ #include LZ4_H #endif -#ifdef HAVE_LZ4_BUILTIN -#include "lib/lz4/lz4.h" -#endif - #include "address_cache.h" #include "cipher.h" #include "conf.h" @@ -75,9 +73,7 @@ static char lzo_wrkmem[LZO1X_999_MEM_COMPRESS > LZO1X_1_MEM_COMPRESS ? LZO1X_999 #ifdef HAVE_LZ4_BUILTIN static LZ4_stream_t lz4_stream; #else -#ifdef HAVE_LZ4_STATE static void *lz4_state = NULL; -#endif /* HAVE_LZ4_STATE */ #endif /* HAVE_LZ4_BUILTIN */ static void send_udppacket(node_t *, vpn_packet_t *); @@ -222,57 +218,61 @@ static void udp_probe_h(node_t *n, vpn_packet_t *packet, length_t len) { } } -static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { - switch(level) { #ifdef HAVE_LZ4 - - case 12: +static length_t compress_packet_lz4(uint8_t *dest, const uint8_t *source, length_t len) { #ifdef HAVE_LZ4_BUILTIN - return LZ4_compress_fast_extState(&lz4_stream, (char *)source, (char *) dest, len, MAXSIZE, 0); - + return LZ4_compress_fast_extState(&lz4_stream, (const char *) source, (char *) dest, len, MAXSIZE, 0); #else -#ifdef HAVE_LZ4_STATE - - /* @FIXME: Put this in a better place, and free() it too. */ - if(lz4_state == NULL) { - lz4_state = malloc(LZ4_sizeofState()); - } - if(lz4_state == NULL) { - logger(DEBUG_ALWAYS, LOG_ERR, "Failed to allocate lz4_state, error: %i", errno); - return 0; - } - - return LZ4_compress_fast_extState(lz4_state, source, dest, len, MAXSIZE, 0); + /* @FIXME: Put this in a better place, and free() it too. */ + if(lz4_state == NULL) { + lz4_state = malloc(LZ4_sizeofState()); + } -#else - return LZ4_compress_shim(source, dest, len, MAXSIZE); + if(lz4_state == NULL) { + logger(DEBUG_ALWAYS, LOG_ERR, "Failed to allocate lz4_state, error: %i", errno); + return 0; + } -#endif /* HAVE_LZ4_STATE */ + return LZ4_compress_fast_extState(lz4_state, (const char *) source, (char *) dest, len, MAXSIZE, 0); #endif /* HAVE_LZ4_BUILTIN */ -#endif /* HAVE_LZ4 */ +} +#endif /* HAVE_LZ4 */ + #ifdef HAVE_LZO +static length_t compress_packet_lzo(uint8_t *dest, const uint8_t *source, length_t len, int level) { + assert(level == 10 || level == 11); - case 11: { - lzo_uint lzolen = MAXSIZE; + lzo_uint lzolen = MAXSIZE; + int result; - if(lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem) == LZO_E_OK) { - return lzolen; - } else { - return 0; - } + if(level == 11) { + result = lzo1x_999_compress(source, len, dest, &lzolen, lzo_wrkmem); + } else { // level == 10 + result = lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem); } - case 10: { - lzo_uint lzolen = MAXSIZE; - - if(lzo1x_1_compress(source, len, dest, &lzolen, lzo_wrkmem) == LZO_E_OK) { - return lzolen; - } else { - return 0; - } + if(result == LZO_E_OK) { + return lzolen; + } else { + return 0; } +} +#endif +static length_t compress_packet(uint8_t *dest, const uint8_t *source, length_t len, int level) { + switch(level) { +#ifdef HAVE_LZ4 + + case 12: + return compress_packet_lz4(dest, source, len); +#endif + +#ifdef HAVE_LZO + + case 11: + case 10: + return compress_packet_lzo(dest, source, len, level); #endif #ifdef HAVE_ZLIB -- 2.20.1