Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F3153020
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/libknet/tests/Makefile.am b/libknet/tests/Makefile.am
index e2a05382..c1d203cd 100644
--- a/libknet/tests/Makefile.am
+++ b/libknet/tests/Makefile.am
@@ -1,89 +1,91 @@
#
# Copyright (C) 2016 Red Hat, Inc. All rights reserved.
#
# Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
#
# This software licensed under GPL-2.0+, LGPL-2.0+
#
MAINTAINERCLEANFILES = Makefile.in
include $(top_srcdir)/build-aux/check.mk
include $(top_srcdir)/libknet/tests/api-check.mk
EXTRA_DIST = \
api-test-coverage \
api-check.mk
AM_CPPFLAGS = -I$(top_srcdir)/libknet
# override global LIBS that pulls in lots of craft we don't need here
LIBS =
LDADD = $(top_builddir)/libknet/libknet.la
noinst_HEADERS = \
test-common.h
# the order of those tests is NOT random.
# some functions can only be tested properly after some dependents
# API have been validated upfront.
check_PROGRAMS = \
$(api_checks) \
$(int_checks) \
$(fun_checks)
int_checks = \
int_crypto_test \
int_timediff_test
fun_checks =
benchmarks = \
crypto_bench_test \
knet_bench_test
noinst_PROGRAMS = \
pckt_test \
$(benchmarks) \
$(check_PROGRAMS)
noinst_SCRIPTS = \
api-test-coverage
TESTS = $(check_PROGRAMS)
check-local: check-api-test-coverage
check-api-test-coverage:
chmod u+x $(top_srcdir)/libknet/tests/api-test-coverage
$(top_srcdir)/libknet/tests/api-test-coverage $(top_srcdir) $(top_builddir)
pckt_test_SOURCES = pckt_test.c
int_crypto_test_SOURCES = int_crypto.c \
../crypto.c \
../nsscrypto.c \
../logging.c \
test-common.c
int_crypto_test_CFLAGS = $(nss_CFLAGS)
int_crypto_test_LDFLAGS = $(nss_LIBS)
int_timediff_test_SOURCES = int_timediff.c
crypto_bench_test_SOURCES = crypto_bench.c \
../crypto.c \
../nsscrypto.c \
../logging.c \
test-common.c
crypto_bench_test_CFLAGS = $(nss_CFLAGS)
crypto_bench_test_LDFLAGS = $(nss_LIBS)
knet_bench_test_SOURCES = knet_bench.c \
test-common.c \
- ../compat.c
+ ../common.c \
+ ../logging.c \
+ ../transport_common.c
diff --git a/libknet/tests/knet_bench.c b/libknet/tests/knet_bench.c
index 527725c4..a5e10808 100644
--- a/libknet/tests/knet_bench.c
+++ b/libknet/tests/knet_bench.c
@@ -1,663 +1,664 @@
/*
* Copyright (C) 2016 Red Hat, Inc. All rights reserved.
*
* Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
*
* This software licensed under GPL-2.0+, LGPL-2.0+
*/
#include "config.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>
#include "libknet.h"
#include "internals.h"
#include "netutils.h"
+#include "transports.h"
#include "test-common.h"
#define MAX_NODES 128
static int senderid = -1;
static knet_handle_t knet_h;
static int datafd = 0;
static int8_t channel = 0;
static int globallistener = 0;
static int continous = 0;
static struct sockaddr_storage allv4;
static struct sockaddr_storage allv6;
static int broadcast_test = 1;
static pthread_t rx_thread = (pthread_t)NULL;
static char *rx_buf[PCKT_FRAG_MAX];
static int shutdown_in_progress = 0;
static pthread_mutex_t shutdown_mutex = PTHREAD_MUTEX_INITIALIZER;
#define TEST_PING 0
#define TEST_PING_AND_DATA 1
#define TEST_PERF 2
static int test_type = TEST_PING;
struct node {
int nodeid;
int links;
struct sockaddr_storage address[KNET_MAX_LINK];
};
static void print_help(void)
{
printf("knet_bench usage:\n");
printf(" -h print this help (no really)\n");
printf(" -d enable debug logs (default INFO)\n");
printf(" -c [implementation]:[crypto]:[hashing] crypto configuration. (default disabled)\n");
printf(" Example: -c nss:aes128:sha1\n");
printf(" -p [active|passive|rr] (default: passive)\n");
printf(" -P [udp|sctp] (default: udp) protocol (transport) to use\n");
printf(" -t [nodeid] This nodeid (required)\n");
printf(" -n [nodeid],[link1_ip_addr],[link2_..] Other nodes information (at least one required)\n");
printf(" Example: -t 1,192.168.8.1,3ffe::8:1,..\n");
printf(" can be repeated up to %d and should contain also the localnode info\n", MAX_NODES);
printf(" -b [port] baseport (default: 50000)\n");
printf(" -l enable global listener on 0.0.0.0/:: (default: off, incompatible with -o)\n");
printf(" -o enable baseport offset per nodeid\n");
printf(" -w dont wait for all nodes to be up before starting the test (default: wait)\n");
printf(" -T [ping|ping_data|perf] test type (default: ping)\n");
printf(" ping: will wait for all hosts to join the knet network, sleep 5 seconds and quit\n");
printf(" ping_data: will wait for all hosts to join the knet network, sends some data to all nodes and quit\n");
printf(" perf: will wait for all hosts to join the knet network, perform a series of benchmarks and quit\n");
printf(" -s nodeid that will generate traffic for benchmarks\n");
printf(" -C repeat the test continously (default: off)\n");
}
static void parse_nodes(char *nodesinfo[MAX_NODES], int onidx, int port, struct node nodes[MAX_NODES], int thisnodeid, int *thisidx)
{
int i;
char *temp = NULL;
char port_str[10];
memset(port_str, 0, sizeof(port_str));
sprintf(port_str, "%d", port);
for (i = 0; i < onidx; i++) {
nodes[i].nodeid = atoi(strtok(nodesinfo[i], ","));
if ((nodes[i].nodeid < 0) || (nodes[i].nodeid > KNET_MAX_HOST)) {
printf("Invalid nodeid: %d (0 - %d)\n", nodes[i].nodeid, KNET_MAX_HOST);
exit(FAIL);
}
if (thisnodeid == nodes[i].nodeid) {
*thisidx = i;
}
while((temp = strtok(NULL, ","))) {
if (nodes[i].links == KNET_MAX_LINK) {
printf("Too many links configured. Max %d\n", KNET_MAX_LINK);
exit(FAIL);
}
if (knet_strtoaddr(temp, port_str,
&nodes[i].address[nodes[i].links],
sizeof(struct sockaddr_storage)) < 0) {
printf("Unable to convert %s to sockaddress\n", temp);
exit(FAIL);
}
nodes[i].links++;
}
}
if (knet_strtoaddr("0.0.0.0", port_str, &allv4, sizeof(struct sockaddr_storage)) < 0) {
printf("Unable to convert 0.0.0.0 to sockaddress\n");
exit(FAIL);
}
if (knet_strtoaddr("::", port_str, &allv6, sizeof(struct sockaddr_storage)) < 0) {
printf("Unable to convert :: to sockaddress\n");
exit(FAIL);
}
for (i = 1; i < onidx; i++) {
if (nodes[0].links != nodes[i].links) {
printf("knet_bench does not support unbalanced link configuration\n");
exit(FAIL);
}
}
return;
}
static int private_data;
static void sock_notify(void *pvt_data,
int local_datafd,
int8_t local_channel,
uint8_t tx_rx,
int error,
int errorno)
{
printf("Error (%d - %d - %s) from socket: %d\n", error, errorno, strerror(errno), local_datafd);
return;
}
static void setup_knet(int argc, char *argv[])
{
int logfd;
int rv;
char *cryptocfg = NULL, *policystr = NULL, *protostr = NULL;
char *othernodeinfo[MAX_NODES];
struct node nodes[MAX_NODES];
int thisnodeid = -1;
int thisidx = -1;
int onidx = 0;
int debug = KNET_LOG_INFO;
int port = 50000, portoffset = 0;
int thisport = 0, otherport = 0;
int thisnewport = 0, othernewport = 0;
struct sockaddr_in *so_in;
struct sockaddr_in6 *so_in6;
struct sockaddr_storage *src;
int i, link_idx, allnodesup = 0;
int policy = KNET_LINK_POLICY_PASSIVE, policyfound = 0;
int protocol = KNET_TRANSPORT_UDP, protofound = 0;
int wait = 1;
struct knet_handle_crypto_cfg knet_handle_crypto_cfg;
char *cryptomodel = NULL, *cryptotype = NULL, *cryptohash = NULL;
memset(nodes, 0, sizeof(nodes));
while ((rv = getopt(argc, argv, "CT:s:ldowb:t:n:c:p:P:h")) != EOF) {
switch(rv) {
case 'h':
print_help();
exit(PASS);
break;
case 'd':
debug = KNET_LOG_DEBUG;
break;
case 'c':
if (cryptocfg) {
printf("Error: -c can only be specified once\n");
exit(FAIL);
}
cryptocfg = optarg;
break;
case 'p':
if (policystr) {
printf("Error: -p can only be specified once\n");
exit(FAIL);
}
policystr = optarg;
if (!strcmp(policystr, "active")) {
policy = KNET_LINK_POLICY_ACTIVE;
policyfound = 1;
}
if (!strcmp(policystr, "rr")) {
policy = KNET_LINK_POLICY_RR;
policyfound = 1;
}
if (!strcmp(policystr, "passive")) {
policy = KNET_LINK_POLICY_PASSIVE;
policyfound = 1;
}
if (!policyfound) {
printf("Error: invalid policy %s specified. -p accepts active|passive|rr\n", policystr);
exit(FAIL);
}
break;
case 'P':
if (protostr) {
printf("Error: -P can only be specified once\n");
exit(FAIL);
}
protostr = optarg;
if (!strcmp(protostr, "udp")) {
protocol = KNET_TRANSPORT_UDP;
protofound = 1;
}
if (!strcmp(protostr, "sctp")) {
protocol = KNET_TRANSPORT_SCTP;
protofound = 1;
}
if (!protofound) {
printf("Error: invalid protocol %s specified. -P accepts udp|sctp\n", policystr);
exit(FAIL);
}
break;
case 't':
if (thisnodeid >= 0) {
printf("Error: -t can only be specified once\n");
exit(FAIL);
}
thisnodeid = atoi(optarg);
if ((thisnodeid < 0) || (thisnodeid > 65536)) {
printf("Error: -t nodeid out of range %d (1 - 65536)\n", thisnodeid);
exit(FAIL);
}
break;
case 'n':
if (onidx == MAX_NODES) {
printf("Error: too many other nodes. Max %d\n", MAX_NODES);
exit(FAIL);
}
othernodeinfo[onidx] = optarg;
onidx++;
break;
case 'b':
port = atoi(optarg);
if ((port < 1) || (port > 65536)) {
printf("Error: port %d out of range (1 - 65536)\n", port);
exit(FAIL);
}
case 'o':
if (globallistener) {
printf("Error: -l cannot be used with -o\n");
exit(FAIL);
}
portoffset = 1;
break;
case 'l':
if (portoffset) {
printf("Error: -o cannot be used with -l\n");
exit(FAIL);
}
globallistener = 1;
break;
case 'w':
wait = 0;
break;
case 's':
if (senderid >= 0) {
printf("Error: -s can only be specified once\n");
exit(FAIL);
}
senderid = atoi(optarg);
if ((senderid < 0) || (senderid > 65536)) {
printf("Error: -s nodeid out of range %d (1 - 65536)\n", senderid);
exit(FAIL);
}
break;
case 'T':
if (!strcmp("ping", optarg)) {
test_type = TEST_PING;
}
if (!strcmp("ping_data", optarg)) {
test_type = TEST_PING_AND_DATA;
}
if (!strcmp("perf", optarg)) {
test_type = TEST_PERF;
}
break;
case 'C':
continous = 1;
break;
default:
break;
}
}
if (thisnodeid < 0) {
printf("Who am I?!? missing -t from command line?\n");
exit(FAIL);
}
if (onidx < 1) {
printf("no other nodes configured?!? missing -n from command line\n");
exit(FAIL);
}
parse_nodes(othernodeinfo, onidx, port, nodes, thisnodeid, &thisidx);
if (thisidx < 0) {
printf("no config for this node found\n");
exit(FAIL);
}
if (senderid >= 0) {
for (i=0; i < onidx; i++) {
if (senderid == nodes[i].nodeid) {
break;
}
}
if (i == onidx) {
printf("Unable to find senderid in nodelist\n");
exit(FAIL);
}
}
if ((test_type == TEST_PERF) && (senderid < 0)) {
printf("Error: performance test requires -s to be set (for now)\n");
exit(FAIL);
}
logfd = start_logging(stdout);
knet_h = knet_handle_new(thisnodeid, logfd, debug);
if (!knet_h) {
printf("Unable to knet_handle_new: %s\n", strerror(errno));
exit(FAIL);
}
if (cryptocfg) {
memset(&knet_handle_crypto_cfg, 0, sizeof(knet_handle_crypto_cfg));
cryptomodel = strtok(cryptocfg, ":");
cryptotype = strtok(NULL, ":");
cryptohash = strtok(NULL, ":");
if (cryptomodel) {
strncpy(knet_handle_crypto_cfg.crypto_model, cryptomodel, sizeof(knet_handle_crypto_cfg.crypto_model) - 1);
}
if (cryptotype) {
strncpy(knet_handle_crypto_cfg.crypto_cipher_type, cryptotype, sizeof(knet_handle_crypto_cfg.crypto_cipher_type) - 1);
}
if (cryptohash) {
strncpy(knet_handle_crypto_cfg.crypto_hash_type, cryptohash, sizeof(knet_handle_crypto_cfg.crypto_hash_type) - 1);
}
knet_handle_crypto_cfg.private_key_len = KNET_MAX_KEY_LEN;
if (knet_handle_crypto(knet_h, &knet_handle_crypto_cfg)) {
printf("Unable to init crypto\n");
exit(FAIL);
}
}
if (knet_handle_enable_sock_notify(knet_h, &private_data, sock_notify) < 0) {
printf("knet_handle_enable_sock_notify failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
exit(FAIL);
}
datafd = 0;
channel = -1;
if (knet_handle_add_datafd(knet_h, &datafd, &channel) < 0) {
printf("knet_handle_add_datafd failed: %s\n", strerror(errno));
knet_handle_free(knet_h);
exit(FAIL);
}
for (i=0; i < onidx; i++) {
if (i == thisidx) {
continue;
}
if (knet_host_add(knet_h, nodes[i].nodeid) < 0) {
printf("knet_host_add failed: %s\n", strerror(errno));
exit(FAIL);
}
if (knet_host_set_policy(knet_h, nodes[i].nodeid, policy) < 0) {
printf("knet_host_set_policy failed: %s\n", strerror(errno));
exit(FAIL);
}
for (link_idx = 0; link_idx < nodes[i].links; link_idx++) {
if (portoffset) {
if (nodes[thisidx].address[link_idx].ss_family == AF_INET) {
so_in = (struct sockaddr_in *)&nodes[thisidx].address[link_idx];
thisport = ntohs(so_in->sin_port);
thisnewport = thisport + nodes[i].nodeid;
so_in->sin_port = (htons(thisnewport));
so_in = (struct sockaddr_in *)&nodes[i].address[link_idx];
otherport = ntohs(so_in->sin_port);
othernewport = otherport + nodes[thisidx].nodeid;
so_in->sin_port = (htons(othernewport));
} else {
so_in6 = (struct sockaddr_in6 *)&nodes[thisidx].address[link_idx];
thisport = ntohs(so_in6->sin6_port);
thisnewport = thisport + nodes[i].nodeid;
so_in6->sin6_port = (htons(thisnewport));
so_in6 = (struct sockaddr_in6 *)&nodes[i].address[link_idx];
otherport = ntohs(so_in6->sin6_port);
othernewport = otherport + nodes[thisidx].nodeid;
so_in6->sin6_port = (htons(othernewport));
}
}
if (!globallistener) {
src = &nodes[thisidx].address[link_idx];
} else {
if (nodes[thisidx].address[link_idx].ss_family == AF_INET) {
src = &allv4;
} else {
src = &allv6;
}
}
if (knet_link_set_config(knet_h, nodes[i].nodeid, link_idx,
protocol, src,
&nodes[i].address[link_idx]) < 0) {
printf("Unable to configure link: %s\n", strerror(errno));
exit(FAIL);
}
if (portoffset) {
if (nodes[thisidx].address[link_idx].ss_family == AF_INET) {
so_in = (struct sockaddr_in *)&nodes[thisidx].address[link_idx];
so_in->sin_port = (htons(thisport));
so_in = (struct sockaddr_in *)&nodes[i].address[link_idx];
so_in->sin_port = (htons(otherport));
} else {
so_in6 = (struct sockaddr_in6 *)&nodes[thisidx].address[link_idx];
so_in6->sin6_port = (htons(thisport));
so_in6 = (struct sockaddr_in6 *)&nodes[i].address[link_idx];
so_in6->sin6_port = (htons(otherport));
}
}
if (knet_link_set_enable(knet_h, nodes[i].nodeid, link_idx, 1) < 0) {
printf("knet_link_set_enable failed: %s\n", strerror(errno));
exit(FAIL);
}
}
}
if (knet_handle_setfwd(knet_h, 1) < 0) {
printf("knet_handle_setfwd failed: %s\n", strerror(errno));
exit(FAIL);
}
if (wait) {
while(!allnodesup) {
allnodesup = 1;
for (i=0; i < onidx; i++) {
if (i == thisidx) {
continue;
}
if(knet_h->host_index[nodes[i].nodeid]->status.reachable != 1) {
printf("waiting host %d to be reachable\n", nodes[i].nodeid);
allnodesup = 0;
}
}
if (!allnodesup) {
sleep(1);
}
}
sleep(1);
}
}
static int ping_dst_host_filter(void *pvt_data,
const unsigned char *outdata,
ssize_t outdata_len,
uint8_t tx_rx,
knet_node_id_t this_host_id,
knet_node_id_t src_host_id,
int8_t *dst_channel,
knet_node_id_t *dst_host_ids,
size_t *dst_host_ids_entries)
{
if (broadcast_test) {
return 1;
}
if (tx_rx == KNET_NOTIFY_TX) {
memmove(&dst_host_ids[0], outdata, 2);
} else {
dst_host_ids[0] = this_host_id;
}
*dst_host_ids_entries = 1;
return 0;
}
static void *_rx_thread(void *args)
{
fd_set rfds;
ssize_t len;
struct timeval tv;
struct sockaddr_storage address[PCKT_FRAG_MAX];
struct mmsghdr msg[PCKT_FRAG_MAX];
struct iovec iov_in[PCKT_FRAG_MAX];
int i, msg_recv;
for (i = 0; i < PCKT_FRAG_MAX; i++) {
rx_buf[i] = malloc(KNET_MAX_PACKET_SIZE);
if (!rx_buf[i]) {
printf("RXT: Unable to malloc!\n");
return NULL;
}
memset(rx_buf[i], 0, KNET_MAX_PACKET_SIZE);
iov_in[i].iov_base = (void *)rx_buf[i];
iov_in[i].iov_len = KNET_MAX_PACKET_SIZE;
memset(&msg[i].msg_hdr, 0, sizeof(struct msghdr));
msg[i].msg_hdr.msg_name = &address[i];
msg[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_storage);
msg[i].msg_hdr.msg_iov = &iov_in[i];
msg[i].msg_hdr.msg_iovlen = 1;
}
select_loop:
tv.tv_sec = 5;
tv.tv_usec = 0;
FD_ZERO(&rfds);
FD_SET(datafd, &rfds);
len = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
if (len < 0) {
printf("RXT: Unable select over datafd\nHALTING RX THREAD!\n");
return NULL;
}
if (!len) {
printf("RXT: No data for the past 5 seconds\n");
}
if (FD_ISSET(datafd, &rfds)) {
- msg_recv = recvmmsg(datafd, msg, PCKT_FRAG_MAX, MSG_DONTWAIT | MSG_NOSIGNAL, NULL);
+ msg_recv = _recvmmsg(datafd, &msg[0], PCKT_FRAG_MAX, MSG_DONTWAIT | MSG_NOSIGNAL);
if (msg_recv < 0) {
printf("RXT: error from recvmmsg: %s\n", strerror(errno));
}
for (i = 0; i < msg_recv; i++) {
if (msg[i].msg_len == 0) {
printf("RXT: received 0 bytes message?\n");
}
if (test_type == TEST_PING_AND_DATA) {
printf("received %lu bytes message: %s\n", (long)msg[i].msg_len, (char *)msg[i].msg_hdr.msg_iov->iov_base);
}
/*
* do stats here
*/
}
}
goto select_loop;
return NULL;
}
static void setup_data_txrx_common(void)
{
if (!rx_thread) {
if (knet_handle_enable_filter(knet_h, NULL, ping_dst_host_filter)) {
printf("Unable to enable dst_host_filter: %s\n", strerror(errno));
exit(FAIL);
}
printf("Setting up rx thread\n");
if (pthread_create(&rx_thread, 0, _rx_thread, NULL)) {
printf("Unable to start rx thread\n");
exit(FAIL);
}
}
}
static void stop_rx_thread(void)
{
void *retval;
int i;
if (rx_thread) {
printf("Shutting down rx thread\n");
pthread_cancel(rx_thread);
pthread_join(rx_thread, &retval);
for (i = 0; i < PCKT_FRAG_MAX; i ++) {
free(rx_buf[i]);
}
}
}
static void send_ping_data(void)
{
const char *buf = "Hello world!\x0";
ssize_t len = strlen(buf);
if (knet_send(knet_h, buf, len, channel) != len) {
printf("Error sending hello world: %s\n", strerror(errno));
}
sleep(1);
}
static void cleanup_all(void)
{
if (pthread_mutex_lock(&shutdown_mutex)) {
return;
}
if (shutdown_in_progress) {
pthread_mutex_unlock(&shutdown_mutex);
return;
}
shutdown_in_progress = 1;
pthread_mutex_unlock(&shutdown_mutex);
if (rx_thread) {
stop_rx_thread();
}
knet_handle_stop(knet_h);
}
static void sigint_handler(int signum)
{
printf("Cleaning up... got signal: %d\n", signum);
cleanup_all();
exit(PASS);
}
int main(int argc, char *argv[])
{
if (signal(SIGINT, sigint_handler) == SIG_ERR) {
printf("Unable to configure SIGINT handler\n");
exit(FAIL);
}
need_root();
setup_knet(argc, argv);
restart:
switch(test_type) {
default:
case TEST_PING: /* basic ping, no data */
sleep(5);
break;
case TEST_PING_AND_DATA:
setup_data_txrx_common();
send_ping_data();
break;
case TEST_PERF:
setup_data_txrx_common();
break;
}
if (continous) {
goto restart;
}
cleanup_all();
return PASS;
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Tue, Feb 25, 7:43 AM (1 d, 13 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1464747
Default Alt Text
(20 KB)
Attached To
Mode
rK kronosnet
Attached
Detach File
Event Timeline
Log In to Comment