]> git.ipfire.org Git - thirdparty/bird.git/blob - lib/flowspec_test.c
ed4afe515af012cb4a766496aa603bfa5cf6c2a5
[thirdparty/bird.git] / lib / flowspec_test.c
1 /*
2 * BIRD Library -- Flow specification (RFC 5575) Tests
3 *
4 * (c) 2016 CZ.NIC z.s.p.o.
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 #include "test/birdtest.h"
10 #include "lib/flowspec.h"
11
12 #define NET_ADDR_FLOW4_(what,prefix,pxlen,data_) \
13 do \
14 { \
15 what = alloca(sizeof(net_addr_flow4) + 128); \
16 *what = NET_ADDR_FLOW4(prefix, pxlen, sizeof(data_)); \
17 memcpy(what->data, &(data_), sizeof(data_)); \
18 } while(0)
19
20 #define NET_ADDR_FLOW6_(what,prefix,pxlen,data_) \
21 do \
22 { \
23 what = alloca(sizeof(net_addr_flow6) + 128); \
24 *what = NET_ADDR_FLOW6(prefix, pxlen, sizeof(data_)); \
25 memcpy(what->data, &(data_), sizeof(data_)); \
26 } while(0)
27
28 static int
29 t_read_length(void)
30 {
31 byte data[] = { 0xcc, 0xcc, 0xcc };
32
33 for (uint expect = 0; expect < 0xf0; expect++)
34 {
35 *data = expect;
36 uint get = flow_read_length(data);
37 bt_assert_msg(get == expect, "Testing get length 0x%02x (get 0x%02x)", expect, get);
38 }
39
40 for (uint expect = 0; expect <= 0xfff; expect++)
41 {
42 put_u16(data, expect | 0xf000);
43 uint get = flow_read_length(data);
44 bt_assert_msg(get == expect, "Testing get length 0x%03x (get 0x%03x)", expect, get);
45 }
46
47 return 1;
48 }
49
50 static int
51 t_write_length(void)
52 {
53 byte data[] = { 0xcc, 0xcc, 0xcc };
54
55 for (uint expect = 0; expect <= 0xfff; expect++)
56 {
57 uint offset = flow_write_length(data, expect);
58
59 uint set = (expect < 0xf0) ? *data : (get_u16(data) & 0x0fff);
60 bt_assert_msg(set == expect, "Testing set length 0x%03x (set 0x%03x)", expect, set);
61 bt_assert(offset == (expect < 0xf0 ? 1 : 2));
62 }
63
64 return 1;
65 }
66
67 static int
68 t_first_part(void)
69 {
70 net_addr_flow4 *f;
71 NET_ADDR_FLOW4_(f, ip4_build(10,0,0,1), 24, ((byte[]) { 0x00, 0x00, 0xab }));
72
73 const byte *under240 = &f->data[1];
74 const byte *above240 = &f->data[2];
75
76 /* Case 0x00 0x00 */
77 bt_assert(flow4_first_part(f) == NULL);
78
79 /* Case 0x01 0x00 */
80 f->data[0] = 0x01;
81 bt_assert(flow4_first_part(f) == under240);
82
83 /* Case 0xef 0x00 */
84 f->data[0] = 0xef;
85 bt_assert(flow4_first_part(f) == under240);
86
87 /* Case 0xf0 0x00 */
88 f->data[0] = 0xf0;
89 bt_assert(flow4_first_part(f) == NULL);
90
91 /* Case 0xf0 0x01 */
92 f->data[1] = 0x01;
93 bt_assert(flow4_first_part(f) == above240);
94
95 /* Case 0xff 0xff */
96 f->data[0] = 0xff;
97 f->data[1] = 0xff;
98 bt_assert(flow4_first_part(f) == above240);
99
100 return 1;
101 }
102
103 static int
104 t_iterators4(void)
105 {
106 net_addr_flow4 *f;
107 NET_ADDR_FLOW4_(f, ip4_build(5,6,7,0), 24, ((byte[]) {
108 25, /* Length */
109 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
110 FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
111 FLOW_TYPE_IP_PROTOCOL, 0x81, 0x06,
112 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
113 FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
114 }));
115
116 const byte *start = f->data;
117 const byte *p1_dst_pfx = &f->data[1];
118 const byte *p2_src_pfx = &f->data[6];
119 const byte *p3_ip_proto = &f->data[12];
120 const byte *p4_port = &f->data[15];
121 const byte *p5_tcp_flags = &f->data[23];
122 const byte *end = &f->data[25];
123
124 bt_assert(flow_read_length(f->data) == (end-start));
125 bt_assert(flow4_first_part(f) == p1_dst_pfx);
126
127 bt_assert(flow4_next_part(p1_dst_pfx, end) == p2_src_pfx);
128 bt_assert(flow4_next_part(p2_src_pfx, end) == p3_ip_proto);
129 bt_assert(flow4_next_part(p3_ip_proto, end) == p4_port);
130 bt_assert(flow4_next_part(p4_port, end) == p5_tcp_flags);
131 bt_assert(flow4_next_part(p5_tcp_flags, end) == NULL);
132
133 return 1;
134 }
135
136 static int
137 t_iterators6(void)
138 {
139 net_addr_flow6 *f;
140 NET_ADDR_FLOW6_(f, ip6_build(0,0,0x12345678,0x9a000000), 0x68, ((byte[]) {
141 26, /* Length */
142 FLOW_TYPE_DST_PREFIX, 0x68, 0x40, 0x12, 0x34, 0x56, 0x78, 0x9a,
143 FLOW_TYPE_SRC_PREFIX, 0x08, 0x0, 0xc0,
144 FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
145 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
146 FLOW_TYPE_LABEL, 0x80, 0x55,
147 }));
148
149 const byte *start = f->data;
150 const byte *p1_dst_pfx = &f->data[1];
151 const byte *p2_src_pfx = &f->data[9];
152 const byte *p3_next_header = &f->data[13];
153 const byte *p4_port = &f->data[16];
154 const byte *p5_label = &f->data[24];
155 const byte *end = &f->data[26];
156
157 bt_assert(flow_read_length(f->data) == (end-start));
158 bt_assert(flow6_first_part(f) == p1_dst_pfx);
159
160 bt_assert(flow6_next_part(p1_dst_pfx, end) == p2_src_pfx);
161 bt_assert(flow6_next_part(p2_src_pfx, end) == p3_next_header);
162 bt_assert(flow6_next_part(p3_next_header, end) == p4_port);
163 bt_assert(flow6_next_part(p4_port, end) == p5_label);
164 bt_assert(flow6_next_part(p5_label, end) == NULL);
165
166 return 1;
167 }
168
169 static int
170 t_accessors4(void)
171 {
172 net_addr_flow4 *f;
173 NET_ADDR_FLOW4_(f, ip4_build(5,6,7,0), 24, ((byte[]) {
174 25, /* Length */
175 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
176 FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
177 FLOW_TYPE_IP_PROTOCOL, 0x81, 0x06,
178 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
179 FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
180 }));
181
182 const byte *p1_dst_px = &f->data[1];
183 const ip4_addr p1_dst_addr = ip4_build(5,6,7,0);
184
185 const byte *p2_src_px = &f->data[6];
186 const ip4_addr p2_src_addr = ip4_build(10,11,12,13);
187
188 bt_assert(ip4_equal(flow_read_ip4_part(p1_dst_px), p1_dst_addr));
189 bt_assert(ip4_equal(flow_read_ip4_part(p2_src_px), p2_src_addr));
190
191 return 1;
192 }
193
194 static int
195 t_accessors6(void)
196 {
197 net_addr_flow6 *f;
198 NET_ADDR_FLOW6_(f, ip6_build(0,0,0x12345678,0x9a000000), 0x68, ((byte[]) {
199 26, /* Length */
200 FLOW_TYPE_DST_PREFIX, 0x68, 0x40, 0x12, 0x34, 0x56, 0x78, 0x9a,
201 FLOW_TYPE_SRC_PREFIX, 0x08, 0x0, 0xc0,
202 FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
203 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
204 FLOW_TYPE_LABEL, 0x80, 0x55,
205 }));
206
207 const byte *p1_dst_px = &f->data[1];
208 const ip6_addr p1_dst_addr = ip6_build(0,0,0x12345678,0x9a000000);
209
210 const byte *p2_src_px = &f->data[9];
211 const ip6_addr p2_src_addr = ip6_build(0xc0000000, 0, 0, 0);
212
213 bt_assert(ip6_equal(flow_read_ip6_part(p1_dst_px), p1_dst_addr));
214 bt_assert(ip6_equal(flow_read_ip6_part(p2_src_px), p2_src_addr));
215
216 return 1;
217 }
218
219 static int
220 t_validation4(void)
221 {
222 enum flow_validated_state res;
223
224 byte nlri1[] = {
225 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
226 FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
227 FLOW_TYPE_IP_PROTOCOL, 0x81, 0x06,
228 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
229 FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
230 };
231
232 /* Empty NLRI */
233 res = flow4_validate(nlri1, 0);
234 bt_assert(res == FLOW_ST_VALID);
235
236 /* Valid / Not Complete testing */
237 uint valid_sizes[] = {5, 11, 14, 22, 25, 0};
238 uint valid_idx = 0;
239 for (uint size = 1; size <= sizeof(nlri1); size++)
240 {
241 res = flow4_validate(nlri1, size);
242 bt_debug("size %u, result: %s\n", size, flow_validated_state_str(res));
243 if (size == valid_sizes[valid_idx])
244 {
245 valid_idx++;
246 bt_assert(res == FLOW_ST_VALID);
247 }
248 else
249 {
250 bt_assert(res == FLOW_ST_NOT_COMPLETE);
251 }
252 }
253
254 /* Misc err tests */
255
256 struct tset {
257 enum flow_validated_state expect;
258 char *description;
259 u16 size;
260 byte *nlri;
261 };
262
263 #define TS(type, msg, data) ((struct tset) {type, msg, sizeof(data), (data)})
264 struct tset tset[] = {
265 TS(
266 FLOW_ST_EXCEED_MAX_PREFIX_LENGTH,
267 "33-length IPv4 prefix",
268 ((byte []) {
269 FLOW_TYPE_DST_PREFIX, 33, 5, 6, 7, 8, 9
270 })
271 ),
272 TS(
273 FLOW_ST_BAD_TYPE_ORDER,
274 "Bad flowspec component type order",
275 ((byte []) {
276 FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
277 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
278 })
279 ),
280 TS(
281 FLOW_ST_BAD_TYPE_ORDER,
282 "Doubled destination prefix component",
283 ((byte []) {
284 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
285 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
286 })
287 ),
288 TS(
289 FLOW_ST_AND_BIT_SHOULD_BE_UNSET,
290 "The first numeric operator has set the AND bit",
291 ((byte []) {
292 FLOW_TYPE_PORT, 0x43, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
293 })
294 ),
295 TS(
296 FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED,
297 "Set zero bit in operand to one",
298 ((byte []) {
299 FLOW_TYPE_IP_PROTOCOL, 0x89, 0x06,
300 })
301 ),
302 TS(
303 FLOW_ST_UNKNOWN_COMPONENT,
304 "Unknown component of type number 13",
305 ((byte []) {
306 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
307 FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
308 13 /*something new*/, 0x80, 0x55,
309 })
310 ),
311 };
312 #undef TS
313
314 for (uint tcase = 0; tcase < ARRAY_SIZE(tset); tcase++)
315 {
316 res = flow4_validate(tset[tcase].nlri, tset[tcase].size);
317 bt_assert_msg(res == tset[tcase].expect, "Assertion (%s == %s) %s", flow_validated_state_str(res), flow_validated_state_str(tset[tcase].expect), tset[tcase].description);
318 }
319
320 return 1;
321 }
322
323 static int
324 t_validation6(void)
325 {
326 enum flow_validated_state res;
327
328 byte nlri1[] = {
329 FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
330 FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
331 FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
332 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
333 FLOW_TYPE_LABEL, 0x80, 0x55,
334 };
335
336 /* Isn't included destination prefix */
337 res = flow6_validate(nlri1, 0);
338 bt_assert(res == FLOW_ST_VALID);
339
340 /* Valid / Not Complete testing */
341 uint valid_sizes[] = {0, 9, 13, 16, 24, 27, 0};
342 uint valid_idx = 0;
343 for (uint size = 0; size <= sizeof(nlri1); size++)
344 {
345 res = flow6_validate(nlri1, size);
346 bt_debug("size %u, result: %s\n", size, flow_validated_state_str(res));
347 if (size == valid_sizes[valid_idx])
348 {
349 valid_idx++;
350 bt_assert(res == FLOW_ST_VALID);
351 }
352 else
353 {
354 bt_assert(res == FLOW_ST_NOT_COMPLETE);
355 }
356 }
357
358 /* Misc err tests */
359
360 struct tset {
361 enum flow_validated_state expect;
362 char *description;
363 u16 size;
364 byte *nlri;
365 };
366
367 #define TS(type, msg, data) ((struct tset) {type, msg, sizeof(data), (data)})
368 struct tset tset[] = {
369 TS(
370 FLOW_ST_EXCEED_MAX_PREFIX_LENGTH,
371 "129-length IPv6 prefix",
372 ((byte []) {
373 FLOW_TYPE_DST_PREFIX, 129, 64, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
374 })
375 ),
376 TS(
377 FLOW_ST_EXCEED_MAX_PREFIX_OFFSET,
378 "Prefix offset is higher than prefix length",
379 ((byte []) {
380 FLOW_TYPE_DST_PREFIX, 48, 64, 0x40, 0x12, 0x34
381 })
382 ),
383 TS(
384 FLOW_ST_BAD_TYPE_ORDER,
385 "Bad flowspec component type order",
386 ((byte []) {
387 FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
388 FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
389 })
390 ),
391 TS(
392 FLOW_ST_BAD_TYPE_ORDER,
393 "Doubled destination prefix component",
394 ((byte []) {
395 FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
396 FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
397 })
398 ),
399 TS(
400 FLOW_ST_AND_BIT_SHOULD_BE_UNSET,
401 "The first numeric operator has set the AND bit",
402 ((byte []) {
403 FLOW_TYPE_PORT, 0x43, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90
404 })
405 ),
406 TS(
407 FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED,
408 "Set zero bit in operand to one",
409 ((byte []) {
410 FLOW_TYPE_NEXT_HEADER, 0x89, 0x06
411 })
412 ),
413 TS(
414 FLOW_ST_VALID,
415 "Component of type number 13 (Label) is well-known in IPv6",
416 ((byte []) {
417 FLOW_TYPE_LABEL, 0x80, 0x55
418 })
419 ),
420 TS(
421 FLOW_ST_UNKNOWN_COMPONENT,
422 "Unknown component of type number 14",
423 ((byte []) {
424 FLOW_TYPE_LABEL, 0x80, 0x55,
425 14 /*something new*/, 0x80, 0x55,
426 })
427 )
428 };
429 #undef TS
430
431 for (uint tcase = 0; tcase < ARRAY_SIZE(tset); tcase++)
432 {
433 res = flow6_validate(tset[tcase].nlri, tset[tcase].size);
434 bt_assert_msg(res == tset[tcase].expect, "Assertion (%s == %s) %s", flow_validated_state_str(res), flow_validated_state_str(tset[tcase].expect), tset[tcase].description);
435 }
436
437 return 1;
438 }
439
440
441
442 /*
443 * Builder tests
444 */
445
446 static int
447 t_builder4(void)
448 {
449 resource_init();
450
451 struct flow_builder *fb = flow_builder_init(&root_pool);
452 linpool *lp = lp_new_default(&root_pool);
453
454 /* Expectation */
455
456 static byte nlri[] = {
457 25,
458 FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
459 FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
460 FLOW_TYPE_IP_PROTOCOL, 0x80, 0x06,
461 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
462 FLOW_TYPE_TCP_FLAGS, 0x80, 0x55
463 };
464
465 net_addr_flow4 *expect;
466 NET_ADDR_FLOW4_(expect, ip4_build(5, 6, 7, 0), 24, nlri);
467
468 /* Normal order */
469
470 net_addr_ip4 n1;
471 net_fill_ip4((net_addr *) &n1, ip4_build(5,6,7,0), 24);
472 flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
473 flow_builder4_add_pfx(fb, &n1);
474
475 net_addr_ip4 n2;
476 net_fill_ip4((net_addr *) &n2, ip4_build(10,11,12,13), 32);
477 flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
478 flow_builder4_add_pfx(fb, &n2);
479
480 flow_builder_set_type(fb, FLOW_TYPE_IP_PROTOCOL);
481 flow_builder_add_op_val(fb, 0, 0x06);
482
483 flow_builder_set_type(fb, FLOW_TYPE_PORT);
484 flow_builder_add_op_val(fb, 0x03, 0x89);
485 flow_builder_add_op_val(fb, 0x45, 0x8b);
486 flow_builder_add_op_val(fb, 0x01, 0x1f90);
487
488 /* Try put a component twice time */
489 flow_builder_set_type(fb, FLOW_TYPE_IP_PROTOCOL);
490 flow_builder_add_op_val(fb, 0, 0x06);
491
492 flow_builder_set_type(fb, FLOW_TYPE_TCP_FLAGS);
493 flow_builder_add_op_val(fb, 0, 0x55);
494
495 net_addr_flow4 *res = flow_builder4_finalize(fb, lp);
496
497 bt_assert(memcmp(res, expect, expect->length) == 0);
498
499 /* Reverse order */
500
501 flow_builder_clear(fb);
502
503 flow_builder_set_type(fb, FLOW_TYPE_TCP_FLAGS);
504 flow_builder_add_op_val(fb, 0, 0x55);
505
506 flow_builder_set_type(fb, FLOW_TYPE_PORT);
507 flow_builder_add_op_val(fb, 0x03, 0x89);
508 flow_builder_add_op_val(fb, 0x45, 0x8b);
509 flow_builder_add_op_val(fb, 0x01, 0x1f90);
510
511 flow_builder_set_type(fb, FLOW_TYPE_IP_PROTOCOL);
512 flow_builder_add_op_val(fb, 0, 0x06);
513
514 net_fill_ip4((net_addr *) &n2, ip4_build(10,11,12,13), 32);
515 flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
516 flow_builder4_add_pfx(fb, &n2);
517
518 net_fill_ip4((net_addr *) &n1, ip4_build(5,6,7,0), 24);
519 flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
520 flow_builder4_add_pfx(fb, &n1);
521
522 bt_assert(memcmp(res, expect, expect->length) == 0);
523
524 return 1;
525 }
526
527 static int
528 t_builder6(void)
529 {
530 net_addr_ip6 ip;
531
532 resource_init();
533 linpool *lp = lp_new_default(&root_pool);
534 struct flow_builder *fb = flow_builder_init(&root_pool);
535 fb->ipv6 = 1;
536
537 /* Expectation */
538
539 byte nlri[] = {
540 27,
541 FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
542 FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
543 FLOW_TYPE_NEXT_HEADER, 0x80, 0x06,
544 FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
545 FLOW_TYPE_LABEL, 0x80, 0x55,
546 };
547
548 net_addr_flow6 *expect;
549 NET_ADDR_FLOW6_(expect, ip6_build(0, 1, 0x12345678, 0x98000000), 103, nlri);
550
551 /* Normal order */
552
553 net_fill_ip6((net_addr *) &ip, ip6_build(0, 1, 0x12345678, 0x98000000), 103);
554 flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
555 flow_builder6_add_pfx(fb, &ip, 61);
556
557 /* Try put a component twice time */
558 net_fill_ip6((net_addr *) &ip, ip6_build(0, 1, 0x12345678, 0x98000000), 103);
559 flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
560 bt_assert(flow_builder6_add_pfx(fb, &ip, 61) == 0);
561
562 net_fill_ip6((net_addr *) &ip, ip6_build(0xc0000000,0,0,0), 8);
563 flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
564 flow_builder6_add_pfx(fb, &ip, 0);
565
566 flow_builder_set_type(fb, FLOW_TYPE_NEXT_HEADER);
567 flow_builder_add_op_val(fb, 0, 0x06);
568
569 flow_builder_set_type(fb, FLOW_TYPE_PORT);
570 flow_builder_add_op_val(fb, 0x03, 0x89);
571 flow_builder_add_op_val(fb, 0x45, 0x8b);
572 flow_builder_add_op_val(fb, 0x01, 0x1f90);
573
574 flow_builder_set_type(fb, FLOW_TYPE_LABEL);
575 flow_builder_add_op_val(fb, 0, 0x55);
576
577 net_addr_flow6 *res = flow_builder6_finalize(fb, lp);
578 bt_assert(memcmp(res, expect, expect->length) == 0);
579
580 /* Reverse order */
581
582 flow_builder_clear(fb);
583 fb->ipv6 = 1;
584
585 flow_builder_set_type(fb, FLOW_TYPE_LABEL);
586 flow_builder_add_op_val(fb, 0, 0x55);
587
588 flow_builder_set_type(fb, FLOW_TYPE_PORT);
589 flow_builder_add_op_val(fb, 0x03, 0x89);
590 flow_builder_add_op_val(fb, 0x45, 0x8b);
591 flow_builder_add_op_val(fb, 0x01, 0x1f90);
592
593 flow_builder_set_type(fb, FLOW_TYPE_NEXT_HEADER);
594 flow_builder_add_op_val(fb, 0, 0x06);
595
596 net_fill_ip6((net_addr *) &ip, ip6_build(0xc0000000,0,0,0), 8);
597 flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
598 flow_builder6_add_pfx(fb, &ip, 0);
599
600 net_fill_ip6((net_addr *) &ip, ip6_build(0, 1, 0x12345678, 0x98000000), 103);
601 flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
602 flow_builder6_add_pfx(fb, &ip, 61);
603
604 res = flow_builder6_finalize(fb, lp);
605 bt_assert(memcmp(res, expect, expect->length) == 0);
606
607 return 1;
608 }
609
610 static int
611 t_formatting4(void)
612 {
613 char b[1024];
614
615 byte nlri[] = {
616 0,
617 FLOW_TYPE_DST_PREFIX, 0x08, 10,
618 FLOW_TYPE_IP_PROTOCOL, 0x81, 23,
619 FLOW_TYPE_DST_PORT, 0x02, 24, 0x44, 30, 0x03, 40, 0x45, 50, 0x03, 60, 0x45, 70, 0x01, 80, 0xc3, 90,
620 FLOW_TYPE_SRC_PORT, 0x02, 24, 0x44, 0x1e, 0x01, 0x28, 0x01, 0x32, 0x03, 0x3c, 0x45, 0x46, 0x81, 0x50,
621 FLOW_TYPE_ICMP_TYPE, 0x81, 0x50,
622 FLOW_TYPE_ICMP_CODE, 0x81, 0x5a,
623 FLOW_TYPE_TCP_FLAGS, 0x01, 0x03, 0xc2, 0x0c,
624 FLOW_TYPE_PACKET_LENGTH, 0x03, 0, 0xd5, 0xff, 0xff,
625 FLOW_TYPE_DSCP, 0x81, 63,
626 FLOW_TYPE_FRAGMENT, 0x01, 0x01, 0x82, 0x02
627 };
628 *nlri = (u8) sizeof(nlri);
629
630 net_addr_flow4 *input;
631 NET_ADDR_FLOW4_(input, ip4_build(5, 6, 7, 0), 24, nlri);
632
633 const char *expect = "flow4 { dst 10.0.0.0/8; proto 23; dport > 24 && < 30 || 40..50,60..70,80 && >= 90; sport > 24 && < 30 || 40,50,60..70,80; icmp type 80; icmp code 90; tcp flags 0x3/0x3 && 0x0/0xc; length 0..65535; dscp 63; fragment dont_fragment || !is_fragment; }";
634
635 bt_assert(flow4_net_format(b, sizeof(b), input) == strlen(expect));
636 bt_debug(" expect: '%s',\n output: '%s'\n", expect, b);
637 bt_assert(strcmp(b, expect) == 0);
638
639 return 1;
640 }
641
642 static int
643 t_formatting6(void)
644 {
645 char b[1024];
646
647 byte nlri[] = {
648 0,
649 FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
650 FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
651 FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
652 FLOW_TYPE_PORT, 0x03, 20, 0x45, 40, 0x91, 0x01, 0x11,
653 FLOW_TYPE_LABEL, 0xa4, 0x00, 0x07, 0xa1, 0x20,
654 };
655 *nlri = (u8) sizeof(nlri);
656
657 net_addr_flow6 *input;
658 NET_ADDR_FLOW6_(input, ip6_build(0, 1, 0x12345678, 0x98000000), 103, nlri);
659
660 const char *expect = "flow6 { dst ::1:1234:5678:9800:0/103 offset 61; src c000::/8; next header 6; port 20..40,273; label < 500000; }";
661
662 bt_assert(flow6_net_format(b, sizeof(b), input) == strlen(expect));
663 bt_debug(" expect: '%s',\n output: '%s'\n", expect, b);
664 bt_assert(strcmp(b, expect) == 0);
665
666 return 1;
667 }
668
669 int
670 main(int argc, char *argv[])
671 {
672 bt_init(argc, argv);
673
674 bt_test_suite(t_read_length, "Testing get NLRI length");
675 bt_test_suite(t_write_length, "Testing set NLRI length");
676 bt_test_suite(t_first_part, "Searching first part in net_addr_flow");
677 bt_test_suite(t_iterators4, "Testing iterators (IPv4)");
678 bt_test_suite(t_iterators6, "Testing iterators (IPv6)");
679 bt_test_suite(t_accessors4, "Testing accessors (IPv4)");
680 bt_test_suite(t_accessors6, "Testing accessors (IPv6)");
681 bt_test_suite(t_validation4, "Testing validation (IPv4)");
682 bt_test_suite(t_validation6, "Testing validation (IPv6)");
683 bt_test_suite(t_builder4, "Inserting components into existing Flow Specification (IPv4)");
684 bt_test_suite(t_builder6, "Inserting components into existing Flow Specification (IPv6)");
685 bt_test_suite(t_formatting4, "Formatting Flow Specification (IPv4) into text representation");
686 bt_test_suite(t_formatting6, "Formatting Flow Specification (IPv6) into text representation");
687
688 return bt_exit_value();
689 }