netutils/iperf: Add iperf example.

system/argtable3: Add an ANSI C library for command-line parsing.
This commit is contained in:
chenwen 2020-12-04 16:16:12 +08:00 committed by Xiang Xiao
parent bfa826d30d
commit 756dc32fd0
11 changed files with 1333 additions and 0 deletions

37
netutils/iperf/Kconfig Normal file
View File

@ -0,0 +1,37 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config EXAMPLES_IPERF
bool "iperf example"
default n
depends on NET
select NETUTILS_NETLIB
select LIBC_FLOATINGPOINT
select SYSTEM_ARGTABLE3
---help---
Enable the \"iperf example\"
if EXAMPLES_IPERF
config EXAMPLES_IPERF_PROGNAME
string "Program name"
default "iperf"
---help---
This is the name of the program that will be used when the NSH ELF
program is installed.
config EXAMPLES_IPERF_PRIORITY
int "iperf task priority"
default 100
config EXAMPLES_IPERF_STACKSIZE
int "iperf stack size"
default DEFAULT_TASK_STACKSIZE
config EXAMPLES_IPERFTEST_DEVNAME
string "Wi-Fi Network device"
default "wlan0"
endif

24
netutils/iperf/Make.defs Normal file
View File

@ -0,0 +1,24 @@
############################################################################
# apps/netutils/iperf/Make.defs
# Adds selected applications to apps/ build
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
ifneq ($(CONFIG_EXAMPLES_IPERF),)
CONFIGURED_APPS += $(APPDIR)/netutils/iperf
endif

35
netutils/iperf/Makefile Normal file
View File

@ -0,0 +1,35 @@
############################################################################
# apps/netutils/iperf/Makefile
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
include $(APPDIR)/Make.defs
# iperf example! built-in application info
PROGNAME = $(CONFIG_EXAMPLES_IPERF_PROGNAME)
PRIORITY = $(CONFIG_EXAMPLES_IPERF_PRIORITY)
STACKSIZE = $(CONFIG_EXAMPLES_IPERF_STACKSIZE)
MODULE = $(CONFIG_EXAMPLES_IPERF)
# Iperf Example
CSRCS += iperf.c
MAINSRC = iperf_main.c
include $(APPDIR)/Application.mk

87
netutils/iperf/README.md Normal file
View File

