/* * Check the status of the connection. If the connection failed, will retry * later. Otherwise, send this processes identifier to the endpoint on the * newly connected socket. */ static void mca_btl_tcp2_endpoint_complete_connect(mca_btl_base_endpoint_t* btl_endpoint) { int so_error = 0; opal_socklen_t so_length = sizeof(so_error); struct sockaddr_storage endpoint_addr; mca_btl_tcp2_proc_tosocks(btl_endpoint->endpoint_addr, &endpoint_addr); /* unregister from receiving event notifications */ opal_event_del(&btl_endpoint->endpoint_send_event); /* check connect completion status */ if(getsockopt(btl_endpoint->endpoint_sd, SOL_SOCKET, SO_ERROR, (char *)&so_error, &so_length) < 0) { BTL_ERROR(("getsockopt() to %s failed: %s (%d)", opal_net_get_hostname((struct sockaddr*) &endpoint_addr), strerror(opal_socket_errno), opal_socket_errno)); mca_btl_tcp2_endpoint_close(btl_endpoint); return; } if(so_error == EINPROGRESS || so_error == EWOULDBLOCK) { opal_event_add(&btl_endpoint->endpoint_send_event, 0); return; } if(so_error != 0) { BTL_ERROR(("connect() to %s failed: %s (%d)", opal_net_get_hostname((struct sockaddr*) &endpoint_addr), strerror(so_error), so_error)); mca_btl_tcp2_endpoint_close(btl_endpoint); return; } if(mca_btl_tcp2_endpoint_send_connect_ack(btl_endpoint) == OMPI_SUCCESS) { btl_endpoint->endpoint_state = MCA_BTL_TCP_CONNECT_ACK; opal_event_add(&btl_endpoint->endpoint_recv_event, 0); } else { mca_btl_tcp2_endpoint_close(btl_endpoint); } }
/* Called by mca_oob_tcp_accept() and connection_handler() on * a socket that has been accepted. This call finishes processing the * socket, including setting socket options and registering for the * OOB-level connection handshake. Used in both the threaded and * event listen modes. */ static void accept_connection(const int accepted_fd, const struct sockaddr *addr) { opal_output_verbose(OOB_TCP_DEBUG_CONNECT, orte_oob_base_framework.framework_output, "%s accept_connection: %s:%d\n", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), opal_net_get_hostname(addr), opal_net_get_port(addr)); /* setup socket options */ orte_oob_tcp_set_socket_options(accepted_fd); /* use a one-time event to wait for receipt of peer's * process ident message to complete this connection */ ORTE_ACTIVATE_TCP_ACCEPT_STATE(accepted_fd, addr, recv_handler); }
/* * Start a connection to the endpoint. This will likely not complete, * as the socket is set to non-blocking, so register for event * notification of connect completion. On connection we send * our globally unique process identifier to the endpoint and wait for * the endpoints response. */ static int mca_btl_tcp2_endpoint_start_connect(mca_btl_base_endpoint_t* btl_endpoint) { int rc,flags; struct sockaddr_storage endpoint_addr; /* By default consider a IPv4 connection */ uint16_t af_family = AF_INET; opal_socklen_t addrlen = sizeof(struct sockaddr_in); #if OPAL_WANT_IPV6 if (AF_INET6 == btl_endpoint->endpoint_addr->addr_family) { af_family = AF_INET6; addrlen = sizeof (struct sockaddr_in6); } #endif btl_endpoint->endpoint_sd = socket(af_family, SOCK_STREAM, 0); if (btl_endpoint->endpoint_sd < 0) { btl_endpoint->endpoint_retries++; return OMPI_ERR_UNREACH; } /* setup socket buffer sizes */ mca_btl_tcp2_set_socket_options(btl_endpoint->endpoint_sd); /* setup event callbacks */ mca_btl_tcp2_endpoint_event_init(btl_endpoint); /* setup the socket as non-blocking */ if((flags = fcntl(btl_endpoint->endpoint_sd, F_GETFL, 0)) < 0) { BTL_ERROR(("fcntl(F_GETFL) failed: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } else { flags |= O_NONBLOCK; if(fcntl(btl_endpoint->endpoint_sd, F_SETFL, flags) < 0) BTL_ERROR(("fcntl(F_SETFL) failed: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } /* start the connect - will likely fail with EINPROGRESS */ mca_btl_tcp2_proc_tosocks(btl_endpoint->endpoint_addr, &endpoint_addr); opal_output_verbose(20, mca_btl_base_output, "btl: tcp: attempting to connect() to address %s on port %d", opal_net_get_hostname((struct sockaddr*) &endpoint_addr), btl_endpoint->endpoint_addr->addr_port); if(connect(btl_endpoint->endpoint_sd, (struct sockaddr*)&endpoint_addr, addrlen) < 0) { /* non-blocking so wait for completion */ if(opal_socket_errno == EINPROGRESS || opal_socket_errno == EWOULDBLOCK) { btl_endpoint->endpoint_state = MCA_BTL_TCP_CONNECTING; opal_event_add(&btl_endpoint->endpoint_send_event, 0); return OMPI_SUCCESS; } { char *address; address = opal_net_get_hostname((struct sockaddr*) &endpoint_addr); BTL_PEER_ERROR( btl_endpoint->endpoint_proc->proc_ompi, ( "Unable to connect to the peer %s on port %d: %s\n", address, btl_endpoint->endpoint_addr->addr_port, strerror(opal_socket_errno) ) ); } mca_btl_tcp2_endpoint_close(btl_endpoint); btl_endpoint->endpoint_retries++; return OMPI_ERR_UNREACH; } /* send our globally unique process identifier to the endpoint */ if((rc = mca_btl_tcp2_endpoint_send_connect_ack(btl_endpoint)) == OMPI_SUCCESS) { btl_endpoint->endpoint_state = MCA_BTL_TCP_CONNECT_ACK; opal_event_add(&btl_endpoint->endpoint_recv_event, 0); } else { mca_btl_tcp2_endpoint_close(btl_endpoint); } return rc; }
static void mca_btl_tcp2_endpoint_dump(mca_btl_base_endpoint_t* btl_endpoint, const char* msg) { char src[64]; char dst[64]; int sndbuf,rcvbuf,nodelay,flags; #if OPAL_WANT_IPV6 struct sockaddr_storage inaddr; #else struct sockaddr_in inaddr; #endif opal_socklen_t obtlen; opal_socklen_t addrlen = sizeof(inaddr); getsockname(btl_endpoint->endpoint_sd, (struct sockaddr*)&inaddr, &addrlen); #if OPAL_WANT_IPV6 { char *address; address = (char *) opal_net_get_hostname((struct sockaddr*) &inaddr); if (NULL != address) { sprintf(src, "%s", address); } } #else sprintf(src, "%s", inet_ntoa(inaddr.sin_addr)); #endif getpeername(btl_endpoint->endpoint_sd, (struct sockaddr*)&inaddr, &addrlen); #if OPAL_WANT_IPV6 { char *address; address = (char *) opal_net_get_hostname ((struct sockaddr*) &inaddr); if (NULL != address) { sprintf(dst, "%s", address); } } #else sprintf(dst, "%s", inet_ntoa(inaddr.sin_addr)); #endif if((flags = fcntl(btl_endpoint->endpoint_sd, F_GETFL, 0)) < 0) { BTL_ERROR(("fcntl(F_GETFL) failed: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #if defined(SO_SNDBUF) obtlen = sizeof(sndbuf); if(getsockopt(btl_endpoint->endpoint_sd, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, &obtlen) < 0) { BTL_ERROR(("SO_SNDBUF option: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #else sndbuf = -1; #endif #if defined(SO_RCVBUF) obtlen = sizeof(rcvbuf); if(getsockopt(btl_endpoint->endpoint_sd, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbuf, &obtlen) < 0) { BTL_ERROR(("SO_RCVBUF option: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #else rcvbuf = -1; #endif #if defined(TCP_NODELAY) obtlen = sizeof(nodelay); if(getsockopt(btl_endpoint->endpoint_sd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, &obtlen) < 0) { BTL_ERROR(("TCP_NODELAY option: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #else nodelay = 0; #endif BTL_VERBOSE(("%s: %s - %s nodelay %d sndbuf %d rcvbuf %d flags %08x", msg, src, dst, nodelay, sndbuf, rcvbuf, flags)); }
static bool component_available(void) { int i, rc; char **interfaces = NULL; bool including = false, excluding = false; char name[32]; struct sockaddr_storage my_ss; int kindex; opal_output_verbose(5, orte_oob_base_framework.framework_output, "oob:tcp: component_available called"); /* if interface include was given, construct a list * of those interfaces which match the specifications - remember, * the includes could be given as named interfaces, IP addrs, or * subnet+mask */ if (NULL != mca_oob_tcp_component.if_include) { interfaces = split_and_resolve(&mca_oob_tcp_component.if_include, "include"); including = true; excluding = false; } else if (NULL != mca_oob_tcp_component.if_exclude) { interfaces = split_and_resolve(&mca_oob_tcp_component.if_exclude, "exclude"); including = false; excluding = true; } /* look at all available interfaces */ for (i = opal_ifbegin(); i >= 0; i = opal_ifnext(i)) { if (OPAL_SUCCESS != opal_ifindextoaddr(i, (struct sockaddr*) &my_ss, sizeof (my_ss))) { opal_output (0, "oob_tcp: problems getting address for index %i (kernel index %i)\n", i, opal_ifindextokindex(i)); continue; } /* ignore non-ip4/6 interfaces */ if (AF_INET != my_ss.ss_family #if OPAL_ENABLE_IPV6 && AF_INET6 != my_ss.ss_family #endif ) { continue; } kindex = opal_ifindextokindex(i); if (kindex <= 0) { continue; } opal_output_verbose(10, orte_oob_base_framework.framework_output, "WORKING INTERFACE %d KERNEL INDEX %d FAMILY: %s", i, kindex, (AF_INET == my_ss.ss_family) ? "V4" : "V6"); /* get the name for diagnostic purposes */ opal_ifindextoname(i, name, sizeof(name)); /* handle include/exclude directives */ if (NULL != interfaces) { /* check for match */ rc = opal_ifmatches(kindex, interfaces); /* if one of the network specifications isn't parseable, then * error out as we can't do what was requested */ if (OPAL_ERR_NETWORK_NOT_PARSEABLE == rc) { orte_show_help("help-oob-tcp.txt", "not-parseable", true); opal_argv_free(interfaces); return false; } /* if we are including, then ignore this if not present */ if (including) { if (OPAL_SUCCESS != rc) { opal_output_verbose(20, orte_oob_base_framework.framework_output, "%s oob:tcp:init rejecting interface %s (not in include list)", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), name); continue; } } else { /* we are excluding, so ignore if present */ if (OPAL_SUCCESS == rc) { opal_output_verbose(20, orte_oob_base_framework.framework_output, "%s oob:tcp:init rejecting interface %s (in exclude list)", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), name); continue; } } } else { /* if no specific interfaces were provided, we ignore the loopback * interface unless nothing else is available */ if (1 < opal_ifcount() && opal_ifisloopback(i)) { opal_output_verbose(20, orte_oob_base_framework.framework_output, "%s oob:tcp:init rejecting loopback interface %s", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), name); continue; } } /* Refs ticket #3019 * it would probably be worthwhile to print out a warning if OMPI detects multiple * IP interfaces that are "up" on the same subnet (because that's a Bad Idea). Note * that we should only check for this after applying the relevant include/exclude * list MCA params. If we detect redundant ports, we can also automatically ignore * them so that applications won't hang. */ /* add this address to our connections */ if (AF_INET == my_ss.ss_family) { opal_output_verbose(10, orte_oob_base_framework.framework_output, "%s oob:tcp:init adding %s to our list of %s connections", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), opal_net_get_hostname((struct sockaddr*) &my_ss), (AF_INET == my_ss.ss_family) ? "V4" : "V6"); opal_argv_append_nosize(&mca_oob_tcp_component.ipv4conns, opal_net_get_hostname((struct sockaddr*) &my_ss)); } else if (AF_INET6 == my_ss.ss_family) { #if OPAL_ENABLE_IPV6 opal_output_verbose(10, orte_oob_base_framework.framework_output, "%s oob:tcp:init adding %s to our list of %s connections", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), opal_net_get_hostname((struct sockaddr*) &my_ss), (AF_INET == my_ss.ss_family) ? "V4" : "V6"); opal_argv_append_nosize(&mca_oob_tcp_component.ipv6conns, opal_net_get_hostname((struct sockaddr*) &my_ss)); #endif } else { opal_output_verbose(10, orte_oob_base_framework.framework_output, "%s oob:tcp:init ignoring %s from out list of connections", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), opal_net_get_hostname((struct sockaddr*) &my_ss)); } } /* cleanup */ if (NULL != interfaces) { opal_argv_free(interfaces); } if (0 == opal_argv_count(mca_oob_tcp_component.ipv4conns) #if OPAL_ENABLE_IPV6 && 0 == opal_argv_count(mca_oob_tcp_component.ipv6conns) #endif ) { if (including) { orte_show_help("help-oob-tcp.txt", "no-included-found", true, mca_oob_tcp_component.if_include); } else if (excluding) { orte_show_help("help-oob-tcp.txt", "excluded-all", true, mca_oob_tcp_component.if_exclude); } return false; } /* set the module event base - this is where we would spin off a separate * progress thread if so desired */ mca_oob_tcp_module.ev_base = orte_event_base; return true; }
void mca_btl_tcp_endpoint_dump(mca_btl_base_endpoint_t* btl_endpoint, const char* msg) { char src[64], dst[64], *status; int sndbuf, rcvbuf, nodelay, flags = -1; #if OPAL_ENABLE_IPV6 struct sockaddr_storage inaddr; #else struct sockaddr_in inaddr; #endif opal_socklen_t obtlen; opal_socklen_t addrlen = sizeof(inaddr); opal_list_item_t *item; if( -1 != btl_endpoint->endpoint_sd ) { getsockname(btl_endpoint->endpoint_sd, (struct sockaddr*)&inaddr, &addrlen); #if OPAL_ENABLE_IPV6 { char *address; address = (char *) opal_net_get_hostname((struct sockaddr*) &inaddr); if (NULL != address) { sprintf(src, "%s", address); } } #else sprintf(src, "%s", inet_ntoa(inaddr.sin_addr)); #endif getpeername(btl_endpoint->endpoint_sd, (struct sockaddr*)&inaddr, &addrlen); #if OPAL_ENABLE_IPV6 { char *address; address = (char *) opal_net_get_hostname ((struct sockaddr*) &inaddr); if (NULL != address) { sprintf(dst, "%s", address); } } #else sprintf(dst, "%s", inet_ntoa(inaddr.sin_addr)); #endif if((flags = fcntl(btl_endpoint->endpoint_sd, F_GETFL, 0)) < 0) { BTL_ERROR(("fcntl(F_GETFL) failed: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #if defined(SO_SNDBUF) obtlen = sizeof(sndbuf); if(getsockopt(btl_endpoint->endpoint_sd, SOL_SOCKET, SO_SNDBUF, (char *)&sndbuf, &obtlen) < 0) { BTL_ERROR(("SO_SNDBUF option: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #else sndbuf = -1; #endif #if defined(SO_RCVBUF) obtlen = sizeof(rcvbuf); if(getsockopt(btl_endpoint->endpoint_sd, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbuf, &obtlen) < 0) { BTL_ERROR(("SO_RCVBUF option: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #else rcvbuf = -1; #endif #if defined(TCP_NODELAY) obtlen = sizeof(nodelay); if(getsockopt(btl_endpoint->endpoint_sd, IPPROTO_TCP, TCP_NODELAY, (char *)&nodelay, &obtlen) < 0) { BTL_ERROR(("TCP_NODELAY option: %s (%d)", strerror(opal_socket_errno), opal_socket_errno)); } #else nodelay = 0; #endif } mca_btl_base_err("%s %s: endpoint %p src %s - dst %s nodelay %d sndbuf %d rcvbuf %d flags %08x\n", ORTE_NAME_PRINT(ORTE_PROC_MY_NAME), msg, (void*)btl_endpoint, src, dst, nodelay, sndbuf, rcvbuf, flags); switch(btl_endpoint->endpoint_state) { case MCA_BTL_TCP_CONNECTING: status = "connecting"; break; case MCA_BTL_TCP_CONNECT_ACK: status = "connect ack"; break; case MCA_BTL_TCP_CLOSED: status = "closed"; break; case MCA_BTL_TCP_FAILED: status = "failed"; break; case MCA_BTL_TCP_CONNECTED: status = "connected"; break; default: status = "undefined"; break; } mca_btl_base_err("%s | [socket %d] [state %s] (nbo %s) (retries %u)\n" #if MCA_BTL_TCP_ENDPOINT_CACHE "\tcache %p length %lu pos %ld\n" #endif /* MCA_BTL_TCP_ENDPOINT_CACHE */ "\tpending: send %p recv %p\n", msg, btl_endpoint->endpoint_sd, status, (btl_endpoint->endpoint_nbo ? "true" : "false"), btl_endpoint->endpoint_retries, #if MCA_BTL_TCP_ENDPOINT_CACHE btl_endpoint->endpoint_cache, btl_endpoint->endpoint_cache_length, btl_endpoint->endpoint_cache_pos - btl_endpoint->endpoint_cache, #endif /* MCA_BTL_TCP_ENDPOINT_CACHE */ (void*)btl_endpoint->endpoint_send_frag, (void*)btl_endpoint->endpoint_recv_frag ); for(item = opal_list_get_first(&btl_endpoint->endpoint_frags); item != opal_list_get_end(&btl_endpoint->endpoint_frags); item = opal_list_get_next(item)) { mca_btl_tcp_dump_frag( (mca_btl_tcp_frag_t*)item, " | send" ); } }