1 /* udp.c - UDP specific code for echo client */
2
3 /*
4 * Copyright (c) 2017 Intel Corporation.
5 * Copyright (c) 2018 Nordic Semiconductor ASA.
6 *
7 * SPDX-License-Identifier: Apache-2.0
8 */
9
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_DECLARE(net_echo_client_sample, LOG_LEVEL_DBG);
12
13 #include <zephyr/kernel.h>
14 #include <errno.h>
15 #include <stdio.h>
16
17 #include <zephyr/net/socket.h>
18 #include <zephyr/net/tls_credentials.h>
19 #include <zephyr/random/random.h>
20
21 #include "common.h"
22 #include "ca_certificate.h"
23
24 #define RECV_BUF_SIZE 1280
25 #define UDP_SLEEP K_MSEC(150)
26 #define UDP_WAIT K_SECONDS(10)
27
28 static APP_BMEM char recv_buf[RECV_BUF_SIZE];
29
30 static K_THREAD_STACK_DEFINE(udp_tx_thread_stack, UDP_STACK_SIZE);
31 static struct k_thread udp_tx_thread;
32
33 /* Kernel objects should not be placed in a memory area accessible from user
34 * threads.
35 */
36 static struct udp_control udp4_ctrl, udp6_ctrl;
37 static struct k_poll_signal udp_kill;
38
39 static int send_udp_data(struct sample_data *data);
40 static void wait_reply(struct k_timer *timer);
41 static void wait_transmit(struct k_timer *timer);
42
process_udp_tx(void * p1,void * p2,void * p3)43 static void process_udp_tx(void *p1, void *p2, void *p3)
44 {
45 ARG_UNUSED(p1);
46 ARG_UNUSED(p2);
47 ARG_UNUSED(p3);
48
49 struct k_poll_event events[] = {
50 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
51 K_POLL_MODE_NOTIFY_ONLY,
52 &udp_kill),
53 #if defined(CONFIG_NET_IPV4)
54 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
55 K_POLL_MODE_NOTIFY_ONLY,
56 &udp4_ctrl.tx_signal),
57 #endif
58 #if defined(CONFIG_NET_IPV6)
59 K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
60 K_POLL_MODE_NOTIFY_ONLY,
61 &udp6_ctrl.tx_signal),
62 #endif
63 };
64
65 while (true) {
66 k_poll(events, ARRAY_SIZE(events), K_FOREVER);
67
68 for (int i = 0; i < ARRAY_SIZE(events); i++) {
69 unsigned int signaled;
70 int result;
71
72 k_poll_signal_check(events[i].signal, &signaled, &result);
73 if (signaled == 0) {
74 continue;
75 }
76
77 k_poll_signal_reset(events[i].signal);
78 events[i].state = K_POLL_STATE_NOT_READY;
79
80 if (events[i].signal == &udp_kill) {
81 return;
82 } else if (events[i].signal == &udp4_ctrl.tx_signal) {
83 send_udp_data(&conf.ipv4);
84 } else if (events[i].signal == &udp6_ctrl.tx_signal) {
85 send_udp_data(&conf.ipv6);
86 }
87 }
88 }
89 }
90
udp_control_init(struct udp_control * ctrl)91 static void udp_control_init(struct udp_control *ctrl)
92 {
93 k_timer_init(&ctrl->rx_timer, wait_reply, NULL);
94 k_timer_init(&ctrl->tx_timer, wait_transmit, NULL);
95 k_poll_signal_init(&ctrl->tx_signal);
96 }
97
udp_control_access_grant(struct udp_control * ctrl)98 static void udp_control_access_grant(struct udp_control *ctrl)
99 {
100 k_thread_access_grant(k_current_get(),
101 &ctrl->rx_timer,
102 &ctrl->tx_timer,
103 &ctrl->tx_signal);
104 }
105
init_udp(void)106 void init_udp(void)
107 {
108 /* k_timer_init() is not a system call, therefore initialize kernel
109 * objects here.
110 */
111 if (IS_ENABLED(CONFIG_NET_IPV4)) {
112 udp_control_init(&udp4_ctrl);
113 conf.ipv4.udp.ctrl = &udp4_ctrl;
114 }
115
116 if (IS_ENABLED(CONFIG_NET_IPV6)) {
117 udp_control_init(&udp6_ctrl);
118 conf.ipv6.udp.ctrl = &udp6_ctrl;
119 }
120
121 k_poll_signal_init(&udp_kill);
122
123 if (IS_ENABLED(CONFIG_USERSPACE)) {
124 k_thread_access_grant(k_current_get(),
125 &udp_tx_thread,
126 &udp_tx_thread_stack,
127 &udp_kill);
128
129 if (IS_ENABLED(CONFIG_NET_IPV4)) {
130 udp_control_access_grant(&udp4_ctrl);
131 }
132
133 if (IS_ENABLED(CONFIG_NET_IPV6)) {
134 udp_control_access_grant(&udp6_ctrl);
135 }
136 }
137 }
138
send_udp_data(struct sample_data * data)139 static int send_udp_data(struct sample_data *data)
140 {
141 int ret;
142
143 do {
144 data->udp.expecting = sys_rand32_get() % ipsum_len;
145 } while (data->udp.expecting == 0U ||
146 data->udp.expecting > data->udp.mtu);
147
148 ret = send(data->udp.sock, lorem_ipsum, data->udp.expecting, 0);
149
150 if (PRINT_PROGRESS) {
151 LOG_DBG("%s UDP: Sent %d bytes", data->proto, data->udp.expecting);
152 }
153
154 k_timer_start(&data->udp.ctrl->rx_timer, UDP_WAIT, K_NO_WAIT);
155
156 return ret < 0 ? -EIO : 0;
157 }
158
compare_udp_data(struct sample_data * data,const char * buf,uint32_t received)159 static int compare_udp_data(struct sample_data *data, const char *buf, uint32_t received)
160 {
161 if (received != data->udp.expecting) {
162 LOG_ERR("Invalid amount of data received: UDP %s", data->proto);
163 return -EIO;
164 }
165
166 if (memcmp(buf, lorem_ipsum, received) != 0) {
167 LOG_ERR("Invalid data received: UDP %s", data->proto);
168 return -EIO;
169 }
170
171 return 0;
172 }
173
wait_reply(struct k_timer * timer)174 static void wait_reply(struct k_timer *timer)
175 {
176 /* This means that we did not receive response in time. */
177 struct udp_control *ctrl = CONTAINER_OF(timer, struct udp_control, rx_timer);
178 struct sample_data *data = (ctrl == conf.ipv4.udp.ctrl) ? &conf.ipv4 : &conf.ipv6;
179
180 LOG_ERR("UDP %s: Data packet not received", data->proto);
181
182 /* Send a new packet at this point */
183 k_poll_signal_raise(&ctrl->tx_signal, 0);
184 }
185
wait_transmit(struct k_timer * timer)186 static void wait_transmit(struct k_timer *timer)
187 {
188 struct udp_control *ctrl = CONTAINER_OF(timer, struct udp_control, tx_timer);
189
190 k_poll_signal_raise(&ctrl->tx_signal, 0);
191 }
192
start_udp_proto(struct sample_data * data,sa_family_t family,struct sockaddr * addr,socklen_t addrlen)193 static int start_udp_proto(struct sample_data *data, sa_family_t family,
194 struct sockaddr *addr, socklen_t addrlen)
195 {
196 int optval;
197 int ret;
198
199 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
200 data->udp.sock = socket(family, SOCK_DGRAM, IPPROTO_DTLS_1_2);
201 #else
202 data->udp.sock = socket(family, SOCK_DGRAM, IPPROTO_UDP);
203 #endif
204 if (data->udp.sock < 0) {
205 LOG_ERR("Failed to create UDP socket (%s): %d", data->proto,
206 errno);
207 return -errno;
208 }
209
210 #if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
211 sec_tag_t sec_tag_list[] = {
212 CA_CERTIFICATE_TAG,
213 #if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
214 PSK_TAG,
215 #endif
216 };
217
218 ret = setsockopt(data->udp.sock, SOL_TLS, TLS_SEC_TAG_LIST,
219 sec_tag_list, sizeof(sec_tag_list));
220 if (ret < 0) {
221 LOG_ERR("Failed to set TLS_SEC_TAG_LIST option (%s): %d",
222 data->proto, errno);
223 ret = -errno;
224 }
225
226 ret = setsockopt(data->udp.sock, SOL_TLS, TLS_HOSTNAME,
227 TLS_PEER_HOSTNAME, sizeof(TLS_PEER_HOSTNAME));
228 if (ret < 0) {
229 LOG_ERR("Failed to set TLS_HOSTNAME option (%s): %d",
230 data->proto, errno);
231 ret = -errno;
232 }
233 #endif
234
235 /* Prefer IPv6 temporary addresses */
236 if (family == AF_INET6) {
237 optval = IPV6_PREFER_SRC_TMP;
238 (void)setsockopt(data->udp.sock, IPPROTO_IPV6,
239 IPV6_ADDR_PREFERENCES,
240 &optval, sizeof(optval));
241 }
242
243 /* Call connect so we can use send and recv. */
244 ret = connect(data->udp.sock, addr, addrlen);
245 if (ret < 0) {
246 LOG_ERR("Cannot connect to UDP remote (%s): %d", data->proto,
247 errno);
248 ret = -errno;
249 }
250
251 return ret;
252 }
253
process_udp_proto(struct sample_data * data)254 static int process_udp_proto(struct sample_data *data)
255 {
256 int ret, received;
257
258 received = recv(data->udp.sock, recv_buf, sizeof(recv_buf),
259 MSG_DONTWAIT);
260
261 if (received == 0) {
262 return -EIO;
263 }
264 if (received < 0) {
265 if (errno == EAGAIN || errno == EWOULDBLOCK) {
266 ret = 0;
267 } else {
268 ret = -errno;
269 }
270 return ret;
271 }
272
273 ret = compare_udp_data(data, recv_buf, received);
274 if (ret != 0) {
275 LOG_WRN("%s UDP: Received and compared %d bytes, data "
276 "mismatch", data->proto, received);
277 return 0;
278 }
279
280 if (PRINT_PROGRESS) {
281 /* Correct response received */
282 LOG_DBG("%s UDP: Received and compared %d bytes, all ok",
283 data->proto, received);
284 }
285
286 if (++data->udp.counter % 1000 == 0U) {
287 LOG_INF("%s UDP: Exchanged %u packets", data->proto,
288 data->udp.counter);
289 }
290
291 k_timer_stop(&data->udp.ctrl->rx_timer);
292
293 /* Do not flood the link if we have also TCP configured */
294 if (IS_ENABLED(CONFIG_NET_TCP)) {
295 k_timer_start(&data->udp.ctrl->tx_timer, UDP_SLEEP, K_NO_WAIT);
296 } else {
297 k_poll_signal_raise(&data->udp.ctrl->tx_signal, 0);
298 }
299
300 return ret;
301 }
302
start_udp(void)303 int start_udp(void)
304 {
305 int ret = 0;
306 struct sockaddr_in addr4;
307 struct sockaddr_in6 addr6;
308
309 if (IS_ENABLED(CONFIG_NET_IPV6)) {
310 addr6.sin6_family = AF_INET6;
311 addr6.sin6_port = htons(PEER_PORT);
312 inet_pton(AF_INET6, CONFIG_NET_CONFIG_PEER_IPV6_ADDR,
313 &addr6.sin6_addr);
314
315 ret = start_udp_proto(&conf.ipv6, AF_INET6,
316 (struct sockaddr *)&addr6,
317 sizeof(addr6));
318 if (ret < 0) {
319 return ret;
320 }
321 }
322
323 if (IS_ENABLED(CONFIG_NET_IPV4)) {
324 addr4.sin_family = AF_INET;
325 addr4.sin_port = htons(PEER_PORT);
326 inet_pton(AF_INET, CONFIG_NET_CONFIG_PEER_IPV4_ADDR,
327 &addr4.sin_addr);
328
329 ret = start_udp_proto(&conf.ipv4, AF_INET,
330 (struct sockaddr *)&addr4,
331 sizeof(addr4));
332 if (ret < 0) {
333 return ret;
334 }
335 }
336
337 k_thread_create(&udp_tx_thread, udp_tx_thread_stack,
338 K_THREAD_STACK_SIZEOF(udp_tx_thread_stack),
339 process_udp_tx,
340 NULL, NULL, NULL, THREAD_PRIORITY,
341 IS_ENABLED(CONFIG_USERSPACE) ?
342 K_USER | K_INHERIT_PERMS : 0,
343 K_NO_WAIT);
344
345 k_thread_name_set(&udp_tx_thread, "udp_tx");
346
347 if (IS_ENABLED(CONFIG_NET_IPV6)) {
348 k_poll_signal_raise(&conf.ipv6.udp.ctrl->tx_signal, 0);
349 }
350
351 if (IS_ENABLED(CONFIG_NET_IPV4)) {
352 k_poll_signal_raise(&conf.ipv4.udp.ctrl->tx_signal, 0);
353 }
354
355 return ret;
356 }
357
process_udp(void)358 int process_udp(void)
359 {
360 int ret = 0;
361
362 if (IS_ENABLED(CONFIG_NET_IPV6)) {
363 ret = process_udp_proto(&conf.ipv6);
364 if (ret < 0) {
365 return ret;
366 }
367 }
368
369 if (IS_ENABLED(CONFIG_NET_IPV4)) {
370 ret = process_udp_proto(&conf.ipv4);
371 if (ret < 0) {
372 return ret;
373 }
374 }
375
376 return ret;
377 }
378
stop_udp(void)379 void stop_udp(void)
380 {
381 if (IS_ENABLED(CONFIG_NET_IPV6)) {
382 k_timer_stop(&udp6_ctrl.tx_timer);
383 k_timer_stop(&udp6_ctrl.rx_timer);
384
385 if (conf.ipv6.udp.sock >= 0) {
386 (void)close(conf.ipv6.udp.sock);
387 }
388 }
389
390 if (IS_ENABLED(CONFIG_NET_IPV4)) {
391 k_timer_stop(&udp4_ctrl.tx_timer);
392 k_timer_stop(&udp4_ctrl.rx_timer);
393
394 if (conf.ipv4.udp.sock >= 0) {
395 (void)close(conf.ipv4.udp.sock);
396 }
397 }
398
399 k_poll_signal_raise(&udp_kill, 0);
400 }
401