diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo_client.py b/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo.py similarity index 94% rename from features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo_client.py rename to features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo.py index 44ac15df25..8a528dbee9 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo_client.py +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/tcp_echo.py @@ -33,24 +33,18 @@ class TCPEchoClientHandler(BaseRequestHandler): Note: reason for not echoing data back after receiving {{end}} is that send fails raising a SocketError as client closes connection. """ - print ("HOST: TCPEchoClient_Handler: Connection received...") while self.server.isrunning(): try: data = self.recv() if not data: break except Exception as e: - print ('HOST: TCPEchoClient_Handler recv error: %s' % str(e)) break - print ('HOST: TCPEchoClient_Handler: Rx: \n%s\n' % data) - try: # echo data back to the client self.send(data) except Exception as e: - print ('HOST: TCPEchoClient_Handler send error: %s' % str(e)) break - print 'Connection finished' def recv(self): """ diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo_client.py b/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo.py similarity index 98% rename from features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo_client.py rename to features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo.py index 9be3562da5..e63195ae4a 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo_client.py +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/host_tests/udp_echo.py @@ -28,7 +28,6 @@ class UDPEchoClientHandler(BaseRequestHandler): """ UDP packet handler. Echoes data back to sender's address. """ data, sock = self.request - print ('HOST: UDPEchoClientHandler: Rx: \n%s\n' % data) sock.sendto(data, self.client_address) diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_client_echo/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp similarity index 98% rename from features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_client_echo/main.cpp rename to features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp index 3b09657fbc..69a1564dc0 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_client_echo/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_echo/main.cpp @@ -30,7 +30,7 @@ void prep_buffer(char *tx_buffer, size_t tx_size) { } int main() { - GREENTEA_SETUP(20, "tcp_echo_client"); + GREENTEA_SETUP(20, "tcp_echo"); EthernetInterface eth; eth.connect(); diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_client_hello_world/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp similarity index 100% rename from features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_client_hello_world/main.cpp rename to features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_hello_world/main.cpp diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp new file mode 100644 index 0000000000..cd852d5d37 --- /dev/null +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/tcp_packet_pressure/main.cpp @@ -0,0 +1,168 @@ +#if !FEATURE_LWIP + #error [NOT_SUPPORTED] LWIP not supported for this target +#endif + +#include "mbed.h" +#include "EthernetInterface.h" +#include "TCPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" + + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_BUFFER +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_BUFFER 8192 +#endif + +#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + for (size_t i = 0; i < size; i++) { + buffer[i] = next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t buffer[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_BUFFER] = {0}; + +int main() { + GREENTEA_SETUP(60, "tcp_echo"); + + EthernetInterface eth; + int err = eth.connect(); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: TCPClient IP address is '%s'\n", eth.get_ip_address()); + printf("MBED: TCPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", eth.get_ip_address()); + + bool result = true; + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + TCPSocket sock; + SocketAddress tcp_addr(ipbuf, port); + + Timer timer; + timer.start(); + + for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(ð); + TEST_ASSERT_EQUAL(0, err); + err = sock.connect(tcp_addr); + TEST_ASSERT_EQUAL(0, err); + printf("TCP: Connected to %s:%d\r\n", ipbuf, port); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + + while (tx_count < size || rx_count < size) { + if (tx_count < size) { + RandSeq chunk_seq = tx_seq; + size_t chunk_size = size - tx_count; + if (chunk_size > sizeof(buffer)) { + chunk_size = sizeof(buffer); + } + + chunk_seq.buffer(buffer, chunk_size); + int td = sock.send(buffer, chunk_size); + TEST_ASSERT(td > 0 || td == NSAPI_ERROR_WOULD_BLOCK); + if (td > 0) { + printf("TCP: tx -> %d\r\n", td); + tx_seq.skip(td); + tx_count += td; + } + } + + if (rx_count < size) { + int rd = sock.recv(buffer, sizeof(buffer)); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + if (rd > 0) { + printf("TCP: rx <- %d\r\n", rd); + int diff = rx_seq.cmp(buffer, rd); + TEST_ASSERT_EQUAL(0, diff); + rx_count += rd; + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %fkb/s\r\n", + 8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / 1000*timer.read()); + + eth.disconnect(); + GREENTEA_TESTSUITE_RESULT(result); +} diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_client/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp similarity index 97% rename from features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_client/main.cpp rename to features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp index cb91d4fb91..73fb02875a 100644 --- a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo_client/main.cpp +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_echo/main.cpp @@ -29,7 +29,7 @@ void prep_buffer(char *tx_buffer, size_t tx_size) { } int main() { - GREENTEA_SETUP(20, "udp_echo_client"); + GREENTEA_SETUP(20, "udp_echo"); EthernetInterface eth; eth.connect(); diff --git a/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp new file mode 100644 index 0000000000..4e0ad6b14d --- /dev/null +++ b/features/FEATURE_LWIP/TESTS/mbedmicro-net/udp_packet_pressure/main.cpp @@ -0,0 +1,192 @@ +#if !FEATURE_LWIP + #error [NOT_SUPPORTED] LWIP not supported for this target +#endif + +#include "mbed.h" +#include "EthernetInterface.h" +#include "UDPSocket.h" +#include "greentea-client/test_env.h" +#include "unity/unity.h" + + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN 64 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX 0x80000 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_BUFFER +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_BUFFER 8192 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT 100 +#endif + +#ifndef MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED +#define MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564 +#endif + + +// Simple xorshift pseudorandom number generator +class RandSeq { +private: + uint32_t x; + uint32_t y; + static const int A = 15; + static const int B = 18; + static const int C = 11; + +public: + RandSeq(uint32_t seed=MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_SEED) + : x(seed), y(seed) {} + + uint32_t next(void) { + x ^= x << A; + x ^= x >> B; + x ^= y ^ (y >> C); + return x + y; + } + + void skip(size_t size) { + for (size_t i = 0; i < size; i++) { + next(); + } + } + + void buffer(uint8_t *buffer, size_t size) { + for (size_t i = 0; i < size; i++) { + buffer[i] = next() & 0xff; + } + } + + int cmp(uint8_t *buffer, size_t size) { + for (size_t i = 0; i < size; i++) { + int diff = buffer[i] - (next() & 0xff); + if (diff != 0) { + return diff; + } + } + return 0; + } +}; + +// Shared buffer for network transactions +uint8_t buffer[MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_BUFFER] = {0}; + +int main() { + GREENTEA_SETUP(60, "udp_echo"); + + EthernetInterface eth; + int err = eth.connect(); + TEST_ASSERT_EQUAL(0, err); + + printf("MBED: UDPClient IP address is '%s'\n", eth.get_ip_address()); + printf("MBED: UDPClient waiting for server IP and port...\n"); + + greentea_send_kv("target_ip", eth.get_ip_address()); + + bool result = true; + + char recv_key[] = "host_port"; + char ipbuf[60] = {0}; + char portbuf[16] = {0}; + unsigned int port = 0; + + greentea_send_kv("host_ip", " "); + greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf)); + + greentea_send_kv("host_port", " "); + greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf)); + sscanf(portbuf, "%u", &port); + + printf("MBED: Server IP address received: %s:%d \n", ipbuf, port); + + UDPSocket sock; + SocketAddress udp_addr(ipbuf, port); + + Timer timer; + timer.start(); + + for (size_t size = MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN; + size < MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX; + size *= 2) { + err = sock.open(ð); + TEST_ASSERT_EQUAL(0, err); + printf("UDP: Connected to %s:%d\r\n", ipbuf, port); + + sock.set_blocking(false); + + // Loop to send/recv all data + RandSeq tx_seq; + RandSeq rx_seq; + size_t rx_count = 0; + size_t tx_count = 0; + size_t buffer_size = sizeof(buffer); + RandSeq known_seq = rx_seq; + int known_time = timer.read_ms(); + + while (tx_count < size || rx_count < size) { + if (tx_count < size) { + RandSeq chunk_seq = tx_seq; + size_t chunk_size = size - tx_count; + if (chunk_size > buffer_size) { + chunk_size = buffer_size; + } + + chunk_seq.buffer(buffer, chunk_size); + int td = sock.sendto(udp_addr, buffer, chunk_size); + TEST_ASSERT(td > 0 || td == NSAPI_ERROR_WOULD_BLOCK); + if (td > 0) { + printf("UDP: tx -> %d\r\n", td); + tx_seq.skip(td); + tx_count += td; + } + } + + if (rx_count < size) { + int rd = sock.recvfrom(NULL, buffer, sizeof(buffer)); + TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK); + + bool error = (timer.read_ms() - known_time > + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_TIMEOUT); + + if (rd > 0) { + error = (rx_seq.cmp(buffer, rd) != 0); + printf("UDP: rx <- %d %s\r\n", rd, error ? "x" : ""); + + if (!error) { + known_seq = rx_seq; + known_time = timer.read_ms(); + rx_count += rd; + } + } + + // Dropped packet or out of order, revert to last good sequence + // and cut buffer in half + if (error) { + rx_seq = known_seq; + tx_seq = known_seq; + tx_count = rx_count; + if (buffer_size > MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) { + buffer_size /= 2; + } + } + } + } + + err = sock.close(); + TEST_ASSERT_EQUAL(0, err); + } + + timer.stop(); + printf("MBED: Time taken: %fs\r\n", timer.read()); + printf("MBED: Speed: %fkb/s\r\n", + 8*(2*MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MAX - + MBED_CFG_UDP_CLIENT_PACKET_PRESSURE_MIN) / 1000*timer.read()); + + eth.disconnect(); + GREENTEA_TESTSUITE_RESULT(result); +}