1 /*
2  * Copyright (c) 2015 Intel Corporation
3  * Copyright (c) 2023 Arm Limited (or its affiliates). All rights reserved.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #include <zephyr/logging/log.h>
9 LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
10 
11 #include <zephyr/kernel.h>
12 
13 #include <zephyr/linker/sections.h>
14 #include <zephyr/toolchain.h>
15 
16 #include <zephyr/net/socket.h>
17 #include <zephyr/net/socket_service.h>
18 #include <zephyr/net/zperf.h>
19 
20 #include "zperf_internal.h"
21 #include "zperf_session.h"
22 
23 /* To get net_sprint_ipv{4|6}_addr() */
24 #define NET_LOG_ENABLED 1
25 #include "net_private.h"
26 
27 #define SOCK_ID_IPV4_LISTEN 0
28 #define SOCK_ID_IPV6_LISTEN 1
29 #define SOCK_ID_MAX         (CONFIG_NET_ZPERF_MAX_SESSIONS + 2)
30 
31 #define TCP_RECEIVER_BUF_SIZE 1500
32 
33 static zperf_callback tcp_session_cb;
34 static void *tcp_user_data;
35 static bool tcp_server_running;
36 static uint16_t tcp_server_port;
37 static struct sockaddr tcp_server_addr;
38 
39 static struct zsock_pollfd fds[SOCK_ID_MAX];
40 static struct sockaddr sock_addr[SOCK_ID_MAX];
41 
42 static void tcp_svc_handler(struct net_socket_service_event *pev);
43 
44 NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(svc_tcp, tcp_svc_handler,
45 				      SOCK_ID_MAX);
46 
tcp_received(const struct sockaddr * addr,size_t datalen)47 static void tcp_received(const struct sockaddr *addr, size_t datalen)
48 {
49 	struct session *session;
50 	int64_t time;
51 
52 	time = k_uptime_ticks();
53 
54 	session = get_session(addr, SESSION_TCP);
55 	if (!session) {
56 		NET_ERR("Cannot get a session!");
57 		return;
58 	}
59 
60 	switch (session->state) {
61 	case STATE_COMPLETED:
62 	case STATE_NULL:
63 		zperf_reset_session_stats(session);
64 		session->start_time = k_uptime_ticks();
65 		session->state = STATE_ONGOING;
66 
67 		if (tcp_session_cb != NULL) {
68 			tcp_session_cb(ZPERF_SESSION_STARTED, NULL,
69 				       tcp_user_data);
70 		}
71 
72 		__fallthrough;
73 	case STATE_ONGOING:
74 		session->counter++;
75 		session->length += datalen;
76 
77 		if (datalen == 0) { /* EOF */
78 			struct zperf_results results = { 0 };
79 
80 			session->state = STATE_COMPLETED;
81 
82 			results.total_len = session->length;
83 			results.time_in_us = k_ticks_to_us_ceil64(
84 						time - session->start_time);
85 
86 			if (tcp_session_cb != NULL) {
87 				tcp_session_cb(ZPERF_SESSION_FINISHED, &results,
88 					       tcp_user_data);
89 			}
90 		}
91 		break;
92 	default:
93 		NET_ERR("Unsupported case");
94 	}
95 }
96 
tcp_session_error_report(void)97 static void tcp_session_error_report(void)
98 {
99 	if (tcp_session_cb != NULL) {
100 		tcp_session_cb(ZPERF_SESSION_ERROR, NULL, tcp_user_data);
101 	}
102 }
103 
tcp_receiver_cleanup(void)104 static void tcp_receiver_cleanup(void)
105 {
106 	int i;
107 
108 	(void)net_socket_service_unregister(&svc_tcp);
109 
110 	for (i = 0; i < ARRAY_SIZE(fds); i++) {
111 		if (fds[i].fd >= 0) {
112 			zsock_close(fds[i].fd);
113 			fds[i].fd = -1;
114 			memset(&sock_addr[i], 0, sizeof(struct sockaddr));
115 		}
116 	}
117 
118 	tcp_server_running = false;
119 	tcp_session_cb = NULL;
120 
121 	zperf_session_reset(SESSION_TCP);
122 }
123 
tcp_recv_data(struct net_socket_service_event * pev)124 static int tcp_recv_data(struct net_socket_service_event *pev)
125 {
126 	static uint8_t buf[TCP_RECEIVER_BUF_SIZE];
127 	int i, ret = 0;
128 	int family, sock, sock_error;
129 	struct sockaddr addr_incoming_conn;
130 	socklen_t optlen = sizeof(int);
131 	socklen_t addrlen = sizeof(struct sockaddr);
132 
133 	if (!tcp_server_running) {
134 		return -ENOENT;
135 	}
136 
137 	if ((pev->event.revents & ZSOCK_POLLERR) ||
138 	    (pev->event.revents & ZSOCK_POLLNVAL)) {
139 		(void)zsock_getsockopt(pev->event.fd, SOL_SOCKET,
140 				       SO_DOMAIN, &family, &optlen);
141 		(void)zsock_getsockopt(pev->event.fd, SOL_SOCKET,
142 				       SO_ERROR, &sock_error, &optlen);
143 		NET_ERR("TCP receiver IPv%d socket error (%d)",
144 			family == AF_INET ? 4 : 6, sock_error);
145 		ret = -sock_error;
146 		goto error;
147 	}
148 
149 	if (!(pev->event.revents & ZSOCK_POLLIN)) {
150 		return 0;
151 	}
152 
153 	/* What is the index to first accepted socket */
154 	i = SOCK_ID_IPV6_LISTEN + 1;
155 
156 	/* Check first if we need to accept a connection */
157 	if (fds[SOCK_ID_IPV4_LISTEN].fd == pev->event.fd ||
158 	    fds[SOCK_ID_IPV6_LISTEN].fd == pev->event.fd) {
159 		sock = zsock_accept(pev->event.fd,
160 				    &addr_incoming_conn,
161 				    &addrlen);
162 		if (sock < 0) {
163 			ret = -errno;
164 			(void)zsock_getsockopt(pev->event.fd, SOL_SOCKET,
165 					       SO_DOMAIN, &family, &optlen);
166 			NET_ERR("TCP receiver IPv%d accept error (%d)",
167 				family == AF_INET ? 4 : 6, ret);
168 			goto error;
169 		}
170 
171 		for (; i < SOCK_ID_MAX; i++) {
172 			if (fds[i].fd < 0) {
173 				break;
174 			}
175 		}
176 
177 		if (i == SOCK_ID_MAX) {
178 			/* Too many connections. */
179 			NET_ERR("Dropping TCP connection, reached maximum limit.");
180 			zsock_close(sock);
181 		} else {
182 			fds[i].fd = sock;
183 			fds[i].events = ZSOCK_POLLIN;
184 			memcpy(&sock_addr[i], &addr_incoming_conn, addrlen);
185 
186 			(void)net_socket_service_register(&svc_tcp, fds,
187 							  ARRAY_SIZE(fds),
188 							  NULL);
189 		}
190 
191 	} else {
192 		ret = zsock_recv(pev->event.fd, buf, sizeof(buf), 0);
193 		if (ret < 0) {
194 			(void)zsock_getsockopt(pev->event.fd, SOL_SOCKET,
195 					       SO_DOMAIN, &family, &optlen);
196 			NET_ERR("recv failed on IPv%d socket (%d)",
197 				family == AF_INET ? 4 : 6,
198 				errno);
199 			tcp_session_error_report();
200 			/* This will close the zperf session */
201 			ret = 0;
202 		}
203 
204 		for (; i < SOCK_ID_MAX; i++) {
205 			if (fds[i].fd == pev->event.fd) {
206 				break;
207 			}
208 		}
209 
210 		if (i == SOCK_ID_MAX) {
211 			NET_ERR("Descriptor %d not found.", pev->event.fd);
212 		} else {
213 			tcp_received(&sock_addr[i], ret);
214 			if (ret == 0) {
215 				zsock_close(fds[i].fd);
216 				fds[i].fd = -1;
217 				memset(&sock_addr[i], 0, sizeof(struct sockaddr));
218 
219 				(void)net_socket_service_register(&svc_tcp, fds,
220 								  ARRAY_SIZE(fds),
221 								  NULL);
222 			}
223 		}
224 	}
225 
226 	return ret;
227 
228 error:
229 	tcp_session_error_report();
230 
231 	return ret;
232 }
233 
tcp_svc_handler(struct net_socket_service_event * pev)234 static void tcp_svc_handler(struct net_socket_service_event *pev)
235 {
236 	int ret;
237 
238 	ret = tcp_recv_data(pev);
239 	if (ret < 0) {
240 		tcp_receiver_cleanup();
241 	}
242 }
243 
tcp_bind_listen_connection(struct zsock_pollfd * pollfd,struct sockaddr * address)244 static int tcp_bind_listen_connection(struct zsock_pollfd *pollfd,
245 				      struct sockaddr *address)
246 {
247 	uint16_t port;
248 	int ret;
249 
250 	if (address->sa_family == AF_INET) {
251 		port = ntohs(net_sin(address)->sin_port);
252 	} else {
253 		port = ntohs(net_sin6(address)->sin6_port);
254 	}
255 
256 	ret = zsock_bind(pollfd->fd, address, sizeof(*address));
257 	if (ret < 0) {
258 		NET_ERR("Cannot bind IPv%d TCP port %d (%d)",
259 			address->sa_family == AF_INET ? 4 : 6, port, errno);
260 		goto out;
261 	}
262 
263 	ret = zsock_listen(pollfd->fd, 1);
264 	if (ret < 0) {
265 		NET_ERR("Cannot listen IPv%d TCP (%d)",
266 			address->sa_family == AF_INET ? 4 : 6, errno);
267 		goto out;
268 	}
269 
270 	pollfd->events = ZSOCK_POLLIN;
271 
272 out:
273 	return ret;
274 }
275 
zperf_tcp_receiver_init(void)276 static int zperf_tcp_receiver_init(void)
277 {
278 	int ret;
279 	int family;
280 
281 	for (int i = 0; i < ARRAY_SIZE(fds); i++) {
282 		fds[i].fd = -1;
283 	}
284 
285 	family = tcp_server_addr.sa_family;
286 
287 	if (IS_ENABLED(CONFIG_NET_IPV4) && (family == AF_INET || family == AF_UNSPEC)) {
288 		struct sockaddr_in *in4_addr = zperf_get_sin();
289 		const struct in_addr *addr = NULL;
290 
291 		fds[SOCK_ID_IPV4_LISTEN].fd = zsock_socket(AF_INET, SOCK_STREAM,
292 							   IPPROTO_TCP);
293 		if (fds[SOCK_ID_IPV4_LISTEN].fd < 0) {
294 			ret = -errno;
295 			NET_ERR("Cannot create IPv4 network socket.");
296 			goto error;
297 		}
298 
299 		addr = &net_sin(&tcp_server_addr)->sin_addr;
300 
301 		if (!net_ipv4_is_addr_unspecified(addr)) {
302 			memcpy(&in4_addr->sin_addr, addr,
303 				sizeof(struct in_addr));
304 		} else if (strlen(MY_IP4ADDR ? MY_IP4ADDR : "")) {
305 			/* Use Setting IP */
306 			ret = zperf_get_ipv4_addr(MY_IP4ADDR,
307 						  &in4_addr->sin_addr);
308 			if (ret < 0) {
309 				NET_WARN("Unable to set IPv4");
310 				goto use_any_ipv4;
311 			}
312 		} else {
313 use_any_ipv4:
314 			in4_addr->sin_addr.s_addr = INADDR_ANY;
315 		}
316 
317 		in4_addr->sin_port = htons(tcp_server_port);
318 
319 		NET_INFO("Binding to %s",
320 			 net_sprint_ipv4_addr(&in4_addr->sin_addr));
321 
322 		memcpy(net_sin(&sock_addr[SOCK_ID_IPV4_LISTEN]), in4_addr,
323 		       sizeof(struct sockaddr_in));
324 
325 		ret = tcp_bind_listen_connection(
326 				&fds[SOCK_ID_IPV4_LISTEN],
327 				&sock_addr[SOCK_ID_IPV4_LISTEN]);
328 		if (ret < 0) {
329 			goto error;
330 		}
331 	}
332 
333 	if (IS_ENABLED(CONFIG_NET_IPV6) && (family == AF_INET6 || family == AF_UNSPEC)) {
334 		struct sockaddr_in6 *in6_addr = zperf_get_sin6();
335 		const struct in6_addr *addr = NULL;
336 
337 		fds[SOCK_ID_IPV6_LISTEN].fd = zsock_socket(AF_INET6, SOCK_STREAM,
338 							   IPPROTO_TCP);
339 		if (fds[SOCK_ID_IPV6_LISTEN].fd < 0) {
340 			ret = -errno;
341 			NET_ERR("Cannot create IPv6 network socket.");
342 			goto error;
343 		}
344 
345 		addr = &net_sin6(&tcp_server_addr)->sin6_addr;
346 
347 		if (!net_ipv6_is_addr_unspecified(addr)) {
348 			memcpy(&in6_addr->sin6_addr, addr,
349 			       sizeof(struct in6_addr));
350 		} else if (strlen(MY_IP6ADDR ? MY_IP6ADDR : "")) {
351 			/* Use Setting IP */
352 			ret = zperf_get_ipv6_addr(MY_IP6ADDR,
353 						  MY_PREFIX_LEN_STR,
354 						  &in6_addr->sin6_addr);
355 			if (ret < 0) {
356 				NET_WARN("Unable to set IPv6");
357 				goto use_any_ipv6;
358 			}
359 		} else {
360 use_any_ipv6:
361 			memcpy(&in6_addr->sin6_addr, net_ipv6_unspecified_address(),
362 			       sizeof(struct in6_addr));
363 		}
364 
365 		in6_addr->sin6_port = htons(tcp_server_port);
366 
367 		NET_INFO("Binding to %s",
368 			 net_sprint_ipv6_addr(&in6_addr->sin6_addr));
369 
370 		memcpy(net_sin6(&sock_addr[SOCK_ID_IPV6_LISTEN]), in6_addr,
371 		       sizeof(struct sockaddr_in6));
372 
373 		ret = tcp_bind_listen_connection(
374 				&fds[SOCK_ID_IPV6_LISTEN],
375 				&sock_addr[SOCK_ID_IPV6_LISTEN]);
376 		if (ret < 0) {
377 			goto error;
378 		}
379 	}
380 
381 	NET_INFO("Listening on port %d", tcp_server_port);
382 
383 	ret = net_socket_service_register(&svc_tcp, fds,
384 					  ARRAY_SIZE(fds), NULL);
385 	if (ret < 0) {
386 		LOG_ERR("Cannot register socket service handler (%d)", ret);
387 	}
388 
389 error:
390 	return ret;
391 }
392 
zperf_tcp_download(const struct zperf_download_params * param,zperf_callback callback,void * user_data)393 int zperf_tcp_download(const struct zperf_download_params *param,
394 		       zperf_callback callback, void *user_data)
395 {
396 	int ret;
397 
398 	if (param == NULL || callback == NULL) {
399 		return -EINVAL;
400 	}
401 
402 	if (tcp_server_running) {
403 		return -EALREADY;
404 	}
405 
406 	tcp_session_cb = callback;
407 	tcp_user_data = user_data;
408 	tcp_server_port = param->port;
409 	memcpy(&tcp_server_addr, &param->addr, sizeof(struct sockaddr));
410 
411 	ret = zperf_tcp_receiver_init();
412 	if (ret < 0) {
413 		tcp_receiver_cleanup();
414 		return ret;
415 	}
416 
417 	tcp_server_running = true;
418 
419 	return 0;
420 }
421 
zperf_tcp_download_stop(void)422 int zperf_tcp_download_stop(void)
423 {
424 	if (!tcp_server_running) {
425 		return -EALREADY;
426 	}
427 
428 	tcp_receiver_cleanup();
429 
430 	return 0;
431 }
432