1 #include "test_tcp.h"
2
3 #include "lwip/tcp_impl.h"
4 #include "lwip/stats.h"
5 #include "tcp_helper.h"
6
7 #ifdef _MSC_VER
8 #pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */
9 #endif
10
11 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
12 #error "This tests needs TCP- and MEMP-statistics enabled"
13 #endif
14 #if TCP_SND_BUF <= TCP_WND
15 #error "This tests needs TCP_SND_BUF to be > TCP_WND"
16 #endif
17
18 static u8_t test_tcp_timer;
19
20 /* our own version of tcp_tmr so we can reset fast/slow timer state */
21 static void
test_tcp_tmr(void)22 test_tcp_tmr(void)
23 {
24 tcp_fasttmr();
25 if (++test_tcp_timer & 1) {
26 tcp_slowtmr();
27 }
28 }
29
30 /* Setups/teardown functions */
31
32 static void
tcp_setup(void)33 tcp_setup(void)
34 {
35 /* reset iss to default (6510) */
36 tcp_ticks = 0;
37 tcp_ticks = 0 - (tcp_next_iss() - 6510);
38 tcp_next_iss();
39 tcp_ticks = 0;
40
41 test_tcp_timer = 0;
42 tcp_remove_all();
43 }
44
45 static void
tcp_teardown(void)46 tcp_teardown(void)
47 {
48 netif_list = NULL;
49 tcp_remove_all();
50 }
51
52
53 /* Test functions */
54
55 /** Call tcp_new() and tcp_abort() and test memp stats */
START_TEST(test_tcp_new_abort)56 START_TEST(test_tcp_new_abort)
57 {
58 struct tcp_pcb* pcb;
59 LWIP_UNUSED_ARG(_i);
60
61 fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
62
63 pcb = tcp_new();
64 fail_unless(pcb != NULL);
65 if (pcb != NULL) {
66 fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
67 tcp_abort(pcb);
68 fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
69 }
70 }
71 END_TEST
72
73 /** Create an ESTABLISHED pcb and check if receive callback is called */
START_TEST(test_tcp_recv_inseq)74 START_TEST(test_tcp_recv_inseq)
75 {
76 struct test_tcp_counters counters;
77 struct tcp_pcb* pcb;
78 struct pbuf* p;
79 char data[] = {1, 2, 3, 4};
80 ip_addr_t remote_ip, local_ip;
81 u16_t data_len;
82 u16_t remote_port = 0x100, local_port = 0x101;
83 struct netif netif;
84 LWIP_UNUSED_ARG(_i);
85
86 /* initialize local vars */
87 memset(&netif, 0, sizeof(netif));
88 IP4_ADDR(&local_ip, 192, 168, 1, 1);
89 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
90 data_len = sizeof(data);
91 /* initialize counter struct */
92 memset(&counters, 0, sizeof(counters));
93 counters.expected_data_len = data_len;
94 counters.expected_data = data;
95
96 /* create and initialize the pcb */
97 pcb = test_tcp_new_counters_pcb(&counters);
98 EXPECT_RET(pcb != NULL);
99 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
100
101 /* create a segment */
102 p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
103 EXPECT(p != NULL);
104 if (p != NULL) {
105 /* pass the segment to tcp_input */
106 test_tcp_input(p, &netif);
107 /* check if counters are as expected */
108 EXPECT(counters.close_calls == 0);
109 EXPECT(counters.recv_calls == 1);
110 EXPECT(counters.recved_bytes == data_len);
111 EXPECT(counters.err_calls == 0);
112 }
113
114 /* make sure the pcb is freed */
115 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
116 tcp_abort(pcb);
117 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
118 }
119 END_TEST
120
121 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
122 * At the end, send more data. */
START_TEST(test_tcp_fast_retx_recover)123 START_TEST(test_tcp_fast_retx_recover)
124 {
125 struct netif netif;
126 struct test_tcp_txcounters txcounters;
127 struct test_tcp_counters counters;
128 struct tcp_pcb* pcb;
129 struct pbuf* p;
130 char data1[] = { 1, 2, 3, 4};
131 char data2[] = { 5, 6, 7, 8};
132 char data3[] = { 9, 10, 11, 12};
133 char data4[] = {13, 14, 15, 16};
134 char data5[] = {17, 18, 19, 20};
135 char data6[] = {21, 22, 23, 24};
136 ip_addr_t remote_ip, local_ip, netmask;
137 u16_t remote_port = 0x100, local_port = 0x101;
138 err_t err;
139 LWIP_UNUSED_ARG(_i);
140
141 /* initialize local vars */
142 IP4_ADDR(&local_ip, 192, 168, 1, 1);
143 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
144 IP4_ADDR(&netmask, 255, 255, 255, 0);
145 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
146 memset(&counters, 0, sizeof(counters));
147
148 /* create and initialize the pcb */
149 pcb = test_tcp_new_counters_pcb(&counters);
150 EXPECT_RET(pcb != NULL);
151 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
152 pcb->mss = TCP_MSS;
153 /* disable initial congestion window (we don't send a SYN here...) */
154 pcb->cwnd = pcb->snd_wnd;
155
156 /* send data1 */
157 err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY);
158 EXPECT_RET(err == ERR_OK);
159 err = tcp_output(pcb);
160 EXPECT_RET(err == ERR_OK);
161 EXPECT_RET(txcounters.num_tx_calls == 1);
162 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
163 memset(&txcounters, 0, sizeof(txcounters));
164 /* "recv" ACK for data1 */
165 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
166 EXPECT_RET(p != NULL);
167 test_tcp_input(p, &netif);
168 EXPECT_RET(txcounters.num_tx_calls == 0);
169 EXPECT_RET(pcb->unacked == NULL);
170 /* send data2 */
171 err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY);
172 EXPECT_RET(err == ERR_OK);
173 err = tcp_output(pcb);
174 EXPECT_RET(err == ERR_OK);
175 EXPECT_RET(txcounters.num_tx_calls == 1);
176 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
177 memset(&txcounters, 0, sizeof(txcounters));
178 /* duplicate ACK for data1 (data2 is lost) */
179 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
180 EXPECT_RET(p != NULL);
181 test_tcp_input(p, &netif);
182 EXPECT_RET(txcounters.num_tx_calls == 0);
183 EXPECT_RET(pcb->dupacks == 1);
184 /* send data3 */
185 err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
186 EXPECT_RET(err == ERR_OK);
187 err = tcp_output(pcb);
188 EXPECT_RET(err == ERR_OK);
189 /* nagle enabled, no tx calls */
190 EXPECT_RET(txcounters.num_tx_calls == 0);
191 EXPECT_RET(txcounters.num_tx_bytes == 0);
192 memset(&txcounters, 0, sizeof(txcounters));
193 /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */
194 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
195 EXPECT_RET(p != NULL);
196 test_tcp_input(p, &netif);
197 EXPECT_RET(txcounters.num_tx_calls == 0);
198 EXPECT_RET(pcb->dupacks == 2);
199 /* queue data4, don't send it (unsent-oversize is != 0) */
200 err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
201 EXPECT_RET(err == ERR_OK);
202 /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */
203 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
204 EXPECT_RET(p != NULL);
205 test_tcp_input(p, &netif);
206 /*EXPECT_RET(txcounters.num_tx_calls == 1);*/
207 EXPECT_RET(pcb->dupacks == 3);
208 memset(&txcounters, 0, sizeof(txcounters));
209 /* TODO: check expected data?*/
210
211 /* send data5, not output yet */
212 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
213 EXPECT_RET(err == ERR_OK);
214 /*err = tcp_output(pcb);
215 EXPECT_RET(err == ERR_OK);*/
216 EXPECT_RET(txcounters.num_tx_calls == 0);
217 EXPECT_RET(txcounters.num_tx_bytes == 0);
218 memset(&txcounters, 0, sizeof(txcounters));
219 {
220 int i = 0;
221 do
222 {
223 err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
224 i++;
225 }while(err == ERR_OK);
226 EXPECT_RET(err != ERR_OK);
227 }
228 err = tcp_output(pcb);
229 EXPECT_RET(err == ERR_OK);
230 /*EXPECT_RET(txcounters.num_tx_calls == 0);
231 EXPECT_RET(txcounters.num_tx_bytes == 0);*/
232 memset(&txcounters, 0, sizeof(txcounters));
233
234 /* send even more data */
235 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
236 EXPECT_RET(err == ERR_OK);
237 err = tcp_output(pcb);
238 EXPECT_RET(err == ERR_OK);
239 /* ...and even more data */
240 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
241 EXPECT_RET(err == ERR_OK);
242 err = tcp_output(pcb);
243 EXPECT_RET(err == ERR_OK);
244 /* ...and even more data */
245 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
246 EXPECT_RET(err == ERR_OK);
247 err = tcp_output(pcb);
248 EXPECT_RET(err == ERR_OK);
249 /* ...and even more data */
250 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
251 EXPECT_RET(err == ERR_OK);
252 err = tcp_output(pcb);
253 EXPECT_RET(err == ERR_OK);
254
255 /* send ACKs for data2 and data3 */
256 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK);
257 EXPECT_RET(p != NULL);
258 test_tcp_input(p, &netif);
259 /*EXPECT_RET(txcounters.num_tx_calls == 0);*/
260
261 /* ...and even more data */
262 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
263 EXPECT_RET(err == ERR_OK);
264 err = tcp_output(pcb);
265 EXPECT_RET(err == ERR_OK);
266 /* ...and even more data */
267 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
268 EXPECT_RET(err == ERR_OK);
269 err = tcp_output(pcb);
270 EXPECT_RET(err == ERR_OK);
271
272 #if 0
273 /* create expected segment */
274 p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
275 EXPECT_RET(p != NULL);
276 if (p != NULL) {
277 /* pass the segment to tcp_input */
278 test_tcp_input(p, &netif);
279 /* check if counters are as expected */
280 EXPECT_RET(counters.close_calls == 0);
281 EXPECT_RET(counters.recv_calls == 1);
282 EXPECT_RET(counters.recved_bytes == data_len);
283 EXPECT_RET(counters.err_calls == 0);
284 }
285 #endif
286 /* make sure the pcb is freed */
287 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
288 tcp_abort(pcb);
289 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
290 }
291 END_TEST
292
293 static u8_t tx_data[TCP_WND*2];
294
295 static void
check_seqnos(struct tcp_seg * segs,int num_expected,u32_t * seqnos_expected)296 check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected)
297 {
298 struct tcp_seg *s = segs;
299 int i;
300 for (i = 0; i < num_expected; i++, s = s->next) {
301 EXPECT_RET(s != NULL);
302 EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i]));
303 }
304 EXPECT(s == NULL);
305 }
306
307 /** Send data with sequence numbers that wrap around the u32_t range.
308 * Then, provoke fast retransmission by duplicate ACKs and check that all
309 * segment lists are still properly sorted. */
START_TEST(test_tcp_fast_rexmit_wraparound)310 START_TEST(test_tcp_fast_rexmit_wraparound)
311 {
312 struct netif netif;
313 struct test_tcp_txcounters txcounters;
314 struct test_tcp_counters counters;
315 struct tcp_pcb* pcb;
316 struct pbuf* p;
317 ip_addr_t remote_ip, local_ip, netmask;
318 u16_t remote_port = 0x100, local_port = 0x101;
319 err_t err;
320 #define SEQNO1 (0xFFFFFF00 - TCP_MSS)
321 #define ISS 6510
322 u16_t i, sent_total = 0;
323 u32_t seqnos[] = {
324 SEQNO1,
325 SEQNO1 + (1 * TCP_MSS),
326 SEQNO1 + (2 * TCP_MSS),
327 SEQNO1 + (3 * TCP_MSS),
328 SEQNO1 + (4 * TCP_MSS),
329 SEQNO1 + (5 * TCP_MSS)};
330 LWIP_UNUSED_ARG(_i);
331
332 for (i = 0; i < sizeof(tx_data); i++) {
333 tx_data[i] = (u8_t)i;
334 }
335
336 /* initialize local vars */
337 IP4_ADDR(&local_ip, 192, 168, 1, 1);
338 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
339 IP4_ADDR(&netmask, 255, 255, 255, 0);
340 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
341 memset(&counters, 0, sizeof(counters));
342
343 /* create and initialize the pcb */
344 tcp_ticks = SEQNO1 - ISS;
345 pcb = test_tcp_new_counters_pcb(&counters);
346 EXPECT_RET(pcb != NULL);
347 EXPECT(pcb->lastack == SEQNO1);
348 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
349 pcb->mss = TCP_MSS;
350 /* disable initial congestion window (we don't send a SYN here...) */
351 pcb->cwnd = 2*TCP_MSS;
352
353 /* send 6 mss-sized segments */
354 for (i = 0; i < 6; i++) {
355 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
356 EXPECT_RET(err == ERR_OK);
357 sent_total += TCP_MSS;
358 }
359 check_seqnos(pcb->unsent, 6, seqnos);
360 EXPECT(pcb->unacked == NULL);
361 err = tcp_output(pcb);
362 EXPECT(txcounters.num_tx_calls == 2);
363 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
364 memset(&txcounters, 0, sizeof(txcounters));
365
366 check_seqnos(pcb->unacked, 2, seqnos);
367 check_seqnos(pcb->unsent, 4, &seqnos[2]);
368
369 /* ACK the first segment */
370 p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
371 test_tcp_input(p, &netif);
372 /* ensure this didn't trigger a retransmission */
373 EXPECT(txcounters.num_tx_calls == 1);
374 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
375 memset(&txcounters, 0, sizeof(txcounters));
376 check_seqnos(pcb->unacked, 2, &seqnos[1]);
377 check_seqnos(pcb->unsent, 3, &seqnos[3]);
378
379 /* 3 dupacks */
380 EXPECT(pcb->dupacks == 0);
381 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
382 test_tcp_input(p, &netif);
383 EXPECT(txcounters.num_tx_calls == 0);
384 EXPECT(pcb->dupacks == 1);
385 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
386 test_tcp_input(p, &netif);
387 EXPECT(txcounters.num_tx_calls == 0);
388 EXPECT(pcb->dupacks == 2);
389 /* 3rd dupack -> fast rexmit */
390 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
391 test_tcp_input(p, &netif);
392 EXPECT(pcb->dupacks == 3);
393 EXPECT(txcounters.num_tx_calls == 4);
394 memset(&txcounters, 0, sizeof(txcounters));
395 EXPECT(pcb->unsent == NULL);
396 check_seqnos(pcb->unacked, 5, &seqnos[1]);
397
398 /* make sure the pcb is freed */
399 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
400 tcp_abort(pcb);
401 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
402 }
403 END_TEST
404
405 /** Send data with sequence numbers that wrap around the u32_t range.
406 * Then, provoke RTO retransmission and check that all
407 * segment lists are still properly sorted. */
START_TEST(test_tcp_rto_rexmit_wraparound)408 START_TEST(test_tcp_rto_rexmit_wraparound)
409 {
410 struct netif netif;
411 struct test_tcp_txcounters txcounters;
412 struct test_tcp_counters counters;
413 struct tcp_pcb* pcb;
414 ip_addr_t remote_ip, local_ip, netmask;
415 u16_t remote_port = 0x100, local_port = 0x101;
416 err_t err;
417 #define SEQNO1 (0xFFFFFF00 - TCP_MSS)
418 #define ISS 6510
419 u16_t i, sent_total = 0;
420 u32_t seqnos[] = {
421 SEQNO1,
422 SEQNO1 + (1 * TCP_MSS),
423 SEQNO1 + (2 * TCP_MSS),
424 SEQNO1 + (3 * TCP_MSS),
425 SEQNO1 + (4 * TCP_MSS),
426 SEQNO1 + (5 * TCP_MSS)};
427 LWIP_UNUSED_ARG(_i);
428
429 for (i = 0; i < sizeof(tx_data); i++) {
430 tx_data[i] = (u8_t)i;
431 }
432
433 /* initialize local vars */
434 IP4_ADDR(&local_ip, 192, 168, 1, 1);
435 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
436 IP4_ADDR(&netmask, 255, 255, 255, 0);
437 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
438 memset(&counters, 0, sizeof(counters));
439
440 /* create and initialize the pcb */
441 tcp_ticks = 0;
442 tcp_ticks = 0 - tcp_next_iss();
443 tcp_ticks = SEQNO1 - tcp_next_iss();
444 pcb = test_tcp_new_counters_pcb(&counters);
445 EXPECT_RET(pcb != NULL);
446 EXPECT(pcb->lastack == SEQNO1);
447 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
448 pcb->mss = TCP_MSS;
449 /* disable initial congestion window (we don't send a SYN here...) */
450 pcb->cwnd = 2*TCP_MSS;
451
452 /* send 6 mss-sized segments */
453 for (i = 0; i < 6; i++) {
454 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
455 EXPECT_RET(err == ERR_OK);
456 sent_total += TCP_MSS;
457 }
458 check_seqnos(pcb->unsent, 6, seqnos);
459 EXPECT(pcb->unacked == NULL);
460 err = tcp_output(pcb);
461 EXPECT(txcounters.num_tx_calls == 2);
462 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
463 memset(&txcounters, 0, sizeof(txcounters));
464
465 check_seqnos(pcb->unacked, 2, seqnos);
466 check_seqnos(pcb->unsent, 4, &seqnos[2]);
467
468 /* call the tcp timer some times */
469 for (i = 0; i < 10; i++) {
470 test_tcp_tmr();
471 EXPECT(txcounters.num_tx_calls == 0);
472 }
473 /* 11th call to tcp_tmr: RTO rexmit fires */
474 test_tcp_tmr();
475 EXPECT(txcounters.num_tx_calls == 1);
476 check_seqnos(pcb->unacked, 1, seqnos);
477 check_seqnos(pcb->unsent, 5, &seqnos[1]);
478
479 /* fake greater cwnd */
480 pcb->cwnd = pcb->snd_wnd;
481 /* send more data */
482 err = tcp_output(pcb);
483 EXPECT(err == ERR_OK);
484 /* check queues are sorted */
485 EXPECT(pcb->unsent == NULL);
486 check_seqnos(pcb->unacked, 6, seqnos);
487
488 /* make sure the pcb is freed */
489 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
490 tcp_abort(pcb);
491 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
492 }
493 END_TEST
494
495 /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
496 * At the end, send more data. */
test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)497 static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)
498 {
499 struct netif netif;
500 struct test_tcp_txcounters txcounters;
501 struct test_tcp_counters counters;
502 struct tcp_pcb* pcb;
503 struct pbuf *p;
504 ip_addr_t remote_ip, local_ip, netmask;
505 u16_t remote_port = 0x100, local_port = 0x101;
506 err_t err;
507 u16_t sent_total, i;
508 u8_t expected = 0xFE;
509
510 for (i = 0; i < sizeof(tx_data); i++) {
511 u8_t d = (u8_t)i;
512 if (d == 0xFE) {
513 d = 0xF0;
514 }
515 tx_data[i] = d;
516 }
517 if (zero_window_probe_from_unsent) {
518 tx_data[TCP_WND] = expected;
519 } else {
520 tx_data[0] = expected;
521 }
522
523 /* initialize local vars */
524 IP4_ADDR(&local_ip, 192, 168, 1, 1);
525 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
526 IP4_ADDR(&netmask, 255, 255, 255, 0);
527 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
528 memset(&counters, 0, sizeof(counters));
529 memset(&txcounters, 0, sizeof(txcounters));
530
531 /* create and initialize the pcb */
532 pcb = test_tcp_new_counters_pcb(&counters);
533 EXPECT_RET(pcb != NULL);
534 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
535 pcb->mss = TCP_MSS;
536 /* disable initial congestion window (we don't send a SYN here...) */
537 pcb->cwnd = pcb->snd_wnd;
538
539 /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */
540 sent_total = 0;
541 if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) {
542 u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS;
543 err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY);
544 EXPECT_RET(err == ERR_OK);
545 err = tcp_output(pcb);
546 EXPECT_RET(err == ERR_OK);
547 EXPECT(txcounters.num_tx_calls == 1);
548 EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U);
549 memset(&txcounters, 0, sizeof(txcounters));
550 sent_total += initial_data_len;
551 }
552 for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) {
553 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
554 EXPECT_RET(err == ERR_OK);
555 err = tcp_output(pcb);
556 EXPECT_RET(err == ERR_OK);
557 EXPECT(txcounters.num_tx_calls == 1);
558 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
559 memset(&txcounters, 0, sizeof(txcounters));
560 }
561 EXPECT(sent_total == (TCP_WND - TCP_MSS));
562
563 /* now ACK the packet before the first */
564 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
565 test_tcp_input(p, &netif);
566 /* ensure this didn't trigger a retransmission */
567 EXPECT(txcounters.num_tx_calls == 0);
568 EXPECT(txcounters.num_tx_bytes == 0);
569
570 EXPECT(pcb->persist_backoff == 0);
571 /* send the last packet, now a complete window has been sent */
572 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
573 sent_total += TCP_MSS;
574 EXPECT_RET(err == ERR_OK);
575 err = tcp_output(pcb);
576 EXPECT_RET(err == ERR_OK);
577 EXPECT(txcounters.num_tx_calls == 1);
578 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
579 memset(&txcounters, 0, sizeof(txcounters));
580 EXPECT(pcb->persist_backoff == 0);
581
582 if (zero_window_probe_from_unsent) {
583 /* ACK all data but close the TX window */
584 p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0);
585 test_tcp_input(p, &netif);
586 /* ensure this didn't trigger any transmission */
587 EXPECT(txcounters.num_tx_calls == 0);
588 EXPECT(txcounters.num_tx_bytes == 0);
589 EXPECT(pcb->persist_backoff == 1);
590 }
591
592 /* send one byte more (out of window) -> persist timer starts */
593 err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY);
594 EXPECT_RET(err == ERR_OK);
595 err = tcp_output(pcb);
596 EXPECT_RET(err == ERR_OK);
597 EXPECT(txcounters.num_tx_calls == 0);
598 EXPECT(txcounters.num_tx_bytes == 0);
599 memset(&txcounters, 0, sizeof(txcounters));
600 if (!zero_window_probe_from_unsent) {
601 /* no persist timer unless a zero window announcement has been received */
602 EXPECT(pcb->persist_backoff == 0);
603 } else {
604 EXPECT(pcb->persist_backoff == 1);
605
606 /* call tcp_timer some more times to let persist timer count up */
607 for (i = 0; i < 4; i++) {
608 test_tcp_tmr();
609 EXPECT(txcounters.num_tx_calls == 0);
610 EXPECT(txcounters.num_tx_bytes == 0);
611 }
612
613 /* this should trigger the zero-window-probe */
614 txcounters.copy_tx_packets = 1;
615 test_tcp_tmr();
616 txcounters.copy_tx_packets = 0;
617 EXPECT(txcounters.num_tx_calls == 1);
618 EXPECT(txcounters.num_tx_bytes == 1 + 40U);
619 EXPECT(txcounters.tx_packets != NULL);
620 if (txcounters.tx_packets != NULL) {
621 u8_t sent;
622 u16_t ret;
623 ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U);
624 EXPECT(ret == 1);
625 EXPECT(sent == expected);
626 }
627 if (txcounters.tx_packets != NULL) {
628 pbuf_free(txcounters.tx_packets);
629 txcounters.tx_packets = NULL;
630 }
631 }
632
633 /* make sure the pcb is freed */
634 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
635 tcp_abort(pcb);
636 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
637 }
638
START_TEST(test_tcp_tx_full_window_lost_from_unsent)639 START_TEST(test_tcp_tx_full_window_lost_from_unsent)
640 {
641 LWIP_UNUSED_ARG(_i);
642 test_tcp_tx_full_window_lost(1);
643 }
644 END_TEST
645
START_TEST(test_tcp_tx_full_window_lost_from_unacked)646 START_TEST(test_tcp_tx_full_window_lost_from_unacked)
647 {
648 LWIP_UNUSED_ARG(_i);
649 test_tcp_tx_full_window_lost(0);
650 }
651 END_TEST
652
653 /** Create the suite including all tests for this module */
654 Suite *
tcp_suite(void)655 tcp_suite(void)
656 {
657 TFun tests[] = {
658 test_tcp_new_abort,
659 test_tcp_recv_inseq,
660 test_tcp_fast_retx_recover,
661 test_tcp_fast_rexmit_wraparound,
662 test_tcp_rto_rexmit_wraparound,
663 test_tcp_tx_full_window_lost_from_unacked,
664 test_tcp_tx_full_window_lost_from_unsent
665 };
666 return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
667 }
668