net: zperf: Add shell option for asynchronous upload

Add shell option to the UDP/TCP upload command, which allows to execute
the upload asynchronously. This allows to unblock the shell for other
commands during the upload.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2022-11-25 15:43:01 +01:00 committed by Carles Cufí
commit 722ed07287

View file

@ -452,9 +452,51 @@ static void shell_tcp_upload_print_stats(const struct shell *sh,
} }
} }
static void udp_upload_cb(enum zperf_status status,
struct zperf_results *result,
void *user_data)
{
const struct shell *sh = user_data;
switch (status) {
case ZPERF_SESSION_STARTED:
break;
case ZPERF_SESSION_FINISHED: {
shell_udp_upload_print_stats(sh, result);
break;
}
case ZPERF_SESSION_ERROR:
shell_fprintf(sh, SHELL_ERROR, "UDP upload failed\n");
break;
}
}
static void tcp_upload_cb(enum zperf_status status,
struct zperf_results *result,
void *user_data)
{
const struct shell *sh = user_data;
switch (status) {
case ZPERF_SESSION_STARTED:
break;
case ZPERF_SESSION_FINISHED: {
shell_tcp_upload_print_stats(sh, result);
break;
}
case ZPERF_SESSION_ERROR:
shell_fprintf(sh, SHELL_ERROR, "TCP upload failed\n");
break;
}
}
static int execute_upload(const struct shell *sh, static int execute_upload(const struct shell *sh,
const struct zperf_upload_params *param, const struct zperf_upload_params *param,
bool is_udp) bool is_udp, bool async)
{ {
struct zperf_results results = { 0 }; struct zperf_results results = { 0 };
int ret; int ret;
@ -498,14 +540,24 @@ static int execute_upload(const struct shell *sh,
(unsigned int)packet_duration); (unsigned int)packet_duration);
} }
ret = zperf_udp_upload(param, &results); if (async) {
if (ret < 0) { ret = zperf_udp_upload_async(param, udp_upload_cb,
shell_fprintf(sh, SHELL_ERROR, (void *)sh);
"UDP upload failed (%d)\n", ret); if (ret < 0) {
return ret; shell_fprintf(sh, SHELL_ERROR,
} "Failed to start UDP async upload (%d)\n", ret);
return ret;
}
} else {
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); shell_udp_upload_print_stats(sh, &results);
}
} else { } else {
if (!IS_ENABLED(CONFIG_NET_UDP)) { if (!IS_ENABLED(CONFIG_NET_UDP)) {
shell_fprintf(sh, SHELL_INFO, shell_fprintf(sh, SHELL_INFO,
@ -514,14 +566,24 @@ static int execute_upload(const struct shell *sh,
} }
if (!is_udp && IS_ENABLED(CONFIG_NET_TCP)) { if (!is_udp && IS_ENABLED(CONFIG_NET_TCP)) {
ret = zperf_tcp_upload(param, &results); if (async) {
if (ret < 0) { ret = zperf_tcp_upload_async(param, tcp_upload_cb,
shell_fprintf(sh, SHELL_ERROR, (void *)sh);
"TCP upload failed (%d)\n", ret); if (ret < 0) {
return ret; shell_fprintf(sh, SHELL_ERROR,
} "Failed to start TCP async upload (%d)\n", ret);
return ret;
}
} else {
ret = zperf_tcp_upload(param, &results);
if (ret < 0) {
shell_fprintf(sh, SHELL_ERROR,
"TCP upload failed (%d)\n", ret);
return ret;
}
shell_tcp_upload_print_stats(sh, &results); shell_tcp_upload_print_stats(sh, &results);
}
} else { } else {
if (!IS_ENABLED(CONFIG_NET_TCP)) { if (!IS_ENABLED(CONFIG_NET_TCP)) {
shell_fprintf(sh, SHELL_INFO, shell_fprintf(sh, SHELL_INFO,
@ -568,6 +630,7 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
struct sockaddr_in6 ipv6 = { .sin6_family = AF_INET6 }; struct sockaddr_in6 ipv6 = { .sin6_family = AF_INET6 };
struct sockaddr_in ipv4 = { .sin_family = AF_INET }; struct sockaddr_in ipv4 = { .sin_family = AF_INET };
char *port_str; char *port_str;
bool async = false;
bool is_udp; bool is_udp;
int start = 0; int start = 0;
size_t opt_cnt = 0; size_t opt_cnt = 0;
@ -591,15 +654,19 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
} }
param.options.tos = tos; param.options.tos = tos;
opt_cnt += 2;
break; break;
case 'a':
async = true;
opt_cnt += 1;
break;
default: default:
shell_fprintf(sh, SHELL_WARNING, shell_fprintf(sh, SHELL_WARNING,
"Unrecognized argument: %s\n", argv[i]); "Unrecognized argument: %s\n", argv[i]);
return -ENOEXEC; return -ENOEXEC;
} }
opt_cnt += 2;
} }
start += opt_cnt; start += opt_cnt;
@ -707,7 +774,7 @@ static int shell_cmd_upload(const struct shell *sh, size_t argc,
param.rate_kbps = 10U; param.rate_kbps = 10U;
} }
return execute_upload(sh, &param, is_udp); return execute_upload(sh, &param, is_udp, async);
} }
static int cmd_tcp_upload(const struct shell *sh, size_t argc, char *argv[]) static int cmd_tcp_upload(const struct shell *sh, size_t argc, char *argv[])
@ -730,6 +797,7 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc,
struct zperf_upload_params param = { 0 }; struct zperf_upload_params param = { 0 };
sa_family_t family; sa_family_t family;
uint8_t is_udp; uint8_t is_udp;
bool async = false;
int start = 0; int start = 0;
size_t opt_cnt = 0; size_t opt_cnt = 0;
@ -752,15 +820,19 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc,
} }
param.options.tos = tos; param.options.tos = tos;
opt_cnt += 2;
break; break;
case 'a':
async = true;
opt_cnt += 1;
break;
default: default:
shell_fprintf(sh, SHELL_WARNING, shell_fprintf(sh, SHELL_WARNING,
"Unrecognized argument: %s\n", argv[i]); "Unrecognized argument: %s\n", argv[i]);
return -ENOEXEC; return -ENOEXEC;
} }
opt_cnt += 2;
} }
start += opt_cnt; start += opt_cnt;
@ -833,7 +905,7 @@ static int shell_cmd_upload2(const struct shell *sh, size_t argc,
param.rate_kbps = 10U; param.rate_kbps = 10U;
} }
return execute_upload(sh, &param, is_udp); return execute_upload(sh, &param, is_udp, async);
} }
static int cmd_tcp_upload2(const struct shell *sh, size_t argc, static int cmd_tcp_upload2(const struct shell *sh, size_t argc,
@ -1008,22 +1080,28 @@ static void zperf_init(const struct shell *sh)
SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_tcp, SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_tcp,
SHELL_CMD(upload, NULL, SHELL_CMD(upload, NULL,
"[<options>] <dest ip> <dest port> <duration> <packet size>[K]\n" "[<options>] <dest ip> <dest port> <duration> <packet size>[K]\n"
"<options> command options (optional): [-S tos]\n" "<options> command options (optional): [-S tos -a]\n"
"<dest ip> IP destination\n" "<dest ip> IP destination\n"
"<dest port> port destination\n" "<dest port> port destination\n"
"<duration> of the test in seconds\n" "<duration> of the test in seconds\n"
"<packet size> Size of the packet in byte or kilobyte " "<packet size> Size of the packet in byte or kilobyte "
"(with suffix K)\n" "(with suffix K)\n"
"Available options:\n"
"-S tos: Specify IPv4/6 type of service\n"
"-a: Asynchronous call (shell will not block for the upload)\n"
"Example: tcp upload 192.0.2.2 1111 1 1K\n" "Example: tcp upload 192.0.2.2 1111 1 1K\n"
"Example: tcp upload 2001:db8::2\n", "Example: tcp upload 2001:db8::2\n",
cmd_tcp_upload), cmd_tcp_upload),
SHELL_CMD(upload2, NULL, SHELL_CMD(upload2, NULL,
"[<options>] v6|v4 <duration> <packet size>[K] <baud rate>[K|M]\n" "[<options>] v6|v4 <duration> <packet size>[K] <baud rate>[K|M]\n"
"<options> command options (optional): [-S tos]\n" "<options> command options (optional): [-S tos -a]\n"
"<v6|v4>: Use either IPv6 or IPv4\n" "<v6|v4>: Use either IPv6 or IPv4\n"
"<duration> Duration of the test in seconds\n" "<duration> Duration of the test in seconds\n"
"<packet size> Size of the packet in byte or kilobyte " "<packet size> Size of the packet in byte or kilobyte "
"(with suffix K)\n" "(with suffix K)\n"
"Available options:\n"
"-S tos: Specify IPv4/6 type of service\n"
"-a: Asynchronous call (shell will not block for the upload)\n"
"Example: tcp upload2 v6 1 1K\n" "Example: tcp upload2 v6 1 1K\n"
"Example: tcp upload2 v4\n" "Example: tcp upload2 v4\n"
#if defined(CONFIG_NET_IPV6) && defined(MY_IP6ADDR_SET) #if defined(CONFIG_NET_IPV6) && defined(MY_IP6ADDR_SET)
@ -1047,24 +1125,30 @@ SHELL_STATIC_SUBCMD_SET_CREATE(zperf_cmd_udp,
SHELL_CMD(upload, NULL, SHELL_CMD(upload, NULL,
"[<options>] <dest ip> [<dest port> <duration> <packet size>[K] " "[<options>] <dest ip> [<dest port> <duration> <packet size>[K] "
"<baud rate>[K|M]]\n" "<baud rate>[K|M]]\n"
"<options> command options (optional): [-S tos]\n" "<options> command options (optional): [-S tos -a]\n"
"<dest ip> IP destination\n" "<dest ip> IP destination\n"
"<dest port> port destination\n" "<dest port> port destination\n"
"<duration> of the test in seconds\n" "<duration> of the test in seconds\n"
"<packet size> Size of the packet in byte or kilobyte " "<packet size> Size of the packet in byte or kilobyte "
"(with suffix K)\n" "(with suffix K)\n"
"<baud rate> Baudrate in kilobyte or megabyte\n" "<baud rate> Baudrate in kilobyte or megabyte\n"
"Available options:\n"
"-S tos: Specify IPv4/6 type of service\n"
"-a: Asynchronous call (shell will not block for the upload)\n"
"Example: udp upload 192.0.2.2 1111 1 1K 1M\n" "Example: udp upload 192.0.2.2 1111 1 1K 1M\n"
"Example: udp upload 2001:db8::2\n", "Example: udp upload 2001:db8::2\n",
cmd_udp_upload), cmd_udp_upload),
SHELL_CMD(upload2, NULL, SHELL_CMD(upload2, NULL,
"[<options>] v6|v4 [<duration> <packet size>[K] <baud rate>[K|M]]\n" "[<options>] v6|v4 [<duration> <packet size>[K] <baud rate>[K|M]]\n"
"<options> command options (optional): [-S tos]\n" "<options> command options (optional): [-S tos -a]\n"
"<v6|v4>: Use either IPv6 or IPv4\n" "<v6|v4>: Use either IPv6 or IPv4\n"
"<duration> Duration of the test in seconds\n" "<duration> Duration of the test in seconds\n"
"<packet size> Size of the packet in byte or kilobyte " "<packet size> Size of the packet in byte or kilobyte "
"(with suffix K)\n" "(with suffix K)\n"
"<baud rate> Baudrate in kilobyte or megabyte\n" "<baud rate> Baudrate in kilobyte or megabyte\n"
"Available options:\n"
"-S tos: Specify IPv4/6 type of service\n"
"-a: Asynchronous call (shell will not block for the upload)\n"
"Example: udp upload2 v4 1 1K 1M\n" "Example: udp upload2 v4 1 1K 1M\n"
"Example: udp upload2 v6\n" "Example: udp upload2 v6\n"
#if defined(CONFIG_NET_IPV6) && defined(MY_IP6ADDR_SET) #if defined(CONFIG_NET_IPV6) && defined(MY_IP6ADDR_SET)