diff --git a/libknet/tests/api_knet_get_transport_list.c b/libknet/tests/api_knet_get_transport_list.c index 8f2f93c7..35b98a4d 100644 --- a/libknet/tests/api_knet_get_transport_list.c +++ b/libknet/tests/api_knet_get_transport_list.c @@ -1,64 +1,71 @@ /* * Copyright (C) 2017 Red Hat, Inc. All rights reserved. * * Authors: Fabio M. Di Nitto * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include "libknet.h" #include "internals.h" #include "test-common.h" static void test(void) { struct knet_transport_info transport_list[KNET_MAX_TRANSPORTS]; size_t transport_list_entries; + size_t transport_list_entries1; size_t i; memset(transport_list, 0, sizeof(transport_list)); - printf("Test knet_handle_get_transport_list with no transport_list\n"); + printf("Test knet_handle_get_transport_list with no entries_list\n"); - if ((!knet_get_transport_list(NULL, &transport_list_entries)) || (errno != EINVAL)) { - printf("knet_get_transport_list accepted invalid datafd or returned incorrect error: %s\n", strerror(errno)); + if ((!knet_get_transport_list(transport_list, NULL)) || (errno != EINVAL)) { + printf("knet_get_transport_list accepted invalid list_entries or returned incorrect error: %s\n", strerror(errno)); exit(FAIL); } - printf("Test knet_get_transport_list with no count\n"); + printf("Test knet_get_transport_list with no transport_list (get number of entries)\n"); - if ((!knet_get_transport_list(transport_list, NULL)) || (errno != EINVAL)) { - printf("knet_get_transport_list accepted invalid transport_list_entries or returned incorrect error: %s\n", strerror(errno)); + if (knet_get_transport_list(NULL, &transport_list_entries) < 0) { + printf("knet_get_transport_list returned error instead of number of entries: %s\n", strerror(errno)); exit(FAIL); } printf("Test knet_get_transport_list with valid data\n"); - if (knet_get_transport_list(transport_list, &transport_list_entries) < 0) { + if (knet_get_transport_list(transport_list, &transport_list_entries1) < 0) { printf("knet_get_transport_list failed: %s\n", strerror(errno)); exit(FAIL); } + if (transport_list_entries != transport_list_entries1) { + printf("knet_get_transport_list returned a different number of entries: %d, %d\n", + (int)transport_list_entries, (int)transport_list_entries1); + exit(FAIL); + } + for (i=0; i * * This software licensed under GPL-2.0+, LGPL-2.0+ */ #include "config.h" #include #include #include #include #include #include #include "libknet.h" #include "compat.h" #include "host.h" #include "link.h" #include "logging.h" #include "common.h" #include "transports.h" #include "transport_loopback.h" #include "transport_udp.h" #include "transport_sctp.h" #define empty_module 0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }, knet_transport_ops_t transport_modules_cmd[] = { { "LOOPBACK", KNET_TRANSPORT_LOOPBACK, 1, KNET_PMTUD_LOOPBACK_OVERHEAD, loopback_transport_init, loopback_transport_free, loopback_transport_link_set_config, loopback_transport_link_clear_config, loopback_transport_link_dyn_connect, loopback_transport_rx_sock_error, loopback_transport_tx_sock_error, loopback_transport_rx_is_data }, { "UDP", KNET_TRANSPORT_UDP, 1, KNET_PMTUD_UDP_OVERHEAD, udp_transport_init, udp_transport_free, udp_transport_link_set_config, udp_transport_link_clear_config, udp_transport_link_dyn_connect, udp_transport_rx_sock_error, udp_transport_tx_sock_error, udp_transport_rx_is_data }, { "SCTP", KNET_TRANSPORT_SCTP, #ifdef HAVE_NETINET_SCTP_H 1, KNET_PMTUD_SCTP_OVERHEAD, sctp_transport_init, sctp_transport_free, sctp_transport_link_set_config, sctp_transport_link_clear_config, sctp_transport_link_dyn_connect, sctp_transport_rx_sock_error, sctp_transport_tx_sock_error, sctp_transport_rx_is_data }, #else empty_module #endif { NULL, KNET_MAX_TRANSPORTS, empty_module }; /* * transport wrappers */ int start_all_transports(knet_handle_t knet_h) { int idx = 0, savederrno = 0, err = 0; while (transport_modules_cmd[idx].transport_name != NULL) { if (transport_modules_cmd[idx].built_in) { if (transport_modules_cmd[idx].transport_init(knet_h) < 0) { savederrno = errno; log_err(knet_h, KNET_SUB_HANDLE, "Failed to allocate transport handle for %s: %s", transport_modules_cmd[idx].transport_name, strerror(savederrno)); err = -1; goto out; } } idx++; } out: errno = savederrno; return err; } void stop_all_transports(knet_handle_t knet_h) { int idx = 0; while (transport_modules_cmd[idx].transport_name != NULL) { if (transport_modules_cmd[idx].built_in) { transport_modules_cmd[idx].transport_free(knet_h); } idx++; } } int transport_link_set_config(knet_handle_t knet_h, struct knet_link *kn_link, uint8_t transport) { if (!transport_modules_cmd[transport].built_in) { errno = EINVAL; return -1; } kn_link->transport_connected = 0; kn_link->transport_type = transport; kn_link->proto_overhead = transport_modules_cmd[transport].transport_mtu_overhead; return transport_modules_cmd[transport].transport_link_set_config(knet_h, kn_link); } int transport_link_clear_config(knet_handle_t knet_h, struct knet_link *kn_link) { return transport_modules_cmd[kn_link->transport_type].transport_link_clear_config(knet_h, kn_link); } int transport_link_dyn_connect(knet_handle_t knet_h, int sockfd, struct knet_link *kn_link) { return transport_modules_cmd[kn_link->transport_type].transport_link_dyn_connect(knet_h, sockfd, kn_link); } int transport_rx_sock_error(knet_handle_t knet_h, uint8_t transport, int sockfd, int recv_err, int recv_errno) { return transport_modules_cmd[transport].transport_rx_sock_error(knet_h, sockfd, recv_err, recv_errno); } int transport_tx_sock_error(knet_handle_t knet_h, uint8_t transport, int sockfd, int recv_err, int recv_errno) { return transport_modules_cmd[transport].transport_tx_sock_error(knet_h, sockfd, recv_err, recv_errno); } int transport_rx_is_data(knet_handle_t knet_h, uint8_t transport, int sockfd, struct knet_mmsghdr *msg) { return transport_modules_cmd[transport].transport_rx_is_data(knet_h, sockfd, msg); } /* * public api */ int knet_get_transport_list(struct knet_transport_info *transport_list, size_t *transport_list_entries) { int err = 0; - int i, count; - - if (!transport_list) { - errno = EINVAL; - return -1; - } + int idx = 0; + int outidx = 0; if (!transport_list_entries) { errno = EINVAL; return -1; } - count = 0; - i = 0; - - while (transport_modules_cmd[i].transport_name != NULL) { - if (transport_modules_cmd[i].built_in) { - transport_list[count].name = transport_modules_cmd[i].transport_name; - transport_list[count].id = transport_modules_cmd[i].transport_id; - count++; + while (transport_modules_cmd[idx].transport_name != NULL) { + if (transport_modules_cmd[idx].built_in) { + if (transport_list) { + transport_list[outidx].name = transport_modules_cmd[idx].transport_name; + transport_list[outidx].id = transport_modules_cmd[idx].transport_id; + } + outidx++; } - i++; + idx++; } - *transport_list_entries = count; + *transport_list_entries = outidx; return err; } const char *knet_get_transport_name_by_id(uint8_t transport) { int savederrno = 0; const char *name = NULL; if (transport == KNET_MAX_TRANSPORTS) { errno = EINVAL; return name; } if ((transport_modules_cmd[transport].transport_name) && (transport_modules_cmd[transport].built_in)) { name = transport_modules_cmd[transport].transport_name; } else { savederrno = ENOENT; } errno = savederrno; return name; } uint8_t knet_get_transport_id_by_name(const char *name) { int savederrno = 0; uint8_t err = KNET_MAX_TRANSPORTS; int i, found; if (!name) { errno = EINVAL; return err; } i = 0; found = 0; while (transport_modules_cmd[i].transport_name != NULL) { if (transport_modules_cmd[i].built_in) { if (!strcmp(transport_modules_cmd[i].transport_name, name)) { err = transport_modules_cmd[i].transport_id; found = 1; break; } } i++; } if (!found) { savederrno = EINVAL; } errno = savederrno; return err; } int knet_handle_set_transport_reconnect_interval(knet_handle_t knet_h, uint32_t msecs) { int savederrno = 0; if (!knet_h) { errno = EINVAL; return -1; } if (!msecs) { errno = EINVAL; return -1; } if (msecs < 1000) { log_warn(knet_h, KNET_SUB_HANDLE, "reconnect internval below 1 sec (%u msecs) might be too aggressive", msecs); } if (msecs > 60000) { log_warn(knet_h, KNET_SUB_HANDLE, "reconnect internval above 1 minute (%u msecs) could cause long delays in network convergiance", msecs); } savederrno = pthread_rwlock_wrlock(&knet_h->global_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_HANDLE, "Unable to get read lock: %s", strerror(savederrno)); errno = savederrno; return -1; } knet_h->reconnect_int = msecs; pthread_rwlock_unlock(&knet_h->global_rwlock); return 0; } int knet_handle_get_transport_reconnect_interval(knet_handle_t knet_h, uint32_t *msecs) { int savederrno = 0; if (!knet_h) { errno = EINVAL; return -1; } if (!msecs) { errno = EINVAL; return -1; } savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock); if (savederrno) { log_err(knet_h, KNET_SUB_HANDLE, "Unable to get read lock: %s", strerror(savederrno)); errno = savederrno; return -1; } *msecs = knet_h->reconnect_int; pthread_rwlock_unlock(&knet_h->global_rwlock); return 0; }