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 /* used with check_seqnos() */
20*10465441SEvalZero #define SEQNO1 (0xFFFFFF00 - TCP_MSS)
21*10465441SEvalZero #define ISS 6510
22*10465441SEvalZero static u32_t seqnos[] = {
23*10465441SEvalZero SEQNO1,
24*10465441SEvalZero SEQNO1 + (1 * TCP_MSS),
25*10465441SEvalZero SEQNO1 + (2 * TCP_MSS),
26*10465441SEvalZero SEQNO1 + (3 * TCP_MSS),
27*10465441SEvalZero SEQNO1 + (4 * TCP_MSS),
28*10465441SEvalZero SEQNO1 + (5 * TCP_MSS) };
29*10465441SEvalZero
30*10465441SEvalZero static u8_t test_tcp_timer;
31*10465441SEvalZero
32*10465441SEvalZero /* our own version of tcp_tmr so we can reset fast/slow timer state */
33*10465441SEvalZero static void
test_tcp_tmr(void)34*10465441SEvalZero test_tcp_tmr(void)
35*10465441SEvalZero {
36*10465441SEvalZero tcp_fasttmr();
37*10465441SEvalZero if (++test_tcp_timer & 1) {
38*10465441SEvalZero tcp_slowtmr();
39*10465441SEvalZero }
40*10465441SEvalZero }
41*10465441SEvalZero
42*10465441SEvalZero /* Setups/teardown functions */
43*10465441SEvalZero static struct netif *old_netif_list;
44*10465441SEvalZero static struct netif *old_netif_default;
45*10465441SEvalZero
46*10465441SEvalZero static void
tcp_setup(void)47*10465441SEvalZero tcp_setup(void)
48*10465441SEvalZero {
49*10465441SEvalZero struct tcp_pcb dummy_pcb; /* we need this for tcp_next_iss() only */
50*10465441SEvalZero
51*10465441SEvalZero old_netif_list = netif_list;
52*10465441SEvalZero old_netif_default = netif_default;
53*10465441SEvalZero netif_list = NULL;
54*10465441SEvalZero netif_default = NULL;
55*10465441SEvalZero /* reset iss to default (6510) */
56*10465441SEvalZero tcp_ticks = 0;
57*10465441SEvalZero tcp_ticks = 0 - (tcp_next_iss(&dummy_pcb) - 6510);
58*10465441SEvalZero tcp_next_iss(&dummy_pcb);
59*10465441SEvalZero tcp_ticks = 0;
60*10465441SEvalZero
61*10465441SEvalZero test_tcp_timer = 0;
62*10465441SEvalZero tcp_remove_all();
63*10465441SEvalZero lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
64*10465441SEvalZero }
65*10465441SEvalZero
66*10465441SEvalZero static void
tcp_teardown(void)67*10465441SEvalZero tcp_teardown(void)
68*10465441SEvalZero {
69*10465441SEvalZero netif_list = NULL;
70*10465441SEvalZero netif_default = NULL;
71*10465441SEvalZero tcp_remove_all();
72*10465441SEvalZero /* restore netif_list for next tests (e.g. loopif) */
73*10465441SEvalZero netif_list = old_netif_list;
74*10465441SEvalZero netif_default = old_netif_default;
75*10465441SEvalZero lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
76*10465441SEvalZero }
77*10465441SEvalZero
78*10465441SEvalZero
79*10465441SEvalZero /* Test functions */
80*10465441SEvalZero
81*10465441SEvalZero /** Call tcp_new() and tcp_abort() and test memp stats */
START_TEST(test_tcp_new_abort)82*10465441SEvalZero START_TEST(test_tcp_new_abort)
83*10465441SEvalZero {
84*10465441SEvalZero struct tcp_pcb* pcb;
85*10465441SEvalZero LWIP_UNUSED_ARG(_i);
86*10465441SEvalZero
87*10465441SEvalZero fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
88*10465441SEvalZero
89*10465441SEvalZero pcb = tcp_new();
90*10465441SEvalZero fail_unless(pcb != NULL);
91*10465441SEvalZero if (pcb != NULL) {
92*10465441SEvalZero fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
93*10465441SEvalZero tcp_abort(pcb);
94*10465441SEvalZero fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
95*10465441SEvalZero }
96*10465441SEvalZero }
97*10465441SEvalZero END_TEST
98*10465441SEvalZero
99*10465441SEvalZero /** Call tcp_new() and tcp_abort() and test memp stats */
START_TEST(test_tcp_listen_passive_open)100*10465441SEvalZero START_TEST(test_tcp_listen_passive_open)
101*10465441SEvalZero {
102*10465441SEvalZero struct tcp_pcb *pcb, *pcbl;
103*10465441SEvalZero struct tcp_pcb_listen *lpcb;
104*10465441SEvalZero struct netif netif;
105*10465441SEvalZero struct test_tcp_txcounters txcounters;
106*10465441SEvalZero struct test_tcp_counters counters;
107*10465441SEvalZero struct pbuf *p;
108*10465441SEvalZero ip_addr_t src_addr;
109*10465441SEvalZero err_t err;
110*10465441SEvalZero LWIP_UNUSED_ARG(_i);
111*10465441SEvalZero
112*10465441SEvalZero fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
113*10465441SEvalZero
114*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
115*10465441SEvalZero /* initialize counter struct */
116*10465441SEvalZero memset(&counters, 0, sizeof(counters));
117*10465441SEvalZero
118*10465441SEvalZero pcb = tcp_new();
119*10465441SEvalZero EXPECT_RET(pcb != NULL);
120*10465441SEvalZero err = tcp_bind(pcb, &netif.ip_addr, 1234);
121*10465441SEvalZero EXPECT(err == ERR_OK);
122*10465441SEvalZero pcbl = tcp_listen(pcb);
123*10465441SEvalZero EXPECT_RET(pcbl != NULL);
124*10465441SEvalZero EXPECT_RET(pcbl != pcb);
125*10465441SEvalZero lpcb = (struct tcp_pcb_listen *)pcbl;
126*10465441SEvalZero
127*10465441SEvalZero ip_addr_set_ip4_u32_val(src_addr, lwip_htonl(lwip_ntohl(ip_addr_get_ip4_u32(&lpcb->local_ip)) + 1));
128*10465441SEvalZero
129*10465441SEvalZero /* check correct syn packet */
130*10465441SEvalZero p = tcp_create_segment(&src_addr, &lpcb->local_ip, 12345,
131*10465441SEvalZero lpcb->local_port, NULL, 0, 12345, 54321, TCP_SYN);
132*10465441SEvalZero EXPECT(p != NULL);
133*10465441SEvalZero if (p != NULL) {
134*10465441SEvalZero /* pass the segment to tcp_input */
135*10465441SEvalZero test_tcp_input(p, &netif);
136*10465441SEvalZero /* check if counters are as expected */
137*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
138*10465441SEvalZero }
139*10465441SEvalZero
140*10465441SEvalZero /* check syn packet with short length */
141*10465441SEvalZero p = tcp_create_segment(&src_addr, &lpcb->local_ip, 12345,
142*10465441SEvalZero lpcb->local_port, NULL, 0, 12345, 54321, TCP_SYN);
143*10465441SEvalZero EXPECT(p != NULL);
144*10465441SEvalZero EXPECT(p->next == NULL);
145*10465441SEvalZero if ((p != NULL) && (p->next == NULL)) {
146*10465441SEvalZero p->len -= 2;
147*10465441SEvalZero p->tot_len -= 2;
148*10465441SEvalZero /* pass the segment to tcp_input */
149*10465441SEvalZero test_tcp_input(p, &netif);
150*10465441SEvalZero /* check if counters are as expected */
151*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
152*10465441SEvalZero }
153*10465441SEvalZero
154*10465441SEvalZero tcp_close(pcbl);
155*10465441SEvalZero }
156*10465441SEvalZero END_TEST
157*10465441SEvalZero
158*10465441SEvalZero /** Create an ESTABLISHED pcb and check if receive callback is called */
START_TEST(test_tcp_recv_inseq)159*10465441SEvalZero START_TEST(test_tcp_recv_inseq)
160*10465441SEvalZero {
161*10465441SEvalZero struct test_tcp_counters counters;
162*10465441SEvalZero struct tcp_pcb* pcb;
163*10465441SEvalZero struct pbuf* p;
164*10465441SEvalZero char data[] = {1, 2, 3, 4};
165*10465441SEvalZero u16_t data_len;
166*10465441SEvalZero struct netif netif;
167*10465441SEvalZero struct test_tcp_txcounters txcounters;
168*10465441SEvalZero LWIP_UNUSED_ARG(_i);
169*10465441SEvalZero
170*10465441SEvalZero /* initialize local vars */
171*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
172*10465441SEvalZero data_len = sizeof(data);
173*10465441SEvalZero /* initialize counter struct */
174*10465441SEvalZero memset(&counters, 0, sizeof(counters));
175*10465441SEvalZero counters.expected_data_len = data_len;
176*10465441SEvalZero counters.expected_data = data;
177*10465441SEvalZero
178*10465441SEvalZero /* create and initialize the pcb */
179*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
180*10465441SEvalZero EXPECT_RET(pcb != NULL);
181*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
182*10465441SEvalZero
183*10465441SEvalZero /* create a segment */
184*10465441SEvalZero p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
185*10465441SEvalZero EXPECT(p != NULL);
186*10465441SEvalZero if (p != NULL) {
187*10465441SEvalZero /* pass the segment to tcp_input */
188*10465441SEvalZero test_tcp_input(p, &netif);
189*10465441SEvalZero /* check if counters are as expected */
190*10465441SEvalZero EXPECT(counters.close_calls == 0);
191*10465441SEvalZero EXPECT(counters.recv_calls == 1);
192*10465441SEvalZero EXPECT(counters.recved_bytes == data_len);
193*10465441SEvalZero EXPECT(counters.err_calls == 0);
194*10465441SEvalZero }
195*10465441SEvalZero
196*10465441SEvalZero /* make sure the pcb is freed */
197*10465441SEvalZero EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
198*10465441SEvalZero tcp_abort(pcb);
199*10465441SEvalZero EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
200*10465441SEvalZero }
201*10465441SEvalZero END_TEST
202*10465441SEvalZero
203*10465441SEvalZero /** Create an ESTABLISHED pcb and check if receive callback is called if a segment
204*10465441SEvalZero * overlapping rcv_nxt is received */
START_TEST(test_tcp_recv_inseq_trim)205*10465441SEvalZero START_TEST(test_tcp_recv_inseq_trim)
206*10465441SEvalZero {
207*10465441SEvalZero struct test_tcp_counters counters;
208*10465441SEvalZero struct tcp_pcb* pcb;
209*10465441SEvalZero struct pbuf* p;
210*10465441SEvalZero char data[PBUF_POOL_BUFSIZE*2];
211*10465441SEvalZero u16_t data_len;
212*10465441SEvalZero struct netif netif;
213*10465441SEvalZero struct test_tcp_txcounters txcounters;
214*10465441SEvalZero const u32_t new_data_len = 40;
215*10465441SEvalZero LWIP_UNUSED_ARG(_i);
216*10465441SEvalZero
217*10465441SEvalZero /* initialize local vars */
218*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
219*10465441SEvalZero data_len = sizeof(data);
220*10465441SEvalZero memset(data, 0, sizeof(data));
221*10465441SEvalZero /* initialize counter struct */
222*10465441SEvalZero memset(&counters, 0, sizeof(counters));
223*10465441SEvalZero counters.expected_data_len = data_len;
224*10465441SEvalZero counters.expected_data = data;
225*10465441SEvalZero
226*10465441SEvalZero /* create and initialize the pcb */
227*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
228*10465441SEvalZero EXPECT_RET(pcb != NULL);
229*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
230*10465441SEvalZero
231*10465441SEvalZero /* create a segment (with an overlapping/old seqno so that the new data begins in the 2nd pbuf) */
232*10465441SEvalZero p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, (u32_t)(0-(data_len-new_data_len)), 0, 0);
233*10465441SEvalZero EXPECT(p != NULL);
234*10465441SEvalZero if (p != NULL) {
235*10465441SEvalZero EXPECT(p->next != NULL);
236*10465441SEvalZero if (p->next != NULL) {
237*10465441SEvalZero EXPECT(p->next->next != NULL);
238*10465441SEvalZero }
239*10465441SEvalZero }
240*10465441SEvalZero if ((p != NULL) && (p->next != NULL) && (p->next->next != NULL)) {
241*10465441SEvalZero /* pass the segment to tcp_input */
242*10465441SEvalZero test_tcp_input(p, &netif);
243*10465441SEvalZero /* check if counters are as expected */
244*10465441SEvalZero EXPECT(counters.close_calls == 0);
245*10465441SEvalZero EXPECT(counters.recv_calls == 1);
246*10465441SEvalZero EXPECT(counters.recved_bytes == new_data_len);
247*10465441SEvalZero EXPECT(counters.err_calls == 0);
248*10465441SEvalZero }
249*10465441SEvalZero
250*10465441SEvalZero /* make sure the pcb is freed */
251*10465441SEvalZero EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
252*10465441SEvalZero tcp_abort(pcb);
253*10465441SEvalZero EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
254*10465441SEvalZero }
255*10465441SEvalZero END_TEST
256*10465441SEvalZero
257*10465441SEvalZero static err_t test_tcp_recv_expect1byte(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err);
258*10465441SEvalZero
259*10465441SEvalZero static err_t
test_tcp_recv_expectclose(void * arg,struct tcp_pcb * pcb,struct pbuf * p,err_t err)260*10465441SEvalZero test_tcp_recv_expectclose(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
261*10465441SEvalZero {
262*10465441SEvalZero EXPECT_RETX(pcb != NULL, ERR_OK);
263*10465441SEvalZero EXPECT_RETX(err == ERR_OK, ERR_OK);
264*10465441SEvalZero LWIP_UNUSED_ARG(arg);
265*10465441SEvalZero
266*10465441SEvalZero if (p != NULL) {
267*10465441SEvalZero fail();
268*10465441SEvalZero } else {
269*10465441SEvalZero /* correct: FIN received; close our end, too */
270*10465441SEvalZero err_t err2 = tcp_close(pcb);
271*10465441SEvalZero fail_unless(err2 == ERR_OK);
272*10465441SEvalZero /* set back to some other rx function, just to not get here again */
273*10465441SEvalZero tcp_recv(pcb, test_tcp_recv_expect1byte);
274*10465441SEvalZero }
275*10465441SEvalZero return ERR_OK;
276*10465441SEvalZero }
277*10465441SEvalZero
278*10465441SEvalZero static err_t
test_tcp_recv_expect1byte(void * arg,struct tcp_pcb * pcb,struct pbuf * p,err_t err)279*10465441SEvalZero test_tcp_recv_expect1byte(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
280*10465441SEvalZero {
281*10465441SEvalZero EXPECT_RETX(pcb != NULL, ERR_OK);
282*10465441SEvalZero EXPECT_RETX(err == ERR_OK, ERR_OK);
283*10465441SEvalZero LWIP_UNUSED_ARG(arg);
284*10465441SEvalZero
285*10465441SEvalZero if (p != NULL) {
286*10465441SEvalZero if ((p->len == 1) && (p->tot_len == 1)) {
287*10465441SEvalZero tcp_recv(pcb, test_tcp_recv_expectclose);
288*10465441SEvalZero } else {
289*10465441SEvalZero fail();
290*10465441SEvalZero }
291*10465441SEvalZero pbuf_free(p);
292*10465441SEvalZero } else {
293*10465441SEvalZero fail();
294*10465441SEvalZero }
295*10465441SEvalZero return ERR_OK;
296*10465441SEvalZero }
297*10465441SEvalZero
START_TEST(test_tcp_passive_close)298*10465441SEvalZero START_TEST(test_tcp_passive_close)
299*10465441SEvalZero {
300*10465441SEvalZero struct test_tcp_counters counters;
301*10465441SEvalZero struct tcp_pcb* pcb;
302*10465441SEvalZero struct pbuf* p;
303*10465441SEvalZero char data = 0x0f;
304*10465441SEvalZero struct netif netif;
305*10465441SEvalZero struct test_tcp_txcounters txcounters;
306*10465441SEvalZero LWIP_UNUSED_ARG(_i);
307*10465441SEvalZero
308*10465441SEvalZero /* initialize local vars */
309*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
310*10465441SEvalZero
311*10465441SEvalZero /* initialize counter struct */
312*10465441SEvalZero memset(&counters, 0, sizeof(counters));
313*10465441SEvalZero counters.expected_data_len = 1;
314*10465441SEvalZero counters.expected_data = &data;
315*10465441SEvalZero
316*10465441SEvalZero /* create and initialize the pcb */
317*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
318*10465441SEvalZero EXPECT_RET(pcb != NULL);
319*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
320*10465441SEvalZero
321*10465441SEvalZero /* create a segment without data */
322*10465441SEvalZero p = tcp_create_rx_segment(pcb, &data, 1, 0, 0, TCP_FIN);
323*10465441SEvalZero EXPECT(p != NULL);
324*10465441SEvalZero if (p != NULL) {
325*10465441SEvalZero tcp_recv(pcb, test_tcp_recv_expect1byte);
326*10465441SEvalZero /* pass the segment to tcp_input */
327*10465441SEvalZero test_tcp_input(p, &netif);
328*10465441SEvalZero }
329*10465441SEvalZero /* don't free the pcb here (part of the test!) */
330*10465441SEvalZero }
331*10465441SEvalZero END_TEST
332*10465441SEvalZero
333*10465441SEvalZero /** Check that we handle malformed tcp headers, and discard the pbuf(s) */
START_TEST(test_tcp_malformed_header)334*10465441SEvalZero START_TEST(test_tcp_malformed_header)
335*10465441SEvalZero {
336*10465441SEvalZero struct test_tcp_counters counters;
337*10465441SEvalZero struct tcp_pcb* pcb;
338*10465441SEvalZero struct pbuf* p;
339*10465441SEvalZero char data[] = {1, 2, 3, 4};
340*10465441SEvalZero u16_t data_len, chksum;
341*10465441SEvalZero struct netif netif;
342*10465441SEvalZero struct test_tcp_txcounters txcounters;
343*10465441SEvalZero struct tcp_hdr *hdr;
344*10465441SEvalZero LWIP_UNUSED_ARG(_i);
345*10465441SEvalZero
346*10465441SEvalZero /* initialize local vars */
347*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
348*10465441SEvalZero data_len = sizeof(data);
349*10465441SEvalZero /* initialize counter struct */
350*10465441SEvalZero memset(&counters, 0, sizeof(counters));
351*10465441SEvalZero counters.expected_data_len = data_len;
352*10465441SEvalZero counters.expected_data = data;
353*10465441SEvalZero
354*10465441SEvalZero /* create and initialize the pcb */
355*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
356*10465441SEvalZero EXPECT_RET(pcb != NULL);
357*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
358*10465441SEvalZero
359*10465441SEvalZero /* create a segment */
360*10465441SEvalZero p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
361*10465441SEvalZero
362*10465441SEvalZero pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
363*10465441SEvalZero
364*10465441SEvalZero hdr = (struct tcp_hdr *)p->payload;
365*10465441SEvalZero TCPH_HDRLEN_FLAGS_SET(hdr, 15, 0x3d1);
366*10465441SEvalZero
367*10465441SEvalZero hdr->chksum = 0;
368*10465441SEvalZero
369*10465441SEvalZero chksum = ip_chksum_pseudo(p, IP_PROTO_TCP, p->tot_len,
370*10465441SEvalZero &test_remote_ip, &test_local_ip);
371*10465441SEvalZero
372*10465441SEvalZero hdr->chksum = chksum;
373*10465441SEvalZero
374*10465441SEvalZero pbuf_header(p, sizeof(struct ip_hdr));
375*10465441SEvalZero
376*10465441SEvalZero EXPECT(p != NULL);
377*10465441SEvalZero EXPECT(p->next == NULL);
378*10465441SEvalZero if (p != NULL) {
379*10465441SEvalZero /* pass the segment to tcp_input */
380*10465441SEvalZero test_tcp_input(p, &netif);
381*10465441SEvalZero /* check if counters are as expected */
382*10465441SEvalZero EXPECT(counters.close_calls == 0);
383*10465441SEvalZero EXPECT(counters.recv_calls == 0);
384*10465441SEvalZero EXPECT(counters.recved_bytes == 0);
385*10465441SEvalZero EXPECT(counters.err_calls == 0);
386*10465441SEvalZero }
387*10465441SEvalZero
388*10465441SEvalZero /* make sure the pcb is freed */
389*10465441SEvalZero EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
390*10465441SEvalZero tcp_abort(pcb);
391*10465441SEvalZero EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
392*10465441SEvalZero }
393*10465441SEvalZero END_TEST
394*10465441SEvalZero
395*10465441SEvalZero
396*10465441SEvalZero /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
397*10465441SEvalZero * At the end, send more data. */
START_TEST(test_tcp_fast_retx_recover)398*10465441SEvalZero START_TEST(test_tcp_fast_retx_recover)
399*10465441SEvalZero {
400*10465441SEvalZero struct netif netif;
401*10465441SEvalZero struct test_tcp_txcounters txcounters;
402*10465441SEvalZero struct test_tcp_counters counters;
403*10465441SEvalZero struct tcp_pcb* pcb;
404*10465441SEvalZero struct pbuf* p;
405*10465441SEvalZero char data1[] = { 1, 2, 3, 4};
406*10465441SEvalZero char data2[] = { 5, 6, 7, 8};
407*10465441SEvalZero char data3[] = { 9, 10, 11, 12};
408*10465441SEvalZero char data4[] = {13, 14, 15, 16};
409*10465441SEvalZero char data5[] = {17, 18, 19, 20};
410*10465441SEvalZero char data6[TCP_MSS] = {21, 22, 23, 24};
411*10465441SEvalZero err_t err;
412*10465441SEvalZero LWIP_UNUSED_ARG(_i);
413*10465441SEvalZero
414*10465441SEvalZero /* initialize local vars */
415*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
416*10465441SEvalZero memset(&counters, 0, sizeof(counters));
417*10465441SEvalZero
418*10465441SEvalZero /* create and initialize the pcb */
419*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
420*10465441SEvalZero EXPECT_RET(pcb != NULL);
421*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_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 = pcb->snd_wnd;
425*10465441SEvalZero
426*10465441SEvalZero /* send data1 */
427*10465441SEvalZero err = tcp_write(pcb, data1, sizeof(data1), TCP_WRITE_FLAG_COPY);
428*10465441SEvalZero EXPECT_RET(err == ERR_OK);
429*10465441SEvalZero err = tcp_output(pcb);
430*10465441SEvalZero EXPECT_RET(err == ERR_OK);
431*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 1);
432*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
433*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
434*10465441SEvalZero /* "recv" ACK for data1 */
435*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
436*10465441SEvalZero EXPECT_RET(p != NULL);
437*10465441SEvalZero test_tcp_input(p, &netif);
438*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 0);
439*10465441SEvalZero EXPECT_RET(pcb->unacked == NULL);
440*10465441SEvalZero /* send data2 */
441*10465441SEvalZero err = tcp_write(pcb, data2, sizeof(data2), TCP_WRITE_FLAG_COPY);
442*10465441SEvalZero EXPECT_RET(err == ERR_OK);
443*10465441SEvalZero err = tcp_output(pcb);
444*10465441SEvalZero EXPECT_RET(err == ERR_OK);
445*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 1);
446*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
447*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
448*10465441SEvalZero /* duplicate ACK for data1 (data2 is lost) */
449*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
450*10465441SEvalZero EXPECT_RET(p != NULL);
451*10465441SEvalZero test_tcp_input(p, &netif);
452*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 0);
453*10465441SEvalZero EXPECT_RET(pcb->dupacks == 1);
454*10465441SEvalZero /* send data3 */
455*10465441SEvalZero err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
456*10465441SEvalZero EXPECT_RET(err == ERR_OK);
457*10465441SEvalZero err = tcp_output(pcb);
458*10465441SEvalZero EXPECT_RET(err == ERR_OK);
459*10465441SEvalZero /* nagle enabled, no tx calls */
460*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 0);
461*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == 0);
462*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
463*10465441SEvalZero /* 2nd duplicate ACK for data1 (data2 and data3 are lost) */
464*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
465*10465441SEvalZero EXPECT_RET(p != NULL);
466*10465441SEvalZero test_tcp_input(p, &netif);
467*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 0);
468*10465441SEvalZero EXPECT_RET(pcb->dupacks == 2);
469*10465441SEvalZero /* queue data4, don't send it (unsent-oversize is != 0) */
470*10465441SEvalZero err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
471*10465441SEvalZero EXPECT_RET(err == ERR_OK);
472*10465441SEvalZero /* 3nd duplicate ACK for data1 (data2 and data3 are lost) -> fast retransmission */
473*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
474*10465441SEvalZero EXPECT_RET(p != NULL);
475*10465441SEvalZero test_tcp_input(p, &netif);
476*10465441SEvalZero /*EXPECT_RET(txcounters.num_tx_calls == 1);*/
477*10465441SEvalZero EXPECT_RET(pcb->dupacks == 3);
478*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
479*10465441SEvalZero /* @todo: check expected data?*/
480*10465441SEvalZero
481*10465441SEvalZero /* send data5, not output yet */
482*10465441SEvalZero err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
483*10465441SEvalZero EXPECT_RET(err == ERR_OK);
484*10465441SEvalZero /*err = tcp_output(pcb);
485*10465441SEvalZero EXPECT_RET(err == ERR_OK);*/
486*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 0);
487*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == 0);
488*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
489*10465441SEvalZero {
490*10465441SEvalZero int i = 0;
491*10465441SEvalZero do
492*10465441SEvalZero {
493*10465441SEvalZero err = tcp_write(pcb, data6, TCP_MSS, TCP_WRITE_FLAG_COPY);
494*10465441SEvalZero i++;
495*10465441SEvalZero }while(err == ERR_OK);
496*10465441SEvalZero EXPECT_RET(err != ERR_OK);
497*10465441SEvalZero }
498*10465441SEvalZero err = tcp_output(pcb);
499*10465441SEvalZero EXPECT_RET(err == ERR_OK);
500*10465441SEvalZero /*EXPECT_RET(txcounters.num_tx_calls == 0);
501*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == 0);*/
502*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
503*10465441SEvalZero
504*10465441SEvalZero /* send even more data */
505*10465441SEvalZero err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
506*10465441SEvalZero EXPECT_RET(err == ERR_OK);
507*10465441SEvalZero err = tcp_output(pcb);
508*10465441SEvalZero EXPECT_RET(err == ERR_OK);
509*10465441SEvalZero /* ...and even more data */
510*10465441SEvalZero err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
511*10465441SEvalZero EXPECT_RET(err == ERR_OK);
512*10465441SEvalZero err = tcp_output(pcb);
513*10465441SEvalZero EXPECT_RET(err == ERR_OK);
514*10465441SEvalZero /* ...and even more data */
515*10465441SEvalZero err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
516*10465441SEvalZero EXPECT_RET(err == ERR_OK);
517*10465441SEvalZero err = tcp_output(pcb);
518*10465441SEvalZero EXPECT_RET(err == ERR_OK);
519*10465441SEvalZero /* ...and even more data */
520*10465441SEvalZero err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
521*10465441SEvalZero EXPECT_RET(err == ERR_OK);
522*10465441SEvalZero err = tcp_output(pcb);
523*10465441SEvalZero EXPECT_RET(err == ERR_OK);
524*10465441SEvalZero
525*10465441SEvalZero /* send ACKs for data2 and data3 */
526*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 12, TCP_ACK);
527*10465441SEvalZero EXPECT_RET(p != NULL);
528*10465441SEvalZero test_tcp_input(p, &netif);
529*10465441SEvalZero /*EXPECT_RET(txcounters.num_tx_calls == 0);*/
530*10465441SEvalZero
531*10465441SEvalZero /* ...and even more data */
532*10465441SEvalZero err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
533*10465441SEvalZero EXPECT_RET(err == ERR_OK);
534*10465441SEvalZero err = tcp_output(pcb);
535*10465441SEvalZero EXPECT_RET(err == ERR_OK);
536*10465441SEvalZero /* ...and even more data */
537*10465441SEvalZero err = tcp_write(pcb, data5, sizeof(data5), TCP_WRITE_FLAG_COPY);
538*10465441SEvalZero EXPECT_RET(err == ERR_OK);
539*10465441SEvalZero err = tcp_output(pcb);
540*10465441SEvalZero EXPECT_RET(err == ERR_OK);
541*10465441SEvalZero
542*10465441SEvalZero #if 0
543*10465441SEvalZero /* create expected segment */
544*10465441SEvalZero p1 = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
545*10465441SEvalZero EXPECT_RET(p != NULL);
546*10465441SEvalZero if (p != NULL) {
547*10465441SEvalZero /* pass the segment to tcp_input */
548*10465441SEvalZero test_tcp_input(p, &netif);
549*10465441SEvalZero /* check if counters are as expected */
550*10465441SEvalZero EXPECT_RET(counters.close_calls == 0);
551*10465441SEvalZero EXPECT_RET(counters.recv_calls == 1);
552*10465441SEvalZero EXPECT_RET(counters.recved_bytes == data_len);
553*10465441SEvalZero EXPECT_RET(counters.err_calls == 0);
554*10465441SEvalZero }
555*10465441SEvalZero #endif
556*10465441SEvalZero /* make sure the pcb is freed */
557*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
558*10465441SEvalZero tcp_abort(pcb);
559*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
560*10465441SEvalZero }
561*10465441SEvalZero END_TEST
562*10465441SEvalZero
563*10465441SEvalZero static u8_t tx_data[TCP_WND*2];
564*10465441SEvalZero
565*10465441SEvalZero static void
check_seqnos(struct tcp_seg * segs,int num_expected,u32_t * seqnos_expected)566*10465441SEvalZero check_seqnos(struct tcp_seg *segs, int num_expected, u32_t *seqnos_expected)
567*10465441SEvalZero {
568*10465441SEvalZero struct tcp_seg *s = segs;
569*10465441SEvalZero int i;
570*10465441SEvalZero for (i = 0; i < num_expected; i++, s = s->next) {
571*10465441SEvalZero EXPECT_RET(s != NULL);
572*10465441SEvalZero EXPECT(s->tcphdr->seqno == htonl(seqnos_expected[i]));
573*10465441SEvalZero }
574*10465441SEvalZero EXPECT(s == NULL);
575*10465441SEvalZero }
576*10465441SEvalZero
577*10465441SEvalZero /** Send data with sequence numbers that wrap around the u32_t range.
578*10465441SEvalZero * Then, provoke fast retransmission by duplicate ACKs and check that all
579*10465441SEvalZero * segment lists are still properly sorted. */
START_TEST(test_tcp_fast_rexmit_wraparound)580*10465441SEvalZero START_TEST(test_tcp_fast_rexmit_wraparound)
581*10465441SEvalZero {
582*10465441SEvalZero struct netif netif;
583*10465441SEvalZero struct test_tcp_txcounters txcounters;
584*10465441SEvalZero struct test_tcp_counters counters;
585*10465441SEvalZero struct tcp_pcb* pcb;
586*10465441SEvalZero struct pbuf* p;
587*10465441SEvalZero err_t err;
588*10465441SEvalZero size_t i;
589*10465441SEvalZero u16_t sent_total = 0;
590*10465441SEvalZero LWIP_UNUSED_ARG(_i);
591*10465441SEvalZero
592*10465441SEvalZero for (i = 0; i < sizeof(tx_data); i++) {
593*10465441SEvalZero tx_data[i] = (u8_t)i;
594*10465441SEvalZero }
595*10465441SEvalZero
596*10465441SEvalZero /* initialize local vars */
597*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
598*10465441SEvalZero memset(&counters, 0, sizeof(counters));
599*10465441SEvalZero
600*10465441SEvalZero /* create and initialize the pcb */
601*10465441SEvalZero tcp_ticks = SEQNO1 - ISS;
602*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
603*10465441SEvalZero EXPECT_RET(pcb != NULL);
604*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
605*10465441SEvalZero pcb->mss = TCP_MSS;
606*10465441SEvalZero /* disable initial congestion window (we don't send a SYN here...) */
607*10465441SEvalZero pcb->cwnd = 2*TCP_MSS;
608*10465441SEvalZero /* start in congestion advoidance */
609*10465441SEvalZero pcb->ssthresh = pcb->cwnd;
610*10465441SEvalZero
611*10465441SEvalZero /* send 6 mss-sized segments */
612*10465441SEvalZero for (i = 0; i < 6; i++) {
613*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
614*10465441SEvalZero EXPECT_RET(err == ERR_OK);
615*10465441SEvalZero sent_total += TCP_MSS;
616*10465441SEvalZero }
617*10465441SEvalZero check_seqnos(pcb->unsent, 6, seqnos);
618*10465441SEvalZero EXPECT(pcb->unacked == NULL);
619*10465441SEvalZero err = tcp_output(pcb);
620*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 2);
621*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
622*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
623*10465441SEvalZero
624*10465441SEvalZero check_seqnos(pcb->unacked, 2, seqnos);
625*10465441SEvalZero check_seqnos(pcb->unsent, 4, &seqnos[2]);
626*10465441SEvalZero
627*10465441SEvalZero /* ACK the first segment */
628*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
629*10465441SEvalZero test_tcp_input(p, &netif);
630*10465441SEvalZero /* ensure this didn't trigger a retransmission. Only one
631*10465441SEvalZero segment should be transmitted because cwnd opened up by
632*10465441SEvalZero TCP_MSS and a fraction since we are in congestion avoidance */
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 check_seqnos(pcb->unacked, 2, &seqnos[1]);
637*10465441SEvalZero check_seqnos(pcb->unsent, 3, &seqnos[3]);
638*10465441SEvalZero
639*10465441SEvalZero /* 3 dupacks */
640*10465441SEvalZero EXPECT(pcb->dupacks == 0);
641*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
642*10465441SEvalZero test_tcp_input(p, &netif);
643*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
644*10465441SEvalZero EXPECT(pcb->dupacks == 1);
645*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
646*10465441SEvalZero test_tcp_input(p, &netif);
647*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
648*10465441SEvalZero EXPECT(pcb->dupacks == 2);
649*10465441SEvalZero /* 3rd dupack -> fast rexmit */
650*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
651*10465441SEvalZero test_tcp_input(p, &netif);
652*10465441SEvalZero EXPECT(pcb->dupacks == 3);
653*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 4);
654*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
655*10465441SEvalZero EXPECT(pcb->unsent == NULL);
656*10465441SEvalZero check_seqnos(pcb->unacked, 5, &seqnos[1]);
657*10465441SEvalZero
658*10465441SEvalZero /* make sure the pcb is freed */
659*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
660*10465441SEvalZero tcp_abort(pcb);
661*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
662*10465441SEvalZero }
663*10465441SEvalZero END_TEST
664*10465441SEvalZero
665*10465441SEvalZero /** Send data with sequence numbers that wrap around the u32_t range.
666*10465441SEvalZero * Then, provoke RTO retransmission and check that all
667*10465441SEvalZero * segment lists are still properly sorted. */
START_TEST(test_tcp_rto_rexmit_wraparound)668*10465441SEvalZero START_TEST(test_tcp_rto_rexmit_wraparound)
669*10465441SEvalZero {
670*10465441SEvalZero struct netif netif;
671*10465441SEvalZero struct test_tcp_txcounters txcounters;
672*10465441SEvalZero struct test_tcp_counters counters;
673*10465441SEvalZero struct tcp_pcb* pcb;
674*10465441SEvalZero struct tcp_pcb dummy_pcb_for_iss; /* we need this for tcp_next_iss() only */
675*10465441SEvalZero err_t err;
676*10465441SEvalZero size_t i;
677*10465441SEvalZero u16_t sent_total = 0;
678*10465441SEvalZero LWIP_UNUSED_ARG(_i);
679*10465441SEvalZero
680*10465441SEvalZero for (i = 0; i < sizeof(tx_data); i++) {
681*10465441SEvalZero tx_data[i] = (u8_t)i;
682*10465441SEvalZero }
683*10465441SEvalZero
684*10465441SEvalZero /* initialize local vars */
685*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
686*10465441SEvalZero memset(&counters, 0, sizeof(counters));
687*10465441SEvalZero
688*10465441SEvalZero /* create and initialize the pcb */
689*10465441SEvalZero tcp_ticks = 0;
690*10465441SEvalZero tcp_ticks = 0 - tcp_next_iss(&dummy_pcb_for_iss);
691*10465441SEvalZero tcp_ticks = SEQNO1 - tcp_next_iss(&dummy_pcb_for_iss);
692*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
693*10465441SEvalZero EXPECT_RET(pcb != NULL);
694*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
695*10465441SEvalZero pcb->mss = TCP_MSS;
696*10465441SEvalZero /* disable initial congestion window (we don't send a SYN here...) */
697*10465441SEvalZero pcb->cwnd = 2*TCP_MSS;
698*10465441SEvalZero
699*10465441SEvalZero /* send 6 mss-sized segments */
700*10465441SEvalZero for (i = 0; i < 6; i++) {
701*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
702*10465441SEvalZero EXPECT_RET(err == ERR_OK);
703*10465441SEvalZero sent_total += TCP_MSS;
704*10465441SEvalZero }
705*10465441SEvalZero check_seqnos(pcb->unsent, 6, seqnos);
706*10465441SEvalZero EXPECT(pcb->unacked == NULL);
707*10465441SEvalZero err = tcp_output(pcb);
708*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 2);
709*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
710*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
711*10465441SEvalZero
712*10465441SEvalZero check_seqnos(pcb->unacked, 2, seqnos);
713*10465441SEvalZero check_seqnos(pcb->unsent, 4, &seqnos[2]);
714*10465441SEvalZero
715*10465441SEvalZero /* call the tcp timer some times */
716*10465441SEvalZero for (i = 0; i < 10; i++) {
717*10465441SEvalZero test_tcp_tmr();
718*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
719*10465441SEvalZero }
720*10465441SEvalZero /* 11th call to tcp_tmr: RTO rexmit fires */
721*10465441SEvalZero test_tcp_tmr();
722*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
723*10465441SEvalZero check_seqnos(pcb->unacked, 1, seqnos);
724*10465441SEvalZero check_seqnos(pcb->unsent, 5, &seqnos[1]);
725*10465441SEvalZero
726*10465441SEvalZero /* fake greater cwnd */
727*10465441SEvalZero pcb->cwnd = pcb->snd_wnd;
728*10465441SEvalZero /* send more data */
729*10465441SEvalZero err = tcp_output(pcb);
730*10465441SEvalZero EXPECT(err == ERR_OK);
731*10465441SEvalZero /* check queues are sorted */
732*10465441SEvalZero EXPECT(pcb->unsent == NULL);
733*10465441SEvalZero check_seqnos(pcb->unacked, 6, seqnos);
734*10465441SEvalZero
735*10465441SEvalZero /* make sure the pcb is freed */
736*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
737*10465441SEvalZero tcp_abort(pcb);
738*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
739*10465441SEvalZero }
740*10465441SEvalZero END_TEST
741*10465441SEvalZero
742*10465441SEvalZero /** Provoke fast retransmission by duplicate ACKs and then recover by ACKing all sent data.
743*10465441SEvalZero * At the end, send more data. */
test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)744*10465441SEvalZero static void test_tcp_tx_full_window_lost(u8_t zero_window_probe_from_unsent)
745*10465441SEvalZero {
746*10465441SEvalZero struct netif netif;
747*10465441SEvalZero struct test_tcp_txcounters txcounters;
748*10465441SEvalZero struct test_tcp_counters counters;
749*10465441SEvalZero struct tcp_pcb* pcb;
750*10465441SEvalZero struct pbuf *p;
751*10465441SEvalZero err_t err;
752*10465441SEvalZero size_t i;
753*10465441SEvalZero u16_t sent_total;
754*10465441SEvalZero u8_t expected = 0xFE;
755*10465441SEvalZero
756*10465441SEvalZero for (i = 0; i < sizeof(tx_data); i++) {
757*10465441SEvalZero u8_t d = (u8_t)i;
758*10465441SEvalZero if (d == 0xFE) {
759*10465441SEvalZero d = 0xF0;
760*10465441SEvalZero }
761*10465441SEvalZero tx_data[i] = d;
762*10465441SEvalZero }
763*10465441SEvalZero if (zero_window_probe_from_unsent) {
764*10465441SEvalZero tx_data[TCP_WND] = expected;
765*10465441SEvalZero } else {
766*10465441SEvalZero tx_data[0] = expected;
767*10465441SEvalZero }
768*10465441SEvalZero
769*10465441SEvalZero /* initialize local vars */
770*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
771*10465441SEvalZero memset(&counters, 0, sizeof(counters));
772*10465441SEvalZero
773*10465441SEvalZero /* create and initialize the pcb */
774*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
775*10465441SEvalZero EXPECT_RET(pcb != NULL);
776*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
777*10465441SEvalZero pcb->mss = TCP_MSS;
778*10465441SEvalZero /* disable initial congestion window (we don't send a SYN here...) */
779*10465441SEvalZero pcb->cwnd = pcb->snd_wnd;
780*10465441SEvalZero
781*10465441SEvalZero /* send a full window (minus 1 packets) of TCP data in MSS-sized chunks */
782*10465441SEvalZero sent_total = 0;
783*10465441SEvalZero if ((TCP_WND - TCP_MSS) % TCP_MSS != 0) {
784*10465441SEvalZero u16_t initial_data_len = (TCP_WND - TCP_MSS) % TCP_MSS;
785*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], initial_data_len, TCP_WRITE_FLAG_COPY);
786*10465441SEvalZero EXPECT_RET(err == ERR_OK);
787*10465441SEvalZero err = tcp_output(pcb);
788*10465441SEvalZero EXPECT_RET(err == ERR_OK);
789*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
790*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == initial_data_len + 40U);
791*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
792*10465441SEvalZero sent_total += initial_data_len;
793*10465441SEvalZero }
794*10465441SEvalZero for (; sent_total < (TCP_WND - TCP_MSS); sent_total += TCP_MSS) {
795*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
796*10465441SEvalZero EXPECT_RET(err == ERR_OK);
797*10465441SEvalZero err = tcp_output(pcb);
798*10465441SEvalZero EXPECT_RET(err == ERR_OK);
799*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
800*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
801*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
802*10465441SEvalZero }
803*10465441SEvalZero EXPECT(sent_total == (TCP_WND - TCP_MSS));
804*10465441SEvalZero
805*10465441SEvalZero /* now ACK the packet before the first */
806*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_ACK);
807*10465441SEvalZero test_tcp_input(p, &netif);
808*10465441SEvalZero /* ensure this didn't trigger a retransmission */
809*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
810*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
811*10465441SEvalZero
812*10465441SEvalZero EXPECT(pcb->persist_backoff == 0);
813*10465441SEvalZero /* send the last packet, now a complete window has been sent */
814*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
815*10465441SEvalZero sent_total += TCP_MSS;
816*10465441SEvalZero EXPECT_RET(err == ERR_OK);
817*10465441SEvalZero err = tcp_output(pcb);
818*10465441SEvalZero EXPECT_RET(err == ERR_OK);
819*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
820*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
821*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
822*10465441SEvalZero EXPECT(pcb->persist_backoff == 0);
823*10465441SEvalZero
824*10465441SEvalZero if (zero_window_probe_from_unsent) {
825*10465441SEvalZero /* ACK all data but close the TX window */
826*10465441SEvalZero p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_WND, TCP_ACK, 0);
827*10465441SEvalZero test_tcp_input(p, &netif);
828*10465441SEvalZero /* ensure this didn't trigger any transmission */
829*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
830*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
831*10465441SEvalZero /* window is completely full, but persist timer is off since send buffer is empty */
832*10465441SEvalZero EXPECT(pcb->snd_wnd == 0);
833*10465441SEvalZero EXPECT(pcb->persist_backoff == 0);
834*10465441SEvalZero }
835*10465441SEvalZero
836*10465441SEvalZero /* send one byte more (out of window) -> persist timer starts */
837*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], 1, TCP_WRITE_FLAG_COPY);
838*10465441SEvalZero EXPECT_RET(err == ERR_OK);
839*10465441SEvalZero err = tcp_output(pcb);
840*10465441SEvalZero EXPECT_RET(err == ERR_OK);
841*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
842*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
843*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
844*10465441SEvalZero if (!zero_window_probe_from_unsent) {
845*10465441SEvalZero /* no persist timer unless a zero window announcement has been received */
846*10465441SEvalZero EXPECT(pcb->persist_backoff == 0);
847*10465441SEvalZero } else {
848*10465441SEvalZero EXPECT(pcb->persist_backoff == 1);
849*10465441SEvalZero
850*10465441SEvalZero /* call tcp_timer some more times to let persist timer count up */
851*10465441SEvalZero for (i = 0; i < 4; i++) {
852*10465441SEvalZero test_tcp_tmr();
853*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
854*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
855*10465441SEvalZero }
856*10465441SEvalZero
857*10465441SEvalZero /* this should trigger the zero-window-probe */
858*10465441SEvalZero txcounters.copy_tx_packets = 1;
859*10465441SEvalZero test_tcp_tmr();
860*10465441SEvalZero txcounters.copy_tx_packets = 0;
861*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
862*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 1 + 40U);
863*10465441SEvalZero EXPECT(txcounters.tx_packets != NULL);
864*10465441SEvalZero if (txcounters.tx_packets != NULL) {
865*10465441SEvalZero u8_t sent;
866*10465441SEvalZero u16_t ret;
867*10465441SEvalZero ret = pbuf_copy_partial(txcounters.tx_packets, &sent, 1, 40U);
868*10465441SEvalZero EXPECT(ret == 1);
869*10465441SEvalZero EXPECT(sent == expected);
870*10465441SEvalZero }
871*10465441SEvalZero if (txcounters.tx_packets != NULL) {
872*10465441SEvalZero pbuf_free(txcounters.tx_packets);
873*10465441SEvalZero txcounters.tx_packets = NULL;
874*10465441SEvalZero }
875*10465441SEvalZero }
876*10465441SEvalZero
877*10465441SEvalZero /* make sure the pcb is freed */
878*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
879*10465441SEvalZero tcp_abort(pcb);
880*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
881*10465441SEvalZero }
882*10465441SEvalZero
START_TEST(test_tcp_tx_full_window_lost_from_unsent)883*10465441SEvalZero START_TEST(test_tcp_tx_full_window_lost_from_unsent)
884*10465441SEvalZero {
885*10465441SEvalZero LWIP_UNUSED_ARG(_i);
886*10465441SEvalZero test_tcp_tx_full_window_lost(1);
887*10465441SEvalZero }
888*10465441SEvalZero END_TEST
889*10465441SEvalZero
START_TEST(test_tcp_tx_full_window_lost_from_unacked)890*10465441SEvalZero START_TEST(test_tcp_tx_full_window_lost_from_unacked)
891*10465441SEvalZero {
892*10465441SEvalZero LWIP_UNUSED_ARG(_i);
893*10465441SEvalZero test_tcp_tx_full_window_lost(0);
894*10465441SEvalZero }
895*10465441SEvalZero END_TEST
896*10465441SEvalZero
897*10465441SEvalZero /** Send data, provoke retransmission and then add data to a segment
898*10465441SEvalZero * that already has been sent before. */
START_TEST(test_tcp_retx_add_to_sent)899*10465441SEvalZero START_TEST(test_tcp_retx_add_to_sent)
900*10465441SEvalZero {
901*10465441SEvalZero struct netif netif;
902*10465441SEvalZero struct test_tcp_txcounters txcounters;
903*10465441SEvalZero struct test_tcp_counters counters;
904*10465441SEvalZero struct tcp_pcb* pcb;
905*10465441SEvalZero struct pbuf* p;
906*10465441SEvalZero char data1a[] = { 1, 2, 3};
907*10465441SEvalZero char data1b[] = { 4};
908*10465441SEvalZero char data2a[] = { 5, 6, 7, 8};
909*10465441SEvalZero char data2b[] = { 5, 6, 7};
910*10465441SEvalZero char data3[] = { 9, 10, 11, 12, 12};
911*10465441SEvalZero char data4[] = { 13, 14, 15, 16,17};
912*10465441SEvalZero err_t err;
913*10465441SEvalZero int i;
914*10465441SEvalZero LWIP_UNUSED_ARG(_i);
915*10465441SEvalZero
916*10465441SEvalZero /* initialize local vars */
917*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
918*10465441SEvalZero memset(&counters, 0, sizeof(counters));
919*10465441SEvalZero
920*10465441SEvalZero /* create and initialize the pcb */
921*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
922*10465441SEvalZero EXPECT_RET(pcb != NULL);
923*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
924*10465441SEvalZero pcb->mss = TCP_MSS;
925*10465441SEvalZero /* disable initial congestion window (we don't send a SYN here...) */
926*10465441SEvalZero pcb->cwnd = pcb->snd_wnd;
927*10465441SEvalZero
928*10465441SEvalZero /* send data1 */
929*10465441SEvalZero err = tcp_write(pcb, data1a, sizeof(data1a), TCP_WRITE_FLAG_COPY);
930*10465441SEvalZero EXPECT_RET(err == ERR_OK);
931*10465441SEvalZero err = tcp_write(pcb, data1b, sizeof(data1b), TCP_WRITE_FLAG_COPY);
932*10465441SEvalZero EXPECT_RET(err == ERR_OK);
933*10465441SEvalZero err = tcp_output(pcb);
934*10465441SEvalZero EXPECT_RET(err == ERR_OK);
935*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 1);
936*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == sizeof(data1a) + sizeof(data1b) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
937*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
938*10465441SEvalZero /* "recv" ACK for data1 */
939*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 4, TCP_ACK);
940*10465441SEvalZero EXPECT_RET(p != NULL);
941*10465441SEvalZero test_tcp_input(p, &netif);
942*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 0);
943*10465441SEvalZero EXPECT_RET(pcb->unacked == NULL);
944*10465441SEvalZero /* send data2 */
945*10465441SEvalZero err = tcp_write(pcb, data2a, sizeof(data2a), TCP_WRITE_FLAG_COPY);
946*10465441SEvalZero EXPECT_RET(err == ERR_OK);
947*10465441SEvalZero err = tcp_write(pcb, data2b, sizeof(data2b), TCP_WRITE_FLAG_COPY);
948*10465441SEvalZero EXPECT_RET(err == ERR_OK);
949*10465441SEvalZero err = tcp_output(pcb);
950*10465441SEvalZero EXPECT_RET(err == ERR_OK);
951*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 1);
952*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2a) + sizeof(data2b) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
953*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
954*10465441SEvalZero /* send data3 */
955*10465441SEvalZero err = tcp_write(pcb, data3, sizeof(data3), TCP_WRITE_FLAG_COPY);
956*10465441SEvalZero EXPECT_RET(err == ERR_OK);
957*10465441SEvalZero err = tcp_output(pcb);
958*10465441SEvalZero EXPECT_RET(err == ERR_OK);
959*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 0);
960*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == 0);
961*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
962*10465441SEvalZero
963*10465441SEvalZero /* data3 not sent yet (nagle) */
964*10465441SEvalZero EXPECT_RET(pcb->unacked != NULL);
965*10465441SEvalZero EXPECT_RET(pcb->unsent != NULL);
966*10465441SEvalZero
967*10465441SEvalZero /* disable nagle for this test so data to sent segment can be added below... */
968*10465441SEvalZero tcp_nagle_disable(pcb);
969*10465441SEvalZero
970*10465441SEvalZero /* call the tcp timer some times */
971*10465441SEvalZero for (i = 0; i < 20; i++) {
972*10465441SEvalZero test_tcp_tmr();
973*10465441SEvalZero if (txcounters.num_tx_calls != 0) {
974*10465441SEvalZero break;
975*10465441SEvalZero }
976*10465441SEvalZero }
977*10465441SEvalZero /* data3 sent */
978*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 1);
979*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == sizeof(data3) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
980*10465441SEvalZero EXPECT_RET(pcb->unacked != NULL);
981*10465441SEvalZero EXPECT_RET(pcb->unsent == NULL);
982*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
983*10465441SEvalZero
984*10465441SEvalZero tcp_nagle_enable(pcb);
985*10465441SEvalZero
986*10465441SEvalZero /* call the tcp timer some times */
987*10465441SEvalZero for (i = 0; i < 20; i++) {
988*10465441SEvalZero test_tcp_tmr();
989*10465441SEvalZero if (txcounters.num_tx_calls != 0) {
990*10465441SEvalZero break;
991*10465441SEvalZero }
992*10465441SEvalZero }
993*10465441SEvalZero /* RTO: rexmit of data2 */
994*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 1);
995*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == sizeof(data2a) + sizeof(data2b) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
996*10465441SEvalZero EXPECT_RET(pcb->unacked != NULL);
997*10465441SEvalZero EXPECT_RET(pcb->unsent != NULL);
998*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
999*10465441SEvalZero
1000*10465441SEvalZero /* send data4 */
1001*10465441SEvalZero err = tcp_write(pcb, data4, sizeof(data4), TCP_WRITE_FLAG_COPY);
1002*10465441SEvalZero EXPECT_RET(err == ERR_OK);
1003*10465441SEvalZero /* disable nagle for this test so data to transmit without further ACKs... */
1004*10465441SEvalZero tcp_nagle_disable(pcb);
1005*10465441SEvalZero err = tcp_output(pcb);
1006*10465441SEvalZero EXPECT_RET(err == ERR_OK);
1007*10465441SEvalZero /* nagle enabled, no tx calls */
1008*10465441SEvalZero EXPECT_RET(txcounters.num_tx_calls == 1);
1009*10465441SEvalZero EXPECT_RET(txcounters.num_tx_bytes == sizeof(data3) + sizeof(data4) + sizeof(struct tcp_hdr) + sizeof(struct ip_hdr));
1010*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1011*10465441SEvalZero /* make sure the pcb is freed */
1012*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
1013*10465441SEvalZero tcp_abort(pcb);
1014*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1015*10465441SEvalZero }
1016*10465441SEvalZero END_TEST
1017*10465441SEvalZero
START_TEST(test_tcp_rto_tracking)1018*10465441SEvalZero START_TEST(test_tcp_rto_tracking)
1019*10465441SEvalZero {
1020*10465441SEvalZero struct netif netif;
1021*10465441SEvalZero struct test_tcp_txcounters txcounters;
1022*10465441SEvalZero struct test_tcp_counters counters;
1023*10465441SEvalZero struct tcp_pcb* pcb;
1024*10465441SEvalZero struct pbuf* p;
1025*10465441SEvalZero err_t err;
1026*10465441SEvalZero size_t i;
1027*10465441SEvalZero u16_t sent_total = 0;
1028*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1029*10465441SEvalZero
1030*10465441SEvalZero for (i = 0; i < sizeof(tx_data); i++) {
1031*10465441SEvalZero tx_data[i] = (u8_t)i;
1032*10465441SEvalZero }
1033*10465441SEvalZero
1034*10465441SEvalZero /* initialize local vars */
1035*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
1036*10465441SEvalZero memset(&counters, 0, sizeof(counters));
1037*10465441SEvalZero
1038*10465441SEvalZero /* create and initialize the pcb */
1039*10465441SEvalZero tcp_ticks = SEQNO1 - ISS;
1040*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
1041*10465441SEvalZero EXPECT_RET(pcb != NULL);
1042*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
1043*10465441SEvalZero pcb->mss = TCP_MSS;
1044*10465441SEvalZero /* Set congestion window large enough to send all our segments */
1045*10465441SEvalZero pcb->cwnd = 5*TCP_MSS;
1046*10465441SEvalZero
1047*10465441SEvalZero /* send 5 mss-sized segments */
1048*10465441SEvalZero for (i = 0; i < 5; i++) {
1049*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
1050*10465441SEvalZero EXPECT_RET(err == ERR_OK);
1051*10465441SEvalZero sent_total += TCP_MSS;
1052*10465441SEvalZero }
1053*10465441SEvalZero check_seqnos(pcb->unsent, 5, seqnos);
1054*10465441SEvalZero EXPECT(pcb->unacked == NULL);
1055*10465441SEvalZero err = tcp_output(pcb);
1056*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 5);
1057*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 5 * (TCP_MSS + 40U));
1058*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1059*10465441SEvalZero /* Check all 5 are in-flight */
1060*10465441SEvalZero EXPECT(pcb->unsent == NULL);
1061*10465441SEvalZero check_seqnos(pcb->unacked, 5, seqnos);
1062*10465441SEvalZero
1063*10465441SEvalZero /* Force us into retransmisson timeout */
1064*10465441SEvalZero while (!(pcb->flags & TF_RTO)) {
1065*10465441SEvalZero test_tcp_tmr();
1066*10465441SEvalZero }
1067*10465441SEvalZero /* Ensure 4 remaining segments are back on unsent, ready for retransmission */
1068*10465441SEvalZero check_seqnos(pcb->unsent, 4, &seqnos[1]);
1069*10465441SEvalZero /* Ensure 1st segment is on unacked (already retransmitted) */
1070*10465441SEvalZero check_seqnos(pcb->unacked, 1, seqnos);
1071*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1072*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == TCP_MSS + 40U);
1073*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1074*10465441SEvalZero /* Ensure rto_end points to next byte */
1075*10465441SEvalZero EXPECT(pcb->rto_end == seqnos[5]);
1076*10465441SEvalZero EXPECT(pcb->rto_end == pcb->snd_nxt);
1077*10465441SEvalZero /* Check cwnd was reset */
1078*10465441SEvalZero EXPECT(pcb->cwnd == pcb->mss);
1079*10465441SEvalZero
1080*10465441SEvalZero /* Add another segment to send buffer which is outside of RTO */
1081*10465441SEvalZero err = tcp_write(pcb, &tx_data[sent_total], TCP_MSS, TCP_WRITE_FLAG_COPY);
1082*10465441SEvalZero EXPECT_RET(err == ERR_OK);
1083*10465441SEvalZero sent_total += TCP_MSS;
1084*10465441SEvalZero check_seqnos(pcb->unsent, 5, &seqnos[1]);
1085*10465441SEvalZero /* Ensure no new data was sent */
1086*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
1087*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
1088*10465441SEvalZero EXPECT(pcb->rto_end == pcb->snd_nxt);
1089*10465441SEvalZero
1090*10465441SEvalZero /* ACK first segment */
1091*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK);
1092*10465441SEvalZero test_tcp_input(p, &netif);
1093*10465441SEvalZero /* Next two retranmissions should go out, due to cwnd in slow start */
1094*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 2);
1095*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 2 * (TCP_MSS + 40U));
1096*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1097*10465441SEvalZero check_seqnos(pcb->unacked, 2, &seqnos[1]);
1098*10465441SEvalZero check_seqnos(pcb->unsent, 3, &seqnos[3]);
1099*10465441SEvalZero /* RTO should still be marked */
1100*10465441SEvalZero EXPECT(pcb->flags & TF_RTO);
1101*10465441SEvalZero /* cwnd should have only grown by 1 MSS */
1102*10465441SEvalZero EXPECT(pcb->cwnd == (tcpwnd_size_t)(2 * pcb->mss));
1103*10465441SEvalZero /* Ensure no new data was sent */
1104*10465441SEvalZero EXPECT(pcb->rto_end == pcb->snd_nxt);
1105*10465441SEvalZero
1106*10465441SEvalZero /* ACK the next two segments */
1107*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 2*TCP_MSS, TCP_ACK);
1108*10465441SEvalZero test_tcp_input(p, &netif);
1109*10465441SEvalZero /* Final 2 retransmissions and 1 new data should go out */
1110*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 3);
1111*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 3 * (TCP_MSS + 40U));
1112*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1113*10465441SEvalZero check_seqnos(pcb->unacked, 3, &seqnos[3]);
1114*10465441SEvalZero EXPECT(pcb->unsent == NULL);
1115*10465441SEvalZero /* RTO should still be marked */
1116*10465441SEvalZero EXPECT(pcb->flags & TF_RTO);
1117*10465441SEvalZero /* cwnd should have only grown by 1 MSS */
1118*10465441SEvalZero EXPECT(pcb->cwnd == (tcpwnd_size_t)(3 * pcb->mss));
1119*10465441SEvalZero /* snd_nxt should have been advanced past rto_end */
1120*10465441SEvalZero EXPECT(TCP_SEQ_GT(pcb->snd_nxt, pcb->rto_end));
1121*10465441SEvalZero
1122*10465441SEvalZero /* ACK the next two segments, finishing our RTO, leaving new segment unacked */
1123*10465441SEvalZero p = tcp_create_rx_segment(pcb, NULL, 0, 0, 2*TCP_MSS, TCP_ACK);
1124*10465441SEvalZero test_tcp_input(p, &netif);
1125*10465441SEvalZero EXPECT(!(pcb->flags & TF_RTO));
1126*10465441SEvalZero check_seqnos(pcb->unacked, 1, &seqnos[5]);
1127*10465441SEvalZero /* We should be in ABC congestion avoidance, so no change in cwnd */
1128*10465441SEvalZero EXPECT(pcb->cwnd == (tcpwnd_size_t)(3 * pcb->mss));
1129*10465441SEvalZero EXPECT(pcb->cwnd >= pcb->ssthresh);
1130*10465441SEvalZero /* Ensure ABC congestion avoidance is tracking bytes acked */
1131*10465441SEvalZero EXPECT(pcb->bytes_acked == (tcpwnd_size_t)(2 * pcb->mss));
1132*10465441SEvalZero
1133*10465441SEvalZero /* make sure the pcb is freed */
1134*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
1135*10465441SEvalZero tcp_abort(pcb);
1136*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1137*10465441SEvalZero }
1138*10465441SEvalZero END_TEST
1139*10465441SEvalZero
test_tcp_rto_timeout_impl(int link_down)1140*10465441SEvalZero static void test_tcp_rto_timeout_impl(int link_down)
1141*10465441SEvalZero {
1142*10465441SEvalZero struct netif netif;
1143*10465441SEvalZero struct test_tcp_txcounters txcounters;
1144*10465441SEvalZero struct test_tcp_counters counters;
1145*10465441SEvalZero struct tcp_pcb *pcb, *cur;
1146*10465441SEvalZero err_t err;
1147*10465441SEvalZero size_t i;
1148*10465441SEvalZero const size_t max_wait_ctr = 1024 * 1024;
1149*10465441SEvalZero
1150*10465441SEvalZero /* Setup data for a single segment */
1151*10465441SEvalZero for (i = 0; i < TCP_MSS; i++) {
1152*10465441SEvalZero tx_data[i] = (u8_t)i;
1153*10465441SEvalZero }
1154*10465441SEvalZero
1155*10465441SEvalZero /* initialize local vars */
1156*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
1157*10465441SEvalZero memset(&counters, 0, sizeof(counters));
1158*10465441SEvalZero
1159*10465441SEvalZero /* create and initialize the pcb */
1160*10465441SEvalZero tcp_ticks = SEQNO1 - ISS;
1161*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
1162*10465441SEvalZero EXPECT_RET(pcb != NULL);
1163*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
1164*10465441SEvalZero pcb->mss = TCP_MSS;
1165*10465441SEvalZero pcb->cwnd = TCP_MSS;
1166*10465441SEvalZero
1167*10465441SEvalZero /* send our segment */
1168*10465441SEvalZero err = tcp_write(pcb, &tx_data[0], TCP_MSS, TCP_WRITE_FLAG_COPY);
1169*10465441SEvalZero EXPECT_RET(err == ERR_OK);
1170*10465441SEvalZero err = tcp_output(pcb);
1171*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1172*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1173*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1174*10465441SEvalZero
1175*10465441SEvalZero /* ensure no errors have been recorded */
1176*10465441SEvalZero EXPECT(counters.err_calls == 0);
1177*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1178*10465441SEvalZero
1179*10465441SEvalZero /* Force us into retransmisson timeout */
1180*10465441SEvalZero for (i = 0; !(pcb->flags & TF_RTO) && i < max_wait_ctr; i++) {
1181*10465441SEvalZero test_tcp_tmr();
1182*10465441SEvalZero }
1183*10465441SEvalZero EXPECT(i < max_wait_ctr);
1184*10465441SEvalZero
1185*10465441SEvalZero /* check first rexmit */
1186*10465441SEvalZero EXPECT(pcb->nrtx == 1);
1187*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1188*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1189*10465441SEvalZero
1190*10465441SEvalZero /* still no error expected */
1191*10465441SEvalZero EXPECT(counters.err_calls == 0);
1192*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1193*10465441SEvalZero
1194*10465441SEvalZero if (link_down) {
1195*10465441SEvalZero netif_set_link_down(&netif);
1196*10465441SEvalZero }
1197*10465441SEvalZero
1198*10465441SEvalZero /* keep running the timer till we hit our maximum RTO */
1199*10465441SEvalZero for (i = 0; counters.last_err == ERR_OK && i < max_wait_ctr; i++) {
1200*10465441SEvalZero test_tcp_tmr();
1201*10465441SEvalZero }
1202*10465441SEvalZero EXPECT(i < max_wait_ctr);
1203*10465441SEvalZero
1204*10465441SEvalZero /* check number of retransmissions */
1205*10465441SEvalZero if (link_down) {
1206*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1207*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1208*10465441SEvalZero } else {
1209*10465441SEvalZero EXPECT(txcounters.num_tx_calls == TCP_MAXRTX);
1210*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == TCP_MAXRTX * (TCP_MSS + 40U));
1211*10465441SEvalZero }
1212*10465441SEvalZero
1213*10465441SEvalZero /* check the connection (pcb) has been aborted */
1214*10465441SEvalZero EXPECT(counters.err_calls == 1);
1215*10465441SEvalZero EXPECT(counters.last_err == ERR_ABRT);
1216*10465441SEvalZero /* check our pcb is no longer active */
1217*10465441SEvalZero for (cur = tcp_active_pcbs; cur != NULL; cur = cur->next) {
1218*10465441SEvalZero EXPECT(cur != pcb);
1219*10465441SEvalZero }
1220*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1221*10465441SEvalZero }
1222*10465441SEvalZero
START_TEST(test_tcp_rto_timeout)1223*10465441SEvalZero START_TEST(test_tcp_rto_timeout)
1224*10465441SEvalZero {
1225*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1226*10465441SEvalZero test_tcp_rto_timeout_impl(0);
1227*10465441SEvalZero }
1228*10465441SEvalZero END_TEST
1229*10465441SEvalZero
START_TEST(test_tcp_rto_timeout_link_down)1230*10465441SEvalZero START_TEST(test_tcp_rto_timeout_link_down)
1231*10465441SEvalZero {
1232*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1233*10465441SEvalZero test_tcp_rto_timeout_impl(1);
1234*10465441SEvalZero }
1235*10465441SEvalZero END_TEST
1236*10465441SEvalZero
test_tcp_rto_timeout_syn_sent_impl(int link_down)1237*10465441SEvalZero static void test_tcp_rto_timeout_syn_sent_impl(int link_down)
1238*10465441SEvalZero {
1239*10465441SEvalZero struct netif netif;
1240*10465441SEvalZero struct test_tcp_txcounters txcounters;
1241*10465441SEvalZero struct test_tcp_counters counters;
1242*10465441SEvalZero struct tcp_pcb *pcb, *cur;
1243*10465441SEvalZero err_t err;
1244*10465441SEvalZero size_t i;
1245*10465441SEvalZero const size_t max_wait_ctr = 1024 * 1024;
1246*10465441SEvalZero const u16_t tcp_syn_opts_len = LWIP_TCP_OPT_LENGTH(TF_SEG_OPTS_MSS|TF_SEG_OPTS_WND_SCALE|TF_SEG_OPTS_SACK_PERM|TF_SEG_OPTS_TS);
1247*10465441SEvalZero
1248*10465441SEvalZero /* Setup data for a single segment */
1249*10465441SEvalZero for (i = 0; i < TCP_MSS; i++) {
1250*10465441SEvalZero tx_data[i] = (u8_t)i;
1251*10465441SEvalZero }
1252*10465441SEvalZero
1253*10465441SEvalZero /* initialize local vars */
1254*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
1255*10465441SEvalZero memset(&counters, 0, sizeof(counters));
1256*10465441SEvalZero
1257*10465441SEvalZero /* create and initialize the pcb */
1258*10465441SEvalZero tcp_ticks = SEQNO1 - ISS;
1259*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
1260*10465441SEvalZero EXPECT_RET(pcb != NULL);
1261*10465441SEvalZero err = tcp_connect(pcb, &netif.gw, 123, NULL);
1262*10465441SEvalZero EXPECT_RET(err == ERR_OK);
1263*10465441SEvalZero EXPECT_RET(pcb->state == SYN_SENT);
1264*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1265*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 40U + tcp_syn_opts_len);
1266*10465441SEvalZero
1267*10465441SEvalZero /* ensure no errors have been recorded */
1268*10465441SEvalZero EXPECT(counters.err_calls == 0);
1269*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1270*10465441SEvalZero
1271*10465441SEvalZero txcounters.num_tx_calls = 0;
1272*10465441SEvalZero txcounters.num_tx_bytes = 0;
1273*10465441SEvalZero
1274*10465441SEvalZero /* Force us into retransmisson timeout */
1275*10465441SEvalZero for (i = 0; !(pcb->flags & TF_RTO) && i < max_wait_ctr; i++) {
1276*10465441SEvalZero test_tcp_tmr();
1277*10465441SEvalZero }
1278*10465441SEvalZero EXPECT(i < max_wait_ctr);
1279*10465441SEvalZero
1280*10465441SEvalZero /* check first rexmit */
1281*10465441SEvalZero EXPECT(pcb->nrtx == 1);
1282*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1283*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 40U + tcp_syn_opts_len); /* 40: headers; >=: options */
1284*10465441SEvalZero
1285*10465441SEvalZero /* still no error expected */
1286*10465441SEvalZero EXPECT(counters.err_calls == 0);
1287*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1288*10465441SEvalZero
1289*10465441SEvalZero if (link_down) {
1290*10465441SEvalZero /* set link down and check what happens to the RTO counter */
1291*10465441SEvalZero netif_set_link_down(&netif);
1292*10465441SEvalZero }
1293*10465441SEvalZero
1294*10465441SEvalZero /* keep running the timer till we hit our maximum RTO */
1295*10465441SEvalZero for (i = 0; counters.last_err == ERR_OK && i < max_wait_ctr; i++) {
1296*10465441SEvalZero test_tcp_tmr();
1297*10465441SEvalZero }
1298*10465441SEvalZero EXPECT(i < max_wait_ctr);
1299*10465441SEvalZero
1300*10465441SEvalZero /* check number of retransmissions */
1301*10465441SEvalZero if (link_down) {
1302*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1303*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 40U + tcp_syn_opts_len);
1304*10465441SEvalZero } else {
1305*10465441SEvalZero EXPECT(txcounters.num_tx_calls == TCP_SYNMAXRTX);
1306*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == TCP_SYNMAXRTX * (tcp_syn_opts_len + 40U));
1307*10465441SEvalZero }
1308*10465441SEvalZero
1309*10465441SEvalZero /* check the connection (pcb) has been aborted */
1310*10465441SEvalZero EXPECT(counters.err_calls == 1);
1311*10465441SEvalZero EXPECT(counters.last_err == ERR_ABRT);
1312*10465441SEvalZero /* check our pcb is no longer active */
1313*10465441SEvalZero for (cur = tcp_active_pcbs; cur != NULL; cur = cur->next) {
1314*10465441SEvalZero EXPECT(cur != pcb);
1315*10465441SEvalZero }
1316*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1317*10465441SEvalZero }
1318*10465441SEvalZero
START_TEST(test_tcp_rto_timeout_syn_sent)1319*10465441SEvalZero START_TEST(test_tcp_rto_timeout_syn_sent)
1320*10465441SEvalZero {
1321*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1322*10465441SEvalZero test_tcp_rto_timeout_syn_sent_impl(0);
1323*10465441SEvalZero }
1324*10465441SEvalZero END_TEST
1325*10465441SEvalZero
START_TEST(test_tcp_rto_timeout_syn_sent_link_down)1326*10465441SEvalZero START_TEST(test_tcp_rto_timeout_syn_sent_link_down)
1327*10465441SEvalZero {
1328*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1329*10465441SEvalZero test_tcp_rto_timeout_syn_sent_impl(1);
1330*10465441SEvalZero }
1331*10465441SEvalZero END_TEST
1332*10465441SEvalZero
test_tcp_zwp_timeout_impl(int link_down)1333*10465441SEvalZero static void test_tcp_zwp_timeout_impl(int link_down)
1334*10465441SEvalZero {
1335*10465441SEvalZero struct netif netif;
1336*10465441SEvalZero struct test_tcp_txcounters txcounters;
1337*10465441SEvalZero struct test_tcp_counters counters;
1338*10465441SEvalZero struct tcp_pcb *pcb, *cur;
1339*10465441SEvalZero struct pbuf* p;
1340*10465441SEvalZero err_t err;
1341*10465441SEvalZero size_t i;
1342*10465441SEvalZero
1343*10465441SEvalZero /* Setup data for two segments */
1344*10465441SEvalZero for (i = 0; i < 2*TCP_MSS; i++) {
1345*10465441SEvalZero tx_data[i] = (u8_t)i;
1346*10465441SEvalZero }
1347*10465441SEvalZero
1348*10465441SEvalZero /* initialize local vars */
1349*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
1350*10465441SEvalZero memset(&counters, 0, sizeof(counters));
1351*10465441SEvalZero
1352*10465441SEvalZero /* create and initialize the pcb */
1353*10465441SEvalZero tcp_ticks = SEQNO1 - ISS;
1354*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
1355*10465441SEvalZero EXPECT_RET(pcb != NULL);
1356*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
1357*10465441SEvalZero pcb->mss = TCP_MSS;
1358*10465441SEvalZero pcb->cwnd = TCP_MSS;
1359*10465441SEvalZero
1360*10465441SEvalZero /* send first segment */
1361*10465441SEvalZero err = tcp_write(pcb, &tx_data[0], TCP_MSS, TCP_WRITE_FLAG_COPY);
1362*10465441SEvalZero EXPECT(err == ERR_OK);
1363*10465441SEvalZero err = tcp_output(pcb);
1364*10465441SEvalZero EXPECT(err == ERR_OK);
1365*10465441SEvalZero
1366*10465441SEvalZero /* verify segment is in-flight */
1367*10465441SEvalZero EXPECT(pcb->unsent == NULL);
1368*10465441SEvalZero check_seqnos(pcb->unacked, 1, seqnos);
1369*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1370*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 1 * (TCP_MSS + 40U));
1371*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1372*10465441SEvalZero
1373*10465441SEvalZero /* ACK the segment and close the TX window */
1374*10465441SEvalZero p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_MSS, TCP_ACK, 0);
1375*10465441SEvalZero test_tcp_input(p, &netif);
1376*10465441SEvalZero EXPECT(pcb->unacked == NULL);
1377*10465441SEvalZero EXPECT(pcb->unsent == NULL);
1378*10465441SEvalZero /* send buffer empty, persist should be off */
1379*10465441SEvalZero EXPECT(pcb->persist_backoff == 0);
1380*10465441SEvalZero EXPECT(pcb->snd_wnd == 0);
1381*10465441SEvalZero
1382*10465441SEvalZero /* send second segment, should be buffered */
1383*10465441SEvalZero err = tcp_write(pcb, &tx_data[TCP_MSS], TCP_MSS, TCP_WRITE_FLAG_COPY);
1384*10465441SEvalZero EXPECT(err == ERR_OK);
1385*10465441SEvalZero err = tcp_output(pcb);
1386*10465441SEvalZero EXPECT(err == ERR_OK);
1387*10465441SEvalZero
1388*10465441SEvalZero /* ensure it is buffered and persist timer started */
1389*10465441SEvalZero EXPECT(pcb->unacked == NULL);
1390*10465441SEvalZero check_seqnos(pcb->unsent, 1, &seqnos[1]);
1391*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
1392*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
1393*10465441SEvalZero EXPECT(pcb->persist_backoff == 1);
1394*10465441SEvalZero
1395*10465441SEvalZero /* ensure no errors have been recorded */
1396*10465441SEvalZero EXPECT(counters.err_calls == 0);
1397*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1398*10465441SEvalZero
1399*10465441SEvalZero /* run timer till first probe */
1400*10465441SEvalZero EXPECT(pcb->persist_probe == 0);
1401*10465441SEvalZero while (pcb->persist_probe == 0) {
1402*10465441SEvalZero test_tcp_tmr();
1403*10465441SEvalZero }
1404*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1405*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == (1 + 40U));
1406*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1407*10465441SEvalZero
1408*10465441SEvalZero /* respond to probe with remote's current SEQ, ACK, and zero-window */
1409*10465441SEvalZero p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, 0, TCP_ACK, 0);
1410*10465441SEvalZero test_tcp_input(p, &netif);
1411*10465441SEvalZero /* ensure zero-window is still active, but probe count reset */
1412*10465441SEvalZero EXPECT(pcb->persist_backoff > 1);
1413*10465441SEvalZero EXPECT(pcb->persist_probe == 0);
1414*10465441SEvalZero EXPECT(pcb->snd_wnd == 0);
1415*10465441SEvalZero
1416*10465441SEvalZero /* ensure no errors have been recorded */
1417*10465441SEvalZero EXPECT(counters.err_calls == 0);
1418*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1419*10465441SEvalZero
1420*10465441SEvalZero if (link_down) {
1421*10465441SEvalZero netif_set_link_down(&netif);
1422*10465441SEvalZero }
1423*10465441SEvalZero
1424*10465441SEvalZero /* now run the timer till we hit our maximum probe count */
1425*10465441SEvalZero while (counters.last_err == ERR_OK) {
1426*10465441SEvalZero test_tcp_tmr();
1427*10465441SEvalZero }
1428*10465441SEvalZero
1429*10465441SEvalZero if (link_down) {
1430*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
1431*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
1432*10465441SEvalZero } else {
1433*10465441SEvalZero /* check maximum number of 1 byte probes were sent */
1434*10465441SEvalZero EXPECT(txcounters.num_tx_calls == TCP_MAXRTX);
1435*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == TCP_MAXRTX * (1 + 40U));
1436*10465441SEvalZero }
1437*10465441SEvalZero
1438*10465441SEvalZero /* check the connection (pcb) has been aborted */
1439*10465441SEvalZero EXPECT(counters.err_calls == 1);
1440*10465441SEvalZero EXPECT(counters.last_err == ERR_ABRT);
1441*10465441SEvalZero /* check our pcb is no longer active */
1442*10465441SEvalZero for (cur = tcp_active_pcbs; cur != NULL; cur = cur->next) {
1443*10465441SEvalZero EXPECT(cur != pcb);
1444*10465441SEvalZero }
1445*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1446*10465441SEvalZero }
1447*10465441SEvalZero
START_TEST(test_tcp_zwp_timeout)1448*10465441SEvalZero START_TEST(test_tcp_zwp_timeout)
1449*10465441SEvalZero {
1450*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1451*10465441SEvalZero test_tcp_zwp_timeout_impl(0);
1452*10465441SEvalZero }
1453*10465441SEvalZero END_TEST
1454*10465441SEvalZero
START_TEST(test_tcp_zwp_timeout_link_down)1455*10465441SEvalZero START_TEST(test_tcp_zwp_timeout_link_down)
1456*10465441SEvalZero {
1457*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1458*10465441SEvalZero test_tcp_zwp_timeout_impl(1);
1459*10465441SEvalZero }
1460*10465441SEvalZero END_TEST
1461*10465441SEvalZero
START_TEST(test_tcp_persist_split)1462*10465441SEvalZero START_TEST(test_tcp_persist_split)
1463*10465441SEvalZero {
1464*10465441SEvalZero struct netif netif;
1465*10465441SEvalZero struct test_tcp_txcounters txcounters;
1466*10465441SEvalZero struct test_tcp_counters counters;
1467*10465441SEvalZero struct tcp_pcb *pcb;
1468*10465441SEvalZero struct pbuf* p;
1469*10465441SEvalZero err_t err;
1470*10465441SEvalZero size_t i;
1471*10465441SEvalZero LWIP_UNUSED_ARG(_i);
1472*10465441SEvalZero
1473*10465441SEvalZero /* Setup data for four segments */
1474*10465441SEvalZero for (i = 0; i < 4 * TCP_MSS; i++) {
1475*10465441SEvalZero tx_data[i] = (u8_t)i;
1476*10465441SEvalZero }
1477*10465441SEvalZero
1478*10465441SEvalZero /* initialize local vars */
1479*10465441SEvalZero test_tcp_init_netif(&netif, &txcounters, &test_local_ip, &test_netmask);
1480*10465441SEvalZero memset(&counters, 0, sizeof(counters));
1481*10465441SEvalZero
1482*10465441SEvalZero /* create and initialize the pcb */
1483*10465441SEvalZero tcp_ticks = SEQNO1 - ISS;
1484*10465441SEvalZero pcb = test_tcp_new_counters_pcb(&counters);
1485*10465441SEvalZero EXPECT_RET(pcb != NULL);
1486*10465441SEvalZero tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
1487*10465441SEvalZero pcb->mss = TCP_MSS;
1488*10465441SEvalZero /* set window to three segments */
1489*10465441SEvalZero pcb->cwnd = 3 * TCP_MSS;
1490*10465441SEvalZero pcb->snd_wnd = 3 * TCP_MSS;
1491*10465441SEvalZero pcb->snd_wnd_max = 3 * TCP_MSS;
1492*10465441SEvalZero
1493*10465441SEvalZero /* send four segments. Fourth should stay buffered and is a 3/4 MSS segment to
1494*10465441SEvalZero get coverage on the oversized segment case */
1495*10465441SEvalZero err = tcp_write(pcb, &tx_data[0], (3 * TCP_MSS) + (TCP_MSS - (TCP_MSS / 4)), TCP_WRITE_FLAG_COPY);
1496*10465441SEvalZero EXPECT(err == ERR_OK);
1497*10465441SEvalZero err = tcp_output(pcb);
1498*10465441SEvalZero EXPECT(err == ERR_OK);
1499*10465441SEvalZero
1500*10465441SEvalZero /* verify 3 segments are in-flight */
1501*10465441SEvalZero EXPECT(pcb->unacked != NULL);
1502*10465441SEvalZero check_seqnos(pcb->unacked, 3, seqnos);
1503*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 3);
1504*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 3 * (TCP_MSS + 40U));
1505*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1506*10465441SEvalZero /* verify 4th segment is on unsent */
1507*10465441SEvalZero EXPECT(pcb->unsent != NULL);
1508*10465441SEvalZero EXPECT(pcb->unsent->len == TCP_MSS - (TCP_MSS / 4));
1509*10465441SEvalZero check_seqnos(pcb->unsent, 1, &seqnos[3]);
1510*10465441SEvalZero #if TCP_OVERSIZE
1511*10465441SEvalZero EXPECT(pcb->unsent_oversize == TCP_MSS / 4);
1512*10465441SEvalZero #if TCP_OVERSIZE_DBGCHECK
1513*10465441SEvalZero EXPECT(pcb->unsent->oversize_left == pcb->unsent_oversize);
1514*10465441SEvalZero #endif /* TCP_OVERSIZE_DBGCHECK */
1515*10465441SEvalZero #endif /* TCP_OVERSIZE */
1516*10465441SEvalZero
1517*10465441SEvalZero /* ACK the 3 segments and update the window to only 1/2 TCP_MSS.
1518*10465441SEvalZero 4th segment should stay on unsent because it's bigger than 1/2 MSS */
1519*10465441SEvalZero p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, 3 * TCP_MSS, TCP_ACK, TCP_MSS / 2);
1520*10465441SEvalZero test_tcp_input(p, &netif);
1521*10465441SEvalZero EXPECT(pcb->unacked == NULL);
1522*10465441SEvalZero EXPECT(pcb->snd_wnd == TCP_MSS / 2);
1523*10465441SEvalZero EXPECT(pcb->unsent != NULL);
1524*10465441SEvalZero check_seqnos(pcb->unsent, 1, &seqnos[3]);
1525*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
1526*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
1527*10465441SEvalZero /* persist timer should be started since 4th segment is stuck waiting on snd_wnd */
1528*10465441SEvalZero EXPECT(pcb->persist_backoff == 1);
1529*10465441SEvalZero
1530*10465441SEvalZero /* ensure no errors have been recorded */
1531*10465441SEvalZero EXPECT(counters.err_calls == 0);
1532*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1533*10465441SEvalZero
1534*10465441SEvalZero /* call tcp_timer some more times to let persist timer count up */
1535*10465441SEvalZero for (i = 0; i < 4; i++) {
1536*10465441SEvalZero test_tcp_tmr();
1537*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 0);
1538*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == 0);
1539*10465441SEvalZero }
1540*10465441SEvalZero
1541*10465441SEvalZero /* this should be the first timer shot, which should split the
1542*10465441SEvalZero * segment and send a runt (of the remaining window size) */
1543*10465441SEvalZero txcounters.copy_tx_packets = 1;
1544*10465441SEvalZero test_tcp_tmr();
1545*10465441SEvalZero txcounters.copy_tx_packets = 0;
1546*10465441SEvalZero /* persist will be disabled as RTO timer takes over */
1547*10465441SEvalZero EXPECT(pcb->persist_backoff == 0);
1548*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1549*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == ((TCP_MSS /2) + 40U));
1550*10465441SEvalZero /* verify 1/2 MSS segment sent, 1/4 MSS still buffered */
1551*10465441SEvalZero EXPECT(pcb->unsent != NULL);
1552*10465441SEvalZero EXPECT(pcb->unsent->len == TCP_MSS / 4);
1553*10465441SEvalZero EXPECT(pcb->unacked != NULL);
1554*10465441SEvalZero EXPECT(pcb->unacked->len == TCP_MSS / 2);
1555*10465441SEvalZero #if TCP_OVERSIZE
1556*10465441SEvalZero /* verify there is no oversized remaining since during the
1557*10465441SEvalZero segment split, the remainder pbuf is always the exact length */
1558*10465441SEvalZero EXPECT(pcb->unsent_oversize == 0);
1559*10465441SEvalZero #if TCP_OVERSIZE_DBGCHECK
1560*10465441SEvalZero /* Split segment already transmitted, should be at 0 */
1561*10465441SEvalZero EXPECT(pcb->unacked->oversize_left == 0);
1562*10465441SEvalZero /* Remainder segement should match pcb value (which is 0) */
1563*10465441SEvalZero EXPECT(pcb->unsent->oversize_left == pcb->unsent_oversize);
1564*10465441SEvalZero #endif /* TCP_OVERSIZE_DBGCHECK */
1565*10465441SEvalZero #endif /* TCP_OVERSIZE */
1566*10465441SEvalZero
1567*10465441SEvalZero /* verify first half segment */
1568*10465441SEvalZero EXPECT(txcounters.tx_packets != NULL);
1569*10465441SEvalZero if (txcounters.tx_packets != NULL) {
1570*10465441SEvalZero u8_t sent[TCP_MSS / 2];
1571*10465441SEvalZero u16_t ret;
1572*10465441SEvalZero ret = pbuf_copy_partial(txcounters.tx_packets, &sent, TCP_MSS / 2, 40U);
1573*10465441SEvalZero EXPECT(ret == TCP_MSS / 2);
1574*10465441SEvalZero EXPECT(memcmp(sent, &tx_data[3 * TCP_MSS], TCP_MSS / 2) == 0);
1575*10465441SEvalZero }
1576*10465441SEvalZero if (txcounters.tx_packets != NULL) {
1577*10465441SEvalZero pbuf_free(txcounters.tx_packets);
1578*10465441SEvalZero txcounters.tx_packets = NULL;
1579*10465441SEvalZero }
1580*10465441SEvalZero memset(&txcounters, 0, sizeof(txcounters));
1581*10465441SEvalZero
1582*10465441SEvalZero /* ACK the half segment, leave window at half segment */
1583*10465441SEvalZero p = tcp_create_rx_segment_wnd(pcb, NULL, 0, 0, TCP_MSS / 2, TCP_ACK, TCP_MSS / 2);
1584*10465441SEvalZero txcounters.copy_tx_packets = 1;
1585*10465441SEvalZero test_tcp_input(p, &netif);
1586*10465441SEvalZero txcounters.copy_tx_packets = 0;
1587*10465441SEvalZero /* ensure remaining segment was sent */
1588*10465441SEvalZero EXPECT(txcounters.num_tx_calls == 1);
1589*10465441SEvalZero EXPECT(txcounters.num_tx_bytes == ((TCP_MSS / 4) + 40U));
1590*10465441SEvalZero EXPECT(pcb->unsent == NULL);
1591*10465441SEvalZero EXPECT(pcb->unacked != NULL);
1592*10465441SEvalZero EXPECT(pcb->unacked->len == TCP_MSS / 4);
1593*10465441SEvalZero EXPECT(pcb->snd_wnd == TCP_MSS / 2);
1594*10465441SEvalZero
1595*10465441SEvalZero /* verify remainder segment */
1596*10465441SEvalZero EXPECT(txcounters.tx_packets != NULL);
1597*10465441SEvalZero if (txcounters.tx_packets != NULL) {
1598*10465441SEvalZero u8_t sent[TCP_MSS / 4];
1599*10465441SEvalZero u16_t ret;
1600*10465441SEvalZero ret = pbuf_copy_partial(txcounters.tx_packets, &sent, TCP_MSS / 4, 40U);
1601*10465441SEvalZero EXPECT(ret == TCP_MSS / 4);
1602*10465441SEvalZero EXPECT(memcmp(sent, &tx_data[(3 * TCP_MSS) + TCP_MSS / 2], TCP_MSS / 4) == 0);
1603*10465441SEvalZero }
1604*10465441SEvalZero if (txcounters.tx_packets != NULL) {
1605*10465441SEvalZero pbuf_free(txcounters.tx_packets);
1606*10465441SEvalZero txcounters.tx_packets = NULL;
1607*10465441SEvalZero }
1608*10465441SEvalZero
1609*10465441SEvalZero /* ensure no errors have been recorded */
1610*10465441SEvalZero EXPECT(counters.err_calls == 0);
1611*10465441SEvalZero EXPECT(counters.last_err == ERR_OK);
1612*10465441SEvalZero
1613*10465441SEvalZero /* make sure the pcb is freed */
1614*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
1615*10465441SEvalZero tcp_abort(pcb);
1616*10465441SEvalZero EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
1617*10465441SEvalZero }
1618*10465441SEvalZero END_TEST
1619*10465441SEvalZero
1620*10465441SEvalZero /** Create the suite including all tests for this module */
1621*10465441SEvalZero Suite *
tcp_suite(void)1622*10465441SEvalZero tcp_suite(void)
1623*10465441SEvalZero {
1624*10465441SEvalZero testfunc tests[] = {
1625*10465441SEvalZero TESTFUNC(test_tcp_new_abort),
1626*10465441SEvalZero TESTFUNC(test_tcp_listen_passive_open),
1627*10465441SEvalZero TESTFUNC(test_tcp_recv_inseq),
1628*10465441SEvalZero TESTFUNC(test_tcp_recv_inseq_trim),
1629*10465441SEvalZero TESTFUNC(test_tcp_passive_close),
1630*10465441SEvalZero TESTFUNC(test_tcp_malformed_header),
1631*10465441SEvalZero TESTFUNC(test_tcp_fast_retx_recover),
1632*10465441SEvalZero TESTFUNC(test_tcp_fast_rexmit_wraparound),
1633*10465441SEvalZero TESTFUNC(test_tcp_rto_rexmit_wraparound),
1634*10465441SEvalZero TESTFUNC(test_tcp_tx_full_window_lost_from_unacked),
1635*10465441SEvalZero TESTFUNC(test_tcp_tx_full_window_lost_from_unsent),
1636*10465441SEvalZero TESTFUNC(test_tcp_retx_add_to_sent),
1637*10465441SEvalZero TESTFUNC(test_tcp_rto_tracking),
1638*10465441SEvalZero TESTFUNC(test_tcp_rto_timeout),
1639*10465441SEvalZero TESTFUNC(test_tcp_rto_timeout_link_down),
1640*10465441SEvalZero TESTFUNC(test_tcp_rto_timeout_syn_sent),
1641*10465441SEvalZero TESTFUNC(test_tcp_rto_timeout_syn_sent_link_down),
1642*10465441SEvalZero TESTFUNC(test_tcp_zwp_timeout),
1643*10465441SEvalZero TESTFUNC(test_tcp_zwp_timeout_link_down),
1644*10465441SEvalZero TESTFUNC(test_tcp_persist_split)
1645*10465441SEvalZero };
1646*10465441SEvalZero return create_suite("TCP", tests, sizeof(tests)/sizeof(testfunc), tcp_setup, tcp_teardown);
1647*10465441SEvalZero }
1648