Page MenuHomeClusterLabs Projects

No OneTemporary

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;
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Feb 24, 7:01 AM (1 d, 1 h ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464012
Default Alt Text
(47 KB)

Event Timeline