Skip to content

Commit 39714f3

Browse files
committed
lwip - Added parallel versions of the packet pressure tests
1 parent 8e7a3c8 commit 39714f3

File tree

2 files changed

+572
-0
lines changed
  • features/FEATURE_LWIP/TESTS/mbedmicro-net

2 files changed

+572
-0
lines changed
Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
#if !FEATURE_LWIP
2+
#error [NOT_SUPPORTED] LWIP not supported for this target
3+
#endif
4+
5+
#include "mbed.h"
6+
#include "EthernetInterface.h"
7+
#include "TCPSocket.h"
8+
#include "greentea-client/test_env.h"
9+
#include "unity/unity.h"
10+
11+
12+
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN
13+
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN 64
14+
#endif
15+
16+
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX
17+
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX 0x80000
18+
#endif
19+
20+
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED
21+
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED 0x6d626564
22+
#endif
23+
24+
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS
25+
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS 3
26+
#endif
27+
28+
#ifndef MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG
29+
#define MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG false
30+
#endif
31+
32+
33+
// Simple xorshift pseudorandom number generator
34+
class RandSeq {
35+
private:
36+
uint32_t x;
37+
uint32_t y;
38+
static const int A = 15;
39+
static const int B = 18;
40+
static const int C = 11;
41+
42+
public:
43+
RandSeq(uint32_t seed=MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_SEED)
44+
: x(seed), y(seed) {}
45+
46+
uint32_t next(void) {
47+
x ^= x << A;
48+
x ^= x >> B;
49+
x ^= y ^ (y >> C);
50+
return x + y;
51+
}
52+
53+
void skip(size_t size) {
54+
for (size_t i = 0; i < size; i++) {
55+
next();
56+
}
57+
}
58+
59+
void buffer(uint8_t *buffer, size_t size) {
60+
RandSeq lookahead = *this;
61+
62+
for (size_t i = 0; i < size; i++) {
63+
buffer[i] = lookahead.next() & 0xff;
64+
}
65+
}
66+
67+
int cmp(uint8_t *buffer, size_t size) {
68+
RandSeq lookahead = *this;
69+
70+
for (size_t i = 0; i < size; i++) {
71+
int diff = buffer[i] - (lookahead.next() & 0xff);
72+
if (diff != 0) {
73+
return diff;
74+
}
75+
}
76+
return 0;
77+
}
78+
};
79+
80+
81+
// Tries to get the biggest buffer possible on the device. Exponentially
82+
// grows a buffer until heap runs out of space, and uses half to leave
83+
// space for the rest of the program
84+
void generate_buffer(uint8_t **buffer, size_t *size, size_t min, size_t max) {
85+
size_t i = min;
86+
while (i < max) {
87+
void *b = malloc(i);
88+
if (!b) {
89+
i /= 4;
90+
if (i < min) {
91+
i = min;
92+
}
93+
break;
94+
}
95+
free(b);
96+
i *= 2;
97+
}
98+
99+
*buffer = (uint8_t *)malloc(i);
100+
*size = i;
101+
TEST_ASSERT(buffer);
102+
}
103+
104+
105+
// Global variables shared between pressure tests
106+
EthernetInterface net;
107+
SocketAddress tcp_addr;
108+
Timer timer;
109+
Mutex iomutex;
110+
111+
// Single instance of a pressure test
112+
class PressureTest {
113+
private:
114+
uint8_t *buffer;
115+
size_t buffer_size;
116+
117+
TCPSocket sock;
118+
Thread thread;
119+
120+
public:
121+
PressureTest(uint8_t *buffer, size_t buffer_size)
122+
: buffer(buffer), buffer_size(buffer_size) {
123+
}
124+
125+
void start() {
126+
osStatus status = thread.start(callback(this, &PressureTest::run));
127+
TEST_ASSERT_EQUAL(osOK, status);
128+
}
129+
130+
void join() {
131+
osStatus status = thread.join();
132+
TEST_ASSERT_EQUAL(osOK, status);
133+
}
134+
135+
void run() {
136+
// Tests exponentially growing sequences
137+
for (size_t size = MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN;
138+
size < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX;
139+
size *= 2) {
140+
int err = sock.open(&net);
141+
TEST_ASSERT_EQUAL(0, err);
142+
err = sock.connect(tcp_addr);
143+
TEST_ASSERT_EQUAL(0, err);
144+
iomutex.lock();
145+
printf("TCP: %s:%d streaming %d bytes\r\n",
146+
tcp_addr.get_ip_address(), tcp_addr.get_port(), size);
147+
iomutex.unlock();
148+
149+
sock.set_blocking(false);
150+
151+
// Loop to send/recv all data
152+
RandSeq tx_seq;
153+
RandSeq rx_seq;
154+
size_t rx_count = 0;
155+
size_t tx_count = 0;
156+
157+
while (tx_count < size || rx_count < size) {
158+
// Send out data
159+
if (tx_count < size) {
160+
size_t chunk_size = size - tx_count;
161+
if (chunk_size > buffer_size) {
162+
chunk_size = buffer_size;
163+
}
164+
165+
tx_seq.buffer(buffer, chunk_size);
166+
int td = sock.send(buffer, chunk_size);
167+
TEST_ASSERT(td > 0 || td == NSAPI_ERROR_WOULD_BLOCK);
168+
if (td > 0) {
169+
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
170+
iomutex.lock();
171+
printf("TCP: tx -> %d\r\n", td);
172+
iomutex.unlock();
173+
}
174+
tx_seq.skip(td);
175+
tx_count += td;
176+
}
177+
}
178+
179+
// Verify recieved data
180+
if (rx_count < size) {
181+
int rd = sock.recv(buffer, buffer_size);
182+
TEST_ASSERT(rd > 0 || rd == NSAPI_ERROR_WOULD_BLOCK);
183+
if (rd > 0) {
184+
if (MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_DEBUG) {
185+
iomutex.lock();
186+
printf("TCP: rx <- %d\r\n", rd);
187+
iomutex.unlock();
188+
}
189+
int diff = rx_seq.cmp(buffer, rd);
190+
TEST_ASSERT_EQUAL(0, diff);
191+
rx_seq.skip(rd);
192+
rx_count += rd;
193+
}
194+
}
195+
}
196+
197+
err = sock.close();
198+
TEST_ASSERT_EQUAL(0, err);
199+
}
200+
}
201+
};
202+
203+
PressureTest *pressure_tests[MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS];
204+
205+
206+
int main() {
207+
GREENTEA_SETUP(60, "tcp_echo");
208+
209+
uint8_t *buffer;
210+
size_t buffer_size;
211+
generate_buffer(&buffer, &buffer_size,
212+
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN,
213+
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX);
214+
215+
size_t buffer_subsize = buffer_size / MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS;
216+
printf("MBED: Generated buffer %d\r\n", buffer_size);
217+
printf("MBED: Split into %d buffers %d\r\n",
218+
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS,
219+
buffer_subsize);
220+
221+
int err = net.connect();
222+
TEST_ASSERT_EQUAL(0, err);
223+
224+
printf("MBED: TCPClient IP address is '%s'\n", net.get_ip_address());
225+
printf("MBED: TCPClient waiting for server IP and port...\n");
226+
227+
greentea_send_kv("target_ip", net.get_ip_address());
228+
229+
bool result = true;
230+
231+
char recv_key[] = "host_port";
232+
char ipbuf[60] = {0};
233+
char portbuf[16] = {0};
234+
unsigned int port = 0;
235+
236+
greentea_send_kv("host_ip", " ");
237+
greentea_parse_kv(recv_key, ipbuf, sizeof(recv_key), sizeof(ipbuf));
238+
239+
greentea_send_kv("host_port", " ");
240+
greentea_parse_kv(recv_key, portbuf, sizeof(recv_key), sizeof(ipbuf));
241+
sscanf(portbuf, "%u", &port);
242+
243+
printf("MBED: Server IP address received: %s:%d \n", ipbuf, port);
244+
tcp_addr.set_ip_address(ipbuf);
245+
tcp_addr.set_port(port);
246+
247+
timer.start();
248+
249+
// Startup pressure tests in parallel
250+
for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) {
251+
pressure_tests[i] = new PressureTest(&buffer[i*buffer_subsize], buffer_subsize);
252+
pressure_tests[i]->start();
253+
}
254+
255+
for (int i = 0; i < MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS; i++) {
256+
pressure_tests[i]->join();
257+
delete pressure_tests[i];
258+
}
259+
260+
timer.stop();
261+
printf("MBED: Time taken: %fs\r\n", timer.read());
262+
printf("MBED: Speed: %.3fkb/s\r\n",
263+
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_THREADS*
264+
8*(2*MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MAX -
265+
MBED_CFG_TCP_CLIENT_PACKET_PRESSURE_MIN) / (1000*timer.read()));
266+
267+
net.disconnect();
268+
GREENTEA_TESTSUITE_RESULT(result);
269+
}

0 commit comments

Comments
 (0)