2 * Copyright (C) 2016-2019 Red Hat, Inc. All rights reserved.
4 * Author: Fabio M. Di Nitto <fabbione@kronosnet.org>
6 * This software licensed under GPL-2.0+
16 #include <sys/types.h>
20 #include <sys/select.h>
23 #include "test-common.h"
25 static pthread_mutex_t log_mutex
= PTHREAD_MUTEX_INITIALIZER
;
26 static int log_init
= 0;
27 static pthread_mutex_t log_thread_mutex
= PTHREAD_MUTEX_INITIALIZER
;
28 static pthread_t log_thread
;
29 static int log_thread_init
= 0;
30 static int log_fds
[2];
31 struct log_thread_data
{
35 static struct log_thread_data data
;
36 static pthread_mutex_t shutdown_mutex
= PTHREAD_MUTEX_INITIALIZER
;
37 static int stop_in_progress
= 0;
39 static int _read_pipe(int fd
, char **file
, size_t *length
)
48 memset(buf
, 0, sizeof(buf
));
52 n
= read(fd
, buf
, sizeof(buf
));
64 if (n
== 0 && (!*length
))
71 *file
= realloc(*file
, (*length
) + n
+ done
);
73 *file
= malloc(n
+ done
);
78 memmove((*file
) + (*length
), buf
, n
);
79 *length
+= (done
+ n
);
83 (*file
)[(*length
) - 1] = 0;
88 int execute_shell(const char *command
, char **error_string
)
95 if ((command
== NULL
) || (!error_string
)) {
100 *error_string
= NULL
;
112 if (pid
) { /* parent */
115 err
= _read_pipe(fd
[0], error_string
, &size
);
119 waitpid(pid
, &status
, 0);
120 if (!WIFEXITED(status
)) {
124 if (WIFEXITED(status
) && WEXITSTATUS(status
) != 0) {
125 err
= WEXITSTATUS(status
);
139 execlp("/bin/sh", "/bin/sh", "-c", command
, NULL
);
151 int is_memcheck(void)
155 val
= getenv("KNETMEMCHECK");
158 if (!strncmp(val
, "yes", 3)) {
166 int is_helgrind(void)
170 val
= getenv("KNETHELGRIND");
173 if (!strncmp(val
, "yes", 3)) {
181 void set_scheduler(int policy
)
183 struct sched_param sched_param
;
186 err
= sched_get_priority_max(policy
);
188 printf("Could not get maximum scheduler priority\n");
191 sched_param
.sched_priority
= err
;
192 err
= sched_setscheduler(0, policy
, &sched_param
);
194 printf("Could not set priority\n");
200 int setup_logpipes(int *logfds
)
202 if (pipe2(logfds
, O_CLOEXEC
| O_NONBLOCK
) < 0) {
203 printf("Unable to setup logging pipe\n");
210 void close_logpipes(int *logfds
)
218 void flush_logs(int logfd
, FILE *std
)
220 struct knet_log_msg msg
;
224 len
= read(logfd
, &msg
, sizeof(msg
));
225 if (len
!= sizeof(msg
)) {
227 * clear errno to avoid incorrect propagation
235 * this is harsh but this function is void
236 * and it is used also inside log_thread.
237 * this is the easiest to get out with an error
239 fprintf(std
, "NO HANDLE INFO IN LOG MSG!!\n");
243 msg
.msg
[sizeof(msg
.msg
) - 1] = 0;
245 fprintf(std
, "[knet]: [%s] %s: %.*s\n",
246 knet_log_get_loglevel_name(msg
.msglevel
),
247 knet_log_get_subsystem_name(msg
.subsystem
),
248 KNET_MAX_LOG_MSG_SIZE
, msg
.msg
);
252 static void *_logthread(void *args
)
256 struct timeval tv
= { 60, 0 };
260 FD_SET(data
.logfd
, &rfds
);
262 num
= select(FD_SETSIZE
, &rfds
, NULL
, NULL
, &tv
);
264 fprintf(data
.std
, "Unable select over logfd!\nHALTING LOGTHREAD!\n");
268 fprintf(data
.std
, "[knet]: No logs in the last 60 seconds\n");
271 if (FD_ISSET(data
.logfd
, &rfds
)) {
272 flush_logs(data
.logfd
, data
.std
);
277 int start_logthread(int logfd
, FILE *std
)
281 savederrno
= pthread_mutex_lock(&log_thread_mutex
);
283 printf("Unable to get log_thread mutex lock\n");
287 if (!log_thread_init
) {
291 savederrno
= pthread_create(&log_thread
, 0, _logthread
, NULL
);
293 printf("Unable to start logging thread: %s\n", strerror(savederrno
));
294 pthread_mutex_unlock(&log_thread_mutex
);
300 pthread_mutex_unlock(&log_thread_mutex
);
304 int stop_logthread(void)
309 savederrno
= pthread_mutex_lock(&log_thread_mutex
);
311 printf("Unable to get log_thread mutex lock\n");
315 if (log_thread_init
) {
316 pthread_cancel(log_thread
);
317 pthread_join(log_thread
, &retval
);
321 pthread_mutex_unlock(&log_thread_mutex
);
325 static void stop_logging(void)
328 flush_logs(log_fds
[0], stdout
);
329 close_logpipes(log_fds
);
332 int start_logging(FILE *std
)
336 savederrno
= pthread_mutex_lock(&log_mutex
);
338 printf("Unable to get log_mutex lock\n");
343 setup_logpipes(log_fds
);
345 if (atexit(&stop_logging
) != 0) {
346 printf("Unable to register atexit handler to stop logging: %s\n",
351 if (start_logthread(log_fds
[0], std
) < 0) {
358 pthread_mutex_unlock(&log_mutex
);
363 knet_handle_t
knet_handle_start(int logfds
[2], uint8_t log_level
)
365 knet_handle_t knet_h
= knet_handle_new(1, logfds
[1], log_level
, 0);
370 printf("knet_handle_new failed: %s\n", strerror(errno
));
371 flush_logs(logfds
[0], stdout
);
372 close_logpipes(logfds
);
377 int knet_handle_stop(knet_handle_t knet_h
)
381 knet_node_id_t host_ids
[KNET_MAX_HOST
];
382 uint8_t link_ids
[KNET_MAX_LINK
];
383 size_t host_ids_entries
= 0, link_ids_entries
= 0;
384 struct knet_link_status status
;
386 savederrno
= pthread_mutex_lock(&shutdown_mutex
);
388 printf("Unable to get shutdown mutex lock\n");
392 if (stop_in_progress
) {
393 pthread_mutex_unlock(&shutdown_mutex
);
398 stop_in_progress
= 1;
400 pthread_mutex_unlock(&shutdown_mutex
);
407 if (knet_handle_setfwd(knet_h
, 0) < 0) {
408 printf("knet_handle_setfwd failed: %s\n", strerror(errno
));
412 if (knet_host_get_host_list(knet_h
, host_ids
, &host_ids_entries
) < 0) {
413 printf("knet_host_get_host_list failed: %s\n", strerror(errno
));
417 for (i
= 0; i
< host_ids_entries
; i
++) {
418 if (knet_link_get_link_list(knet_h
, host_ids
[i
], link_ids
, &link_ids_entries
)) {
419 printf("knet_link_get_link_list failed: %s\n", strerror(errno
));
422 for (j
= 0; j
< link_ids_entries
; j
++) {
423 if (knet_link_get_status(knet_h
, host_ids
[i
], link_ids
[j
], &status
, sizeof(struct knet_link_status
))) {
424 printf("knet_link_get_status failed: %s\n", strerror(errno
));
427 if (status
.enabled
) {
428 if (knet_link_set_enable(knet_h
, host_ids
[i
], j
, 0)) {
429 printf("knet_link_set_enable failed: %s\n", strerror(errno
));
433 knet_link_clear_config(knet_h
, host_ids
[i
], j
);
435 if (knet_host_remove(knet_h
, host_ids
[i
]) < 0) {
436 printf("knet_host_remove failed: %s\n", strerror(errno
));
441 if (knet_handle_free(knet_h
)) {
442 printf("knet_handle_free failed: %s\n", strerror(errno
));
448 static int _make_local_sockaddr(struct sockaddr_storage
*lo
, uint16_t offset
, int family
)
453 /* Use the pid if we can. but makes sure its in a sensible range */
454 port
= (uint32_t)getpid() + offset
;
459 port
= port
& 0xFFFF;
461 sprintf(portstr
, "%u", port
);
462 memset(lo
, 0, sizeof(struct sockaddr_storage
));
463 printf("Using port %u\n", port
);
465 if (family
== AF_INET6
) {
466 return knet_strtoaddr("::1", portstr
, lo
, sizeof(struct sockaddr_storage
));
468 return knet_strtoaddr("127.0.0.1", portstr
, lo
, sizeof(struct sockaddr_storage
));
471 int make_local_sockaddr(struct sockaddr_storage
*lo
, uint16_t offset
)
473 return _make_local_sockaddr(lo
, offset
, AF_INET
);
476 int make_local_sockaddr6(struct sockaddr_storage
*lo
, uint16_t offset
)
478 return _make_local_sockaddr(lo
, offset
, AF_INET6
);
481 int wait_for_host(knet_handle_t knet_h
, uint16_t host_id
, int seconds
, int logfd
, FILE *std
)
485 if (is_memcheck() || is_helgrind()) {
486 printf("Test suite is running under valgrind, adjusting wait_for_host timeout\n");
487 seconds
= seconds
* 16;
490 while (i
< seconds
) {
491 flush_logs(logfd
, std
);
492 if (knet_h
->host_index
[host_id
]->status
.reachable
== 1) {
495 printf("waiting host %u to be reachable for %d more seconds\n", host_id
, seconds
- i
);
502 int wait_for_packet(knet_handle_t knet_h
, int seconds
, int datafd
, int logfd
, FILE *std
)
508 if (is_memcheck() || is_helgrind()) {
509 printf("Test suite is running under valgrind, adjusting wait_for_packet timeout\n");
510 seconds
= seconds
* 16;
515 FD_SET(datafd
, &rfds
);
520 err
= select(datafd
+1, &rfds
, NULL
, NULL
, &tv
);
522 * on slow arches the first call to select can return 0.
523 * pick an arbitrary 10 times loop (multiplied by waiting seconds)
526 if ((!err
) && (i
< seconds
)) {
527 flush_logs(logfd
, std
);
531 if ((err
> 0) && (FD_ISSET(datafd
, &rfds
))) {