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, ¶m->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