diff --git a/configure.ac b/configure.ac
index 732d082..f96161f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -134,8 +134,13 @@ AC_CHECK_LIB([pthread], [pthread_create])
 AC_CHECK_LIB([m], [ceil])
 AC_CHECK_LIB([rt], [clock_gettime])
 
+# crypto libraries checks
 PKG_CHECK_MODULES([nss],[nss])
 
+# compress libraries checks
+# zlib is cheap because it's pulled in by nss
+PKG_CHECK_MODULES([zlib], [zlib])
+
 # Checks for header files.
 AC_CHECK_HEADERS([fcntl.h])
 AC_CHECK_HEADERS([stdlib.h])
diff --git a/libknet/Makefile.am b/libknet/Makefile.am
index 29719ec..103fb25 100644
--- a/libknet/Makefile.am
+++ b/libknet/Makefile.am
@@ -25,6 +25,7 @@ LIBS			=
 sources			= \
 			  common.c \
 			  compat.c \
+			  compress.c \
 			  crypto.c \
 			  handle.c \
 			  host.c \
@@ -52,6 +53,7 @@ pkgconfig_DATA		= libknet.pc
 noinst_HEADERS		= \
 			  common.h \
 			  compat.h \
+			  compress.h \
 			  crypto.h \
 			  host.h \
 			  internals.h \
@@ -72,7 +74,7 @@ lib_LTLIBRARIES		= libknet.la
 
 libknet_la_SOURCES	= $(sources)
 
-libknet_la_CFLAGS	= $(nss_CFLAGS)
+libknet_la_CFLAGS	= $(nss_CFLAGS) $(zlib_CFLAGS)
 
 EXTRA_libknet_la_DEPENDENCIES	= $(SYMFILE)
 
@@ -80,4 +82,5 @@ libknet_la_LDFLAGS	= -Wl,--version-script=$(srcdir)/$(SYMFILE) \
 			  --export-dynamic \
 			  -version-number $(libversion)
 
-libknet_la_LIBADD	= $(nss_LIBS) -lrt -lpthread -lm
+libknet_la_LIBADD	= $(nss_LIBS) $(zlib_LIBS) \
+			  -lrt -lpthread -lm
diff --git a/libknet/handle.c b/libknet/handle.c
index e538b83..4a880ae 100644
--- a/libknet/handle.c
+++ b/libknet/handle.c
@@ -21,6 +21,7 @@
 
 #include "internals.h"
 #include "crypto.h"
+#include "compress.h"
 #include "compat.h"
 #include "common.h"
 #include "threads_common.h"
@@ -235,6 +236,24 @@ static int _init_buffers(knet_handle_t knet_h)
 	}
 	memset(knet_h->pmtudbuf_crypt, 0, KNET_DATABUFSIZE_CRYPT);
 
+	knet_h->recv_from_links_buf_decompress = malloc(KNET_DATABUFSIZE_COMPRESS);
+	if (!knet_h->recv_from_links_buf_decompress) {
+		savederrno = errno;
+		log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for decompress buffer: %s",
+			strerror(savederrno));
+		goto exit_fail;
+	}
+	memset(knet_h->recv_from_links_buf_decompress, 0, KNET_DATABUFSIZE_COMPRESS);
+
+	knet_h->send_to_links_buf_compress = malloc(KNET_DATABUFSIZE_COMPRESS);
+	if (!knet_h->send_to_links_buf_compress) {
+		savederrno = errno;
+		log_err(knet_h, KNET_SUB_HANDLE, "Unable to allocate memory for compress buffer: %s",
+			strerror(savederrno));
+		goto exit_fail;
+	}
+	memset(knet_h->send_to_links_buf_compress, 0, KNET_DATABUFSIZE_COMPRESS);
+
 	memset(knet_h->knet_transport_fd_tracker, KNET_MAX_TRANSPORTS, sizeof(knet_h->knet_transport_fd_tracker));
 
 	return 0;
@@ -257,6 +276,8 @@ static void _destroy_buffers(knet_handle_t knet_h)
 		free(knet_h->recv_from_links_buf[i]);
 	}
 
