Hi all!!! Im working on simple file transfering from embedded board with LWIP to server via TCP. Embedde board is custom STM32 with SIM7500 GSM modem, PPP is working fine(tested with sending UDP packets with way higher speed than TCP). I'm using sockets. Right now I have huge lag when trying to receive acknolage packet from server.
Logic of transfer:
1) connect to server using TCP
2) send file size
3) receive acknolage from server (wait for packet from server)
4) start while loop
4.1) send some amount of data
4.2) wait for acknolage (same as 3)

Right now Im getting ~25kbytes/s.

Tryied to set TCP_NODELAY and TCK_QUICKACK(only on server because as far as I know lwip doesn't support this feature).

Source code of server, embedded part and lwipports.h are in attachments. Also attaching timings: time where blue line high is send, orange is for recv.

P.S. Sorry for my english.

/*
 * settings.c
 *
 *  Created on: May 6, 2021
 *      Author: maobuff
 */

#include <stdio.h>
#include <stdint.h>

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "cmsis_os.h"

static char buffer[1024 * 10];

void settings_tcp_task(void *arg) {
	int sock;
	struct sockaddr_in dest;
	ssize_t bc;

	dest.sin_addr.s_addr = inet_addr("ipofserver");
	dest.sin_family = AF_INET;
	dest.sin_port = htons(5005);

	sock = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (sock == -1) {
		printf("Failed to create socket\n");
		close(sock);
		return;
	}
	printf("Socket created\n");

	int opt = 1;
	setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void* ) &opt, sizeof(opt));

	if (connect(sock, (struct sockaddr *) &dest, sizeof(dest)) == -1) {
		printf("Failed to connect to server\n");
		close(sock);
		return;
	}
	printf("Connected to server\n");

	int file_size = 1024 * 1024 * 10;
	bc = send(sock, &file_size, sizeof(int), 0);
	if (bc <= 0) {
		printf("Failed to send file size\n");
		close(sock);
		return;
	}
	printf("File size sent\n");

	bc = recv(sock, buffer, sizeof(char), 0);
	if (bc <= 0) {
		printf("Failed receive ack\n");
		close(sock);
		return;
	}

	printf("File transfer started\n");
	while (1) {
		HAL_GPIO_WritePin(DEBUG_SEND_GPIO_Port, DEBUG_SEND_Pin, GPIO_PIN_SET);
		bc = send(sock, buffer, 1024, 0);
		if (bc <= 0) {
			printf("Failed to send file\n");
			close(sock);
			return;
		}
		HAL_GPIO_WritePin(DEBUG_SEND_GPIO_Port, DEBUG_SEND_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(DEBUG_RECV_GPIO_Port, DEBUG_RECV_Pin, GPIO_PIN_SET);
		bc = recv(sock, buffer, sizeof(char), 0);
		if (bc <= 0) {
			printf("Failed receive ack\n");
			close(sock);
			return;
		}
		HAL_GPIO_WritePin(DEBUG_RECV_GPIO_Port, DEBUG_RECV_Pin, GPIO_PIN_RESET);

		file_size -= 1024;
		if (file_size <= 0) {
			printf("Done!\n");
			close(sock);
			return;
		}
	}
}
/**
  ******************************************************************************
  * File Name          : Target/lwipopts.h
  * Description        : This file overrides LwIP stack default configuration
  *                      done in opt.h file.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
  * All rights reserved.</center></h2>
  *
  * This software component is licensed by ST under Ultimate Liberty license
  * SLA0044, the "License"; You may not use this file except in compliance with
  * the License. You may obtain a copy of the License at:
  *                             www.st.com/SLA0044
  *
  ******************************************************************************
  */

/* Define to prevent recursive inclusion --------------------------------------*/
#ifndef __LWIPOPTS__H__
#define __LWIPOPTS__H__

#include "main.h"

/*-----------------------------------------------------------------------------*/
/* Current version of LwIP supported by CubeMx: 2.1.2 -*/
/*-----------------------------------------------------------------------------*/

/* Within 'USER CODE' section, code will be kept by default at each generation */
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

