XFusion API v1.3.0
载入中...
搜索中...
未找到
xf_iperf.c
浏览该文件的文档.
1
12/* Iperf Example - iperf implementation
13
14 This example code is in the Public Domain (or CC0 licensed, at your option.)
15
16 Unless required by applicable law or agreed to in writing, this
17 software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
18 CONDITIONS OF ANY KIND, either express or implied.
19*/
20
21/* ==================== [Includes] ========================================== */
22
23#include <stdio.h>
24#include <string.h>
25#include <sys/param.h>
26
27#include "lwip/err.h"
28#include "lwip/sockets.h"
29#include "lwip/sys.h"
30#include "lwip/netdb.h"
31
32#include "xf_utils.h"
33#include "xf_netif.h"
34#include "xf_osal.h"
35#include "xf_sys.h"
36
37#include "xf_iperf.h"
38
39/* ==================== [Defines] =========================================== */
40
41#define IPERF_HUNDRED 100
42
43/* ==================== [Typedefs] ========================================== */
44
45/* ==================== [Static Prototypes] ================================= */
46
47static inline bool iperf_is_udp_client(void);
48static inline bool iperf_is_udp_server(void);
49static inline bool iperf_is_tcp_client(void);
50static inline bool iperf_is_tcp_server(void);
51static int iperf_get_socket_error_code(int sockfd);
52static int iperf_show_socket_error_reason(const char *str, int sockfd);
53static void iperf_report_task(void *arg);
54static xf_err_t iperf_start_report(void);
55static void socket_recv(int recv_socket, struct sockaddr *listen_addr, uint8_t type);
56static void socket_send(int send_socket, struct sockaddr *dest_addr, uint8_t type, int bw_lim);
61static void iperf_task_traffic(void *arg);
62static uint32_t iperf_get_buffer_len(void);
63static uint32_t iperf_get_float_int(float in);
64static uint32_t iperf_get_float_dec(float in);
65
66/* ==================== [Static Variables] ================================== */
67
69static const char *TAG = "iperf";
70
71/* ==================== [Macros] ============================================ */
72
73#define XF_ASSERT_RET_GOTO(condition, err_code, label, tag, format, ...) \
74 do { \
75 ret = err_code; \
76 XF_ASSERT_GOTO(condition, label, tag, format, ##__VA_ARGS__); \
77 } while (0)
78
79/* ==================== [Global Functions] ================================== */
80
82 const xf_iperf_cfg_t *p_cfg, xf_iperf_cb_t cb_func, void *user_args)
83{
84 if (!p_cfg) {
85 return XF_FAIL;
86 }
87
89 XF_LOGW(TAG, "iperf is running");
90 return XF_FAIL;
91 }
92
93 xf_memset(&s_ctx, 0, sizeof(s_ctx));
94 xf_memcpy(&s_ctx.cfg, p_cfg, sizeof(*p_cfg));
96 s_ctx.finish = false;
99 if (!s_ctx.buffer) {
100 XF_LOGE(TAG, "create buffer: not enough memory");
101 return XF_FAIL;
102 }
104
105 s_ctx.cb_func = cb_func;
106 s_ctx.user_args = user_args;
107
108 /* socket 成功通信后再创建 report_task */
109
110 xf_osal_thread_attr_t thread_attr = {
112 .priority = p_cfg->traffic_task_prio,
113 .stack_size = p_cfg->traffic_task_stack_size,
114 };
116 xf_osal_thread_create(iperf_task_traffic, NULL, &thread_attr);
117 if (s_ctx.traffic_task_hdl == NULL) {
118 XF_LOGE(TAG, "create task %s failed", IPERF_TRAFFIC_TASK_NAME);
120 s_ctx.buffer = NULL;
121 return XF_FAIL;
122 }
123 return XF_OK;
124}
125
127{
129 s_ctx.finish = true;
130 }
131
133 XF_LOGI(TAG, "wait current iperf to stop ...");
134 xf_osal_delay_ms(100);
135 }
136
137 return XF_OK;
138}
139
141{
143}
144
145/* ==================== [Static Functions] ================================== */
146
147static inline bool iperf_is_udp_client(void)
148{
149 return ((s_ctx.cfg.flag & IPERF_FLAG_CLIENT)
151}
152
153static inline bool iperf_is_udp_server(void)
154{
155 return ((s_ctx.cfg.flag & IPERF_FLAG_SERVER)
157}
158
159static inline bool iperf_is_tcp_client(void)
160{
161 return ((s_ctx.cfg.flag & IPERF_FLAG_CLIENT)
163}
164
165static inline bool iperf_is_tcp_server(void)
166{
167 return ((s_ctx.cfg.flag & IPERF_FLAG_SERVER)
169}
170
171static int iperf_get_socket_error_code(int sockfd)
172{
173 return errno;
174}
175
176static int iperf_show_socket_error_reason(const char *str, int sockfd)
177{
178 int err = errno;
179 if (err != 0) {
180 XF_LOGW(TAG, "%s error, error code: %d, reason: %s",
181 str, err, strerror(err));
182 }
183
184 return err;
185}
186
187static void iperf_report_task(void *arg)
188{
189 UNUSED(arg);
191
192 uint32_t interval = s_ctx.cfg.interval;
193 uint32_t time = s_ctx.cfg.time;
194 uint32_t delay_interval_ms = interval * 1000;
195 uint32_t cur = 0;
196 float average = 0;
197 float actual_bandwidth = 0;
198 int k = 1;
199
200 if (s_ctx.cb_func) {
202 }
204 xf_log_printf("\n%16s %s\n", "Interval", "Bandwidth");
205 }
206
207 while (!s_ctx.finish) {
208 xf_osal_delay_ms(delay_interval_ms);
209
210 /* 更新本次带宽 */
212 actual_bandwidth = ((float)(s_ctx.actual_len * 8) / 1e6f) / (float)interval;
213 s_ctx.actual_bandwidth = actual_bandwidth;
214
215 /* 更新平均带宽 */
216 average = ((average * (k - 1) / k) + (actual_bandwidth / k));
217 s_ctx.average_bandwidth = average;
218
219 /* 更新报告时刻 */
220 s_ctx.curr_time = cur;
221
222 if (s_ctx.cb_func) {
224 }
226 xf_log_printf("%4d-%4d sec %d.%02d Mbits/sec\n",
227 (int)cur, (int)(cur + interval),
228 (int)iperf_get_float_int(actual_bandwidth),
229 (int)iperf_get_float_dec(actual_bandwidth));
230 }
231
232 cur += interval;
233 k++;
235
236 if (cur >= time) {
237 s_ctx.finish = true;
238 break;
239 }
240 }
241
242 s_ctx.finish = true;
243
244 if (s_ctx.cb_func) {
246 }
248 xf_log_printf("%4d-%4d sec %d.%02d Mbits/sec\n",
249 0, (int)time,
250 (int)iperf_get_float_int(average),
251 (int)iperf_get_float_dec(average));
252 }
253
254 s_ctx.report_is_running = false;
256}
257
259{
260 xf_osal_thread_attr_t thread_attr = {
262 .priority = s_ctx.cfg.report_task_prio,
263 .stack_size = s_ctx.cfg.report_task_stack_size,
264 };
266 if (s_ctx.report_task_hdl == NULL) {
267 XF_LOGE(TAG, "create task %s failed", IPERF_REPORT_TASK_NAME);
268 s_ctx.finish = true;
269 return XF_FAIL;
270 }
271 return XF_OK;
272}
273
274static void socket_recv(int recv_socket, struct sockaddr *listen_addr, uint8_t type)
275{
276 bool iperf_recv_start = true;
277 uint8_t *buffer;
278 int want_recv = 0;
279 int actual_recv = 0;
280 socklen_t socklen = (s_ctx.cfg.type == IPERF_IP_TYPE_IPV6)
281 ? sizeof(struct sockaddr_in6)
282 : sizeof(struct sockaddr_in);
283 const char *error_log = (type == IPERF_TRANS_TYPE_TCP)
284 ? "tcp server recv"
285 : "udp server recv";
286
288
289 buffer = s_ctx.buffer;
290 want_recv = s_ctx.buffer_len;
291 while (!s_ctx.finish) {
292 actual_recv = recvfrom(recv_socket, buffer, want_recv, 0, listen_addr, &socklen);
293 if (actual_recv >= 0) {
294 if (iperf_recv_start) {
296 iperf_recv_start = false;
297 }
298 s_ctx.actual_len_internal += actual_recv;
299 } else if (type == IPERF_TRANS_TYPE_TCP) { /* UDP 时不判断接收错误 */
300 iperf_show_socket_error_reason(error_log, recv_socket);
301 s_ctx.finish = true;
302 break;
303 }
304
305 }
306}
307
308static void socket_send(int send_socket, struct sockaddr *dest_addr, uint8_t type, int bw_lim)
309{
310 uint8_t *buffer;
311 uint32_t *pkt_id_p;
312 uint32_t pkt_cnt = 0;
313 int actual_send = 0;
314 int want_send = 0;
315 int period_us = -1;
316 int delay_us = 0;
317 xf_us_t prev_time = 0;
318 xf_us_t send_time = 0;
319 int err = 0;
320 const socklen_t socklen = (s_ctx.cfg.type == IPERF_IP_TYPE_IPV6)
321 ? sizeof(struct sockaddr_in6)
322 : sizeof(struct sockaddr_in);
323 const char *error_log = (type == IPERF_TRANS_TYPE_TCP)
324 ? "tcp client send"
325 : "udp client send";
326
327 buffer = s_ctx.buffer;
328 pkt_id_p = (uint32_t *)s_ctx.buffer;
329 want_send = s_ctx.buffer_len;
331
332 if (bw_lim > 0) {
333 period_us = want_send * 8 / bw_lim;
334 }
335
336 while (!s_ctx.finish) {
337 if (period_us > 0) {
338 send_time = xf_sys_time_get_us();
339 if (actual_send > 0) {
340 // Last packet "send" was successful, check how much off the previous loop duration was to the ideal send period. Result will adjust the
341 // next send delay.
342 delay_us += period_us + (int32_t)(prev_time - send_time);
343 } else {
344 // Last packet "send" was not successful. Ideally we should try to catch up the whole previous loop duration (e.g. prev_time - send_time).
345 // However, that's not possible since the most probable reason why the send was unsuccessful is the HW was not able to process the packet.
346 // Hence, we cannot queue more packets with shorter (or no) delay to catch up since we are already at the performance edge. The best we
347 // can do is to reset the send delay (which is probably big negative number) and start all over again.
348 delay_us = 0;
349 }
350 prev_time = send_time;
351 }
352 *pkt_id_p = htonl(pkt_cnt++); // datagrams need to be sequentially numbered
353 actual_send = sendto(send_socket, buffer, want_send, 0, dest_addr, socklen);
354 if (actual_send != want_send) {
355 if (type == IPERF_TRANS_TYPE_UDP) {
356 err = iperf_get_socket_error_code(send_socket);
357 // ENOMEM is expected under heavy load => do not print it
358 if (err != ENOMEM) {
359 iperf_show_socket_error_reason(error_log, send_socket);
360 }
361 } else if (type == IPERF_TRANS_TYPE_TCP) {
362 iperf_show_socket_error_reason(error_log, send_socket);
363 break;
364 }
365 } else {
366 s_ctx.actual_len_internal += actual_send;
367 }
368 // The send delay may be negative, it indicates we are trying to catch up and hence to not delay the loop at all.
369 if (delay_us > 0) {
370 xf_delay_us(delay_us);
371 }
372 }
373}
374
376{
377 int listen_socket = -1;
378 int client_socket = -1;
379 int opt = 1;
380 int err = 0;
381 xf_err_t ret = XF_OK;
382 struct sockaddr_in remote_addr;
383 struct timeval timeout = { 0 };
384 socklen_t addr_len = sizeof(struct sockaddr);
385 struct sockaddr *listen_addr = NULL;
386 struct sockaddr_in6 listen_addr6 = { 0 };
387 struct sockaddr_in listen_addr4 = { 0 };
388
390 XF_FAIL, l_exit, TAG, "Ivalid AF types");
391
393 // The TCP server listen at the address "::", which means all addresses can be listened to.
394 inet6_aton("::", &listen_addr6.sin6_addr);
395 listen_addr6.sin6_family = AF_INET6;
396 listen_addr6.sin6_port = htons(s_ctx.cfg.sport);
397
398 listen_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
399 XF_ASSERT_RET_GOTO((listen_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
400
401 setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
402 setsockopt(listen_socket, IPPROTO_IPV6, IPV6_V6ONLY, &opt, sizeof(opt));
403
404 XF_LOGI(TAG, "Socket created");
405
406 err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(listen_addr6));
407 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET6);
408 err = listen(listen_socket, 1);
409 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Error occurred during listen: errno %d", errno);
410
411 timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT_MS / 1000;
412 timeout.tv_usec = (IPERF_SOCKET_RX_TIMEOUT_MS % 1000) * 1000;
413 setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
414
415 listen_addr = (struct sockaddr *)&listen_addr6;
416 } else if (s_ctx.cfg.type == IPERF_IP_TYPE_IPV4) {
417 listen_addr4.sin_family = AF_INET;
418 listen_addr4.sin_port = htons(s_ctx.cfg.sport);
419 listen_addr4.sin_addr.s_addr = s_ctx.cfg.sip.u_addr.ip4.addr;
420
421 listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
422 XF_ASSERT_RET_GOTO((listen_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
423
424 setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
425
426 XF_LOGI(TAG, "Socket created");
427
428 err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(listen_addr4));
429 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Socket unable to bind: errno %d, IPPROTO: %d", errno, AF_INET);
430
431 err = listen(listen_socket, 5);
432 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Error occurred during listen: errno %d", errno);
433
434 listen_addr = (struct sockaddr *)&listen_addr4;
435 }
436
437 client_socket = accept(listen_socket, (struct sockaddr *)&remote_addr, &addr_len);
438 XF_ASSERT_RET_GOTO((client_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to accept connection: errno %d", errno);
439 XF_LOGI(TAG, "accept: %s,%d\n", inet_ntoa(remote_addr.sin_addr), htons(remote_addr.sin_port));
440
441 timeout.tv_sec = IPERF_SOCKET_RX_TIMEOUT_MS / 1000;
442 timeout.tv_usec = (IPERF_SOCKET_RX_TIMEOUT_MS % 1000) * 1000;
443 setsockopt(client_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
444
445 socket_recv(client_socket, listen_addr, IPERF_TRANS_TYPE_TCP);
446l_exit:
447 if (client_socket != -1) {
448 shutdown(client_socket, SHUT_RDWR);
449 closesocket(client_socket);
450 }
451
452 if (listen_socket != -1) {
453 shutdown(listen_socket, SHUT_RDWR);
454 closesocket(listen_socket);
455 XF_LOGI(TAG, "TCP Socket server is closed.");
456 }
457 s_ctx.finish = true;
458 return ret;
459}
460
462{
463 int client_socket = -1;
464 int err = 0;
465 xf_err_t ret = XF_OK;
466 struct sockaddr *dest_addr = NULL;
467 struct sockaddr_in6 dest_addr6 = { 0 };
468 struct sockaddr_in dest_addr4 = { 0 };
469
471 XF_FAIL, l_exit, TAG, "Ivalid AF types");
472
474 client_socket = socket(AF_INET6, SOCK_STREAM, IPPROTO_IPV6);
475 XF_ASSERT_RET_GOTO((client_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
476
477 xf_memcpy(&dest_addr6.sin6_addr, s_ctx.cfg.dip.u_addr.ip6.addr, sizeof(struct in6_addr));
478 dest_addr6.sin6_family = AF_INET6;
479 dest_addr6.sin6_port = htons(s_ctx.cfg.dport);
480
481 err = connect(client_socket, (struct sockaddr *)&dest_addr6, sizeof(struct sockaddr_in6));
482 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Socket unable to connect: errno %d", errno);
483 XF_LOGI(TAG, "Successfully connected");
484
485 dest_addr = (struct sockaddr *)&dest_addr6;
486 } else if (s_ctx.cfg.type == IPERF_IP_TYPE_IPV4) {
487 client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
488 XF_ASSERT_RET_GOTO((client_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
489
490 dest_addr4.sin_family = AF_INET;
491 dest_addr4.sin_port = htons(s_ctx.cfg.dport);
492 dest_addr4.sin_addr.s_addr = s_ctx.cfg.dip.u_addr.ip4.addr;
493
494 err = connect(client_socket, (struct sockaddr *)&dest_addr4, sizeof(struct sockaddr_in));
495 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Socket unable to connect: errno %d", errno);
496 XF_LOGI(TAG, "Successfully connected");
497
498 dest_addr = (struct sockaddr *)&dest_addr4;
499 }
500
501 socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_TCP, s_ctx.cfg.bw_lim);
502l_exit:
503 if (client_socket != -1) {
504 shutdown(client_socket, SHUT_RDWR);
505 closesocket(client_socket);
506 XF_LOGI(TAG, "TCP Socket client is closed.");
507 }
508 s_ctx.finish = true;
509 return ret;
510}
511
513{
514 int listen_socket = -1;
515 int opt = 1;
516 int err = 0;
517 xf_err_t ret = XF_OK;
518 struct timeval timeout = { 0 };
519 struct sockaddr *listen_addr = NULL;
520 struct sockaddr_in6 listen_addr6 = { 0 };
521 struct sockaddr_in listen_addr4 = { 0 };
522
524 XF_FAIL, l_exit, TAG, "Ivalid AF types");
525
527 // The UDP server listen at the address "::", which means all addresses can be listened to.
528 inet6_aton("::", &listen_addr6.sin6_addr);
529 listen_addr6.sin6_family = AF_INET6;
530 listen_addr6.sin6_port = htons(s_ctx.cfg.sport);
531
532 listen_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
533 XF_ASSERT_RET_GOTO((listen_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
534 XF_LOGI(TAG, "Socket created");
535
536 setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
537
538 err = bind(listen_socket, (struct sockaddr *)&listen_addr6, sizeof(struct sockaddr_in6));
539 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Socket unable to bind: errno %d", errno);
540 XF_LOGI(TAG, "Socket bound, port %d", listen_addr6.sin6_port);
541
542 listen_addr = (struct sockaddr *)&listen_addr6;
543 } else if (s_ctx.cfg.type == IPERF_IP_TYPE_IPV4) {
544 listen_addr4.sin_family = AF_INET;
545 listen_addr4.sin_port = htons(s_ctx.cfg.sport);
546 listen_addr4.sin_addr.s_addr = s_ctx.cfg.sip.u_addr.ip4.addr;
547
548 listen_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
549 XF_ASSERT_RET_GOTO((listen_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
550 XF_LOGI(TAG, "Socket created");
551
552 setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
553
554 err = bind(listen_socket, (struct sockaddr *)&listen_addr4, sizeof(struct sockaddr_in));
555 XF_ASSERT_RET_GOTO((err == 0), XF_FAIL, l_exit, TAG, "Socket unable to bind: errno %d", errno);
556 XF_LOGI(TAG, "Socket bound, port %d", listen_addr4.sin_port);
557
558 listen_addr = (struct sockaddr *)&listen_addr4;
559 }
560
561 /* UDP 接收一直轮询,避免长时间阻塞影响 s_ctx.finish 的检测,任务无法及时退出 */
562 timeout.tv_sec = 0;
563 timeout.tv_usec = 1000;
564 setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
565
566 socket_recv(listen_socket, listen_addr, IPERF_TRANS_TYPE_UDP);
567l_exit:
568 if (listen_socket != -1) {
569 shutdown(listen_socket, SHUT_RDWR);
570 closesocket(listen_socket);
571 }
572 XF_LOGI(TAG, "Udp socket server is closed.");
573 s_ctx.finish = true;
574 return ret;
575}
576
578{
579 int client_socket = -1;
580 int opt = 1;
581 xf_err_t ret = XF_OK;
582 struct sockaddr *dest_addr = NULL;
583 struct sockaddr_in6 dest_addr6 = { 0 };
584 struct sockaddr_in dest_addr4 = { 0 };
585
587 XF_FAIL, l_exit, TAG, "Ivalid AF types");
588
590 xf_memcpy(&dest_addr6.sin6_addr, s_ctx.cfg.dip.u_addr.ip6.addr, sizeof(struct in6_addr));
591 dest_addr6.sin6_family = AF_INET6;
592 dest_addr6.sin6_port = htons(s_ctx.cfg.dport);
593
594 client_socket = socket(AF_INET6, SOCK_DGRAM, IPPROTO_IPV6);
595 XF_ASSERT_RET_GOTO((client_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
596 XF_LOGI(TAG, "Socket created, sending to " XF_IPV6STR ":%d",
598
599 setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
600
601 dest_addr = (struct sockaddr *)&dest_addr6;
602 } else if (s_ctx.cfg.type == IPERF_IP_TYPE_IPV4) {
603 dest_addr4.sin_family = AF_INET;
604 dest_addr4.sin_port = htons(s_ctx.cfg.dport);
605 dest_addr4.sin_addr.s_addr = s_ctx.cfg.dip.u_addr.ip4.addr;
606
607 client_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
608 XF_ASSERT_RET_GOTO((client_socket >= 0), XF_FAIL, l_exit, TAG, "Unable to create socket: errno %d", errno);
609 XF_LOGI(TAG, "Socket created, sending to " XF_IPSTR ":%d",
611
612 setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
613
614 dest_addr = (struct sockaddr *)&dest_addr4;
615 }
616
617 socket_send(client_socket, dest_addr, IPERF_TRANS_TYPE_UDP, s_ctx.cfg.bw_lim);
618l_exit:
619 if (client_socket != -1) {
620 shutdown(client_socket, SHUT_RDWR);
621 closesocket(client_socket);
622 }
623 s_ctx.finish = true;
624 XF_LOGI(TAG, "UDP Socket client is closed");
625 return ret;
626}
627
628static void iperf_task_traffic(void *arg)
629{
630 if (iperf_is_udp_client()) {
632 } else if (iperf_is_udp_server()) {
634 } else if (iperf_is_tcp_client()) {
636 } else {
638 }
639
640 if (s_ctx.buffer) {
642 s_ctx.buffer = NULL;
643 }
645 XF_LOGI(TAG, "iperf done");
647}
648
649static uint32_t iperf_get_buffer_len(void)
650{
651 if (iperf_is_udp_client()) {
652#ifdef CONFIG_XF_NET_APPS_ENABLE_IPV6
653 if (s_ctx.cfg.len_send_buf) {
654 return s_ctx.cfg.len_send_buf;
655 } else if (s_ctx.cfg.type == IPERF_IP_TYPE_IPV6) {
657 } else {
659 }
660#else
661 return (s_ctx.cfg.len_send_buf == 0
664#endif
665 } else if (iperf_is_udp_server()) {
667 } else if (iperf_is_tcp_client()) {
668 return (s_ctx.cfg.len_send_buf == 0
671 } else {
673 }
674 return 0;
675}
676
677static uint32_t iperf_get_float_int(float in)
678{
679 return (uint32_t)(((uint64_t)(in * IPERF_HUNDRED)) / IPERF_HUNDRED);
680}
681
682static uint32_t iperf_get_float_dec(float in)
683{
684 return (uint32_t)(((uint64_t)(in * IPERF_HUNDRED)) % IPERF_HUNDRED);
685}
#define XF_IPSTR
#define XF_IPV6STR
#define XF_IPV62STR(ipaddr)
#define XF_IP2STR(ipaddr)
xf_err_t xf_iperf_start(const xf_iperf_cfg_t *p_cfg, xf_iperf_cb_t cb_func, void *user_args)
启动 iperf.
Definition xf_iperf.c:81
#define IPERF_DEFAULT_IPV6_UDP_TX_LEN
Definition xf_iperf.h:77
#define IPERF_TRAFFIC_TASK_NAME
Definition xf_iperf.h:69
void(* xf_iperf_cb_t)(xf_iperf_event_id_t event_id, xf_iperf_t hdl, void *user_args)
iperf 回调函数原型。
Definition xf_iperf.h:131
#define IPERF_DEFAULT_UDP_RX_LEN
Definition xf_iperf.h:78
#define IPERF_TRANS_TYPE_TCP
Definition xf_iperf.h:53
#define IPERF_DEFAULT_TCP_RX_LEN
Definition xf_iperf.h:80
#define IPERF_DEFAULT_IPV4_UDP_TX_LEN
Definition xf_iperf.h:76
#define IPERF_FLAG_SERVER
Definition xf_iperf.h:60
#define IPERF_SOCKET_RX_TIMEOUT_MS
Definition xf_iperf.h:84
#define IPERF_FLAG_CLIENT
Definition xf_iperf.h:59
#define IPERF_DEFAULT_TCP_TX_LEN
Definition xf_iperf.h:79
#define IPERF_IP_TYPE_IPV6
Definition xf_iperf.h:52
#define IPERF_FLAG_TCP
Definition xf_iperf.h:61
#define IPERF_IP_TYPE_IPV4
Definition xf_iperf.h:51
bool xf_iperf_is_running(void)
检查 iperf 是否正在运行。
Definition xf_iperf.c:140
xf_err_t xf_iperf_stop(void)
停止 iperf.
Definition xf_iperf.c:126
#define IPERF_FLAG_UDP
Definition xf_iperf.h:62
#define IPERF_REPORT_TASK_NAME
Definition xf_iperf.h:72
#define IPERF_TRANS_TYPE_UDP
Definition xf_iperf.h:54
@ XF_IPERF_EVENT_END
Definition xf_iperf.h:109
@ XF_IPERF_EVENT_REPORT
Definition xf_iperf.h:103
xf_err_t xf_osal_thread_delete(xf_osal_thread_t thread)
终止线程的执行。
xf_osal_thread_t xf_osal_thread_create(xf_osal_thread_func_t func, void *argument, const xf_osal_thread_attr_t *attr)
创建一个线程并将其添加到活动线程中。
xf_err_t xf_osal_delay_ms(uint32_t ms)
(睡眠)等待超时,以 ms 为单位。
xf_us_t xf_sys_time_get_us(void)
获取系统时间的时间戳,单位微秒(us)
xf_err_t xf_delay_us(xf_us_t n_us)
微秒级延时
Definition xf_sys_time.c:57
int32_t xf_err_t
整形错误类型。 错误码具体值见 xf_err_code_t.
Definition xf_err.h:69
@ XF_FAIL
Definition xf_err.h:42
@ XF_OK
Definition xf_err.h:43
#define xf_malloc(x)
Definition xf_stdlib.h:38
#define xf_free(x)
Definition xf_stdlib.h:39
#define xf_memset(ptr, value, size)
Definition xf_string.h:42
#define xf_memcpy(dest, src, n)
Definition xf_string.h:44
union _xf_ip_addr::@10 u_addr
iperf 配置类型。
Definition xf_iperf.h:137
xf_ip_addr_t dip
Definition xf_iperf.h:141
uint32_t traffic_task_prio
Definition xf_iperf.h:155
uint32_t report_task_stack_size
Definition xf_iperf.h:158
uint16_t dport
Definition xf_iperf.h:144
xf_ip_addr_t sip
Definition xf_iperf.h:142
bool report_enabled
Definition xf_iperf.h:157
uint16_t sport
Definition xf_iperf.h:145
uint32_t report_task_prio
Definition xf_iperf.h:159
uint32_t flag
Definition xf_iperf.h:138
uint16_t len_send_buf
Definition xf_iperf.h:148
uint32_t interval
Definition xf_iperf.h:146
int32_t bw_lim
Definition xf_iperf.h:152
uint32_t time
Definition xf_iperf.h:147
uint32_t traffic_task_stack_size
Definition xf_iperf.h:154
iperf 上下文.
Definition xf_iperf.h:188
xf_iperf_cb_t cb_func
Definition xf_iperf.h:214
xf_osal_thread_t report_task_hdl
Definition xf_iperf.h:220
uint32_t curr_time
Definition xf_iperf.h:192
xf_osal_thread_t traffic_task_hdl
Definition xf_iperf.h:217
float average_bandwidth
Definition xf_iperf.h:202
bool report_is_running
Definition xf_iperf.h:221
uint32_t actual_len_internal
Definition xf_iperf.h:209
uint8_t * buffer
Definition xf_iperf.h:207
uint32_t buffer_len
Definition xf_iperf.h:208
void * user_args
Definition xf_iperf.h:215
bool traffic_is_running
Definition xf_iperf.h:218
uint32_t actual_len
Definition xf_iperf.h:196
float actual_bandwidth
Definition xf_iperf.h:201
xf_iperf_cfg_t cfg
Definition xf_iperf.h:191
线程的属性结构。
static void iperf_report_task(void *arg)
Definition xf_iperf.c:187
static uint32_t iperf_get_buffer_len(void)
Definition xf_iperf.c:649
static int iperf_get_socket_error_code(int sockfd)
Definition xf_iperf.c:171
static uint32_t iperf_get_float_dec(float in)
Definition xf_iperf.c:682
static int iperf_show_socket_error_reason(const char *str, int sockfd)
Definition xf_iperf.c:176
#define XF_ASSERT_RET_GOTO(condition, err_code, label, tag, format,...)
Definition xf_iperf.c:73
static bool iperf_is_udp_server(void)
Definition xf_iperf.c:153
static uint32_t iperf_get_float_int(float in)
Definition xf_iperf.c:677
static xf_err_t iperf_run_udp_client(void)
Definition xf_iperf.c:577
static void socket_send(int send_socket, struct sockaddr *dest_addr, uint8_t type, int bw_lim)
Definition xf_iperf.c:308
static const char * TAG
Definition xf_iperf.c:69
static void iperf_task_traffic(void *arg)
Definition xf_iperf.c:628
static xf_err_t iperf_run_tcp_server(void)
Definition xf_iperf.c:375
static bool iperf_is_udp_client(void)
Definition xf_iperf.c:147
static xf_err_t iperf_run_tcp_client(void)
Definition xf_iperf.c:461
#define IPERF_HUNDRED
Definition xf_iperf.c:41
static bool iperf_is_tcp_client(void)
Definition xf_iperf.c:159
static xf_err_t iperf_start_report(void)
Definition xf_iperf.c:258
static xf_err_t iperf_run_udp_server(void)
Definition xf_iperf.c:512
static xf_iperf_ctx_t s_ctx
Definition xf_iperf.c:68
static bool iperf_is_tcp_server(void)
Definition xf_iperf.c:165
static void socket_recv(int recv_socket, struct sockaddr *listen_addr, uint8_t type)
Definition xf_iperf.c:274
#define XF_LOGI(tag, format,...)
#define XF_LOGE(tag, format,...)
#define XF_LOGW(tag, format,...)
XF_US_TYPE xf_us_t
#define UNUSED(_x)
#define xf_log_printf(format,...)