samples: net: zperf: Rewrite upload part to use sockets
Rewrite TCP/UDP upload part of the zperf sample to use socket API instead of net_context. This has a negligible impact on the upload throughputs (< 1 Mbps). Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
parent
ef6770f22b
commit
6c30c9ac47
5 changed files with 134 additions and 193 deletions
|
|
@ -11,11 +11,17 @@ CONFIG_NET_PKT_RX_COUNT=14
|
|||
CONFIG_NET_PKT_TX_COUNT=14
|
||||
CONFIG_NET_BUF_RX_COUNT=28
|
||||
CONFIG_NET_BUF_TX_COUNT=28
|
||||
CONFIG_NET_BUF_DATA_SIZE=1500
|
||||
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=4
|
||||
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5
|
||||
CONFIG_NET_IF_UNICAST_IPV4_ADDR_COUNT=1
|
||||
CONFIG_NET_MAX_CONTEXTS=5
|
||||
CONFIG_NET_CONTEXT_SYNC_RECV=y
|
||||
CONFIG_NET_CONTEXT_RCVTIMEO=y
|
||||
CONFIG_NET_TC_TX_COUNT=1
|
||||
CONFIG_NET_SOCKETS=y
|
||||
CONFIG_NET_SOCKETS_POSIX_NAMES=y
|
||||
CONFIG_NET_SOCKETS_POLL_MAX=4
|
||||
CONFIG_POSIX_MAX_FDS=8
|
||||
|
||||
CONFIG_INIT_STACKS=y
|
||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ int zperf_get_ipv4_addr(const struct shell *shell, char *host,
|
|||
struct sockaddr_in *zperf_get_sin(void);
|
||||
|
||||
extern void zperf_udp_upload(const struct shell *shell,
|
||||
struct net_context *context,
|
||||
int sock,
|
||||
int port,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
|
|
@ -91,7 +91,7 @@ extern void zperf_udp_receiver_init(const struct shell *shell, int port);
|
|||
extern void zperf_tcp_receiver_init(const struct shell *shell, int port);
|
||||
extern void zperf_tcp_uploader_init(struct k_fifo *tx_queue);
|
||||
extern void zperf_tcp_upload(const struct shell *shell,
|
||||
struct net_context *net_context,
|
||||
int sock,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
struct zperf_results *results);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ LOG_MODULE_REGISTER(net_zperf_sample, LOG_LEVEL_DBG);
|
|||
|
||||
#include <zephyr/net/net_ip.h>
|
||||
#include <zephyr/net/net_core.h>
|
||||
#include <zephyr/net/socket.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
|
|
@ -52,7 +53,6 @@ static const char *CONFIG =
|
|||
#define MY_SRC_PORT 50000
|
||||
#define DEF_PORT 5001
|
||||
#define DEF_PORT_STR STRINGIFY(DEF_PORT)
|
||||
#define WAIT_CONNECT K_SECONDS(2) /* in ms */
|
||||
|
||||
static struct in6_addr ipv6;
|
||||
|
||||
|
|
@ -451,27 +451,24 @@ static void shell_tcp_upload_print_stats(const struct shell *shell,
|
|||
}
|
||||
}
|
||||
|
||||
static int setup_contexts(const struct shell *shell,
|
||||
struct net_context **context6,
|
||||
struct net_context **context4,
|
||||
sa_family_t family,
|
||||
struct sockaddr_in6 *ipv6,
|
||||
struct sockaddr_in *ipv4,
|
||||
int port,
|
||||
bool is_udp,
|
||||
char *argv0)
|
||||
static int setup_upload_sockets(const struct shell *shell,
|
||||
int *sock6,
|
||||
int *sock4,
|
||||
sa_family_t family,
|
||||
struct sockaddr_in6 *ipv6,
|
||||
struct sockaddr_in *ipv4,
|
||||
int port,
|
||||
bool is_udp,
|
||||
char *argv0)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
ret = net_context_get(AF_INET6,
|
||||
is_udp ? SOCK_DGRAM : SOCK_STREAM,
|
||||
is_udp ? IPPROTO_UDP : IPPROTO_TCP,
|
||||
context6);
|
||||
if (ret < 0) {
|
||||
*sock6 = socket(AF_INET6,
|
||||
is_udp ? SOCK_DGRAM : SOCK_STREAM,
|
||||
is_udp ? IPPROTO_UDP : IPPROTO_TCP);
|
||||
if (*sock6 < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Cannot get IPv6 network context (%d)\n",
|
||||
ret);
|
||||
"Cannot create IPv6 network socket (%d)\n",
|
||||
errno);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
|
@ -480,14 +477,13 @@ static int setup_contexts(const struct shell *shell,
|
|||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
ret = net_context_get(AF_INET,
|
||||
is_udp ? SOCK_DGRAM : SOCK_STREAM,
|
||||
is_udp ? IPPROTO_UDP : IPPROTO_TCP,
|
||||
context4);
|
||||
if (ret < 0) {
|
||||
*sock4 = socket(AF_INET,
|
||||
is_udp ? SOCK_DGRAM : SOCK_STREAM,
|
||||
is_udp ? IPPROTO_UDP : IPPROTO_TCP);
|
||||
if (*sock4 < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Cannot get IPv4 network context (%d)\n",
|
||||
ret);
|
||||
"Cannot create IPv4 network socket (%d)\n",
|
||||
errno);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
|
@ -495,33 +491,9 @@ static int setup_contexts(const struct shell *shell,
|
|||
ipv4->sin_family = AF_INET;
|
||||
}
|
||||
|
||||
if (family == AF_INET6 && *context6) {
|
||||
ret = net_context_bind(*context6,
|
||||
(struct sockaddr *)ipv6,
|
||||
sizeof(struct sockaddr_in6));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_NORMAL,
|
||||
"Cannot bind IPv6 port %d (%d)",
|
||||
ntohs(ipv6->sin6_port), ret);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
if (family == AF_INET && *context4) {
|
||||
ret = net_context_bind(*context4,
|
||||
(struct sockaddr *)ipv4,
|
||||
sizeof(struct sockaddr_in));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Cannot bind IPv4 port %d (%d)",
|
||||
ntohs(ipv4->sin_port), ret);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(*context6) && !(*context4)) {
|
||||
if ((*sock6 < 0) && (*sock4 < 0)) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Fail to retrieve network context(s)\n");
|
||||
"Fail to create network socket(s)\n");
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
|
@ -529,8 +501,8 @@ static int setup_contexts(const struct shell *shell,
|
|||
}
|
||||
|
||||
static int execute_upload(const struct shell *shell,
|
||||
struct net_context *context6,
|
||||
struct net_context *context4,
|
||||
int sock6,
|
||||
int sock4,
|
||||
sa_family_t family,
|
||||
struct sockaddr_in6 *ipv6,
|
||||
struct sockaddr_in *ipv4,
|
||||
|
|
@ -554,7 +526,7 @@ static int execute_upload(const struct shell *shell,
|
|||
rate_in_kbps);
|
||||
shell_fprintf(shell, SHELL_NORMAL, "Starting...\n");
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6 && context6) {
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && family == AF_INET6 && sock6 >= 0) {
|
||||
/* 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.
|
||||
|
|
@ -570,40 +542,34 @@ static int execute_upload(const struct shell *shell,
|
|||
print_number(shell, rate_in_kbps, KBPS, KBPS_UNIT);
|
||||
shell_fprintf(shell, SHELL_NORMAL, "\n");
|
||||
|
||||
if (family == AF_INET6 && context6) {
|
||||
ret = net_context_connect(context6,
|
||||
(struct sockaddr *)ipv6,
|
||||
sizeof(*ipv6),
|
||||
NULL,
|
||||
K_NO_WAIT,
|
||||
NULL);
|
||||
if (family == AF_INET6 && sock6 >= 0) {
|
||||
ret = connect(sock6,
|
||||
(struct sockaddr *)ipv6,
|
||||
sizeof(*ipv6));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"IPv6 connect failed (%d)\n",
|
||||
ret);
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
zperf_udp_upload(shell, context6, port, duration_in_ms,
|
||||
zperf_udp_upload(shell, sock6, port, duration_in_ms,
|
||||
packet_size, rate_in_kbps, &results);
|
||||
shell_udp_upload_print_stats(shell, &results);
|
||||
}
|
||||
|
||||
if (family == AF_INET && context4) {
|
||||
ret = net_context_connect(context4,
|
||||
(struct sockaddr *)ipv4,
|
||||
sizeof(*ipv4),
|
||||
NULL,
|
||||
K_NO_WAIT,
|
||||
NULL);
|
||||
if (family == AF_INET && sock4 >= 0) {
|
||||
ret = connect(sock4,
|
||||
(struct sockaddr *)ipv4,
|
||||
sizeof(*ipv4));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_NORMAL,
|
||||
"IPv4 connect failed (%d)\n",
|
||||
ret);
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
zperf_udp_upload(shell, context4, port, duration_in_ms,
|
||||
zperf_udp_upload(shell, sock4, port, duration_in_ms,
|
||||
packet_size, rate_in_kbps, &results);
|
||||
shell_udp_upload_print_stats(shell, &results);
|
||||
}
|
||||
|
|
@ -615,59 +581,51 @@ static int execute_upload(const struct shell *shell,
|
|||
}
|
||||
|
||||
if (!is_udp && IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
if (family == AF_INET6 && context6) {
|
||||
ret = net_context_connect(context6,
|
||||
(struct sockaddr *)ipv6,
|
||||
sizeof(*ipv6),
|
||||
NULL,
|
||||
WAIT_CONNECT,
|
||||
NULL);
|
||||
if (family == AF_INET6 && sock6 >= 0) {
|
||||
ret = connect(sock6,
|
||||
(struct sockaddr *)ipv6,
|
||||
sizeof(*ipv6));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"IPv6 connect failed (%d)\n",
|
||||
ret);
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* We either upload using IPv4 or IPv6, not both at
|
||||
* the same time.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
net_context_put(context4);
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && sock4 >= 0) {
|
||||
(void)close(sock4);
|
||||
sock4 = -1;
|
||||
}
|
||||
|
||||
zperf_tcp_upload(shell, context6, duration_in_ms,
|
||||
zperf_tcp_upload(shell, sock6, duration_in_ms,
|
||||
packet_size, &results);
|
||||
|
||||
shell_tcp_upload_print_stats(shell, &results);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (family == AF_INET && context4) {
|
||||
ret = net_context_connect(context4,
|
||||
(struct sockaddr *)ipv4,
|
||||
sizeof(*ipv4),
|
||||
NULL,
|
||||
WAIT_CONNECT,
|
||||
NULL);
|
||||
if (family == AF_INET && sock4 >= 0) {
|
||||
ret = connect(sock4,
|
||||
(struct sockaddr *)ipv4,
|
||||
sizeof(*ipv4));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"IPv4 connect failed (%d)\n",
|
||||
ret);
|
||||
errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
net_context_put(context6);
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && sock6 >= 0) {
|
||||
(void)close(sock6);
|
||||
sock6 = -1;
|
||||
}
|
||||
|
||||
zperf_tcp_upload(shell, context4, duration_in_ms,
|
||||
zperf_tcp_upload(shell, sock4, duration_in_ms,
|
||||
packet_size, &results);
|
||||
|
||||
shell_tcp_upload_print_stats(shell, &results);
|
||||
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!IS_ENABLED(CONFIG_NET_TCP)) {
|
||||
|
|
@ -677,11 +635,14 @@ static int execute_upload(const struct shell *shell,
|
|||
}
|
||||
|
||||
out:
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6)) {
|
||||
net_context_put(context6);
|
||||
if (IS_ENABLED(CONFIG_NET_IPV6) && sock6 >= 0) {
|
||||
(void)close(sock6);
|
||||
sock6 = -1;
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4)) {
|
||||
net_context_put(context4);
|
||||
|
||||
if (IS_ENABLED(CONFIG_NET_IPV4) && sock4 >= 0) {
|
||||
(void)close(sock4);
|
||||
sock4 = -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
@ -692,7 +653,7 @@ static int shell_cmd_upload(const struct shell *shell, size_t argc,
|
|||
{
|
||||
struct sockaddr_in6 ipv6 = { .sin6_family = AF_INET6 };
|
||||
struct sockaddr_in ipv4 = { .sin_family = AF_INET };
|
||||
struct net_context *context6 = NULL, *context4 = NULL;
|
||||
int sock6 = -1, sock4 = -1;
|
||||
sa_family_t family = AF_UNSPEC;
|
||||
unsigned int duration_in_ms, packet_size, rate_in_kbps;
|
||||
char *port_str;
|
||||
|
|
@ -786,8 +747,8 @@ static int shell_cmd_upload(const struct shell *shell, size_t argc,
|
|||
}
|
||||
}
|
||||
|
||||
if (setup_contexts(shell, &context6, &context4, family, &in6_addr_my,
|
||||
&in4_addr_my, port, is_udp, argv[start]) < 0) {
|
||||
if (setup_upload_sockets(shell, &sock6, &sock4, family, &in6_addr_my,
|
||||
&in4_addr_my, port, is_udp, argv[start]) < 0) {
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
|
@ -812,7 +773,7 @@ static int shell_cmd_upload(const struct shell *shell, size_t argc,
|
|||
rate_in_kbps = 10U;
|
||||
}
|
||||
|
||||
return execute_upload(shell, context6, context4, family, &ipv6, &ipv4,
|
||||
return execute_upload(shell, sock6, sock4, family, &ipv6, &ipv4,
|
||||
is_udp, port, argv[start], duration_in_ms,
|
||||
packet_size, rate_in_kbps);
|
||||
}
|
||||
|
|
@ -834,7 +795,7 @@ static int cmd_udp_upload(const struct shell *shell, size_t argc, char *argv[])
|
|||
static int shell_cmd_upload2(const struct shell *shell, size_t argc,
|
||||
char *argv[], enum net_ip_protocol proto)
|
||||
{
|
||||
struct net_context *context6 = NULL, *context4 = NULL;
|
||||
int sock6 = -1, sock4 = -1;
|
||||
uint16_t port = DEF_PORT;
|
||||
unsigned int duration_in_ms, packet_size, rate_in_kbps;
|
||||
sa_family_t family;
|
||||
|
|
@ -906,8 +867,8 @@ static int shell_cmd_upload2(const struct shell *shell, size_t argc,
|
|||
net_sprint_ipv4_addr(&in4_addr_dst.sin_addr));
|
||||
}
|
||||
|
||||
if (setup_contexts(shell, &context6, &context4, family, &in6_addr_my,
|
||||
&in4_addr_my, port, is_udp, argv[start]) < 0) {
|
||||
if (setup_upload_sockets(shell, &sock6, &sock4, family, &in6_addr_my,
|
||||
&in4_addr_my, port, is_udp, argv[start]) < 0) {
|
||||
return -ENOEXEC;
|
||||
}
|
||||
|
||||
|
|
@ -932,7 +893,7 @@ static int shell_cmd_upload2(const struct shell *shell, size_t argc,
|
|||
rate_in_kbps = 10U;
|
||||
}
|
||||
|
||||
return execute_upload(shell, context6, context4, family, &in6_addr_dst,
|
||||
return execute_upload(shell, sock6, sock4, family, &in6_addr_dst,
|
||||
&in4_addr_dst, is_udp, port, argv[start],
|
||||
duration_in_ms, packet_size, rate_in_kbps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,9 +12,7 @@ LOG_MODULE_DECLARE(net_zperf_sample, LOG_LEVEL_DBG);
|
|||
#include <errno.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
|
||||
#include <zephyr/net/net_pkt.h>
|
||||
#include <zephyr/net/net_ip.h>
|
||||
#include <zephyr/net/net_core.h>
|
||||
#include <zephyr/net/socket.h>
|
||||
|
||||
#include "zperf.h"
|
||||
#include "zperf_internal.h"
|
||||
|
|
@ -22,7 +20,7 @@ LOG_MODULE_DECLARE(net_zperf_sample, LOG_LEVEL_DBG);
|
|||
static char sample_packet[PACKET_SIZE_MAX];
|
||||
|
||||
void zperf_tcp_upload(const struct shell *shell,
|
||||
struct net_context *ctx,
|
||||
int sock,
|
||||
unsigned int duration_in_ms,
|
||||
unsigned int packet_size,
|
||||
struct zperf_results *results)
|
||||
|
|
@ -58,19 +56,17 @@ void zperf_tcp_upload(const struct shell *shell,
|
|||
int ret = 0;
|
||||
|
||||
/* Send the packet */
|
||||
ret = net_context_send(ctx, sample_packet,
|
||||
packet_size, NULL,
|
||||
K_NO_WAIT, NULL);
|
||||
ret = send(sock, sample_packet, packet_size, 0);
|
||||
if (ret < 0) {
|
||||
if (nb_errors == 0 && ret != -ENOMEM) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Failed to send the packet (%d)\n",
|
||||
ret);
|
||||
"Failed to send the packet (%d)\n",
|
||||
errno);
|
||||
}
|
||||
|
||||
nb_errors++;
|
||||
|
||||
if (ret == -ENOMEM) {
|
||||
if (errno == -ENOMEM) {
|
||||
/* Ignore memory errors as we just run out of
|
||||
* buffers which is kind of expected if the
|
||||
* buffer count is not optimized for the test
|
||||
|
|
@ -111,6 +107,4 @@ void zperf_tcp_upload(const struct shell *shell,
|
|||
"options.\n",
|
||||
alloc_errors);
|
||||
}
|
||||
|
||||
net_context_put(ctx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,43 +11,30 @@ LOG_MODULE_DECLARE(net_zperf_sample, LOG_LEVEL_DBG);
|
|||
|
||||
#include <zephyr/sys/printk.h>
|
||||
|
||||
#include <zephyr/net/net_core.h>
|
||||
#include <zephyr/net/net_ip.h>
|
||||
#include <zephyr/net/net_pkt.h>
|
||||
#include <zephyr/net/socket.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];
|
||||
sizeof(struct zperf_client_hdr_v1) +
|
||||
PACKET_SIZE_MAX];
|
||||
|
||||
static inline void zperf_upload_decode_stat(const struct shell *shell,
|
||||
struct net_pkt *pkt,
|
||||
const uint8_t *data,
|
||||
size_t datalen,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
NET_PKT_DATA_ACCESS_DEFINE(zperf_udp, struct zperf_udp_datagram);
|
||||
NET_PKT_DATA_ACCESS_DEFINE(zperf_stat, struct zperf_server_hdr);
|
||||
struct zperf_udp_datagram *hdr;
|
||||
struct zperf_server_hdr *stat;
|
||||
|
||||
hdr = (struct zperf_udp_datagram *)
|
||||
net_pkt_get_data(pkt, &zperf_udp);
|
||||
if (!hdr) {
|
||||
if (datalen < sizeof(struct zperf_udp_datagram) +
|
||||
sizeof(struct zperf_server_hdr)) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Network packet too short\n");
|
||||
return;
|
||||
}
|
||||
|
||||
net_pkt_acknowledge_data(pkt, &zperf_udp);
|
||||
|
||||
stat = (struct zperf_server_hdr *)
|
||||
net_pkt_get_data(pkt, &zperf_stat);
|
||||
if (!stat) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Network packet too short\n");
|
||||
return;
|
||||
}
|
||||
(data + sizeof(struct zperf_udp_datagram));
|
||||
|
||||
results->nb_packets_rcvd = ntohl(UNALIGNED_GET(&stat->datagrams));
|
||||
results->nb_packets_lost = ntohl(UNALIGNED_GET(&stat->error_cnt));
|
||||
|
|
@ -60,34 +47,27 @@ static inline void zperf_upload_decode_stat(const struct shell *shell,
|
|||
ntohl(UNALIGNED_GET(&stat->jitter1)) * USEC_PER_SEC;
|
||||
}
|
||||
|
||||
static void stat_received(struct net_context *context,
|
||||
struct net_pkt *pkt,
|
||||
union net_ip_header *ip_hdr,
|
||||
union net_proto_header *proto_hdr,
|
||||
int status,
|
||||
void *user_data)
|
||||
{
|
||||
struct net_pkt **stat = user_data;
|
||||
|
||||
*stat = pkt;
|
||||
}
|
||||
|
||||
static inline void zperf_upload_fin(const struct shell *shell,
|
||||
struct net_context *context,
|
||||
int sock,
|
||||
uint32_t nb_packets,
|
||||
uint64_t end_time,
|
||||
uint32_t packet_size,
|
||||
struct zperf_results *results)
|
||||
{
|
||||
struct net_pkt *stat = NULL;
|
||||
uint8_t stats[sizeof(struct zperf_udp_datagram) +
|
||||
sizeof(struct zperf_server_hdr)] = { 0 };
|
||||
struct zperf_udp_datagram *datagram;
|
||||
struct zperf_client_hdr_v1 *hdr;
|
||||
uint32_t secs = k_ticks_to_ms_ceil32(end_time) / 1000U;
|
||||
uint32_t usecs = k_ticks_to_us_ceil32(end_time) - secs * USEC_PER_SEC;
|
||||
int loop = 2;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct timeval rcvtimeo = {
|
||||
.tv_sec = 2,
|
||||
.tv_usec = 0,
|
||||
};
|
||||
|
||||
while (!stat && loop-- > 0) {
|
||||
while (ret <= 0 && loop-- > 0) {
|
||||
datagram = (struct zperf_udp_datagram *)sample_packet;
|
||||
|
||||
/* Fill the packet header */
|
||||
|
|
@ -112,60 +92,61 @@ static inline void zperf_upload_fin(const struct shell *shell,
|
|||
hdr->num_of_bytes = htonl(packet_size);
|
||||
|
||||
/* Send the packet */
|
||||
ret = net_context_send(context, sample_packet, packet_size,
|
||||
NULL, K_NO_WAIT, NULL);
|
||||
ret = send(sock, sample_packet, packet_size, 0);
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Failed to send the packet (%d)\n",
|
||||
ret);
|
||||
errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Receive statistics */
|
||||
stat = NULL;
|
||||
ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &rcvtimeo,
|
||||
sizeof(rcvtimeo));
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"setsockopt error (%d)\n",
|
||||
errno);
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = net_context_recv(context, stat_received,
|
||||
K_SECONDS(2), &stat);
|
||||
if (ret == -ETIMEDOUT) {
|
||||
break;
|
||||
ret = recv(sock, stats, sizeof(stats), 0);
|
||||
if (ret == -EAGAIN) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Stats receive timeout\n");
|
||||
} else if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Failed to receive packet (%d)\n",
|
||||
errno);
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode statistics */
|
||||
if (stat) {
|
||||
zperf_upload_decode_stat(shell, stat, results);
|
||||
|
||||
net_pkt_unref(stat);
|
||||
if (ret > 0) {
|
||||
zperf_upload_decode_stat(shell, stats, ret, results);
|
||||
}
|
||||
|
||||
/* Drain RX */
|
||||
while (stat) {
|
||||
stat = NULL;
|
||||
|
||||
ret = net_context_recv(context, stat_received,
|
||||
K_NO_WAIT, &stat);
|
||||
if (ret == -ETIMEDOUT) {
|
||||
while (true) {
|
||||
ret = recv(sock, stats, sizeof(stats), MSG_DONTWAIT);
|
||||
if (ret < 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (stat) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Drain one spurious stat packet!\n");
|
||||
|
||||
net_pkt_unref(stat);
|
||||
}
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Drain one spurious stat packet!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void zperf_udp_upload(const struct shell *shell,
|
||||
struct net_context *context,
|
||||
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 = ((uint32_t)packet_size * 8U * USEC_PER_SEC) /
|
||||
uint32_t packet_duration = ((uint64_t)packet_size * 8U * USEC_PER_SEC) /
|
||||
(rate_in_kbps * 1024U);
|
||||
uint64_t duration = sys_clock_timeout_end_calc(K_MSEC(duration_in_ms));
|
||||
int64_t print_interval = sys_clock_timeout_end_calc(K_SECONDS(1));
|
||||
|
|
@ -257,12 +238,11 @@ void zperf_udp_upload(const struct shell *shell,
|
|||
hdr->num_of_bytes = htonl(packet_size);
|
||||
|
||||
/* Send the packet */
|
||||
ret = net_context_send(context, sample_packet, packet_size,
|
||||
NULL, K_NO_WAIT, NULL);
|
||||
ret = send(sock, sample_packet, packet_size, 0);
|
||||
if (ret < 0) {
|
||||
shell_fprintf(shell, SHELL_WARNING,
|
||||
"Failed to send the packet (%d)\n",
|
||||
ret);
|
||||
errno);
|
||||
break;
|
||||
} else {
|
||||
nb_packets++;
|
||||
|
|
@ -296,7 +276,7 @@ void zperf_udp_upload(const struct shell *shell,
|
|||
|
||||
end_time = k_uptime_ticks();
|
||||
|
||||
zperf_upload_fin(shell, context, nb_packets, end_time, packet_size,
|
||||
zperf_upload_fin(shell, sock, nb_packets, end_time, packet_size,
|
||||
results);
|
||||
|
||||
/* Add result coming from the client */
|
||||
|
|
|
|||
Loading…
Reference in a new issue