1 #include "test_tcp_oos.h"
3 #include "lwip/tcp_impl.h"
4 #include "lwip/stats.h"
5 #include "tcp_helper.h"
7 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
8 #error "This tests needs TCP- and MEMP-statistics enabled"
11 #error "This tests needs TCP_QUEUE_OOSEQ enabled"
14 /** CHECK_SEGMENTS_ON_OOSEQ:
15 * 1: check count, seqno and len of segments on pcb->ooseq (strict)
16 * 0: only check that bytes are received in correct order (less strict) */
17 #define CHECK_SEGMENTS_ON_OOSEQ 1
19 #if CHECK_SEGMENTS_ON_OOSEQ
20 #define EXPECT_OOSEQ(x) EXPECT(x)
22 #define EXPECT_OOSEQ(x)
25 /* helper functions */
27 /** Get the numbers of segments on the ooseq list */
28 static int tcp_oos_count(struct tcp_pcb* pcb)
31 struct tcp_seg* seg = pcb->ooseq;
39 /** Get the seqno of a segment (by index) on the ooseq list
41 * @param pcb the pcb to check for ooseq segments
42 * @param seg_index index of the segment on the ooseq list
43 * @return seqno of the segment
46 tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index)
49 struct tcp_seg* seg = pcb->ooseq;
51 /* then check the actual segment */
53 if(num == seg_index) {
54 return seg->tcphdr->seqno;
63 /** Get the tcplen (datalen + SYN/FIN) of a segment (by index) on the ooseq list
65 * @param pcb the pcb to check for ooseq segments
66 * @param seg_index index of the segment on the ooseq list
67 * @return tcplen of the segment
70 tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index)
73 struct tcp_seg* seg = pcb->ooseq;
75 /* then check the actual segment */
77 if(num == seg_index) {
78 return TCP_TCPLEN(seg);
87 /** Get the tcplen (datalen + SYN/FIN) of all segments on the ooseq list
89 * @param pcb the pcb to check for ooseq segments
90 * @return tcplen of all segment
93 tcp_oos_tcplen(struct tcp_pcb* pcb)
96 struct tcp_seg* seg = pcb->ooseq;
98 /* then check the actual segment */
100 len += TCP_TCPLEN(seg);
106 /* Setup/teardown functions */
115 tcp_oos_teardown(void)
124 /** create multiple segments and pass them to tcp_input in a wrong
125 * order to see if ooseq-caching works correctly
126 * FIN is received in out-of-sequence segments only */
127 START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
129 struct test_tcp_counters counters;
131 struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq;
137 ip_addr_t remote_ip, local_ip;
139 u16_t remote_port = 0x100, local_port = 0x101;
143 /* initialize local vars */
144 memset(&netif, 0, sizeof(netif));
145 IP4_ADDR(&local_ip, 192, 168, 1, 1);
146 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
147 data_len = sizeof(data);
148 /* initialize counter struct */
149 memset(&counters, 0, sizeof(counters));
150 counters.expected_data_len = data_len;
151 counters.expected_data = data;
153 /* create and initialize the pcb */
154 pcb = test_tcp_new_counters_pcb(&counters);
155 EXPECT_RET(pcb != NULL);
156 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
158 /* create segments */
159 /* pinseq is sent as last segment! */
160 pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
161 /* p1: 8 bytes before FIN */
163 p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN);
164 /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
166 p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
167 /* p3: same as p2 but 2 bytes longer */
169 p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK);
170 /* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */
172 p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK);
174 p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN);
175 EXPECT(pinseq != NULL);
176 EXPECT(p_8_9 != NULL);
177 EXPECT(p_4_8 != NULL);
178 EXPECT(p_4_10 != NULL);
179 EXPECT(p_2_14 != NULL);
180 EXPECT(p_fin != NULL);
181 if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
182 /* pass the segment to tcp_input */
183 tcp_input(p_8_9, &netif);
184 /* check if counters are as expected */
185 EXPECT(counters.close_calls == 0);
186 EXPECT(counters.recv_calls == 0);
187 EXPECT(counters.recved_bytes == 0);
188 EXPECT(counters.err_calls == 0);
189 /* check ooseq queue */
190 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
191 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8);
192 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
194 /* pass the segment to tcp_input */
195 tcp_input(p_4_8, &netif);
196 /* check if counters are as expected */
197 EXPECT(counters.close_calls == 0);
198 EXPECT(counters.recv_calls == 0);
199 EXPECT(counters.recved_bytes == 0);
200 EXPECT(counters.err_calls == 0);
201 /* check ooseq queue */
202 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
203 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
204 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
205 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
206 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
208 /* pass the segment to tcp_input */
209 tcp_input(p_4_10, &netif);
210 /* check if counters are as expected */
211 EXPECT(counters.close_calls == 0);
212 EXPECT(counters.recv_calls == 0);
213 EXPECT(counters.recved_bytes == 0);
214 EXPECT(counters.err_calls == 0);
215 /* ooseq queue: unchanged */
216 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
217 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
218 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
219 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
220 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
222 /* pass the segment to tcp_input */
223 tcp_input(p_2_14, &netif);
224 /* check if counters are as expected */
225 EXPECT(counters.close_calls == 0);
226 EXPECT(counters.recv_calls == 0);
227 EXPECT(counters.recved_bytes == 0);
228 EXPECT(counters.err_calls == 0);
229 /* check ooseq queue */
230 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
231 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
232 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
234 /* pass the segment to tcp_input */
235 tcp_input(p_fin, &netif);
236 /* check if counters are as expected */
237 EXPECT(counters.close_calls == 0);
238 EXPECT(counters.recv_calls == 0);
239 EXPECT(counters.recved_bytes == 0);
240 EXPECT(counters.err_calls == 0);
241 /* ooseq queue: unchanged */
242 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
243 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
244 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
246 /* pass the segment to tcp_input */
247 tcp_input(pinseq, &netif);
248 /* check if counters are as expected */
249 EXPECT(counters.close_calls == 1);
250 EXPECT(counters.recv_calls == 1);
251 EXPECT(counters.recved_bytes == data_len);
252 EXPECT(counters.err_calls == 0);
253 EXPECT(pcb->ooseq == NULL);
256 /* make sure the pcb is freed */
257 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
259 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
264 /** create multiple segments and pass them to tcp_input in a wrong
265 * order to see if ooseq-caching works correctly
266 * FIN is received IN-SEQUENCE at the end */
267 START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
269 struct test_tcp_counters counters;
271 struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN;
277 ip_addr_t remote_ip, local_ip;
279 u16_t remote_port = 0x100, local_port = 0x101;
283 /* initialize local vars */
284 memset(&netif, 0, sizeof(netif));
285 IP4_ADDR(&local_ip, 192, 168, 1, 1);
286 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
287 data_len = sizeof(data);
288 /* initialize counter struct */
289 memset(&counters, 0, sizeof(counters));
290 counters.expected_data_len = data_len;
291 counters.expected_data = data;
293 /* create and initialize the pcb */
294 pcb = test_tcp_new_counters_pcb(&counters);
295 EXPECT_RET(pcb != NULL);
296 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
298 /* create segments */
299 /* p1: 7 bytes - 2 before FIN */
301 p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK);
302 /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
304 p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
305 /* p3: same as p2 but 2 bytes longer and one byte more at the front */
307 p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK);
308 /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */
310 p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK);
311 /* pinseq is the first segment that is held back to create ooseq! */
313 pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
314 /* p5: last byte before FIN */
316 p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
317 /* p6: same as p5, should be ignored */
318 p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
319 /* pinseqFIN: last 2 bytes plus FIN */
320 /* only segment containing seqno 14 and FIN */
321 pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN);
322 EXPECT(pinseq != NULL);
323 EXPECT(p_1_2 != NULL);
324 EXPECT(p_4_8 != NULL);
325 EXPECT(p_3_11 != NULL);
326 EXPECT(p_2_12 != NULL);
327 EXPECT(p_15_1 != NULL);
328 EXPECT(p_15_1a != NULL);
329 EXPECT(pinseqFIN != NULL);
330 if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
331 && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
332 /* pass the segment to tcp_input */
333 tcp_input(p_1_2, &netif);
334 /* check if counters are as expected */
335 EXPECT(counters.close_calls == 0);
336 EXPECT(counters.recv_calls == 0);
337 EXPECT(counters.recved_bytes == 0);
338 EXPECT(counters.err_calls == 0);
339 /* check ooseq queue */
340 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
341 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
342 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
344 /* pass the segment to tcp_input */
345 tcp_input(p_4_8, &netif);
346 /* check if counters are as expected */
347 EXPECT(counters.close_calls == 0);
348 EXPECT(counters.recv_calls == 0);
349 EXPECT(counters.recved_bytes == 0);
350 EXPECT(counters.err_calls == 0);
351 /* check ooseq queue */
352 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
353 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
354 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
355 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4);
356 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
358 /* pass the segment to tcp_input */
359 tcp_input(p_3_11, &netif);
360 /* check if counters are as expected */
361 EXPECT(counters.close_calls == 0);
362 EXPECT(counters.recv_calls == 0);
363 EXPECT(counters.recved_bytes == 0);
364 EXPECT(counters.err_calls == 0);
365 /* check ooseq queue */
366 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
367 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
368 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
369 /* p_3_11 has removed p_4_8 from ooseq */
370 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3);
371 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
373 /* pass the segment to tcp_input */
374 tcp_input(p_2_12, &netif);
375 /* check if counters are as expected */
376 EXPECT(counters.close_calls == 0);
377 EXPECT(counters.recv_calls == 0);
378 EXPECT(counters.recved_bytes == 0);
379 EXPECT(counters.err_calls == 0);
380 /* check ooseq queue */
381 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
382 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
383 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
384 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
385 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12);
387 /* pass the segment to tcp_input */
388 tcp_input(pinseq, &netif);
389 /* check if counters are as expected */
390 EXPECT(counters.close_calls == 0);
391 EXPECT(counters.recv_calls == 1);
392 EXPECT(counters.recved_bytes == 14);
393 EXPECT(counters.err_calls == 0);
394 EXPECT(pcb->ooseq == NULL);
396 /* pass the segment to tcp_input */
397 tcp_input(p_15_1, &netif);
398 /* check if counters are as expected */
399 EXPECT(counters.close_calls == 0);
400 EXPECT(counters.recv_calls == 1);
401 EXPECT(counters.recved_bytes == 14);
402 EXPECT(counters.err_calls == 0);
403 /* check ooseq queue */
404 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
405 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
406 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
408 /* pass the segment to tcp_input */
409 tcp_input(p_15_1a, &netif);
410 /* check if counters are as expected */
411 EXPECT(counters.close_calls == 0);
412 EXPECT(counters.recv_calls == 1);
413 EXPECT(counters.recved_bytes == 14);
414 EXPECT(counters.err_calls == 0);
415 /* check ooseq queue: unchanged */
416 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
417 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
418 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
420 /* pass the segment to tcp_input */
421 tcp_input(pinseqFIN, &netif);
422 /* check if counters are as expected */
423 EXPECT(counters.close_calls == 1);
424 EXPECT(counters.recv_calls == 2);
425 EXPECT(counters.recved_bytes == data_len);
426 EXPECT(counters.err_calls == 0);
427 EXPECT(pcb->ooseq == NULL);
430 /* make sure the pcb is freed */
431 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
433 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
437 static char data_full_wnd[TCP_WND];
439 /** create multiple segments and pass them to tcp_input with the first segment missing
440 * to simulate overruning the rxwin with ooseq queueing enabled */
441 START_TEST(test_tcp_recv_ooseq_overrun_rxwin)
444 struct test_tcp_counters counters;
446 struct pbuf *pinseq, *p_ovr;
447 ip_addr_t remote_ip, local_ip;
448 u16_t remote_port = 0x100, local_port = 0x101;
454 for(i = 0; i < sizeof(data_full_wnd); i++) {
455 data_full_wnd[i] = (char)i;
458 /* initialize local vars */
459 memset(&netif, 0, sizeof(netif));
460 IP4_ADDR(&local_ip, 192, 168, 1, 1);
461 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
462 /* initialize counter struct */
463 memset(&counters, 0, sizeof(counters));
464 counters.expected_data_len = TCP_WND;
465 counters.expected_data = data_full_wnd;
467 /* create and initialize the pcb */
468 pcb = test_tcp_new_counters_pcb(&counters);
469 EXPECT_RET(pcb != NULL);
470 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
471 pcb->rcv_nxt = 0x8000;
473 /* create segments */
474 /* pinseq is sent as last segment! */
475 pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK);
477 for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) {
478 int count, expected_datalen;
479 struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)],
480 TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
482 /* pass the segment to tcp_input */
483 tcp_input(p, &netif);
484 /* check if counters are as expected */
485 EXPECT(counters.close_calls == 0);
486 EXPECT(counters.recv_calls == 0);
487 EXPECT(counters.recved_bytes == 0);
488 EXPECT(counters.err_calls == 0);
489 /* check ooseq queue */
490 count = tcp_oos_count(pcb);
491 EXPECT_OOSEQ(count == k+1);
492 datalen = tcp_oos_tcplen(pcb);
493 if (i + TCP_MSS < TCP_WND) {
494 expected_datalen = (k+1)*TCP_MSS;
496 expected_datalen = TCP_WND - TCP_MSS;
498 if (datalen != expected_datalen) {
499 EXPECT_OOSEQ(datalen == expected_datalen);
503 /* pass in one more segment, cleary overrunning the rxwin */
504 p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
505 EXPECT(p_ovr != NULL);
506 /* pass the segment to tcp_input */
507 tcp_input(p_ovr, &netif);
508 /* check if counters are as expected */
509 EXPECT(counters.close_calls == 0);
510 EXPECT(counters.recv_calls == 0);
511 EXPECT(counters.recved_bytes == 0);
512 EXPECT(counters.err_calls == 0);
513 /* check ooseq queue */
514 EXPECT_OOSEQ(tcp_oos_count(pcb) == k);
515 datalen2 = tcp_oos_tcplen(pcb);
516 EXPECT_OOSEQ(datalen == datalen2);
519 tcp_input(pinseq, &netif);
520 EXPECT(pcb->ooseq == NULL);
522 /* make sure the pcb is freed */
523 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
525 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
530 /** Create the suite including all tests for this module */
535 test_tcp_recv_ooseq_FIN_OOSEQ,
536 test_tcp_recv_ooseq_FIN_INSEQ,
537 test_tcp_recv_ooseq_overrun_rxwin,
539 return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);