Annotation of embedaddon/iperf/src/iperf_tcp.c, revision 1.1.1.3

1.1       misho       1: /*
1.1.1.3 ! misho       2:  * iperf, Copyright (c) 2014-2022, The Regents of the University of
1.1       misho       3:  * California, through Lawrence Berkeley National Laboratory (subject
                      4:  * to receipt of any required approvals from the U.S. Dept. of
                      5:  * Energy).  All rights reserved.
                      6:  *
                      7:  * If you have questions about your rights to use or distribute this
                      8:  * software, please contact Berkeley Lab's Technology Transfer
                      9:  * Department at TTD@lbl.gov.
                     10:  *
                     11:  * NOTICE.  This software is owned by the U.S. Department of Energy.
                     12:  * As such, the U.S. Government has been granted for itself and others
                     13:  * acting on its behalf a paid-up, nonexclusive, irrevocable,
                     14:  * worldwide license in the Software to reproduce, prepare derivative
                     15:  * works, and perform publicly and display publicly.  Beginning five
                     16:  * (5) years after the date permission to assert copyright is obtained
                     17:  * from the U.S. Department of Energy, and subject to any subsequent
                     18:  * five (5) year renewals, the U.S. Government is granted for itself
                     19:  * and others acting on its behalf a paid-up, nonexclusive,
                     20:  * irrevocable, worldwide license in the Software to reproduce,
                     21:  * prepare derivative works, distribute copies to the public, perform
                     22:  * publicly and display publicly, and to permit others to do so.
                     23:  *
                     24:  * This code is distributed under a BSD style license, see the LICENSE
                     25:  * file for complete information.
                     26:  */
                     27: #include <stdio.h>
                     28: #include <stdlib.h>
                     29: #include <string.h>
                     30: #include <errno.h>
                     31: #include <unistd.h>
1.1.1.2   misho      32: #include <arpa/inet.h>
1.1       misho      33: #include <sys/socket.h>
                     34: #include <sys/types.h>
                     35: #include <netinet/in.h>
                     36: #include <netdb.h>
                     37: #include <sys/time.h>
                     38: #include <sys/select.h>
1.1.1.2   misho      39: #include <limits.h>
1.1       misho      40: 
                     41: #include "iperf.h"
                     42: #include "iperf_api.h"
                     43: #include "iperf_tcp.h"
                     44: #include "net.h"
1.1.1.2   misho      45: #include "cjson.h"
1.1       misho      46: 
                     47: #if defined(HAVE_FLOWLABEL)
                     48: #include "flowlabel.h"
                     49: #endif /* HAVE_FLOWLABEL */
                     50: 
                     51: /* iperf_tcp_recv
                     52:  *
                     53:  * receives the data for TCP
                     54:  */
                     55: int
                     56: iperf_tcp_recv(struct iperf_stream *sp)
                     57: {
                     58:     int r;
                     59: 
                     60:     r = Nread(sp->socket, sp->buffer, sp->settings->blksize, Ptcp);
                     61: 
                     62:     if (r < 0)
                     63:         return r;
                     64: 
1.1.1.2   misho      65:     /* Only count bytes received while we're in the correct state. */
                     66:     if (sp->test->state == TEST_RUNNING) {
                     67:        sp->result->bytes_received += r;
                     68:        sp->result->bytes_received_this_interval += r;
                     69:     }
                     70:     else {
                     71:        if (sp->test->debug)
                     72:            printf("Late receive, state = %d\n", sp->test->state);
                     73:     }
1.1       misho      74: 
                     75:     return r;
                     76: }
                     77: 
                     78: 
