/* * Copyright (c) 2004-2010 The Trustees of Indiana University and Indiana * University Research and Technology * Corporation. All rights reserved. * Copyright (c) 2004-2011 The University of Tennessee and The University * of Tennessee Research Foundation. All rights * reserved. * Copyright (c) 2004-2005 High Performance Computing Center Stuttgart, * University of Stuttgart. All rights reserved. * Copyright (c) 2004-2005 The Regents of the University of California. * All rights reserved. * Copyright (c) 2006-2013 Los Alamos National Security, LLC. * All rights reserved. * Copyright (c) 2009-2020 Cisco Systems, Inc. All rights reserved * Copyright (c) 2011 Oak Ridge National Labs. All rights reserved. * Copyright (c) 2014-2020 Intel, Inc. All rights reserved. * Copyright (c) 2014-2019 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2021-2022 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ * * In windows, many of the socket functions return an EWOULDBLOCK * instead of things like EAGAIN, EINPROGRESS, etc. It has been * verified that this will not conflict with other error codes that * are returned by these functions under UNIX/Linux environments */ #include "prte_config.h" #include "types.h" #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #include #ifdef HAVE_NETINET_IN_H # include #endif #ifdef HAVE_NETINET_TCP_H # include #endif #ifdef HAVE_ARPA_INET_H # include #endif #ifdef HAVE_NETDB_H # include #endif #ifdef HAVE_SYS_SOCKET_H # include #endif #include #include "src/include/prte_socket_errno.h" #include "src/mca/prtebacktrace/prtebacktrace.h" #include "src/util/error.h" #include "src/util/pmix_if.h" #include "src/util/pmix_net.h" #include "src/util/pmix_output.h" #include "oob_tcp_common.h" #include "oob_tcp_peer.h" #include "src/mca/oob/tcp/oob_tcp.h" #include "src/mca/oob/tcp/oob_tcp_component.h" /** * Set socket buffering */ static void set_keepalive(int sd) { #if defined(SO_KEEPALIVE) int option; socklen_t optlen; /* see if the keepalive option is available */ optlen = sizeof(option); if (getsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &option, &optlen) < 0) { /* not available, so just return */ return; } /* Set the option active */ option = 1; if (setsockopt(sd, SOL_SOCKET, SO_KEEPALIVE, &option, optlen) < 0) { pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(SO_KEEPALIVE) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); return; } # if defined(TCP_KEEPALIVE) /* set the idle time */ if (setsockopt(sd, IPPROTO_TCP, TCP_KEEPALIVE, &prte_mca_oob_tcp_component.keepalive_time, sizeof(prte_mca_oob_tcp_component.keepalive_time)) < 0) { pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(TCP_KEEPALIVE) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); return; } # elif defined(TCP_KEEPIDLE) /* set the idle time */ if (setsockopt(sd, IPPROTO_TCP, TCP_KEEPIDLE, &prte_mca_oob_tcp_component.keepalive_time, sizeof(prte_mca_oob_tcp_component.keepalive_time)) < 0) { pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(TCP_KEEPIDLE) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); return; } # endif // TCP_KEEPIDLE # if defined(TCP_KEEPINTVL) /* set the keepalive interval */ if (setsockopt(sd, IPPROTO_TCP, TCP_KEEPINTVL, &prte_mca_oob_tcp_component.keepalive_intvl, sizeof(prte_mca_oob_tcp_component.keepalive_intvl)) < 0) { pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(TCP_KEEPINTVL) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); return; } # endif // TCP_KEEPINTVL # if defined(TCP_KEEPCNT) /* set the miss rate */ if (setsockopt(sd, IPPROTO_TCP, TCP_KEEPCNT, &prte_mca_oob_tcp_component.keepalive_probes, sizeof(prte_mca_oob_tcp_component.keepalive_probes)) < 0) { pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(TCP_KEEPCNT) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); } # endif // TCP_KEEPCNT #endif // SO_KEEPALIVE } void prte_oob_tcp_set_socket_options(int sd) { #if defined(TCP_NODELAY) int optval; optval = 1; if (setsockopt(sd, IPPROTO_TCP, TCP_NODELAY, (char *) &optval, sizeof(optval)) < 0) { prte_backtrace_print(stderr, NULL, 1); pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(TCP_NODELAY) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); } #endif #if defined(SO_SNDBUF) if (prte_mca_oob_tcp_component.tcp_sndbuf > 0 && setsockopt(sd, SOL_SOCKET, SO_SNDBUF, (char *) &prte_mca_oob_tcp_component.tcp_sndbuf, sizeof(int)) < 0) { pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(SO_SNDBUF) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); } #endif #if defined(SO_RCVBUF) if (prte_mca_oob_tcp_component.tcp_rcvbuf > 0 && setsockopt(sd, SOL_SOCKET, SO_RCVBUF, (char *) &prte_mca_oob_tcp_component.tcp_rcvbuf, sizeof(int)) < 0) { pmix_output_verbose(5, prte_oob_base_framework.framework_output, "[%s:%d] setsockopt(SO_RCVBUF) failed: %s (%d)", __FILE__, __LINE__, strerror(prte_socket_errno), prte_socket_errno); } #endif if (0 < prte_mca_oob_tcp_component.keepalive_time) { set_keepalive(sd); } } prte_oob_tcp_peer_t *prte_oob_tcp_peer_lookup(const pmix_proc_t *name) { prte_oob_tcp_peer_t *peer; PMIX_LIST_FOREACH(peer, &prte_mca_oob_tcp_component.peers, prte_oob_tcp_peer_t) { if (PMIX_CHECK_PROCID(name, &peer->name)) { return peer; } } return NULL; } char *prte_oob_tcp_state_print(prte_oob_tcp_state_t state) { switch (state) { case MCA_OOB_TCP_UNCONNECTED: return "UNCONNECTED"; case MCA_OOB_TCP_CLOSED: return "CLOSED"; case MCA_OOB_TCP_RESOLVE: return "RESOLVE"; case MCA_OOB_TCP_CONNECTING: return "CONNECTING"; case MCA_OOB_TCP_CONNECT_ACK: return "ACK"; case MCA_OOB_TCP_CONNECTED: return "CONNECTED"; case MCA_OOB_TCP_FAILED: return "FAILED"; default: return "UNKNOWN"; } }