Browse Source

Merge pull request #246 from Logan007/zstdCompression

added optional payload compression (zstd) for all transforms
pull/253/head
Luca Deri 4 years ago
committed by GitHub
parent
commit
27709c22b1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      configure.seed
  2. 41
      edge.c
  3. 71
      edge_utils.c
  4. 12
      n2n.h

14
configure.seed

@ -13,14 +13,24 @@ else
GIT_RELEASE=${N2N_VERSION_SHORT} GIT_RELEASE=${N2N_VERSION_SHORT}
fi fi
N2N_LIBS=
AC_CHECK_LIB([zstd], [ZSTD_compress])
if test "x$ac_cv_lib_zstd_ZSTD_compress" != xyes; then
AC_MSG_RESULT(Building n2n without ZSTD support)
else
AC_DEFINE([N2N_HAVE_ZSTD], [], [Have ZSTD support])
N2N_LIBS="-lzstd ${N2N_LIBS}"
fi
AC_CHECK_LIB([crypto], [AES_cbc_encrypt]) AC_CHECK_LIB([crypto], [AES_cbc_encrypt])
N2N_LIBS=
if test "x$ac_cv_lib_crypto_AES_cbc_encrypt" != xyes; then if test "x$ac_cv_lib_crypto_AES_cbc_encrypt" != xyes; then
AC_MSG_RESULT(Building n2n without AES support) AC_MSG_RESULT(Building n2n without AES support)
else else
AC_DEFINE([N2N_HAVE_AES], [], [Have AES support]) AC_DEFINE([N2N_HAVE_AES], [], [Have AES support])
N2N_LIBS=-lcrypto N2N_LIBS="-lcrypto ${N2N_LIBS}"
fi fi
OLD_CFLAGS="${CFLAGS}" OLD_CFLAGS="${CFLAGS}"

41
edge.c