@ -0,0 +1,87 @@
Configuring NuttX to use your Wireless Router (aka Access Point)
================================================================
Since you are already in the root of NuttX/ repository, execute
make menuconfig to define your Wireless Router and your password:
$ make menuconfig
Browser the menus this way:
Application Configuration --->
Network Utilities --->
Networking Configuration --->
WAPI Configuration --->
(myApSSID) SSID
(mySSIDpassphrase) Passprhase
Replace the SSID from myApSSID with your wireless router name and
the Passprhase with your WiFi password.
Exit and save your configuration.
iperf Test Example
===================================
To set up, do `make menuconfig` and select the Apps > netutils > iperf example. By default, NuttX will the be the client
which sends data; and the host computer (Linux, macOS, or Windows) will be the server.
Set up networking so the NuttX computer can ping the host, and the host can ping NuttX. Now you are ready to run the
test.
If you are using a wireless network card, you must first connect to the router:
On host:
$ iperf -s -p 5471 -i 1 -w 416K
------------------------------------------------------------
Server listening on TCP port 5471
TCP window size: 416 KByte
------------------------------------------------------------
On NuttX:
nsh> iperf -c 192.168.1.181 -p 5471 -i 1 -t 10
mode=tcp-client sip=192.168.1.198:5001, dip=192.168.1.181:5471, interval=1, time=10
Interval Bandwidth
0- 1 sec, 0.39 Mbits/sec
1- 2 sec, 0.26 Mbits/sec
2- 3 sec, 0.39 Mbits/sec
3- 4 sec, 0.26 Mbits/sec
4- 5 sec, 0.26 Mbits/sec
5- 6 sec, 0.26 Mbits/sec
6- 7 sec, 0.26 Mbits/sec
7- 8 sec, 0.26 Mbits/sec
8- 9 sec, 0.26 Mbits/sec
9- 10 sec, 0.26 Mbits/sec
0- 10 sec, 0.28 Mbits/sec
Now on the host you should see something like:
$ iperf -s -p 5471 -i 1 -w 416K
------------------------------------------------------------
Server listening on TCP port 5471
TCP window size: 416 KByte
------------------------------------------------------------
[ 5] local 192.168.1.181 port 5471 connected with 192.168.1.198 port 4210
[ 5] 0.0- 1.0 sec 60.8 KBytes 498 Kbits/sec
[ 5] 1.0- 2.0 sec 34.9 KBytes 286 Kbits/sec
[ 5] 2.0- 3.0 sec 33.7 KBytes 276 Kbits/sec
[ 5] 3.0- 4.0 sec 33.4 KBytes 274 Kbits/sec
[ 5] 4.0- 5.0 sec 32.0 KBytes 262 Kbits/sec
[ 5] 5.0- 6.0 sec 32.0 KBytes 262 Kbits/sec
[ 5] 6.0- 7.0 sec 33.4 KBytes 274 Kbits/sec
[ 5] 7.0- 8.0 sec 32.0 KBytes 262 Kbits/sec
[ 5] 8.0- 9.0 sec 32.0 KBytes 262 Kbits/sec
[ 5] 9.0-10.0 sec 33.4 KBytes 274 Kbits/sec
[ 5] 0.0-10.3 sec 368 KBytes 292 Kbits/sec
This will tell you the link speed in Kbits/sec kilobits per second. If you want kilobytes, divide by 8.

722
netutils/iperf/iperf.c Normal file
View File

