diff --git a/libknet/compress.c b/libknet/compress.c
index 24755c77..e85448b5 100644
--- a/libknet/compress.c
+++ b/libknet/compress.c
@@ -1,484 +1,511 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 
 #include "config.h"
 
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <pthread.h>
 #include <time.h>
 
 #include "internals.h"
 #include "compress.h"
 #include "compress_model.h"
 #include "logging.h"
 #include "threads_common.h"
 #include "common.h"
 
 /*
  * internal module switch data
  */
 
 /*
  * DO NOT CHANGE MODEL_ID HERE OR ONWIRE COMPATIBILITY
  * WILL BREAK!
  *
  * Always add new items before the last NULL.
  */
 
 static compress_model_t compress_modules_cmds[] = {
 	{ "none" , 0, 0, 0, NULL },
 	{ "zlib" , 1, WITH_COMPRESS_ZLIB , 0, NULL },
 	{ "lz4"  , 2, WITH_COMPRESS_LZ4  , 0, NULL },
 	{ "lz4hc", 3, WITH_COMPRESS_LZ4  , 0, NULL },
 	{ "lzo2" , 4, WITH_COMPRESS_LZO2 , 0, NULL },
 	{ "lzma" , 5, WITH_COMPRESS_LZMA , 0, NULL },
 	{ "bzip2", 6, WITH_COMPRESS_BZIP2, 0, NULL },
 	{ "zstd" , 7, WITH_COMPRESS_ZSTD, 0, NULL },
 	{ NULL, 255, 0, 0, NULL }
 };
 
 static int max_model = 0;
 static struct timespec last_load_failure;
 
 static int compress_get_model(const char *model)
 {
 	int idx = 0;
 
 	while (compress_modules_cmds[idx].model_name != NULL) {
 		if (!strcmp(compress_modules_cmds[idx].model_name, model)) {
 			return compress_modules_cmds[idx].model_id;
 		}
 		idx++;
 	}
 	return -1;
 }
 
 static int compress_get_max_model(void)
 {
 	int idx = 0;
 	while (compress_modules_cmds[idx].model_name != NULL) {
 		idx++;
 	}
 	return idx - 1;
 }
 
 static int compress_is_valid_model(int compress_model)
 {
 	int idx = 0;
 
 	while (compress_modules_cmds[idx].model_name != NULL) {
 		if ((compress_model == compress_modules_cmds[idx].model_id) &&
 		    (compress_modules_cmds[idx].built_in == 1)) {
 			return 0;
 		}
 		idx++;
 	}
 	return -1;
 }
 
 static int val_level(
 	knet_handle_t knet_h,
 	int compress_model,
 	int compress_level)
 {
 	if (compress_modules_cmds[compress_model].ops->val_level != NULL) {
 		return compress_modules_cmds[compress_model].ops->val_level(knet_h, compress_level);
 	}
 	return 0;
 }
 
 /*
  * compress_check_lib_is_init needs to be invoked in a locked context!
  */
 static int compress_check_lib_is_init(knet_handle_t knet_h, int cmp_model)
 {
 	/*
 	 * lack of a .is_init function means that the module does not require
 	 * init per handle so we use a fake reference in the compress_int_data
 	 * to identify that we already increased the libref for this handle
 	 */
 	if (compress_modules_cmds[cmp_model].loaded == 1) {
 		if (compress_modules_cmds[cmp_model].ops->is_init == NULL) {
 			if (knet_h->compress_int_data[cmp_model] != NULL) {
 				return 1;
 			}
 		} else {
 			if (compress_modules_cmds[cmp_model].ops->is_init(knet_h, cmp_model) == 1) {
 				return 1;
 			}
 		}
 	}
 
 	return 0;
 }
 
 /*
  * compress_load_lib should _always_ be invoked in write lock context
  */
 static int compress_load_lib(knet_handle_t knet_h, int cmp_model, int rate_limit)
 {
 	struct timespec clock_now;
 	unsigned long long timediff;
 
 	/*
 	 * checking again for paranoia and because
 	 * compress_check_lib_is_init is usually invoked in read context
 	 * and we need to switch from read to write locking in between.
 	 * another thread might have init the library in the meantime
 	 */
 	if (compress_check_lib_is_init(knet_h, cmp_model)) {
 		return 0;
 	}
 
 	/*
 	 * due to the fact that decompress can load libraries
 	 * on demand, depending on the compress model selected
 	 * on other nodes, it is possible for an attacker
 	 * to send crafted packets to attempt to load libraries
 	 * at random in a DoS fashion.
 	 * If there is an error loading a library, then we want
 	 * to rate_limit a retry to reload the library every X
 	 * seconds to avoid a lock DoS that could greatly slow
 	 * down libknet.
 	 */
 	if (rate_limit) {
 		if ((last_load_failure.tv_sec != 0) ||
 		    (last_load_failure.tv_nsec != 0)) {
 			clock_gettime(CLOCK_MONOTONIC, &clock_now);
 			timespec_diff(last_load_failure, clock_now, &timediff);
 			if (timediff < 10000000000) {
 				errno = EAGAIN;
 				return -1;
 			}
 		}
 	}
 
 	if (compress_modules_cmds[cmp_model].loaded == 0) {
 		compress_modules_cmds[cmp_model].ops = load_module (knet_h, "compress", compress_modules_cmds[cmp_model].model_name);
 		if (!compress_modules_cmds[cmp_model].ops) {
 			clock_gettime(CLOCK_MONOTONIC, &last_load_failure);
 			return -1;
 		}
 		if (compress_modules_cmds[cmp_model].ops->abi_ver != KNET_COMPRESS_MODEL_ABI) {
 			log_err(knet_h, KNET_SUB_COMPRESS,
 				"ABI mismatch loading module %s. knet ver: %d, module ver: %d",
 				compress_modules_cmds[cmp_model].model_name, KNET_COMPRESS_MODEL_ABI,
 				compress_modules_cmds[cmp_model].ops->abi_ver);
 			errno = EINVAL;
 			return -1;
 		}
 		compress_modules_cmds[cmp_model].loaded = 1;
 	}
 
 	if (compress_modules_cmds[cmp_model].ops->init != NULL) {
 		if (compress_modules_cmds[cmp_model].ops->init(knet_h, cmp_model) < 0) {
 			return -1;
 		}
 	} else {
 		knet_h->compress_int_data[cmp_model] = (void *)&"1";
 	}
 
 	return 0;
 }
 
 static int compress_lib_test(knet_handle_t knet_h)
 {
 	int savederrno = 0;
 	unsigned char src[KNET_DATABUFSIZE];
 	unsigned char dst[KNET_DATABUFSIZE_COMPRESS];
 	ssize_t dst_comp_len = KNET_DATABUFSIZE_COMPRESS, dst_decomp_len = KNET_DATABUFSIZE;
 	unsigned int i;
+	int request_level;
 
 	memset(src, 0, KNET_DATABUFSIZE);
 	memset(dst, 0, KNET_DATABUFSIZE_COMPRESS);
 
 	/*
 	 * NOTE: we cannot use compress and decompress API calls due to locking
 	 * so we need to call directly into the modules
 	 */
 
 	if (compress_modules_cmds[knet_h->compress_model].ops->compress(knet_h, src, KNET_DATABUFSIZE, dst, &dst_comp_len) < 0) {
 		savederrno = errno;
 		log_err(knet_h, KNET_SUB_COMPRESS, "Unable to compress test buffer. Please check your compression settings: %s", strerror(savederrno));
 		errno = savederrno;
 		return -1;
+	} else if ((long unsigned int)dst_comp_len >= KNET_DATABUFSIZE) {
+		/*
+		 * compress not effective, try again using default compression level when available
+		 */
+		request_level = knet_h->compress_level;
+		log_warn(knet_h, KNET_SUB_COMPRESS, "Requested compression level (%d) did not generate any compressed data (source: %zu destination: %zu)",
+				request_level, sizeof(src), dst_comp_len);
+
+		if ((!compress_modules_cmds[knet_h->compress_model].ops->get_default_level()) ||
+				((knet_h->compress_level = compress_modules_cmds[knet_h->compress_model].ops->get_default_level()) == KNET_COMPRESS_UNKNOWN_DEFAULT)) {
+                        log_err(knet_h, KNET_SUB_COMPRESS, "compression %s does not provide a default value",
+					compress_modules_cmds[knet_h->compress_model].model_name);
+			return -1;
+                } else {
+			memset(src, 0, KNET_DATABUFSIZE);
+			memset(dst, 0, KNET_DATABUFSIZE_COMPRESS);
+			dst_comp_len = KNET_DATABUFSIZE_COMPRESS;
+			if (compress_modules_cmds[knet_h->compress_model].ops->compress(knet_h, src, KNET_DATABUFSIZE, dst, &dst_comp_len) < 0) {
+                                savederrno = errno;
+                                log_err(knet_h, KNET_SUB_COMPRESS, "Unable to compress with default compression level: %s", strerror(savederrno));
+				errno = savederrno;
+				return -1;
+			}
+			log_warn(knet_h, KNET_SUB_COMPRESS, "Requested compression level (%d) did not work, switching to default (%d)",
+					request_level, knet_h->compress_level);
+		}
 	}
 
 	if (compress_modules_cmds[knet_h->compress_model].ops->decompress(knet_h, dst, dst_comp_len, src, &dst_decomp_len) < 0) {
 		savederrno = errno;
 		log_err(knet_h, KNET_SUB_COMPRESS, "Unable to decompress test buffer. Please check your compression settings: %s", strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	for (i = 0; i < KNET_DATABUFSIZE; i++) {
 		if (src[i] != 0) {
 			log_err(knet_h, KNET_SUB_COMPRESS, "Decompressed buffer contains incorrect data");
 			errno = EINVAL;
 			return -1;
 		}
 	}
 
 	return 0;
 }
 
 int compress_init(
 	knet_handle_t knet_h)
 {
 	max_model = compress_get_max_model();
 	if (max_model > KNET_MAX_COMPRESS_METHODS) {
 		log_err(knet_h, KNET_SUB_COMPRESS, "Too many compress methods defined in compress.c.");
 		errno = EINVAL;
 		return -1;
 	}
 
 	memset(&last_load_failure, 0, sizeof(struct timespec));
 
 	return 0;
 }
 
 int compress_cfg(
 	knet_handle_t knet_h,
 	struct knet_handle_compress_cfg *knet_handle_compress_cfg)
 {
 	int savederrno = 0, err = 0;
 	int cmp_model;
 
 	cmp_model = compress_get_model(knet_handle_compress_cfg->compress_model);
 	if (cmp_model < 0) {
 		log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s not supported", knet_handle_compress_cfg->compress_model);
 		errno = EINVAL;
 		return -1;
 	}
 
 	log_debug(knet_h, KNET_SUB_COMPRESS,
 		  "Initizializing compress module [%s/%d/%u]",
 		  knet_handle_compress_cfg->compress_model, knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_threshold);
 
 	if (cmp_model > 0) {
 		if (compress_modules_cmds[cmp_model].built_in == 0) {
 			log_err(knet_h, KNET_SUB_COMPRESS, "compress model %s support has not been built in. Please contact your vendor or fix the build", knet_handle_compress_cfg->compress_model);
 			errno = EINVAL;
 			return -1;
 		}
 
 		if (knet_handle_compress_cfg->compress_threshold > KNET_MAX_PACKET_SIZE) {
 			log_err(knet_h, KNET_SUB_COMPRESS, "compress threshold cannot be higher than KNET_MAX_PACKET_SIZE (%d).",
 				 KNET_MAX_PACKET_SIZE);
 			errno = EINVAL;
 			return -1;
 		}
 
 		if (knet_handle_compress_cfg->compress_threshold == 0) {
 			knet_h->compress_threshold = KNET_COMPRESS_THRESHOLD;
 			log_debug(knet_h, KNET_SUB_COMPRESS, "resetting compression threshold to default (%d)", KNET_COMPRESS_THRESHOLD);
 		} else {
 			knet_h->compress_threshold = knet_handle_compress_cfg->compress_threshold;
 		}
 
 		savederrno = pthread_rwlock_rdlock(&shlib_rwlock);
 		if (savederrno) {
 			log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s",
 				strerror(savederrno));
 			errno = savederrno;
 			return -1;
 		}
 
 		if (!compress_check_lib_is_init(knet_h, cmp_model)) {
 			/*
 			 * need to switch to write lock, load the lib, and return with a write lock
 			 * this is not racy because compress_load_lib is written idempotent.
 			 */
 			pthread_rwlock_unlock(&shlib_rwlock);
 			savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
 			if (savederrno) {
 				log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s",
 					strerror(savederrno));
 				errno = savederrno;
 				return -1;
 			}
 
 			if (compress_load_lib(knet_h, cmp_model, 0) < 0) {
 				savederrno = errno;
 				log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s",
 					strerror(savederrno));
 				err = -1;
 				goto out_unlock;
 			}
 		}
 
 		if (val_level(knet_h, cmp_model, knet_handle_compress_cfg->compress_level) < 0) {
 			log_err(knet_h, KNET_SUB_COMPRESS, "compress level %d not supported for model %s",
 				knet_handle_compress_cfg->compress_level, knet_handle_compress_cfg->compress_model);
 			savederrno = EINVAL;
 			err = -1;
 			goto out_unlock;
 		}
 
 		knet_h->compress_model = cmp_model;
 		knet_h->compress_level = knet_handle_compress_cfg->compress_level;
 
 		if (compress_lib_test(knet_h) < 0) {
 			savederrno = errno;
 			err = -1;
 			goto out_unlock;
 		}
 
 out_unlock:
 		pthread_rwlock_unlock(&shlib_rwlock);
 	}
 
 	if (err) {
 		knet_h->compress_model = 0;
 		knet_h->compress_level = 0;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
 void compress_fini(
 	knet_handle_t knet_h,
 	int all)
 {
 	int savederrno = 0;
 	int idx = 0;
 
 	savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s",
 			strerror(savederrno));
 		return;
 	}
 
 	while (compress_modules_cmds[idx].model_name != NULL) {
 		if ((idx < KNET_MAX_COMPRESS_METHODS) && /* check idx first so we don't read bad data */
 		    (compress_modules_cmds[idx].built_in == 1) &&
 		    (compress_modules_cmds[idx].loaded == 1) &&
 		    (compress_modules_cmds[idx].model_id > 0) &&
 		    (knet_h->compress_int_data[idx] != NULL)) {
 			if ((all) || (compress_modules_cmds[idx].model_id == knet_h->compress_model)) {
 				if (compress_modules_cmds[idx].ops->fini != NULL) {
 					compress_modules_cmds[idx].ops->fini(knet_h, idx);
 				} else {
 					knet_h->compress_int_data[idx] = NULL;
 				}
 			}
 		}
 		idx++;
 	}
 
 	pthread_rwlock_unlock(&shlib_rwlock);
 	return;
 }
 
 /*
  * compress does not require compress_check_lib_is_init
  * because it's protected by compress_cfg
  */
 int compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	return compress_modules_cmds[knet_h->compress_model].ops->compress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
 }
 
 int decompress(
 	knet_handle_t knet_h,
 	int compress_model,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int savederrno = 0, err = 0;
 
 	if (compress_model > max_model) {
 		log_err(knet_h,  KNET_SUB_COMPRESS, "Received packet with unknown compress model %d", compress_model);
 		errno = EINVAL;
 		return -1;
 	}
 
 	if (compress_is_valid_model(compress_model) < 0) {
 		log_err(knet_h,  KNET_SUB_COMPRESS, "Received packet compressed with %s but support is not built in this version of libknet. Please contact your distribution vendor or fix the build.", compress_modules_cmds[compress_model].model_name);
 		errno = EINVAL;
 		return -1;
 	}
 
 	savederrno = pthread_rwlock_rdlock(&shlib_rwlock);
 	if (savederrno) {
 		log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get read lock: %s",
 			strerror(savederrno));
 		errno = savederrno;
 		return -1;
 	}
 
 	if (!compress_check_lib_is_init(knet_h, compress_model)) {
 		/*
 		 * need to switch to write lock, load the lib, and return with a write lock
 		 * this is not racy because compress_load_lib is written idempotent.
 		 */
 		pthread_rwlock_unlock(&shlib_rwlock);
 		savederrno = pthread_rwlock_wrlock(&shlib_rwlock);
 		if (savederrno) {
 			log_err(knet_h, KNET_SUB_COMPRESS, "Unable to get write lock: %s",
 				strerror(savederrno));
 			errno = savederrno;
 			return -1;
 		}
 
 		if (compress_load_lib(knet_h, compress_model, 1) < 0) {
 			savederrno = errno;
 			err = -1;
 			log_err(knet_h, KNET_SUB_COMPRESS, "Unable to load library: %s",
 				strerror(savederrno));
 			goto out_unlock;
 		}
 	}
 
 	err = compress_modules_cmds[compress_model].ops->decompress(knet_h, buf_in, buf_in_len, buf_out, buf_out_len);
 	savederrno = errno;
 
 out_unlock:
 	pthread_rwlock_unlock(&shlib_rwlock);
 
 	errno = savederrno;
 	return err;
 }
 
 int knet_get_compress_list(struct knet_compress_info *compress_list, size_t *compress_list_entries)
 {
 	int err = 0;
 	int idx = 0;
 	int outidx = 0;
 
 	if (!compress_list_entries) {
 		errno = EINVAL;
 		return -1;
 	}
 
 	while (compress_modules_cmds[idx].model_name != NULL) {
 		if (compress_modules_cmds[idx].built_in) {
 			if (compress_list) {
 				compress_list[outidx].name = compress_modules_cmds[idx].model_name;
 			}
 			outidx++;
 		}
 		idx++;
 	}
 	*compress_list_entries = outidx;
 
 	if (!err)
 		errno = 0;
 	return err;
 }