1.1.1.3 ! misho      79: /* iperf_tcp_send
1.1       misho      80:  *
                     81:  * sends the data for TCP
                     82:  */
                     83: int
                     84: iperf_tcp_send(struct iperf_stream *sp)
                     85: {
                     86:     int r;
                     87: 
1.1.1.3 ! misho      88:     if (!sp->pending_size)
        !            89:        sp->pending_size = sp->settings->blksize;
        !            90: 
1.1       misho      91:     if (sp->test->zerocopy)
1.1.1.3 ! misho      92:        r = Nsendfile(sp->buffer_fd, sp->socket, sp->buffer, sp->pending_size);
1.1       misho      93:     else
1.1.1.3 ! misho      94:        r = Nwrite(sp->socket, sp->buffer, sp->pending_size, Ptcp);
1.1       misho      95: 
                     96:     if (r < 0)
                     97:         return r;
                     98: 
1.1.1.3 ! misho      99:     sp->pending_size -= r;
1.1       misho     100:     sp->result->bytes_sent += r;
                    101:     sp->result->bytes_sent_this_interval += r;
                    102: 
1.1.1.3 ! misho     103:     if (sp->test->debug_level >=  DEBUG_LEVEL_DEBUG)
        !           104:        printf("sent %d bytes of %d, pending %d, total %" PRIu64 "\n",
        !           105:            r, sp->settings->blksize, sp->pending_size, sp->result->bytes_sent);
1.1.1.2   misho     106: 
1.1       misho     107:     return r;
                    108: }
                    109: 
                    110: 
                    111: /* iperf_tcp_accept
                    112:  *
                    113:  * accept a new TCP stream connection
                    114:  */
                    115: int
                    116: iperf_tcp_accept(struct iperf_test * test)
                    117: {
                    118:     int     s;
                    119:     signed char rbuf = ACCESS_DENIED;
                    120:     char    cookie[COOKIE_SIZE];
                    121:     socklen_t len;
                    122:     struct sockaddr_storage addr;
                    123: 
                    124:     len = sizeof(addr);
                    125:     if ((s = accept(test->listener, (struct sockaddr *) &addr, &len)) < 0) {
                    126:         i_errno = IESTREAMCONNECT;
                    127:         return -1;
                    128:     }
                    129: 
                    130:     if (Nread(s, cookie, COOKIE_SIZE, Ptcp) < 0) {
                    131:         i_errno = IERECVCOOKIE;
                    132:         return -1;
                    133:     }
                    134: 
                    135:     if (strcmp(test->cookie, cookie) != 0) {
                    136:         if (Nwrite(s, (char*) &rbuf, sizeof(rbuf), Ptcp) < 0) {
1.1.1.3 ! misho     137:             iperf_err(test, "failed to send access denied from busy server to new connecting client, errno = %d\n", errno);
1.1       misho     138:         }
                    139:         close(s);
                    140:     }
                    141: 
                    142:     return s;
                    143: }
                    144: 
                    145: 
                    146: /* iperf_tcp_listen
                    147:  *
                    148:  * start up a listener for TCP stream connections
                    149:  */
                    150: int
                    151: iperf_tcp_listen(struct iperf_test *test)
                    152: {
                    153:     int s, opt;
1.1.1.2   misho     154:     socklen_t optlen;
1.1       misho     155:     int saved_errno;
1.1.1.2   misho     156:     int rcvbuf_actual, sndbuf_actual;
1.1       misho     157: 
                    158:     s = test->listener;
                    159: 
                    160:     /*
                    161:      * If certain parameters are specified (such as socket buffer
                    162:      * size), then throw away the listening socket (the one for which
                    163:      * we just accepted the control connection) and recreate it with
                    164:      * those parameters.  That way, when new data connections are
                    165:      * set, they'll have all the correct parameters in place.
                    166:      *
                    167:      * It's not clear whether this is a requirement or a convenience.
                    168:      */
                    169:     if (test->no_delay || test->settings->mss || test->settings->socket_bufsize) {
1.1.1.2   misho     170:        struct addrinfo hints, *res;
                    171:        char portstr[6];
                    172: 
1.1       misho     173:         FD_CLR(s, &test->read_set);
                    174:         close(s);
                    175: 
                    176:         snprintf(portstr, 6, "%d", test->server_port);
                    177:         memset(&hints, 0, sizeof(hints));
                    178: 
                    179:        /*
                    180:         * If binding to the wildcard address with no explicit address
                    181:         * family specified, then force us to get an AF_INET6 socket.
                    182:         * More details in the comments in netanounce().
                    183:         */
                    184:        if (test->settings->domain == AF_UNSPEC && !test->bind_address) {
                    185:            hints.ai_family = AF_INET6;
                    186:        }
                    187:        else {
                    188:            hints.ai_family = test->settings->domain;
                    189:        }
                    190:         hints.ai_socktype = SOCK_STREAM;
                    191:         hints.ai_flags = AI_PASSIVE;
1.1.1.2   misho     192:         if ((gerror = getaddrinfo(test->bind_address, portstr, &hints, &res)) != 0) {
1.1       misho     193:             i_errno = IESTREAMLISTEN;
                    194:             return -1;
                    195:         }
                    196: 
                    197:         if ((s = socket(res->ai_family, SOCK_STREAM, 0)) < 0) {
                    198:            freeaddrinfo(res);
                    199:             i_errno = IESTREAMLISTEN;
                    200:             return -1;
                    201:         }
                    202: 
                    203:         if (test->no_delay) {
                    204:             opt = 1;
                    205:             if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
                    206:                saved_errno = errno;
                    207:                close(s);
                    208:                freeaddrinfo(res);
                    209:                errno = saved_errno;
                    210:                 i_errno = IESETNODELAY;
                    211:                 return -1;
                    212:             }
                    213:         }
                    214:         // XXX: Setting MSS is very buggy!
                    215:         if ((opt = test->settings->mss)) {
                    216:             if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
                    217:                saved_errno = errno;
                    218:                close(s);
                    219:                freeaddrinfo(res);
                    220:                errno = saved_errno;
                    221:                 i_errno = IESETMSS;
                    222:                 return -1;
                    223:             }
                    224:         }
                    225:         if ((opt = test->settings->socket_bufsize)) {
                    226:             if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
                    227:                saved_errno = errno;
                    228:                close(s);
                    229:                freeaddrinfo(res);
                    230:                errno = saved_errno;
                    231:                 i_errno = IESETBUF;
                    232:                 return -1;
                    233:             }
                    234:             if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
                    235:                saved_errno = errno;
                    236:                close(s);
                    237:                freeaddrinfo(res);
                    238:                errno = saved_errno;
                    239:                 i_errno = IESETBUF;
                    240:                 return -1;
                    241:             }
                    242:         }
                    243: #if defined(HAVE_SO_MAX_PACING_RATE)
