This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

LTE TCP socket stability testing

I am trying to design some test cases to check the LTE stability and performance. 

I avoid to use the existing Nordic samples to do this as they are too complicate for the testing purposes. 
Here is a test case I've made to test the LTE TCP communication stability. It borrows the idea from the samples of asset_tracker, at_client and tcp. TCP is the prime feature on which TLS, MQTT are based. The test case does the following things:
  1) start the LTE modem
  2) establish a simple TCP connection to a cloud server
  3) periodically (10s) monitor the modem status
  4) periodically (10s) send 2 bytes of payload to the server
I want to see how long the connection can last. 
To build the code, please replace nrf\samples\nrf9160\asset_tracker\src\main.c with the attached main.c. Then rebuild asset_tracker. 
You can see the log in fail1.log attached.
I've run this testing code in a Nordic board (v.07.0) and our own board. Both of them show similar result.
The testing result is inconsistent. Sometime it ran only a few loops (the attached fail1.log is of such kind). Sometime it ran longer. Usually it wouldn't exceed 100 loops. 
When it started to fail, it was usually stuck at recv() which is used to receive AT commands. recv() has been configured with the non-block mode so supposedly it should always return.
Occasionally, it was stuck at connect() when creating TCP connection at boot up.
My questions:
1) is this a proper test case for testing LTE/network stability?
2) is anything missed in the coding for correctly configuring the modem?
3) does the test result meet your expectation?
4) has Nordic done similar testing?
Best,
Kai
#include <zephyr.h>
#include <stdio.h>
#include <string.h>
#include <gps.h>
#include <sensor.h>
#include <console.h>
#include <nrf_cloud.h>
#include <dk_buttons_and_leds.h>
#include <lte_lc.h>
#include <misc/reboot.h>
#include <bsd.h>
#include "nrf_socket.h"
#include "orientation_detector.h"
#include <net/socket.h>
#include <sys/time.h>


#define TCP_HOST "45.33.53.75"
#define TCP_PORT 9090


#define LC_MAX_READ_LENGTH1 128
#define AT_CMD_SIZE1(x) (sizeof(x) - 1)

static const char subscribe[] = "AT+CEREG=2";
static const char psm_disable[] = "AT+CPSMS=0";
static const char normal[] = "AT+CFUN=1";
static const char success[] = "OK";
static const char status1[] = "+CEREG: 1";
static const char status2[] = "+CEREG:1";
static const char status3[] = "+CEREG: 5";
static const char status4[] = "+CEREG:5";

static int at_cmd1(int fd, const char *cmd, size_t size)
{
	int len;
	u8_t buffer[LC_MAX_READ_LENGTH1];

	printk("====AT send (%d bytes): %s\n", strlen(cmd), cmd);
	len = send(fd, cmd, size, 0);
	if (len != size) {
		printk("***ERROR: AT send: failed, ret=%d.\n", len);
		return -1;
	}

	for (int i=0; i<50; i++)		// wait for 5s
	{
		len = recv(fd, buffer, LC_MAX_READ_LENGTH1, MSG_DONTWAIT);
		if (len > 0)
		{
			printk("====AT receive (%d bytes): %s", strlen(buffer), buffer);
			return 0;
		} 
		k_sleep(K_MSEC(100));
	}
	printk("**********AT receive ERROR.\n");
	return -1;
}

