Page MenuHomeClusterLabs Projects

No OneTemporary

diff --git a/libknet/tests/fun_config_crypto.c b/libknet/tests/fun_config_crypto.c
index 2a4b5df1..ac9deb6a 100644
--- a/libknet/tests/fun_config_crypto.c
+++ b/libknet/tests/fun_config_crypto.c
@@ -1,278 +1,278 @@
/*
* Copyright (C) 2020 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 <inttypes.h>
#include "libknet.h"
#include "compress.h"
#include "internals.h"
#include "netutils.h"
#include "test-common.h"
#define TESTNODES 2
static void test(const char *model)
{
knet_handle_t knet_h[TESTNODES + 1];
int logfds[2];
struct knet_handle_crypto_cfg knet_handle_crypto_cfg;
int i,x,j;
- int seconds = 5;
+ int seconds = 10;
if (is_memcheck() || is_helgrind()) {
printf("Test suite is running under valgrind, adjusting wait_for_host timeout\n");
seconds = seconds * 16;
}
setup_logpipes(logfds);
knet_handle_start_nodes(knet_h, TESTNODES, logfds, KNET_LOG_DEBUG);
flush_logs(logfds[0], stdout);
/*
* config1: aes128/sha256 key1 is all 0s (2000 bytes)
*/
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes128", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha256", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
memset(knet_handle_crypto_cfg.private_key, 0, KNET_MAX_KEY_LEN);
knet_handle_crypto_cfg.private_key_len = 2000;
for (i = 1; i <= TESTNODES; i++) {
if (knet_handle_crypto_set_config(knet_h[i], &knet_handle_crypto_cfg, 1) < 0) {
printf("knet_handle_crypto_set_config (1) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_handle_crypto_use_config(knet_h[i], 1) < 0) {
printf("knet_handle_crypto_use_config (1) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
if (knet_handle_crypto_rx_clear_traffic(knet_h[i], KNET_CRYPTO_RX_DISALLOW_CLEAR_TRAFFIC)) {
printf("knet_handle_crypto_rx_clear_traffic failed: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
flush_logs(logfds[0], stdout);
knet_handle_join_nodes(knet_h, TESTNODES, 1, AF_INET, KNET_TRANSPORT_UDP);
flush_logs(logfds[0], stdout);
/*
* config2: aes256/sha512 key1 is all 1s (KNET_MAX_KEY_LEN bytes)
*/
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, model, sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "aes256", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "sha512", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
memset(knet_handle_crypto_cfg.private_key, 1, KNET_MAX_KEY_LEN);
knet_handle_crypto_cfg.private_key_len = KNET_MAX_KEY_LEN;
for (i = 1; i <= TESTNODES; i++) {
if (knet_handle_crypto_set_config(knet_h[i], &knet_handle_crypto_cfg, 2) < 0) {
printf("knet_handle_crypto_set_config (2) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
flush_logs(logfds[0], stdout);
printf("Testing crypto config switch from 1 to 2\n");
for (i = 1; i <= TESTNODES; i++) {
if (knet_handle_crypto_use_config(knet_h[i], 2) < 0) {
printf("knet_handle_crypto_use_config (2) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
for (x = 0; x < seconds; x++){
flush_logs(logfds[0], stdout);
sleep(1);
}
for (x = 1; x <= TESTNODES; x++) {
for (j = 1; j <= TESTNODES; j++) {
if (j == x) {
continue;
}
if (knet_h[x]->host_index[j]->status.reachable != 1) {
printf("knet failed to switch config for host %d\n", x);
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
}
flush_logs(logfds[0], stdout);
printf("Testing crypto config switch from 2 to 1\n");
for (i = 1; i <= TESTNODES; i++) {
if (knet_handle_crypto_use_config(knet_h[i], 1) < 0) {
printf("knet_handle_crypto_use_config (1) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
for (x = 0; x < seconds; x++){
flush_logs(logfds[0], stdout);
sleep(1);
}
for (x = 1; x <= TESTNODES; x++) {
for (j = 1; j <= TESTNODES; j++) {
if (j == x) {
continue;
}
if (knet_h[x]->host_index[j]->status.reachable != 1) {
printf("knet failed to switch config for host %d\n", x);
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
}
printf("Testing disable crypto config and allow clear traffic\n");
memset(&knet_handle_crypto_cfg, 0, sizeof(struct knet_handle_crypto_cfg));
strncpy(knet_handle_crypto_cfg.crypto_model, "none", sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, "none", sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
strncpy(knet_handle_crypto_cfg.crypto_hash_type, "none", sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
memset(knet_handle_crypto_cfg.private_key, 0, KNET_MAX_KEY_LEN);
knet_handle_crypto_cfg.private_key_len = KNET_MAX_KEY_LEN;
for (i = 1; i <= TESTNODES; i++) {
/*
* config2 is no longer in use
*/
if (knet_handle_crypto_set_config(knet_h[i], &knet_handle_crypto_cfg, 2) < 0) {
printf("knet_handle_crypto_set_config (2) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
/*
* allow clear traffic on RX on all nodes, before we change config to clear traffic
*/
if (knet_handle_crypto_rx_clear_traffic(knet_h[i], KNET_CRYPTO_RX_ALLOW_CLEAR_TRAFFIC)) {
printf("knet_handle_crypto_rx_clear_traffic failed: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
for (i = 1; i <= TESTNODES; i++) {
/*
* switch to clear traffic on RX on all nodes
*/
if (knet_handle_crypto_use_config(knet_h[i], 0) < 0) {
printf("knet_handle_crypto_use_config (0) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
for (i = 1; i <= TESTNODES; i++) {
/*
* config1 is no longer in use
*/
if (knet_handle_crypto_set_config(knet_h[i], &knet_handle_crypto_cfg, 1) < 0) {
printf("knet_handle_crypto_set_config (2) failed with correct config: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
for (i = 1; i <= TESTNODES; i++) {
for (x = 0; x < seconds; x++){
flush_logs(logfds[0], stdout);
sleep(1);
}
for (x = 1; x <= TESTNODES; x++) {
for (j = 1; j <= TESTNODES; j++) {
if (j == x) {
continue;
}
if (knet_h[x]->host_index[j]->status.reachable != 1) {
printf("knet failed to switch config for host %d\n", x);
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
}
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
knet_handle_stop_nodes(knet_h, TESTNODES);
}
int main(int argc, char *argv[])
{
struct knet_crypto_info crypto_list[16];
size_t crypto_list_entries;
size_t i;
memset(crypto_list, 0, sizeof(crypto_list));
if (knet_get_crypto_list(crypto_list, &crypto_list_entries) < 0) {
printf("knet_get_crypto_list failed: %s\n", strerror(errno));
return FAIL;
}
if (crypto_list_entries == 0) {
printf("no crypto modules detected. Skipping\n");
return SKIP;
}
for (i=0; i < crypto_list_entries; i++) {
test(crypto_list[i].name);
}
return PASS;
}
diff --git a/libknet/tests/fun_onwire_upgrade.c b/libknet/tests/fun_onwire_upgrade.c
index 40c4f1b5..b2ed5371 100644
--- a/libknet/tests/fun_onwire_upgrade.c
+++ b/libknet/tests/fun_onwire_upgrade.c
@@ -1,373 +1,373 @@
/*
* Copyright (C) 2020 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 <inttypes.h>
#include <pthread.h>
#include "libknet.h"
#include "compress.h"
#include "internals.h"
#include "netutils.h"
#include "test-common.h"
#define TESTNODES 3
static int upgrade_onwire_max_ver(knet_handle_t knet_h, uint8_t min, uint8_t max, int seconds)
{
if (knet_handle_disconnect_links(knet_h) < 0) {
return -1;
}
sleep(seconds);
knet_h->onwire_min_ver = min;
knet_h->onwire_max_ver = max;
if (knet_handle_reconnect_links(knet_h) < 0) {
return -1;
}
sleep(seconds);
return 0;
}
static void onwire_ver_callback_fn(void *private_data, uint8_t onwire_min_ver, uint8_t onwire_max_ver, uint8_t onwire_ver)
{
knet_handle_t knet_h = (knet_handle_t)private_data;
printf("Received callback from %p: min: %u max: %u current: %u\n", knet_h, onwire_min_ver, onwire_max_ver, onwire_ver);
}
static void test(void)
{
knet_handle_t knet_h[TESTNODES + 1];
int logfds[2];
int i,j;
- int seconds = 5;
+ int seconds = 10;
if (is_memcheck() || is_helgrind()) {
printf("Test suite is running under valgrind, adjusting wait_for_host timeout\n");
seconds = seconds * 16;
}
setup_logpipes(logfds);
knet_handle_start_nodes(knet_h, TESTNODES, logfds, KNET_LOG_DEBUG);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
knet_h[i]->onwire_ver_remap = 1;
if (knet_handle_enable_onwire_ver_notify(knet_h[i], (void *)&knet_h[i], onwire_ver_callback_fn) < 0) {
printf("Failed to install onwire ver callback\n");
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
flush_logs(logfds[0], stdout);
knet_handle_join_nodes(knet_h, TESTNODES, 1, AF_INET, KNET_TRANSPORT_UDP);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
for (j = 1; j <= TESTNODES; j++) {
if (j == i) {
continue;
}
if (knet_h[i]->host_index[j]->status.reachable != 1) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
}
}
printf("Test normal onwire upgrade from %u to %u\n", knet_h[1]->onwire_ver, knet_h[1]->onwire_ver + 1);
for (i = 1; i <= TESTNODES; i++) {
if (upgrade_onwire_max_ver(knet_h[i], knet_h[1]->onwire_ver, knet_h[1]->onwire_ver + 1, seconds) < 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
}
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
printf("node %u, onwire: %u min: %u max: %u\n", i, knet_h[i]->onwire_ver, knet_h[i]->onwire_min_ver, knet_h[i]->onwire_max_ver);
for (j = 1; j <= TESTNODES; j++) {
if (j == i) {
continue;
}
if ((knet_h[i]->host_index[j]->status.reachable != 1) || (knet_h[i]->onwire_ver != knet_h[1]->onwire_max_ver)) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
printf("Test onwire upgrade from %u to %u (all but one node)\n", knet_h[1]->onwire_ver, knet_h[1]->onwire_ver + 1);
for (i = 1; i < TESTNODES; i++) {
if (upgrade_onwire_max_ver(knet_h[i], knet_h[i]->onwire_ver, knet_h[i]->onwire_ver + 1, seconds) < 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
}
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
printf("node %u, onwire: %u min: %u max: %u\n", i, knet_h[i]->onwire_ver, knet_h[i]->onwire_min_ver, knet_h[i]->onwire_max_ver);
for (j = 1; j <= TESTNODES; j++) {
if (j == i) {
continue;
}
if ((knet_h[i]->host_index[j]->status.reachable != 1) || (knet_h[i]->onwire_ver == knet_h[1]->onwire_max_ver)) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
printf("Test onwire upgrade from %u to %u (all but one node - phase 2, node should be kicked out and remaining nodes should upgrade)\n", knet_h[1]->onwire_max_ver, knet_h[1]->onwire_max_ver + 1);
for (i = 1; i < TESTNODES; i++) {
if (upgrade_onwire_max_ver(knet_h[i], knet_h[i]->onwire_max_ver, knet_h[i]->onwire_max_ver + 1, seconds) < 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
flush_logs(logfds[0], stdout);
}
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
printf("node %u, onwire: %u min: %u max: %u\n", i, knet_h[i]->onwire_ver, knet_h[i]->onwire_min_ver, knet_h[i]->onwire_max_ver);
for (j = 1; j <= TESTNODES; j++) {
if (j == i) {
continue;
}
if (i == TESTNODES) {
/*
* highset node has been kicked out and should not
* be able to reach any other node
*/
if (knet_h[i]->host_index[j]->status.reachable != 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
} else {
/*
* all other nodes should detect the highest node unreachable
* and all the remaining nodes reachable
*/
if (j == TESTNODES) {
if (knet_h[i]->host_index[j]->status.reachable != 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
} else {
if (knet_h[i]->host_index[j]->status.reachable != 1) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
}
}
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
/*
* CHANGE THIS TEST if we decide to support downgrades
*/
printf("Testing node rejoining one version lower (cluster should reject the node)\n");
if (upgrade_onwire_max_ver(knet_h[TESTNODES], knet_h[1]->onwire_min_ver - 1, knet_h[1]->onwire_max_ver - 1, seconds) < 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
/*
* need more time here for membership to settle
*/
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
printf("node %u, onwire: %u min: %u max: %u\n", i, knet_h[i]->onwire_ver, knet_h[i]->onwire_min_ver, knet_h[i]->onwire_max_ver);
for (j = 1; j <= TESTNODES; j++) {
if (j == i) {
continue;
}
if (i == TESTNODES) {
/*
* highset node has been kicked out and should not
* be able to reach any other node
*/
if (knet_h[i]->host_index[j]->status.reachable != 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
} else {
/*
* all other nodes should detect the highest node unreachable
* and all the remaining nodes reachable
*/
if (j == TESTNODES) {
if (knet_h[i]->host_index[j]->status.reachable != 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
} else {
if (knet_h[i]->host_index[j]->status.reachable != 1) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
}
}
printf("Testing node rejoining with proper version (cluster should reform)\n");
if (upgrade_onwire_max_ver(knet_h[TESTNODES], knet_h[1]->onwire_min_ver, knet_h[1]->onwire_max_ver, seconds) < 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
/*
* need more time here for membership to settle
*/
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
printf("node %u, onwire: %u min: %u max: %u\n", i, knet_h[i]->onwire_ver, knet_h[i]->onwire_min_ver, knet_h[i]->onwire_max_ver);
for (j = 1; j <= TESTNODES; j++) {
if (j == i) {
continue;
}
if ((knet_h[i]->host_index[j]->status.reachable != 1) || (knet_h[i]->onwire_ver != knet_h[1]->onwire_max_ver)) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
printf("Testing node force onwire version\n");
for (i = 1; i <= TESTNODES; i++) {
if (knet_handle_set_onwire_ver(knet_h[i], knet_h[i]->onwire_min_ver) < 0) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
/*
* need more time here for membership to settle
*/
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
sleep(seconds);
flush_logs(logfds[0], stdout);
for (i = 1; i <= TESTNODES; i++) {
printf("node %u, onwire: %u min: %u max: %u\n", i, knet_h[i]->onwire_ver, knet_h[i]->onwire_min_ver, knet_h[i]->onwire_max_ver);
for (j = 1; j <= TESTNODES; j++) {
if (j == i) {
continue;
}
if ((knet_h[i]->host_index[j]->status.reachable != 1) || (knet_h[i]->onwire_ver != knet_h[1]->onwire_min_ver)) {
knet_handle_stop_nodes(knet_h, TESTNODES);
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
}
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
knet_handle_stop_nodes(knet_h, TESTNODES);
}
int main(int argc, char *argv[])
{
test();
return PASS;
}
diff --git a/libknet/tests/test-common.c b/libknet/tests/test-common.c
index 4ac74629..5aa57783 100644
--- a/libknet/tests/test-common.c
+++ b/libknet/tests/test-common.c
@@ -1,785 +1,771 @@
/*
* Copyright (C) 2016-2020 Red Hat, Inc. All rights reserved.
*
* Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/select.h>
#include "libknet.h"
#include "test-common.h"
static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
static int log_init = 0;
static pthread_mutex_t log_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_t log_thread;
static int log_thread_init = 0;
static int log_fds[2];
struct log_thread_data {
int logfd;
FILE *std;
};
static struct log_thread_data data;
static int _read_pipe(int fd, char **file, size_t *length)
{
char buf[4096];
int n;
int done = 0;
*file = NULL;
*length = 0;
memset(buf, 0, sizeof(buf));
while (!done) {
n = read(fd, buf, sizeof(buf));
if (n < 0) {
if (errno == EINTR)
continue;
if (*file)
free(*file);
return n;
}
if (n == 0 && (!*length))
return 0;
if (n == 0)
done = 1;
if (*file)
*file = realloc(*file, (*length) + n + done);
else
*file = malloc(n + done);
if (!*file)
return -1;
memmove((*file) + (*length), buf, n);
*length += (done + n);
}
/* Null terminator */
(*file)[(*length) - 1] = 0;
return 0;
}
int execute_shell(const char *command, char **error_string)
{
pid_t pid;
int status, err = 0;
int fd[2];
size_t size = 0;
if ((command == NULL) || (!error_string)) {
errno = EINVAL;
return FAIL;
}
*error_string = NULL;
err = pipe(fd);
if (err)
goto out_clean;
pid = fork();
if (pid < 0) {
err = pid;
goto out_clean;
}
if (pid) { /* parent */
close(fd[1]);
err = _read_pipe(fd[0], error_string, &size);
if (err)
goto out_clean0;
waitpid(pid, &status, 0);
if (!WIFEXITED(status)) {
err = -1;
goto out_clean0;
}
if (WIFEXITED(status) && WEXITSTATUS(status) != 0) {
err = WEXITSTATUS(status);
goto out_clean0;
}
goto out_clean0;
} else { /* child */
close(0);
close(1);
close(2);
close(fd[0]);
dup2(fd[1], 1);
dup2(fd[1], 2);
close(fd[1]);
execlp("/bin/sh", "/bin/sh", "-c", command, NULL);
exit(FAIL);
}
out_clean:
close(fd[1]);
out_clean0:
close(fd[0]);
return err;
}
int is_memcheck(void)
{
char *val;
val = getenv("KNETMEMCHECK");
if (val) {
if (!strncmp(val, "yes", 3)) {
return 1;
}
}
return 0;
}
int is_helgrind(void)
{
char *val;
val = getenv("KNETHELGRIND");
if (val) {
if (!strncmp(val, "yes", 3)) {
return 1;
}
}
return 0;
}
void set_scheduler(int policy)
{
struct sched_param sched_param;
int err;
err = sched_get_priority_max(policy);
if (err < 0) {
printf("Could not get maximum scheduler priority\n");
exit(FAIL);
}
sched_param.sched_priority = err;
err = sched_setscheduler(0, policy, &sched_param);
if (err < 0) {
printf("Could not set priority\n");
exit(FAIL);
}
return;
}
int setup_logpipes(int *logfds)
{
if (pipe2(logfds, O_CLOEXEC | O_NONBLOCK) < 0) {
printf("Unable to setup logging pipe\n");
exit(FAIL);
}
return PASS;
}
void close_logpipes(int *logfds)
{
close(logfds[0]);
logfds[0] = 0;
close(logfds[1]);
logfds[1] = 0;
}
void flush_logs(int logfd, FILE *std)
{
struct knet_log_msg msg;
int len;
while (1) {
len = read(logfd, &msg, sizeof(msg));
if (len != sizeof(msg)) {
/*
* clear errno to avoid incorrect propagation
*/
errno = 0;
return;
}
if (!msg.knet_h) {
/*
* this is harsh but this function is void
* and it is used also inside log_thread.
* this is the easiest to get out with an error
*/
fprintf(std, "NO HANDLE INFO IN LOG MSG!!\n");
abort();
}
msg.msg[sizeof(msg.msg) - 1] = 0;
fprintf(std, "[knet: %p]: [%s] %s: %.*s\n",
msg.knet_h,
knet_log_get_loglevel_name(msg.msglevel),
knet_log_get_subsystem_name(msg.subsystem),
KNET_MAX_LOG_MSG_SIZE, msg.msg);
}
}
static void *_logthread(void *args)
{
while (1) {
int num;
struct timeval tv = { 60, 0 };
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(data.logfd, &rfds);
num = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
if (num < 0) {
fprintf(data.std, "Unable select over logfd!\nHALTING LOGTHREAD!\n");
return NULL;
}
if (num == 0) {
fprintf(data.std, "[knet]: No logs in the last 60 seconds\n");
continue;
}
if (FD_ISSET(data.logfd, &rfds)) {
flush_logs(data.logfd, data.std);
}
}
}
int start_logthread(int logfd, FILE *std)
{
int savederrno = 0;
savederrno = pthread_mutex_lock(&log_thread_mutex);
if (savederrno) {
printf("Unable to get log_thread mutex lock\n");
return -1;
}
if (!log_thread_init) {
data.logfd = logfd;
data.std = std;
savederrno = pthread_create(&log_thread, 0, _logthread, NULL);
if (savederrno) {
printf("Unable to start logging thread: %s\n", strerror(savederrno));
pthread_mutex_unlock(&log_thread_mutex);
return -1;
}
log_thread_init = 1;
}
pthread_mutex_unlock(&log_thread_mutex);
return 0;
}
int stop_logthread(void)
{
int savederrno = 0;
void *retval;
savederrno = pthread_mutex_lock(&log_thread_mutex);
if (savederrno) {
printf("Unable to get log_thread mutex lock\n");
return -1;
}
if (log_thread_init) {
pthread_cancel(log_thread);
pthread_join(log_thread, &retval);
log_thread_init = 0;
}
pthread_mutex_unlock(&log_thread_mutex);
return 0;
}
static void stop_logging(void)
{
stop_logthread();
flush_logs(log_fds[0], stdout);
close_logpipes(log_fds);
}
int start_logging(FILE *std)
{
int savederrno = 0;
savederrno = pthread_mutex_lock(&log_mutex);
if (savederrno) {
printf("Unable to get log_mutex lock\n");
return -1;
}
if (!log_init) {
setup_logpipes(log_fds);
if (atexit(&stop_logging) != 0) {
printf("Unable to register atexit handler to stop logging: %s\n",
strerror(errno));
exit(FAIL);
}
if (start_logthread(log_fds[0], std) < 0) {
exit(FAIL);
}
log_init = 1;
}
pthread_mutex_unlock(&log_mutex);
return log_fds[1];
}
knet_handle_t knet_handle_start(int logfds[2], uint8_t log_level)
{
knet_handle_t knet_h = knet_handle_new(1, logfds[1], log_level, 0);
if (knet_h) {
printf("knet_handle_new at %p\n", knet_h);
return knet_h;
} else {
printf("knet_handle_new failed: %s\n", strerror(errno));
flush_logs(logfds[0], stdout);
close_logpipes(logfds);
exit(FAIL);
}
}
int knet_handle_reconnect_links(knet_handle_t knet_h)
{
size_t i, j;
knet_node_id_t host_ids[KNET_MAX_HOST];
uint8_t link_ids[KNET_MAX_LINK];
size_t host_ids_entries = 0, link_ids_entries = 0;
unsigned int enabled;
if (!knet_h) {
errno = EINVAL;
return -1;
}
if (knet_host_get_host_list(knet_h, host_ids, &host_ids_entries) < 0) {
printf("knet_host_get_host_list failed: %s\n", strerror(errno));
return -1;
}
for (i = 0; i < host_ids_entries; i++) {
if (knet_link_get_link_list(knet_h, host_ids[i], link_ids, &link_ids_entries)) {
printf("knet_link_get_link_list failed: %s\n", strerror(errno));
return -1;
}
for (j = 0; j < link_ids_entries; j++) {
if (knet_link_get_enable(knet_h, host_ids[i], link_ids[j], &enabled)) {
printf("knet_link_get_enable failed: %s\n", strerror(errno));
return -1;
}
if (!enabled) {
if (knet_link_set_enable(knet_h, host_ids[i], j, 1)) {
printf("knet_link_set_enable failed: %s\n", strerror(errno));
return -1;
}
}
}
}
return 0;
}
int knet_handle_disconnect_links(knet_handle_t knet_h)
{
size_t i, j;
knet_node_id_t host_ids[KNET_MAX_HOST];
uint8_t link_ids[KNET_MAX_LINK];
size_t host_ids_entries = 0, link_ids_entries = 0;
unsigned int enabled;
if (!knet_h) {
errno = EINVAL;
return -1;
}
if (knet_host_get_host_list(knet_h, host_ids, &host_ids_entries) < 0) {
printf("knet_host_get_host_list failed: %s\n", strerror(errno));
return -1;
}
for (i = 0; i < host_ids_entries; i++) {
if (knet_link_get_link_list(knet_h, host_ids[i], link_ids, &link_ids_entries)) {
printf("knet_link_get_link_list failed: %s\n", strerror(errno));
return -1;
}
for (j = 0; j < link_ids_entries; j++) {
if (knet_link_get_enable(knet_h, host_ids[i], link_ids[j], &enabled)) {
printf("knet_link_get_enable failed: %s\n", strerror(errno));
return -1;
}
if (enabled) {
if (knet_link_set_enable(knet_h, host_ids[i], j, 0)) {
printf("knet_link_set_enable failed: %s\n", strerror(errno));
return -1;
}
}
}
}
return 0;
}
int knet_handle_stop(knet_handle_t knet_h)
{
size_t i, j;
knet_node_id_t host_ids[KNET_MAX_HOST];
uint8_t link_ids[KNET_MAX_LINK];
size_t host_ids_entries = 0, link_ids_entries = 0;
unsigned int enabled;
if (!knet_h) {
errno = EINVAL;
return -1;
}
if (knet_handle_setfwd(knet_h, 0) < 0) {
printf("knet_handle_setfwd failed: %s\n", strerror(errno));
return -1;
}
if (knet_host_get_host_list(knet_h, host_ids, &host_ids_entries) < 0) {
printf("knet_host_get_host_list failed: %s\n", strerror(errno));
return -1;
}
for (i = 0; i < host_ids_entries; i++) {
if (knet_link_get_link_list(knet_h, host_ids[i], link_ids, &link_ids_entries)) {
printf("knet_link_get_link_list failed: %s\n", strerror(errno));
return -1;
}
for (j = 0; j < link_ids_entries; j++) {
if (knet_link_get_enable(knet_h, host_ids[i], link_ids[j], &enabled)) {
printf("knet_link_get_enable failed: %s\n", strerror(errno));
return -1;
}
if (enabled) {
if (knet_link_set_enable(knet_h, host_ids[i], j, 0)) {
printf("knet_link_set_enable failed: %s\n", strerror(errno));
return -1;
}
}
printf("clearing config for: %p host: %u link: %zu\n", knet_h, host_ids[i], j);
knet_link_clear_config(knet_h, host_ids[i], j);
}
if (knet_host_remove(knet_h, host_ids[i]) < 0) {
printf("knet_host_remove failed: %s\n", strerror(errno));
return -1;
}
}
if (knet_handle_free(knet_h)) {
printf("knet_handle_free failed: %s\n", strerror(errno));
return -1;
}
return 0;
}
static int _make_local_sockaddr(struct sockaddr_storage *lo, int offset, int family)
{
in_port_t port;
char portstr[32];
if (offset < 0) {
/*
* api_knet_link_set_config needs to access the API directly, but
* it does not send any traffic, so it´s safe to ask the kernel
* for a random port.
*/
port = 0;
} else {
/* Use the pid if we can. but makes sure its in a sensible range */
port = (getpid() + offset) % (65536-1024) + 1024;
}
sprintf(portstr, "%u", port);
memset(lo, 0, sizeof(struct sockaddr_storage));
printf("Using port %u\n", port);
if (family == AF_INET6) {
return knet_strtoaddr("::1", portstr, lo, sizeof(struct sockaddr_storage));
}
return knet_strtoaddr("127.0.0.1", portstr, lo, sizeof(struct sockaddr_storage));
}
int make_local_sockaddr(struct sockaddr_storage *lo, int offset)
{
return _make_local_sockaddr(lo, offset, AF_INET);
}
int make_local_sockaddr6(struct sockaddr_storage *lo, int offset)
{
return _make_local_sockaddr(lo, offset, AF_INET6);
}
int _knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
uint8_t transport, uint64_t flags, int family, int dynamic,
struct sockaddr_storage *lo)
{
int err = 0, savederrno = 0;
uint32_t port;
char portstr[32];
for (port = 1025; port < 65536; port++) {
sprintf(portstr, "%u", port);
memset(lo, 0, sizeof(struct sockaddr_storage));
if (family == AF_INET6) {
err = knet_strtoaddr("::1", portstr, lo, sizeof(struct sockaddr_storage));
} else {
err = knet_strtoaddr("127.0.0.1", portstr, lo, sizeof(struct sockaddr_storage));
}
if (err < 0) {
printf("Unable to convert loopback to sockaddr: %s\n", strerror(errno));
goto out;
}
errno = 0;
if (dynamic) {
err = knet_link_set_config(knet_h, host_id, link_id, transport, lo, NULL, flags);
} else {
err = knet_link_set_config(knet_h, host_id, link_id, transport, lo, lo, flags);
}
savederrno = errno;
if ((err < 0) && (savederrno != EADDRINUSE)) {
printf("Unable to configure link: %s\n", strerror(savederrno));
goto out;
}
if (!err) {
printf("Using port %u\n", port);
goto out;
}
}
if (err) {
printf("No more ports available\n");
}
out:
errno = savederrno;
return err;
}
void test_sleep(knet_handle_t knet_h, int seconds)
{
if (is_memcheck() || is_helgrind()) {
printf("Test suite is running under valgrind, adjusting sleep timers\n");
seconds = seconds * 16;
}
sleep(seconds);
}
int wait_for_host(knet_handle_t knet_h, uint16_t host_id, int seconds, int logfd, FILE *std)
{
int i = 0;
if (is_memcheck() || is_helgrind()) {
printf("Test suite is running under valgrind, adjusting wait_for_host timeout\n");
seconds = seconds * 16;
}
while (i < seconds) {
flush_logs(logfd, std);
if (knet_h->host_index[host_id]->status.reachable == 1) {
printf("Waiting for host to settle\n");
test_sleep(knet_h, 1);
return 0;
}
printf("waiting host %u to be reachable for %d more seconds\n", host_id, seconds - i);
sleep(1);
i++;
}
return -1;
}
int wait_for_packet(knet_handle_t knet_h, int seconds, int datafd, int logfd, FILE *std)
{
fd_set rfds;
struct timeval tv;
int err = 0, i = 0;
if (is_memcheck() || is_helgrind()) {
printf("Test suite is running under valgrind, adjusting wait_for_packet timeout\n");
seconds = seconds * 16;
}
try_again:
FD_ZERO(&rfds);
FD_SET(datafd, &rfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
err = select(datafd+1, &rfds, NULL, NULL, &tv);
/*
* on slow arches the first call to select can return 0.
* pick an arbitrary 10 times loop (multiplied by waiting seconds)
* before failing.
*/
if ((!err) && (i < seconds)) {
flush_logs(logfd, std);
i++;
goto try_again;
}
if ((err > 0) && (FD_ISSET(datafd, &rfds))) {
return 0;
}
errno = ETIMEDOUT;
return -1;
}
/*
* functional tests helpers
*/
void knet_handle_start_nodes(knet_handle_t knet_h[], uint8_t numnodes, int logfds[2], uint8_t log_level)
{
uint8_t i;
for (i = 1; i <= numnodes; i++) {
knet_h[i] = knet_handle_new(i, logfds[1], log_level, 0);
if (!knet_h[i]) {
printf("failed to create handle: %s\n", strerror(errno));
break;
} else {
printf("knet_h[%u] at %p\n", i, knet_h[i]);
}
}
if (i < numnodes) {
knet_handle_stop_nodes(knet_h, i);
exit(FAIL);
}
return;
}
void knet_handle_stop_nodes(knet_handle_t knet_h[], uint8_t numnodes)
{
uint8_t i;
for (i = 1; i <= numnodes; i++) {
printf("stopping handle %u at %p\n", i, knet_h[i]);
knet_handle_stop(knet_h[i]);
}
return;
}
void knet_handle_join_nodes(knet_handle_t knet_h[], uint8_t numnodes, uint8_t numlinks, int family, uint8_t transport)
{
uint8_t i, x, j;
struct sockaddr_storage src, dst;
+ int offset = 0;
+ int res;
for (i = 1; i <= numnodes; i++) {
for (j = 1; j <= numnodes; j++) {
/*
* don´t connect to itself
*/
if (j == i) {
continue;
}
printf("host %u adding host: %u\n", i, j);
if (knet_host_add(knet_h[i], j) < 0) {
printf("Unable to add host: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, numnodes);
exit(FAIL);
}
for (x = 0; x < numlinks; x++) {
- if (family == AF_INET6) {
- if (make_local_sockaddr6(&src, i + x) < 0) {
+ res = -1;
+ offset = 0;
+ while (i + x + offset++ < 65535 && res != 0) {
+ if (_make_local_sockaddr(&src, i + x + offset, family) < 0) {
printf("Unable to convert src to sockaddr: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, numnodes);
exit(FAIL);
}
- if (make_local_sockaddr6(&dst, j + x) < 0) {
+ if (_make_local_sockaddr(&dst, j + x + offset, family) < 0) {
printf("Unable to convert dst to sockaddr: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, numnodes);
exit(FAIL);
}
- } else {
- if (make_local_sockaddr(&src, i + x) < 0) {
- printf("Unable to convert src to sockaddr: %s\n", strerror(errno));
- knet_handle_stop_nodes(knet_h, numnodes);
- exit(FAIL);
- }
- if (make_local_sockaddr(&dst, j + x) < 0) {
- printf("Unable to convert dst to sockaddr: %s\n", strerror(errno));
- knet_handle_stop_nodes(knet_h, numnodes);
- exit(FAIL);
- }
+ res = knet_link_set_config(knet_h[i], j, x, transport, &src, &dst, 0);
}
-
printf("joining node %u with node %u via link %u src offset: %u dst offset: %u\n", i, j, x, i+x, j+x);
-
- if (knet_link_set_config(knet_h[i], j, x, transport, &src, &dst, 0) < 0) {
- printf("unable to configure link: %s\n", strerror(errno));
- knet_handle_stop_nodes(knet_h, numnodes);
- exit(FAIL);
- }
-
if (knet_link_set_enable(knet_h[i], j, x, 1) < 0) {
printf("unable to enable link: %s\n", strerror(errno));
knet_handle_stop_nodes(knet_h, numnodes);
exit(FAIL);
}
}
}
}
for (i = 1; i <= numnodes; i++) {
for (j = 1; j <= numnodes; j++) {
/*
* don´t wait for self
*/
if (j == i) {
continue;
}
if (wait_for_host(knet_h[i], j, (10 * numnodes) , knet_h[i]->logfd, stdout) < 0) {
printf("Cannot connect node %u to node %u: %s\n", i, j, strerror(errno));
knet_handle_stop_nodes(knet_h, numnodes);
exit(FAIL);
}
}
}
return;
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jan 25, 12:01 PM (1 d, 20 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1322486
Default Alt Text
(37 KB)

Event Timeline