• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
sender_thread(LTP_ATTRIBUTE_UNUSED void * arg)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 
receiver_thread(LTP_ATTRIBUTE_UNUSED void * arg)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 
run(void)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