add iperf for w5500

This commit is contained in:
Jeremy 2023-05-15 11:02:00 +08:00
parent 12c24ddc73
commit 7aac1926f3
1 changed files with 465 additions and 0 deletions

View File

@ -0,0 +1,465 @@
#include "socket.h"
#include "w5500.h"
#include "connect_w5500.h"
#ifdef BSP_WIZ_USE_IPERF
#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;
uint8 host[4];
uint16 port;
} IPERF_PARAM;
static IPERF_PARAM param = {IPERF_MODE_STOP, {0, 0, 0, 0}, IPERF_PORT};
static void iperf_udp_client(void *thread_param)
{
int sock;
uint8 *buffer;
uint16 local_port = 4840;
uint32 packet_count = 0;
uint32 tick;
int send_size;
send_size = IPERF_BUFSZ > 1470 ? 1470 : IPERF_BUFSZ;
sock = 0; // w5500支持8个socket独立工作todo socket端口管理
// setSn_TXBUF_SIZE(sock, 16);
// setSn_RXBUF_SIZE(sock, 16);
buffer = malloc(IPERF_BUFSZ);
if (buffer == NULL){
printf("[%s:%d] malloc failed\n", __FILE__, __LINE__);
return;
}
for(int i = 0; i < IPERF_BUFSZ; i++)
buffer[i] = i % 10;
KPrintf("iperf udp mode run...\n");
while (param.mode != IPERF_MODE_STOP){
switch(getSn_SR(sock)){
case SOCK_CLOSED:
wiz_socket(sock, Sn_MR_UDP, local_port, 0x00);
break;
case SOCK_UDP:
packet_count++;
tick = CurrentTicksGain();
buffer[0] = (uint8)(packet_count >> 24);
buffer[1] = (uint8)(packet_count >> 16);
buffer[2] = (uint8)(packet_count >> 8);
buffer[3] = (uint8)(packet_count);
buffer[4] = (uint8)((tick / TICK_PER_SECOND) >> 24);
buffer[5] = (uint8)((tick / TICK_PER_SECOND) >> 16);
buffer[6] = (uint8)((tick / TICK_PER_SECOND) >> 8);
buffer[7] = (uint8)((tick / TICK_PER_SECOND));
buffer[8] = (uint8)(((tick % TICK_PER_SECOND) * 1000) >> 24);
buffer[9] = (uint8)(((tick % TICK_PER_SECOND) * 1000) >> 16);
buffer[10] = (uint8)(((tick % TICK_PER_SECOND) * 1000) >> 8);
buffer[11] = (uint8)(((tick % TICK_PER_SECOND) * 1000));
wiz_sock_sendto(sock, buffer, send_size, param.host, param.port);
break;
}
}
if(getSn_SR(sock) != SOCK_CLOSED) wiz_sock_close(sock);
free(buffer);
KPrintf("iperf udp mode exit...\n");
}
static void iperf_udp_server(void *thread_param)
{
int sock, sender_len, r_size;
uint8 *buffer, client_addr[4];
uint16 client_port;
uint32 pcount = 0, last_pcount = 0;
uint32 lost, total;
uint64 recvlen;
x_ticks_t tick1, tick2;
struct timeval timeout;
buffer = malloc(IPERF_BUFSZ);
if (buffer == NULL){
return;
}
sock = 0; //todo
// setSn_RXBUF_SIZE(sock, 16);
// setSn_TXBUF_SIZE(sock, 16);
KPrintf("iperf udp server run...\n");
while (param.mode != IPERF_MODE_STOP){
tick1 = CurrentTicksGain();
tick2 = tick1;
lost = 0;
total = 0;
recvlen = 0;
while ((tick2 - tick1) < (TICK_PER_SECOND * 5)){
switch(getSn_SR(sock)){
case SOCK_UDP:
if ((r_size = getSn_RX_RSR(sock)) > 0){
if (r_size > IPERF_BUFSZ) r_size = IPERF_BUFSZ;
memset(buffer, 0, IPERF_BUFSZ);
wiz_sock_recvfrom(sock, buffer, r_size, client_addr, &client_port);
recvlen += r_size;
last_pcount = buffer[0] << 24 | buffer[1] << 16 | buffer[2] << 8 | buffer[3];
if(last_pcount > pcount){
total += last_pcount - pcount;
lost += last_pcount - pcount - 1;
pcount = last_pcount;
}
else if(last_pcount < 10){
pcount = last_pcount;
total = 1;
lost = 0;
}
}
tick2 = CurrentTicksGain();
break;
case SOCK_CLOSED:
wiz_socket(sock, Sn_MR_UDP, param.port, 0x00);
break;
}
}
if (recvlen > 0){
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! recv:%d lost:%d total:%d\n", tid->task_base_info.name, integer, decimal, total - lost, lost, total);
}
}
free(buffer);
if(getSn_SR(sock) != SOCK_CLOSED) wiz_sock_close(sock);
}
static void iperf_client(void *thread_param)
{
int i;
int sock = 0;
int ret;
uint8_t *send_buf, connected = 0;
uint64 sentlen;
x_ticks_t tick1, tick2;
// setSn_RXBUF_SIZE(sock, 16);
// setSn_TXBUF_SIZE(sock, 16);
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)
{
while((getSn_SR(sock) != SOCK_ESTABLISHED || !connected) && param.mode != IPERF_MODE_STOP){
switch (getSn_SR(sock)) {
case SOCK_ESTABLISHED:
if (getSn_IR(sock) & Sn_IR_CON) {
KPrintf("Connected\n", sock);
setSn_IR(sock, Sn_IR_CON);
}
connected = 1;
break;
case SOCK_CLOSE_WAIT:
wiz_sock_disconnect(sock);
break;
case SOCK_INIT:
KPrintf("Socket %d:try to connect to [%d.%d.%d.%d:%d]...",
sock, param.host[0], param.host[1], param.host[2], param.host[3], param.port);
ret = wiz_sock_connect(sock, param.host, param.port);
if (ret != SOCK_OK){
printf("failed, wait 1s to try again\n");
MdelayKTask(1000);
}
break;
case SOCK_CLOSED:
if(connected) KPrintf("Socket %d:closed\n", sock);
wiz_socket(sock, Sn_MR_TCP, param.port, 0x00);
connected = 0;
break;
default:
break;
}
}
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 = wiz_sock_send(sock, send_buf, IPERF_BUFSZ);
if (ret > 0){
sentlen += ret;
}
if (ret < 0) break;
}
if(getSn_SR(sock) != SOCK_CLOSED)wiz_sock_close(sock);
KPrintf("Disconnected, iperf client exit!");
}
free(send_buf);
}
static void iperf_server(void *thread_param)
{
uint8_t *recv_data;
x_ticks_t tick1, tick2;
int sock = -1, connected = 0, bytes_received;
uint64 recvlen;
sock = 0; //todo
// setSn_RXBUF_SIZE(sock, 16);
// setSn_TXBUF_SIZE(sock, 16);
recv_data = (uint8_t *)malloc(IPERF_BUFSZ);
if (recv_data == NULL){
KPrintf("No memory!\n");
goto __exit;
}
while (param.mode != IPERF_MODE_STOP){
while((getSn_SR(sock) != SOCK_ESTABLISHED || !connected)){
switch (getSn_SR(sock)) {
case SOCK_ESTABLISHED:
if (getSn_IR(sock) & Sn_IR_CON) {
KPrintf("Socket %d:Connected\n", sock);
setSn_IR(sock, Sn_IR_CON);
}
recvlen = 0;
tick1 = CurrentTicksGain();
connected = 1;
break;
case SOCK_CLOSE_WAIT:
wiz_sock_disconnect(sock);
break;
case SOCK_INIT:
KPrintf("Socket %d:Listen, port [%d]\n", sock, param.port);
wiz_sock_listen(sock);
break;
case SOCK_CLOSED:
if(connected) KPrintf("Socket %d:closed\n", sock);
wiz_socket(sock, Sn_MR_TCP, param.port, 0x00);
connected = 0;
break;
default:
break;
}
if(param.mode == IPERF_MODE_STOP) goto __exit;
}
if ((bytes_received = getSn_RX_RSR(sock)) > 0) {
if (bytes_received > IPERF_BUFSZ) bytes_received = IPERF_BUFSZ;
memset(recv_data, 0, IPERF_BUFSZ);
wiz_sock_recv(sock, recv_data, bytes_received);
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;
}
}
__exit:
if(getSn_SR(sock) != SOCK_CLOSED)wiz_sock_close(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 <host> run in client mode, connecting to <host>\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 <time> the number of multi-threaded \ns");
return;
}
int iperf(int argc, char **argv)
{
int mode = 0; /* server mode */
char *host = NULL;
int port = IPERF_PORT;
int numtid = 1;
int use_udp = 0;
int index = 1;
if (argc == 1)
{
goto __usage;
}
if (strcmp(argv[1], "-u") == 0)
{
index = 2;
use_udp = 1;
}
if (strcmp(argv[index], "-h") == 0) goto __usage;
else if (strcmp(argv[index], "--stop") == 0)
{
/* stop iperf */
param.mode = IPERF_MODE_STOP;
MdelayKTask(10);
return 0;
}
else if (strcmp(argv[index], "-s") == 0)
{
mode = IPERF_MODE_SERVER; /* server mode */
/* iperf -s -p 5000 */
if (argc >= 4)
{
if (strcmp(argv[index + 1], "-p") == 0)
{
port = atoi(argv[index + 2]);
}
else goto __usage;
}
}
else if (strcmp(argv[index], "-c") == 0)
{
mode = IPERF_MODE_CLIENT; /* client mode */
if (argc < 3) goto __usage;
host = argv[index + 1];
if (argc >= 5)
{
/* iperf -c host -p port */
if (strcmp(argv[index + 2], "-p") == 0)
{
port = atoi(argv[index + 3]);
}
else goto __usage;
}
}
else goto __usage;
if (argc >= 7)
{
if(strcmp(argv[argc - 2], "-m") == 0)
{
numtid = atoi(argv[argc - 1]);
}
else goto __usage;
}
/* start iperf */
if (param.mode == IPERF_MODE_STOP)
{
int i = 0;
char tid_name[NAME_NUM_MAX + 1] = {0};
param.mode = mode;
param.port = port;
if (host) {
uint32 t1,t2,t3,t4;
sscanf(host, "%d.%d.%d.%d", &t1, &t2, &t3, &t4);
param.host[0] = (uint8)t1;
param.host[1] = (uint8)t2;
param.host[2] = (uint8)t3;
param.host[3] = (uint8)t4;
}
for (i = 0; i < numtid; i++)
{
int32 tid = 0;
void (*function)(void *parameter);
if (use_udp)
{
if (mode == IPERF_MODE_CLIENT)
{
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
function = iperf_udp_client;
}
else if (mode == IPERF_MODE_SERVER)
{
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
function = iperf_udp_server;
}
}
else
{
if (mode == IPERF_MODE_CLIENT)
{
snprintf(tid_name, sizeof(tid_name), "iperfc%02d", i + 1);
function = iperf_client;
}
else if (mode == IPERF_MODE_SERVER)
{
snprintf(tid_name, sizeof(tid_name), "iperfd%02d", i + 1);
function = iperf_server;
}
}
tid = KTaskCreate(tid_name, function, NULL, 4096, 25);
if (tid) StartupKTask(tid);
MdelayKTask(10);
}
}
else
{
KPrintf("Please stop iperf firstly, by:\n");
KPrintf("iperf --stop\n");
}
return 0;
__usage:
iperf_usage();
return 0;
}
SHELL_EXPORT_CMD(SHELL_CMD_PERMISSION(0) | SHELL_CMD_TYPE(SHELL_TYPE_CMD_MAIN),
iperf, iperf,
iperf throughput test);
#endif