1 /*
2  * Copyright (c) 2019 Linaro Limited
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
9 
10 #include <stdio.h>
11 #include <zephyr/ztest_assert.h>
12 
13 #include <zephyr/net/socket.h>
14 #include <zephyr/sys/fdtable.h>
15 
16 #include "../../socket_helpers.h"
17 
18 #define BUF_AND_SIZE(buf) buf, sizeof(buf) - 1
19 #define STRLEN(buf) (sizeof(buf) - 1)
20 
21 #define TEST_STR_SMALL "test"
22 
23 #define MY_IPV6_ADDR "::1"
24 
25 #define ANY_PORT 0
26 #define SERVER_PORT 4242
27 #define CLIENT_PORT 9898
28 
29 /* On QEMU, poll() which waits takes +10ms from the requested time. */
30 #define FUZZ 10
31 
32 #define TCP_TEARDOWN_TIMEOUT K_SECONDS(3)
33 
ZTEST(net_socket_poll,test_poll)34 ZTEST(net_socket_poll, test_poll)
35 {
36 	int res;
37 	int c_sock;
38 	int s_sock;
39 	int c_sock_tcp;
40 	int s_sock_tcp;
41 	struct sockaddr_in6 c_addr;
42 	struct sockaddr_in6 s_addr;
43 	struct zsock_pollfd pollfds[2];
44 	struct zsock_pollfd pollout[1];
45 	uint32_t tstamp;
46 	ssize_t len;
47 	char buf[10];
48 
49 	prepare_sock_udp_v6(MY_IPV6_ADDR, CLIENT_PORT, &c_sock, &c_addr);
50 	prepare_sock_udp_v6(MY_IPV6_ADDR, SERVER_PORT, &s_sock, &s_addr);
51 	prepare_sock_tcp_v6(MY_IPV6_ADDR, CLIENT_PORT, &c_sock_tcp, &c_addr);
52 	prepare_sock_tcp_v6(MY_IPV6_ADDR, SERVER_PORT, &s_sock_tcp, &s_addr);
53 
54 	res = zsock_bind(s_sock, (struct sockaddr *)&s_addr, sizeof(s_addr));
55 	zassert_equal(res, 0, "bind failed");
56 
57 	res = zsock_connect(c_sock, (struct sockaddr *)&s_addr, sizeof(s_addr));
58 	zassert_equal(res, 0, "connect failed");
59 
60 	memset(pollfds, 0, sizeof(pollfds));
61 	pollfds[0].fd = c_sock;
62 	pollfds[0].events = ZSOCK_POLLIN;
63 	pollfds[1].fd = s_sock;
64 	pollfds[1].events = ZSOCK_POLLIN;
65 
66 	/* Poll non-ready fd's with timeout of 0 */
67 	tstamp = k_uptime_get_32();
68 	res = zsock_poll(pollfds, ARRAY_SIZE(pollfds), 0);
69 	zassert_true(k_uptime_get_32() - tstamp <= FUZZ, "");
70 	zassert_equal(res, 0, "");
71 
72 	zassert_equal(pollfds[0].fd, c_sock, "");
73 	zassert_equal(pollfds[0].events, ZSOCK_POLLIN, "");
74 	zassert_equal(pollfds[0].revents, 0, "");
75 	zassert_equal(pollfds[1].fd, s_sock, "");
76 	zassert_equal(pollfds[1].events, ZSOCK_POLLIN, "");
77 	zassert_equal(pollfds[1].revents, 0, "");
78 
79 
80 	/* Poll non-ready fd's with timeout of 30 */
81 	tstamp = k_uptime_get_32();
82 	res = zsock_poll(pollfds, ARRAY_SIZE(pollfds), 30);
83 	tstamp = k_uptime_get_32() - tstamp;
84 	zassert_true(tstamp >= 30U && tstamp <= 30 + FUZZ * 2, "tstamp %d",
85 		     tstamp);
86 	zassert_equal(res, 0, "");
87 
88 	/* Send pkt for s_sock and poll with timeout of 10 */
89 	len = zsock_send(c_sock, BUF_AND_SIZE(TEST_STR_SMALL), 0);
90 	zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid send len");
91 
92 	tstamp = k_uptime_get_32();
93 	res = zsock_poll(pollfds, ARRAY_SIZE(pollfds), 30);
94 	tstamp = k_uptime_get_32() - tstamp;
95 	zassert_true(tstamp <= FUZZ, "");
96 	zassert_equal(res, 1, "");
97 
98 	zassert_equal(pollfds[0].fd, c_sock, "");
99 	zassert_equal(pollfds[0].events, ZSOCK_POLLIN, "");
100 	zassert_equal(pollfds[0].revents, 0, "");
101 	zassert_equal(pollfds[1].fd, s_sock, "");
102 	zassert_equal(pollfds[1].events, ZSOCK_POLLIN, "");
103 	zassert_equal(pollfds[1].revents, ZSOCK_POLLIN, "");
104 
105 
106 	/* Recv pkt from s_sock and ensure no poll events happen */
107 	len = zsock_recv(s_sock, BUF_AND_SIZE(buf), 0);
108 	zassert_equal(len, STRLEN(TEST_STR_SMALL), "invalid recv len");
109 
110 	tstamp = k_uptime_get_32();
111 	res = zsock_poll(pollfds, ARRAY_SIZE(pollfds), 0);
112 	zassert_true(k_uptime_get_32() - tstamp <= FUZZ, "");
113 	zassert_equal(res, 0, "");
114 	zassert_equal(pollfds[1].revents, 0, "");
115 
116 	/* Make sure that POLLOUT does not wait if not really needed */
117 	memset(pollout, 0, sizeof(pollout));
118 	pollout[0].fd = c_sock;
119 	pollout[0].events = ZSOCK_POLLOUT;
120 
121 	res = zsock_connect(c_sock, (const struct sockaddr *)&s_addr,
122 			    sizeof(s_addr));
123 	zassert_equal(res, 0, "");
124 
125 	tstamp = k_uptime_get_32();
126 	res = zsock_poll(pollout, ARRAY_SIZE(pollout), 200);
127 	zassert_true(k_uptime_get_32() - tstamp < 100, "");
128 	zassert_equal(res, 1, "");
129 	zassert_equal(pollout[0].revents, ZSOCK_POLLOUT, "");
130 
131 	/* First test that TCP POLLOUT will not wait if there is enough
132 	 * room in TCP window
133 	 */
134 	memset(pollout, 0, sizeof(pollout));
135 	pollout[0].fd = c_sock_tcp;
136 	pollout[0].events = ZSOCK_POLLOUT;
137 
138 	res = zsock_bind(s_sock_tcp, (struct sockaddr *)&s_addr, sizeof(s_addr));
139 	zassert_equal(res, 0, "");
140 	res = zsock_listen(s_sock_tcp, 0);
141 	zassert_equal(res, 0, "");
142 
143 	res = zsock_connect(c_sock_tcp, (const struct sockaddr *)&s_addr,
144 			    sizeof(s_addr));
145 	zassert_equal(res, 0, "");
146 
147 	tstamp = k_uptime_get_32();
148 	res = zsock_poll(pollout, ARRAY_SIZE(pollout), 200);
149 	zassert_true(k_uptime_get_32() - tstamp < 100, "");
150 	zassert_equal(res, 1, "");
151 	zassert_equal(pollout[0].revents, ZSOCK_POLLOUT, "");
152 
153 	res = zsock_close(c_sock_tcp);
154 	zassert_equal(res, 0, "close failed");
155 
156 	res = zsock_close(s_sock_tcp);
157 	zassert_equal(res, 0, "close failed");
158 
159 	/* Close one socket and ensure POLLNVAL happens */
160 	res = zsock_close(c_sock);
161 	zassert_equal(res, 0, "close failed");
162 
163 	tstamp = k_uptime_get_32();
164 	res = zsock_poll(pollfds, ARRAY_SIZE(pollfds), 0);
165 	zassert_true(k_uptime_get_32() - tstamp <= FUZZ, "");
166 	zassert_equal(res, 1, "");
167 	zassert_equal(pollfds[0].revents, ZSOCK_POLLNVAL, "");
168 	zassert_equal(pollfds[1].revents, 0, "");
169 
170 	res = zsock_close(s_sock);
171 	zassert_equal(res, 0, "close failed");
172 
173 	k_sleep(TCP_TEARDOWN_TIMEOUT);
174 }
175 
176 #define TEST_SNDBUF_SIZE CONFIG_NET_TCP_MAX_RECV_WINDOW_SIZE
177 
ZTEST(net_socket_poll,test_pollout_tcp)178 ZTEST(net_socket_poll, test_pollout_tcp)
179 {
180 	int res;
181 	int c_sock;
182 	int s_sock;
183 	int new_sock;
184 	struct sockaddr_in6 c_addr;
185 	struct sockaddr_in6 s_addr;
186 	struct zsock_pollfd pollout[1];
187 	char buf[TEST_SNDBUF_SIZE] = { };
188 
189 	prepare_sock_tcp_v6(MY_IPV6_ADDR, CLIENT_PORT, &c_sock, &c_addr);
190 	prepare_sock_tcp_v6(MY_IPV6_ADDR, SERVER_PORT, &s_sock, &s_addr);
191 
192 	res = zsock_bind(s_sock, (struct sockaddr *)&s_addr, sizeof(s_addr));
193 	zassert_equal(res, 0, "");
194 	res = zsock_listen(s_sock, 0);
195 	zassert_equal(res, 0, "");
196 	res = zsock_connect(c_sock, (const struct sockaddr *)&s_addr,
197 			    sizeof(s_addr));
198 	zassert_equal(res, 0, "");
199 	new_sock = zsock_accept(s_sock, NULL, NULL);
200 	zassert_true(new_sock >= 0, "");
201 
202 	k_msleep(10);
203 
204 	/* POLLOUT should be reported after connecting */
205 	memset(pollout, 0, sizeof(pollout));
206 	pollout[0].fd = c_sock;
207 	pollout[0].events = ZSOCK_POLLOUT;
208 
209 	res = zsock_poll(pollout, ARRAY_SIZE(pollout), 10);
210 	zassert_equal(res, 1, "");
211 	zassert_equal(pollout[0].revents, ZSOCK_POLLOUT, "");
212 
213 	/* POLLOUT should not be reported after filling the window */
214 	res = zsock_send(c_sock, buf, sizeof(buf), 0);
215 	zassert_equal(res, sizeof(buf), "");
216 
217 	memset(pollout, 0, sizeof(pollout));
218 	pollout[0].fd = c_sock;
219 	pollout[0].events = ZSOCK_POLLOUT;
220 
221 	res = zsock_poll(pollout, ARRAY_SIZE(pollout), 10);
222 	zassert_equal(res, 0, "%d", pollout[0].revents);
223 	zassert_equal(pollout[0].revents, 0, "");
224 
225 	/* POLLOUT should be reported again after consuming the data server
226 	 * side.
227 	 */
228 	res = zsock_recv(new_sock, buf, sizeof(buf), 0);
229 	zassert_equal(res, sizeof(buf), "");
230 
231 	memset(pollout, 0, sizeof(pollout));
232 	pollout[0].fd = c_sock;
233 	pollout[0].events = ZSOCK_POLLOUT;
234 
235 	/* Wait longer this time to give TCP stack a chance to send ZWP. */
236 	res = zsock_poll(pollout, ARRAY_SIZE(pollout), 500);
237 	zassert_equal(res, 1, "");
238 	zassert_equal(pollout[0].revents, ZSOCK_POLLOUT, "");
239 
240 	k_msleep(10);
241 
242 	/* Finalize the test */
243 	res = zsock_close(c_sock);
244 	zassert_equal(res, 0, "close failed");
245 	res = zsock_close(s_sock);
246 	zassert_equal(res, 0, "close failed");
247 	res = zsock_close(new_sock);
248 	zassert_equal(res, 0, "close failed");
249 }
250 
251 ZTEST_SUITE(net_socket_poll, NULL, NULL, NULL, NULL, NULL);
252