@ -0,0 +1,722 @@
/****************************************************************************
* apps/netutils/iperf/iperf.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <sys/socket.h>
#include <sys/time.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include "iperf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define IPERF_TRAFFIC_TASK_NAME "iperf_traffic"
#define IPERF_TRAFFIC_TASK_PRIORITY 100
#define IPERF_TRAFFIC_TASK_STACK 4096
#define IPERF_REPORT_TASK_NAME "iperf_report"
#define IPERF_REPORT_TASK_PRIORITY 100
#define IPERF_REPORT_TASK_STACK 4096
#define IPERF_REPORT_TASK_NAME "iperf_report"
#define IPERF_UDP_TX_LEN (1472)
#define IPERF_UDP_RX_LEN (16 << 10)
#define IPERF_TCP_TX_LEN (16 << 10)
#define IPERF_TCP_RX_LEN (16 << 10)
#define IPERF_MAX_DELAY 64
#define IPERF_SOCKET_RX_TIMEOUT 10
/****************************************************************************
* Private Types
****************************************************************************/
struct iperf_ctrl_t
{
struct iperf_cfg_t cfg;
bool finish;
uint32_t total_len;
uint32_t buffer_len;
uint8_t *buffer;
uint32_t sockfd;
};
struct iperf_udp_pkt_t
{
int32_t id;
uint32_t sec;
uint32_t usec;
};
/****************************************************************************
* Private Data
****************************************************************************/
static bool s_iperf_is_running = false;
static struct iperf_ctrl_t s_iperf_ctrl;
/****************************************************************************
* Private Functions Prototypes
****************************************************************************/
inline static bool iperf_is_udp_client(void);
inline static bool iperf_is_udp_server(void);
inline static bool iperf_is_tcp_client(void);
inline static bool iperf_is_tcp_server(void);
static int iperf_get_socket_error_code(int sockfd);
static int iperf_show_socket_error_reason(const char *str, int sockfd);
static void iperf_report_task(void *arg);
static int iperf_start_report(void);
static int iperf_run_tcp_server(void);
static int iperf_run_udp_server(void);
static int iperf_run_udp_client(void);
static int iperf_run_tcp_client(void);
static void iperf_task_traffic(void *arg);
static uint32_t iperf_get_buffer_len(void);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: iperf_is_udp_client
*
* Description:
* Check if it is a udp client
*
****************************************************************************/
inline static bool iperf_is_udp_client(void)
{
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
}
/****************************************************************************
* Name: iperf_is_udp_server
*
* Description:
* Check if it is a udp server
*
****************************************************************************/
inline static bool iperf_is_udp_server(void)
{
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_UDP));
}
/****************************************************************************
* Name: iperf_is_tcp_client
*
* Description:
* Check if it is a tcp client
*
****************************************************************************/
inline static bool iperf_is_tcp_client(void)
{
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_CLIENT)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
}
/****************************************************************************
* Name: iperf_is_tcp_server
*
* Description:
* Check if it is a tcp server
*
****************************************************************************/
inline static bool iperf_is_tcp_server(void)
{
return ((s_iperf_ctrl.cfg.flag & IPERF_FLAG_SERVER)
&& (s_iperf_ctrl.cfg.flag & IPERF_FLAG_TCP));
}
/****************************************************************************
* Name: iperf_get_socket_error_code
*
* Description:
* Get reason of socket error.
*
****************************************************************************/
static int iperf_get_socket_error_code(int sockfd)
{
return errno;
}
/****************************************************************************
* Name: iperf_show_socket_error_reason
*
* Description:
* Show reason of socket error.
*
****************************************************************************/
static int iperf_show_socket_error_reason(const char *str, int sockfd)
{
int err = errno;
if (err != 0)
{
printf("%s error, error code: %d, reason: %s",
str, err, strerror(err));
}
return err;
}
/****************************************************************************
* Name: iperf_report_task
*
* Description:
* Start iperf report task
*
****************************************************************************/
static void iperf_report_task(void *arg)
{
uint32_t interval = s_iperf_ctrl.cfg.interval;
uint32_t time = s_iperf_ctrl.cfg.time;
uint32_t last_len = 0;
uint32_t cur = 0;
printf("\n%16s %s\n", "Interval", "Bandwidth\n");
while (!s_iperf_ctrl.finish)
{
sleep(interval);
printf("%4d-%4d sec, %.2f Mbits/sec\n", cur, cur + interval,
(double)((s_iperf_ctrl.total_len - last_len) * 8) / interval / 1e6);
cur += interval;
last_len = s_iperf_ctrl.total_len;
if (cur >= time)
{
break;
}
}
if (cur != 0)
{
printf("%4d-%4d sec, %.2f Mbits/sec\n", 0, time,
(double)(s_iperf_ctrl.total_len * 8) / cur / 1e6);
}
s_iperf_ctrl.finish = true;
pthread_exit(NULL);
}
/****************************************************************************
* Name: iperf_start_report
*
* Description:
* Start iperf report
*
****************************************************************************/
static int iperf_start_report(void)
{
int ret;
pthread_t thread;
struct sched_param param;
pthread_attr_t attr;
pthread_attr_init(&attr);
param.sched_priority = IPERF_REPORT_TASK_PRIORITY;
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setstacksize(&attr, IPERF_REPORT_TASK_STACK);
ret = pthread_create(&thread, &attr, (void *)iperf_report_task,
IPERF_REPORT_TASK_NAME);
if (ret != 0)
{
printf("iperf_thread: pthread_create failed: %d, %s\n",
ret, IPERF_REPORT_TASK_NAME);
return -1;
}
return 0;
}
/****************************************************************************
* Name: iperf_run_tcp_server
*
* Description:
* Start tcp server
*
****************************************************************************/
static int iperf_run_tcp_server(void)
{
socklen_t addr_len = sizeof(struct sockaddr);
struct sockaddr_in remote_addr;
struct sockaddr_in addr;
int actual_recv = 0;
int want_recv = 0;
uint8_t *buffer;
int listen_socket;
struct timeval t;
int sockfd;
int opt;
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_socket < 0)
{
iperf_show_socket_error_reason("tcp server create", listen_socket);
return -1;
}
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.sport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip;
if (bind(listen_socket, (struct sockaddr *)&addr, sizeof(addr)) != 0)
{
iperf_show_socket_error_reason("tcp server bind", listen_socket);
close(listen_socket);
return -1;
}
if (listen(listen_socket, 5) < 0)
{
iperf_show_socket_error_reason("tcp server listen", listen_socket);
close(listen_socket);
return -1;
}
buffer = s_iperf_ctrl.buffer;
want_recv = s_iperf_ctrl.buffer_len;
while (!s_iperf_ctrl.finish)
{
/* TODO need to change to non-block mode */
sockfd = accept(listen_socket, (struct sockaddr *)&remote_addr,
&addr_len);
if (sockfd < 0)
{
iperf_show_socket_error_reason("tcp server listen", listen_socket);
close(listen_socket);
return -1;
}
else
{
printf("accept: %s,%d\n", inet_ntoa(remote_addr.sin_addr),
htons(remote_addr.sin_port));
iperf_start_report();
t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
}
while (!s_iperf_ctrl.finish)
{
actual_recv = recv(sockfd, buffer, want_recv, 0);
if (actual_recv < 0)
{
iperf_show_socket_error_reason("tcp server recv",
listen_socket);
s_iperf_ctrl.finish = true;
break;
}
else
{
s_iperf_ctrl.total_len += actual_recv;
}
}
close(sockfd);
}
s_iperf_ctrl.finish = true;
close(listen_socket);
return 0;
}
/****************************************************************************
* Name: iperf_run_udp_server
*
* Description:
* Start udp server
*
****************************************************************************/
static int iperf_run_udp_server(void)
{
socklen_t addr_len = sizeof(struct sockaddr_in);
struct sockaddr_in addr;
int actual_recv = 0;
struct timeval t;
int want_recv = 0;
uint8_t *buffer;
int sockfd;
int opt;
bool udp_recv_start = true;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0)
{
iperf_show_socket_error_reason("udp server create", sockfd);
return -1;
}
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.sport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip;
if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) != 0)
{
iperf_show_socket_error_reason("udp server bind", sockfd);
return -1;
}
addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.sport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.sip;
buffer = s_iperf_ctrl.buffer;
want_recv = s_iperf_ctrl.buffer_len;
printf("want recv=%d", want_recv);
t.tv_sec = IPERF_SOCKET_RX_TIMEOUT;
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &t, sizeof(t));
while (!s_iperf_ctrl.finish)
{
actual_recv = recvfrom(sockfd, buffer, want_recv, 0,
(struct sockaddr *)&addr, &addr_len);
if (actual_recv < 0)
{
iperf_show_socket_error_reason("udp server recv", sockfd);
}
else
{
if (udp_recv_start == true)
{
iperf_start_report();
udp_recv_start = false;
}
s_iperf_ctrl.total_len += actual_recv;
}
}
s_iperf_ctrl.finish = true;
close(sockfd);
return 0;
}
/****************************************************************************
* Name: iperf_run_udp_client
*
* Description:
* Start udp client
*
****************************************************************************/
static int iperf_run_udp_client(void)
{
struct sockaddr_in addr;
struct iperf_udp_pkt_t *udp;
int actual_send = 0;
bool retry = false;
uint32_t delay = 1;
int want_send = 0;
uint8_t *buffer;
int sockfd;
int opt;
int err;
int id;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0)
{
iperf_show_socket_error_reason("udp client create", sockfd);
return -1;
}
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
addr.sin_family = AF_INET;
addr.sin_port = htons(s_iperf_ctrl.cfg.dport);
addr.sin_addr.s_addr = s_iperf_ctrl.cfg.dip;
iperf_start_report();
buffer = s_iperf_ctrl.buffer;
udp = (struct iperf_udp_pkt_t *)buffer;
want_send = s_iperf_ctrl.buffer_len;
id = 0;
while (!s_iperf_ctrl.finish)
{
if (false == retry)
{
id++;
udp->id = htonl(id);
delay = 1;
}
retry = false;
actual_send = sendto(sockfd, buffer, want_send, 0,
(struct sockaddr *)&addr, sizeof(addr));
if (actual_send != want_send)
{
err = iperf_get_socket_error_code(sockfd);
if (err == ENOMEM)
{
usleep(delay * 10000);
if (delay < IPERF_MAX_DELAY)
{
delay <<= 1;
}
retry = true;
continue;
}
else
{
printf("udp client send abort: err=%d", err);
break;
}
}
else
{
s_iperf_ctrl.total_len += actual_send;
}
}
s_iperf_ctrl.finish = true;
close(sockfd);
return 0;
}
/****************************************************************************
* Name: iperf_run_tcp_client
*
* Description:
* Start tcp client
*
****************************************************************************/
static int iperf_run_tcp_client(void)
{
struct sockaddr_in remote_addr;
int actual_send = 0;
int want_send = 0;
uint8_t *buffer;
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0)
{
iperf_show_socket_error_reason("tcp client create", sockfd);
return -1;
}
memset(&remote_addr, 0, sizeof(remote_addr));
remote_addr.sin_family = AF_INET;
remote_addr.sin_port = htons(s_iperf_ctrl.cfg.dport);
remote_addr.sin_addr.s_addr = s_iperf_ctrl.cfg.dip;
if (connect(sockfd, (struct sockaddr *)&remote_addr,
sizeof(remote_addr)) < 0)
{
iperf_show_socket_error_reason("tcp client connect", sockfd);
return -1;
}
iperf_start_report();
buffer = s_iperf_ctrl.buffer;
want_send = s_iperf_ctrl.buffer_len;
while (!s_iperf_ctrl.finish)
{
actual_send = send(sockfd, buffer, want_send, 0);
if (actual_send <= 0)
{
iperf_show_socket_error_reason("tcp client send", sockfd);
break;
}
else
{
s_iperf_ctrl.total_len += actual_send;
}
}
s_iperf_ctrl.finish = true;
close(sockfd);
return 0;
}
/****************************************************************************
* Name: iperf_task_traffic
*
* Description:
* Select to run tcp or udp.
*
****************************************************************************/
static void iperf_task_traffic(void *arg)
{
if (iperf_is_udp_client())
{
iperf_run_udp_client();
}
else if (iperf_is_udp_server())
{
iperf_run_udp_server();
}
else if (iperf_is_tcp_client())
{
iperf_run_tcp_client();
}
else
{
iperf_run_tcp_server();
}
if (s_iperf_ctrl.buffer)
{
free(s_iperf_ctrl.buffer);
s_iperf_ctrl.buffer = NULL;
}
printf("iperf exit");
s_iperf_is_running = false;
pthread_exit(NULL);
}
static uint32_t iperf_get_buffer_len(void)
{
if (iperf_is_udp_client())
{
return IPERF_UDP_TX_LEN;
}
else if (iperf_is_udp_server())
{
return IPERF_UDP_RX_LEN;
}
else if (iperf_is_tcp_client())
{
return IPERF_TCP_TX_LEN;
}
else
{
return IPERF_TCP_RX_LEN;
}
return 0;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: iperf_start
*
* Description:
* Start iperf task.
*
****************************************************************************/
int iperf_start(struct iperf_cfg_t *cfg)
{
int ret;
struct sched_param param;
pthread_t thread;
pthread_attr_t attr;
if (!cfg)
{
return -1;
}
if (s_iperf_is_running)
{
printf("iperf is running\n");
return -1;
}
memset(&s_iperf_ctrl, 0, sizeof(s_iperf_ctrl));
memcpy(&s_iperf_ctrl.cfg, cfg, sizeof(*cfg));
s_iperf_is_running = true;
s_iperf_ctrl.finish = false;
s_iperf_ctrl.buffer_len = iperf_get_buffer_len();
s_iperf_ctrl.buffer = (uint8_t *)malloc(s_iperf_ctrl.buffer_len);
if (!s_iperf_ctrl.buffer)
{
printf("create buffer: not enough memory\n");
return -1;
}
memset(s_iperf_ctrl.buffer, 0, s_iperf_ctrl.buffer_len);
pthread_attr_init(&attr);
param.sched_priority = IPERF_TRAFFIC_TASK_PRIORITY;
pthread_attr_setschedparam(&attr, &param);
pthread_attr_setstacksize(&attr, IPERF_TRAFFIC_TASK_STACK);
ret = pthread_create(&thread, &attr, (void *)iperf_task_traffic,
IPERF_TRAFFIC_TASK_NAME);
if (ret != 0)
{
printf("iperf_task_traffic: create task failed: %d\n", ret);
free(s_iperf_ctrl.buffer);
s_iperf_ctrl.buffer = NULL;
return -1;
}
return 0;
}
/****************************************************************************
* Name: iperf_stop
*
* Description:
* Stop iperf task.
*
****************************************************************************/
int iperf_stop(void)
{
if (s_iperf_is_running)
{
s_iperf_ctrl.finish = true;
}
while (s_iperf_is_running)
{
printf("wait current iperf to stop ...\n");
usleep(300 * 1000);
}
return 0;
}

97
netutils/iperf/iperf.h Normal file
View File

@ -0,0 +1,97 @@
/****************************************************************************
* apps/netutils/iperf/iperf.h
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
#ifndef __IPERF_H_
#define __IPERF_H_
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define IPERF_FLAG_CLIENT (1)
#define IPERF_FLAG_SERVER (1 << 1)
#define IPERF_FLAG_TCP (1 << 2)
#define IPERF_FLAG_UDP (1 << 3)
/****************************************************************************
* Public Types
****************************************************************************/
struct iperf_cfg_t
{
uint32_t flag;
uint32_t dip;
uint32_t sip;
uint16_t dport;
uint16_t sport;
uint32_t interval;
uint32_t time;
};
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: iperf_start
*
* Description:
* Start iperf task.
*
****************************************************************************/
int iperf_start(struct iperf_cfg_t *cfg);
/****************************************************************************
* Name: iperf_stop
*
* Description:
* Stop iperf task.
*
****************************************************************************/
int iperf_stop(void);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif

230
netutils/iperf/iperf_main.c Normal file
View File

@ -0,0 +1,230 @@
/****************************************************************************
* apps/netutils/iperf/iperf_main.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <net/if.h>
#include "netutils/netlib.h"
#include "argtable3.h"
#include "iperf.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_EXAMPLES_IPERFTEST_DEVNAME
# define DEVNAME CONFIG_EXAMPLES_IPERFTEST_DEVNAME
#else
# define DEVNAME "wlan0"
#endif
#define IPERF_DEFAULT_PORT 5001
#define IPERF_DEFAULT_INTERVAL 3
#define IPERF_DEFAULT_TIME 30
/****************************************************************************
* Private Types
****************************************************************************/
struct wifi_iperf_t
{
struct arg_str *ip;
struct arg_lit *server;
struct arg_lit *udp;
struct arg_int *port;
struct arg_int *interval;
struct arg_int *time;
struct arg_lit *abort;
struct arg_end *end;
};
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: iperf_showusage
*
* Description:
* Show usage of the demo program and exit
*
****************************************************************************/
static void iperf_showusage(FAR const char *progname, int exitcode)
{
printf("USAGE: %s [-sua] [-c <ip>] [-p <port>]\
[-i <interval>] [-t <time>]\n", progname);
printf("iperf command:\n");
printf(" -c, --client=<ip> run in client mode,\
connecting to <host>\n");
printf(" -s, --server run in server mode\n");
printf(" -u, --udp use UDP rather than TCP\n");
printf(" -p, --port=<port> server port to listen on/connect to\n");
printf(" -i, --interval=<interval>\
seconds between periodic bandwidth reports\n");
printf(" -t, --time=<time>\
time in seconds to transmit for (default 10 secs)\n");
printf(" -a, --abort abort running iperf\n");
printf("\n");
exit(exitcode);
}
/****************************************************************************
* Public Functions
****************************************************************************/
int main(int argc, FAR char *argv[])
{
struct wifi_iperf_t iperf_args;
struct iperf_cfg_t cfg;
struct in_addr addr;
int nerrors;
bzero(&addr, sizeof(struct in_addr));
bzero(&cfg, sizeof(cfg));
iperf_args.ip = arg_str0("c", "client", "<ip>",
"run in client mode, connecting to <host>");
iperf_args.server = arg_lit0("s", "server", "run in server mode");
iperf_args.udp = arg_lit0("u", "udp", "use UDP rather than TCP");
iperf_args.port = arg_int0("p", "port", "<port>",
"server port to listen on/connect to");
iperf_args.interval = arg_int0("i", "interval", "<interval>",
"seconds between periodic bandwidth reports");
iperf_args.time = arg_int0("t", "time", "<time>",
"time in seconds to transmit for (default 10 secs)");
iperf_args.abort = arg_lit0("a", "abort", "abort running iperf");
iperf_args.end = arg_end(1);
nerrors = arg_parse(argc, argv, (void**) &iperf_args);
if (nerrors != 0)
{
arg_print_errors(stderr, iperf_args.end, argv[0]);
iperf_showusage(argv[0], 0);
}
if (iperf_args.abort->count != 0)
{
iperf_stop();
printf("ERROR: abort->count: %d\n", iperf_args.abort->count);
iperf_showusage(argv[0], 0);
}
if (((iperf_args.ip->count == 0) && (iperf_args.server->count == 0)) ||
((iperf_args.ip->count != 0) && (iperf_args.server->count != 0)))
{
printf("ERROR: should specific client/server mode\n");
iperf_showusage(argv[0], 0);
}
if (iperf_args.ip->count == 0)
{
cfg.flag |= IPERF_FLAG_SERVER;
}
else
{
cfg.dip = inet_addr(iperf_args.ip->sval[0]);
cfg.flag |= IPERF_FLAG_CLIENT;
}
addr.s_addr = 0;
netlib_get_ipv4addr(DEVNAME, &addr);
if (addr.s_addr == 0)
{
printf("ERROR: access IP is 0x00 \n");
return -1;
}
printf(" IP: %s\n", inet_ntoa(addr));
cfg.sip = addr.s_addr;
if (iperf_args.udp->count == 0)
{
cfg.flag |= IPERF_FLAG_TCP;
}
else
{
cfg.flag |= IPERF_FLAG_UDP;
}
if (iperf_args.port->count == 0)
{
cfg.sport = IPERF_DEFAULT_PORT;
cfg.dport = IPERF_DEFAULT_PORT;
}
else
{
if (cfg.flag & IPERF_FLAG_SERVER)
{
cfg.sport = iperf_args.port->ival[0];
cfg.dport = IPERF_DEFAULT_PORT;
}
else
{
cfg.sport = IPERF_DEFAULT_PORT;
cfg.dport = iperf_args.port->ival[0];
}
}
if (iperf_args.interval->count == 0)
{
cfg.interval = IPERF_DEFAULT_INTERVAL;
}
else
{
cfg.interval = iperf_args.interval->ival[0];
if (cfg.interval <= 0)
{
cfg.interval = IPERF_DEFAULT_INTERVAL;
}
}
if (iperf_args.time->count == 0)
{
cfg.time = IPERF_DEFAULT_TIME;
}
else
{
cfg.time = iperf_args.time->ival[0];
if (cfg.time <= cfg.interval)
{
cfg.time = cfg.interval;
}
}
printf("\n mode=%s-%s sip=%d.%d.%d.%d:%d,\
dip=%d.%d.%d.%d:%d, interval=%d, time=%d\n",
cfg.flag & IPERF_FLAG_TCP ?"tcp":"udp",
cfg.flag & IPERF_FLAG_SERVER ?"server":"client",
cfg.sip & 0xff, (cfg.sip >> 8) & 0xff, (cfg.sip >> 16) & 0xff,
(cfg.sip >> 24) & 0xff, cfg.sport,
cfg.dip & 0xff, (cfg.dip >> 8) & 0xff, (cfg.dip >> 16) & 0xff,
(cfg.dip >> 24) & 0xff, cfg.dport,
cfg.interval, cfg.time);
iperf_start(&cfg);
return 0;
}

2
system/argtable3/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/argtable3*
/v*.tar.gz

18
system/argtable3/Kconfig Normal file
View File

@ -0,0 +1,18 @@
#
# For a description of the syntax of this configuration file,
# see the file kconfig-language.txt in the NuttX tools repository.
#
config SYSTEM_ARGTABLE3
bool "ARGTABLE3 library"
default n
---help---
Enables the ARGTABLE3 library.
if SYSTEM_ARGTABLE3
config SYSTEM_ARGTABLE3_VERSION
string "ARGTABLE3 Version"
default "3.0.0"
endif

View File

@ -0,0 +1,27 @@
############################################################################
# apps/system/argtable3/Make.defs
# Adds selected applications to apps/ build
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
ifneq ($(CONFIG_SYSTEM_ARGTABLE3),)
CONFIGURED_APPS += $(APPDIR)/system/argtable3
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" "$(APPDIR)/system/argtable3/argtable3/"}
CXXFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" "$(APPDIR)/system/argtable3/argtable3/"}
endif

54
system/argtable3/Makefile Normal file
View File

@ -0,0 +1,54 @@
############################################################################
# apps/system/argtable3/Makefile
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership. The
# ASF licenses this file to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance with the
# License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
############################################################################
include $(APPDIR)/Make.defs
ARGTABLE3_VERSION := $(patsubst "%",%,$(CONFIG_SYSTEM_ARGTABLE3_VERSION))
ARGTABLE3_TARBALL = v$(ARGTABLE3_VERSION).tar.gz
ARGTABLE3_UNPACK = argtable3
ARGTABLE3_SRCDIR = $(ARGTABLE3_UNPACK)
DEPPATH += --dep-path $(ARGTABLE3_SRCDIR)
VPATH += :$(ARGTABLE3_SRCDIR)
CSRCS := $(notdir $(wildcard $(ARGTABLE3_SRCDIR)$(DELIM)argtable3.c))
$(ARGTABLE3_TARBALL):
$(Q) echo "Downloading argtable3-$(ARGTABLE3_VERSION)"
$(Q) echo "$(ARGTABLE3_SRCDIR)"
$(Q) echo "$(ARGTABLE3_TARBALL)--$(ARGTABLE3_UNPACK)"
$(Q) wget https://github.com/argtable/argtable3/archive/$(ARGTABLE3_TARBALL)
$(ARGTABLE3_UNPACK): $(ARGTABLE3_TARBALL)
$(Q) tar zxf $(ARGTABLE3_TARBALL)
$(Q) mv argtable3-$(ARGTABLE3_VERSION) $(ARGTABLE3_UNPACK)
$(Q) echo "Patching $(ARGTABLE3_UNPACK)"
$(Q) patch -p0 < argtable3.patch
$(ARGTABLE3_UNPACK)/.patch: $(ARGTABLE3_UNPACK)
$(Q) touch $(ARGTABLE3_UNPACK)/.patch
context:: $(ARGTABLE3_UNPACK)/.patch
distclean::
$(call DELFILE, $(ARGTABLE3_TARBALL))
$(call DELDIR, $(ARGTABLE3_UNPACK))
include $(APPDIR)/Application.mk