1 #include "test_tcp_oos.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 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 /* Setup/teardown functions */
96 tcp_oos_teardown(void)
105 /** create multiple segments and pass them to tcp_input in a wrong
106 * order to see if ooseq-caching works correctly
107 * FIN is received in out-of-sequence segments only */
108 START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
110 struct test_tcp_counters counters;
112 struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq;
118 struct ip_addr remote_ip, local_ip;
120 u16_t remote_port = 0x100, local_port = 0x101;
124 /* initialize local vars */
125 memset(&netif, 0, sizeof(netif));
126 IP4_ADDR(&local_ip, 192, 168, 1, 1);
127 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
128 data_len = sizeof(data);
129 /* initialize counter struct */
130 memset(&counters, 0, sizeof(counters));
131 counters.expected_data_len = data_len;
132 counters.expected_data = data;
134 /* create and initialize the pcb */
135 pcb = test_tcp_new_counters_pcb(&counters);
136 EXPECT_RET(pcb != NULL);
137 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
139 /* create segments */
140 /* pinseq is sent as last segment! */
141 pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
142 /* p1: 8 bytes before FIN */
144 p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN);
145 /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
147 p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
148 /* p3: same as p2 but 2 bytes longer */
150 p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK);
151 /* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */
153 p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK);
155 p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN);
156 EXPECT(pinseq != NULL);
157 EXPECT(p_8_9 != NULL);
158 EXPECT(p_4_8 != NULL);
159 EXPECT(p_4_10 != NULL);
160 EXPECT(p_2_14 != NULL);
161 EXPECT(p_fin != NULL);
162 if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
163 /* pass the segment to tcp_input */
164 tcp_input(p_8_9, &netif);
165 /* check if counters are as expected */
166 EXPECT(counters.close_calls == 0);
167 EXPECT(counters.recv_calls == 0);
168 EXPECT(counters.recved_bytes == 0);
169 EXPECT(counters.err_calls == 0);
170 /* check ooseq queue */
171 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
172 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8);
173 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
175 /* pass the segment to tcp_input */
176 tcp_input(p_4_8, &netif);
177 /* check if counters are as expected */
178 EXPECT(counters.close_calls == 0);
179 EXPECT(counters.recv_calls == 0);
180 EXPECT(counters.recved_bytes == 0);
181 EXPECT(counters.err_calls == 0);
182 /* check ooseq queue */
183 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
184 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
185 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
186 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
187 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
189 /* pass the segment to tcp_input */
190 tcp_input(p_4_10, &netif);
191 /* check if counters are as expected */
192 EXPECT(counters.close_calls == 0);
193 EXPECT(counters.recv_calls == 0);
194 EXPECT(counters.recved_bytes == 0);
195 EXPECT(counters.err_calls == 0);
196 /* ooseq queue: unchanged */
197 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
198 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
199 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
200 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
201 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
203 /* pass the segment to tcp_input */
204 tcp_input(p_2_14, &netif);
205 /* check if counters are as expected */
206 EXPECT(counters.close_calls == 0);
207 EXPECT(counters.recv_calls == 0);
208 EXPECT(counters.recved_bytes == 0);
209 EXPECT(counters.err_calls == 0);
210 /* check ooseq queue */
211 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
212 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
213 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6);
214 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
215 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
217 /* pass the segment to tcp_input */
218 tcp_input(p_fin, &netif);
219 /* check if counters are as expected */
220 EXPECT(counters.close_calls == 0);
221 EXPECT(counters.recv_calls == 0);
222 EXPECT(counters.recved_bytes == 0);
223 EXPECT(counters.err_calls == 0);
224 /* ooseq queue: unchanged */
225 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
226 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
227 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 6);
228 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
229 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
231 /* pass the segment to tcp_input */
232 tcp_input(pinseq, &netif);
233 /* check if counters are as expected */
234 EXPECT(counters.close_calls == 1);
235 EXPECT(counters.recv_calls == 1);
236 EXPECT(counters.recved_bytes == data_len);
237 EXPECT(counters.err_calls == 0);
238 EXPECT(pcb->ooseq == NULL);
241 /* make sure the pcb is freed */
242 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
244 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
249 /** create multiple segments and pass them to tcp_input in a wrong
250 * order to see if ooseq-caching works correctly
251 * FIN is received IN-SEQUENCE at the end */
252 START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
254 struct test_tcp_counters counters;
256 struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN;
262 struct ip_addr remote_ip, local_ip;
264 u16_t remote_port = 0x100, local_port = 0x101;
268 /* initialize local vars */
269 memset(&netif, 0, sizeof(netif));
270 IP4_ADDR(&local_ip, 192, 168, 1, 1);
271 IP4_ADDR(&remote_ip, 192, 168, 1, 2);
272 data_len = sizeof(data);
273 /* initialize counter struct */
274 memset(&counters, 0, sizeof(counters));
275 counters.expected_data_len = data_len;
276 counters.expected_data = data;
278 /* create and initialize the pcb */
279 pcb = test_tcp_new_counters_pcb(&counters);
280 EXPECT_RET(pcb != NULL);
281 tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
283 /* create segments */
284 /* p1: 7 bytes - 2 before FIN */
286 p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK);
287 /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
289 p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
290 /* p3: same as p2 but 2 bytes longer and one byte more at the front */
292 p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK);
293 /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */
295 p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK);
296 /* pinseq is the first segment that is held back to create ooseq! */
298 pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
299 /* p5: last byte before FIN */
301 p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
302 /* p6: same as p5, should be ignored */
303 p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
304 /* pinseqFIN: last 2 bytes plus FIN */
305 /* only segment containing seqno 14 and FIN */
306 pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN);
307 EXPECT(pinseq != NULL);
308 EXPECT(p_1_2 != NULL);
309 EXPECT(p_4_8 != NULL);
310 EXPECT(p_3_11 != NULL);
311 EXPECT(p_2_12 != NULL);
312 EXPECT(p_15_1 != NULL);
313 EXPECT(p_15_1a != NULL);
314 EXPECT(pinseqFIN != NULL);
315 if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
316 && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
317 /* pass the segment to tcp_input */
318 tcp_input(p_1_2, &netif);
319 /* check if counters are as expected */
320 EXPECT(counters.close_calls == 0);
321 EXPECT(counters.recv_calls == 0);
322 EXPECT(counters.recved_bytes == 0);
323 EXPECT(counters.err_calls == 0);
324 /* check ooseq queue */
325 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
326 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
327 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
329 /* pass the segment to tcp_input */
330 tcp_input(p_4_8, &netif);
331 /* check if counters are as expected */
332 EXPECT(counters.close_calls == 0);
333 EXPECT(counters.recv_calls == 0);
334 EXPECT(counters.recved_bytes == 0);
335 EXPECT(counters.err_calls == 0);
336 /* check ooseq queue */
337 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
338 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
339 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
340 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4);
341 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
343 /* pass the segment to tcp_input */
344 tcp_input(p_3_11, &netif);
345 /* check if counters are as expected */
346 EXPECT(counters.close_calls == 0);
347 EXPECT(counters.recv_calls == 0);
348 EXPECT(counters.recved_bytes == 0);
349 EXPECT(counters.err_calls == 0);
350 /* check ooseq queue */
351 EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
352 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
353 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
354 /* p_3_11 has removed p_4_8 from ooseq */
355 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3);
356 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
358 /* pass the segment to tcp_input */
359 tcp_input(p_2_12, &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) == 3);
367 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
368 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
369 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
370 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 1);
371 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 2) == 3);
372 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 2) == 11);
374 /* pass the segment to tcp_input */
375 tcp_input(pinseq, &netif);
376 /* check if counters are as expected */
377 EXPECT(counters.close_calls == 0);
378 EXPECT(counters.recv_calls == 1);
379 EXPECT(counters.recved_bytes == 14);
380 EXPECT(counters.err_calls == 0);
381 EXPECT(pcb->ooseq == NULL);
383 /* pass the segment to tcp_input */
384 tcp_input(p_15_1, &netif);
385 /* check if counters are as expected */
386 EXPECT(counters.close_calls == 0);
387 EXPECT(counters.recv_calls == 1);
388 EXPECT(counters.recved_bytes == 14);
389 EXPECT(counters.err_calls == 0);
390 /* check ooseq queue */
391 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
392 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
393 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
395 /* pass the segment to tcp_input */
396 tcp_input(p_15_1a, &netif);
397 /* check if counters are as expected */
398 EXPECT(counters.close_calls == 0);
399 EXPECT(counters.recv_calls == 1);
400 EXPECT(counters.recved_bytes == 14);
401 EXPECT(counters.err_calls == 0);
402 /* check ooseq queue: unchanged */
403 EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
404 EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
405 EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
407 /* pass the segment to tcp_input */
408 tcp_input(pinseqFIN, &netif);
409 /* check if counters are as expected */
410 EXPECT(counters.close_calls == 1);
411 EXPECT(counters.recv_calls == 2);
412 EXPECT(counters.recved_bytes == data_len);
413 EXPECT(counters.err_calls == 0);
414 EXPECT(pcb->ooseq == NULL);
417 /* make sure the pcb is freed */
418 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
420 EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
424 /** Create the suite including all tests for this module */
429 test_tcp_recv_ooseq_FIN_OOSEQ,
430 test_tcp_recv_ooseq_FIN_INSEQ,
432 return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);