STM32F769IDiscovery  1.00
uDANTE Audio Networking with STM32F7 DISCO board
test_tcp.c
Go to the documentation of this file.
1 #include "test_tcp.h"
2 
3 #include "lwip/priv/tcp_priv.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
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
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;
43 }
44 
45 static void
46 tcp_teardown(void)
47 {
49  netif_list = NULL;
51 }
52 
53 
54 /* Test functions */
55 
57 START_TEST(test_tcp_new_abort)
58 {
59  struct tcp_pcb* pcb;
60  LWIP_UNUSED_ARG(_i);
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 }
72 END_TEST
73 
75 START_TEST(test_tcp_recv_inseq)
76 {
77  struct test_tcp_counters counters;
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;
86  LWIP_UNUSED_ARG(_i);
87 
88  /* initialize local vars */
89  memset(&netif, 0, sizeof(netif));
90  IP_ADDR4(&local_ip, 192, 168, 1, 1);
91  IP_ADDR4(&remote_ip, 192, 168, 1, 2);
92  IP_ADDR4(&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 */
101  pcb = test_tcp_new_counters_pcb(&counters);
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 */
110  test_tcp_input(p, &netif);
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 }
123 END_TEST
124 
127 START_TEST(test_tcp_fast_retx_recover)
128 {
129  struct netif netif;
130  struct test_tcp_txcounters txcounters;
131  struct test_tcp_counters counters;
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  IP_ADDR4(&local_ip, 192, 168, 1, 1);
147  IP_ADDR4(&remote_ip, 192, 168, 1, 2);
148  IP_ADDR4(&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 */
153  pcb = test_tcp_new_counters_pcb(&counters);
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);
162  EXPECT_RET(err == ERR_OK);
163  err = tcp_output(pcb);
164  EXPECT_RET(err == ERR_OK);
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);
171  test_tcp_input(p, &netif);
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);
176  EXPECT_RET(err == ERR_OK);
177  err = tcp_output(pcb);
178  EXPECT_RET(err == ERR_OK);
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);
185  test_tcp_input(p, &netif);
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);
190  EXPECT_RET(err == ERR_OK);
191  err = tcp_output(pcb);
192  EXPECT_RET(err == ERR_OK);
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);
200  test_tcp_input(p, &netif);
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);
205  EXPECT_RET(err == ERR_OK);
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);
209  test_tcp_input(p, &netif);
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);
217  EXPECT_RET(err == ERR_OK);
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);
230  EXPECT_RET(err != ERR_OK);
231  }
232  err = tcp_output(pcb);
233  EXPECT_RET(err == ERR_OK);
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);
240  EXPECT_RET(err == ERR_OK);
241  err = tcp_output(pcb);
242  EXPECT_RET(err == ERR_OK);
243  /* ...and even more data */
244  err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
245  EXPECT_RET(err == ERR_OK);
246  err = tcp_output(pcb);
247  EXPECT_RET(err == ERR_OK);
248  /* ...and even more data */
249  err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
250  EXPECT_RET(err == ERR_OK);
251  err = tcp_output(pcb);
252  EXPECT_RET(err == ERR_OK);
253  /* ...and even more data */
254  err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
255  EXPECT_RET(err == ERR_OK);
256  err = tcp_output(pcb);
257  EXPECT_RET(err == ERR_OK);
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);
262  test_tcp_input(p, &netif);
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);
267  EXPECT_RET(err == ERR_OK);
268  err = tcp_output(pcb);
269  EXPECT_RET(err == ERR_OK);
270  /* ...and even more data */
271  err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
272  EXPECT_RET(err == ERR_OK);
273  err = tcp_output(pcb);
274  EXPECT_RET(err == ERR_OK);
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 */
282  test_tcp_input(p, &netif);
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 }
295 END_TEST
296 
297 static u8_t tx_data[TCP_WND*2];
298 
299 static void
300 check_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 
314 START_TEST(test_tcp_fast_rexmit_wraparound)
315 {
316  struct netif netif;
317  struct test_tcp_txcounters txcounters;
318  struct test_tcp_counters counters;
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  IP_ADDR4(&local_ip, 192, 168, 1, 1);
342  IP_ADDR4(&remote_ip, 192, 168, 1, 2);
343  IP_ADDR4(&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;
349  pcb = test_tcp_new_counters_pcb(&counters);
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);
360  EXPECT_RET(err == ERR_OK);
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);
375  test_tcp_input(p, &netif);
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);
386  test_tcp_input(p, &netif);
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);
390  test_tcp_input(p, &netif);
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);
395  test_tcp_input(p, &netif);
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 }
407 END_TEST
408 
412 START_TEST(test_tcp_rto_rexmit_wraparound)
413 {
414  struct netif netif;
415  struct test_tcp_txcounters txcounters;
416  struct test_tcp_counters counters;
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  IP_ADDR4(&local_ip, 192, 168, 1, 1);
439  IP_ADDR4(&remote_ip, 192, 168, 1, 2);
440  IP_ADDR4(&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();
448  pcb = test_tcp_new_counters_pcb(&counters);
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);
459  EXPECT_RET(err == ERR_OK);
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 }
497 END_TEST
498 
501 static 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;
505  struct test_tcp_counters counters;
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) {
522  tx_data[TCP_WND] = expected;
523  } else {
524  tx_data[0] = expected;
525  }
526 
527  /* initialize local vars */
528  IP_ADDR4(&local_ip, 192, 168, 1, 1);
529  IP_ADDR4(&remote_ip, 192, 168, 1, 2);
530  IP_ADDR4(&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 */
536  pcb = test_tcp_new_counters_pcb(&counters);
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);
548  EXPECT_RET(err == ERR_OK);
549  err = tcp_output(pcb);
550  EXPECT_RET(err == ERR_OK);
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);
558  EXPECT_RET(err == ERR_OK);
559  err = tcp_output(pcb);
560  EXPECT_RET(err == ERR_OK);
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);
569  test_tcp_input(p, &netif);
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;
578  EXPECT_RET(err == ERR_OK);
579  err = tcp_output(pcb);
580  EXPECT_RET(err == ERR_OK);
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);
589  test_tcp_input(p, &netif);
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);
598  EXPECT_RET(err == ERR_OK);
599  err = tcp_output(pcb);
600  EXPECT_RET(err == ERR_OK);
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 
643 START_TEST(test_tcp_tx_full_window_lost_from_unsent)
644 {
645  LWIP_UNUSED_ARG(_i);
646  test_tcp_tx_full_window_lost(1);
647 }
648 END_TEST
649 
650 START_TEST(test_tcp_tx_full_window_lost_from_unacked)
651 {
652  LWIP_UNUSED_ARG(_i);
653  test_tcp_tx_full_window_lost(0);
654 }
655 END_TEST
656 
658 Suite *
660 {
661  testfunc tests[] = {
662  TESTFUNC(test_tcp_new_abort),
663  TESTFUNC(test_tcp_recv_inseq),
664  TESTFUNC(test_tcp_fast_retx_recover),
665  TESTFUNC(test_tcp_fast_rexmit_wraparound),
666  TESTFUNC(test_tcp_rto_rexmit_wraparound),
667  TESTFUNC(test_tcp_tx_full_window_lost_from_unacked),
668  TESTFUNC(test_tcp_tx_full_window_lost_from_unsent)
669  };
670  return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown);
671 }
struct tcp_pcb * test_tcp_new_counters_pcb(struct test_tcp_counters *counters)
Definition: tcp_helper.c:225
struct netif * netif_list
Definition: netif.c:84
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:285
#define TESTFUNC(x)
Definition: lwip_check.h:21
#define SEQNO1
struct netif * netif_default
Definition: netif.c:85
END_TEST Suite * tcp_suite(void)
Definition: test_tcp.c:659
#define EXPECT_RET(x)
Definition: lwip_check.h:12
#define NULL
Definition: usbd_def.h:53
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:652
#define ISS
void tcp_remove_all(void)
Definition: tcp_helper.c:29
#define EXPECT(x)
Definition: lwip_check.h:11
unsigned long u32_t
Definition: cc.h:42
char * expected_data
Definition: tcp_helper.h:18
void tcp_set_state(struct tcp_pcb *pcb, enum tcp_state state, ip_addr_t *local_ip, ip_addr_t *remote_ip, u16_t local_port, u16_t remote_port)
Definition: tcp_helper.c:141
Suite * create_suite(const char *name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown)
#define ERR_OK
Definition: err.h:52
Definition: pbuf.h:108
s8_t err_t
Definition: err.h:47
#define TCP_WND
Definition: lwipopts.h:128
void test_tcp_input(struct pbuf *p, struct netif *inp)
Definition: tcp_helper.c:240
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:120
u32_t expected_data_len
Definition: tcp_helper.h:19
Definition: netif.h:182
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
Definition: pbuf.c:952
unsigned char u8_t
Definition: cc.h:38
#define TCP_MSS
Definition: lwipopts.h:117
ip6_addr_t ip_addr_t
Definition: ip_addr.h:194
struct pbuf * tx_packets
Definition: tcp_helper.h:26
START_TEST(test_tcp_new_abort)
Definition: test_tcp.c:57
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:132
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:89
#define htonl(x)
Definition: def.h:88
unsigned short u16_t
Definition: cc.h:40