#ifdef __cplusplus
 extern "C" {
#endif

/* STM32CubeMX Specific Parameters (not defined in opt.h) ---------------------*/
/* Parameters set in STM32CubeMX LwIP Configuration GUI -*/
/*----- WITH_RTOS enabled (Since FREERTOS is set) -----*/
#define WITH_RTOS 1
/*----- CHECKSUM_BY_HARDWARE enabled -----*/
#define CHECKSUM_BY_HARDWARE 0
/*-----------------------------------------------------------------------------*/

/* LwIP Stack Parameters (modified compared to initialization value in opt.h) -*/
/* Parameters set in STM32CubeMX LwIP Configuration GUI -*/
/*----- Value in opt.h for LWIP_DHCP: 0 -----*/
#define LWIP_DHCP 1
/*----- Value in opt.h for LWIP_TCP: 1 -----*/
#define LWIP_TCP 1
/*----- Value in opt.h for MEM_ALIGNMENT: 1 -----*/
#define MEM_ALIGNMENT 4
#define DEFAULT_TCP_RECVMBOX_SIZE 6
/*----- Value in opt.h for LWIP_ETHERNET: LWIP_ARP || PPPOE_SUPPORT -*/
//#define TCP_MSS 1024 * 2
/*----- Value in opt.h for LWIP_DNS_SECURE: (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_NO_MULTIPLE_OUTSTANDING | LWIP_DNS_SECURE_RAND_SRC_PORT) -*/
#define LWIP_DNS_SECURE 7
/*----- Value in opt.h for TCP_SND_QUEUELEN: (4*TCP_SND_BUF + (TCP_MSS - 1))/TCP_MSS -----*/
#define TCP_SND_QUEUELEN 9
/*----- Value in opt.h for TCP_SNDLOWAT: LWIP_MIN(LWIP_MAX(((TCP_SND_BUF)/2), (2 * TCP_MSS) + 1), (TCP_SND_BUF) - 1) -*/
#define TCP_SNDLOWAT (2 * TCP_MSS) - 1
/*----- Value in opt.h for TCP_SNDQUEUELOWAT: LWIP_MAX(TCP_SND_QUEUELEN)/2, 5) -*/
#define TCP_SNDQUEUELOWAT 5
/*----- Value in opt.h for TCP_WND_UPDATE_THRESHOLD: LWIP_MIN(TCP_WND/4, TCP_MSS*4) -----*/
#define TCP_WND_UPDATE_THRESHOLD 536
/*----- Value in opt.h for LWIP_NETIF_LINK_CALLBACK: 0 -----*/
#define LWIP_NETIF_LINK_CALLBACK 1
/*----- Value in opt.h for TCPIP_THREAD_STACKSIZE: 0 -----*/
#define TCPIP_THREAD_STACKSIZE 1024
/*----- Value in opt.h for TCPIP_THREAD_PRIO: 1 -----*/
#define TCPIP_THREAD_PRIO 24
/*----- Value in opt.h for TCPIP_MBOX_SIZE: 0 -----*/
#define TCPIP_MBOX_SIZE 6
/*----- Value in opt.h for SLIPIF_THREAD_STACKSIZE: 0 -----*/
#define SLIPIF_THREAD_STACKSIZE 1024
/*----- Value in opt.h for SLIPIF_THREAD_PRIO: 1 -----*/
#define SLIPIF_THREAD_PRIO 3
/*----- Value in opt.h for DEFAULT_THREAD_STACKSIZE: 0 -----*/
#define DEFAULT_THREAD_STACKSIZE 1024
/*----- Value in opt.h for DEFAULT_THREAD_PRIO: 1 -----*/
#define DEFAULT_THREAD_PRIO 3
/*----- Value in opt.h for DEFAULT_UDP_RECVMBOX_SIZE: 0 -----*/
#define DEFAULT_UDP_RECVMBOX_SIZE 6
/*----- Value in opt.h for DEFAULT_ACCEPTMBOX_SIZE: 0 -----*/
#define DEFAULT_ACCEPTMBOX_SIZE 6
/*----- Value in opt.h for RECV_BUFSIZE_DEFAULT: INT_MAX -----*/
#define RECV_BUFSIZE_DEFAULT 2000000000
/*----- Default Value for PPP_SUPPORT: 0 ---*/
#define PPP_SUPPORT 1
/*----- Value in opt.h for LWIP_STATS: 1 -----*/
#define LWIP_STATS 0
/*----- Value in opt.h for CHECKSUM_GEN_ICMP: 1 -----*/
#define CHECKSUM_GEN_ICMP 0
/*----- Value in opt.h for CHECKSUM_GEN_ICMP6: 1 -----*/
#define CHECKSUM_GEN_ICMP6 0
/*----- Value in opt.h for CHECKSUM_CHECK_IP: 1 -----*/
#define CHECKSUM_CHECK_IP 0
/*----- Value in opt.h for CHECKSUM_CHECK_UDP: 1 -----*/
#define CHECKSUM_CHECK_UDP 0
/*----- Value in opt.h for CHECKSUM_CHECK_TCP: 1 -----*/
#define CHECKSUM_CHECK_TCP 0
/*----- Value in opt.h for CHECKSUM_CHECK_ICMP: 1 -----*/
#define CHECKSUM_CHECK_ICMP 0
/*----- Value in opt.h for CHECKSUM_CHECK_ICMP6: 1 -----*/
#define CHECKSUM_CHECK_ICMP6 0
/*-----------------------------------------------------------------------------*/
/* USER CODE BEGIN 1 */
#define LWIP_SOCKET 1
#define LWIP_NETCONN 1
#define PPP_IPV4_SUPPORT 1
#define LWIP_DEBUG 1
//#define NETCONN_DEBUG LWIP_DBG_ON
//#define TCP_DEBUG LWIP_DBG_ON
//#define SOCKETS_DEBUG LWIP_DBG_ON
//#define PPP_DEBUG LWIP_DBG_ON
#define PAP_SUPPORT 1
/* USER CODE END 1 */

#ifdef __cplusplus
}
#endif
#endif /*__LWIPOPTS__H__ */

