Home | History | Annotate | Download | only in sendmmsg
      1 /*
      2  * This test is based on source contained in the man pages for sendmmsg and
      3  * recvmmsg in release 4.15 of the Linux man-pages project.
      4  */
      5 
      6 #define _GNU_SOURCE
      7 #include <netinet/ip.h>
      8 #include <stdio.h>
      9 #include <stdlib.h>
     10 #include <string.h>
     11 #include <sys/types.h>
     12 #include <sys/socket.h>
     13 
     14 #include "tst_test.h"
     15 #include "tst_safe_macros.h"
     16 #include "tst_safe_pthread.h"
     17 
     18 #define BUFSIZE 16
     19 #define VLEN 2
     20 
     21 static void *sender_thread(LTP_ATTRIBUTE_UNUSED void *arg)
     22 {
     23 	struct sockaddr_in addr;
     24 	struct mmsghdr msg[2];
     25 	struct iovec msg1[2], msg2;
     26 	int send_sockfd;
     27 	int retval;
     28 
     29 	send_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
     30 
     31 	addr.sin_family = AF_INET;
     32 	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
     33 	addr.sin_port = htons(1234);
     34 	SAFE_CONNECT(send_sockfd, (struct sockaddr *) &addr, sizeof(addr));
     35 
     36 	memset(msg1, 0, sizeof(msg1));
     37 	msg1[0].iov_base = "one";
     38 	msg1[0].iov_len = 3;
     39 	msg1[1].iov_base = "two";
     40 	msg1[1].iov_len = 3;
     41 
     42 	memset(&msg2, 0, sizeof(msg2));
     43 	msg2.iov_base = "three";
     44 	msg2.iov_len = 5;
     45 
     46 	memset(msg, 0, sizeof(msg));
     47 	msg[0].msg_hdr.msg_iov = msg1;
     48 	msg[0].msg_hdr.msg_iovlen = 2;
     49 
     50 	msg[1].msg_hdr.msg_iov = &msg2;
     51 	msg[1].msg_hdr.msg_iovlen = 1;
     52 
     53 	retval = sendmmsg(send_sockfd, msg, 2, 0);
     54 	if (retval < 0)
     55 		tst_brk(TFAIL|TTERRNO, "sendmmsg failed");
     56 
     57 	return NULL;
     58 }
     59 
     60 
     61 static void *receiver_thread(LTP_ATTRIBUTE_UNUSED void *arg)
     62 {
     63 	int receive_sockfd;
     64 	struct sockaddr_in addr;
     65 	struct mmsghdr msgs[VLEN];
     66 	struct iovec iovecs[VLEN];
     67 	char bufs[VLEN][BUFSIZE+1];
     68 	struct timespec timeout;
     69 	int i, retval;
     70 
     71 	receive_sockfd = SAFE_SOCKET(AF_INET, SOCK_DGRAM, 0);
     72 	addr.sin_family = AF_INET;
     73 	addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
     74 	addr.sin_port = htons(1234);
     75 	SAFE_BIND(receive_sockfd, (struct sockaddr *)&addr, sizeof(addr));
     76 
     77 	memset(msgs, 0, sizeof(msgs));
     78 	for (i = 0; i < VLEN; i++) {
     79 		iovecs[i].iov_base = bufs[i];
     80 		iovecs[i].iov_len = BUFSIZE;
     81 		msgs[i].msg_hdr.msg_iov = &iovecs[i];
     82 		msgs[i].msg_hdr.msg_iovlen = 1;
     83 	}
     84 
     85 	timeout.tv_sec = 1;
     86 	timeout.tv_nsec = 0;
     87 
     88 	retval = recvmmsg(receive_sockfd, msgs, VLEN, 0, &timeout);
     89 	if (retval == -1)
     90 		tst_brk(TFAIL | TTERRNO, "recvmmsg failed");
     91 	if (retval != 2)
     92 		tst_brk(TFAIL, "Received unexpected number of messages (%d)",
     93 			retval);
     94 
     95 	bufs[0][msgs[0].msg_len] = 0;
     96 	if (strcmp(bufs[0], "onetwo"))
     97 		tst_res(TFAIL, "Error in first received message.");
     98 	else
     99 		tst_res(TPASS, "First message received successfully.");
    100 
    101 	bufs[1][msgs[1].msg_len] = 0;
    102 	if (strcmp(bufs[1], "three"))
    103 		tst_res(TFAIL, "Error in second received message.");
    104 	else
    105 		tst_res(TPASS, "Second message received successfully.");
    106 
    107 	return NULL;
    108 }
    109 
    110 static void run(void)
    111 {
    112 	pthread_t sender;
    113 	pthread_t receiver;
    114 
    115 	SAFE_PTHREAD_CREATE(&sender, NULL, sender_thread, NULL);
    116 	SAFE_PTHREAD_CREATE(&receiver, NULL, receiver_thread, NULL);
    117 	SAFE_PTHREAD_JOIN(sender, NULL);
    118 	SAFE_PTHREAD_JOIN(receiver, NULL);
    119 }
    120 
    121 static struct tst_test test = {
    122 	.test_all = run,
    123 };
    124