/*
 *===========================================================================
 *                    ipcom_waitif
 *===========================================================================
 * Description: Wait for interface to get an IP address assigned.
 * Parameters:  ifindex - Index of the interface to wait for.
 *                        0 = any interface except loopback.
 *              domain - The address domain.
 * Returns:     0 = success, -1 = error, and sets errno.
 *
 */
IP_PUBLIC int
ipcom_waitif(int ifindex, int domain)
{
    struct Ipnet_rs_msghdr rtmsg;
    struct Ip_timeval stop;
    struct Ip_timeval tv;
    Ip_fd fd = IP_INVALID_SOCKET;
    int ret = -1;

    /* Check domain */
    if (domain != IP_AF_INET
#ifdef IPCOM_USE_INET6
        && domain != IP_AF_INET6
#endif /* IPCOM_USE_INET6 */
       )
    {
        IPCOM_LOG1(ERR, "ipcom_waitif :: invalid domain: %d", domain);
        ipcom_errno_set(IP_ERRNO_EINVAL);
        goto leave;
    }

    /* Get routing socket */
    fd = ipcom_socket(IP_AF_ROUTE, IP_SOCK_RAW, 0);
    if (fd == IP_INVALID_SOCKET)
    {
        IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_socket(ROUTE, RAW) failed, errno = %d", ipcom_errno);
        goto leave;
    }

    /* Get stop time */
    ipcom_microtime(&tv);
    stop.tv_sec = tv.tv_sec + IPNET_WAITIF_TIMEOUT;

    /* Loop and wait for address */
    for (;;)
    {
        Ip_ssize_t length;

        /* Check if address available */
        if (ifindex == 0)
        {
            int i;

            /* Any if will do */
            for (i = 2; i < IPNET_WAITIF_MAXIF; i++)
            {
                if (ipcom_waitif_gifaddr(fd, i, domain) == 0)
                {
                    ret = 0;
                    goto leave;
                }
            }
        }
        else if (ipcom_waitif_gifaddr(fd, ifindex, domain) == 0)
        {
            ret = 0;
            goto leave;
        }

again:
        /* Get timeout time */
        ipcom_microtime(&tv);
        tv.tv_sec = stop.tv_sec - tv.tv_sec;
        tv.tv_usec = 0;
        if (tv.tv_sec <= 0)
        {
            ipcom_errno_set(IP_ERRNO_ETIMEDOUT);
            goto leave;
        }

        /* Set receive timeout */
        if (ipcom_setsockopt(fd, IP_SOL_SOCKET, IP_SO_RCVTIMEO, &tv, sizeof(tv)) < 0)
        {
            IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_setsockopt(RCVTIMEO) failed, errno = %d", ipcom_errno);
            goto leave;
        }

        /* Read routing message headers only (truncated read). */
        length = ipcom_recv(fd, &rtmsg, sizeof(rtmsg), 0);
        if (length == IP_SOCKERR)
        {
            if (ipcom_errno != IP_ERRNO_ETIMEDOUT && ipcom_errno != IP_ERRNO_EWOULDBLOCK)
            {
                IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_recv() failed, errno = %d", ipcom_errno);
            }

            goto leave;
        }

        /* Only bother about newaddr */
        if (rtmsg.type != IPNET_RTM_NEWADDR)
        {
            goto again;
        }
    }

leave:
    if (fd != IP_INVALID_SOCKET)
    {
        ipcom_socketclose(fd);
    }

    return ret;
}
IP_STATIC
IPCOM_PROCESS( ipcom_cmd_smptest_server_spawn )
{
    union
    {
        struct Ip_sockaddr          sa;
#ifdef IPCOM_USE_INET6
        struct Ip_sockaddr_in6      sin6;
#endif
        struct Ip_sockaddr_storage  ss;
        struct Ip_sockaddr_in       sin;
    } addr;

    Ip_fd  listen_socket;
    Ip_fd  connect_sock = 0;
    int    opt_val = 1;
    int    portadd = spawn_number_server++;
    int    bytes = 0;
    int    sec = SECONDS_CLIENT + SECONDS_SERVER;
    unsigned char *buf = 0;
    int    num_recives = 0;
    unsigned long num_bytes = 0;
    struct Ip_sockaddr from;
    struct Ip_linger   linger;
    Ip_socklen_t       from_length = 0;
    int     retry_count = 0;

    ipcom_proc_init();

    ipcom_memset( &addr.ss, 0, sizeof( addr.ss ) );
    ipcom_memcpy( &addr.sa, smp_opt_server.res->ai_addr, smp_opt_server.res->ai_addrlen );

    linger.l_onoff  = 1;
    linger.l_linger = 2;

    listen_socket = ipcom_socket( smp_opt_server.res->ai_family, smp_opt_server.res->ai_socktype, smp_opt_server.res->ai_protocol );
    if (listen_socket == IP_SOCKERR)
    {
        ipcom_printf("Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    if ( 0 != ipcom_setsockopt(listen_socket, IP_SOL_SOCKET, IP_SO_REUSEPORT, &opt_val, sizeof (opt_val)) )
    {
        ipcom_printf("ipcom_setsockopt failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    addr.sin.sin_port = ip_htons( smp_opt_server.port + portadd );   /* port is in the same place for IPv4 and IPv6 */
    if ( 0 != ipcom_bind( listen_socket, &addr.sa, sizeof( addr.ss ) ) )
    {
        ipcom_printf("Failed to bind: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    buf = ipcom_malloc( smp_opt_server.num_bytes );

    if ( smp_opt_server.tcp )
    {
        if ( -1 == ipcom_listen( listen_socket, 0 ) )
        {
            ipcom_printf("Listen failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_sem_post( sem_wait_server );
            return;
        }
        if ( verbose )
            ipcom_printf("Thread %d listens to %s:%d"IP_LF, portadd, smp_opt_server.res->ai_canonname, ip_ntohs( addr.sin.sin_port ) );
    }

    if ( 0 == ipcom_atomic_sub_and_return( &listen_wait, 1 ) )
    {
        /* Send to the test-server or write to stdout? */
        if ( server_out >= 0 )
        {
            char ready[] = "Ready.";
            ipcom_socketwrite(server_out, ready, 8 );
        }
        else
            ipcom_printf("Ready."IP_LF );
    }

    if ( 0 != ipcom_socketioctl( listen_socket, IP_X_SIOCSINTR, &sec ) )
    {
        ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
        return_server = 1;
        ipcom_sem_post( sem_wait_server );
        return;
    }

    if ( smp_opt_server.tcp )
    {
retry:
        connect_sock = ipcom_accept( listen_socket, IP_NULL, 0 );
        if ( -1 == connect_sock )
        {
            if ( ipcom_errno == IP_ERRNO_EINTR )
            {
                if ( verbose )
                {
                    if ( ++retry_count < 5 )
                    {
                        ipcom_printf("Accept failed for thread %d: %s.. Retrying."IP_LF, portadd, ipcom_strerror(ipcom_errno));
                        goto retry;
                    }
                }
            }
            ipcom_printf("Accept failed for thread %d: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_socketclose( listen_socket );
            ipcom_sem_post( sem_wait_server );
            return;
        }

        if ( 0 != ipcom_socketioctl( connect_sock, IP_X_SIOCSINTR, &sec ) )
        {
            ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_sem_post( sem_wait_server );
            return;
        }

        if ( 0 != ipcom_setsockopt( connect_sock, IP_SOL_SOCKET, IP_SO_LINGER, &linger, sizeof (linger)) )
        {
            ipcom_printf("ipcom_setsockopt failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return_server = 1;
            ipcom_sem_post( sem_wait_server );
            return;
        }
    }

    while ( 1 )
    {
        num_recives++;
        if ( smp_opt_server.tcp )
            bytes = ipcom_recv( connect_sock, buf, smp_opt_server.num_bytes, 0);
        else
        {
            bytes = ipcom_recvfrom( listen_socket, buf, smp_opt_server.num_bytes, 0, &from, &from_length );
            if ( num_recives == 1 && 0 == smp_opt_server.tcp )
            {
                sec = SECONDS_CLIENT+2+portadd;
                if ( 0 != ipcom_socketioctl( listen_socket, IP_X_SIOCSINTR, &sec ) )
                {
                    ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
                    return_server = 1;
                    ipcom_sem_post( sem_wait_server );
                    return;
                }
            }
        }

        if ( bytes > 0 )
            num_bytes += bytes;
        if (bytes == 0)
        {
            if ( verbose )
            {
                ipcom_printf("Thread %d done."IP_LF, portadd );
                ipcom_printf("  Recives: %d"IP_LF, num_recives );
                ipcom_printf("  MB/s:    %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f );
            }
            break;
        }
        else if (bytes < 0)
        {
            if ( ipcom_errno == IP_ERRNO_EINTR )
            {
                if ( smp_opt_server.tcp )
                {
                    return_server = 1;
                    ipcom_printf("Error! Out of time!"IP_LF );
                    break;
                }
                else
                {
                    if ( verbose )
                    {
                        ipcom_printf("Thread %d done."IP_LF, portadd );
                        ipcom_printf("  Recives: %d"IP_LF, num_recives );
                        ipcom_printf("  MB/s:    %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f );
                    }
                    break;
                }
            }
            else if ( bytes == IP_SOCKERR )    /* Connection reset by peer */
            {
            }

            return_server = 1;
            ipcom_printf("recv failed: %s"IP_LF, ipcom_strerror(ipcom_errno));
            return;
        }
    }

    if ( verbose )
    {
        if ( spawn_number_server != smp_opt_server.num_sock )
        {
            ipcom_printf("Error. Only %d server-sockets seemed to work."IP_LF, spawn_number_server );
        }
    }

    if ( smp_opt_server.tcp )
        ipcom_shutdown( connect_sock, IP_SHUT_RDWR );

    ipcom_free( buf );
    ipcom_socketclose( listen_socket );

    if ( 0 == ipcom_atomic_sub_and_return( &num_wait_server, 1 ) )
        ipcom_sem_post( sem_wait_server );

    if ( smp_opt_server.tcp )
        ipcom_socketclose( connect_sock );

    ipcom_proc_exit();
}
Esempio n. 3
0
/*
 *===========================================================================
 *                    ipcom_cmd_sockperf_run
 *===========================================================================
 * Description: Sends/receives data.
 * Parameters:
 * Returns:
 */
IP_STATIC void
ipcom_cmd_sockperf_run(Ipcom_cmd_sockperf_t *cmd)
{
    struct Ip_timeval  tmo = { 0, 0 };
    struct Ip_timeval *ptmo;
    struct Ip_timeval  start;
    struct Ip_timeval  stop;
    Ip_u32             i;
    Ip_u32             c;
    int                num_ready;
    Ip_fd             *s = cmd->sock_array;
    Ip_u32             total_bytes_to_send = cmd->num_buf * cmd->buf_len;
    Ip_u32             finished_sockets = 0;
    Ip_u32             total_bytes_read = 0;
    Ip_ssize_t         bytes;
    Ip_fd_set          read_set;
    int                send_flags = (cmd->transmit && cmd->receive) ? IP_MSG_DONTWAIT : 0;

    if (cmd->transmit)
        ipcom_printf("sockperf-t: send buffer is %u"IP_LF, cmd->sendbuf_size);
    if (cmd->receive)
        ipcom_printf("sockperf-r: receive buffer is %u"IP_LF, cmd->sendbuf_size);
    for (i = 0; i < cmd->num_sock; i++)
    {
        int on = 1;

        if (ipcom_setsockopt(s[i],
                             IP_SOL_SOCKET,
                             IP_SO_REUSEADDR,
                             &on,
                             sizeof(on)) < 0)
        {
            ipcom_printf("sockperf-c: setsockopt IP_SO_REUSEADDR failed : %s"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return;
        }

        if (ipcom_setsockopt(s[i],
                             IP_SOL_SOCKET,
                             IP_SO_SNDBUF,
                             &cmd->sendbuf_size,
                             sizeof(cmd->sendbuf_size)) < 0)
        {
            ipcom_printf("sockperf-c: setsockopt IP_SO_SNDBUF failed : %s"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return;
        }

        if (ipcom_setsockopt(s[i],
                             IP_SOL_SOCKET,
                             IP_SO_RCVBUF,
                             &cmd->recvbuf_size,
                             sizeof(cmd->recvbuf_size)) < 0)
        {
            ipcom_printf("sockperf-c: setsockopt IP_SO_SNDBUF failed : %s"IP_LF,
                         ipcom_strerror(ipcom_errno));
            return;
        }
    }


    if (cmd->receive)
    {
        IP_FD_ZERO(&cmd->read_set);
        cmd->width = s[0];
        IP_FD_SET(s[0], &cmd->read_set);
        for (i = 1; i < cmd->num_sock; i++)
            if (s[i] != IP_INVALID_SOCKET)
            {
                cmd->width = IP_MAX(cmd->width, s[i]);
                IP_FD_SET(s[i], &cmd->read_set);
            }
    }

    ipcom_microtime(&start);
    while ((cmd->transmit && total_bytes_to_send)
           || (cmd->receive && finished_sockets < cmd->num_sock))
    {
        if (cmd->transmit && total_bytes_to_send)
        {
            for (i = 0; i < cmd->num_sock; i++)
            {
                if (cmd->testpattern)
                {
                    /* Test patter is "[B|E|D]xxxxxx ", B = first 8 byte in buffer, E = last 8 bytes, D = all other */
                    for (c = 0; c < cmd->buf_len; c += 8)
                        ipcom_sprintf(cmd->buf + c, "%c%06ld ",
                                      c == 0 ? '>' : (c >= cmd->buf_len - 8 ? '<' : '#'),
                                      cmd->send_pattern[i]++ % 1000000);
                }

                bytes = ipcom_send(s[i],
                                   cmd->buf,
                                   IP_MIN(cmd->buf_len, total_bytes_to_send),
                                   send_flags);
                if (bytes < 0 && ipcom_errno == IP_ERRNO_EWOULDBLOCK)
                    (void)ipcom_sleep(0);
                else
                {
                    if (bytes < 0)
                    {
                        ipcom_printf("sockperf-t: send failed : %s"IP_LF,
                                     ipcom_strerror(ipcom_errno));
                        return;
                    }
                    total_bytes_to_send -= bytes;
                }
            }

            if (cmd->receive && total_bytes_to_send == 0)
                for (i = 0; i < cmd->num_sock; i++)
                    if (ipcom_shutdown(s[i], IP_SHUT_WR) < 0)
                    {
                        ipcom_printf("sockperf-t: shutdown failed: %s"IP_LF,
                                     ipcom_strerror(ipcom_errno));
                        return;
                    }
        }

        if (cmd->receive)
        {
            ptmo = IP_NULL;
            while (finished_sockets < cmd->num_sock)
            {
                read_set = cmd->read_set;
                num_ready = ipcom_socketselect(cmd->width + 1, &read_set, IP_NULL, IP_NULL, ptmo);

                if (num_ready == 0)
                    break;

                if (num_ready < 0)
                {
                    ipcom_printf("sockperf-r: select failed: %s"IP_LF,
                                 ipcom_strerror(ipcom_errno));
                    return;
                }

                for (i = 0; i < cmd->num_sock; i++)
                {
                    if (IP_FD_ISSET(s[i], &read_set))
                    {
                        bytes = ipcom_recv(s[i], cmd->buf, cmd->buf_len, 0);
                        if (bytes < 0)
                        {
                            ipcom_printf("sockperf-r: recv failed: %s"IP_LF,
                                         ipcom_strerror(ipcom_errno));
                            return;
                        }

                        if (cmd->testpattern)
                        {
                            if (cmd->echo)
                                ipcom_cmd_sockperf_echo_buf(cmd->buf, bytes, cmd->recv_pattern[i]);
                            for (c = 0; c < (Ip_u32)bytes; c += 8)
                            {
                                if (cmd->buf[c] != '#' && cmd->buf[c] != '>' && cmd->buf[c] != '<')
                                {
                                    ipcom_printf("\nsockperf-r: test pattern error, expected B, D or E found %c(%d) offset %ld"IP_LF,
                                                 cmd->buf[c], (int)cmd->buf[c], c);
                                    ipcom_cmd_sockperf_echo_buf(cmd->buf, bytes, 0);
                                    return;
                                }

                                if (ipcom_atoi(cmd->buf + c + 1) != (int)(cmd->recv_pattern[i]++ % 1000000))
                                {
                                    ipcom_printf("\nsockperf-r: test pattern error, was %d should be %ld offset %ld"IP_LF,
                                                 ipcom_atoi(cmd->buf + c + 1), (cmd->recv_pattern[i] - 1) % 1000000, c);
                                    ipcom_cmd_sockperf_echo_buf(cmd->buf, bytes, 0);
                                    return;
                                }
                            }
                        }

                        if (bytes > 0)
                            total_bytes_read += bytes;
                        else
                        {
                            finished_sockets++;
                            IP_FD_CLR(s[i], &cmd->read_set);
                        }
                    }
                }

                if (cmd->transmit && total_bytes_to_send)
                    ptmo = &tmo;
            }
        }
    }
    ipcom_microtime(&stop);

    if (cmd->transmit)
        ipcom_printf("sockperf-t: %lu bytes sent in %ld ms (%lu kbyte/s)"IP_LF,
                     cmd->num_buf * cmd->buf_len,
                     ipcom_cmd_sockperf_tv_to_msec(&start, &stop),
                     cmd->num_buf * cmd->buf_len / (Ip_u32)ipcom_cmd_sockperf_tv_to_msec(&start, &stop) * 1000 / 1024);
    if (cmd->receive)
        ipcom_printf("sockperf-r: %lu bytes read in %ld ms (%lu kbyte/s)"IP_LF,
                     total_bytes_read,
                     ipcom_cmd_sockperf_tv_to_msec(&start, &stop),
                     total_bytes_read / (Ip_u32)ipcom_cmd_sockperf_tv_to_msec(&start, &stop) * 1000 / 1024);

}