/************************* (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>
#include <netinet/tcp.h>

int server;

void timespec_diff(const struct timespec *start, const struct timespec *stop, struct timespec *result)
{
	if ((stop->tv_nsec - start->tv_nsec) < 0) {
		result->tv_sec = stop->tv_sec - start->tv_sec - 1;
		result->tv_nsec = stop->tv_nsec - start->tv_nsec + 1000000000L;
	} else {
		result->tv_sec = stop->tv_sec - start->tv_sec;
		result->tv_nsec = stop->tv_nsec - start->tv_nsec;
	}
}

double timespec_conv(const struct timespec *ts)
{
	return ts->tv_sec + (double) ts->tv_nsec / 1000000000L;
}

void recieve(int sock)
{
	struct timespec start, stop, result;
	char buffer[1024 * 10];
	ssize_t bc;

	int bytes;
	bc = recv(sock, &bytes, sizeof(int), 0);
	if (bc <= 0) {
		printf("Failed to receive file size\n");
		close(sock);
		return;
	}
	printf("File size: %i\n", bytes);

    bc = send(sock, buffer, sizeof(char), 0);
    if (bc <= 0) {
        printf("Failed to send ack\n");
        close(sock);
        return;
    }

	int count = 0;
	FILE *fp = fopen("/tmp/TEST", "w");

	timespec_get(&start, TIME_UTC);
	while (count < bytes) {
	    int temp = 0;
	    gtrecv:
		bc = recv(sock, buffer, sizeof(buffer), 0);
		if (bc <= 0) {
			printf("Failed to receive file\n");
			close(sock);
			return;
		}
        temp += (int) bc;
		fwrite(buffer, sizeof(char), bc, fp);
		printf("Received: %zi bytes, total: %i\n", bc, count);
		if (temp < 512)
		    goto gtrecv;
		count += temp;
		bc = send(sock, buffer, sizeof(char), 0);
		if (bc <= 0) {
			printf("Failed to send ack\n");
			close(sock);
			return;
		}
	}
	timespec_get(&stop, TIME_UTC);
	timespec_diff(&start, &stop, &result);
	printf("time: %g\n", timespec_conv(&result));
	printf("speed: %g\n", (count / timespec_conv(&result)) / (1024 * 1024 / 8));
	fclose(fp);

	close(sock);
}

void cli()
{
	int conn;
	struct sockaddr_in server_addr, cl;

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(5005);

	server = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
	if (server == -1) {
		printf("Failed creating socket\n");
		close(server);
		return;
	}

	int err;
	int opt = 1;
    err = setsockopt(server, IPPROTO_TCP, TCP_QUICKACK, (void *) &opt, sizeof(opt));
    if (err == -1) {
        printf("Failed to set socket to TCP_QUICKACK\n");
        close(server);
        return;
    }

    int opt2 = 1;
    err = setsockopt(server, IPPROTO_TCP, TCP_NODELAY, (void *) &opt2, sizeof(opt2));
    if (err == -1) {
        printf("Failed to set socket to TCP_NODELAY\n");
        close(server);
        return;
    }

	if ((bind(server, (struct sockaddr *) &server_addr, sizeof(server_addr))) != 0) {
		printf("Failed binding socket\n");
		close(server);
		return;
	}

	if ((listen(server, 5)) != 0) {
		printf("Failed to start listening socket\n");
		close(server);
		return;
	}

	socklen_t len = sizeof(cl);
	conn = accept(server, (struct sockaddr *) &cl, &len);
	if (conn <= 0) {
		printf("Failed to accept client\n");
		close(server);
		return;
	}

	recieve(conn);

	close(server);
}

void handler(int c)
{
	close(server);
	exit(EXIT_SUCCESS);
}

int main(void)
{
	struct sigaction act;
	act.sa_handler = handler;
	sigaction(SIGINT, &act, NULL);
	sigaction(SIGTERM, &act, NULL);

	cli();
	handler(0);
	return 0;
}
_______________________________________________
lwip-users mailing list
lwip-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users

Reply via email to