+	free(knet_h->recv_from_links_buf_decompress);
+	free(knet_h->send_to_links_buf_compress);
 	free(knet_h->recv_from_sock_buf);
 	free(knet_h->recv_from_links_buf_decrypt);
 	free(knet_h->recv_from_links_buf_crypt);
@@ -606,6 +627,11 @@ knet_handle_t knet_handle_new(knet_node_id_t host_id,
 		goto exit_fail;
 	}
 
+	if (compress_init(knet_h, "none", 0)) {
+		savederrno = EINVAL;
+		goto exit_fail;
+	}
+
 	/*
 	 * create epoll fds
 	 */
@@ -1300,6 +1326,36 @@ exit_unlock:
 	return err;
 }
 
+int knet_handle_compress(knet_handle_t knet_h, const char* compress_model, int compress_level)
+{
+	int savederrno = 0;
+	int err = 0;
+
+	if (!knet_h) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (!compress_model) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock);
+	if (savederrno) {
+		log_err(knet_h, KNET_SUB_HANDLE, "Unable to get write lock: %s",
+			strerror(savederrno));
+		errno = savederrno;
+		return -1;
+	}
+
+	err = compress_init(knet_h, compress_model, compress_level);
+
+	pthread_rwlock_unlock(&knet_h->global_rwlock);
+	errno = savederrno;
+	return err;
+}
+
 ssize_t knet_recv(knet_handle_t knet_h, char *buff, const size_t buff_len, const int8_t channel)
 {
 	int savederrno = 0;
diff --git a/libknet/internals.h b/libknet/internals.h
index 8f330dd..129c39a 100644
--- a/libknet/internals.h
+++ b/libknet/internals.h
@@ -19,9 +19,13 @@
 #include "compat.h"
 
 #define KNET_DATABUFSIZE KNET_MAX_PACKET_SIZE + KNET_HEADER_ALL_SIZE
+
 #define KNET_DATABUFSIZE_CRYPT_PAD 1024
 #define KNET_DATABUFSIZE_CRYPT KNET_DATABUFSIZE + KNET_DATABUFSIZE_CRYPT_PAD
 
+#define KNET_DATABUFSIZE_COMPRESS_PAD 1024
+#define KNET_DATABUFSIZE_COMPRESS KNET_DATABUFSIZE + KNET_DATABUFSIZE_COMPRESS_PAD
+
 #define KNET_RING_RCVBUFF 8388608
 
 #define PCKT_FRAG_MAX UINT8_MAX
@@ -178,6 +182,11 @@ struct knet_handle {
 	unsigned char *recv_from_links_buf_decrypt;
 	unsigned char *pingbuf_crypt;
 	unsigned char *pmtudbuf_crypt;
+	int compress_model;
+	int compress_max_model;
+	int compress_level;
+	unsigned char *recv_from_links_buf_decompress;
+	unsigned char *send_to_links_buf_compress;
 	seq_num_t tx_seq_num;
 	pthread_mutex_t tx_seq_num_mutex;
 	uint8_t has_loop_link;
diff --git a/libknet/libknet.h b/libknet/libknet.h
index e1f0fb3..03b9054 100644
--- a/libknet/libknet.h
+++ b/libknet/libknet.h
@@ -593,6 +593,10 @@ struct knet_handle_crypto_cfg {
 int knet_handle_crypto(knet_handle_t knet_h,
 		       struct knet_handle_crypto_cfg *knet_handle_crypto_cfg);
 
+int knet_handle_compress(knet_handle_t knet_h,
+			 const char* compress_model,
+			 int compress_level);
+
 /*
  * host structs/API calls
  */
@@ -1459,6 +1463,7 @@ int knet_link_get_status(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t l
 #define KNET_SUB_LINK         4 /* link add/del/modify */
 #define KNET_SUB_TRANSPORT    5 /* Transport common */
 #define KNET_SUB_CRYPTO       6 /* crypto.c config generic layer */
+#define KNET_SUB_COMPRESS     7 /* compress.c config generic layer */
 
 #define KNET_SUB_FILTER      19 /* allocated for users to log from dst_filter */
 
@@ -1475,6 +1480,8 @@ int knet_link_get_status(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t l
 
 #define KNET_SUB_NSSCRYPTO   60 /* nsscrypto.c */
 
+#define KNET_SUB_ZLIBCOMP    70 /* zlibcompress.c */
+
 #define KNET_SUB_UNKNOWN     254
 #define KNET_MAX_SUBSYSTEMS  KNET_SUB_UNKNOWN + 1
 
diff --git a/libknet/logging.c b/libknet/logging.c
index 1fb6d34..7d08926 100644
--- a/libknet/logging.c
+++ b/libknet/logging.c
@@ -33,6 +33,7 @@ static struct pretty_names subsystem_names[] =
 	{ "link", KNET_SUB_LINK },
 	{ "transport", KNET_SUB_TRANSPORT },
 	{ "crypto", KNET_SUB_CRYPTO },
+	{ "compress", KNET_SUB_COMPRESS },
 	{ "filter", KNET_SUB_FILTER },
 	{ "dstcache", KNET_SUB_DSTCACHE },
 	{ "heartbeat", KNET_SUB_HEARTBEAT },
@@ -43,6 +44,7 @@ static struct pretty_names subsystem_names[] =
 	{ "udp", KNET_SUB_TRANSP_UDP },
 	{ "sctp", KNET_SUB_TRANSP_SCTP },
 	{ "nsscrypto", KNET_SUB_NSSCRYPTO },
+	{ "zlibcomp", KNET_SUB_ZLIBCOMP },
 	{ "unknown", KNET_SUB_UNKNOWN }		/* unknown MUST always be last in this array */
 };
 
diff --git a/libknet/onwire.h b/libknet/onwire.h
index 5d51701..50de9af 100644
--- a/libknet/onwire.h
+++ b/libknet/onwire.h
@@ -100,8 +100,8 @@ typedef uint16_t seq_num_t;
 
 struct knet_header_payload_data {
 	seq_num_t	khp_data_seq_num;	/* pckt seq number used to deduplicate pkcts */
+	uint8_t		khp_data_compress;	/* identify if user data are compressed */
 	uint8_t		khp_data_pad1;		/* make sure to have space in the header to grow features */
-	uint8_t		khp_data_pad2;
 	uint8_t		khp_data_bcast;		/* data destination bcast/ucast */
 	uint8_t		khp_data_frag_num;	/* number of fragments of this pckt. 1 is not fragmented */
 	uint8_t		khp_data_frag_seq;	/* as above, indicates the frag sequence number */
@@ -178,6 +178,7 @@ struct knet_header {
 #define khp_data_userdata kh_payload.khp_data.khp_data_userdata
 #define khp_data_bcast    kh_payload.khp_data.khp_data_bcast
 #define khp_data_channel  kh_payload.khp_data.khp_data_channel
+#define khp_data_compress kh_payload.khp_data.khp_data_compress
 
 #define khp_ping_link     kh_payload.khp_ping.khp_ping_link
 #define khp_ping_time     kh_payload.khp_ping.khp_ping_time
diff --git a/libknet/threads_rx.c b/libknet/threads_rx.c
index 0a3ea70..e87cbed 100644
--- a/libknet/threads_rx.c
+++ b/libknet/threads_rx.c
@@ -16,6 +16,7 @@
 #include <pthread.h>
 
 #include "compat.h"
+#include "compress.h"
 #include "crypto.h"
 #include "host.h"
 #include "link.h"
@@ -355,6 +356,29 @@ static void _parse_recv_from_links(knet_handle_t knet_h, int sockfd, const struc
 			len = len + KNET_HEADER_DATA_SIZE;
 		}
 
+		if (inbuf->khp_data_compress) {
+			ssize_t decmp_outlen = KNET_DATABUFSIZE_COMPRESS;
+
+			log_debug(knet_h, KNET_SUB_COMPRESS, "WEEE GOT COMPRESSED DATA!");
+
+			if (inbuf->khp_data_compress > knet_h->compress_max_model) {
+				log_err(knet_h, KNET_SUB_COMPRESS, "Received packet with unsupported compression method. Dropping");
+				return;
+			}
+
+			if(!decompress(knet_h, inbuf->khp_data_compress,
+				       (const unsigned char *)inbuf->khp_data_userdata,
+				       len - KNET_HEADER_DATA_SIZE,
+				       knet_h->recv_from_links_buf_decompress,
+				       &decmp_outlen)) {
+				memmove(inbuf->khp_data_userdata, knet_h->recv_from_links_buf_decompress, decmp_outlen);
+				len = decmp_outlen + KNET_HEADER_DATA_SIZE;
+			} else {
+				log_warn(knet_h, KNET_SUB_COMPRESS, "Unable to decompress packet: error");
+				return;
+			}
+		}
+
 		if (inbuf->kh_type == KNET_HEADER_TYPE_DATA) {
 			if (knet_h->enabled != 1) /* data forward is disabled */
 				break;
diff --git a/libknet/threads_tx.c b/libknet/threads_tx.c
index 960b00c..53ae85a 100644
--- a/libknet/threads_tx.c
+++ b/libknet/threads_tx.c
@@ -17,6 +17,7 @@
 #include <errno.h>
 
 #include "compat.h"
+#include "compress.h"
 #include "crypto.h"
 #include "host.h"
 #include "link.h"
@@ -148,6 +149,7 @@ static int _parse_recv_from_sock(knet_handle_t knet_h, ssize_t inlen, int8_t cha
 	int msgs_to_send, msg_idx;
 	unsigned int i;
 	int send_local = 0;
+	int data_compressed = 0;
 
 	inbuf = knet_h->recv_from_sock_buf;
 
@@ -317,6 +319,28 @@ static int _parse_recv_from_sock(knet_handle_t knet_h, ssize_t inlen, int8_t cha
 	}
 
 	/*
+	 * compress data
+	 */
+	if (knet_h->compress_model > 0) {
+		ssize_t cmp_outlen = KNET_DATABUFSIZE_COMPRESS;
+
+		err = compress(knet_h,
+			       (const unsigned char *)inbuf->khp_data_userdata, inlen,
+			       knet_h->send_to_links_buf_compress, &cmp_outlen);
+		if (err < 0) {
+			log_warn(knet_h, KNET_SUB_COMPRESS, "Compression failed (%d): something", err);
+		} else {
+			if (cmp_outlen < inlen) {
+				log_debug(knet_h, KNET_SUB_COMPRESS, "Packet compressed from %zd to %zd",
+					  inlen, cmp_outlen);
+				memmove(inbuf->khp_data_userdata, knet_h->send_to_links_buf_compress, cmp_outlen);
+				inlen = cmp_outlen;
+				data_compressed = 1;
+			}
+		}
+	}
+
+	/*
 	 * prepare the outgoing buffers
 	 */
 
@@ -326,6 +350,9 @@ static int _parse_recv_from_sock(knet_handle_t knet_h, ssize_t inlen, int8_t cha
 	inbuf->khp_data_bcast = bcast;
 	inbuf->khp_data_frag_num = ceil((float)inlen / temp_data_mtu);
 	inbuf->khp_data_channel = channel;
+	if (data_compressed) {
+		inbuf->khp_data_compress = knet_h->compress_model;
+	}
 
 	if (pthread_mutex_lock(&knet_h->tx_seq_num_mutex)) {
 		log_debug(knet_h, KNET_SUB_TX, "Unable to get seq mutex lock");
@@ -388,6 +415,7 @@ static int _parse_recv_from_sock(knet_handle_t knet_h, ssize_t inlen, int8_t cha
 			knet_h->send_to_links_buf[frag_idx]->khp_data_frag_num = inbuf->khp_data_frag_num;
 			knet_h->send_to_links_buf[frag_idx]->khp_data_bcast = inbuf->khp_data_bcast;
 			knet_h->send_to_links_buf[frag_idx]->khp_data_channel = inbuf->khp_data_channel;
+			knet_h->send_to_links_buf[frag_idx]->khp_data_compress = inbuf->khp_data_compress;
 
 			frag_len = frag_len - temp_data_mtu;
 			frag_idx++;
