ReactOS 0.4.15-dev-5666-gc548b97
test_tcp.c
Go to the documentation of this file.
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
19
20/* our own version of tcp_tmr so we can reset fast/slow timer state */
21static void
23{
24 tcp_fasttmr();
25 if (++test_tcp_timer & 1) {
26 tcp_slowtmr();
27 }
28}
29
30/* Setups/teardown functions */
31
32static 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
43}
44
45static void
47{
51}
52
53
54/* Test functions */
55
57START_TEST(test_tcp_new_abort)
58{
59 struct tcp_pcb* pcb;
61
62 fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
63
64 pcb = tcp_new();
65 fail_unless(pcb != NULL);
66 if (pcb != NULL) {
67 fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
68 tcp_abort(pcb);
69 fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
70 }
71}
72END_TEST
73
75START_TEST(test_tcp_recv_inseq)
76{
78 struct tcp_pcb* pcb;
79 struct pbuf* p;
80 char data[] = {1, 2, 3, 4};
81 ip_addr_t remote_ip, local_ip, netmask;
82 u16_t data_len;
83 u16_t remote_port = 0x100, local_port = 0x101;
84 struct netif netif;
85 struct test_tcp_txcounters txcounters;
87
88 /* initialize local vars */
89 memset(&netif, 0, sizeof(netif));
90 IP4_ADDR(&local_ip, 192, 168, 1, 1);
91 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
92 IP4_ADDR(&netmask, 255, 255, 255, 0);
93 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
94 data_len = sizeof(data);
95 /* initialize counter struct */
96 memset(&counters, 0, sizeof(counters));
97 counters.expected_data_len = data_len;
98 counters.expected_data = data;
99
100 /* create and initialize the pcb */
102 EXPECT_RET(pcb != NULL);
103 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
104
105 /* create a segment */
106 p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
107 EXPECT(p != NULL);
108 if (p != NULL) {
109 /* pass the segment to tcp_input */
111 /* check if counters are as expected */
112 EXPECT(counters.close_calls == 0);
113 EXPECT(counters.recv_calls == 1);
114 EXPECT(counters.recved_bytes == data_len);
115 EXPECT(counters.err_calls == 0);
116 }
117
118 /* make sure the pcb is freed */
119 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
120 tcp_abort(pcb);
121 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
122}
123END_TEST
124
127START_TEST(test_tcp_fast_retx_recover)
128{
129 struct netif netif;
130 struct test_tcp_txcounters txcounters;
132 struct tcp_pcb* pcb;
133 struct pbuf* p;
134 char data1[] = { 1, 2, 3, 4};
135 char data2[] = { 5, 6, 7, 8};
136 char data3[] = { 9, 10, 11, 12};
137 char data4[] = {13, 14, 15, 16};
138 char data5[] = {17, 18, 19, 20};
139 char data6[] = {21, 22, 23, 24};
140 ip_addr_t remote_ip, local_ip, netmask;
141 u16_t remote_port = 0x100, local_port = 0x101;
142 err_t err;
143 LWIP_UNUSED_ARG(_i);
144
145 /* initialize local vars */
146 IP4_ADDR(&local_ip, 192, 168, 1, 1);
147 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
148 IP4_ADDR(&netmask, 255, 255, 255, 0);
149 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
150 memset(&counters, 0, sizeof(counters));
151
152 /* create and initialize the pcb */
154 EXPECT_RET(pcb != NULL);
155 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
156 pcb->mss = TCP_MSS;
157 /* disable initial congestion window (we don't send a SYN here...) */
158 pcb->cwnd = pcb->snd_wnd;
159
160 /* send data1 */
161 err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY);
163 err = tcp_output(pcb);
165 EXPECT_RET(txcounters.num_tx_calls == 1);
166 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
167 memset(&txcounters, 0, sizeof(txcounters));
168 /* "recv" ACK for data1 */
169 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
170 EXPECT_RET(p != NULL);
172 EXPECT_RET(txcounters.num_tx_calls == 0);
173 EXPECT_RET(pcb->unacked == NULL);
174 /* send data2 */
175 err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY);
177 err = tcp_output(pcb);
179 EXPECT_RET(txcounters.num_tx_calls == 1);
180 EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
181 memset(&txcounters, 0, sizeof(txcounters));
182 /* duplicate ACK for data1 (data2 is lost) */
183 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
184 EXPECT_RET(p != NULL);
186 EXPECT_RET(txcounters.num_tx_calls == 0);
187 EXPECT_RET(pcb->dupacks == 1);
188 /* send data3 */
189 err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
191 err = tcp_output(pcb);
193 /* nagle enabled, no tx calls */
194 EXPECT_RET(txcounters.num_tx_calls == 0);
195 EXPECT_RET(txcounters.num_tx_bytes == 0);
196 memset(&txcounters, 0, sizeof(txcounters));
197 /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */
198 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
199 EXPECT_RET(p != NULL);
201 EXPECT_RET(txcounters.num_tx_calls == 0);
202 EXPECT_RET(pcb->dupacks == 2);
203 /* queue data4, don't send it (unsent-oversize is != 0) */
204 err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
206 /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */
207 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
208 EXPECT_RET(p != NULL);
210 /*EXPECT_RET(txcounters.num_tx_calls == 1);*/
211 EXPECT_RET(pcb->dupacks == 3);
212 memset(&txcounters, 0, sizeof(txcounters));
213 /* TODO: check expected data?*/
214
215 /* send data5, not output yet */
216 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
218 /*err = tcp_output(pcb);
219 EXPECT_RET(err == ERR_OK);*/
220 EXPECT_RET(txcounters.num_tx_calls == 0);
221 EXPECT_RET(txcounters.num_tx_bytes == 0);
222 memset(&txcounters, 0, sizeof(txcounters));
223 {
224 int i = 0;
225 do
226 {
227 err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
228 i++;
229 }while(err == ERR_OK);
231 }
232 err = tcp_output(pcb);
234 /*EXPECT_RET(txcounters.num_tx_calls == 0);
235 EXPECT_RET(txcounters.num_tx_bytes == 0);*/
236 memset(&txcounters, 0, sizeof(txcounters));
237
238 /* send even more data */
239 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
241 err = tcp_output(pcb);
243 /* ...and even more data */
244 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
246 err = tcp_output(pcb);
248 /* ...and even more data */
249 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
251 err = tcp_output(pcb);
253 /* ...and even more data */
254 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
256 err = tcp_output(pcb);
258
259 /* send ACKs for data2 and data3 */
260 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK);
261 EXPECT_RET(p != NULL);
263 /*EXPECT_RET(txcounters.num_tx_calls == 0);*/
264
265 /* ...and even more data */
266 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
268 err = tcp_output(pcb);
270 /* ...and even more data */
271 err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
273 err = tcp_output(pcb);
275
276#if 0
277 /* create expected segment */
278 p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
279 EXPECT_RET(p != NULL);
280 if (p != NULL) {
281 /* pass the segment to tcp_input */
283 /* check if counters are as expected */
284 EXPECT_RET(counters.close_calls == 0);
285 EXPECT_RET(counters.recv_calls == 1);
286 EXPECT_RET(counters.recved_bytes == data_len);
287 EXPECT_RET(counters.err_calls == 0);
288 }
289#endif
290 /* make sure the pcb is freed */
291 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
292 tcp_abort(pcb);
293 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
294}
295END_TEST
296
298
299static void
300check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected)
301{
302 struct tcp_seg *s = segs;
303 int i;
304 for (i = 0; i < num_expected; i++, s = s->next) {
305 EXPECT_RET(s != NULL);
306 EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i]));
307 }
308 EXPECT(s == NULL);
309}
310
314START_TEST(test_tcp_fast_rexmit_wraparound)
315{
316 struct netif netif;
317 struct test_tcp_txcounters txcounters;
319 struct tcp_pcb* pcb;
320 struct pbuf* p;
321 ip_addr_t remote_ip, local_ip, netmask;
322 u16_t remote_port = 0x100, local_port = 0x101;
323 err_t err;
324#define SEQNO1 (0xFFFFFF00 - TCP_MSS)
325#define ISS 6510
326 u16_t i, sent_total = 0;
327 u32_t seqnos[] = {
328 SEQNO1,
329 SEQNO1 + (1 * TCP_MSS),
330 SEQNO1 + (2 * TCP_MSS),
331 SEQNO1 + (3 * TCP_MSS),
332 SEQNO1 + (4 * TCP_MSS),
333 SEQNO1 + (5 * TCP_MSS)};
334 LWIP_UNUSED_ARG(_i);
335
336 for (i = 0; i < sizeof(tx_data); i++) {
337 tx_data[i] = (u8_t)i;
338 }
339
340 /* initialize local vars */
341 IP4_ADDR(&local_ip, 192, 168, 1, 1);
342 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
343 IP4_ADDR(&netmask, 255, 255, 255, 0);
344 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
345 memset(&counters, 0, sizeof(counters));
346
347 /* create and initialize the pcb */
348 tcp_ticks = SEQNO1 - ISS;
350 EXPECT_RET(pcb != NULL);
351 EXPECT(pcb->lastack == SEQNO1);
352 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
353 pcb->mss = TCP_MSS;
354 /* disable initial congestion window (we don't send a SYN here...) */
355 pcb->cwnd = 2*TCP_MSS;
356
357 /* send 6 mss-sized segments */
358 for (i = 0; i < 6; i++) {
359 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
361 sent_total += TCP_MSS;
362 }
363 check_seqnos(pcb->unsent, 6, seqnos);
364 EXPECT(pcb->unacked == NULL);
365 err = tcp_output(pcb);
366 EXPECT(txcounters.num_tx_calls == 2);
367 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
368 memset(&txcounters, 0, sizeof(txcounters));
369
370 check_seqnos(pcb->unacked, 2, seqnos);
371 check_seqnos(pcb->unsent, 4, &seqnos[2]);
372
373 /* ACK the first segment */
374 p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
376 /* ensure this didn't trigger a retransmission */
377 EXPECT(txcounters.num_tx_calls == 1);
378 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
379 memset(&txcounters, 0, sizeof(txcounters));
380 check_seqnos(pcb->unacked, 2, &seqnos[1]);
381 check_seqnos(pcb->unsent, 3, &seqnos[3]);
382
383 /* 3 dupacks */
384 EXPECT(pcb->dupacks == 0);
385 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
387 EXPECT(txcounters.num_tx_calls == 0);
388 EXPECT(pcb->dupacks == 1);
389 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
391 EXPECT(txcounters.num_tx_calls == 0);
392 EXPECT(pcb->dupacks == 2);
393 /* 3rd dupack -> fast rexmit */
394 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
396 EXPECT(pcb->dupacks == 3);
397 EXPECT(txcounters.num_tx_calls == 4);
398 memset(&txcounters, 0, sizeof(txcounters));
399 EXPECT(pcb->unsent == NULL);
400 check_seqnos(pcb->unacked, 5, &seqnos[1]);
401
402 /* make sure the pcb is freed */
403 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
404 tcp_abort(pcb);
405 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
406}
407END_TEST
408
412START_TEST(test_tcp_rto_rexmit_wraparound)
413{
414 struct netif netif;
415 struct test_tcp_txcounters txcounters;
417 struct tcp_pcb* pcb;
418 ip_addr_t remote_ip, local_ip, netmask;
419 u16_t remote_port = 0x100, local_port = 0x101;
420 err_t err;
421#define SEQNO1 (0xFFFFFF00 - TCP_MSS)
422#define ISS 6510
423 u16_t i, sent_total = 0;
424 u32_t seqnos[] = {
425 SEQNO1,
426 SEQNO1 + (1 * TCP_MSS),
427 SEQNO1 + (2 * TCP_MSS),
428 SEQNO1 + (3 * TCP_MSS),
429 SEQNO1 + (4 * TCP_MSS),
430 SEQNO1 + (5 * TCP_MSS)};
431 LWIP_UNUSED_ARG(_i);
432
433 for (i = 0; i < sizeof(tx_data); i++) {
434 tx_data[i] = (u8_t)i;
435 }
436
437 /* initialize local vars */
438 IP4_ADDR(&local_ip, 192, 168, 1, 1);
439 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
440 IP4_ADDR(&netmask, 255, 255, 255, 0);
441 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
442 memset(&counters, 0, sizeof(counters));
443
444 /* create and initialize the pcb */
445 tcp_ticks = 0;
446 tcp_ticks = 0 - tcp_next_iss();
447 tcp_ticks = SEQNO1 - tcp_next_iss();
449 EXPECT_RET(pcb != NULL);
450 EXPECT(pcb->lastack == SEQNO1);
451 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
452 pcb->mss = TCP_MSS;
453 /* disable initial congestion window (we don't send a SYN here...) */
454 pcb->cwnd = 2*TCP_MSS;
455
456 /* send 6 mss-sized segments */
457 for (i = 0; i < 6; i++) {
458 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
460 sent_total += TCP_MSS;
461 }
462 check_seqnos(pcb->unsent, 6, seqnos);
463 EXPECT(pcb->unacked == NULL);
464 err = tcp_output(pcb);
465 EXPECT(txcounters.num_tx_calls == 2);
466 EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
467 memset(&txcounters, 0, sizeof(txcounters));
468
469 check_seqnos(pcb->unacked, 2, seqnos);
470 check_seqnos(pcb->unsent, 4, &seqnos[2]);
471
472 /* call the tcp timer some times */
473 for (i = 0; i < 10; i++) {
474 test_tcp_tmr();
475 EXPECT(txcounters.num_tx_calls == 0);
476 }
477 /* 11th call to tcp_tmr: RTO rexmit fires */
478 test_tcp_tmr();
479 EXPECT(txcounters.num_tx_calls == 1);
480 check_seqnos(pcb->unacked, 1, seqnos);
481 check_seqnos(pcb->unsent, 5, &seqnos[1]);
482
483 /* fake greater cwnd */
484 pcb->cwnd = pcb->snd_wnd;
485 /* send more data */
486 err = tcp_output(pcb);
487 EXPECT(err == ERR_OK);
488 /* check queues are sorted */
489 EXPECT(pcb->unsent == NULL);
490 check_seqnos(pcb->unacked, 6, seqnos);
491
492 /* make sure the pcb is freed */
493 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
494 tcp_abort(pcb);
495 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
496}
497END_TEST
498
501static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)
502{
503 struct netif netif;
504 struct test_tcp_txcounters txcounters;
506 struct tcp_pcb* pcb;
507 struct pbuf *p;
508 ip_addr_t remote_ip, local_ip, netmask;
509 u16_t remote_port = 0x100, local_port = 0x101;
510 err_t err;
511 u16_t sent_total, i;
512 u8_t expected = 0xFE;
513
514 for (i = 0; i < sizeof(tx_data); i++) {
515 u8_t d = (u8_t)i;
516 if (d == 0xFE) {
517 d = 0xF0;
518 }
519 tx_data[i] = d;
520 }
521 if (zero_window_probe_from_unsent) {
523 } else {
524 tx_data[0] = expected;
525 }
526
527 /* initialize local vars */
528 IP4_ADDR(&local_ip, 192, 168, 1, 1);
529 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
530 IP4_ADDR(&netmask, 255, 255, 255, 0);
531 test_tcp_init_netif(&netif, &txcounters, &local_ip, &netmask);
532 memset(&counters, 0, sizeof(counters));
533 memset(&txcounters, 0, sizeof(txcounters));
534
535 /* create and initialize the pcb */
537 EXPECT_RET(pcb != NULL);
538 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
539 pcb->mss = TCP_MSS;
540 /* disable initial congestion window (we don't send a SYN here...) */
541 pcb->cwnd = pcb->snd_wnd;
542
543 /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */
544 sent_total = 0;
545 if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) {
546 u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS;
547 err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY);
549 err = tcp_output(pcb);
551 EXPECT(txcounters.num_tx_calls == 1);
552 EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U);
553 memset(&txcounters, 0, sizeof(txcounters));
554 sent_total += initial_data_len;
555 }
556 for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) {
557 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
559 err = tcp_output(pcb);
561 EXPECT(txcounters.num_tx_calls == 1);
562 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
563 memset(&txcounters, 0, sizeof(txcounters));
564 }
565 EXPECT(sent_total == (TCP_WND - TCP_MSS));
566
567 /* now ACK the packet before the first */
568 p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
570 /* ensure this didn't trigger a retransmission */
571 EXPECT(txcounters.num_tx_calls == 0);
572 EXPECT(txcounters.num_tx_bytes == 0);
573
574 EXPECT(pcb->persist_backoff == 0);
575 /* send the last packet, now a complete window has been sent */
576 err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
577 sent_total += TCP_MSS;
579 err = tcp_output(pcb);
581 EXPECT(txcounters.num_tx_calls == 1);
582 EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
583 memset(&txcounters, 0, sizeof(txcounters));
584 EXPECT(pcb->persist_backoff == 0);
585
586 if (zero_window_probe_from_unsent) {
587 /* ACK all data but close the TX window */
588 p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0);
590 /* ensure this didn't trigger any transmission */
591 EXPECT(txcounters.num_tx_calls == 0);
592 EXPECT(txcounters.num_tx_bytes == 0);
593 EXPECT(pcb->persist_backoff == 1);
594 }
595
596 /* send one byte more (out of window) -> persist timer starts */
597 err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY);
599 err = tcp_output(pcb);
601 EXPECT(txcounters.num_tx_calls == 0);
602 EXPECT(txcounters.num_tx_bytes == 0);
603 memset(&txcounters, 0, sizeof(txcounters));
604 if (!zero_window_probe_from_unsent) {
605 /* no persist timer unless a zero window announcement has been received */
606 EXPECT(pcb->persist_backoff == 0);
607 } else {
608 EXPECT(pcb->persist_backoff == 1);
609
610 /* call tcp_timer some more times to let persist timer count up */
611 for (i = 0; i < 4; i++) {
612 test_tcp_tmr();
613 EXPECT(txcounters.num_tx_calls == 0);
614 EXPECT(txcounters.num_tx_bytes == 0);
615 }
616
617 /* this should trigger the zero-window-probe */
618 txcounters.copy_tx_packets = 1;
619 test_tcp_tmr();
620 txcounters.copy_tx_packets = 0;
621 EXPECT(txcounters.num_tx_calls == 1);
622 EXPECT(txcounters.num_tx_bytes == 1 + 40U);
623 EXPECT(txcounters.tx_packets != NULL);
624 if (txcounters.tx_packets != NULL) {
625 u8_t sent;
626 u16_t ret;
627 ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U);
628 EXPECT(ret == 1);
629 EXPECT(sent == expected);
630 }
631 if (txcounters.tx_packets != NULL) {
632 pbuf_free(txcounters.tx_packets);
633 txcounters.tx_packets = NULL;
634 }
635 }
636
637 /* make sure the pcb is freed */
638 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
639 tcp_abort(pcb);
640 EXPECT_RET(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
641}
642
643START_TEST(test_tcp_tx_full_window_lost_from_unsent)
644{
645 LWIP_UNUSED_ARG(_i);
647}
648END_TEST
649
650START_TEST(test_tcp_tx_full_window_lost_from_unacked)
651{
652 LWIP_UNUSED_ARG(_i);
654}
655END_TEST
656
658Suite *
660{
661 TFun tests[] = {
662 test_tcp_new_abort,
663 test_tcp_recv_inseq,
664 test_tcp_fast_retx_recover,
665 test_tcp_fast_rexmit_wraparound,
666 test_tcp_rto_rexmit_wraparound,
667 test_tcp_tx_full_window_lost_from_unacked,
668 test_tcp_tx_full_window_lost_from_unsent
669 };
670 return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
671}
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define START_TEST(x)
Definition: atltest.h:75
@ sent
Definition: msg.h:34
static const char data4[]
Definition: db.c:2904
static const WCHAR data3[]
Definition: db.c:2900
static const WCHAR data5[]
Definition: db.c:2906
static const WCHAR data6[]
Definition: db.c:2924
#define NULL
Definition: types.h:112
unsigned long u32_t
Definition: cc.h:25
unsigned char u8_t
Definition: cc.h:23
unsigned short u16_t
Definition: cc.h:24
#define ERR_OK
Definition: err.h:52
s8_t err_t
Definition: err.h:47
GLdouble s
Definition: gl.h:2039
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLuint * counters
Definition: glext.h:11114
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define IP4_ADDR(ipaddr, a, b, c, d)
Definition: ip_addr.h:139
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
#define d
Definition: ke_i.h:81
static Suite * create_suite(const char *name, TFun *tests, size_t num_tests, SFun setup, SFun teardown)
Definition: lwip_check.h:20
#define EXPECT(x)
Definition: lwip_check.h:11
#define EXPECT_RET(x)
Definition: lwip_check.h:12
#define htonl(x)
Definition: module.h:212
static struct test_info tests[]
BOOL expected
Definition: store.c:2063
struct netif * netif_list
Definition: netif.c:75
struct netif * netif_default
Definition: netif.c:76
#define TCP_WND
Definition: opt.h:923
#define TCP_MSS
Definition: opt.h:956
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:918
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
#define err(...)
#define memset(x, y, z)
Definition: compat.h:39
Definition: tftpd.h:126
Definition: tftpd.h:138
Definition: ip.h:116
Definition: netif.h:136
Definition: pbuf.h:79
struct pbuf * tx_packets
Definition: tcp_helper.h:26
void test_tcp_input(struct pbuf *p, struct netif *inp)
Definition: tcp_helper.c:238
struct pbuf * tcp_create_rx_segment_wnd(struct tcp_pcb *pcb, void *data, size_t data_len, u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd)
Definition: tcp_helper.c:130
struct pbuf * tcp_create_rx_segment(struct tcp_pcb *pcb, void *data, size_t data_len, u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags)
Definition: tcp_helper.c:118
struct tcp_pcb * test_tcp_new_counters_pcb(struct test_tcp_counters *counters)
Definition: tcp_helper.c:223
void tcp_remove_all(void)
Definition: tcp_helper.c:28
void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, ip_addr_t *ip_addr, ip_addr_t *netmask)
Definition: tcp_helper.c:283
static __inline void tcp_set_state(struct sock *sk, int state)
Definition: tcpcore.h:3256
static END_TEST u8_t tx_data[TCP_WND *2]
Definition: test_tcp.c:297
static void check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected)
Definition: test_tcp.c:300
static void tcp_teardown(void)
Definition: test_tcp.c:46
#define SEQNO1
END_TEST Suite * tcp_suite(void)
Definition: test_tcp.c:659
static void test_tcp_tmr(void)
Definition: test_tcp.c:22
static u8_t test_tcp_timer
Definition: test_tcp.c:18
#define ISS
static void tcp_setup(void)
Definition: test_tcp.c:33
static END_TEST void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)
Definition: test_tcp.c:501
int ret