static int send_udp_sendmmsg(int fd, char *data) { const int max_nr_msg = ETH_MAX_MTU / ETH_DATA_LEN; struct mmsghdr mmsgs[max_nr_msg]; struct iovec iov[max_nr_msg]; unsigned int off = 0, left; int i = 0, ret; memset(mmsgs, 0, sizeof(mmsgs)); left = cfg_payload_len; while (left) { if (i == max_nr_msg) error(1, 0, "sendmmsg: exceeds max_nr_msg"); iov[i].iov_base = data + off; iov[i].iov_len = cfg_mss < left ? cfg_mss : left; mmsgs[i].msg_hdr.msg_iov = iov + i; mmsgs[i].msg_hdr.msg_iovlen = 1; off += iov[i].iov_len; left -= iov[i].iov_len; i++; } ret = sendmmsg(fd, mmsgs, i, cfg_zerocopy ? MSG_ZEROCOPY : 0); if (ret == -1) error(1, errno, "sendmmsg"); return ret; }
int udp_multisend_send( udp_multisend_t *um, int fd, int packets ) { static char use_emul = 0; int n, i; if (um == NULL) { errno = EINVAL; return -1; } if (packets > um->um_packets) packets = um->um_packets; for (i = 0; i < packets; i++) ((struct mmsghdr *)um->um_msg)[i].msg_len = um->um_iovec[i].iov_len; if (!use_emul) { n = sendmmsg(fd, (struct mmsghdr *)um->um_msg, packets, MSG_DONTWAIT); } else { n = -1; errno = ENOSYS; } if (n < 0 && errno == ENOSYS) { use_emul = 1; n = sendmmsg_i(fd, (struct mmsghdr *)um->um_msg, packets, MSG_DONTWAIT); } if (n > 0) { for (i = 0; i < n; i++) um->um_iovec[i].iov_len = ((struct mmsghdr *)um->um_msg)[i].msg_len; } return n; }
void send_message(struct client_state *state, int amount) { int r = sendmmsg(state->sock, state->out_msgs, amount, 0); if (r <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { } if (errno == ECONNREFUSED) { } perror("sendmmsg()"); } if (state->verbose) { printf("Send %d messages\n", r); } }
void thread_loop(void *userdata) { struct state *state = userdata; struct mmsghdr *messages = calloc(state->packets_in_buf, sizeof(struct mmsghdr)); struct iovec *iovecs = calloc(state->packets_in_buf, sizeof(struct iovec)); int fd = net_connect_udp(state->target_addr, state->src_port); int i; for (i = 0; i < state->packets_in_buf; i++) { struct iovec *iovec = &iovecs[i]; struct mmsghdr *msg = &messages[i]; msg->msg_hdr.msg_iov = iovec; msg->msg_hdr.msg_iovlen = 1; iovec->iov_base = (void*)state->payload; iovec->iov_len = state->payload_sz; } while (1) { int r = sendmmsg(fd, messages, state->packets_in_buf, 0); if (r <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { continue; } if (errno == ECONNREFUSED) { continue; } PFATAL("sendmmsg()"); } int i, bytes = 0; for (i = 0; i < r; i++) { struct mmsghdr *msg = &messages[i]; /* char *buf = msg->msg_hdr.msg_iov->iov_base; */ int len = msg->msg_len; msg->msg_hdr.msg_flags = 0; msg->msg_len = 0; bytes += len; } } }
static jint netty_epoll_native_sendmmsg0(JNIEnv* env, jclass clazz, jint fd, jobjectArray packets, jint offset, jint len) { struct mmsghdr msg[len]; struct sockaddr_storage addr[len]; socklen_t addrSize; int i; memset(msg, 0, sizeof(msg)); for (i = 0; i < len; i++) { jobject packet = (*env)->GetObjectArrayElement(env, packets, i + offset); jbyteArray address = (jbyteArray) (*env)->GetObjectField(env, packet, packetAddrFieldId); jint scopeId = (*env)->GetIntField(env, packet, packetScopeIdFieldId); jint port = (*env)->GetIntField(env, packet, packetPortFieldId); if (netty_unix_socket_initSockaddr(env, address, scopeId, port, &addr[i], &addrSize) == -1) { return -1; } msg[i].msg_hdr.msg_name = &addr[i]; msg[i].msg_hdr.msg_namelen = addrSize; msg[i].msg_hdr.msg_iov = (struct iovec*) (intptr_t) (*env)->GetLongField(env, packet, packetMemoryAddressFieldId); msg[i].msg_hdr.msg_iovlen = (*env)->GetIntField(env, packet, packetCountFieldId);; } ssize_t res; int err; do { res = sendmmsg(fd, msg, len, 0); // keep on writing if it was interrupted } while (res == -1 && ((err = errno) == EINTR)); if (res < 0) { return -err; } return (jint) res; }
static void* writemsg(void* param) { int sockfd; struct mmsghdr msg = {{ 0 }, 0 }; struct sockaddr_in soaddr = { 0 }; (void)param; /* UNUSED */ soaddr.sin_family = AF_INET; soaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); soaddr.sin_port = htons(UDP_SERVER_PORT); sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd == -1) { perror("socket client failed"); pthread_exit((void*)-1); } if (connect(sockfd, (struct sockaddr *)&soaddr, sizeof(soaddr)) == -1) { perror("connect failed"); pthread_exit((void*)-1); } msg.msg_hdr.msg_iov = sendiovs; msg.msg_hdr.msg_iovlen = IOVECS; msg.msg_hdr.msg_control = sendiovs; msg.msg_hdr.msg_controllen = (IOVECS * sizeof(struct iovec)); while(!stop_send) { sendmmsg(sockfd, &msg, 1, 0); } close(sockfd); pthread_exit(NULL); }
int main(int argc, char* argv[]) { char token = '!'; struct timeval ts; pthread_t reader; int sock; gettimeofday(&ts, NULL); socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds); sock = sockfds[0]; pthread_mutex_lock(&lock); pthread_create(&reader, NULL, reader_thread, NULL); /* Make the reader thread wait on its pthread_mutex_lock() */ atomic_puts("M: sleeping ..."); usleep(500000); atomic_puts("M: unlocking mutex ..."); pthread_mutex_unlock(&lock); atomic_puts("M: ... done"); /* Force a wait on read() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); test_assert(1 == write(sock, &token, sizeof(token))); ++token; atomic_puts("M: ... done"); /* Force a wait on readv() */ { struct iovec v = { .iov_base = &token, .iov_len = sizeof(token) }; atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("r: writev('%c')'ing socket ...\n", token); test_assert(1 == writev(sock, &v, 1)); ++token; atomic_puts("M: ... done"); } /* Force a wait on recv() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); /* Force a wait on recvfrom() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); /* Force a wait on recvfrom(&sock) */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); { struct mmsghdr mmsg = { { 0 } }; struct iovec data = { 0 }; int magic = msg_magic; data.iov_base = &magic; data.iov_len = sizeof(magic); mmsg.msg_hdr.msg_iov = &data; mmsg.msg_hdr.msg_iovlen = 1; struct cmsghdr* cmptr = (struct cmsghdr*)malloc(CTRLMSG_LEN); // send a fd cmptr->cmsg_level = SOL_SOCKET; cmptr->cmsg_type = SCM_RIGHTS; cmptr->cmsg_len = CTRLMSG_LEN; mmsg.msg_hdr.msg_control = cmptr; mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN; *(int*)CMSG_DATA(cmptr) = STDERR_FILENO; // send stderr as fd /* Force a wait on recvmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmsg'ing 0x%x to socket ...\n", msg_magic); sendmsg(sock, &mmsg.msg_hdr, 0); atomic_puts("M: ... done"); /* Force a wait on recvmmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmmsg'ing 0x%x to socket ...\n", msg_magic); breakpoint(); sendmmsg(sock, &mmsg, 1, 0); atomic_printf("M: ... sent %u bytes\n", mmsg.msg_len); /* Force a wait on recvmmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmmsg'ing(by socketcall) 0x%x to socket ...\n", msg_magic); #if defined(SYS_socketcall) struct sendmmsg_arg arg = { 0 }; arg.sockfd = sock; arg.msgvec = &mmsg; arg.vlen = 1; syscall(SYS_socketcall, SYS_SENDMMSG, (void*)&arg); #elif defined(SYS_sendmmsg) syscall(SYS_sendmmsg, sock, &mmsg, 1, 0); #else #error unable to call sendmmsg #endif free(cmptr); } { struct msghdr msg = { 0 }; struct iovec iovs[2]; char c1 = token++; char c2 = token++; iovs[0].iov_base = &c1; iovs[0].iov_len = sizeof(c1); iovs[1].iov_base = &c2; iovs[1].iov_len = sizeof(c2); msg.msg_iov = iovs; msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]); /* Force a wait on recvmsg(). */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing { '%c', '%c' } to socket ...\n", c1, c2); test_assert(2 == sendmsg(sock, &msg, 0)); atomic_puts("M: ... done"); } /* Force a wait on poll() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on ppoll() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on select(), raw syscall */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on select(), library call */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on epoll_wait() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on write() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: reading socket ...\n"); ++token; { char* buf = (char*)malloc(num_sockbuf_bytes); int i; for (i = 0; i < 2; ++i) { read_all_chunks(sock, buf, num_sockbuf_bytes, token); ++token; } free(buf); } atomic_puts("M: ... done"); /* Force a wait on read() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); atomic_puts("M: ... done"); pthread_join(reader, NULL); atomic_puts("EXIT-SUCCESS"); return 0; }
int main(int argc, char *argv[]) { char token = '!'; struct timeval ts; pthread_t reader; int sock; gettimeofday(&ts, NULL); socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds); sock = sockfds[0]; pthread_barrier_init(&cheater_barrier, NULL, 2); pthread_mutex_lock(&lock); pthread_create(&reader, NULL, reader_thread, NULL); /* Make the reader thread wait on its pthread_mutex_lock() */ atomic_puts("M: sleeping ..."); usleep(500000); atomic_puts("M: unlocking mutex ..."); pthread_mutex_unlock(&lock); atomic_puts("M: ... done"); /* Force a wait on read() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); test_assert(1 == write(sock, &token, sizeof(token))); ++token; atomic_puts("M: ... done"); /* Force a wait on readv() */ { struct iovec v = { .iov_base = &token, .iov_len = sizeof(token) }; atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("r: writev('%c')'ing socket ...\n", token); test_assert(1 == writev(sock, &v, 1)); ++token; atomic_puts("M: ... done"); } /* Force a wait on recv() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); /* Force a wait on recvfrom() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); /* Force a wait on recvfrom(&sock) */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sending '%c' to socket ...\n", token); send(sock, &token, sizeof(token), 0); ++token; atomic_puts("M: ... done"); { struct mmsghdr mmsg = {{ 0 }}; struct iovec data = { 0 }; int magic = msg_magic; data.iov_base = &magic; data.iov_len = sizeof(magic); mmsg.msg_hdr.msg_iov = &data; mmsg.msg_hdr.msg_iovlen = 1; /* Force a wait on recvmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmsg'ing 0x%x to socket ...\n", msg_magic); sendmsg(sock, &mmsg.msg_hdr, 0); atomic_puts("M: ... done"); /* Force a wait on recvmmsg() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: sendmmsg'ing 0x%x to socket ...\n", msg_magic); breakpoint(); sendmmsg(sock, &mmsg, 1, 0); atomic_printf("M: ... sent %u bytes\n", mmsg.msg_len); pthread_barrier_wait(&cheater_barrier); } { struct msghdr msg = { 0 }; struct iovec iovs[2]; char c1 = token++; char c2 = token++; iovs[0].iov_base = &c1; iovs[0].iov_len = sizeof(c1); iovs[1].iov_base = &c2; iovs[1].iov_len = sizeof(c2); msg.msg_iov = iovs; msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]); /* Force a wait on recvmsg(). */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing { '%c', '%c' } to socket ...\n", c1, c2); test_assert(2 == sendmsg(sock, &msg, 0)); atomic_puts("M: ... done"); } /* Force a wait on poll() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on ppoll() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on select() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on epoll_wait() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); ++token; atomic_puts("M: ... done"); /* Force a wait on write() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: reading socket ...\n"); ++token; { char* buf = (char*)malloc(num_sockbuf_bytes); int i; for (i = 0; i < 2; ++i) { read_all_chunks(sock, buf, num_sockbuf_bytes, token); ++token; } free(buf); } atomic_puts("M: ... done"); /* Force a wait on read() */ atomic_puts("M: sleeping again ..."); usleep(500000); atomic_printf("M: writing '%c' to socket ...\n", token); write(sock, &token, sizeof(token)); atomic_puts("M: ... done"); pthread_join(reader, NULL); atomic_puts("EXIT-SUCCESS"); return 0; }
int main(int argc, char* argv[]) { signal( SIGTRAP, SIG_IGN ); params p = get_params( argc, argv ); unistd::addrinfo hint = addrinfo{ 0, AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, 0, nullptr, nullptr, nullptr }; std::vector<unistd::addrinfo> addrs = unistd::getaddrinfo( p.hostname, p.port, hint ); const unistd::addrinfo& addr = addrs.at( 0 ); unistd::fd sock = unistd::socket( addr ); subscribe_events( sock ); if ( 0 != p.sndbuf ) unistd::setsockopt( sock, SOL_SOCKET, SO_SNDBUF, p.sndbuf ); if ( 0 != p.mtu ) { unistd::setsockopt( sock, IPPROTO_IPV6, IPV6_MTU_DISCOVER, IP_PMTUDISC_DONT ); unistd::setsockopt( sock, IPPROTO_IPV6, IPV6_MTU, p.mtu ); } if ( p.nodelay ) unistd::setsockopt( sock, SOL_SCTP, SCTP_NODELAY, 1 ); if ( 0 != p.max_burst ) unistd::setsockopt( sock, SOL_SCTP, SCTP_MAX_BURST, p.max_burst ); if ( 0 != p.maxseg ) unistd::setsockopt( sock, SOL_SCTP, SCTP_MAXSEG, p.maxseg ); int sndbuf = 0; socklen_t len = sizeof(sndbuf); getsockopt( sock, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len ); fprintf( stderr, "sndbuf: set=%d get=%d\n", p.sndbuf, sndbuf ); if ( 0 != p.rcvbuf ) unistd::setsockopt( sock, SOL_SOCKET, SO_RCVBUF, p.rcvbuf ); sctp_initmsg init_params; memset( &init_params, 0, sizeof(init_params) ); init_params.sinit_num_ostreams = 1; init_params.sinit_max_instreams = 1; init_params.sinit_max_attempts = 3; init_params.sinit_max_init_timeo = 100; unistd::setsockopt( sock, SOL_SCTP, SCTP_INITMSG, init_params ); unistd::connect( sock, addr ); sctp_assoc_t assoc_id = 0; while ( assoc_id == 0 ) { std::vector<char> cmsg_buff( CMSG_SPACE( sizeof( sctp_sndrcvinfo ) ) ); std::vector<char> msg_buff( 8192 ); //TODO: struct iovec iov; memset( &iov, 0, sizeof(iov) ); iov.iov_base = msg_buff.data(); iov.iov_len = msg_buff.size(); struct msghdr hdr; memset( &hdr, 0, sizeof(hdr) ); hdr.msg_name = nullptr; hdr.msg_namelen = 0; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; hdr.msg_control = cmsg_buff.data(); hdr.msg_controllen = cmsg_buff.size(); hdr.msg_flags = 0; ssize_t nrecv = 0; TEMP_FAILURE_RETRY( nrecv = recvmsg( sock, &hdr, 0 ) ); if ( 0 == nrecv ) raise( SIGTRAP ); if ( -1 == nrecv ) raise( SIGTRAP ); if ( hdr.msg_flags & MSG_NOTIFICATION ) { const sctp_notification& notify = *reinterpret_cast<const sctp_notification*>( hdr.msg_iov[0].iov_base ); switch ( notify.sn_header.sn_type ) { case SCTP_ASSOC_CHANGE: { const auto& sac = notify.sn_assoc_change; std::cout << " assoc_id=" << sac.sac_assoc_id << " error=" << sac.sac_error << " in=" << sac.sac_inbound_streams << " out=" << sac.sac_outbound_streams << std::endl; assoc_id = sac.sac_assoc_id; break; } case SCTP_REMOTE_ERROR: { const auto& sre = notify.sn_remote_error; printf( "^^^ remote_error: err=%hu len=%hu\n", ntohs(sre.sre_error), ntohs(sre.sre_length) ); return EXIT_FAILURE; } case SCTP_SHUTDOWN_EVENT: { printf( "^^^ SCTP_SHUTDOWN_EVENT\n" ); return EXIT_FAILURE; } } } } //int flags = fcntl( sock, F_GETFL, 0 ); //fcntl( sock, F_SETFL, flags | O_NONBLOCK ); const std::vector<char> msg = generate_message( p.msgsize ); struct iovec iov; iov.iov_base = const_cast<char*>( msg.data() ); iov.iov_len = msg.size(); std::vector<char> cmsg_buff( CMSG_SPACE( sizeof( sctp_sndrcvinfo ) ) ); struct mmsghdr mhdr; memset( &mhdr, 0, sizeof(mhdr) ); struct msghdr& hdr = mhdr.msg_hdr; hdr.msg_name = nullptr; hdr.msg_namelen = 0; hdr.msg_iov = &iov; hdr.msg_iovlen = 1; hdr.msg_flags = 0; hdr.msg_control = cmsg_buff.data(); hdr.msg_controllen = cmsg_buff.size(); cmsghdr* cmsg = CMSG_FIRSTHDR( &hdr ); cmsg->cmsg_level = IPPROTO_SCTP; cmsg->cmsg_type = SCTP_SNDRCV; cmsg->cmsg_len = CMSG_LEN( sizeof( sctp_sndrcvinfo ) ); sctp_sndrcvinfo& cmsg_data = *reinterpret_cast<sctp_sndrcvinfo*>( CMSG_DATA( cmsg ) ); cmsg_data.sinfo_stream = 0; cmsg_data.sinfo_ssn = 0; //ignored cmsg_data.sinfo_flags = SCTP_UNORDERED; cmsg_data.sinfo_ppid = 31337; cmsg_data.sinfo_context = 123456; cmsg_data.sinfo_timetolive = 0; cmsg_data.sinfo_tsn = 0; //ignored cmsg_data.sinfo_cumtsn = 0; //ignored cmsg_data.sinfo_assoc_id = assoc_id; std::vector<mmsghdr> mhdrs( p.batch, mhdr ); while ( p.count ) { const ssize_t count = std::min<uint64_t>( p.batch, p.count ); ssize_t nsend = 0; TEMP_FAILURE_RETRY( nsend = sendmmsg( sock, mhdrs.data(), count, 0 ) ); if ( 0 == nsend ) raise( SIGTRAP ); if ( -1 == nsend ) raise( SIGTRAP ); if ( count != nsend ) raise( SIGTRAP ); p.count -= count; } //raise( SIGTRAP ); sock.close(); return EXIT_SUCCESS; }
int main() { /* Only try this test if we have sendmmsg(). Unfortunately, * on RHEL6 we have SYS_sendmmsg(), but no glibc support for * sendmmsg(). */ #if defined(SYS_sendmmsg) || defined (SYS_SENDMMSG) int s, fd_null; struct sockaddr_in sin1, from; pid_t pid = 0; char buf[2][1024]; fd_set rdfds; struct mmsghdr msgs[2]; struct iovec iov[2]; socklen_t fromlen; /* initialize sockaddr's */ sin1.sin_family = AF_INET; sin1.sin_port = htons((getpid() % 32768) + 11000); sin1.sin_addr.s_addr = INADDR_ANY; pid = start_server(&sin1); fromlen = sizeof(from); memset(msgs, 0, sizeof(msgs)); iov[0].iov_base = buf[0]; iov[0].iov_len = sizeof(buf[0]); msgs[0].msg_hdr.msg_iov = &iov[0]; msgs[0].msg_hdr.msg_iovlen = 1; iov[1].iov_base = buf[1]; iov[1].iov_len = sizeof(buf[1]); msgs[1].msg_hdr.msg_iov = &iov[1]; msgs[1].msg_hdr.msg_iovlen = 1; fd_null = open("/dev/null", O_WRONLY); sendmmsg(-1, msgs, 2, 0); //staptest// sendmmsg (-1, XXXX, 2, 0x0) = -NNNN (EBADF) sendmmsg(fd_null, msgs, 2, MSG_DONTWAIT); //staptest// sendmmsg (NNNN, XXXX, 2, MSG_DONTWAIT) = -NNNN (ENOTSOCK) s = socket(PF_INET, SOCK_DGRAM, 0); //staptest// socket (PF_INET, SOCK_DGRAM, IPPROTO_IP) = NNNN sendmmsg(s, msgs, 2, 0); //staptest// sendmmsg (NNNN, XXXX, 2, 0x0) = -NNNN (EDESTADDRREQ) sendmmsg(s, (struct mmsghdr *)-1, 2, 0); //staptest// sendmmsg (NNNN, 0x[f]+, 2, 0x0) = -NNNN (EFAULT) close(s); //staptest// close (NNNN) = 0 s = socket(PF_INET, SOCK_STREAM, 0); //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN connect(s, (struct sockaddr *)&sin1, sizeof(sin1)); //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0 // Note that the exact failure return value can differ here, so // we'll just ignore it. sendmmsg(s, msgs, 2, -1); //staptest// sendmmsg (NNNN, XXXX, 2, MSG_[^ ]+|XXXX) = -NNNN close(s); //staptest// close (NNNN) = 0 s = socket(PF_INET, SOCK_STREAM, 0); //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN connect(s, (struct sockaddr *)&sin1, sizeof(sin1)); //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0 // We don't want to wait for -1 vectors, since we'd be waiting for // a long time... sendmmsg(s, msgs, -1, MSG_DONTWAIT); //staptest// sendmmsg (NNNN, XXXX, 4294967295, MSG_DONTWAIT) close(s); //staptest// close (NNNN) = 0 s = socket(PF_INET, SOCK_STREAM, 0); //staptest// socket (PF_INET, SOCK_STREAM, IPPROTO_IP) = NNNN connect(s, (struct sockaddr *)&sin1, sizeof(sin1)); //staptest// connect (NNNN, {AF_INET, 0.0.0.0, NNNN}, 16) = 0 sendmmsg(s, msgs, 2, MSG_DONTWAIT); //staptest// sendmmsg (NNNN, XXXX, 2, MSG_DONTWAIT) = NNNN close(s); //staptest// close (NNNN) = 0 close(fd_null); //staptest// close (NNNN) = 0 if (pid > 0) (void)kill(pid, SIGKILL); /* kill server */ //staptest// kill (NNNN, SIGKILL) = 0 #endif return 0; }
/* * stress_socket_server() * server writer */ static int stress_socket_server( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name, const pid_t pid, const pid_t ppid) { char buf[SOCKET_BUF]; int fd, status; int so_reuseaddr = 1; socklen_t addr_len = 0; struct sockaddr *addr; uint64_t msgs = 0; int rc = EXIT_SUCCESS; setpgid(pid, pgrp); if (stress_sighandler(name, SIGALRM, handle_socket_sigalrm, NULL) < 0) { rc = EXIT_FAILURE; goto die; } if ((fd = socket(opt_socket_domain, SOCK_STREAM, 0)) < 0) { rc = exit_status(errno); pr_fail_dbg(name, "socket"); goto die; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &so_reuseaddr, sizeof(so_reuseaddr)) < 0) { pr_fail_dbg(name, "setsockopt"); rc = EXIT_FAILURE; goto die_close; } stress_set_sockaddr(name, instance, ppid, opt_socket_domain, opt_socket_port, &addr, &addr_len); if (bind(fd, addr, addr_len) < 0) { rc = exit_status(errno); pr_fail_dbg(name, "bind"); goto die_close; } if (listen(fd, 10) < 0) { pr_fail_dbg(name, "listen"); rc = EXIT_FAILURE; goto die_close; } do { int sfd = accept(fd, (struct sockaddr *)NULL, NULL); if (sfd >= 0) { size_t i, j; struct sockaddr addr; socklen_t len; int sndbuf; struct msghdr msg; struct iovec vec[sizeof(buf)/16]; #if defined(HAVE_SENDMMSG) struct mmsghdr msgvec[MSGVEC_SIZE]; unsigned int msg_len = 0; #endif #if defined(SOCKET_NODELAY) int one = 1; #endif len = sizeof(addr); if (getsockname(fd, &addr, &len) < 0) { pr_fail_dbg(name, "getsockname"); (void)close(sfd); break; } len = sizeof(sndbuf); if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) { pr_fail_dbg(name, "getsockopt"); (void)close(sfd); break; } #if defined(SOCKET_NODELAY) if (opt_flags & OPT_FLAGS_SOCKET_NODELAY) { if (setsockopt(fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) < 0) { pr_inf(stderr, "%s: setsockopt TCP_NODELAY " "failed and disabled, errno=%d (%s)\n", name, errno, strerror(errno)); opt_flags &= ~OPT_FLAGS_SOCKET_NODELAY; } } #endif memset(buf, 'A' + (*counter % 26), sizeof(buf)); switch (opt_socket_opts) { case SOCKET_OPT_SEND: for (i = 16; i < sizeof(buf); i += 16) { ssize_t ret = send(sfd, buf, i, 0); if (ret < 0) { if (errno != EINTR) pr_fail_dbg(name, "send"); break; } else msgs++; } break; case SOCKET_OPT_SENDMSG: for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) { vec[j].iov_base = buf; vec[j].iov_len = i; } memset(&msg, 0, sizeof(msg)); msg.msg_iov = vec; msg.msg_iovlen = j; if (sendmsg(sfd, &msg, 0) < 0) { if (errno != EINTR) pr_fail_dbg(name, "sendmsg"); } else msgs += j; break; #if defined(HAVE_SENDMMSG) case SOCKET_OPT_SENDMMSG: memset(msgvec, 0, sizeof(msgvec)); for (j = 0, i = 16; i < sizeof(buf); i += 16, j++) { vec[j].iov_base = buf; vec[j].iov_len = i; msg_len += i; } for (i = 0; i < MSGVEC_SIZE; i++) { msgvec[i].msg_hdr.msg_iov = vec; msgvec[i].msg_hdr.msg_iovlen = j; } if (sendmmsg(sfd, msgvec, MSGVEC_SIZE, 0) < 0) { if (errno != EINTR) pr_fail_dbg(name, "sendmmsg"); } else msgs += (MSGVEC_SIZE * j); break; #endif default: /* Should never happen */ pr_err(stderr, "%s: bad option %d\n", name, opt_socket_opts); (void)close(sfd); goto die_close; } if (getpeername(sfd, &addr, &len) < 0) { pr_fail_dbg(name, "getpeername"); } (void)close(sfd); } (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); die_close: (void)close(fd); die: #ifdef AF_UNIX if (opt_socket_domain == AF_UNIX) { struct sockaddr_un *addr_un = (struct sockaddr_un *)addr; (void)unlink(addr_un->sun_path); } #endif if (pid) { (void)kill(pid, SIGKILL); (void)waitpid(pid, &status, 0); } pr_dbg(stderr, "%s: %" PRIu64 " messages sent\n", name, msgs); return rc; }
int aeron_udp_channel_transport_recvmmsg( aeron_udp_channel_transport_t *transport, struct mmsghdr *msgvec, size_t vlen, aeron_udp_transport_recv_func_t recv_func, void *clientd) { #if defined(HAVE_RECVMMSG) struct timespec tv = {.tv_nsec = 0, .tv_sec = 0}; int result = recvmmsg(transport->fd, msgvec, vlen, 0, &tv); if (result < 0) { int err = errno; if (EINTR == err || EAGAIN == err) { return 0; } aeron_set_err(err, "recvmmsg: %s", strerror(err)); return -1; } else if (0 == result) { return 0; } else { for (size_t i = 0, length = result; i < length; i++) { recv_func( clientd, transport->dispatch_clientd, msgvec[i].msg_hdr.msg_iov[0].iov_base, msgvec[i].msg_len, msgvec[i].msg_hdr.msg_name); } return result; } #else int work_count = 0; for (size_t i = 0, length = vlen; i < length; i++) { ssize_t result = recvmsg(transport->fd, &msgvec[i].msg_hdr, 0); if (result < 0) { int err = errno; if (EINTR == err || EAGAIN == err) { break; } aeron_set_err(err, "recvmsg: %s", strerror(err)); return -1; } if (0 == result) { break; } msgvec[i].msg_len = (unsigned int)result; recv_func( clientd, transport->dispatch_clientd, msgvec[i].msg_hdr.msg_iov[0].iov_base, msgvec[i].msg_len, msgvec[i].msg_hdr.msg_name); work_count++; } return work_count; #endif } int aeron_udp_channel_transport_sendmmsg( aeron_udp_channel_transport_t *transport, struct mmsghdr *msgvec, size_t vlen) { #if defined(HAVE_RECVMMSG) int sendmmsg_result = sendmmsg(transport->fd, msgvec, vlen, 0); if (sendmmsg_result < 0) { aeron_set_err(errno, "sendmmsg: %s", strerror(errno)); return -1; } return sendmmsg_result; #else int result = 0; for (size_t i = 0, length = vlen; i < length; i++) { ssize_t sendmsg_result = sendmsg(transport->fd, &msgvec[i].msg_hdr, 0); if (sendmsg_result < 0) { aeron_set_err(errno, "sendmsg: %s", strerror(errno)); return -1; } msgvec[i].msg_len = (unsigned int)sendmsg_result; if (0 == sendmsg_result) { break; } result++; } return result; #endif }
int CNIOLinux_sendmmsg(int sockfd, CNIOLinux_mmsghdr *msgvec, unsigned int vlen, int flags) { // This is technically undefined behaviour, but it's basically fine because these types are the same size, and we // don't think the compiler is inclined to blow anything up here. return sendmmsg(sockfd, (struct mmsghdr *)msgvec, vlen, flags); }