diff --git a/libknet/compress_bzip2.c b/libknet/compress_bzip2.c
index 5a972fff..68f5280c 100644
--- a/libknet/compress_bzip2.c
+++ b/libknet/compress_bzip2.c
@@ -1,114 +1,126 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 #define KNET_MODULE
 
 #include "config.h"
 
 #include <errno.h>
 #include <bzlib.h>
 
 #include "logging.h"
 #include "compress_model.h"
 
+#ifdef BZIP2_COMPRESS_LEVEL
+#define KNET_COMPRESS_DEFAULT BZIP2_COMPRESS_LEVEL
+#else
+#define KNET_COMPRESS_DEFAULT KNET_COMPRESS_UNKNOWN_DEFAULT
+#endif
+
 static int bzip2_compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int err = 0;
 	int savederrno = 0;
 	unsigned int destLen = KNET_DATABUFSIZE_COMPRESS;
 
 	err = BZ2_bzBuffToBuffCompress((char *)buf_out, &destLen,
 				       (char *)buf_in, buf_in_len,
 				       knet_h->compress_level,
 				       0, 0);
 
 	switch(err) {
 		case BZ_OK:
 			*buf_out_len = destLen;
 			break;
 		case BZ_MEM_ERROR:
 			log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 compress has not enough memory");
 			savederrno = ENOMEM;
 			err = -1;
 			break;
 		case BZ_OUTBUFF_FULL:
 			log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unable to compress source in destination buffer");
 			savederrno = E2BIG;
 			err = -1;
 			break;
 		default:
 			log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 compress unknown error %d", err);
 			savederrno = EINVAL;
 			err = -1;
 			break;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
 static int bzip2_decompress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int err = 0;
 	int savederrno = 0;
 	unsigned int destLen = KNET_DATABUFSIZE_COMPRESS;
 
 	err = BZ2_bzBuffToBuffDecompress((char *)buf_out, &destLen,
 					 (char *)buf_in, buf_in_len,
 					 0, 0);
 
 	switch(err) {
 		case BZ_OK:
 			*buf_out_len = destLen;
 			break;
 		case BZ_MEM_ERROR:
 			log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress has not enough memory");
 			savederrno = ENOMEM;
 			err = -1;
 			break;
 		case BZ_OUTBUFF_FULL:
 			log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 unable to decompress source in destination buffer");
 			savederrno = E2BIG;
 			err = -1;
 			break;
 		case BZ_DATA_ERROR:
 		case BZ_DATA_ERROR_MAGIC:
 		case BZ_UNEXPECTED_EOF:
 			log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress detected input data corruption");
 			savederrno = EINVAL;
 			err = -1;
 			break;
 		default:
 			log_err(knet_h, KNET_SUB_BZIP2COMP, "bzip2 decompress unknown error %d", err);
 			savederrno = EINVAL;
 			err = -1;
 			break;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
+static int bzip2_get_default_level()
+{
+	return KNET_COMPRESS_DEFAULT;
+}
+
 compress_ops_t compress_model = {
 	KNET_COMPRESS_MODEL_ABI,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
 	bzip2_compress,
-	bzip2_decompress
+	bzip2_decompress,
+	bzip2_get_default_level
 };
diff --git a/libknet/compress_lz4.c b/libknet/compress_lz4.c
index 60aa1966..db0fa514 100644
--- a/libknet/compress_lz4.c
+++ b/libknet/compress_lz4.c
@@ -1,91 +1,104 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 #define KNET_MODULE
+#define ACCELERATION_DEFAULT 1 /* lz4 default compression level from lz4.c */
 
 #include "config.h"
 
 #include <errno.h>
 #include <lz4.h>
 
 #include "logging.h"
 #include "compress_model.h"
 
+#ifdef LZ4_COMPRESS_DEFAULT
+#define KNET_COMPRESS_DEFAULT LZ4_COMPRESS_DEFAULT
+#else
+#define KNET_COMPRESS_DEFAULT KNET_COMPRESS_UNKNOWN_DEFAULT
+#endif
+
 static int lz4_compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int lzerr = 0, err = 0;
 	int savederrno = 0;
 
 	lzerr = LZ4_compress_fast((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level);
 
 	/*
 	 * data compressed
 	 */
         if (lzerr > 0) {
 		*buf_out_len = lzerr;
 	}
 
 	/*
 	 * unable to compress
 	 */
 	if (lzerr == 0) {
 		*buf_out_len = buf_in_len;
 	}
 
 	/*
 	 * lz4 internal error
 	 */
 	if (lzerr < 0) {
 		log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 compression error: %d", lzerr);
 		savederrno = EINVAL;
 		err = -1;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
 static int lz4_decompress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int lzerr = 0, err = 0;
 	int savederrno = 0;
 
 	lzerr = LZ4_decompress_safe((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE);
 
 	if (lzerr < 0) {
 		log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 decompression error: %d", lzerr);
 		savederrno = EINVAL;
 		err = -1;
 	}
 
 	if (lzerr > 0) {
 		*buf_out_len = lzerr;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
+static int lz4_get_default_level()
+{
+	return KNET_COMPRESS_DEFAULT;
+}
+
 compress_ops_t compress_model = {
 	KNET_COMPRESS_MODEL_ABI,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
 	lz4_compress,
-	lz4_decompress
+	lz4_decompress,
+	lz4_get_default_level
 };
diff --git a/libknet/compress_lz4hc.c b/libknet/compress_lz4hc.c
index 781bf12f..963ad66c 100644
--- a/libknet/compress_lz4hc.c
+++ b/libknet/compress_lz4hc.c
@@ -1,102 +1,113 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 #define KNET_MODULE
 
 #include "config.h"
 
 #include <errno.h>
 #include <lz4.h>
 #include <lz4hc.h>
 
 #include "logging.h"
 #include "compress_model.h"
 
+#ifdef LZ4HC_CLEVEL_DEFAULT
+#define KNET_COMPRESS_DEFAULT LZ4HC_CLEVEL_DEFAULT /* lz4hc default compression level from lz4hc.h */
+#else
+#define KNET_COMPRESS_DEFAULT KNET_COMPRESS_UNKNOWN_DEFAULT
+#endif
 #ifdef LZ4HC_CLEVEL_MAX
 #define KNET_LZ4HC_MAX LZ4HC_CLEVEL_MAX
 #endif
 #ifdef LZ4HC_MAX_CLEVEL
 #define KNET_LZ4HC_MAX LZ4HC_MAX_CLEVEL
 #endif
 #ifndef KNET_LZ4HC_MAX
 /*
  * older releases of lz4 do not define LZ4HC_CLEVEL range.
  * According to lz4hc.h, any value between 0 and 16 is valid.
  * We defalt to 16 based on the comments in the include file
  * from older versions.
  */
 #define KNET_LZ4HC_MAX 16
 #endif
 
 static int lz4hc_compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int lzerr = 0, err = 0;
 	int savederrno = 0;
 
 	lzerr = LZ4_compress_HC((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE_COMPRESS, knet_h->compress_level);
 
 	/*
 	 * data compressed
 	 */
         if (lzerr > 0) {
 		*buf_out_len = lzerr;
 	}
 
 	/*
 	 * unable to compress
 	 */
 	if (lzerr <= 0) {
 		log_err(knet_h, KNET_SUB_LZ4HCCOMP, "lz4hc compression error: %d", lzerr);
 		savederrno = EINVAL;
 		err = -1;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
 /* This is a straight copy from compress_lz4.c */
 static int lz4_decompress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int lzerr = 0, err = 0;
 	int savederrno = 0;
 
 	lzerr = LZ4_decompress_safe((const char *)buf_in, (char *)buf_out, buf_in_len, KNET_DATABUFSIZE);
 
 	if (lzerr < 0) {
 		log_err(knet_h, KNET_SUB_LZ4COMP, "lz4 decompression error: %d", lzerr);
 		savederrno = EINVAL;
 		err = -1;
 	}
 
 	if (lzerr > 0) {
 		*buf_out_len = lzerr;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
+static int lz4hc_get_default_level()
+{
+	return KNET_COMPRESS_DEFAULT;
+}
+
 compress_ops_t compress_model = {
 	KNET_COMPRESS_MODEL_ABI,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
 	lz4hc_compress,
-	lz4_decompress
+	lz4_decompress,
+	lz4hc_get_default_level
 };
diff --git a/libknet/compress_lzma.c b/libknet/compress_lzma.c
index 7fdd1782..b4fd05c3 100644
--- a/libknet/compress_lzma.c
+++ b/libknet/compress_lzma.c
@@ -1,125 +1,137 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 #define KNET_MODULE
 
 #include "config.h"
 
 #include <errno.h>
 #include <lzma.h>
 
 #include "logging.h"
 #include "compress_model.h"
 
+#ifdef LZMA_PRESET_DEFAULT
+#define KNET_COMPRESS_DEFAULT LZMA_PRESET_DEFAULT /* lzma default compression level from lzma.h */
+#else
+#define KNET_COMPRESS_DEFAULT KNET_COMPRESS_UNKNOWN_DEFAULT
+#endif
+
 static int lzma_compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int err = 0;
 	int savederrno = 0;
 	size_t out_pos = 0;
 	lzma_ret ret = 0;
 
 	ret = lzma_easy_buffer_encode(knet_h->compress_level, LZMA_CHECK_NONE, NULL,
 				      (const uint8_t *)buf_in, buf_in_len,
 				      (uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS);
 
 	switch(ret) {
 		case LZMA_OK:
 			*buf_out_len = out_pos;
 			break;
 		case LZMA_MEM_ERROR:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress memory allocation failed");
 			savederrno = ENOMEM;
 			err = -1;
 			break;
 		case LZMA_MEMLIMIT_ERROR:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress requires higher memory boundaries (see lzma_memlimit_set)");
 			savederrno = ENOMEM;
 			err = -1;
 			break;
 		case LZMA_PROG_ERROR:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress has been called with incorrect options");
 			savederrno = EINVAL;
 			err = -1;
 			break;
 		default:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma compress unknown error %u", ret);
 			savederrno = EINVAL;
 			err = -1;
 			break;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
 static int lzma_decompress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int err = 0;
 	int savederrno = 0;
 	uint64_t memlimit = UINT64_MAX; /* disable lzma internal memlimit check */
 	size_t out_pos = 0, in_pos = 0;
 	lzma_ret ret = 0;
 
 	ret = lzma_stream_buffer_decode(&memlimit, 0, NULL,
 					(const uint8_t *)buf_in, &in_pos, buf_in_len,
 					(uint8_t *)buf_out, &out_pos, KNET_DATABUFSIZE_COMPRESS);
 
 	switch(ret) {
 		case LZMA_OK:
 			*buf_out_len = out_pos;
 			break;
 		case LZMA_MEM_ERROR:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress memory allocation failed");
 			savederrno = ENOMEM;
 			err = -1;
 			break;
 		case LZMA_MEMLIMIT_ERROR:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress requires higher memory boundaries (see lzma_memlimit_set)");
 			savederrno = ENOMEM;
 			err = -1;
 			break;
 		case LZMA_DATA_ERROR:
 		case LZMA_FORMAT_ERROR:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress invalid data received");
 			savederrno = EINVAL;
 			err = -1;
 			break;
 		case LZMA_PROG_ERROR:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress has been called with incorrect options");
 			savederrno = EINVAL;
 			err = -1;
 			break;
 		default:
 			log_err(knet_h, KNET_SUB_LZMACOMP, "lzma decompress unknown error %u", ret);
 			savederrno = EINVAL;
 			err = -1;
 			break;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
+static int lzma_get_default_level()
+{
+	return KNET_COMPRESS_DEFAULT;
+}
+
 compress_ops_t compress_model = {
 	KNET_COMPRESS_MODEL_ABI,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
 	lzma_compress,
-	lzma_decompress
+	lzma_decompress,
+	lzma_get_default_level
 };
diff --git a/libknet/compress_lzo2.c b/libknet/compress_lzo2.c
index 12066ed9..72dac824 100644
--- a/libknet/compress_lzo2.c
+++ b/libknet/compress_lzo2.c
@@ -1,165 +1,178 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 #define KNET_MODULE
+#define LZO2_COMPRESS_DEFAULT 1
 
 #include "config.h"
 
 #include <string.h>
 #include <stdlib.h>
 #include <errno.h>
 #include <lzo/lzo1x.h>
 
 #include "logging.h"
 #include "compress_model.h"
 
+#ifdef LZO2_COMPRESS_DEFAULT
+#define KNET_COMPRESS_DEFAULT LZO2_COMPRESS_DEFAULT
+#else
+#define KNET_COMPRESS_DEFAULT KNET_COMPRESS_UNKNOWN_DEFAULT
+#endif
+
 static int lzo2_is_init(
 	knet_handle_t knet_h,
 	int method_idx)
 {
 	if (knet_h->compress_int_data[method_idx]) {
 		return 1;
 	}
 	return 0;
 }
 
 static int lzo2_init(
 	knet_handle_t knet_h,
 	int method_idx)
 {
 	/*
 	 * LZO1X_999_MEM_COMPRESS is the highest amount of memory lzo2 can use
 	 */
 	if (!knet_h->compress_int_data[method_idx]) {
 		knet_h->compress_int_data[method_idx] = malloc(LZO1X_999_MEM_COMPRESS);
 		if (!knet_h->compress_int_data[method_idx]) {
 			log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 unable to allocate work memory");
 			errno = ENOMEM;
 			return -1;
 		}
 		memset(knet_h->compress_int_data[method_idx], 0, LZO1X_999_MEM_COMPRESS);
 	}
 
 	return 0;
 }
 
 static void lzo2_fini(
 	knet_handle_t knet_h,
 	int method_idx)
 {
 	if (knet_h->compress_int_data[method_idx]) {
 		free(knet_h->compress_int_data[method_idx]);
 		knet_h->compress_int_data[method_idx] = NULL;
 	}
 	return;
 }
 
 static int lzo2_val_level(
 	knet_handle_t knet_h,
 	int compress_level)
 {
 	switch(compress_level) {
 		case 1:
 			log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_compress internal compress method");
 			break;
 		case 11:
 			log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_11_compress internal compress method");
 			break;
 		case 12:
 			log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_12_compress internal compress method");
 			break;
 		case 15:
 			log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_1_15_compress internal compress method");
 			break;
 		case 999:
 			log_debug(knet_h, KNET_SUB_LZO2COMP, "lzo2 will use lzo1x_999_compress internal compress method");
 			break;
 		default:
 			log_warn(knet_h, KNET_SUB_LZO2COMP, "Unknown lzo2 internal compress method. lzo1x_1_compress will be used as default fallback");
 			break;
 	}
 
 	return 0;
 }
 
 static int lzo2_compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int savederrno = 0, lzerr = 0, err = 0;
 	lzo_uint cmp_len;
 
 	switch(knet_h->compress_level) {
 		case 1:
 			lzerr = lzo1x_1_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]);
 			break;
 		case 11:
 			lzerr = lzo1x_1_11_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]);
 			break;
 		case 12:
 			lzerr = lzo1x_1_12_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]);
 			break;
 		case 15:
 			lzerr = lzo1x_1_15_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]);
 			break;
 		case 999:
 			lzerr = lzo1x_999_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]);
 			break;
 		default:
 			lzerr = lzo1x_1_compress(buf_in, buf_in_len, buf_out, &cmp_len, knet_h->compress_int_data[knet_h->compress_model]);
 			break;
 	}
 
 	if (lzerr != LZO_E_OK) {
 		log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 internal compression error");
 		savederrno = EAGAIN;
 		err = -1;
 	} else {
 		*buf_out_len = cmp_len;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
 static int lzo2_decompress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int lzerr = 0, err = 0;
 	int savederrno = 0;
 	lzo_uint decmp_len;
 
 	lzerr = lzo1x_decompress(buf_in, buf_in_len, buf_out, &decmp_len, NULL);
 
 	if (lzerr != LZO_E_OK) {
 		log_err(knet_h, KNET_SUB_LZO2COMP, "lzo2 internal decompression error");
 		savederrno = EAGAIN;
 		err = -1;
 	} else {
 		*buf_out_len = decmp_len;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
+static int lzo2_get_default_level()
+{
+	return KNET_COMPRESS_DEFAULT;
+}
+
 compress_ops_t compress_model = {
 	KNET_COMPRESS_MODEL_ABI,
 	lzo2_is_init,
 	lzo2_init,
 	lzo2_fini,
 	lzo2_val_level,
 	lzo2_compress,
-	lzo2_decompress
+	lzo2_decompress,
+	lzo2_get_default_level
 };
diff --git a/libknet/compress_model.h b/libknet/compress_model.h
index e69e4915..57cf8115 100644
--- a/libknet/compress_model.h
+++ b/libknet/compress_model.h
@@ -1,91 +1,97 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 
 #ifndef __KNET_COMPRESS_MODEL_H__
 #define __KNET_COMPRESS_MODEL_H__
 
 #include "internals.h"
 
-#define KNET_COMPRESS_MODEL_ABI 1
+#define KNET_COMPRESS_MODEL_ABI            2
+#define KNET_COMPRESS_UNKNOWN_DEFAULT    (-2)
 
 typedef struct {
 	uint8_t abi_ver;
 
 	/*
 	 * some libs need special init and handling of buffers etc.
 	 * is_init is called in shlib_rwlock read only context to see if
 	 * the module has been initialized within this knet_handle.
 	 * Providing is_init is optional. A module that does not export
 	 * an is_init and if the associated shared library is already loaded
 	 * is treated as "does not require init".
 	 */
 	int (*is_init)  (knet_handle_t knet_h, int method_idx);
 
 	/*
 	 * init is called when the library requires special init handling,
 	 * such as memory allocation and such.
 	 * init is invoked in shlib_rwlock write only context when
 	 * the module exports this function.
 	 * It is optional to provide an init function if the module
 	 * does not require any init.
 	 */
 	int (*init)     (knet_handle_t knet_h, int method_idx);
 
 	/*
 	 * fini is invoked only on knet_handle_free in a write only context.
 	 * It is optional to provide this function if the module
 	 * does not require any finalization
 	 */
 	void (*fini)    (knet_handle_t knet_h, int method_idx);
 
 	/*
 	 * runtime config validation and compress/decompress
 	 */
 
 	/*
 	 * val_level is called upon compress configuration changes
 	 * to make sure that the requested compress_level is valid
 	 * within the context of a given module.
 	 */
 	int (*val_level)(knet_handle_t knet_h,
 			 int compress_level);
 
 	/*
 	 * required functions
 	 *
 	 * hopefully those 2 don't require any explanation....
 	 */
 	int (*compress)	(knet_handle_t knet_h,
 			 const unsigned char *buf_in,
 			 const ssize_t buf_in_len,
 			 unsigned char *buf_out,
 			 ssize_t *buf_out_len);
 	int (*decompress)(knet_handle_t knet_h,
 			 const unsigned char *buf_in,
 			 const ssize_t buf_in_len,
 			 unsigned char *buf_out,
 			 ssize_t *buf_out_len);
+
+	/*
+	 * Get default compression level
+	 */
+	int (*get_default_level) (void);
 } compress_ops_t;
 
 typedef struct {
 	const char	*model_name;
 	uint8_t		model_id;    /* sequential unique identifier */
 	uint8_t		built_in;    /* set at configure/build time to 1 if available */
 
 	/*
 	 * library is loaded
 	 */
 	uint8_t		loaded;
 
 	/*
 	 * runtime bits
 	 */
 	compress_ops_t	*ops;
 } compress_model_t;
 
 #endif
diff --git a/libknet/compress_zlib.c b/libknet/compress_zlib.c
index 2fb12f51..fa6ae011 100644
--- a/libknet/compress_zlib.c
+++ b/libknet/compress_zlib.c
@@ -1,117 +1,129 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 #define KNET_MODULE
 
 #include "config.h"
 
 #include <errno.h>
 #include <zlib.h>
 
 #include "logging.h"
 #include "compress_model.h"
 
+#ifdef Z_DEFAULT_COMPRESSION
+#define KNET_COMPRESS_DEFAULT Z_DEFAULT_COMPRESSION /* zlib default compression level from zlib.h */
+#else
+#define KNET_COMPRESS_DEFAULT KNET_COMPRESS_UNKNOWN_DEFAULT
+#endif
+
 static int zlib_compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int zerr = 0, err = 0;
 	int savederrno = 0;
 	uLongf destLen = *buf_out_len;
 
 	zerr = compress2(buf_out, &destLen,
 			 buf_in, buf_in_len,
 			 knet_h->compress_level);
 
 	*buf_out_len = destLen;
 
 	switch(zerr) {
 		case Z_OK:
 			err = 0;
 			savederrno = 0;
 			break;
 		case Z_MEM_ERROR:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress mem error");
 			err = -1;
 			savederrno = ENOMEM;
 			break;
 		case Z_BUF_ERROR:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress buf error");
 			err = -1;
 			savederrno = ENOBUFS;
 			break;
 		case Z_STREAM_ERROR:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib compress stream error");
 			err = -1;
 			savederrno = EINVAL;
 			break;
 		default:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib unknown compress error: %d", zerr);
 			break;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
 static int zlib_decompress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	int zerr = 0, err = 0;
 	int savederrno = 0;
 	uLongf destLen = *buf_out_len;
 
 	zerr = uncompress(buf_out, &destLen,
 			  buf_in, buf_in_len);
 
 	*buf_out_len = destLen;
 
 	switch(zerr) {
 		case Z_OK:
 			err = 0;
 			savederrno = 0;
 			break;
 		case Z_MEM_ERROR:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress mem error");
 			err = -1;
 			savederrno = ENOMEM;
 			break;
 		case Z_BUF_ERROR:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress buf error");
 			err = -1;
 			savederrno = ENOBUFS;
 			break;
 		case Z_DATA_ERROR:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib decompress data error");
 			err = -1;
 			savederrno = EINVAL;
 			break;
 		default:
 			log_err(knet_h, KNET_SUB_ZLIBCOMP, "zlib unknown decompress error: %d", zerr);
 			break;
 	}
 
 	errno = savederrno;
 	return err;
 }
 
+static int zlib_get_default_level()
+{
+	return KNET_COMPRESS_DEFAULT;
+}
+
 compress_ops_t compress_model = {
 	KNET_COMPRESS_MODEL_ABI,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
 	zlib_compress,
-	zlib_decompress
+	zlib_decompress,
+	zlib_get_default_level
 };
diff --git a/libknet/compress_zstd.c b/libknet/compress_zstd.c
index e234f8d6..8e679bb6 100644
--- a/libknet/compress_zstd.c
+++ b/libknet/compress_zstd.c
@@ -1,160 +1,172 @@
 /*
  * Copyright (C) 2019 Red Hat, Inc.  All rights reserved.
  *
  * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under LGPL-2.0+
  */
 #define KNET_MODULE
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <zstd.h>
 
 #include "logging.h"
 #include "compress_model.h"
 
+#ifdef ZSTD_CLEVEL_DEFAULT
+#define KNET_COMPRESS_DEFAULT ZSTD_CLEVEL_DEFAULT /* zstd default compression level from zstd.h */
+#else
+#define KNET_COMPRESS_DEFAULT KNET_COMPRESS_UNKNOWN_DEFAULT
+#endif
+
 struct zstd_ctx {
 	ZSTD_CCtx* cctx;
 	ZSTD_DCtx* dctx;
 };
 
 static int zstd_is_init(
 	knet_handle_t knet_h,
 	int method_idx)
 {
 	if (knet_h->compress_int_data[method_idx]) {
 		return 1;
 	}
 	return 0;
 }
 
 static void zstd_fini(
 	knet_handle_t knet_h,
 	int method_idx)
 {
 	struct zstd_ctx *zstd_ctx = knet_h->compress_int_data[knet_h->compress_model];
 
 	if (zstd_ctx) {
 		if (zstd_ctx->cctx) {
 			ZSTD_freeCCtx(zstd_ctx->cctx);
 		}
 		if (zstd_ctx->dctx) {
 			ZSTD_freeDCtx(zstd_ctx->dctx);
 		}
 		free(knet_h->compress_int_data[method_idx]);
 		knet_h->compress_int_data[method_idx] = NULL;
 	}
 	return;
 }
 
 static int zstd_init(
 	knet_handle_t knet_h,
 	int method_idx)
 {
 	struct zstd_ctx *zstd_ctx;
 	int err = 0;
 
 	if (!knet_h->compress_int_data[method_idx]) {
 		zstd_ctx = malloc(sizeof(struct zstd_ctx));
 		if (!zstd_ctx) {
 			errno = ENOMEM;
 			return -1;
 		}
 		memset(zstd_ctx, 0, sizeof(struct zstd_ctx));
 
 		zstd_ctx->cctx = ZSTD_createCCtx();
 		if (!zstd_ctx->cctx) {
 			log_err(knet_h, KNET_SUB_ZSTDCOMP, "Unable to create compression context");
 			err = -1;
 			goto out_err;
 		}
 
 		zstd_ctx->dctx = ZSTD_createDCtx();
 		if (!zstd_ctx->dctx) {
 			log_err(knet_h, KNET_SUB_ZSTDCOMP, "Unable to create decompression context");
 			err = -1;
 			goto out_err;
 		}
 
 		knet_h->compress_int_data[method_idx] = zstd_ctx;
 	}
 
 out_err:
 	if (err) {
 		zstd_fini(knet_h, method_idx);
 	}
 	return err;
 }
 
 static int zstd_compress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	struct zstd_ctx *zstd_ctx = knet_h->compress_int_data[knet_h->compress_model];
 	size_t compress_size;
 
 	compress_size = ZSTD_compressCCtx(zstd_ctx->cctx,
 					  buf_out, *buf_out_len,
 					  buf_in, buf_in_len,
 					  knet_h->compress_level);
 
 	if (ZSTD_isError(compress_size)) {
 		log_err(knet_h, KNET_SUB_ZSTDCOMP, "error compressing packet: %s", ZSTD_getErrorName(compress_size));
 		/*
 		 * ZSTD has lots of internal errors that are not easy to map
 		 * to standard errnos. Use a generic one for now
 		 */
 		errno = EINVAL;
 		return -1;
 	}
 
 	*buf_out_len = compress_size;
 
 	return 0;
 }
 
 static int zstd_decompress(
 	knet_handle_t knet_h,
 	const unsigned char *buf_in,
 	const ssize_t buf_in_len,
 	unsigned char *buf_out,
 	ssize_t *buf_out_len)
 {
 	struct zstd_ctx *zstd_ctx = knet_h->compress_int_data[knet_h->compress_model];
 	size_t decompress_size;
 
 	decompress_size = ZSTD_decompressDCtx(zstd_ctx->dctx,
 					      buf_out, *buf_out_len,
 					      buf_in, buf_in_len);
 
 	if (ZSTD_isError(decompress_size)) {
 		log_err(knet_h, KNET_SUB_ZSTDCOMP, "error decompressing packet: %s", ZSTD_getErrorName(decompress_size));
 		/*
 		 * ZSTD has lots of internal errors that are not easy to map
 		 * to standard errnos. Use a generic one for now
 		 */
 		errno = EINVAL;
 		return -1;
 	}
 
 	*buf_out_len = decompress_size;
 
 	return 0;
 }
 
+static int zstd_get_default_level()
+{
+	return KNET_COMPRESS_DEFAULT;
+}
+
 compress_ops_t compress_model = {
 	KNET_COMPRESS_MODEL_ABI,
 	zstd_is_init,
 	zstd_init,
 	zstd_fini,
 	NULL,
 	zstd_compress,
-	zstd_decompress
+	zstd_decompress,
+	zstd_get_default_level
 };
diff --git a/libknet/tests/api_knet_handle_compress.c b/libknet/tests/api_knet_handle_compress.c
index 40b6f397..3cb2ef41 100644
--- a/libknet/tests/api_knet_handle_compress.c
+++ b/libknet/tests/api_knet_handle_compress.c
@@ -1,181 +1,197 @@
 /*
  * Copyright (C) 2017-2019 Red Hat, Inc.  All rights reserved.
  *
  * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
  *
  * This software licensed under GPL-2.0+
  */
 
 #include "config.h"
 
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 #include "libknet.h"
 
 #include "internals.h"
 #include "test-common.h"
 
 static void test(void)
 {
 	knet_handle_t knet_h;
 	int logfds[2];
 	struct knet_handle_compress_cfg knet_handle_compress_cfg;
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 
 	printf("Test knet_handle_compress incorrect knet_h\n");
 
 	if ((!knet_handle_compress(NULL, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
 		printf("knet_handle_compress accepted invalid knet_h or returned incorrect error: %s\n", strerror(errno));
 		exit(FAIL);
 	}
 
 	setup_logpipes(logfds);
 
 	knet_h = knet_handle_start(logfds, KNET_LOG_DEBUG);
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_compress with invalid cfg\n");
 
 	if ((!knet_handle_compress(knet_h, NULL)) || (errno != EINVAL)) {
 		printf("knet_handle_compress accepted invalid cfg or returned incorrect error: %s\n", strerror(errno));
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_compress with un-initialized cfg\n");
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 
 	if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
 		printf("knet_handle_compress accepted invalid un-initialized cfg\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_compress with none compress model (disable compress)\n");
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 	strncpy(knet_handle_compress_cfg.compress_model, "none", sizeof(knet_handle_compress_cfg.compress_model) - 1);
 
 	if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) != 0) {
 		printf("knet_handle_compress did not accept none compress mode cfg\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
+	printf("Test knet_handle_compress with zlib compress and not effective compression level (0)\n");
+
+	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
+	strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
+	knet_handle_compress_cfg.compress_level = 0;
+
+	if((knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno == EINVAL)) {
+		printf("knet_handle_compress failed to compress with default compression level\n");
+		knet_handle_free(knet_h);
+		flush_logs(logfds[0], stdout);
+		close_logpipes(logfds);
+		exit(FAIL);
+	}
+
+	flush_logs(logfds[0], stdout);
+
 	printf("Test knet_handle_compress with zlib compress and negative level (-2)\n");
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 	strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
 	knet_handle_compress_cfg.compress_level = -2;
 
 	if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
 		printf("knet_handle_compress accepted invalid (-2) compress level for zlib\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_compress with zlib compress and excessive compress level\n");
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 	strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
 	knet_handle_compress_cfg.compress_level = 10;
 
 	if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
 		printf("knet_handle_compress accepted invalid (10) compress level for zlib\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_compress with zlib compress and excessive compress threshold\n");
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 	strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
 	knet_handle_compress_cfg.compress_level = 1;
 	knet_handle_compress_cfg.compress_threshold = KNET_MAX_PACKET_SIZE +1;
 
 	if ((!knet_handle_compress(knet_h, &knet_handle_compress_cfg)) || (errno != EINVAL)) {
 		printf("knet_handle_compress accepted invalid compress threshold\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 
 	flush_logs(logfds[0], stdout);
 
 	printf("Test knet_handle_compress with zlib compress model normal compress level and threshold\n");
 
 	memset(&knet_handle_compress_cfg, 0, sizeof(struct knet_handle_compress_cfg));
 	strncpy(knet_handle_compress_cfg.compress_model, "zlib", sizeof(knet_handle_compress_cfg.compress_model) - 1);
 	knet_handle_compress_cfg.compress_level = 1;
 	knet_handle_compress_cfg.compress_threshold = 64;
 
 	if (knet_handle_compress(knet_h, &knet_handle_compress_cfg) != 0) {
 		printf("knet_handle_compress did not accept zlib compress mode with compress level 1 cfg\n");
 		knet_handle_free(knet_h);
 		flush_logs(logfds[0], stdout);
 		close_logpipes(logfds);
 		exit(FAIL);
 	}
 	flush_logs(logfds[0], stdout);
 
 	knet_handle_free(knet_h);
 	flush_logs(logfds[0], stdout);
 	close_logpipes(logfds);
 }
 
 int main(int argc, char *argv[])
 {
 	struct knet_compress_info compress_list[16];
 	size_t compress_list_entries;
 	size_t i;
 
 	memset(compress_list, 0, sizeof(compress_list));
 
 	if (knet_get_compress_list(compress_list, &compress_list_entries) < 0) {
 		printf("knet_get_compress_list failed: %s\n", strerror(errno));
 		return FAIL;
 	}
 
 	if (compress_list_entries == 0) {
 		printf("no compression modules detected. Skipping\n");
 		return SKIP;
 	}
 
 	for (i=0; i < compress_list_entries; i++) {
 		if (!strcmp(compress_list[i].name, "zlib")) {
 			test();
 			return PASS;
 		}
 	}
 
 	printf("WARNING: zlib support not builtin the library. Unable to test/verify internal compress API calls\n");
 	return SKIP;
 }