--- embedaddon/iperf/src/iperf_tcp.c 2021/03/17 00:36:46 1.1.1.2 +++ embedaddon/iperf/src/iperf_tcp.c 2023/09/27 11:14:54 1.1.1.3 @@ -1,5 +1,5 @@ /* - * iperf, Copyright (c) 2014-2019, The Regents of the University of + * iperf, Copyright (c) 2014-2022, The Regents of the University of * California, through Lawrence Berkeley National Laboratory (subject * to receipt of any required approvals from the U.S. Dept. of * Energy). All rights reserved. @@ -76,7 +76,7 @@ iperf_tcp_recv(struct iperf_stream *sp) } -/* iperf_tcp_send +/* iperf_tcp_send * * sends the data for TCP */ @@ -85,19 +85,24 @@ iperf_tcp_send(struct iperf_stream *sp) { int r; + if (!sp->pending_size) + sp->pending_size = sp->settings->blksize; + if (sp->test->zerocopy) - r = Nsendfile(sp->buffer_fd, sp->socket, sp->buffer, sp->settings->blksize); + r = Nsendfile(sp->buffer_fd, sp->socket, sp->buffer, sp->pending_size); else - r = Nwrite(sp->socket, sp->buffer, sp->settings->blksize, Ptcp); + r = Nwrite(sp->socket, sp->buffer, sp->pending_size, Ptcp); if (r < 0) return r; + sp->pending_size -= r; sp->result->bytes_sent += r; sp->result->bytes_sent_this_interval += r; - if (sp->test->debug) - printf("sent %d bytes of %d, total %" PRIu64 "\n", r, sp->settings->blksize, sp->result->bytes_sent); + if (sp->test->debug_level >= DEBUG_LEVEL_DEBUG) + printf("sent %d bytes of %d, pending %d, total %" PRIu64 "\n", + r, sp->settings->blksize, sp->pending_size, sp->result->bytes_sent); return r; } @@ -129,8 +134,7 @@ iperf_tcp_accept(struct iperf_test * test) if (strcmp(test->cookie, cookie) != 0) { if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Ptcp) < 0) { - i_errno = IESENDMESSAGE; - return -1; + iperf_err(test, "failed to send access denied from busy server to new connecting client, errno = %d\n", errno); } close(s); } @@ -270,7 +274,7 @@ iperf_tcp_listen(struct iperf_test *test) } /* - * If we got an IPv6 socket, figure out if it shoudl accept IPv4 + * If we got an IPv6 socket, figure out if it should accept IPv4 * connections as well. See documentation in netannounce() for * more details. */ @@ -278,9 +282,9 @@ iperf_tcp_listen(struct iperf_test *test) if (res->ai_family == AF_INET6 && (test->settings->domain == AF_UNSPEC || test->settings->domain == AF_INET)) { if (test->settings->domain == AF_UNSPEC) opt = 0; - else + else opt = 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt)) < 0) { saved_errno = errno; close(s); @@ -310,7 +314,7 @@ iperf_tcp_listen(struct iperf_test *test) test->listener = s; } - + /* Read back and verify the sender socket buffer size */ optlen = sizeof(sndbuf_actual); if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_actual, &optlen) < 0) { @@ -365,103 +369,18 @@ iperf_tcp_listen(struct iperf_test *test) int iperf_tcp_connect(struct iperf_test *test) { - struct addrinfo hints, *local_res, *server_res; - char portstr[6]; + struct addrinfo *server_res; int s, opt; socklen_t optlen; int saved_errno; int rcvbuf_actual, sndbuf_actual; - if (test->bind_address) { - memset(&hints, 0, sizeof(hints)); - hints.ai_family = test->settings->domain; - hints.ai_socktype = SOCK_STREAM; - if ((gerror = getaddrinfo(test->bind_address, NULL, &hints, &local_res)) != 0) { - i_errno = IESTREAMCONNECT; - return -1; - } + s = create_socket(test->settings->domain, SOCK_STREAM, test->bind_address, test->bind_dev, test->bind_port, test->server_hostname, test->server_port, &server_res); + if (s < 0) { + i_errno = IESTREAMCONNECT; + return -1; } - memset(&hints, 0, sizeof(hints)); - hints.ai_family = test->settings->domain; - hints.ai_socktype = SOCK_STREAM; - snprintf(portstr, sizeof(portstr), "%d", test->server_port); - if ((gerror = getaddrinfo(test->server_hostname, portstr, &hints, &server_res)) != 0) { - if (test->bind_address) - freeaddrinfo(local_res); - i_errno = IESTREAMCONNECT; - return -1; - } - - if ((s = socket(server_res->ai_family, SOCK_STREAM, 0)) < 0) { - if (test->bind_address) - freeaddrinfo(local_res); - freeaddrinfo(server_res); - i_errno = IESTREAMCONNECT; - return -1; - } - - /* - * Various ways to bind the local end of the connection. - * 1. --bind (with or without --cport). - */ - if (test->bind_address) { - struct sockaddr_in *lcladdr; - lcladdr = (struct sockaddr_in *)local_res->ai_addr; - lcladdr->sin_port = htons(test->bind_port); - - if (bind(s, (struct sockaddr *) local_res->ai_addr, local_res->ai_addrlen) < 0) { - saved_errno = errno; - close(s); - freeaddrinfo(local_res); - freeaddrinfo(server_res); - errno = saved_errno; - i_errno = IESTREAMCONNECT; - return -1; - } - freeaddrinfo(local_res); - } - /* --cport, no --bind */ - else if (test->bind_port) { - size_t addrlen; - struct sockaddr_storage lcl; - - /* IPv4 */ - if (server_res->ai_family == AF_INET) { - struct sockaddr_in *lcladdr = (struct sockaddr_in *) &lcl; - lcladdr->sin_family = AF_INET; - lcladdr->sin_port = htons(test->bind_port); - lcladdr->sin_addr.s_addr = INADDR_ANY; - addrlen = sizeof(struct sockaddr_in); - } - /* IPv6 */ - else if (server_res->ai_family == AF_INET6) { - struct sockaddr_in6 *lcladdr = (struct sockaddr_in6 *) &lcl; - lcladdr->sin6_family = AF_INET6; - lcladdr->sin6_port = htons(test->bind_port); - lcladdr->sin6_addr = in6addr_any; - addrlen = sizeof(struct sockaddr_in6); - } - /* Unknown protocol */ - else { - saved_errno = errno; - close(s); - freeaddrinfo(server_res); - errno = saved_errno; - i_errno = IEPROTOCOL; - return -1; - } - - if (bind(s, (struct sockaddr *) &lcl, addrlen) < 0) { - saved_errno = errno; - close(s); - freeaddrinfo(server_res); - errno = saved_errno; - i_errno = IESTREAMCONNECT; - return -1; - } - } - /* Set socket options */ if (test->no_delay) { opt = 1; @@ -502,6 +421,18 @@ iperf_tcp_connect(struct iperf_test *test) return -1; } } +#if defined(HAVE_TCP_USER_TIMEOUT) + if ((opt = test->settings->snd_timeout)) { + if (setsockopt(s, IPPROTO_TCP, TCP_USER_TIMEOUT, &opt, sizeof(opt)) < 0) { + saved_errno = errno; + close(s); + freeaddrinfo(server_res); + errno = saved_errno; + i_errno = IESETUSERTIMEOUT; + return -1; + } + } +#endif /* HAVE_TCP_USER_TIMEOUT */ /* Read back and verify the sender socket buffer size */ optlen = sizeof(sndbuf_actual); @@ -540,10 +471,21 @@ iperf_tcp_connect(struct iperf_test *test) } if (test->json_output) { - cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize); + cJSON *sock_bufsize_item = cJSON_GetObjectItem(test->json_start, "sock_bufsize"); + if (sock_bufsize_item == NULL) { + cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize); + } + + cJSON *sndbuf_actual_item = cJSON_GetObjectItem(test->json_start, "sndbuf_actual"); + if (sndbuf_actual_item == NULL) { cJSON_AddNumberToObject(test->json_start, "sndbuf_actual", sndbuf_actual); + } + + cJSON *rcvbuf_actual_item = cJSON_GetObjectItem(test->json_start, "rcvbuf_actual"); + if (rcvbuf_actual_item == NULL) { cJSON_AddNumberToObject(test->json_start, "rcvbuf_actual", rcvbuf_actual); } + } #if defined(HAVE_FLOWLABEL) if (test->settings->flowlabel) { @@ -585,7 +527,7 @@ iperf_tcp_connect(struct iperf_test *test) errno = saved_errno; i_errno = IESETFLOW; return -1; - } + } } } #endif /* HAVE_FLOWLABEL */ @@ -613,6 +555,9 @@ iperf_tcp_connect(struct iperf_test *test) } } } + + /* Set common socket options */ + iperf_common_sockopts(test, s); if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) { saved_errno = errno;