]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - test/unit/tcp/test_tcp_oos.c
8e4c7f4d0e703833bd130864d2b7b13772f67945
[pes-rpp/rpp-lwip.git] / test / unit / tcp / test_tcp_oos.c
1 #include "test_tcp_oos.h"
2
3 #include "lwip/tcp.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   struct ip_addr 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) == 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 */
216
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 */
230
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);
239   }
240
241   /* make sure the pcb is freed */
242   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
243   tcp_abort(pcb);
244   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
245 }
246 END_TEST
247
248
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)
253 {
254   struct test_tcp_counters counters;
255   struct tcp_pcb* pcb;
256   struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN;
257   char data[] = {
258      1,  2,  3,  4,
259      5,  6,  7,  8,
260      9, 10, 11, 12,
261     13, 14, 15, 16};
262   struct ip_addr remote_ip, local_ip;
263   u16_t data_len;
264   u16_t remote_port = 0x100, local_port = 0x101;
265   struct netif netif;
266   LWIP_UNUSED_ARG(_i);
267
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;
277
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);
282
283   /* create segments */
284   /* p1: 7 bytes - 2 before FIN */
285   /*     seqno: 1..2 */
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) */
288   /*     seqno: 4..11 */
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 */
291   /*     seqno: 3..13 */
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 */
294   /*     seqno: 2..13 */
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! */
297   /*     seqno: 0..3 */
298   pinseq = tcp_create_rx_segment(pcb, &data[0],  4, 0, 0, TCP_ACK);
299   /* p5: last byte before FIN */
300   /*     seqno: 15 */
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);
328
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);
342
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);
357
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);
373
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);
382
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);
394
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);
406
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);
415   }
416
417   /* make sure the pcb is freed */
418   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
419   tcp_abort(pcb);
420   EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
421 }
422 END_TEST
423
424 /** Create the suite including all tests for this module */
425 Suite *
426 tcp_oos_suite(void)
427 {
428   TFun tests[] = {
429     test_tcp_recv_ooseq_FIN_OOSEQ,
430     test_tcp_recv_ooseq_FIN_INSEQ,
431   };
432   return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);
433 }