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