1.1.1.2   misho     244:     /* If fq socket pacing is specified, enable it. */
                    245:     if (test->settings->fqrate) {
1.1       misho     246:        /* Convert bits per second to bytes per second */
1.1.1.2   misho     247:        unsigned int fqrate = test->settings->fqrate / 8;
                    248:        if (fqrate > 0) {
1.1       misho     249:            if (test->debug) {
1.1.1.2   misho     250:                printf("Setting fair-queue socket pacing to %u\n", fqrate);
1.1       misho     251:            }
1.1.1.2   misho     252:            if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
                    253:                warning("Unable to set socket pacing");
1.1       misho     254:            }
                    255:        }
                    256:     }
                    257: #endif /* HAVE_SO_MAX_PACING_RATE */
1.1.1.2   misho     258:     {
                    259:        unsigned int rate = test->settings->rate / 8;
                    260:        if (rate > 0) {
                    261:            if (test->debug) {
                    262:                printf("Setting application pacing to %u\n", rate);
                    263:            }
                    264:        }
                    265:     }
1.1       misho     266:         opt = 1;
                    267:         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
                    268:            saved_errno = errno;
                    269:             close(s);
                    270:            freeaddrinfo(res);
                    271:            errno = saved_errno;
                    272:             i_errno = IEREUSEADDR;
                    273:             return -1;
                    274:         }
                    275: 
                    276:        /*
1.1.1.3 ! misho     277:         * If we got an IPv6 socket, figure out if it should accept IPv4
1.1       misho     278:         * connections as well.  See documentation in netannounce() for
                    279:         * more details.
                    280:         */
                    281: #if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
                    282:        if (res->ai_family == AF_INET6 && (test->settings->domain == AF_UNSPEC || test->settings->domain == AF_INET)) {
                    283:            if (test->settings->domain == AF_UNSPEC)
                    284:                opt = 0;
1.1.1.3 ! misho     285:            else
1.1       misho     286:                opt = 1;
1.1.1.3 ! misho     287:            if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,
1.1       misho     288:                           (char *) &opt, sizeof(opt)) < 0) {
                    289:                saved_errno = errno;
                    290:                close(s);
                    291:                freeaddrinfo(res);
                    292:                errno = saved_errno;
                    293:                i_errno = IEV6ONLY;
                    294:                return -1;
                    295:            }
                    296:        }
                    297: #endif /* IPV6_V6ONLY */
                    298: 
                    299:         if (bind(s, (struct sockaddr *) res->ai_addr, res->ai_addrlen) < 0) {
                    300:            saved_errno = errno;
                    301:             close(s);
                    302:            freeaddrinfo(res);
                    303:            errno = saved_errno;
                    304:             i_errno = IESTREAMLISTEN;
                    305:             return -1;
                    306:         }
                    307: 
                    308:         freeaddrinfo(res);
                    309: 
