From db3784b9283f6cf9cf488f6e36971ae1f25d595f Mon Sep 17 00:00:00 2001 From: Jeremy Date: Mon, 15 May 2023 15:00:13 +0800 Subject: [PATCH 1/6] optmize lwip demo and add iperf for hc32 --- .../third_party_driver/ethernet/ethernetif.c | 1 + .../timer/connect_hwtimer.c | 2 +- .../resources/ethernet/LwIP/arch/lwipopts.h | 4 +- .../resources/ethernet/cmd_lwip/Makefile | 2 +- .../resources/ethernet/cmd_lwip/iperf.c | 510 ++++++++++++++++++ .../ethernet/cmd_lwip/lwip_tcp_demo.c | 33 +- .../ethernet/cmd_lwip/lwip_udp_demo.c | 39 +- .../resources/ethernet/cmd_lwip/ping.c | 5 +- 8 files changed, 579 insertions(+), 17 deletions(-) create mode 100644 Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c diff --git a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c index 6658a96e2..0dd282339 100644 --- a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c +++ b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/ethernet/ethernetif.c @@ -110,6 +110,7 @@ static char txBuf[] = "Ethernet Loop-Back Test"; /******************************************************************************* * Local variable definitions ('static') ******************************************************************************/ + /* Global Ethernet handle*/ static stc_eth_handle_t EthHandle; /* Ethernet Tx DMA Descriptor */ diff --git a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/timer/connect_hwtimer.c b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/timer/connect_hwtimer.c index d753db2c6..37ad87ec6 100644 --- a/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/timer/connect_hwtimer.c +++ b/Ubiquitous/XiZi_IIoT/board/hc32f4a0/third_party_driver/timer/connect_hwtimer.c @@ -163,7 +163,7 @@ static int BoardHwtimerDevBend(void) return ret; } -/*K210 BOARD HWTIMER INIT*/ +/*HC32F4A0 BOARD HWTIMER INIT*/ int HwTimerInit(void) { x_err_t ret = EOK; diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h index 698afb121..d960b16bb 100644 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/LwIP/arch/lwipopts.h @@ -146,7 +146,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums - To use this feature let the following define uncommented. - To disable it and process by CPU comment the the checksum. */ -//#define CHECKSUM_BY_HARDWARE +#define CHECKSUM_BY_HARDWARE #ifdef CHECKSUM_BY_HARDWARE /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/ @@ -176,7 +176,7 @@ The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums #define CHECKSUM_CHECK_UDP 1 /* CHECKSUM_CHECK_TCP==1: Check checksums in software for incoming TCP packets.*/ #define CHECKSUM_CHECK_TCP 1 - /* CHECKSUM_CHECK_ICMP==1: Check checksums by hardware for incoming ICMP packets.*/ + /* CHECKSUM_CHECK_ICMP==1: Check checksums by software for incoming ICMP packets.*/ #define CHECKSUM_GEN_ICMP 1 #endif diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile index 9426c8faf..41a014d57 100755 --- a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/Makefile @@ -1,3 +1,3 @@ -SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c +SRC_FILES := ping.c lwip_ping_demo.c lwip_tcp_demo.c lwip_udp_demo.c tcpecho_raw.c lwip_config_demo.c lwip_dhcp_demo.c iperf.c include $(KERNEL_ROOT)/compiler.mk diff --git a/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c new file mode 100644 index 000000000..bbf10fbbd --- /dev/null +++ b/Ubiquitous/XiZi_IIoT/resources/ethernet/cmd_lwip/iperf.c @@ -0,0 +1,510 @@ +/** +* iperf-liked network performance tool +* +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "lwip/sockets.h" +#include + +#define IPERF_PORT 5001 +#define IPERF_BUFSZ (4 * 1024) + +#define IPERF_MODE_STOP 0 +#define IPERF_MODE_SERVER 1 +#define IPERF_MODE_CLIENT 2 + +typedef struct{ + int mode; + char *host; + int port; +} IPERF_PARAM; +static IPERF_PARAM param = {IPERF_MODE_STOP, NULL, IPERF_PORT}; + +char tcp_iperf_ip[] = {192, 168, 131, 77}; +char tcp_iperf_mask[] = {255, 255, 254, 0}; +char tcp_iperf_gw[] = {192, 168, 131, 1}; + +static void iperf_udp_client(void *thread_param) +{ + int sock; + uint32 *buffer; + struct sockaddr_in server; + uint32 packet_count = 0; + uint32 tick; + int send_size; + + send_size = IPERF_BUFSZ > 1470 ? 1470 : IPERF_BUFSZ; + + sock = socket(PF_INET, SOCK_DGRAM, 0); + if(sock < 0){ + KPrintf("[%s:%d] can't create socket! exit!\n", __FILE__, __LINE__); + return; + } + + server.sin_family = PF_INET; + server.sin_port = htons(param.port); + server.sin_addr.s_addr = inet_addr(param.host); + memset(&(server.sin_zero), 0, sizeof(server.sin_zero)); + + if (connect(sock, (struct sockaddr *)&server, sizeof(struct sockaddr))){ + lw_error("Unable to connect\n"); + closesocket(sock); + return; + } + + buffer = malloc(IPERF_BUFSZ); + if (buffer == NULL){ + printf("[%s:%d] malloc failed\n", __FILE__, __LINE__); + return; + } + memset(buffer, 0x00, IPERF_BUFSZ); + + KPrintf("iperf udp mode run...\n"); + while (param.mode != IPERF_MODE_STOP){ + packet_count++; + tick = CurrentTicksGain(); + buffer[0] = htonl(packet_count); + buffer[1] = htonl(tick / TICK_PER_SECOND); + buffer[2] = htonl((tick % TICK_PER_SECOND) * 1000); + sendto(sock, buffer, send_size, 0, (struct sockaddr *)&server, sizeof(struct sockaddr_in)); + } + closesocket(sock); + free(buffer); + KPrintf("iperf udp mode exit...\n"); +} + +static void iperf_udp_server(void *thread_param) +{ + int sock; + uint32 *buffer; + struct sockaddr_in server; + struct sockaddr_in sender; + int sender_len, r_size; + uint64 sentlen; + uint32 pcount = 0, last_pcount = 0; + uint32 lost, total; + x_ticks_t tick1, tick2; + struct timeval timeout; + + buffer = malloc(IPERF_BUFSZ); + if (buffer == NULL){ + return; + } + + sock = socket(PF_INET, SOCK_DGRAM, 0); + if(sock < 0){ + KPrintf("can't create socket! exit!"); + return; + } + + server.sin_family = PF_INET; + server.sin_port = htons(param.port); + server.sin_addr.s_addr = inet_addr("0.0.0.0"); + + timeout.tv_sec = 2; + timeout.tv_usec = 0; + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) == -1){ + KPrintf("setsockopt failed!"); + closesocket(sock); + free(buffer); + return; + } + + if (bind(sock, (struct sockaddr *)&server, sizeof(struct sockaddr_in)) < 0){ + KPrintf("iperf server bind failed! exit!"); + closesocket(sock); + free(buffer); + return; + } + + while (param.mode != IPERF_MODE_STOP){ + tick1 = CurrentTicksGain(); + tick2 = tick1; + lost = 0; + total = 0; + sentlen = 0; + while ((tick2 - tick1) < (TICK_PER_SECOND * 5)){ + r_size = recvfrom(sock, buffer, IPERF_BUFSZ, 0, (struct sockaddr *)&sender, (socklen_t*)&sender_len); + if (r_size > 12){ + pcount = ntohl(buffer[0]); + if (last_pcount < pcount){ + lost += pcount - last_pcount - 1; + total += pcount - last_pcount; + } + else{ + last_pcount = pcount; + } + last_pcount = pcount; + sentlen += r_size; + } + tick2 = CurrentTicksGain(); + } + if (sentlen > 0){ + long data; + int integer, decimal; + KTaskDescriptorType tid; + + tid = GetKTaskDescriptor(); + data = sentlen * TICK_PER_SECOND / 125 / (tick2 - tick1); + integer = data/1000; + decimal = data%1000; + KPrintf("%s: %d.%03d0 Mbps! lost:%d total:%d\n", tid->task_base_info.name, integer, decimal, lost, total); + } + } + free(buffer); + closesocket(sock); +} + +static void iperf_client(void *thread_param) +{ + int i; + int sock; + int ret; + int tips = 1; + uint8_t *send_buf; + uint64 sentlen; + x_ticks_t tick1, tick2; + struct sockaddr_in addr; + + send_buf = (uint8_t *) malloc(IPERF_BUFSZ); + if (!send_buf) return ; + + for (i = 0; i < IPERF_BUFSZ; i ++) + send_buf[i] = i & 0xff; + + while (param.mode != IPERF_MODE_STOP) + { + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0){ + KPrintf("create socket failed!"); + DelayKTask(TICK_PER_SECOND); + continue; + } + + addr.sin_family = PF_INET; + addr.sin_port = htons(param.port); + addr.sin_addr.s_addr = inet_addr((char *)param.host); + + ret = connect(sock, (const struct sockaddr *)&addr, sizeof(addr)); + if (ret == -1){ + if (tips){ + KPrintf("Connect to iperf server faile, Waiting for the server to open!"); + tips = 0; + } + closesocket(sock); + DelayKTask(TICK_PER_SECOND); + continue; + } + KPrintf("Connect to iperf server successful!\n"); + + { + int flag = 1; + + setsockopt(sock, + IPPROTO_TCP, /* set option at TCP level */ + TCP_NODELAY, /* name of option */ + (void *) &flag, /* the cast is historical cruft */ + sizeof(int)); /* length of option value */ + } + + sentlen = 0; + + tick1 = CurrentTicksGain(); + while (param.mode != IPERF_MODE_STOP){ + tick2 = CurrentTicksGain(); + if (tick2 - tick1 >= TICK_PER_SECOND * 5){ + long data; + int integer, decimal; + KTaskDescriptorType tid; + + tid = GetKTaskDescriptor(); + data = sentlen * TICK_PER_SECOND / 125 / (tick2 - tick1); + integer = data/1000; + decimal = data%1000; + KPrintf("%s: %d.%03d0 Mbps!\n", tid->task_base_info.name, integer, decimal); + tick1 = tick2; + sentlen = 0; + } + + ret = send(sock, send_buf, IPERF_BUFSZ, 0); + if (ret > 0){ + sentlen += ret; + } + + if (ret < 0) break; + } + + closesocket(sock); + + DelayKTask(TICK_PER_SECOND * 2); + KPrintf("Disconnected, iperf server shut down!"); + tips = 1; + } + free(send_buf); +} + +void iperf_server(void *thread_param) +{ + uint8_t *recv_data; + socklen_t sin_size; + x_ticks_t tick1, tick2; + int sock = -1, connected, bytes_received; + uint64 recvlen; + struct sockaddr_in server_addr, client_addr; + fd_set readset; + struct timeval timeout; + + sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock < 0){ + KPrintf("[%s:%d] Socket error!\n", __FILE__, __LINE__); + goto __exit; + } + + recv_data = (uint8_t *)malloc(IPERF_BUFSZ); + if (recv_data == NULL){ + KPrintf("No memory!\n"); + goto __exit; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(param.port); + server_addr.sin_addr.s_addr = INADDR_ANY; + memset(&(server_addr.sin_zero), 0x0, sizeof(server_addr.sin_zero)); + + if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1){ + KPrintf("Unable to bind!\n"); + goto __exit; + } + + if (listen(sock, 5) == -1){ + KPrintf("Listen error!\n"); + goto __exit; + } + + timeout.tv_sec = 3; + timeout.tv_usec = 0; + + while (param.mode != IPERF_MODE_STOP){ + FD_ZERO(&readset); + FD_SET(sock, &readset); + + if (select(sock + 1, &readset, NULL, NULL, &timeout) == 0) + continue; + + sin_size = sizeof(struct sockaddr_in); + + connected = accept(sock, (struct sockaddr *)&client_addr, &sin_size); + + KPrintf("new client connected from (%s, %d)", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + + int flag = 1; + setsockopt(connected, + IPPROTO_TCP, /* set option at TCP level */ + TCP_NODELAY, /* name of option */ + (void *) &flag, /* the cast is historical cruft */ + sizeof(int)); /* length of option value */ + + printf(" \n"); //BUG + + recvlen = 0; + tick1 = CurrentTicksGain(); + while (param.mode != IPERF_MODE_STOP){ + bytes_received = recv(connected, recv_data, IPERF_BUFSZ, 0); + if (bytes_received <= 0) break; + + recvlen += bytes_received; + + tick2 = CurrentTicksGain(); + if (tick2 - tick1 >= TICK_PER_SECOND * 5){ + long data; + int integer, decimal; + KTaskDescriptorType tid; + + tid = GetKTaskDescriptor(); + data = recvlen * TICK_PER_SECOND / 125 / (tick2 - tick1); + integer = data/1000; + decimal = data%1000; + KPrintf("%s: %d.%03d0 Mbps!\n", tid->task_base_info.name, integer, decimal); + tick1 = tick2; + recvlen = 0; + } + } + KPrintf("client disconnected (%s, %d)\n", + inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port)); + if (connected >= 0) closesocket(connected); + connected = -1; + } + +__exit: + if (sock >= 0) closesocket(sock); + if (recv_data) free(recv_data); +} + +void iperf_usage(void) +{ + KPrintf("Usage: iperf [-s|-c host] [options] [multi-threaded]\n"); + KPrintf(" iperf [-h|--stop]\n"); + KPrintf("\n"); + KPrintf("Client/Server:\n"); + KPrintf(" -p # server port to listen on/connect to\n"); + KPrintf("\n"); + KPrintf("Server specific:\n"); + KPrintf(" -s run in server mode\n"); + KPrintf("\n"); + KPrintf("Client specific:\n"); + KPrintf(" -c run in client mode, connecting to \n"); + KPrintf("\n"); + KPrintf("Miscellaneous:\n"); + KPrintf(" -h print this message and quit\n"); + KPrintf(" --stop stop iperf program\n"); + KPrintf(" -u testing UDP protocol\n"); + KPrintf(" -m