blob: d1bdf40a1eb75ea2c97eb1cfba0d69e3a49a2798 [file] [log] [blame]
/*
* 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 <netinet/ip.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#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,
};