source: mainline/uspace/srv/net/tcp/test/seq_no.c@ e73dbc1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e73dbc1 was e73dbc1, checked in by Jiri Svoboda <jiri@…>, 8 years ago

Add TCP unit tests for segment and seq_no modules. Fix seq_no_segment_acceptable() returning false if receive window is a strict subset of the segment.

  • Property mode set to 100644
File size: 12.6 KB
Line 
1/*
2 * Copyright (c) 2017 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <errno.h>
30#include <inet/endpoint.h>
31#include <pcut/pcut.h>
32
33#include "../conn.h"
34#include "../segment.h"
35#include "../seq_no.h"
36
37PCUT_INIT
38
39PCUT_TEST_SUITE(seq_no);
40
41/** Test seq_no_ack_acceptable() */
42PCUT_TEST(ack_acceptable)
43{
44 tcp_conn_t *conn;
45 inet_ep2_t epp;
46
47 inet_ep2_init(&epp);
48 conn = tcp_conn_new(&epp);
49 PCUT_ASSERT_NOT_NULL(conn);
50
51 /* ACK is acceptable iff SND.UNA < SEG.ACK <= SND.NXT */
52
53 conn->snd_una = 10;
54 conn->snd_nxt = 30;
55
56 PCUT_ASSERT_FALSE(seq_no_ack_acceptable(conn, 9));
57 PCUT_ASSERT_FALSE(seq_no_ack_acceptable(conn, 10));
58 PCUT_ASSERT_TRUE(seq_no_ack_acceptable(conn, 11));
59 PCUT_ASSERT_TRUE(seq_no_ack_acceptable(conn, 29));
60 PCUT_ASSERT_TRUE(seq_no_ack_acceptable(conn, 30));
61 PCUT_ASSERT_FALSE(seq_no_ack_acceptable(conn, 31));
62
63 /* We also test whether seq_no_lt_le() wraps around properly */
64
65 conn->snd_una = 30;
66 conn->snd_nxt = 10;
67
68 PCUT_ASSERT_FALSE(seq_no_ack_acceptable(conn, 29));
69 PCUT_ASSERT_FALSE(seq_no_ack_acceptable(conn, 30));
70 PCUT_ASSERT_TRUE(seq_no_ack_acceptable(conn, 31));
71 PCUT_ASSERT_TRUE(seq_no_ack_acceptable(conn, 9));
72 PCUT_ASSERT_TRUE(seq_no_ack_acceptable(conn, 10));
73 PCUT_ASSERT_FALSE(seq_no_ack_acceptable(conn, 11));
74
75 tcp_conn_delete(conn);
76}
77
78/** Test seq_no_ack_duplicate() */
79PCUT_TEST(ack_duplicate)
80{
81 tcp_conn_t *conn;
82 inet_ep2_t epp;
83
84 inet_ep2_init(&epp);
85 conn = tcp_conn_new(&epp);
86 PCUT_ASSERT_NOT_NULL(conn);
87
88 /* ACK is duplicate iff SEG.ACK <= SND.UNA */
89
90 conn->snd_una = 10;
91
92 PCUT_ASSERT_TRUE(seq_no_ack_duplicate(conn, 9));
93 PCUT_ASSERT_TRUE(seq_no_ack_duplicate(conn, 10));
94 PCUT_ASSERT_FALSE(seq_no_ack_duplicate(conn, 11));
95
96 conn->snd_una = (uint32_t) -10;
97
98 PCUT_ASSERT_TRUE(seq_no_ack_duplicate(conn, (uint32_t) -11));
99 PCUT_ASSERT_TRUE(seq_no_ack_duplicate(conn, (uint32_t) -10));
100 PCUT_ASSERT_FALSE(seq_no_ack_duplicate(conn, (uint32_t) -9));
101
102 tcp_conn_delete(conn);
103}
104
105/** Test seq_no_in_rcv_wnd() */
106PCUT_TEST(in_rcv_wnd)
107{
108 tcp_conn_t *conn;
109 inet_ep2_t epp;
110
111 inet_ep2_init(&epp);
112 conn = tcp_conn_new(&epp);
113 PCUT_ASSERT_NOT_NULL(conn);
114
115 /* In receive window iff RCV.WND <= SEG.SEQ <= SND.UNA */
116
117 conn->rcv_nxt = 10;
118 conn->rcv_wnd = 20;
119
120 PCUT_ASSERT_FALSE(seq_no_in_rcv_wnd(conn, 9));
121 PCUT_ASSERT_TRUE(seq_no_in_rcv_wnd(conn, 10));
122 PCUT_ASSERT_TRUE(seq_no_in_rcv_wnd(conn, 11));
123 PCUT_ASSERT_TRUE(seq_no_in_rcv_wnd(conn, 29));
124 PCUT_ASSERT_FALSE(seq_no_in_rcv_wnd(conn, 30));
125 PCUT_ASSERT_FALSE(seq_no_in_rcv_wnd(conn, 31));
126
127 /* We also test whether seq_no_le_lt() wraps around properly */
128
129 conn->rcv_nxt = 20;
130 conn->rcv_wnd = (uint32_t) -10;
131
132 PCUT_ASSERT_FALSE(seq_no_in_rcv_wnd(conn,19));
133 PCUT_ASSERT_TRUE(seq_no_in_rcv_wnd(conn, 20));
134 PCUT_ASSERT_TRUE(seq_no_in_rcv_wnd(conn, 21));
135 PCUT_ASSERT_TRUE(seq_no_in_rcv_wnd(conn, 9));
136 PCUT_ASSERT_FALSE(seq_no_in_rcv_wnd(conn, 10));
137 PCUT_ASSERT_FALSE(seq_no_in_rcv_wnd(conn, 11));
138
139 tcp_conn_delete(conn);
140}
141
142/** Test seq_no_new_wnd_update() */
143PCUT_TEST(new_wnd_update)
144{
145 tcp_conn_t *conn;
146 inet_ep2_t epp;
147 tcp_segment_t *seg;
148
149 inet_ep2_init(&epp);
150 conn = tcp_conn_new(&epp);
151 PCUT_ASSERT_NOT_NULL(conn);
152
153 /*
154 * Segment must be acceptable. Segment has new window update iff
155 * either SND.WL1 < SEG.SEQ or
156 * (SND.WL1 = SEG.SEQ and SND.WL2 <= SEG.ACK)
157 */
158
159 conn->rcv_nxt = 10;
160 conn->rcv_wnd = 20;
161 conn->snd_una = 30;
162 conn->snd_wnd = 40;
163 conn->snd_wl1 = 15;
164 conn->snd_wl2 = 60;
165
166 seg = tcp_segment_make_ctrl(CTL_ACK);
167 PCUT_ASSERT_NOT_NULL(seg);
168
169 seg->seq = 14;
170 seg->ack = 80;
171 PCUT_ASSERT_FALSE(seq_no_new_wnd_update(conn, seg));
172
173 seg->seq = 15;
174 seg->ack = 59;
175 PCUT_ASSERT_FALSE(seq_no_new_wnd_update(conn, seg));
176
177 seg->seq = 15;
178 seg->ack = 60;
179 PCUT_ASSERT_TRUE(seq_no_new_wnd_update(conn, seg));
180
181 seg->seq = 16;
182 seg->ack = 50;
183 PCUT_ASSERT_TRUE(seq_no_new_wnd_update(conn, seg));
184
185 tcp_segment_delete(seg);
186 tcp_conn_delete(conn);
187}
188
189/** Test seq_no_segment_acked() */
190PCUT_TEST(segment_acked)
191{
192 tcp_conn_t *conn;
193 inet_ep2_t epp;
194 tcp_segment_t *seg;
195 uint8_t *data;
196 size_t dsize;
197
198 inet_ep2_init(&epp);
199 conn = tcp_conn_new(&epp);
200 PCUT_ASSERT_NOT_NULL(conn);
201
202 dsize = 15;
203 data = calloc(dsize, 1);
204 PCUT_ASSERT_NOT_NULL(data);
205
206 seg = tcp_segment_make_data(0, data, dsize);
207 PCUT_ASSERT_NOT_NULL(seg);
208
209 /* Segment is acked iff SEG.SEQ + SEG.LEN <= SND.UNA */
210
211 seg->seq = 10;
212 PCUT_ASSERT_INT_EQUALS(dsize, seg->len);
213
214 PCUT_ASSERT_FALSE(seq_no_segment_acked(conn, seg, 24));
215 PCUT_ASSERT_TRUE(seq_no_segment_acked(conn, seg, 25));
216
217 tcp_segment_delete(seg);
218 tcp_conn_delete(conn);
219 free(data);
220}
221
222/** Test seq_no_syn_acked() */
223PCUT_TEST(syn_acked)
224{
225 tcp_conn_t *conn;
226 inet_ep2_t epp;
227
228 inet_ep2_init(&epp);
229 conn = tcp_conn_new(&epp);
230 PCUT_ASSERT_NOT_NULL(conn);
231
232 conn->iss = 1;
233 conn->snd_una = 1;
234 conn->snd_nxt = 2;
235
236 PCUT_ASSERT_FALSE(seq_no_syn_acked(conn));
237
238 conn->snd_una = 2;
239 PCUT_ASSERT_TRUE(seq_no_syn_acked(conn));
240
241 tcp_conn_delete(conn);
242}
243
244/** Test seq_no_segment_acceptable() */
245PCUT_TEST(segment_acceptable)
246{
247 tcp_conn_t *conn;
248 inet_ep2_t epp;
249 tcp_segment_t *seg;
250 uint8_t *data;
251 size_t dsize;
252
253 inet_ep2_init(&epp);
254 conn = tcp_conn_new(&epp);
255 PCUT_ASSERT_NOT_NULL(conn);
256
257 dsize = 15;
258 data = calloc(dsize, 1);
259 PCUT_ASSERT_NOT_NULL(data);
260
261 seg = tcp_segment_make_data(0, data, dsize);
262 PCUT_ASSERT_NOT_NULL(seg);
263
264 /* Segment acceptable iff overlaps receive window */
265
266 /* Segment shorter than receive window */
267 conn->rcv_nxt = 30;
268 conn->rcv_wnd = 20;
269
270 PCUT_ASSERT_INT_EQUALS(dsize, seg->len);
271
272 seg->seq = 10;
273 PCUT_ASSERT_FALSE(seq_no_segment_acceptable(conn, seg));
274
275 seg->seq = 15;
276 PCUT_ASSERT_FALSE(seq_no_segment_acceptable(conn, seg));
277
278 seg->seq = 16;
279 PCUT_ASSERT_TRUE(seq_no_segment_acceptable(conn, seg));
280
281 seg->seq = 49;
282 PCUT_ASSERT_TRUE(seq_no_segment_acceptable(conn, seg));
283
284 seg->seq = 50;
285 PCUT_ASSERT_FALSE(seq_no_segment_acceptable(conn, seg));
286
287 /* Segment longer than receive window */
288 conn->rcv_nxt = 30;
289 conn->rcv_wnd = 10;
290
291 PCUT_ASSERT_INT_EQUALS(dsize, seg->len);
292
293 seg->seq = 10;
294 PCUT_ASSERT_FALSE(seq_no_segment_acceptable(conn, seg));
295
296 seg->seq = 15;
297 PCUT_ASSERT_FALSE(seq_no_segment_acceptable(conn, seg));
298
299 seg->seq = 16;
300 PCUT_ASSERT_TRUE(seq_no_segment_acceptable(conn, seg));
301
302 seg->seq = 39;
303 PCUT_ASSERT_TRUE(seq_no_segment_acceptable(conn, seg));
304
305 seg->seq = 40;
306 PCUT_ASSERT_FALSE(seq_no_segment_acceptable(conn, seg));
307
308 tcp_segment_delete(seg);
309 tcp_conn_delete(conn);
310 free(data);
311}
312
313/** Test seq_no_seg_trim_calc() */
314PCUT_TEST(seg_trim_calc)
315{
316 tcp_conn_t *conn;
317 inet_ep2_t epp;
318 tcp_segment_t *seg;
319 uint8_t *data;
320 size_t dsize;
321 uint32_t ltrim, rtrim;
322
323 inet_ep2_init(&epp);
324 conn = tcp_conn_new(&epp);
325 PCUT_ASSERT_NOT_NULL(conn);
326
327 dsize = 15;
328 data = calloc(dsize, 1);
329 PCUT_ASSERT_NOT_NULL(data);
330
331 seg = tcp_segment_make_data(0, data, dsize);
332 PCUT_ASSERT_NOT_NULL(seg);
333
334 /* Segment must be acceptable, amount of trim needed */
335
336 /* Segment shorter than receive window */
337 conn->rcv_nxt = 30;
338 conn->rcv_wnd = 20;
339
340 PCUT_ASSERT_INT_EQUALS(dsize, seg->len);
341
342 seg->seq = 16;
343 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
344 PCUT_ASSERT_INT_EQUALS(14, ltrim);
345 PCUT_ASSERT_INT_EQUALS(0, rtrim);
346
347 seg->seq = 17;
348 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
349 PCUT_ASSERT_INT_EQUALS(13, ltrim);
350 PCUT_ASSERT_INT_EQUALS(0, rtrim);
351
352 seg->seq = 29;
353 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
354 PCUT_ASSERT_INT_EQUALS(1, ltrim);
355 PCUT_ASSERT_INT_EQUALS(0, rtrim);
356
357 seg->seq = 30;
358 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
359 PCUT_ASSERT_INT_EQUALS(0, ltrim);
360 PCUT_ASSERT_INT_EQUALS(0, rtrim);
361
362 seg->seq = 31;
363 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
364 PCUT_ASSERT_INT_EQUALS(0, ltrim);
365 PCUT_ASSERT_INT_EQUALS(0, rtrim);
366
367 seg->seq = 35;
368 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
369 PCUT_ASSERT_INT_EQUALS(0, ltrim);
370 PCUT_ASSERT_INT_EQUALS(0, rtrim);
371
372 seg->seq = 36;
373 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
374 PCUT_ASSERT_INT_EQUALS(0, ltrim);
375 PCUT_ASSERT_INT_EQUALS(1, rtrim);
376
377 seg->seq = 37;
378 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
379 PCUT_ASSERT_INT_EQUALS(0, ltrim);
380 PCUT_ASSERT_INT_EQUALS(2, rtrim);
381
382 seg->seq = 48;
383 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
384 PCUT_ASSERT_INT_EQUALS(0, ltrim);
385 PCUT_ASSERT_INT_EQUALS(13, rtrim);
386
387 seg->seq = 49;
388 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
389 PCUT_ASSERT_INT_EQUALS(0, ltrim);
390 PCUT_ASSERT_INT_EQUALS(14, rtrim);
391
392 /* Segment longer than receive window */
393 conn->rcv_nxt = 30;
394 conn->rcv_wnd = 10;
395
396 PCUT_ASSERT_INT_EQUALS(dsize, seg->len);
397
398 seg->seq = 16;
399 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
400 PCUT_ASSERT_INT_EQUALS(14, ltrim);
401 PCUT_ASSERT_INT_EQUALS(0, rtrim);
402
403 seg->seq = 17;
404 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
405 PCUT_ASSERT_INT_EQUALS(13, ltrim);
406 PCUT_ASSERT_INT_EQUALS(0, rtrim);
407
408 seg->seq = 24;
409 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
410 PCUT_ASSERT_INT_EQUALS(6, ltrim);
411 PCUT_ASSERT_INT_EQUALS(0, rtrim);
412
413 seg->seq = 25;
414 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
415 PCUT_ASSERT_INT_EQUALS(5, ltrim);
416 PCUT_ASSERT_INT_EQUALS(0, rtrim);
417
418 seg->seq = 26;
419 seq_no_seg_trim_calc(conn, seg, &ltrim, &rtrim);
420 PCUT_ASSERT_INT_EQUALS(4, ltrim);
421 PCUT_ASSERT_INT_EQUALS(1, rtrim);
422
423 tcp_segment_delete(seg);
424 tcp_conn_delete(conn);
425 free(data);
426}
427
428/** Test seq_no_seg_cmp() */
429PCUT_TEST(seg_cmp)
430{
431 tcp_conn_t *conn;
432 inet_ep2_t epp;
433 tcp_segment_t *seg1, *seg2;
434 uint8_t *data;
435 size_t dsize;
436
437 inet_ep2_init(&epp);
438 conn = tcp_conn_new(&epp);
439 PCUT_ASSERT_NOT_NULL(conn);
440
441 dsize = 15;
442 data = calloc(dsize, 1);
443 PCUT_ASSERT_NOT_NULL(data);
444
445 seg1 = tcp_segment_make_data(0, data, dsize);
446 PCUT_ASSERT_NOT_NULL(seg1);
447 seg2 = tcp_segment_make_data(0, data, dsize);
448 PCUT_ASSERT_NOT_NULL(seg2);
449
450 /* Both segments must be acceptable */
451
452 conn->rcv_nxt = 10;
453 conn->rcv_wnd = 20;
454
455 PCUT_ASSERT_INT_EQUALS(dsize, seg1->len);
456 PCUT_ASSERT_INT_EQUALS(dsize, seg2->len);
457
458 seg1->seq = 5;
459 seg2->seq = 6;
460 PCUT_ASSERT_INT_EQUALS(-1, seq_no_seg_cmp(conn, seg1, seg2));
461
462 seg1->seq = 6;
463 seg2->seq = 6;
464 PCUT_ASSERT_INT_EQUALS(0, seq_no_seg_cmp(conn, seg1, seg2));
465
466 seg1->seq = 6;
467 seg2->seq = 5;
468 PCUT_ASSERT_INT_EQUALS(1, seq_no_seg_cmp(conn, seg1, seg2));
469
470 tcp_segment_delete(seg1);
471 tcp_segment_delete(seg2);
472 tcp_conn_delete(conn);
473 free(data);
474}
475
476/** Test seq_no_control_len() */
477PCUT_TEST(control_len)
478{
479 PCUT_ASSERT_INT_EQUALS(0, seq_no_control_len(0));
480 PCUT_ASSERT_INT_EQUALS(0, seq_no_control_len(CTL_ACK));
481 PCUT_ASSERT_INT_EQUALS(0, seq_no_control_len(CTL_RST));
482 PCUT_ASSERT_INT_EQUALS(0, seq_no_control_len(CTL_ACK | CTL_RST));
483 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_SYN));
484 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_FIN));
485 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_SYN | CTL_ACK));
486 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_FIN | CTL_ACK));
487 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_SYN | CTL_RST));
488 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_FIN | CTL_RST));
489 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_SYN | CTL_ACK |
490 CTL_RST));
491 PCUT_ASSERT_INT_EQUALS(1, seq_no_control_len(CTL_FIN | CTL_ACK |
492 CTL_RST));
493 PCUT_ASSERT_INT_EQUALS(2, seq_no_control_len(CTL_SYN | CTL_FIN));
494 PCUT_ASSERT_INT_EQUALS(2, seq_no_control_len(CTL_SYN | CTL_FIN |
495 CTL_ACK));
496 PCUT_ASSERT_INT_EQUALS(2, seq_no_control_len(CTL_SYN | CTL_FIN |
497 CTL_RST));
498 PCUT_ASSERT_INT_EQUALS(2, seq_no_control_len(CTL_SYN | CTL_FIN |
499 CTL_ACK | CTL_RST));
500}
501
502PCUT_EXPORT(seq_no);
Note: See TracBrowser for help on using the repository browser.