netutils/iperf: Add iperf example.
system/argtable3: Add an ANSI C library for command-line parsing.
This commit is contained in:
parent
bfa826d30d
commit
756dc32fd0
37
netutils/iperf/Kconfig
Normal file
37
netutils/iperf/Kconfig
Normal 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
24
netutils/iperf/Make.defs
Normal 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
35
netutils/iperf/Makefile
Normal 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
87
netutils/iperf/README.md
Normal 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
722
netutils/iperf/iperf.c
Normal 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, ¶m);
|
||||||
|
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, ¶m);
|
||||||
|
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
97
netutils/iperf/iperf.h
Normal 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
230
netutils/iperf/iperf_main.c
Normal 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
2
system/argtable3/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/argtable3*
|
||||||
|
/v*.tar.gz
|
18
system/argtable3/Kconfig
Normal file
18
system/argtable3/Kconfig
Normal 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
|
27
system/argtable3/Make.defs
Normal file
27
system/argtable3/Make.defs
Normal 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
54
system/argtable3/Makefile
Normal 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
|
Loading…
x
Reference in New Issue
Block a user