net: zperf: Define a public upload API for the library
This commit defines a public API for zperf upload functionality. The UDP/TCP uploader modules are decoupled from shell, allowing to perform uploads directly from the application code. The shell submodule makes use of this new public API. Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
71e95ae29d
commit
812a1bc152
11 changed files with 368 additions and 368 deletions
|
@ -4,6 +4,7 @@ zephyr_library_named(zperf)
|
|||
|
||||
zephyr_library_sources(
|
||||
shell_utils.c
|
||||
zperf_common.c
|
||||
zperf_session.c
|
||||
zperf_shell.c
|
||||
zperf_udp_receiver.c
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef __ZPERF_H
|
||||
#define __ZPERF_H
|
||||
|
||||
#define VERSION "1.1"
|
||||
|
||||
struct zperf_results {
|
||||
uint32_t nb_packets_sent;
|
||||
uint32_t nb_packets_rcvd;
|
||||
uint32_t nb_packets_lost;
|
||||
uint32_t nb_packets_outorder;
|
||||
uint32_t nb_bytes_sent;
|
||||
uint32_t time_in_us;
|
||||
uint32_t jitter_in_us;
|
||||
uint32_t client_time_in_us;
|
||||
uint32_t packet_size;
|
||||
uint32_t nb_packets_errors;
|
||||
};
|
||||
|
||||
typedef void (*zperf_callback)(int status, struct zperf_results *);
|
||||
|
||||
#define IPV4_STR_LEN_MAX 15
|
||||
#define IPV4_STR_LEN_MIN 7
|
||||
|
||||
#endif /* __ZPERF_H */
|
89
subsys/net/lib/zperf/zperf_common.c
Normal file
89
subsys/net/lib/zperf/zperf_common.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/net/socket.h>
|
||||
|
||||
LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
|
||||
|
||||
int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos,
|
||||
int proto)
|
||||
{
|
||||
socklen_t addrlen = peer_addr->sa_family == AF_INET6 ?
|
||||
sizeof(struct sockaddr_in6) :
|
||||
sizeof(struct sockaddr_in);
|
||||
int type = (proto == IPPROTO_UDP) ? SOCK_DGRAM : SOCK_STREAM;
|
||||
int sock = -1;
|
||||
int ret;
|
||||
|
||||
switch (peer_addr->sa_family) {
|
||||
case AF_INET:
|
||||
if (!IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
NET_ERR("IPv4 not available.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sock = zsock_socket(AF_INET, type, proto);
|
||||
if (sock < 0) {
|
||||
NET_ERR("Cannot create IPv4 network socket (%d)",
|
||||
errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (tos > 0) {
|
||||
if (zsock_setsockopt(sock, IPPROTO_IP, IP_TOS,
|
||||
&tos, sizeof(tos)) != 0) {
|
||||
NET_WARN("Failed to set IP_TOS socket option. "
|
||||
"Please enable CONFIG_NET_CONTEXT_DSCP_ECN.");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case AF_INET6:
|
||||
if (!IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
NET_ERR("IPv6 not available.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sock = zsock_socket(AF_INET6, type, proto);
|
||||
if (sock < 0) {
|
||||
NET_ERR("Cannot create IPv6 network socket (%d)",
|
||||
errno);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (tos >= 0) {
|
||||
if (zsock_setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS,
|
||||
&tos, sizeof(tos)) != 0) {
|
||||
NET_WARN("Failed to set IPV6_TCLASS socket option. "
|
||||
"Please enable CONFIG_NET_CONTEXT_DSCP_ECN.");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_ERR("Invalid address family (%d)", peer_addr->sa_family);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = zsock_connect(sock, peer_addr, addrlen);
|
||||
if (ret < 0) {
|
||||
NET_ERR("Connect failed (%d)", errno);
|
||||
ret = -errno;
|
||||
zsock_close(sock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return sock;
|
||||
}
|
||||
|
||||
uint32_t zperf_packet_duration(uint32_t packet_size, uint32_t rate_in_kbps)
|
||||
{
|
||||
return (uint32_t)(((uint64_t)packet_size * 8U * USEC_PER_SEC) /
|
||||
(rate_in_kbps * 1024U));
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include <limits.h>
|
||||
#include <zephyr/net/net_ip.h>
|
||||
#include <zephyr/net/zperf.h>
|
||||
#include <zephyr/shell/shell.h>
|
||||
#include <zephyr/sys/__assert.h>
|
||||
|
||||
|
@ -81,23 +82,9 @@ int zperf_get_ipv4_addr(const struct shell *sh, char *host,
|
|||
struct in_addr *addr);
|
||||
struct sockaddr_in *zperf_get_sin(void);
|
||||
|
||||
extern void zperf_udp_upload(const struct shell *sh,
|
||||
int sock,
|
||||
int port,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
unsigned int rate_in_kbps,
|
||||
struct zperf_results *results);
|
||||
|
||||
extern void zperf_udp_receiver_init(const struct shell *sh, int port);
|
||||
|
||||
extern void zperf_tcp_receiver_init(const struct shell *sh, int port);
|
||||
extern void zperf_tcp_uploader_init(struct k_fifo *tx_queue);
|
||||
extern void zperf_tcp_upload(const struct shell *sh,
|
||||
int sock,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
struct zperf_results *results);
|
||||
|
||||
extern void connect_ap(char *ssid);
|
||||
|
||||
|
@ -107,4 +94,9 @@ const struct in6_addr *zperf_get_default_if_in6_addr(void);
|
|||
void zperf_tcp_stopped(void);
|
||||
void zperf_tcp_started(void);
|
||||
|
||||
int zperf_prepare_upload_sock(const struct sockaddr *peer_addr, int tos,
|
||||
int proto);
|
||||
|
||||
uint32_t zperf_packet_duration(uint32_t packet_size, uint32_t rate_in_kbps);
|
||||
|
||||
#endif /* __ZPERF_INTERNAL_H */
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#include <zephyr/net/net_ip.h>
|
||||
#include <zephyr/net/net_core.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
#include "shell_utils.h"
|
||||
|
||||
|
|
|
@ -17,8 +17,8 @@ LOG_MODULE_REGISTER(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
|
|||
#include <zephyr/net/net_ip.h>
|
||||
#include <zephyr/net/net_core.h>
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <zephyr/net/zperf.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
#include "shell_utils.h"
|
||||
#include "zperf_session.h"
|
||||
|
@ -53,6 +53,8 @@ static const char *CONFIG =
|
|||
#define DEF_PORT 5001
|
||||
#define DEF_PORT_STR STRINGIFY(DEF_PORT)
|
||||
|
||||
#define ZPERF_VERSION "1.1"
|
||||
|
||||
static struct in6_addr ipv6;
|
||||
|
||||
static struct sockaddr_in6 in6_addr_my = {
|
||||
|
@ -362,7 +364,7 @@ static void shell_udp_upload_print_stats(const struct shell *sh,
|
|||
|
||||
if (results->time_in_us != 0U) {
|
||||
rate_in_kbps = (uint32_t)
|
||||
(((uint64_t)results->nb_bytes_sent *
|
||||
(((uint64_t)results->total_len *
|
||||
(uint64_t)8 * (uint64_t)USEC_PER_SEC) /
|
||||
((uint64_t)results->time_in_us * 1024U));
|
||||
} else {
|
||||
|
@ -450,101 +452,26 @@ static void shell_tcp_upload_print_stats(const struct shell *sh,
|
|||
}
|
||||
}
|
||||
|
||||
static int setup_upload_sockets(const struct shell *sh,
|
||||
int *sock6,
|
||||
int *sock4,
|
||||
sa_family_t family,
|
||||
struct sockaddr_in6 *ipv6,
|
||||
struct sockaddr_in *ipv4,
|
||||
int port,
|
||||
int tos,
|
||||
bool is_udp)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
*sock6 = zsock_socket(AF_INET6,
|
||||
is_udp ? SOCK_DGRAM : SOCK_STREAM,
|
||||
is_udp ? IPPROTO_UDP : IPPROTO_TCP);
|
||||
if (*sock6 < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Cannot create IPv6 network socket (%d)\n",
|
||||
errno);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (tos >= 0) {
|
||||
if (zsock_setsockopt(*sock6, IPPROTO_IPV6, IPV6_TCLASS,
|
||||
&tos, sizeof(tos)) != 0) {
|
||||
shell_fprintf(
|
||||
sh, SHELL_WARNING,
|
||||
"Failed to set IPV6_TCLASS socket option. "
|
||||
"Please enable CONFIG_NET_CONTEXT_DSCP_ECN.\n");
|
||||
}
|
||||
}
|
||||
|
||||
ipv6->sin6_port = htons(port);
|
||||
ipv6->sin6_family = AF_INET6;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
*sock4 = zsock_socket(AF_INET,
|
||||
is_udp ? SOCK_DGRAM : SOCK_STREAM,
|
||||
is_udp ? IPPROTO_UDP : IPPROTO_TCP);
|
||||
if (*sock4 < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Cannot create IPv4 network socket (%d)\n",
|
||||
errno);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (tos >= 0) {
|
||||
if (zsock_setsockopt(*sock4, IPPROTO_IP, IP_TOS,
|
||||
&tos, sizeof(tos)) != 0) {
|
||||
shell_fprintf(
|
||||
sh, SHELL_WARNING,
|
||||
"Failed to set IP_TOS socket option. "
|
||||
"Please enable CONFIG_NET_CONTEXT_DSCP_ECN.\n");
|
||||
}
|
||||
}
|
||||
|
||||
ipv4->sin_port = htons(port);
|
||||
ipv4->sin_family = AF_INET;
|
||||
}
|
||||
|
||||
if ((*sock6 < 0) && (*sock4 < 0)) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Fail to create network socket(s)\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int execute_upload(const struct shell *sh,
|
||||
int sock6,
|
||||
int sock4,
|
||||
sa_family_t family,
|
||||
struct sockaddr_in6 *ipv6,
|
||||
struct sockaddr_in *ipv4,
|
||||
bool is_udp,
|
||||
int port,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
unsigned int rate_in_kbps)
|
||||
const struct zperf_upload_params *param,
|
||||
bool is_udp)
|
||||
{
|
||||
struct zperf_results results = { };
|
||||
struct zperf_results results = { 0 };
|
||||
int ret;
|
||||
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Duration:\t");
|
||||
print_number(sh, duration_in_ms * USEC_PER_MSEC, TIME_US,
|
||||
print_number(sh, param->duration_ms * USEC_PER_MSEC, TIME_US,
|
||||
TIME_US_UNIT);
|
||||
shell_fprintf(sh, SHELL_NORMAL, "\n");
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Packet size:\t%u bytes\n",
|
||||
packet_size);
|
||||
param->packet_size);
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Rate:\t\t%u kbps\n",
|
||||
rate_in_kbps);
|
||||
param->rate_kbps);
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Starting...\n");
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6 && sock6 >= 0) {
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && param->peer_addr.sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *ipv6 =
|
||||
(struct sockaddr_in6 *)¶m->peer_addr;
|
||||
/* For IPv6, we should make sure that neighbor discovery
|
||||
* has been done for the peer. So send ping here, wait
|
||||
* some time and start the test after that.
|
||||
|
@ -556,41 +483,29 @@ static int execute_upload(const struct shell *sh,
|
|||
}
|
||||
|
||||
if (is_udp && IS_ENABLED(CONFIG_NET_UDP)) {
|
||||
uint32_t packet_duration =
|
||||
zperf_packet_duration(param->packet_size, param->rate_kbps);
|
||||
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Rate:\t\t");
|
||||
print_number(sh, rate_in_kbps, KBPS, KBPS_UNIT);
|
||||
print_number(sh, param->rate_kbps, KBPS, KBPS_UNIT);
|
||||
shell_fprintf(sh, SHELL_NORMAL, "\n");
|
||||
|
||||
if (family == AF_INET6 && sock6 >= 0) {
|
||||
ret = zsock_connect(sock6,
|
||||
(struct sockaddr *)ipv6,
|
||||
sizeof(*ipv6));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"IPv6 connect failed (%d)\n",
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
zperf_udp_upload(sh, sock6, port, duration_in_ms,
|
||||
packet_size, rate_in_kbps, &results);
|
||||
shell_udp_upload_print_stats(sh, &results);
|
||||
if (packet_duration > 1000U) {
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Packet duration %u ms\n",
|
||||
(unsigned int)(packet_duration / 1000U));
|
||||
} else {
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Packet duration %u us\n",
|
||||
(unsigned int)packet_duration);
|
||||
}
|
||||
|
||||
if (family == AF_INET && sock4 >= 0) {
|
||||
ret = zsock_connect(sock4,
|
||||
(struct sockaddr *)ipv4,
|
||||
sizeof(*ipv4));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"IPv4 connect failed (%d)\n",
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
zperf_udp_upload(sh, sock4, port, duration_in_ms,
|
||||
packet_size, rate_in_kbps, &results);
|
||||
shell_udp_upload_print_stats(sh, &results);
|
||||
ret = zperf_udp_upload(param, &results);
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_ERROR,
|
||||
"UDP upload failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
shell_udp_upload_print_stats(sh, &results);
|
||||
} else {
|
||||
if (!IS_ENABLED(CONFIG_NET_UDP)) {
|
||||
shell_fprintf(sh, SHELL_INFO,
|
||||
|
@ -599,52 +514,14 @@ static int execute_upload(const struct shell *sh,
|
|||
}
|
||||
|
||||
if (!is_udp && IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
if (family == AF_INET6 && sock6 >= 0) {
|
||||
ret = zsock_connect(sock6,
|
||||
(struct sockaddr *)ipv6,
|
||||
sizeof(*ipv6));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"IPv6 connect failed (%d)\n",
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We either upload using IPv4 or IPv6, not both at
|
||||
* the same time.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && sock4 >= 0) {
|
||||
(void)zsock_close(sock4);
|
||||
sock4 = -1;
|
||||
}
|
||||
|
||||
zperf_tcp_upload(sh, sock6, duration_in_ms,
|
||||
packet_size, &results);
|
||||
|
||||
shell_tcp_upload_print_stats(sh, &results);
|
||||
ret = zperf_tcp_upload(param, &results);
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_ERROR,
|
||||
"TCP upload failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (family == AF_INET && sock4 >= 0) {
|
||||
ret = zsock_connect(sock4,
|
||||
(struct sockaddr *)ipv4,
|
||||
sizeof(*ipv4));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"IPv4 connect failed (%d)\n",
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && sock6 >= 0) {
|
||||
(void)zsock_close(sock6);
|
||||
sock6 = -1;
|
||||
}
|
||||
|
||||
zperf_tcp_upload(sh, sock4, duration_in_ms,
|
||||
packet_size, &results);
|
||||
|
||||
shell_tcp_upload_print_stats(sh, &results);
|
||||
}
|
||||
shell_tcp_upload_print_stats(sh, &results);
|
||||
} else {
|
||||
if (!IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
shell_fprintf(sh, SHELL_INFO,
|
||||
|
@ -652,17 +529,6 @@ static int execute_upload(const struct shell *sh,
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && sock6 >= 0) {
|
||||
(void)zsock_close(sock6);
|
||||
sock6 = -1;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && sock4 >= 0) {
|
||||
(void)zsock_close(sock4);
|
||||
sock4 = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -698,17 +564,13 @@ static int parse_arg(size_t *i, size_t argc, char *argv[])
|
|||
static int shell_cmd_upload(const struct shell *sh, size_t argc,
|
||||
char *argv[], enum net_ip_protocol proto)
|
||||
{
|
||||
struct zperf_upload_params param = { 0 };
|
||||
struct sockaddr_in6 ipv6 = { .sin6_family = AF_INET6 };
|
||||
struct sockaddr_in ipv4 = { .sin_family = AF_INET };
|
||||
int sock6 = -1, sock4 = -1;
|
||||
sa_family_t family = AF_UNSPEC;
|
||||
unsigned int duration_in_ms, packet_size, rate_in_kbps;
|
||||
char *port_str;
|
||||
uint16_t port;
|
||||
bool is_udp;
|
||||
int start = 0;
|
||||
size_t opt_cnt = 0;
|
||||
int tos = 0;
|
||||
|
||||
is_udp = proto == IPPROTO_UDP;
|
||||
|
||||
|
@ -720,13 +582,16 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
|
|||
|
||||
switch (argv[i][1]) {
|
||||
case 'S':
|
||||
tos = parse_arg(&i, argc, argv);
|
||||
int tos = parse_arg(&i, argc, argv);
|
||||
|
||||
if (tos < 0 || tos > UINT8_MAX) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Parse error: %s\n", argv[i]);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
param.options.tos = tos;
|
||||
|
||||
break;
|
||||
default:
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
|
@ -760,12 +625,10 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
|
|||
}
|
||||
|
||||
if (argc > 2) {
|
||||
port = strtoul(argv[start + 2], NULL, 10);
|
||||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"Remote port is %u\n", port);
|
||||
port_str = argv[start + 2];
|
||||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"Remote port is %s\n", port_str);
|
||||
} else {
|
||||
port = DEF_PORT;
|
||||
port_str = DEF_PORT_STR;
|
||||
}
|
||||
|
||||
|
@ -781,7 +644,7 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
|
|||
shell_fprintf(sh, SHELL_WARNING, "Connecting to %s\n",
|
||||
net_sprint_ipv6_addr(&ipv6.sin6_addr));
|
||||
|
||||
family = AF_INET6;
|
||||
memcpy(¶m.peer_addr, &ipv6, sizeof(ipv6));
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && !IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
|
@ -796,7 +659,7 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
|
|||
shell_fprintf(sh, SHELL_NORMAL, "Connecting to %s\n",
|
||||
net_sprint_ipv4_addr(&ipv4.sin_addr));
|
||||
|
||||
family = AF_INET;
|
||||
memcpy(¶m.peer_addr, &ipv4, sizeof(ipv4));
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
|
@ -814,45 +677,37 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
|
|||
"Connecting to %s\n",
|
||||
net_sprint_ipv4_addr(&ipv4.sin_addr));
|
||||
|
||||
family = AF_INET;
|
||||
memcpy(¶m.peer_addr, &ipv4, sizeof(ipv4));
|
||||
} else {
|
||||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"Connecting to %s\n",
|
||||
net_sprint_ipv6_addr(&ipv6.sin6_addr));
|
||||
|
||||
family = AF_INET6;
|
||||
memcpy(¶m.peer_addr, &ipv6, sizeof(ipv6));
|
||||
}
|
||||
}
|
||||
|
||||
if (setup_upload_sockets(sh, &sock6, &sock4, family, &in6_addr_my,
|
||||
&in4_addr_my, port, tos, is_udp) < 0) {
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
duration_in_ms = MSEC_PER_SEC * strtoul(argv[start + 3],
|
||||
NULL, 10);
|
||||
param.duration_ms = MSEC_PER_SEC * strtoul(argv[start + 3],
|
||||
NULL, 10);
|
||||
} else {
|
||||
duration_in_ms = MSEC_PER_SEC * 1;
|
||||
param.duration_ms = MSEC_PER_SEC * 1;
|
||||
}
|
||||
|
||||
if (argc > 4) {
|
||||
packet_size = parse_number(argv[start + 4], K, K_UNIT);
|
||||
param.packet_size = parse_number(argv[start + 4], K, K_UNIT);
|
||||
} else {
|
||||
packet_size = 256U;
|
||||
param.packet_size = 256U;
|
||||
}
|
||||
|
||||
if (argc > 5) {
|
||||
rate_in_kbps =
|
||||
(parse_number(argv[start + 5], K, K_UNIT) +
|
||||
1023) / 1024;
|
||||
param.rate_kbps =
|
||||
(parse_number(argv[start + 5], K, K_UNIT) + 1023) / 1024;
|
||||
} else {
|
||||
rate_in_kbps = 10U;
|
||||
param.rate_kbps = 10U;
|
||||
}
|
||||
|
||||
return execute_upload(sh, sock6, sock4, family, &ipv6, &ipv4,
|
||||
is_udp, port, duration_in_ms,
|
||||
packet_size, rate_in_kbps);
|
||||
return execute_upload(sh, ¶m, is_udp);
|
||||
}
|
||||
|
||||
static int cmd_tcp_upload(const struct shell *sh, size_t argc, char *argv[])
|
||||
|
@ -872,14 +727,11 @@ static int cmd_udp_upload(const struct shell *sh, size_t argc, char *argv[])
|
|||
static int shell_cmd_upload2(const struct shell *sh, size_t argc,
|
||||
char *argv[], enum net_ip_protocol proto)
|
||||
{
|
||||
int sock6 = -1, sock4 = -1;
|
||||
uint16_t port = DEF_PORT;
|
||||
unsigned int duration_in_ms, packet_size, rate_in_kbps;
|
||||
struct zperf_upload_params param = { 0 };
|
||||
sa_family_t family;
|
||||
uint8_t is_udp;
|
||||
int start = 0;
|
||||
size_t opt_cnt = 0;
|
||||
int tos = -1;
|
||||
|
||||
is_udp = proto == IPPROTO_UDP;
|
||||
|
||||
|
@ -891,13 +743,16 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc,
|
|||
|
||||
switch (argv[i][1]) {
|
||||
case 'S':
|
||||
tos = parse_arg(&i, argc, argv);
|
||||
int tos = parse_arg(&i, argc, argv);
|
||||
|
||||
if (tos < 0 || tos > UINT8_MAX) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Parse error: %s\n", argv[i]);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
param.options.tos = tos;
|
||||
|
||||
break;
|
||||
default:
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
|
@ -932,21 +787,7 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc,
|
|||
|
||||
family = !strcmp(argv[start + 1], "v4") ? AF_INET : AF_INET6;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
in6_addr_my.sin6_port = htons(port);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
in4_addr_my.sin_port = htons(port);
|
||||
}
|
||||
|
||||
if (family == AF_INET6) {
|
||||
if (net_ipv6_is_addr_unspecified(&in6_addr_my.sin6_addr)) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Invalid local IPv6 address.\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
if (net_ipv6_is_addr_unspecified(&in6_addr_dst.sin6_addr)) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Invalid destination IPv6 address.\n");
|
||||
|
@ -956,13 +797,9 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc,
|
|||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"Connecting to %s\n",
|
||||
net_sprint_ipv6_addr(&in6_addr_dst.sin6_addr));
|
||||
} else {
|
||||
if (net_ipv4_is_addr_unspecified(&in4_addr_my.sin_addr)) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Invalid local IPv4 address.\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
memcpy(¶m.peer_addr, &in6_addr_dst, sizeof(in6_addr_dst));
|
||||
} else {
|
||||
if (net_ipv4_is_addr_unspecified(&in4_addr_dst.sin_addr)) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Invalid destination IPv4 address.\n");
|
||||
|
@ -972,37 +809,31 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc,
|
|||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"Connecting to %s\n",
|
||||
net_sprint_ipv4_addr(&in4_addr_dst.sin_addr));
|
||||
}
|
||||
|
||||
if (setup_upload_sockets(sh, &sock6, &sock4, family, &in6_addr_my,
|
||||
&in4_addr_my, port, tos, is_udp) < 0) {
|
||||
return -ENOEXEC;
|
||||
memcpy(¶m.peer_addr, &in4_addr_dst, sizeof(in4_addr_dst));
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
duration_in_ms = MSEC_PER_SEC * strtoul(argv[start + 2],
|
||||
NULL, 10);
|
||||
param.duration_ms = MSEC_PER_SEC * strtoul(argv[start + 2],
|
||||
NULL, 10);
|
||||
} else {
|
||||
duration_in_ms = MSEC_PER_SEC * 1;
|
||||
param.duration_ms = MSEC_PER_SEC * 1;
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
packet_size = parse_number(argv[start + 3], K, K_UNIT);
|
||||
param.packet_size = parse_number(argv[start + 3], K, K_UNIT);
|
||||
} else {
|
||||
packet_size = 256U;
|
||||
param.packet_size = 256U;
|
||||
}
|
||||
|
||||
if (argc > 4) {
|
||||
rate_in_kbps =
|
||||
(parse_number(argv[start + 4], K, K_UNIT) + 1023) /
|
||||
1024;
|
||||
param.rate_kbps =
|
||||
(parse_number(argv[start + 4], K, K_UNIT) + 1023) / 1024;
|
||||
} else {
|
||||
rate_in_kbps = 10U;
|
||||
param.rate_kbps = 10U;
|
||||
}
|
||||
|
||||
return execute_upload(sh, sock6, sock4, family, &in6_addr_dst,
|
||||
&in4_addr_dst, is_udp, port,
|
||||
duration_in_ms, packet_size, rate_in_kbps);
|
||||
return execute_upload(sh, ¶m, is_udp);
|
||||
}
|
||||
|
||||
static int cmd_tcp_upload2(const struct shell *sh, size_t argc,
|
||||
|
@ -1105,7 +936,7 @@ static int cmd_tcp_download(const struct shell *sh, size_t argc,
|
|||
static int cmd_version(const struct shell *sh, size_t argc, char *argv[])
|
||||
{
|
||||
shell_fprintf(sh, SHELL_NORMAL, "Version: %s\nConfig: %s\n",
|
||||
VERSION, CONFIG);
|
||||
ZPERF_VERSION, CONFIG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
|
|||
#include <zephyr/toolchain.h>
|
||||
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <zephyr/net/zperf.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
#include "shell_utils.h"
|
||||
#include "zperf_session.h"
|
||||
|
|
|
@ -12,14 +12,13 @@ LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
|
|||
#include <errno.h>
|
||||
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <zephyr/net/zperf.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
|
||||
static char sample_packet[PACKET_SIZE_MAX];
|
||||
|
||||
void zperf_tcp_upload(const struct shell *sh,
|
||||
int sock,
|
||||
static int tcp_upload(int sock,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
struct zperf_results *results)
|
||||
|
@ -28,11 +27,11 @@ void zperf_tcp_upload(const struct shell *sh,
|
|||
int64_t start_time, last_print_time, end_time, remaining;
|
||||
uint32_t nb_packets = 0U, nb_errors = 0U;
|
||||
uint32_t alloc_errors = 0U;
|
||||
int ret = 0;
|
||||
|
||||
if (packet_size > PACKET_SIZE_MAX) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Packet size too large! max size: %u\n",
|
||||
PACKET_SIZE_MAX);
|
||||
NET_WARN("Packet size too large! max size: %u\n",
|
||||
PACKET_SIZE_MAX);
|
||||
packet_size = PACKET_SIZE_MAX;
|
||||
}
|
||||
|
||||
|
@ -40,9 +39,6 @@ void zperf_tcp_upload(const struct shell *sh,
|
|||
start_time = k_uptime_ticks();
|
||||
last_print_time = start_time;
|
||||
|
||||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"New session started\n");
|
||||
|
||||
(void)memset(sample_packet, 'z', sizeof(sample_packet));
|
||||
|
||||
/* Set the "flags" field in start of the packet to be 0.
|
||||
|
@ -52,15 +48,11 @@ void zperf_tcp_upload(const struct shell *sh,
|
|||
(void)memset(sample_packet, 0, sizeof(uint32_t));
|
||||
|
||||
do {
|
||||
int ret = 0;
|
||||
|
||||
/* Send the packet */
|
||||
ret = zsock_send(sock, sample_packet, packet_size, 0);
|
||||
if (ret < 0) {
|
||||
if (nb_errors == 0 && ret != -ENOMEM) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Failed to send the packet (%d)\n",
|
||||
errno);
|
||||
NET_ERR("Failed to send the packet (%d)", errno);
|
||||
}
|
||||
|
||||
nb_errors++;
|
||||
|
@ -73,6 +65,7 @@ void zperf_tcp_upload(const struct shell *sh,
|
|||
*/
|
||||
alloc_errors++;
|
||||
} else {
|
||||
ret = -errno;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
|
@ -98,12 +91,40 @@ void zperf_tcp_upload(const struct shell *sh,
|
|||
results->nb_packets_errors = nb_errors;
|
||||
|
||||
if (alloc_errors > 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"There was %u network buffer allocation "
|
||||
"errors during send.\nConsider increasing the "
|
||||
"value of CONFIG_NET_BUF_TX_COUNT and\n"
|
||||
"optionally CONFIG_NET_PKT_TX_COUNT Kconfig "
|
||||
"options.\n",
|
||||
alloc_errors);
|
||||
NET_WARN("There was %u network buffer allocation "
|
||||
"errors during send.\nConsider increasing the "
|
||||
"value of CONFIG_NET_BUF_TX_COUNT and\n"
|
||||
"optionally CONFIG_NET_PKT_TX_COUNT Kconfig "
|
||||
"options.",
|
||||
alloc_errors);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zperf_tcp_upload(const struct zperf_upload_params *param,
|
||||
struct zperf_results *result)
|
||||
{
|
||||
int sock;
|
||||
int ret;
|
||||
|
||||
if (param == NULL || result == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sock = zperf_prepare_upload_sock(¶m->peer_addr, param->options.tos,
|
||||
IPPROTO_TCP);
|
||||
if (sock < 0) {
|
||||
return sock;
|
||||
}
|
||||
|
||||
ret = tcp_upload(sock, param->duration_ms, param->packet_size, result);
|
||||
|
||||
zsock_close(sock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
|
|||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <zephyr/net/zperf.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
#include "shell_utils.h"
|
||||
#include "zperf_session.h"
|
||||
|
|
|
@ -10,16 +10,15 @@ LOG_MODULE_DECLARE(net_zperf, CONFIG_NET_ZPERF_LOG_LEVEL);
|
|||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <zephyr/net/zperf.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
|
||||
static uint8_t sample_packet[sizeof(struct zperf_udp_datagram) +
|
||||
sizeof(struct zperf_client_hdr_v1) +
|
||||
PACKET_SIZE_MAX];
|
||||
|
||||
static inline void zperf_upload_decode_stat(const struct shell *sh,
|
||||
const uint8_t *data,
|
||||
static inline void zperf_upload_decode_stat(const uint8_t *data,
|
||||
size_t datalen,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
|
@ -27,8 +26,7 @@ static inline void zperf_upload_decode_stat(const struct shell *sh,
|
|||
|
||||
if (datalen < sizeof(struct zperf_udp_datagram) +
|
||||
sizeof(struct zperf_server_hdr)) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Network packet too short\n");
|
||||
NET_WARN("Network packet too short");
|
||||
}
|
||||
|
||||
stat = (struct zperf_server_hdr *)
|
||||
|
@ -38,19 +36,18 @@ static inline void zperf_upload_decode_stat(const struct shell *sh,
|
|||
results->nb_packets_lost = ntohl(UNALIGNED_GET(&stat->error_cnt));
|
||||
results->nb_packets_outorder =
|
||||
ntohl(UNALIGNED_GET(&stat->outorder_cnt));
|
||||
results->nb_bytes_sent = ntohl(UNALIGNED_GET(&stat->total_len2));
|
||||
results->total_len = ntohl(UNALIGNED_GET(&stat->total_len2));
|
||||
results->time_in_us = ntohl(UNALIGNED_GET(&stat->stop_usec)) +
|
||||
ntohl(UNALIGNED_GET(&stat->stop_sec)) * USEC_PER_SEC;
|
||||
results->jitter_in_us = ntohl(UNALIGNED_GET(&stat->jitter2)) +
|
||||
ntohl(UNALIGNED_GET(&stat->jitter1)) * USEC_PER_SEC;
|
||||
}
|
||||
|
||||
static inline void zperf_upload_fin(const struct shell *sh,
|
||||
int sock,
|
||||
uint32_t nb_packets,
|
||||
uint64_t end_time,
|
||||
uint32_t packet_size,
|
||||
struct zperf_results *results)
|
||||
static inline int zperf_upload_fin(int sock,
|
||||
uint32_t nb_packets,
|
||||
uint64_t end_time,
|
||||
uint32_t packet_size,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
uint8_t stats[sizeof(struct zperf_udp_datagram) +
|
||||
sizeof(struct zperf_server_hdr)] = { 0 };
|
||||
|
@ -92,9 +89,7 @@ static inline void zperf_upload_fin(const struct shell *sh,
|
|||
/* Send the packet */
|
||||
ret = zsock_send(sock, sample_packet, packet_size, 0);
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Failed to send the packet (%d)\n",
|
||||
errno);
|
||||
NET_ERR("Failed to send the packet (%d)", errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -102,26 +97,23 @@ static inline void zperf_upload_fin(const struct shell *sh,
|
|||
ret = zsock_setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo,
|
||||
sizeof(rcvtimeo));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"setsockopt error (%d)\n",
|
||||
errno);
|
||||
NET_ERR("setsockopt error (%d)", errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = zsock_recv(sock, stats, sizeof(stats), 0);
|
||||
if (ret == -EAGAIN) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Stats receive timeout\n");
|
||||
NET_WARN("Stats receive timeout");
|
||||
} else if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Failed to receive packet (%d)\n",
|
||||
errno);
|
||||
NET_ERR("Failed to receive packet (%d)", errno);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode statistics */
|
||||
if (ret > 0) {
|
||||
zperf_upload_decode_stat(sh, stats, ret, results);
|
||||
zperf_upload_decode_stat(stats, ret, results);
|
||||
} else {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Drain RX */
|
||||
|
@ -131,50 +123,37 @@ static inline void zperf_upload_fin(const struct shell *sh,
|
|||
break;
|
||||
}
|
||||
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Drain one spurious stat packet!\n");
|
||||
NET_WARN("Drain one spurious stat packet!");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zperf_udp_upload(const struct shell *sh,
|
||||
int sock,
|
||||
int port,
|
||||
static int udp_upload(int sock, int port,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
unsigned int rate_in_kbps,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
uint32_t packet_duration = ((uint64_t)packet_size * 8U * USEC_PER_SEC) /
|
||||
(rate_in_kbps * 1024U);
|
||||
uint32_t packet_duration = zperf_packet_duration(packet_size, rate_in_kbps);
|
||||
uint64_t duration = sys_clock_timeout_end_calc(K_MSEC(duration_in_ms));
|
||||
uint64_t delay = packet_duration;
|
||||
uint32_t nb_packets = 0U;
|
||||
int64_t start_time, end_time;
|
||||
int64_t last_print_time, last_loop_time;
|
||||
int64_t remaining;
|
||||
int ret;
|
||||
|
||||
if (packet_size > PACKET_SIZE_MAX) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Packet size too large! max size: %u\n",
|
||||
PACKET_SIZE_MAX);
|
||||
NET_WARN("Packet size too large! max size: %u",
|
||||
PACKET_SIZE_MAX);
|
||||
packet_size = PACKET_SIZE_MAX;
|
||||
} else if (packet_size < sizeof(struct zperf_udp_datagram)) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Packet size set to the min size: %zu\n",
|
||||
sizeof(struct zperf_udp_datagram));
|
||||
NET_WARN("Packet size set to the min size: %zu",
|
||||
sizeof(struct zperf_udp_datagram));
|
||||
packet_size = sizeof(struct zperf_udp_datagram);
|
||||
}
|
||||
|
||||
if (packet_duration > 1000U) {
|
||||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"Packet duration %u ms\n",
|
||||
(unsigned int)(packet_duration / 1000U));
|
||||
} else {
|
||||
shell_fprintf(sh, SHELL_NORMAL,
|
||||
"Packet duration %u us\n",
|
||||
(unsigned int)packet_duration);
|
||||
}
|
||||
|
||||
/* Start the loop */
|
||||
start_time = k_uptime_ticks();
|
||||
last_print_time = start_time;
|
||||
|
@ -188,7 +167,6 @@ void zperf_udp_upload(const struct shell *sh,
|
|||
uint32_t secs, usecs;
|
||||
int64_t loop_time;
|
||||
int32_t adjust;
|
||||
int ret;
|
||||
|
||||
/* Timestamp */
|
||||
loop_time = k_uptime_ticks();
|
||||
|
@ -237,10 +215,8 @@ void zperf_udp_upload(const struct shell *sh,
|
|||
/* Send the packet */
|
||||
ret = zsock_send(sock, sample_packet, packet_size, 0);
|
||||
if (ret < 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"Failed to send the packet (%d)\n",
|
||||
errno);
|
||||
break;
|
||||
NET_ERR("Failed to send the packet (%d)", errno);
|
||||
return -errno;
|
||||
} else {
|
||||
nb_packets++;
|
||||
}
|
||||
|
@ -251,10 +227,9 @@ void zperf_udp_upload(const struct shell *sh,
|
|||
int64_t print_info = print_interval - k_uptime_ticks();
|
||||
|
||||
if (print_info <= 0) {
|
||||
shell_fprintf(sh, SHELL_WARNING,
|
||||
"nb_packets=%u\tdelay=%u\tadjust=%d\n",
|
||||
nb_packets, (unsigned int)delay,
|
||||
(int)adjust);
|
||||
NET_DBG("nb_packets=%u\tdelay=%u\tadjust=%d",
|
||||
nb_packets, (unsigned int)delay,
|
||||
(int)adjust);
|
||||
print_interval = sys_clock_timeout_end_calc(K_SECONDS(1));
|
||||
}
|
||||
}
|
||||
|
@ -277,12 +252,52 @@ void zperf_udp_upload(const struct shell *sh,
|
|||
|
||||
end_time = k_uptime_ticks();
|
||||
|
||||
zperf_upload_fin(sh, sock, nb_packets, end_time, packet_size,
|
||||
results);
|
||||
ret = zperf_upload_fin(sock, nb_packets, end_time, packet_size,
|
||||
results);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Add result coming from the client */
|
||||
results->nb_packets_sent = nb_packets;
|
||||
results->client_time_in_us =
|
||||
k_ticks_to_us_ceil32(end_time - start_time);
|
||||
results->packet_size = packet_size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int zperf_udp_upload(const struct zperf_upload_params *param,
|
||||
struct zperf_results *result)
|
||||
{
|
||||
int port = 0;
|
||||
int sock;
|
||||
int ret;
|
||||
|
||||
if (param == NULL || result == NULL) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (param->peer_addr.sa_family == AF_INET) {
|
||||
port = ntohs(net_sin(¶m->peer_addr)->sin_port);
|
||||
} else if (param->peer_addr.sa_family == AF_INET6) {
|
||||
port = ntohs(net_sin6(¶m->peer_addr)->sin6_port);
|
||||
} else {
|
||||
NET_ERR("Invalid address family (%d)",
|
||||
param->peer_addr.sa_family);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sock = zperf_prepare_upload_sock(¶m->peer_addr, param->options.tos,
|
||||
IPPROTO_UDP);
|
||||
if (sock < 0) {
|
||||
return sock;
|
||||
}
|
||||
|
||||
ret = udp_upload(sock, port, param->duration_ms, param->packet_size,
|
||||
param->rate_kbps, result);
|
||||
|
||||
zsock_close(sock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue