MCUXpresso_MIMXRT1021xxxxx/middleware/wifi_nxp/nw_utils/iperf.c
Yilin Sun 763d32be90
Updated SDK to v2.15.000
Signed-off-by: Yilin Sun <imi415@imi.moe>
2024-03-15 22:23:36 +08:00

954 lines
27 KiB
C

/** @file iperf.c
*
* @brief This file provides the support for network utility iperf
*
* Copyright 2008-2022 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
/* iperf.c: This file contains the support for network utility iperf */
#include <string.h>
#include <wm_os.h>
#include <wm_net.h>
#include <cli.h>
#include <cli_utils.h>
#include <wlan.h>
#include "iperf.h"
#include "lwiperf.h"
#include "lwip/tcpip.h"
#ifndef IPERF_UDP_CLIENT_RATE
#define IPERF_UDP_CLIENT_RATE (1 * 1024 * 1024) /* 1 Mbit/s */
#endif
#ifndef IPERF_CLIENT_AMOUNT
#define IPERF_CLIENT_AMOUNT (-1000) /* 10 seconds */
#endif
#define IPERF_UDP_DEFAULT_FACTOR 100
struct iperf_test_context
{
bool server_mode;
bool tcp;
enum lwiperf_client_type client_type;
void *iperf_session;
};
static struct iperf_test_context ctx;
static os_timer_t ptimer = NULL;
static ip_addr_t server_address;
static ip_addr_t bind_address;
static bool multicast;
#ifdef CONFIG_IPV6
static bool ipv6;
#endif
static int amount = IPERF_CLIENT_AMOUNT;
static unsigned int udp_rate_factor = IPERF_UDP_DEFAULT_FACTOR;
unsigned int buffer_len = 0;
unsigned int port = LWIPERF_TCP_PORT_DEFAULT;
#ifdef CONFIG_WMM
uint8_t qos = 0;
#endif
static uint8_t mcast_mac[6];
static bool mcast_mac_valid;
static void timer_poll_udp_client(TimerHandle_t timer);
#if defined(CONFIG_WIFI_BLE_COEX_APP) && (CONFIG_WIFI_BLE_COEX_APP == 1)
#ifdef CONFIG_HOST_SLEEP
#endif
#endif
/* Report state => string */
const char *report_type_str[] = {
"TCP_DONE_SERVER (RX)", /* LWIPERF_TCP_DONE_SERVER_RX,*/
"TCP_DONE_SERVER (TX)", /* LWIPERF_TCP_DONE_SERVER_TX,*/
"TCP_DONE_CLIENT (TX)", /* LWIPERF_TCP_DONE_CLIENT_TX,*/
"TCP_DONE_CLIENT (RX)", /* LWIPERF_TCP_DONE_CLIENT_RX,*/
"TCP_ABORTED_LOCAL", /* LWIPERF_TCP_ABORTED_LOCAL, */
"TCP_ABORTED_LOCAL_DATAERROR", /* LWIPERF_TCP_ABORTED_LOCAL_DATAERROR, */
"TCP_ABORTED_LOCAL_TXERROR", /* LWIPERF_TCP_ABORTED_LOCAL_TXERROR, */
"TCP_ABORTED_REMOTE", /* LWIPERF_TCP_ABORTED_REMOTE, */
"UDP_DONE_SERVER (RX)", /* LWIPERF_UDP_DONE_SERVER_RX, */
"UDP_DONE_SERVER (TX)", /* LWIPERF_UDP_DONE_SERVER_TX, */
"UDP_DONE_CLIENT (TX)", /* LWIPERF_UDP_DONE_CLIENT_TX, */
"UDP_DONE_CLIENT (RX)", /* LWIPERF_UDP_DONE_CLIENT_RX, */
"UDP_ABORTED_LOCAL", /* LWIPERF_UDP_ABORTED_LOCAL, */
"UDP_ABORTED_LOCAL_DATAERROR", /* LWIPERF_UDP_ABORTED_LOCAL_DATAERROR, */
"UDP_ABORTED_LOCAL_TXERROR", /* LWIPERF_UDP_ABORTED_LOCAL_TXERROR, */
"UDP_ABORTED_REMOTE", /* LWIPERF_UDP_ABORTED_REMOTE, */
};
#if defined(CONFIG_WIFI_BLE_COEX_APP) && (CONFIG_WIFI_BLE_COEX_APP == 1)
#ifdef CONFIG_HOST_SLEEP
#endif
#endif
static void iperf_free_ctx_iperf_session(void *arg, enum lwiperf_report_type report_type)
{
struct iperf_test_context *ctx = (struct iperf_test_context *)arg;
if (!ctx || ctx->server_mode ||
(ctx->client_type == LWIPERF_TRADEOFF &&
(report_type == LWIPERF_TCP_DONE_CLIENT_TX || report_type == LWIPERF_UDP_DONE_CLIENT_TX)))
return;
ctx->iperf_session = NULL;
}
/** Prototype of a report function that is called when a session is finished.
This report function shows the test results. */
static void lwiperf_report(void *arg,
enum lwiperf_report_type report_type,
const ip_addr_t *local_addr,
u16_t local_port,
const ip_addr_t *remote_addr,
u16_t remote_port,
u64_t bytes_transferred,
u32_t ms_duration,
u32_t bandwidth_kbitpsec)
{
if (arg == NULL)
{
(void)PRINTF("Unable to print iperf report\r\n");
return;
}
(void)PRINTF("-------------------------------------------------\r\n");
if (report_type < (enum lwiperf_report_type)(sizeof(report_type_str) / sizeof(report_type_str[0])))
{
(void)PRINTF(" %s \r\n", report_type_str[report_type]);
if (local_addr != NULL && remote_addr != NULL)
{
#ifdef CONFIG_IPV6
if (ipv6)
{
(void)PRINTF(" Local address : %s ", inet6_ntoa(local_addr->u_addr.ip6));
}
else
#endif
{
(void)PRINTF(" Local address : %u.%u.%u.%u ", ((const u8_t *)local_addr)[0],
((const u8_t *)local_addr)[1], ((const u8_t *)local_addr)[2],
((const u8_t *)local_addr)[3]);
}
(void)PRINTF(" Port %d \r\n", local_port);
#ifdef CONFIG_IPV6
if (ipv6)
{
(void)PRINTF(" Remote address : %s ", inet6_ntoa(remote_addr->u_addr.ip6));
}
else
#endif
{
(void)PRINTF(" Remote address : %u.%u.%u.%u ", ((const u8_t *)remote_addr)[0],
((const u8_t *)remote_addr)[1], ((const u8_t *)remote_addr)[2],
((const u8_t *)remote_addr)[3]);
}
(void)PRINTF(" Port %d \r\n", remote_port);
(void)PRINTF(" Bytes Transferred %llu \r\n", bytes_transferred);
(void)PRINTF(" Duration (ms) %d \r\n", ms_duration);
(void)PRINTF(" Bandwidth (Mbitpsec) %d \r\n", bandwidth_kbitpsec / 1000U);
}
}
else
{
(void)PRINTF(" IPERF Report error\r\n");
}
struct iperf_test_context *test_ctx = (struct iperf_test_context *)arg;
if (test_ctx->server_mode == 0 && test_ctx->client_type != LWIPERF_DUAL)
{
os_timer_deactivate(&ptimer);
}
(void)PRINTF("\r\n");
iperf_free_ctx_iperf_session(arg, report_type);
#if defined(CONFIG_WIFI_BLE_COEX_APP) || (CONFIG_WIFI_BLE_COEX_APP == 1)
#ifdef CONFIG_HOST_SLEEP
#endif
#endif
}
/*!
* @brief Function to start iperf test.
*/
static void iperf_test_start(void *arg)
{
struct iperf_test_context *ctx = (struct iperf_test_context *)arg;
#ifdef CONFIG_IPV6
struct netif *netiftmp = NULL;
struct netif *netifbind = NULL;
#endif
if (ctx->iperf_session != NULL)
{
(void)PRINTF("Abort ongoing IPERF session\r\n");
lwiperf_abort(ctx->iperf_session);
ctx->iperf_session = NULL;
}
#if defined(CONFIG_WIFI_BLE_COEX_APP) && (CONFIG_WIFI_BLE_COEX_APP == 1)
#ifdef CONFIG_HOST_SLEEP
#endif
#endif
os_timer_activate(&ptimer);
if (ctx->server_mode)
{
if (ctx->tcp)
{
#ifdef CONFIG_IPV6
if (ipv6)
{
ctx->iperf_session = lwiperf_start_tcp_server(IP6_ADDR_ANY, port, lwiperf_report, ctx);
}
else
#endif
{
ctx->iperf_session = lwiperf_start_tcp_server(IP_ADDR_ANY, port, lwiperf_report, ctx);
}
}
else
{
if (multicast)
{
#ifdef CONFIG_IPV6
wifi_get_ipv4_multicast_mac(ntohl(bind_address.u_addr.ip4.addr), mcast_mac);
#else
wifi_get_ipv4_multicast_mac(ntohl(bind_address.addr), mcast_mac);
#endif
if (wifi_add_mcast_filter(mcast_mac) != WM_SUCCESS)
{
(void)PRINTF("IPERF session init failed\r\n");
lwiperf_abort(ctx->iperf_session);
ctx->iperf_session = NULL;
return;
}
mcast_mac_valid = true;
}
#ifdef CONFIG_IPV6
if (ipv6)
{
ctx->iperf_session = lwiperf_start_udp_server(IP6_ADDR_ANY, port, lwiperf_report, ctx);
}
else
#endif
{
ctx->iperf_session = lwiperf_start_udp_server(&bind_address, port, lwiperf_report, ctx);
}
}
}
else
{
if (ctx->tcp)
{
#ifdef CONFIG_IPV6
if (ipv6)
{
NETIF_FOREACH(netiftmp)
{
if ((netif_get_ip6_addr_match(netiftmp, ip_2_ip6(&bind_address)) >= 0) && netif_is_up(netiftmp))
{
netifbind = netiftmp;
break;
}
}
if (!netifbind)
{
(void)PRINTF("Could not find correspinding netif by bind_address\r\n");
lwiperf_abort(ctx->iperf_session);
ctx->iperf_session = NULL;
return;
}
ip6_addr_assign_zone(ip_2_ip6(&server_address), IP6_UNICAST, netifbind);
}
#endif
ctx->iperf_session = lwiperf_start_tcp_client(&server_address, port, ctx->client_type, amount, buffer_len,
#ifdef CONFIG_WMM
qos,
#else
0,
#endif
lwiperf_report, ctx);
}
else
{
if (IP_IS_V4(&server_address) && ip_addr_ismulticast(&server_address))
{
#ifdef CONFIG_IPV6
wifi_get_ipv4_multicast_mac(ntohl(server_address.u_addr.ip4.addr), mcast_mac);
#else
wifi_get_ipv4_multicast_mac(ntohl(server_address.addr), mcast_mac);
#endif
(void)wifi_add_mcast_filter(mcast_mac);
mcast_mac_valid = true;
}
#ifdef CONFIG_IPV6
if (ipv6)
{
ctx->iperf_session =
lwiperf_start_udp_client(&bind_address, port, &server_address, port, ctx->client_type, amount,
buffer_len, IPERF_UDP_CLIENT_RATE * udp_rate_factor,
#ifdef CONFIG_WMM
qos,
#else
0,
#endif
lwiperf_report, ctx);
}
else
{
#endif
ctx->iperf_session =
lwiperf_start_udp_client(&bind_address, port, &server_address, port, ctx->client_type, amount,
buffer_len, IPERF_UDP_CLIENT_RATE * udp_rate_factor,
#ifdef CONFIG_WMM
qos,
#else
0,
#endif
lwiperf_report, ctx);
#ifdef CONFIG_IPV6
}
#endif
}
}
if (ctx->iperf_session == NULL)
{
(void)PRINTF("IPERF initialization failed!\r\n");
}
else
{
(void)PRINTF("IPERF initialization successful\r\n");
}
}
/*!
* @brief Function to abort iperf test.
*/
static void iperf_test_abort(void *arg)
{
struct iperf_test_context *test_ctx = (struct iperf_test_context *)arg;
if (test_ctx->iperf_session != NULL)
{
lwiperf_abort(test_ctx->iperf_session);
test_ctx->iperf_session = NULL;
}
(void)PRINTF("IPERF ABORT DONE\r\n");
(void)memset(&ctx, 0, sizeof(struct iperf_test_context));
os_timer_deactivate(&ptimer);
}
/*!
* @brief Invokes UDP polling, to be run on tcpip_thread.
*/
static void poll_udp_client(void *arg)
{
LWIP_UNUSED_ARG(arg);
lwiperf_poll_udp_client();
}
/*!
* @brief Invokes UDP polling on tcpip_thread.
*/
static void timer_poll_udp_client(TimerHandle_t timer)
{
LWIP_UNUSED_ARG(timer);
(void)tcpip_try_callback(poll_udp_client, NULL);
}
static void TESTAbort(void)
{
(void)tcpip_callback(iperf_test_abort, (void *)&ctx);
}
static void TCPServer(void)
{
ctx.server_mode = true;
ctx.tcp = true;
ctx.client_type = LWIPERF_CLIENT;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void TCPClient(void)
{
ctx.server_mode = false;
ctx.tcp = true;
ctx.client_type = LWIPERF_CLIENT;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void TCPClientDual(void)
{
ctx.server_mode = false;
ctx.tcp = true;
ctx.client_type = LWIPERF_DUAL;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void TCPClientTradeOff(void)
{
ctx.server_mode = false;
ctx.tcp = true;
ctx.client_type = LWIPERF_TRADEOFF;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void TCPClientReverse(void)
{
ctx.server_mode = false;
ctx.tcp = true;
ctx.client_type = LWIPERF_REVERSE;
tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void UDPServer(void)
{
ctx.server_mode = true;
ctx.tcp = false;
ctx.client_type = LWIPERF_CLIENT;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void UDPServerDual(void)
{
ctx.server_mode = true;
ctx.tcp = false;
ctx.client_type = LWIPERF_DUAL;
(void)PRINTF("Bidirectional UDP test simultaneously as server, please add -d with external iperf client\r\n");
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void UDPClient(void)
{
ctx.server_mode = false;
ctx.tcp = false;
ctx.client_type = LWIPERF_CLIENT;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void UDPClientDual(void)
{
ctx.server_mode = false;
ctx.tcp = false;
ctx.client_type = LWIPERF_DUAL;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void UDPClientTradeOff(void)
{
ctx.server_mode = false;
ctx.tcp = false;
ctx.client_type = LWIPERF_TRADEOFF;
(void)tcpip_callback(iperf_test_start, (void *)&ctx);
}
static void UDPClientReverse(void)
{
ctx.server_mode = false;
ctx.tcp = false;
ctx.client_type = LWIPERF_REVERSE;
tcpip_callback(iperf_test_start, (void *)&ctx);
}
/* Display the usage of iperf */
static void display_iperf_usage(void)
{
(void)PRINTF("Usage:\r\n");
(void)PRINTF("\tiperf [-s|-c <host>|-a] [options]\r\n");
(void)PRINTF("\tiperf [-h]\r\n");
(void)PRINTF("\r\n");
(void)PRINTF("\tClient/Server:\r\n");
(void)PRINTF("\t -u use UDP rather than TCP\r\n");
(void)PRINTF("\t -B <host> bind to <host> (including multicast address)\r\n");
#ifdef CONFIG_IPV6
(void)PRINTF("\t -V Set the domain to IPv6 (send packets over IPv6)\r\n");
#endif
(void)PRINTF("\t -a abort ongoing iperf session\r\n");
(void)PRINTF("\t -p server port to listen on/connect to\r\n");
(void)PRINTF("\tServer specific:\r\n");
(void)PRINTF("\t -s run in server mode. Support 8 parallel traffic(-P) maximum from client side\r\n");
(void)PRINTF(
"\t -D Do a bidirectional UDP test simultaneously and with -d from external iperf client\r\n");
(void)PRINTF("\tClient specific:\r\n");
(void)PRINTF("\t -c <host> run in client mode, connecting to <host>\r\n");
(void)PRINTF("\t -d Do a bidirectional test simultaneously\r\n");
(void)PRINTF("\t -r Do a bidirectional test individually\r\n");
(void)PRINTF("\t -R reverse the test (client receives, server sends)\r\n");
(void)PRINTF("\t -t # time in seconds to transmit for (default 10 secs)\r\n");
(void)PRINTF(
"\t -b # for UDP, bandwidth to send at in Mbps, default 100Mbps without the parameter\r\n");
#ifdef CONFIG_WMM
(void)PRINTF("\t -S # QoS for udp traffic (default 0(Best Effort))\r\n");
#endif
(void)PRINTF(
"\t -l length of buffer in bytes to write (Defaults: v4 TCP=1460, v6 TCP=1440, v4 UDP=1470, v6 UDP=1450)\r\n \
\t Note: Limit length is smaller than default size.\r\n");
}
static void cmd_iperf(int argc, char **argv)
{
int arg = 1;
char ip_addr[128] = {0};
char ip_addr_bind[128] = {0};
struct
{
unsigned help : 1;
unsigned udp : 1;
unsigned bind : 1;
unsigned bhost : 1;
unsigned abort : 1;
unsigned server : 1;
unsigned client : 1;
unsigned chost : 1;
unsigned dual : 1;
unsigned tradeoff : 1;
unsigned reverse : 1;
unsigned time : 1;
#ifdef CONFIG_WMM
unsigned tos : 1;
#endif
unsigned dserver : 1;
#ifdef CONFIG_IPV6
unsigned ipv6 : 1;
#endif
unsigned buflen : 1;
unsigned port : 1;
} info;
amount = IPERF_CLIENT_AMOUNT;
udp_rate_factor = IPERF_UDP_DEFAULT_FACTOR;
#ifdef CONFIG_WMM
qos = 0;
#endif
multicast = false;
#ifdef CONFIG_IPV6
ipv6 = false;
#endif
buffer_len = 0;
port = LWIPERF_TCP_PORT_DEFAULT;
if (mcast_mac_valid)
{
(void)wifi_remove_mcast_filter(mcast_mac);
mcast_mac_valid = false;
}
(void)memset(&info, 0, sizeof(info));
(void)memset(ip_addr, 0, sizeof(ip_addr));
(void)memset(ip_addr_bind, 0, sizeof(ip_addr_bind));
if (argc < 2)
{
(void)PRINTF("Incorrect usage\r\n");
display_iperf_usage();
return;
}
do
{
if ((info.help == 0U) && string_equal("-h", argv[arg]))
{
display_iperf_usage();
return;
}
else if ((info.udp == 0U) && string_equal("-u", argv[arg]))
{
arg += 1;
info.udp = 1;
}
else if ((info.abort == 0U) && string_equal("-a", argv[arg]))
{
arg += 1;
info.abort = 1;
}
else if ((info.server == 0U) && string_equal("-s", argv[arg]))
{
arg += 1;
info.server = 1;
}
else if ((info.client == 0U) && string_equal("-c", argv[arg]))
{
arg += 1;
info.client = 1;
if ((info.chost == 0U) && argv[arg] != NULL)
{
if (strlen(argv[arg]) < sizeof(ip_addr))
{
(void)strncpy(ip_addr, argv[arg], strlen(argv[arg]));
arg += 1;
info.chost = 1;
}
}
else
{
PRINTF("Invalid ip addr, length exceeded max ip_addr bytes\r\n");
return;
}
}
else if ((info.bind == 0U) && string_equal("-B", argv[arg]))
{
arg += 1;
info.bind = 1;
if (!info.bhost && argv[arg] != NULL)
{
if (strlen(argv[arg]) < sizeof(ip_addr_bind))
{
strncpy(ip_addr_bind, argv[arg], strlen(argv[arg]));
arg += 1;
}
else
{
PRINTF("Invalid bind ip addr, length exceeded max ip_addr bytes\r\n");
return;
}
}
}
else if ((info.time == 0U) && string_equal("-t", argv[arg]))
{
arg += 1;
info.time = 1;
errno = 0;
amount = -(100 * strtol(argv[arg], NULL, 10));
if (errno != 0)
{
(void)PRINTF("Invalid time, error during strtoul errno:%d", errno);
return;
}
arg += 1;
}
#ifdef CONFIG_WMM
else if (!info.tos && string_equal("-S", argv[arg]))
{
arg += 1;
info.tos = 1;
errno = 0;
qos = strtoul(argv[arg], NULL, 10);
if (errno != 0)
{
(void)PRINTF("Invalid Qos, error during strtoul errno:%d", errno);
return;
}
arg += 1;
}
#endif
#ifdef CONFIG_IPV6
else if ((info.ipv6 == 0U) && string_equal("-V", argv[arg]))
{
arg += 1;
info.ipv6 = 1;
ipv6 = true;
}
#endif
else if ((info.dual == 0U) && string_equal("-d", argv[arg]))
{
arg += 1;
info.dual = 1;
}
else if ((info.tradeoff == 0U) && string_equal("-r", argv[arg]))
{
arg += 1;
info.tradeoff = 1;
}
else if (!info.reverse && string_equal("-R", argv[arg]))
{
arg += 1;
info.reverse = 1;
}
else if (string_equal("-b", argv[arg]))
{
if (arg + 1 >= argc || (get_uint(argv[arg + 1], &udp_rate_factor, strlen(argv[arg + 1])) != 0))
{
(void)PRINTF(
"Error: invalid bandwidth"
" argument\n");
return;
}
arg += 2;
}
else if (string_equal("-D", argv[arg]))
{
arg += 1;
info.dserver = 1;
}
else if (string_equal("-l", argv[arg]))
{
if (arg + 1 >= argc || get_uint(argv[arg + 1], &buffer_len, strlen(argv[arg + 1])))
{
(void)PRINTF("Error: invalid length argument\r\n");
return;
}
if (buffer_len == 0)
{
(void)PRINTF("Error: invalid length argument\r\n");
return;
}
arg += 2;
info.buflen = 1;
}
else if (string_equal("-p", argv[arg]))
{
if (arg + 1 >= argc || get_uint(argv[arg + 1], &port, strlen(argv[arg + 1])))
{
(void)PRINTF("Error: invalid port argument\r\n");
return;
}
if (port == 0)
{
(void)PRINTF("Error: invalid port argument\r\n");
return;
}
arg += 2;
info.port = 1;
}
else
{
(void)PRINTF("Incorrect usage\r\n");
display_iperf_usage();
(void)PRINTF("Error: argument %d is invalid\r\n", arg);
return;
}
} while (arg < argc);
#ifdef CONFIG_IPV6
if (ipv6)
{
(void)inet6_aton(ip_addr, ip_2_ip6(&server_address));
server_address.type = IPADDR_TYPE_V6;
}
else
{
#endif
(void)inet_aton(ip_addr, ip_2_ip4(&server_address));
#ifdef CONFIG_IPV6
server_address.type = IPADDR_TYPE_V4;
}
#endif
if (info.bind)
{
#ifdef CONFIG_IPV6
if (ipv6)
{
inet6_aton(ip_addr_bind, ip_2_ip6(&bind_address));
bind_address.type = IPADDR_TYPE_V6;
if (IP_IS_V6(&bind_address) != 0)
info.bhost = 1;
}
else
{
#endif
inet_aton(ip_addr_bind, ip_2_ip4(&bind_address));
#ifdef CONFIG_IPV6
bind_address.type = IPADDR_TYPE_V4;
#endif
if (IP_IS_V4(&bind_address) != 0)
info.bhost = 1;
#ifdef CONFIG_IPV6
}
#endif
if (ip_addr_ismulticast(&bind_address))
multicast = true;
}
if (((info.abort == 0U) && (info.server == 0U) && (info.client == 0U)) ||
((info.client != 0U) && (info.chost == 0U)) || ((info.server != 0U) && (info.client != 0U)) ||
((info.udp != 0U)
#ifdef CONFIG_IPV6
&& (info.ipv6 == 0U)
#endif
&& ((info.bind == 0U) || (info.bhost == 0U))) ||
(((info.dual != 0U) || (info.tradeoff != 0U)
|| (info.reverse != 0U)
) &&
(info.client == 0U)) ||
((info.dual != 0U) && (info.tradeoff != 0U)) ||
((info.dual != 0U) && (info.reverse != 0U)) || ((info.tradeoff != 0U) && (info.reverse != 0U)) ||
((info.dserver != 0U) && (info.server == 0U || info.udp == 0U))
#ifdef CONFIG_IPV6
|| ((info.ipv6 != 0U) && (info.client != 0U) && ((info.bind == 0U) || (info.bhost == 0U)))
#endif
)
{
(void)PRINTF("Incorrect usage\r\n");
#ifdef CONFIG_IPV6
if ((info.ipv6 != 0U) && (info.client != 0U) && ((info.bind == 0U) || (info.bhost == 0U)))
{
(void)PRINTF("IPv6: For client please specify local interface ip address using -B option\r\n");
}
else if ((info.ipv6 != 0U) && (IP_IS_V4(&server_address)))
{
(void)PRINTF("IPv6: Address family for host not supported\r\n");
}
else
#endif
{
if ((info.udp != 0U)
#ifdef CONFIG_IPV6
&& (info.ipv6 == 0U)
#endif
&& ((info.bind == 0U) || (info.bhost == 0U)))
{
(void)PRINTF("For UDP tests please specify local interface ip address using -B option\r\n");
}
}
display_iperf_usage();
return;
}
if (info.abort != 0U)
{
TESTAbort();
}
else if (info.server != 0U)
{
if (info.udp != 0U)
{
if (info.dserver != 0U)
{
UDPServerDual();
}
else
{
UDPServer();
}
}
else
{
TCPServer();
}
}
else if (info.client != 0U)
{
if (info.udp != 0U)
{
if (info.dual != 0U)
{
UDPClientDual();
}
else if (info.tradeoff != 0U)
{
UDPClientTradeOff();
}
else if (info.reverse != 0U)
{
UDPClientReverse();
}
else
{
UDPClient();
}
}
else
{
if (info.dual != 0U)
{
TCPClientDual();
}
else if (info.tradeoff != 0U)
{
TCPClientTradeOff();
}
else if (info.reverse != 0U)
{
TCPClientReverse();
}
else
{
TCPClient();
}
}
}
else
{ /* Do Nothing */
}
}
static struct cli_command iperf[] = {
{"iperf", "[-s|-c <host>|-a|-h] [options]", cmd_iperf},
};
int iperf_cli_init(void)
{
u8_t i;
int rv = WM_SUCCESS;
for (i = 0; i < sizeof(iperf) / sizeof(struct cli_command); i++)
{
if (cli_register_command(&iperf[i]) != 0)
{
return -WM_FAIL;
}
}
if (ctx.iperf_session != NULL)
{
lwiperf_abort(ctx.iperf_session);
}
(void)memset(&ctx, 0, sizeof(struct iperf_test_context));
if (ptimer == NULL)
rv = os_timer_create(&ptimer, "UDP Poll Timer", 1U / portTICK_PERIOD_MS, timer_poll_udp_client, (void *)0,
OS_TIMER_PERIODIC, OS_TIMER_NO_ACTIVATE);
if (rv != WM_SUCCESS)
{
(void)PRINTF("Unable to create iperf timer rv(%d)\r\n", rv);
while (true)
{
;
}
}
return WM_SUCCESS;
}
int iperf_cli_deinit(void)
{
u8_t i;
if (ctx.iperf_session != NULL)
{
(void)PRINTF("Abort ongoing IPERF session\r\n");
lwiperf_abort(ctx.iperf_session);
ctx.iperf_session = NULL;
}
for (i = 0; i < sizeof(iperf) / sizeof(struct cli_command); i++)
{
if (cli_unregister_command(&iperf[i]) != 0)
{
return -WM_FAIL;
}
}
return WM_SUCCESS;
}