/* *=========================================================================== * ipcom_cmd_sockperf_connect *=========================================================================== * Description: Active open of socket(s) * Parameters: * Returns: */ IP_STATIC void ipcom_cmd_sockperf_connect(Ipcom_cmd_sockperf_t *cmd) { Ip_fd *s = cmd->sock_array; Ip_u32 created_sockets; struct Ip_timeval start; struct Ip_timeval stop; ipcom_printf("sockperf-c: connecting to %s[%d]"IP_LF, cmd->res->ai_canonname, ip_ntohs(((struct Ip_sockaddr_in *)cmd->res->ai_addr)->sin_port)); ipcom_microtime(&start); for (created_sockets = 0; created_sockets < cmd->num_sock; created_sockets++) { s[created_sockets] = ipcom_socket(cmd->res->ai_family, cmd->res->ai_socktype, cmd->res->ai_protocol); if (s[created_sockets] == IP_SOCKERR) { ipcom_printf("sockperf-c: Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); created_sockets--; goto cleanup; } if (ipcom_setsockopt(s[created_sockets], IP_SOL_SOCKET, IP_SO_LINGER, &cmd->linger, sizeof(cmd->linger)) < 0) { ipcom_printf("sockperf-c: setsockopt SO_LINGER failed : %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_connect(s[created_sockets], cmd->res->ai_addr, cmd->res->ai_addrlen) < 0) { ipcom_printf("sockperf-c: Failed to connect: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } } ipcom_microtime(&stop); ipcom_printf("sockperf-t: %ld sockets connected in %ld ms"IP_LF, created_sockets, ipcom_cmd_sockperf_tv_to_msec(&start, &stop)); ipcom_cmd_sockperf_run(cmd); cleanup: while (created_sockets > 0) (void)ipcom_socketclose(s[created_sockets--]); }
/* *=========================================================================== * 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; }
/* *=========================================================================== * ipcom_cmd_sockperf_accept *=========================================================================== * Description: Passive open of socket(s). * Parameters: * Returns: */ IP_STATIC void ipcom_cmd_sockperf_accept(Ipcom_cmd_sockperf_t *cmd) { Ip_fd *s = cmd->sock_array; int listen_sock; Ip_u32 accepted_sockets = 0; struct Ip_timeval start; struct Ip_timeval stop; int on = 1; listen_sock = ipcom_socket(cmd->res->ai_family, cmd->res->ai_socktype, cmd->res->ai_protocol); if (listen_sock == IP_SOCKERR) { ipcom_printf("sockperf-a: Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_setsockopt(listen_sock, IP_SOL_SOCKET, IP_SO_REUSEADDR, &on, sizeof(on)) < 0) { ipcom_printf("sockperf-a: setsockopt IP_SO_REUSEADDR failed : %s"IP_LF, ipcom_strerror(ipcom_errno)); return; } if (ipcom_bind(listen_sock, cmd->res->ai_addr, cmd->res->ai_addrlen) < 0) { ipcom_printf("sockperf-a: Failed to bind: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_listen(listen_sock, cmd->num_sock) < 0) { ipcom_printf("sockperf-a: Failed to listen: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } ipcom_printf("sockperf-a: listen on %s[%d]"IP_LF, cmd->res->ai_canonname, ip_ntohs(((struct Ip_sockaddr_in *)cmd->res->ai_addr)->sin_port)); IP_FD_ZERO(&cmd->read_set); IP_FD_SET(listen_sock, &cmd->read_set); if (ipcom_socketselect(listen_sock + 1, &cmd->read_set, IP_NULL, IP_NULL, IP_NULL) != 1) { ipcom_printf("sockperf-a: Select failed for listen socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } ipcom_microtime(&start); for (;accepted_sockets < cmd->num_sock; accepted_sockets++) { s[accepted_sockets] = ipcom_accept(listen_sock, IP_NULL, IP_NULL); if (s[accepted_sockets] == IP_SOCKERR) { ipcom_printf("sockperf-a: Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_setsockopt(s[accepted_sockets], IP_SOL_SOCKET, IP_SO_LINGER, &cmd->linger, sizeof(cmd->linger)) < 0) { ipcom_printf("sockperf-a: setsockopt SO_LINGER failed : %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } } ipcom_microtime(&stop); ipcom_printf("sockperf-a: %ld sockets accepted in %ld ms"IP_LF, accepted_sockets, ipcom_cmd_sockperf_tv_to_msec(&start, &stop)); ipcom_cmd_sockperf_run(cmd); cleanup: if (listen_sock >= 0) (void)ipcom_socketclose(listen_sock); while (accepted_sockets-- > 0) (void)ipcom_socketclose(s[accepted_sockets]); }
/* *=========================================================================== * 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); }