void main(void)
{
	printk("Application started\n");

	int err;
	int at_socket_fd;
	u8_t buffer[LC_MAX_READ_LENGTH1];


	// create AT socket
	at_socket_fd = socket(AF_LTE, 0, NPROTO_AT);

	// start modem
	at_cmd1(at_socket_fd, subscribe, AT_CMD_SIZE1(subscribe));
	at_cmd1(at_socket_fd, psm_disable, AT_CMD_SIZE1(psm_disable));
	at_cmd1(at_socket_fd, normal, AT_CMD_SIZE1(normal));

	// wait for LET connection ready
	printk("LTE connecting ...\n");
	while (true) {
		int bytes;
		bytes = recv(at_socket_fd, buffer, LC_MAX_READ_LENGTH1, 0);
		if (bytes) {
			buffer[bytes] = 0;
			printk("====AT receive (%d bytes): %s", bytes, buffer);
			if (!memcmp(status1, buffer, AT_CMD_SIZE1(status1)) ||
			    !memcmp(status2, buffer, AT_CMD_SIZE1(status2)) ||
			    !memcmp(status3, buffer, AT_CMD_SIZE1(status3)) ||
			    !memcmp(status4, buffer, AT_CMD_SIZE1(status4))) {
				break;
			}
		}
	}
	printk("\nLTE connected\n\n");


	// get server IP address
	struct addrinfo * server_addr;
	err = getaddrinfo(TCP_HOST, NULL, NULL, &server_addr);
	if (err != 0)
	{
		printk("***ERROR: failed to get server IP address\n");
		return 0;
	}

	// print server IP address
	{
		u8_t * p2 = &(((struct sockaddr_in *)server_addr->ai_addr)->sin_addr.s_addr);
		printk("server IP addr=%d.%d.%d.%d\n", p2[0], p2[1], p2[2], p2[3]);
	}

	// set server TCP listening port
	((struct sockaddr_in *)server_addr->ai_addr)->sin_port = htons(TCP_PORT);

	// create & bind TCP socket
	int tcp_socket_fd;
	{
		tcp_socket_fd = socket(AF_INET, SOCK_STREAM, 0);

		struct sockaddr_in local_addr;
		local_addr.sin_family = AF_INET;
		local_addr.sin_port = htons(0);
		local_addr.sin_addr.s_addr = 0;
		err = bind(tcp_socket_fd, (struct sockaddr *)&local_addr, sizeof(local_addr));
		if (err != 0)
		{
			printk("TCP sokcet bind err: %d\n\r", err);
			return;
		}
	}

	// connect to server
	while(1) 
	{
		printk("\nTCP connect()...\n");
		err = connect(tcp_socket_fd, (struct sockaddr *)server_addr->ai_addr, sizeof(struct sockaddr_in));
		if (err == 0)
		{
			printk("TCP connect() succeeded\n\n");
			break;
		}
		k_sleep(K_MSEC(1000));	// delay 1s
	} 

	// check modem status; send TCP data to server

	int loop = 1;
	while(1) 
	{
		// read AT socket to see if there is any data; with non-block mode read
		while (true) 
		{
			int bytes;
			bytes = recv(at_socket_fd, buffer, LC_MAX_READ_LENGTH1, MSG_DONTWAIT );
			if (bytes <= 0) 
				break;
			buffer[bytes] = 0;
			printk("====AT receive (%d bytes): %s", bytes, buffer);
		}

		printk("---------------------------------------- %d\n", loop++);

		// send AT command to check modem status
//		at_cmd1(at_socket_fd, "AT%XCBAND", AT_CMD_SIZE1("AT%XCBAND"));
		at_cmd1(at_socket_fd, "AT+CESQ", AT_CMD_SIZE1("AT+CESQ"));
		at_cmd1(at_socket_fd, "AT+CEREG?", AT_CMD_SIZE1("AT+CEREG?"));
		at_cmd1(at_socket_fd, "AT+CGDCONT?", AT_CMD_SIZE1("AT+CGDCONT?"));

		// send TCP data to server
#if 1
		static char buf[] = {"a"};
		static int len = sizeof(buf);
		err = send(tcp_socket_fd, buf, len, 0);
		if (err != len)
			printk("**********TCP send: error=%d.\n", err);
		else
			printk("====TCP send (%d bytes)\n", len);
#endif

		// sleep 10s
		k_sleep(K_MSEC(10000));
	}

	close(at_socket_fd);
	return 0;
}

