]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - test/unit/tcp/test_tcp_oos.c
Moved stack-internal parts of tcp.h to tcp_impl.h, tcp.h now only contains the actual...
[pes-rpp/rpp-lwip.git] / test / unit / tcp / test_tcp_oos.c
1 #include "test_tcp_oos.h"
2
3 #include "lwip/tcp_impl.h"
4 #include "lwip/stats.h"
5 #include "tcp_helper.h"
6
7 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
8 #error "This tests needs TCP- and MEMP-statistics enabled"
9 #endif
10 #if !TCP_QUEUE_OOSEQ
11 #error "This tests needs TCP_QUEUE_OOSEQ enabled"
12 #endif
13
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
18
19 #if CHECK_SEGMENTS_ON_OOSEQ
20 #define EXPECT_OOSEQ(x) EXPECT(x)
21 #else
22 #define EXPECT_OOSEQ(x)
23 #endif
24
25 /* helper functions */
26
27 /** Get the numbers of segments on the ooseq list */
28 static int tcp_oos_count(struct tcp_pcb* pcb)
29 {
30   int num = 0;
31   struct tcp_seg* seg = pcb->ooseq;
32   while(seg != NULL) {
33     num++;
34     seg = seg->next;
35   }
36   return num;
37 }
38
39 /** Get the seqno of a segment (by index) on the ooseq list
40  *
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
44  */
45 static u32_t
46 tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index)
47 {
48   int num = 0;
49   struct tcp_seg* seg = pcb->ooseq;
50
51   /* then check the actual segment */
52   while(seg != NULL) {
53     if(num == seg_index) {
54       return seg->tcphdr->seqno;
55     }
56     num++;
57     seg = seg->next;
58   }
59   fail();
60   return 0;
61 }
62
63 /** Get the tcplen of a segment (by index) on the ooseq list
64  *
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
68  */
69 static int
70 tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index)
71 {
72   int num = 0;
73   struct tcp_seg* seg = pcb->ooseq;
74
75   /* then check the actual segment */
76   while(seg != NULL) {
77     if(num == seg_index) {
78       return TCP_TCPLEN(seg);
79     }
80     num++;
81     seg = seg->next;
82   }
83   fail();
84   return -1;
85 }
86
87 /* Setup/teardown functions */
88
89 static void
90 tcp_oos_setup(void)
91 {
92   tcp_remove_all();
93 }
94
95 static void
96 tcp_oos_teardown(void)
97 {
98   tcp_remove_all();
99 }
100
101
102
103 /* Test functions */
104
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)
109 {
110   struct test_tcp_counters counters;
111   struct tcp_pcb* pcb;
112   struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq;
113   char data[] = {
114      1,  2,  3,  4,
115      5,  6,  7,  8,
116      9, 10, 11, 12,
117     13, 14, 15, 16};
118   ip_addr_t remote_ip, local_ip;
119   u16_t data_len;
120   u16_t remote_port = 0x100, local_port = 0x101;
121   struct netif netif;
122   LWIP_UNUSED_ARG(_i);
123
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;
133
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);
138
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 */
143   /*     seqno: 8..16 */
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) */
146   /*     seqno: 4..11 */
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 */
149   /*     seqno: 4..13 */
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 */
152   /*     seqno: 2..15 */
153   p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK);
154   /* FIN, seqno 16 */
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 */
174
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 */
188
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 */
202
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) == 1);
212     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
213     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
214
215     /* pass the segment to tcp_input */
216     tcp_input(p_fin, &netif);
217     /* check if counters are as expected */
218     EXPECT(counters.close_calls == 0);
219     EXPECT(counters.recv_calls == 0);
220     EXPECT(counters.recved_bytes == 0);
221     EXPECT(counters.err_calls == 0);
222     /* ooseq queue: unchanged */
223     EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
224     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
225     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
226
227     /* pass the segment to tcp_input */
228     tcp_input(pinseq, &netif);
229     /* check if counters are as expected */
230     EXPECT(counters.close_calls == 1);
231     EXPECT(counters.recv_calls == 1);
232     EXPECT(counters.recved_bytes == data_len);
233     EXPECT(counters.err_calls == 0);
234     EXPECT(pcb->ooseq == NULL);
235   }
236
237   /* make sure the pcb is freed */
238   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
239   tcp_abort(pcb);
240   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
241 }
242 END_TEST
243
244
245 /** create multiple segments and pass them to tcp_input in a wrong
246  * order to see if ooseq-caching works correctly
247  * FIN is received IN-SEQUENCE at the end */
248 START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
249 {
250   struct test_tcp_counters counters;
251   struct tcp_pcb* pcb;
252   struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN;
253   char data[] = {
254      1,  2,  3,  4,
255      5,  6,  7,  8,
256      9, 10, 11, 12,
257     13, 14, 15, 16};
258   ip_addr_t remote_ip, local_ip;
259   u16_t data_len;
260   u16_t remote_port = 0x100, local_port = 0x101;
261   struct netif netif;
262   LWIP_UNUSED_ARG(_i);
263
264   /* initialize local vars */
265   memset(&netif, 0, sizeof(netif));
266   IP4_ADDR(&local_ip, 192, 168, 1, 1);
267   IP4_ADDR(&remote_ip, 192, 168, 1, 2);
268   data_len = sizeof(data);
269   /* initialize counter struct */
270   memset(&counters, 0, sizeof(counters));
271   counters.expected_data_len = data_len;
272   counters.expected_data = data;
273
274   /* create and initialize the pcb */
275   pcb = test_tcp_new_counters_pcb(&counters);
276   EXPECT_RET(pcb != NULL);
277   tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
278
279   /* create segments */
280   /* p1: 7 bytes - 2 before FIN */
281   /*     seqno: 1..2 */
282   p_1_2  = tcp_create_rx_segment(pcb, &data[1],  2, 1, 0, TCP_ACK);
283   /* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
284   /*     seqno: 4..11 */
285   p_4_8  = tcp_create_rx_segment(pcb, &data[4],  8, 4, 0, TCP_ACK);
286   /* p3: same as p2 but 2 bytes longer and one byte more at the front */
287   /*     seqno: 3..13 */
288   p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK);
289   /* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */
290   /*     seqno: 2..13 */
291   p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK);
292   /* pinseq is the first segment that is held back to create ooseq! */
293   /*     seqno: 0..3 */
294   pinseq = tcp_create_rx_segment(pcb, &data[0],  4, 0, 0, TCP_ACK);
295   /* p5: last byte before FIN */
296   /*     seqno: 15 */
297   p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
298   /* p6: same as p5, should be ignored */
299   p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
300   /* pinseqFIN: last 2 bytes plus FIN */
301   /*     only segment containing seqno 14 and FIN */
302   pinseqFIN = tcp_create_rx_segment(pcb,  &data[14], 2, 14, 0, TCP_ACK|TCP_FIN);
303   EXPECT(pinseq != NULL);
304   EXPECT(p_1_2 != NULL);
305   EXPECT(p_4_8 != NULL);
306   EXPECT(p_3_11 != NULL);
307   EXPECT(p_2_12 != NULL);
308   EXPECT(p_15_1 != NULL);
309   EXPECT(p_15_1a != NULL);
310   EXPECT(pinseqFIN != NULL);
311   if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
312     && (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
313     /* pass the segment to tcp_input */
314     tcp_input(p_1_2, &netif);
315     /* check if counters are as expected */
316     EXPECT(counters.close_calls == 0);
317     EXPECT(counters.recv_calls == 0);
318     EXPECT(counters.recved_bytes == 0);
319     EXPECT(counters.err_calls == 0);
320     /* check ooseq queue */
321     EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
322     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
323     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
324
325     /* pass the segment to tcp_input */
326     tcp_input(p_4_8, &netif);
327     /* check if counters are as expected */
328     EXPECT(counters.close_calls == 0);
329     EXPECT(counters.recv_calls == 0);
330     EXPECT(counters.recved_bytes == 0);
331     EXPECT(counters.err_calls == 0);
332     /* check ooseq queue */
333     EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
334     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
335     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
336     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4);
337     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
338
339     /* pass the segment to tcp_input */
340     tcp_input(p_3_11, &netif);
341     /* check if counters are as expected */
342     EXPECT(counters.close_calls == 0);
343     EXPECT(counters.recv_calls == 0);
344     EXPECT(counters.recved_bytes == 0);
345     EXPECT(counters.err_calls == 0);
346     /* check ooseq queue */
347     EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
348     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
349     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
350     /* p_3_11 has removed p_4_8 from ooseq */
351     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3);
352     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
353
354     /* pass the segment to tcp_input */
355     tcp_input(p_2_12, &netif);
356     /* check if counters are as expected */
357     EXPECT(counters.close_calls == 0);
358     EXPECT(counters.recv_calls == 0);
359     EXPECT(counters.recved_bytes == 0);
360     EXPECT(counters.err_calls == 0);
361     /* check ooseq queue */
362     EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
363     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
364     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
365     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
366     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12);
367
368     /* pass the segment to tcp_input */
369     tcp_input(pinseq, &netif);
370     /* check if counters are as expected */
371     EXPECT(counters.close_calls == 0);
372     EXPECT(counters.recv_calls == 1);
373     EXPECT(counters.recved_bytes == 14);
374     EXPECT(counters.err_calls == 0);
375     EXPECT(pcb->ooseq == NULL);
376
377     /* pass the segment to tcp_input */
378     tcp_input(p_15_1, &netif);
379     /* check if counters are as expected */
380     EXPECT(counters.close_calls == 0);
381     EXPECT(counters.recv_calls == 1);
382     EXPECT(counters.recved_bytes == 14);
383     EXPECT(counters.err_calls == 0);
384     /* check ooseq queue */
385     EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
386     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
387     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
388
389     /* pass the segment to tcp_input */
390     tcp_input(p_15_1a, &netif);
391     /* check if counters are as expected */
392     EXPECT(counters.close_calls == 0);
393     EXPECT(counters.recv_calls == 1);
394     EXPECT(counters.recved_bytes == 14);
395     EXPECT(counters.err_calls == 0);
396     /* check ooseq queue: unchanged */
397     EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
398     EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
399     EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
400
401     /* pass the segment to tcp_input */
402     tcp_input(pinseqFIN, &netif);
403     /* check if counters are as expected */
404     EXPECT(counters.close_calls == 1);
405     EXPECT(counters.recv_calls == 2);
406     EXPECT(counters.recved_bytes == data_len);
407     EXPECT(counters.err_calls == 0);
408     EXPECT(pcb->ooseq == NULL);
409   }
410
411   /* make sure the pcb is freed */
412   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
413   tcp_abort(pcb);
414   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
415 }
416 END_TEST
417
418 /** Create the suite including all tests for this module */
419 Suite *
420 tcp_oos_suite(void)
421 {
422   TFun tests[] = {
423     test_tcp_recv_ooseq_FIN_OOSEQ,
424     test_tcp_recv_ooseq_FIN_INSEQ,
425   };
426   return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);
427 }