/* * This test is based on source contained in the man pages for sendmmsg and * recvmmsg in release 4.15 of the Linux man-pages project. */ #define _GNU_SOURCE #include #include #include #include #include #include #include "tst_test.h" #include "tst_safe_macros.h" #include "tst_safe_pthread.h" #define BUFSIZE 16 #define VLEN 2 static void *sender_thread(LTP_ATTRIBUTE_UNUSED void *arg) { struct sockaddr_in addr; struct mmsghdr msg[2]; struct iovec msg1[2], msg2; int send_sockfd; int retval; send_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(1234); SAFE_CONNECT(send_sockfd, (struct sockaddr *) &addr, sizeof(addr)); memset(msg1, 0, sizeof(msg1)); msg1[0].iov_base = "one"; msg1[0].iov_len = 3; msg1[1].iov_base = "two"; msg1[1].iov_len = 3; memset(&msg2, 0, sizeof(msg2)); msg2.iov_base = "three"; msg2.iov_len = 5; memset(msg, 0, sizeof(msg)); msg[0].msg_hdr.msg_iov = msg1; msg[0].msg_hdr.msg_iovlen = 2; msg[1].msg_hdr.msg_iov = &msg2; msg[1].msg_hdr.msg_iovlen = 1; retval = sendmmsg(send_sockfd, msg, 2, 0); if (retval < 0) tst_brk(TFAIL|TTERRNO, "sendmmsg failed"); return NULL; } static void *receiver_thread(LTP_ATTRIBUTE_UNUSED void *arg) { int receive_sockfd; struct sockaddr_in addr; struct mmsghdr msgs[VLEN]; struct iovec iovecs[VLEN]; char bufs[VLEN][BUFSIZE+1]; struct timespec timeout; int i, retval; receive_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); addr.sin_port = htons(1234); SAFE_BIND(receive_sockfd, (struct sockaddr *)&addr, sizeof(addr)); memset(msgs, 0, sizeof(msgs)); for (i = 0; i < VLEN; i++) { iovecs[i].iov_base = bufs[i]; iovecs[i].iov_len = BUFSIZE; msgs[i].msg_hdr.msg_iov = &iovecs[i]; msgs[i].msg_hdr.msg_iovlen = 1; } timeout.tv_sec = 1; timeout.tv_nsec = 0; retval = recvmmsg(receive_sockfd, msgs, VLEN, 0, &timeout); if (retval == -1) tst_brk(TFAIL | TTERRNO, "recvmmsg failed"); if (retval != 2) tst_brk(TFAIL, "Received unexpected number of messages (%d)", retval); bufs[0][msgs[0].msg_len] = 0; if (strcmp(bufs[0], "onetwo")) tst_res(TFAIL, "Error in first received message."); else tst_res(TPASS, "First message received successfully."); bufs[1][msgs[1].msg_len] = 0; if (strcmp(bufs[1], "three")) tst_res(TFAIL, "Error in second received message."); else tst_res(TPASS, "Second message received successfully."); return NULL; } static void run(void) { pthread_t sender; pthread_t receiver; SAFE_PTHREAD_CREATE(&sender, NULL, sender_thread, NULL); SAFE_PTHREAD_CREATE(&receiver, NULL, receiver_thread, NULL); SAFE_PTHREAD_JOIN(sender, NULL); SAFE_PTHREAD_JOIN(receiver, NULL); } static struct tst_test test = { .test_all = run, };