***** Booting Zephyr OS v1.13.99-ncs2 *****
Secure Boot: configure flash
Secure Boot: SPU: set region 0 as Secure
Secure Boot: SPU: set region 1 as Secure
Secure Boot: SPU: set region 2 as Secure
Secure Boot: SPU: set region 3 as Secure
Secure Boot: SPU: set region 4 as Secure
Secure Boot: SPU: set region 5 as Secure
Secure Boot: SPU: set region 6 as Secure
Secure Boot: SPU: set region 7 as Secure
Secure Boot: SPU: set Flash region 8 as Non-Secure
Secure Boot: SPU: set Flash region 9 as Non-Secure
Secure Boot: SPU: set Flash region 10 as Non-Secure
Secure Boot: SPU: set Flash region 11 as Non-Secure
Secure Boot: SPU: set Flash region 12 as Non-Secure
Secure Boot: SPU: set Flash region 13 as Non-Secure
Secure Boot: SPU: set Flash region 14 as Non-Secure
Secure Boot: SPU: set Flash region 15 as Non-Secure
Secure Boot: SPU: set Flash region 16 as Non-Secure
Secure Boot: SPU: set Flash region 17 as Non-Secure
Secure Boot: SPU: set Flash region 18 as Non-Secure
Secure Boot: SPU: set Flash region 19 as Non-Secure
Secure Boot: SPU: set Flash region 20 as Non-Secure
Secure Boot: SPU: set Flash region 21 as Non-Secure
Secure Boot: SPU: set Flash region 22 as Non-Secure
Secure Boot: SPU: set Flash region 23 as Non-Secure
Secure Boot: SPU: set Flash region 24 as Non-Secure
Secure Boot: SPU: set Flash region 25 as Non-Secure
Secure Boot: SPU: set Flash region 26 as Non-Secure
Secure Boot: SPU: set Flash region 27 as Non-Secure
Secure Boot: SPU: set Flash region 28 as Non-Secure
Secure Boot: SPU: set Flash region 29 as Non-Secure
Secure Boot: SPU: set Flash region 30 as Non-Secure
Secure Boot: SPU: set Flash region 31 as Non-Secure
Secure Boot: configure SRAM
Secure Boot: SPU: set SRAM region 0 as Secure
Secure Boot: SPU: set SRAM region 1 as Secure
Secure Boot: SPU: set SRAM region 2 as Secure
Secure Boot: SPU: set SRAM region 3 as Secure
Secure Boot: SPU: set SRAM region 4 as Secure
Secure Boot: SPU: set SRAM region 5 as Secure
Secure Boot: SPU: set SRAM region 6 as Secure
Secure Boot: SPU: set SRAM region 7 as Secure
Secure Boot: SPU: set SRAM region 8 as Non-Secure
Secure Boot: SPU: set SRAM region 9 as Non-Secure
Secure Boot: SPU: set SRAM region 10 as Non-Secure
Secure Boot: SPU: set SRAM region 11 as Non-Secure
Secure Boot: SPU: set SRAM region 12 as Non-Secure
Secure Boot: SPU: set SRAM region 13 as Non-Secure
Secure Boot: SPU: set SRAM region 14 as Non-Secure
Secure Boot: SPU: set SRAM region 15 as Non-Secure
Secure Boot: SPU: set SRAM region 16 as Non-Secure
Secure Boot: SPU: set SRAM region 17 as Non-Secure
Secure Boot: SPU: set SRAM region 18 as Non-Secure
Secure Boot: SPU: set SRAM region 19 as Non-Secure
Secure Boot: SPU: set SRAM region 20 as Non-Secure
Secure Boot: SPU: set SRAM region 21 as Non-Secure
Secure Boot: SPU: set SRAM region 22 as Non-Secure
Secure Boot: SPU: set SRAM region 23 as Non-Secure
Secure Boot: SPU: set SRAM region 24 as Non-Secure
Secure Boot: SPU: set SRAM region 25 as Non-Secure
Secure Boot: SPU: set SRAM region 26 as Non-Secure
Secure Boot: SPU: set SRAM region 27 as Non-Secure
Secure Boot: SPU: set SRAM region 28 as Non-Secure
Secure Boot: SPU: set SRAM region 29 as Non-Secure
Secure Boot: SPU: set SRAM region 30 as Non-Secure
Secure Boot: SPU: set SRAM region 31 as Non-Secure
Secure Boot: configure peripherals
Secure Boot: MSP_NS 20029828
Secure Boot: prepare to jump to Non-Secure image
***** Booting Zephyr OS v1.13.99-ncs2 *****
Application started
====AT send (10 bytes): AT+CEREG=2
====AT receive (4 bytes): OK
====AT send (10 bytes): AT+CPSMS=0
====AT receive (4 bytes): OK
====AT send (9 bytes): AT+CFUN=1
====AT receive (4 bytes): OK
LTE connecting ...
====AT receive (32 bytes): +CEREG: 2,"2005","00803103",7
====AT receive (32 bytes): +CEREG: 1,"2005","00803103",7

LTE connected

server IP addr=45.33.53.75

TCP connect()...
TCP connect() succeeded

---------------------------------------- 1
====AT send (7 bytes): AT+CESQ
====AT receive (33 bytes): +CESQ: 99,99,255,255,255,51
OK
====AT send (9 bytes): AT+CEREG?
====AT receive (37 bytes): +CEREG: 2,1,"2005","00803103",7
OK
====AT send (11 bytes): AT+CGDCONT?
====AT receive (101 bytes): +CGDCONT: 0,"IPV4V6","vzwinternet","100.88.205.249 2600:1010:B007:C50D:0000:0057:158A:9F01",0,0
OK
====TCP send (2 bytes)
---------------------------------------- 2
====AT send (7 bytes): AT+CESQ
====AT receive (33 bytes): +CESQ: 99,99,255,255,255,51
OK
====AT send (9 bytes): AT+CEREG?
====AT receive (37 bytes): +CEREG: 2,1,"2005","00803103",7
OK
====AT send (11 bytes): AT+CGDCONT?
====AT receive (101 bytes): +CGDCONT: 0,"IPV4V6","vzwinternet","100.88.205.249 2600:1010:B007:C50D:0000:0057:158A:9F01",0,0
OK
====TCP send (2 bytes)
---------------------------------------- 3
====AT send (7 bytes): AT+CESQ
====AT receive (33 bytes): +CESQ: 99,99,255,255,255,51
OK
====AT send (9 bytes): AT+CEREG?
====AT receive (37 bytes): +CEREG: 2,1,"2005","00803103",7
OK
====AT send (11 bytes): AT+CGDCONT?
====AT receive (101 bytes): +CGDCONT: 0,"IPV4V6","vzwinternet","100.88.205.249 2600:1010:B007:C50D:0000:0057:158A:9F01",0,0
OK
====TCP send (2 bytes)
---------------------------------------- 4
====AT send (7 bytes): AT+CESQ
Related