1.1.1.2   misho     310:         if (listen(s, INT_MAX) < 0) {
1.1       misho     311:             i_errno = IESTREAMLISTEN;
                    312:             return -1;
                    313:         }
                    314: 
                    315:         test->listener = s;
                    316:     }
1.1.1.3 ! misho     317: 
1.1.1.2   misho     318:     /* Read back and verify the sender socket buffer size */
                    319:     optlen = sizeof(sndbuf_actual);
                    320:     if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_actual, &optlen) < 0) {
                    321:        saved_errno = errno;
                    322:        close(s);
                    323:        errno = saved_errno;
                    324:        i_errno = IESETBUF;
                    325:        return -1;
                    326:     }
                    327:     if (test->debug) {
                    328:        printf("SNDBUF is %u, expecting %u\n", sndbuf_actual, test->settings->socket_bufsize);
                    329:     }
                    330:     if (test->settings->socket_bufsize && test->settings->socket_bufsize > sndbuf_actual) {
                    331:        i_errno = IESETBUF2;
                    332:        return -1;
                    333:     }
                    334: 
                    335:     /* Read back and verify the receiver socket buffer size */
                    336:     optlen = sizeof(rcvbuf_actual);
                    337:     if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf_actual, &optlen) < 0) {
                    338:        saved_errno = errno;
                    339:        close(s);
                    340:        errno = saved_errno;
                    341:        i_errno = IESETBUF;
                    342:        return -1;
                    343:     }
                    344:     if (test->debug) {
                    345:        printf("RCVBUF is %u, expecting %u\n", rcvbuf_actual, test->settings->socket_bufsize);
                    346:     }
                    347:     if (test->settings->socket_bufsize && test->settings->socket_bufsize > rcvbuf_actual) {
                    348:        i_errno = IESETBUF2;
                    349:        return -1;
                    350:     }
                    351: 
                    352:     if (test->json_output) {
                    353:        cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize);
                    354:        cJSON_AddNumberToObject(test->json_start, "sndbuf_actual", sndbuf_actual);
                    355:        cJSON_AddNumberToObject(test->json_start, "rcvbuf_actual", rcvbuf_actual);
                    356:     }
                    357: 
1.1       misho     358:     return s;
                    359: }
                    360: 
                    361: 
                    362: /* iperf_tcp_connect
                    363:  *
                    364:  * connect to a TCP stream listener
1.1.1.2   misho     365:  * This function is roughly similar to netdial(), and may indeed have
                    366:  * been derived from it at some point, but it sets many TCP-specific
                    367:  * options between socket creation and connection.
1.1       misho     368:  */
                    369: int
                    370: iperf_tcp_connect(struct iperf_test *test)
                    371: {
1.1.1.3 ! misho     372:     struct addrinfo *server_res;
1.1       misho     373:     int s, opt;
1.1.1.2   misho     374:     socklen_t optlen;
1.1       misho     375:     int saved_errno;
1.1.1.2   misho     376:     int rcvbuf_actual, sndbuf_actual;
1.1       misho     377: 
1.1.1.3 ! misho     378:     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);
        !           379:     if (s < 0) {
        !           380:        i_errno = IESTREAMCONNECT;
        !           381:        return -1;
1.1.1.2   misho     382:     }
1.1       misho     383: 
                    384:     /* Set socket options */
                    385:     if (test->no_delay) {
                    386:         opt = 1;
                    387:         if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt)) < 0) {
                    388:            saved_errno = errno;
                    389:            close(s);
                    390:            freeaddrinfo(server_res);
                    391:            errno = saved_errno;
                    392:             i_errno = IESETNODELAY;
                    393:             return -1;
                    394:         }
                    395:     }
                    396:     if ((opt = test->settings->mss)) {
                    397:         if (setsockopt(s, IPPROTO_TCP, TCP_MAXSEG, &opt, sizeof(opt)) < 0) {
                    398:            saved_errno = errno;
                    399:            close(s);
                    400:            freeaddrinfo(server_res);
                    401:            errno = saved_errno;
                    402:             i_errno = IESETMSS;
                    403:             return -1;
                    404:         }
                    405:     }
                    406:     if ((opt = test->settings->socket_bufsize)) {
                    407:         if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(opt)) < 0) {
                    408:            saved_errno = errno;
                    409:            close(s);
                    410:            freeaddrinfo(server_res);
                    411:            errno = saved_errno;
                    412:             i_errno = IESETBUF;
                    413:             return -1;
                    414:         }
                    415:         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0) {
                    416:            saved_errno = errno;
                    417:            close(s);
                    418:            freeaddrinfo(server_res);
                    419:            errno = saved_errno;
                    420:             i_errno = IESETBUF;
                    421:             return -1;
                    422:         }
                    423:     }