@ -159,7 +159,7 @@ static void help() {
#ifndef __APPLE__ #ifndef __APPLE__
"[-D] " "[-D] "
#endif #endif
"[-r] [-E] [-v] [-i <reg_interval>] [-L <reg_ttl>] [-t <mgmt port>] [-A[<cipher>]] [-h]\n\n"); "[-r] [-E] [-v] [-i <reg_interval>] [-L <reg_ttl>] [-t <mgmt port>] [-A[<cipher>]] [-z[<compression algo>]] [-h]\n\n");
#if defined(N2N_CAN_NAME_IFACE) #if defined(N2N_CAN_NAME_IFACE)
printf("-d <tun device> | tun device name\n"); printf("-d <tun device> | tun device name\n");
@ -196,8 +196,11 @@ static void help() {
#ifdef HAVE_OPENSSL_1_1 #ifdef HAVE_OPENSSL_1_1
printf("-A4 | Use ChaCha20 for payload encryption. Requires a key (-k).\n"); printf("-A4 | Use ChaCha20 for payload encryption. Requires a key (-k).\n");
#endif #endif
printf("-z | Enable lzo1x compression for outgoing data packets\n"); printf("-z1 or -z | Enable lzo1x compression for outgoing data packets\n");
printf(" | (default=disabled).\n"); #ifdef N2N_HAVE_ZSTD
printf("-z2 | Enable zstd compression for outgoing data packets\n");
#endif
printf(" | (default=compression disabled)\n");
printf("-E | Accept multicast MAC addresses (default=drop).\n"); printf("-E | Accept multicast MAC addresses (default=drop).\n");
printf("-S | Do not connect P2P. Always use the supernode.\n"); printf("-S | Do not connect P2P. Always use the supernode.\n");
#ifdef __linux__ #ifdef __linux__
@ -364,7 +367,33 @@ static int setOption(int optkey, char *optargument, n2n_priv_config_t *ec, n2n_e
case 'z': case 'z':
{ {
conf->compression = N2N_COMPRESSION_ID_LZO; int compression = N2N_COMPRESSION_ID_LZO; // default, if '-z' only
if (optargument) {
compression = atoi(optargument);
}
/* even though 'compression' and 'conf->compression' share the same encoding scheme,
* a switch-statement under conditional compilation is used to sort out the
* unsupported optarguments */
switch (compression) {
case 1:
{
conf->compression = N2N_COMPRESSION_ID_LZO;
break;
}
#ifdef N2N_HAVE_ZSTD
case 2:
{
conf->compression = N2N_COMPRESSION_ID_ZSTD;
break;
}
#endif
default:
{
conf->compression = N2N_COMPRESSION_ID_NONE;
traceEvent(TRACE_NORMAL, "the %s compression given by -z_ option is not supported in this version.", compression_str(compression));
exit(1); // to make the user aware
}
}
break; break;
} }
@ -512,7 +541,7 @@ static int loadFromCLI(int argc, char *argv[], n2n_edge_conf_t *conf, n2n_priv_c
u_char c; u_char c;
while((c = getopt_long(argc, argv, while((c = getopt_long(argc, argv,
"k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:zA::" "k:a:bc:Eu:g:m:M:s:d:l:p:fvhrt:i:SDL:zA:z::"
#ifdef __linux__ #ifdef __linux__
"T:n:" "T:n:"
#endif #endif
@ -796,6 +825,8 @@ int main(int argc, char* argv[]) {
#if defined(HAVE_OPENSSL_1_1) #if defined(HAVE_OPENSSL_1_1)
traceEvent(TRACE_NORMAL, "Using %s", OpenSSL_version(0)); traceEvent(TRACE_NORMAL, "Using %s", OpenSSL_version(0));
#endif #endif
traceEvent(TRACE_NORMAL, "Using compression: %s.", compression_str(conf.compression));
traceEvent(TRACE_NORMAL, "Using %s cipher.", transop_str(conf.transop_id)); traceEvent(TRACE_NORMAL, "Using %s cipher.", transop_str(conf.transop_id));
/* Random seed */ /* Random seed */

71
edge_utils.c

@ -18,6 +18,7 @@
#include "n2n.h" #include "n2n.h"
#include "lzoconf.h" #include "lzoconf.h"
#include <zstd.h>
#ifdef WIN32 #ifdef WIN32
#include <process.h> #include <process.h>
@ -157,6 +158,17 @@ const char* transop_str(enum n2n_transform tr) {
/* ************************************** */ /* ************************************** */
const char* compression_str(uint8_t cmpr) {
switch(cmpr) {
case N2N_COMPRESSION_ID_NONE: return("none");
case N2N_COMPRESSION_ID_LZO: return("lzo1x");
case N2N_COMPRESSION_ID_ZSTD: return("zstd");
default: return("invalid");
};
}
/* ************************************** */
/** Destination 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF is multicast ethernet. /** Destination 01:00:5E:00:00:00 - 01:00:5E:7F:FF:FF is multicast ethernet.
*/ */
static int is_ethMulticast(const void * buf, size_t bufsize) { static int is_ethMulticast(const void * buf, size_t bufsize) {
@ -236,6 +248,10 @@ n2n_edge_t* edge_init(const tuntap_dev *dev, const n2n_edge_conf_t *conf, int *r
goto edge_init_error; goto edge_init_error;
} }
#ifdef N2N_HAVE_ZSTD
// zstd does not require initialization. if it were required, this would be a good place
#endif
for(i=0; i<conf->sn_num; ++i) for(i=0; i<conf->sn_num; ++i)
traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (conf->sn_ip_array[i])); traceEvent(TRACE_NORMAL, "supernode %u => %s\n", i, (conf->sn_ip_array[i]));
@ -992,20 +1008,37 @@ static int handle_PACKET(n2n_edge_t * eee,
/* decompress if necessary */ /* decompress if necessary */
uint8_t * deflation_buffer = 0; uint8_t * deflation_buffer = 0;
uint32_t deflated_len; int32_t deflated_len;
switch (rx_compression_id) { switch (rx_compression_id) {
case N2N_COMPRESSION_ID_NONE:
break; // continue afterwards
case N2N_COMPRESSION_ID_LZO: case N2N_COMPRESSION_ID_LZO:
deflation_buffer = malloc (N2N_PKT_BUF_SIZE); deflation_buffer = malloc (N2N_PKT_BUF_SIZE);
lzo1x_decompress (eth_payload, eth_size, deflation_buffer, (lzo_uint*)&deflated_len, NULL); lzo1x_decompress (eth_payload, eth_size, deflation_buffer, (lzo_uint*)&deflated_len, NULL);
break; break;
#ifdef N2N_HAVE_ZSTD
default: case N2N_COMPRESSION_ID_ZSTD:
deflated_len = N2N_PKT_BUF_SIZE;
deflation_buffer = malloc (deflated_len);
deflated_len = (int32_t)ZSTD_decompress (deflation_buffer, deflated_len, eth_payload, eth_size);
if (ZSTD_isError(deflated_len)) {
traceEvent (TRACE_ERROR, "payload decompression failed with zstd error '%s'.",
ZSTD_getErrorName(deflated_len));
free (deflation_buffer);
return (-1); // cannot help it
}
break; break;
#endif
default:
traceEvent (TRACE_ERROR, "payload decompression failed: received packet indicating unsupported %s compression.",
compression_str(rx_compression_id));
return (-1); // cannot handle it
} }
if (rx_compression_id) { if (rx_compression_id) {
traceEvent (TRACE_DEBUG, "payload decompression [id: %u]: deflated %u bytes to %u bytes", traceEvent (TRACE_DEBUG, "payload decompression [%s]: deflated %u bytes to %u bytes",
rx_compression_id, eth_size, (int)deflated_len); compression_str(rx_compression_id), eth_size, (int)deflated_len);
memcpy(eth_payload ,deflation_buffer, deflated_len ); memcpy(eth_payload ,deflation_buffer, deflated_len );
eth_size = deflated_len; eth_size = deflated_len;
free (deflation_buffer); free (deflation_buffer);
@ -1370,9 +1403,11 @@ static void send_packet2net(n2n_edge_t * eee,
// compression needs to be tried before encode_PACKET is called for compression indication gets encoded there // compression needs to be tried before encode_PACKET is called for compression indication gets encoded there
pkt.compression = N2N_COMPRESSION_ID_NONE; pkt.compression = N2N_COMPRESSION_ID_NONE;
if (eee->conf.compression) { if (eee->conf.compression) {
uint8_t * compression_buffer; uint8_t * compression_buffer;
uint32_t compression_len; int32_t compression_len;
switch (eee->conf.compression) { switch (eee->conf.compression) {
case N2N_COMPRESSION_ID_LZO: case N2N_COMPRESSION_ID_LZO:
compression_buffer = malloc (len + len / 16 + 64 + 3); compression_buffer = malloc (len + len / 16 + 64 + 3);
@ -1382,14 +1417,30 @@ static void send_packet2net(n2n_edge_t * eee,
} }
} }
break; break;
#ifdef N2N_HAVE_ZSTD
case N2N_COMPRESSION_ID_ZSTD:
compression_len = N2N_PKT_BUF_SIZE + 128;
compression_buffer = malloc (compression_len); // leaves enough room, for exact size call compression_len = ZSTD_compressBound (len); (slower)
compression_len = (int32_t)ZSTD_compress(compression_buffer, compression_len, tap_pkt, len, ZSTD_COMPRESSION_LEVEL) ;
if (!ZSTD_isError(compression_len)) {
if (compression_len < len) {
pkt.compression = N2N_COMPRESSION_ID_ZSTD;
}
} else {
traceEvent (TRACE_ERROR, "payload compression failed with zstd error '%s'.",
ZSTD_getErrorName(compression_len));
free (compression_buffer);
// continue with unset without pkt.compression --> will send uncompressed
}
break;
#endif
default: default:
break; break;
} }
if (pkt.compression) { if (pkt.compression) {
traceEvent (TRACE_DEBUG, "payload compression [id: %u]: compressed %u bytes to %u bytes\n", traceEvent (TRACE_DEBUG, "payload compression [%s]: compressed %u bytes to %u bytes\n",
pkt.compression, len, compression_len); compression_str(pkt.compression), len, compression_len);
memcpy (tap_pkt, compression_buffer, compression_len); memcpy (tap_pkt, compression_buffer, compression_len);
len = compression_len; len = compression_len;

12
n2n.h

@ -164,9 +164,15 @@ typedef struct tuntap_dev {
/* N2N compression indicators. */ /* N2N compression indicators. */
/* Compression is disabled by default for outgoing packets if no cli /* Compression is disabled by default for outgoing packets if no cli
* option is given. All edges are built with decompression support so * option is given. All edges are built with decompression support so
* they are able to understand each other. */ * they are able to understand each other (this applies to lzo only). */
#define N2N_COMPRESSION_ID_NONE 0 /* default, see edge_init_conf_defaults(...) in edge_utils.c */ #define N2N_COMPRESSION_ID_NONE 0 /* default, see edge_init_conf_defaults(...) in edge_utils.c */
#define N2N_COMPRESSION_ID_LZO 1 /* set if '-z' cli option is present, see setOption(...) in edge.c */ #define N2N_COMPRESSION_ID_LZO 1 /* set if '-z1' or '-z' cli option is present, see setOption(...) in edge.c */
#ifdef N2N_HAVE_ZSTD
#define N2N_COMPRESSION_ID_ZSTD 2 /* set if '-z2' cli option is present, available only if compiled with zstd lib */
#define ZSTD_COMPRESSION_LEVEL 7 /* 1 (faster) ... 22 (more compression) */
#endif
// with the next major packet structure update, make '0' = invalid, and '1' = no compression
// '2' = LZO, '3' = ZSTD, ... REVISIT then (also: change all occurences in source).
#define N2N_COMPRESSION_ID_BITLEN 3 /* number of bits used for encoding compression id in the uppermost #define N2N_COMPRESSION_ID_BITLEN 3 /* number of bits used for encoding compression id in the uppermost
bits of transform_id; will be obsolete as soon as compression gets bits of transform_id; will be obsolete as soon as compression gets
@ -200,7 +206,6 @@ struct peer_info {
HASH_ADD(hh,head,mac_addr,sizeof(n2n_mac_t),add) HASH_ADD(hh,head,mac_addr,sizeof(n2n_mac_t),add)
#define HASH_FIND_PEER(head,mac,out) \ #define HASH_FIND_PEER(head,mac,out) \
HASH_FIND(hh,head,mac,sizeof(n2n_mac_t),out) HASH_FIND(hh,head,mac,sizeof(n2n_mac_t),out)
#define N2N_EDGE_SN_HOST_SIZE 48 #define N2N_EDGE_SN_HOST_SIZE 48
#define N2N_EDGE_NUM_SUPERNODES 2 #define N2N_EDGE_NUM_SUPERNODES 2
#define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */ #define N2N_EDGE_SUP_ATTEMPTS 3 /* Number of failed attmpts before moving on to next supernode. */
@ -368,6 +373,7 @@ int quick_edge_init(char *device_name, char *community_name,
int sn_init(n2n_sn_t *sss); int sn_init(n2n_sn_t *sss);
void sn_term(n2n_sn_t *sss); void sn_term(n2n_sn_t *sss);
int run_sn_loop(n2n_sn_t *sss, int *keep_running); int run_sn_loop(n2n_sn_t *sss, int *keep_running);
const char* compression_str(uint8_t cmpr);
const char* transop_str(enum n2n_transform tr); const char* transop_str(enum n2n_transform tr);
#endif /* _N2N_H_ */ #endif /* _N2N_H_ */

Loading…
Cancel
Save