1.1.1.3 ! misho     424: #if defined(HAVE_TCP_USER_TIMEOUT)
        !           425:     if ((opt = test->settings->snd_timeout)) {
        !           426:         if (setsockopt(s, IPPROTO_TCP, TCP_USER_TIMEOUT, &opt, sizeof(opt)) < 0) {
        !           427:            saved_errno = errno;
        !           428:            close(s);
        !           429:            freeaddrinfo(server_res);
        !           430:            errno = saved_errno;
        !           431:             i_errno = IESETUSERTIMEOUT;
        !           432:             return -1;
        !           433:         }
        !           434:     }
        !           435: #endif /* HAVE_TCP_USER_TIMEOUT */
1.1.1.2   misho     436: 
                    437:     /* Read back and verify the sender socket buffer size */
                    438:     optlen = sizeof(sndbuf_actual);
                    439:     if (getsockopt(s, SOL_SOCKET, SO_SNDBUF, &sndbuf_actual, &optlen) < 0) {
                    440:        saved_errno = errno;
                    441:        close(s);
                    442:        freeaddrinfo(server_res);
                    443:        errno = saved_errno;
                    444:        i_errno = IESETBUF;
                    445:        return -1;
                    446:     }
1.1       misho     447:     if (test->debug) {
1.1.1.2   misho     448:        printf("SNDBUF is %u, expecting %u\n", sndbuf_actual, test->settings->socket_bufsize);
                    449:     }
                    450:     if (test->settings->socket_bufsize && test->settings->socket_bufsize > sndbuf_actual) {
                    451:        i_errno = IESETBUF2;
                    452:        return -1;
1.1       misho     453:     }
1.1.1.2   misho     454: 
                    455:     /* Read back and verify the receiver socket buffer size */
                    456:     optlen = sizeof(rcvbuf_actual);
                    457:     if (getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcvbuf_actual, &optlen) < 0) {
                    458:        saved_errno = errno;
                    459:        close(s);
                    460:        freeaddrinfo(server_res);
                    461:        errno = saved_errno;
                    462:        i_errno = IESETBUF;
                    463:        return -1;
                    464:     }
                    465:     if (test->debug) {
                    466:        printf("RCVBUF is %u, expecting %u\n", rcvbuf_actual, test->settings->socket_bufsize);
                    467:     }
                    468:     if (test->settings->socket_bufsize && test->settings->socket_bufsize > rcvbuf_actual) {
                    469:        i_errno = IESETBUF2;
                    470:        return -1;
                    471:     }
                    472: 
                    473:     if (test->json_output) {
1.1.1.3 ! misho     474:     cJSON *sock_bufsize_item = cJSON_GetObjectItem(test->json_start, "sock_bufsize");
        !           475:     if (sock_bufsize_item == NULL) {
        !           476:     cJSON_AddNumberToObject(test->json_start, "sock_bufsize", test->settings->socket_bufsize);
        !           477:     }
        !           478: 
        !           479:     cJSON *sndbuf_actual_item = cJSON_GetObjectItem(test->json_start, "sndbuf_actual");
        !           480:     if (sndbuf_actual_item == NULL) {
1.1.1.2   misho     481:        cJSON_AddNumberToObject(test->json_start, "sndbuf_actual", sndbuf_actual);
1.1.1.3 ! misho     482:     }
        !           483:         
        !           484:     cJSON *rcvbuf_actual_item = cJSON_GetObjectItem(test->json_start, "rcvbuf_actual");
        !           485:     if (rcvbuf_actual_item == NULL) {
1.1.1.2   misho     486:        cJSON_AddNumberToObject(test->json_start, "rcvbuf_actual", rcvbuf_actual);
                    487:     }
1.1.1.3 ! misho     488:     }
1.1.1.2   misho     489: 
1.1       misho     490: #if defined(HAVE_FLOWLABEL)
                    491:     if (test->settings->flowlabel) {
                    492:         if (server_res->ai_addr->sa_family != AF_INET6) {
                    493:            saved_errno = errno;
                    494:            close(s);
                    495:            freeaddrinfo(server_res);
                    496:            errno = saved_errno;
                    497:             i_errno = IESETFLOW;
                    498:             return -1;
                    499:        } else {
                    500:            struct sockaddr_in6* sa6P = (struct sockaddr_in6*) server_res->ai_addr;
                    501:             char freq_buf[sizeof(struct in6_flowlabel_req)];
                    502:             struct in6_flowlabel_req *freq = (struct in6_flowlabel_req *)freq_buf;
                    503:             int freq_len = sizeof(*freq);
                    504: 
                    505:             memset(freq, 0, sizeof(*freq));
                    506:             freq->flr_label = htonl(test->settings->flowlabel & IPV6_FLOWINFO_FLOWLABEL);
                    507:             freq->flr_action = IPV6_FL_A_GET;
                    508:             freq->flr_flags = IPV6_FL_F_CREATE;
1.1.1.2   misho     509:             freq->flr_share = IPV6_FL_S_ANY;
1.1       misho     510:             memcpy(&freq->flr_dst, &sa6P->sin6_addr, 16);
                    511: 
                    512:             if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWLABEL_MGR, freq, freq_len) < 0) {
                    513:                saved_errno = errno;
                    514:                 close(s);
                    515:                 freeaddrinfo(server_res);
                    516:                errno = saved_errno;
                    517:                 i_errno = IESETFLOW;
                    518:                 return -1;
                    519:             }
                    520:             sa6P->sin6_flowinfo = freq->flr_label;
                    521: 
                    522:             opt = 1;
                    523:             if (setsockopt(s, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, &opt, sizeof(opt)) < 0) {
                    524:                saved_errno = errno;
                    525:                 close(s);
                    526:                 freeaddrinfo(server_res);
                    527:                errno = saved_errno;
                    528:                 i_errno = IESETFLOW;
                    529:                 return -1;
1.1.1.3 ! misho     530:             }
1.1       misho     531:        }
                    532:     }
                    533: #endif /* HAVE_FLOWLABEL */
                    534: 
                    535: #if defined(HAVE_SO_MAX_PACING_RATE)
1.1.1.2   misho     536:     /* If socket pacing is specified try to enable it. */
                    537:     if (test->settings->fqrate) {
1.1       misho     538:        /* Convert bits per second to bytes per second */
1.1.1.2   misho     539:        unsigned int fqrate = test->settings->fqrate / 8;
                    540:        if (fqrate > 0) {
1.1       misho     541:            if (test->debug) {
1.1.1.2   misho     542:                printf("Setting fair-queue socket pacing to %u\n", fqrate);
1.1       misho     543:            }
1.1.1.2   misho     544:            if (setsockopt(s, SOL_SOCKET, SO_MAX_PACING_RATE, &fqrate, sizeof(fqrate)) < 0) {
                    545:                warning("Unable to set socket pacing");
1.1       misho     546:            }
                    547:        }
                    548:     }
                    549: #endif /* HAVE_SO_MAX_PACING_RATE */
1.1.1.2   misho     550:     {
                    551:        unsigned int rate = test->settings->rate / 8;
                    552:        if (rate > 0) {
                    553:            if (test->debug) {
                    554:                printf("Setting application pacing to %u\n", rate);
                    555:            }
                    556:        }
                    557:     }
1.1       misho     558: 
1.1.1.3 ! misho     559:     /* Set common socket options */
        !           560:     iperf_common_sockopts(test, s);
        !           561: 
1.1       misho     562:     if (connect(s, (struct sockaddr *) server_res->ai_addr, server_res->ai_addrlen) < 0 && errno != EINPROGRESS) {
                    563:        saved_errno = errno;
                    564:        close(s);
                    565:        freeaddrinfo(server_res);
                    566:        errno = saved_errno;
                    567:         i_errno = IESTREAMCONNECT;
                    568:         return -1;
                    569:     }
                    570: 
                    571:     freeaddrinfo(server_res);
                    572: 
                    573:     /* Send cookie for verification */
                    574:     if (Nwrite(s, test->cookie, COOKIE_SIZE, Ptcp) < 0) {
                    575:        saved_errno = errno;
                    576:        close(s);
                    577:        errno = saved_errno;
                    578:         i_errno = IESENDCOOKIE;
                    579:         return -1;
                    580:     }
                    581: 
                    582:     return s;
                    583: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>