mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-10 13:18:42 +00:00
94eb0858c2
There is a simple universal IO loop, taking care of events, timers and sockets. Primarily, one instance of a protocol should use exactly one IO loop to do all its work, as is now done in BFD. Contrary to previous versions, the loop is now launched and cleaned by the nest/proto.c code, allowing for a protocol to just request its own loop by setting the loop's lock order in config higher than the_bird. It is not supported nor checked if any protocol changed the requested lock order in reconfigure. No protocol should do it at all.
693 lines
19 KiB
C
693 lines
19 KiB
C
/*
|
|
* BIRD Library -- Flow specification (RFC 5575) Tests
|
|
*
|
|
* (c) 2016 CZ.NIC z.s.p.o.
|
|
*
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
*/
|
|
|
|
#include "test/birdtest.h"
|
|
#include "lib/flowspec.h"
|
|
|
|
#define NET_ADDR_FLOW4_(what,prefix,pxlen,data_) \
|
|
do \
|
|
{ \
|
|
what = alloca(sizeof(net_addr_flow4) + 128); \
|
|
*what = NET_ADDR_FLOW4(prefix, pxlen, sizeof(data_)); \
|
|
memcpy(what->data, &(data_), sizeof(data_)); \
|
|
} while(0)
|
|
|
|
#define NET_ADDR_FLOW6_(what,prefix,pxlen,data_) \
|
|
do \
|
|
{ \
|
|
what = alloca(sizeof(net_addr_flow6) + 128); \
|
|
*what = NET_ADDR_FLOW6(prefix, pxlen, sizeof(data_)); \
|
|
memcpy(what->data, &(data_), sizeof(data_)); \
|
|
} while(0)
|
|
|
|
static int
|
|
t_read_length(void)
|
|
{
|
|
byte data[] = { 0xcc, 0xcc, 0xcc };
|
|
|
|
for (uint expect = 0; expect < 0xf0; expect++)
|
|
{
|
|
*data = expect;
|
|
uint get = flow_read_length(data);
|
|
bt_assert_msg(get == expect, "Testing get length 0x%02x (get 0x%02x)", expect, get);
|
|
}
|
|
|
|
for (uint expect = 0; expect <= 0xfff; expect++)
|
|
{
|
|
put_u16(data, expect | 0xf000);
|
|
uint get = flow_read_length(data);
|
|
bt_assert_msg(get == expect, "Testing get length 0x%03x (get 0x%03x)", expect, get);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_write_length(void)
|
|
{
|
|
byte data[] = { 0xcc, 0xcc, 0xcc };
|
|
|
|
for (uint expect = 0; expect <= 0xfff; expect++)
|
|
{
|
|
uint offset = flow_write_length(data, expect);
|
|
|
|
uint set = (expect < 0xf0) ? *data : (get_u16(data) & 0x0fff);
|
|
bt_assert_msg(set == expect, "Testing set length 0x%03x (set 0x%03x)", expect, set);
|
|
bt_assert(offset == (expect < 0xf0 ? 1 : 2));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_first_part(void)
|
|
{
|
|
net_addr_flow4 *f;
|
|
NET_ADDR_FLOW4_(f, ip4_build(10,0,0,1), 24, ((byte[]) { 0x00, 0x00, 0xab }));
|
|
|
|
const byte *under240 = &f->data[1];
|
|
const byte *above240 = &f->data[2];
|
|
|
|
/* Case 0x00 0x00 */
|
|
bt_assert(flow4_first_part(f) == NULL);
|
|
|
|
/* Case 0x01 0x00 */
|
|
f->data[0] = 0x01;
|
|
bt_assert(flow4_first_part(f) == under240);
|
|
|
|
/* Case 0xef 0x00 */
|
|
f->data[0] = 0xef;
|
|
bt_assert(flow4_first_part(f) == under240);
|
|
|
|
/* Case 0xf0 0x00 */
|
|
f->data[0] = 0xf0;
|
|
bt_assert(flow4_first_part(f) == NULL);
|
|
|
|
/* Case 0xf0 0x01 */
|
|
f->data[1] = 0x01;
|
|
bt_assert(flow4_first_part(f) == above240);
|
|
|
|
/* Case 0xff 0xff */
|
|
f->data[0] = 0xff;
|
|
f->data[1] = 0xff;
|
|
bt_assert(flow4_first_part(f) == above240);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_iterators4(void)
|
|
{
|
|
net_addr_flow4 *f;
|
|
NET_ADDR_FLOW4_(f, ip4_build(5,6,7,0), 24, ((byte[]) {
|
|
25, /* Length */
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
|
|
FLOW_TYPE_IP_PROTOCOL, 0x81, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
|
|
}));
|
|
|
|
const byte *start = f->data;
|
|
const byte *p1_dst_pfx = &f->data[1];
|
|
const byte *p2_src_pfx = &f->data[6];
|
|
const byte *p3_ip_proto = &f->data[12];
|
|
const byte *p4_port = &f->data[15];
|
|
const byte *p5_tcp_flags = &f->data[23];
|
|
const byte *end = &f->data[25];
|
|
|
|
bt_assert(flow_read_length(f->data) == (end-start));
|
|
bt_assert(flow4_first_part(f) == p1_dst_pfx);
|
|
|
|
bt_assert(flow4_next_part(p1_dst_pfx, end) == p2_src_pfx);
|
|
bt_assert(flow4_next_part(p2_src_pfx, end) == p3_ip_proto);
|
|
bt_assert(flow4_next_part(p3_ip_proto, end) == p4_port);
|
|
bt_assert(flow4_next_part(p4_port, end) == p5_tcp_flags);
|
|
bt_assert(flow4_next_part(p5_tcp_flags, end) == NULL);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_iterators6(void)
|
|
{
|
|
net_addr_flow6 *f;
|
|
NET_ADDR_FLOW6_(f, ip6_build(0,0,0x12345678,0x9a000000), 0x68, ((byte[]) {
|
|
26, /* Length */
|
|
FLOW_TYPE_DST_PREFIX, 0x68, 0x40, 0x12, 0x34, 0x56, 0x78, 0x9a,
|
|
FLOW_TYPE_SRC_PREFIX, 0x08, 0x0, 0xc0,
|
|
FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_LABEL, 0x80, 0x55,
|
|
}));
|
|
|
|
const byte *start = f->data;
|
|
const byte *p1_dst_pfx = &f->data[1];
|
|
const byte *p2_src_pfx = &f->data[9];
|
|
const byte *p3_next_header = &f->data[13];
|
|
const byte *p4_port = &f->data[16];
|
|
const byte *p5_label = &f->data[24];
|
|
const byte *end = &f->data[26];
|
|
|
|
bt_assert(flow_read_length(f->data) == (end-start));
|
|
bt_assert(flow6_first_part(f) == p1_dst_pfx);
|
|
|
|
bt_assert(flow6_next_part(p1_dst_pfx, end) == p2_src_pfx);
|
|
bt_assert(flow6_next_part(p2_src_pfx, end) == p3_next_header);
|
|
bt_assert(flow6_next_part(p3_next_header, end) == p4_port);
|
|
bt_assert(flow6_next_part(p4_port, end) == p5_label);
|
|
bt_assert(flow6_next_part(p5_label, end) == NULL);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_accessors4(void)
|
|
{
|
|
net_addr_flow4 *f;
|
|
NET_ADDR_FLOW4_(f, ip4_build(5,6,7,0), 24, ((byte[]) {
|
|
25, /* Length */
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
|
|
FLOW_TYPE_IP_PROTOCOL, 0x81, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
|
|
}));
|
|
|
|
const byte *p1_dst_px = &f->data[1];
|
|
const ip4_addr p1_dst_addr = ip4_build(5,6,7,0);
|
|
|
|
const byte *p2_src_px = &f->data[6];
|
|
const ip4_addr p2_src_addr = ip4_build(10,11,12,13);
|
|
|
|
bt_assert(ip4_equal(flow_read_ip4_part(p1_dst_px), p1_dst_addr));
|
|
bt_assert(ip4_equal(flow_read_ip4_part(p2_src_px), p2_src_addr));
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_accessors6(void)
|
|
{
|
|
net_addr_flow6 *f;
|
|
NET_ADDR_FLOW6_(f, ip6_build(0,0,0x12345678,0x9a000000), 0x68, ((byte[]) {
|
|
26, /* Length */
|
|
FLOW_TYPE_DST_PREFIX, 0x68, 0x40, 0x12, 0x34, 0x56, 0x78, 0x9a,
|
|
FLOW_TYPE_SRC_PREFIX, 0x08, 0x0, 0xc0,
|
|
FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_LABEL, 0x80, 0x55,
|
|
}));
|
|
|
|
const byte *p1_dst_px = &f->data[1];
|
|
const ip6_addr p1_dst_addr = ip6_build(0,0,0x12345678,0x9a000000);
|
|
|
|
const byte *p2_src_px = &f->data[9];
|
|
const ip6_addr p2_src_addr = ip6_build(0xc0000000, 0, 0, 0);
|
|
|
|
bt_assert(ip6_equal(flow_read_ip6_part(p1_dst_px), p1_dst_addr));
|
|
bt_assert(ip6_equal(flow_read_ip6_part(p2_src_px), p2_src_addr));
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_validation4(void)
|
|
{
|
|
enum flow_validated_state res;
|
|
|
|
byte nlri1[] = {
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
|
|
FLOW_TYPE_IP_PROTOCOL, 0x81, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
|
|
};
|
|
|
|
/* Empty NLRI */
|
|
res = flow4_validate(nlri1, 0);
|
|
bt_assert(res == FLOW_ST_VALID);
|
|
|
|
/* Valid / Not Complete testing */
|
|
uint valid_sizes[] = {5, 11, 14, 22, 25, 0};
|
|
uint valid_idx = 0;
|
|
for (uint size = 1; size <= sizeof(nlri1); size++)
|
|
{
|
|
res = flow4_validate(nlri1, size);
|
|
bt_debug("size %u, result: %s\n", size, flow_validated_state_str(res));
|
|
if (size == valid_sizes[valid_idx])
|
|
{
|
|
valid_idx++;
|
|
bt_assert(res == FLOW_ST_VALID);
|
|
}
|
|
else
|
|
{
|
|
bt_assert(res == FLOW_ST_NOT_COMPLETE);
|
|
}
|
|
}
|
|
|
|
/* Misc err tests */
|
|
|
|
struct tset {
|
|
enum flow_validated_state expect;
|
|
char *description;
|
|
u16 size;
|
|
byte *nlri;
|
|
};
|
|
|
|
#define TS(type, msg, data) ((struct tset) {type, msg, sizeof(data), (data)})
|
|
struct tset tset[] = {
|
|
TS(
|
|
FLOW_ST_EXCEED_MAX_PREFIX_LENGTH,
|
|
"33-length IPv4 prefix",
|
|
((byte []) {
|
|
FLOW_TYPE_DST_PREFIX, 33, 5, 6, 7, 8, 9
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_BAD_TYPE_ORDER,
|
|
"Bad flowspec component type order",
|
|
((byte []) {
|
|
FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_BAD_TYPE_ORDER,
|
|
"Doubled destination prefix component",
|
|
((byte []) {
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_AND_BIT_SHOULD_BE_UNSET,
|
|
"The first numeric operator has set the AND bit",
|
|
((byte []) {
|
|
FLOW_TYPE_PORT, 0x43, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED,
|
|
"Set zero bit in operand to one",
|
|
((byte []) {
|
|
FLOW_TYPE_IP_PROTOCOL, 0x89, 0x06,
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_UNKNOWN_COMPONENT,
|
|
"Unknown component of type number 13",
|
|
((byte []) {
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
FLOW_TYPE_TCP_FLAGS, 0x80, 0x55,
|
|
13 /*something new*/, 0x80, 0x55,
|
|
})
|
|
),
|
|
};
|
|
#undef TS
|
|
|
|
for (uint tcase = 0; tcase < ARRAY_SIZE(tset); tcase++)
|
|
{
|
|
res = flow4_validate(tset[tcase].nlri, tset[tcase].size);
|
|
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);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_validation6(void)
|
|
{
|
|
enum flow_validated_state res;
|
|
|
|
byte nlri1[] = {
|
|
FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
|
|
FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
|
|
FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_LABEL, 0x80, 0x55,
|
|
};
|
|
|
|
/* Isn't included destination prefix */
|
|
res = flow6_validate(nlri1, 0);
|
|
bt_assert(res == FLOW_ST_VALID);
|
|
|
|
/* Valid / Not Complete testing */
|
|
uint valid_sizes[] = {0, 9, 13, 16, 24, 27, 0};
|
|
uint valid_idx = 0;
|
|
for (uint size = 0; size <= sizeof(nlri1); size++)
|
|
{
|
|
res = flow6_validate(nlri1, size);
|
|
bt_debug("size %u, result: %s\n", size, flow_validated_state_str(res));
|
|
if (size == valid_sizes[valid_idx])
|
|
{
|
|
valid_idx++;
|
|
bt_assert(res == FLOW_ST_VALID);
|
|
}
|
|
else
|
|
{
|
|
bt_assert(res == FLOW_ST_NOT_COMPLETE);
|
|
}
|
|
}
|
|
|
|
/* Misc err tests */
|
|
|
|
struct tset {
|
|
enum flow_validated_state expect;
|
|
char *description;
|
|
u16 size;
|
|
byte *nlri;
|
|
};
|
|
|
|
#define TS(type, msg, data) ((struct tset) {type, msg, sizeof(data), (data)})
|
|
struct tset tset[] = {
|
|
TS(
|
|
FLOW_ST_EXCEED_MAX_PREFIX_LENGTH,
|
|
"129-length IPv6 prefix",
|
|
((byte []) {
|
|
FLOW_TYPE_DST_PREFIX, 129, 64, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_EXCEED_MAX_PREFIX_OFFSET,
|
|
"Prefix offset is higher than prefix length",
|
|
((byte []) {
|
|
FLOW_TYPE_DST_PREFIX, 48, 64, 0x40, 0x12, 0x34
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_BAD_TYPE_ORDER,
|
|
"Bad flowspec component type order",
|
|
((byte []) {
|
|
FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
|
|
FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_BAD_TYPE_ORDER,
|
|
"Doubled destination prefix component",
|
|
((byte []) {
|
|
FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
|
|
FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_AND_BIT_SHOULD_BE_UNSET,
|
|
"The first numeric operator has set the AND bit",
|
|
((byte []) {
|
|
FLOW_TYPE_PORT, 0x43, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_ZERO_BIT_SHOULD_BE_UNSED,
|
|
"Set zero bit in operand to one",
|
|
((byte []) {
|
|
FLOW_TYPE_NEXT_HEADER, 0x89, 0x06
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_VALID,
|
|
"Component of type number 13 (Label) is well-known in IPv6",
|
|
((byte []) {
|
|
FLOW_TYPE_LABEL, 0x80, 0x55
|
|
})
|
|
),
|
|
TS(
|
|
FLOW_ST_UNKNOWN_COMPONENT,
|
|
"Unknown component of type number 14",
|
|
((byte []) {
|
|
FLOW_TYPE_LABEL, 0x80, 0x55,
|
|
14 /*something new*/, 0x80, 0x55,
|
|
})
|
|
)
|
|
};
|
|
#undef TS
|
|
|
|
for (uint tcase = 0; tcase < ARRAY_SIZE(tset); tcase++)
|
|
{
|
|
res = flow6_validate(tset[tcase].nlri, tset[tcase].size);
|
|
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);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* Builder tests
|
|
*/
|
|
|
|
static int
|
|
t_builder4(void)
|
|
{
|
|
resource_init();
|
|
|
|
struct flow_builder *fb = flow_builder_init(&root_pool);
|
|
linpool *lp = lp_new_default(&root_pool);
|
|
|
|
/* Expectation */
|
|
|
|
static byte nlri[] = {
|
|
25,
|
|
FLOW_TYPE_DST_PREFIX, 24, 5, 6, 7,
|
|
FLOW_TYPE_SRC_PREFIX, 32, 10, 11, 12, 13,
|
|
FLOW_TYPE_IP_PROTOCOL, 0x80, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_TCP_FLAGS, 0x80, 0x55
|
|
};
|
|
|
|
net_addr_flow4 *expect;
|
|
NET_ADDR_FLOW4_(expect, ip4_build(5, 6, 7, 0), 24, nlri);
|
|
|
|
/* Normal order */
|
|
|
|
net_addr_ip4 n1;
|
|
net_fill_ip4((net_addr *) &n1, ip4_build(5,6,7,0), 24);
|
|
flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
|
|
flow_builder4_add_pfx(fb, &n1);
|
|
|
|
net_addr_ip4 n2;
|
|
net_fill_ip4((net_addr *) &n2, ip4_build(10,11,12,13), 32);
|
|
flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
|
|
flow_builder4_add_pfx(fb, &n2);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_IP_PROTOCOL);
|
|
flow_builder_add_op_val(fb, 0, 0x06);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_PORT);
|
|
flow_builder_add_op_val(fb, 0x03, 0x89);
|
|
flow_builder_add_op_val(fb, 0x45, 0x8b);
|
|
flow_builder_add_op_val(fb, 0x01, 0x1f90);
|
|
|
|
/* Try put a component twice time */
|
|
flow_builder_set_type(fb, FLOW_TYPE_IP_PROTOCOL);
|
|
flow_builder_add_op_val(fb, 0, 0x06);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_TCP_FLAGS);
|
|
flow_builder_add_op_val(fb, 0, 0x55);
|
|
|
|
net_addr_flow4 *res = flow_builder4_finalize(fb, lp);
|
|
|
|
bt_assert(memcmp(res, expect, expect->length) == 0);
|
|
|
|
/* Reverse order */
|
|
|
|
flow_builder_clear(fb);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_TCP_FLAGS);
|
|
flow_builder_add_op_val(fb, 0, 0x55);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_PORT);
|
|
flow_builder_add_op_val(fb, 0x03, 0x89);
|
|
flow_builder_add_op_val(fb, 0x45, 0x8b);
|
|
flow_builder_add_op_val(fb, 0x01, 0x1f90);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_IP_PROTOCOL);
|
|
flow_builder_add_op_val(fb, 0, 0x06);
|
|
|
|
net_fill_ip4((net_addr *) &n2, ip4_build(10,11,12,13), 32);
|
|
flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
|
|
flow_builder4_add_pfx(fb, &n2);
|
|
|
|
net_fill_ip4((net_addr *) &n1, ip4_build(5,6,7,0), 24);
|
|
flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
|
|
flow_builder4_add_pfx(fb, &n1);
|
|
|
|
bt_assert(memcmp(res, expect, expect->length) == 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_builder6(void)
|
|
{
|
|
net_addr_ip6 ip;
|
|
|
|
resource_init();
|
|
linpool *lp = lp_new_default(&root_pool);
|
|
struct flow_builder *fb = flow_builder_init(&root_pool);
|
|
fb->ipv6 = 1;
|
|
|
|
/* Expectation */
|
|
|
|
byte nlri[] = {
|
|
27,
|
|
FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
|
|
FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
|
|
FLOW_TYPE_NEXT_HEADER, 0x80, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 0x89, 0x45, 0x8b, 0x91, 0x1f, 0x90,
|
|
FLOW_TYPE_LABEL, 0x80, 0x55,
|
|
};
|
|
|
|
net_addr_flow6 *expect;
|
|
NET_ADDR_FLOW6_(expect, ip6_build(0, 1, 0x12345678, 0x98000000), 103, nlri);
|
|
|
|
/* Normal order */
|
|
|
|
net_fill_ip6((net_addr *) &ip, ip6_build(0, 1, 0x12345678, 0x98000000), 103);
|
|
flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
|
|
flow_builder6_add_pfx(fb, &ip, 61);
|
|
|
|
/* Try put a component twice time */
|
|
net_fill_ip6((net_addr *) &ip, ip6_build(0, 1, 0x12345678, 0x98000000), 103);
|
|
flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
|
|
bt_assert(flow_builder6_add_pfx(fb, &ip, 61) == 0);
|
|
|
|
net_fill_ip6((net_addr *) &ip, ip6_build(0xc0000000,0,0,0), 8);
|
|
flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
|
|
flow_builder6_add_pfx(fb, &ip, 0);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_NEXT_HEADER);
|
|
flow_builder_add_op_val(fb, 0, 0x06);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_PORT);
|
|
flow_builder_add_op_val(fb, 0x03, 0x89);
|
|
flow_builder_add_op_val(fb, 0x45, 0x8b);
|
|
flow_builder_add_op_val(fb, 0x01, 0x1f90);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_LABEL);
|
|
flow_builder_add_op_val(fb, 0, 0x55);
|
|
|
|
net_addr_flow6 *res = flow_builder6_finalize(fb, lp);
|
|
bt_assert(memcmp(res, expect, expect->length) == 0);
|
|
|
|
/* Reverse order */
|
|
|
|
flow_builder_clear(fb);
|
|
fb->ipv6 = 1;
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_LABEL);
|
|
flow_builder_add_op_val(fb, 0, 0x55);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_PORT);
|
|
flow_builder_add_op_val(fb, 0x03, 0x89);
|
|
flow_builder_add_op_val(fb, 0x45, 0x8b);
|
|
flow_builder_add_op_val(fb, 0x01, 0x1f90);
|
|
|
|
flow_builder_set_type(fb, FLOW_TYPE_NEXT_HEADER);
|
|
flow_builder_add_op_val(fb, 0, 0x06);
|
|
|
|
net_fill_ip6((net_addr *) &ip, ip6_build(0xc0000000,0,0,0), 8);
|
|
flow_builder_set_type(fb, FLOW_TYPE_SRC_PREFIX);
|
|
flow_builder6_add_pfx(fb, &ip, 0);
|
|
|
|
net_fill_ip6((net_addr *) &ip, ip6_build(0, 1, 0x12345678, 0x98000000), 103);
|
|
flow_builder_set_type(fb, FLOW_TYPE_DST_PREFIX);
|
|
flow_builder6_add_pfx(fb, &ip, 61);
|
|
|
|
res = flow_builder6_finalize(fb, lp);
|
|
bt_assert(memcmp(res, expect, expect->length) == 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_formatting4(void)
|
|
{
|
|
char b[1024];
|
|
|
|
byte nlri[] = {
|
|
0,
|
|
FLOW_TYPE_DST_PREFIX, 0x08, 10,
|
|
FLOW_TYPE_IP_PROTOCOL, 0x81, 23,
|
|
FLOW_TYPE_DST_PORT, 0x02, 24, 0x44, 30, 0x03, 40, 0x45, 50, 0x03, 60, 0x45, 70, 0x01, 80, 0xc3, 90,
|
|
FLOW_TYPE_SRC_PORT, 0x02, 24, 0x44, 0x1e, 0x01, 0x28, 0x01, 0x32, 0x03, 0x3c, 0x45, 0x46, 0x81, 0x50,
|
|
FLOW_TYPE_ICMP_TYPE, 0x81, 0x50,
|
|
FLOW_TYPE_ICMP_CODE, 0x81, 0x5a,
|
|
FLOW_TYPE_TCP_FLAGS, 0x01, 0x03, 0xc2, 0x0c,
|
|
FLOW_TYPE_PACKET_LENGTH, 0x03, 0, 0xd5, 0xff, 0xff,
|
|
FLOW_TYPE_DSCP, 0x81, 63,
|
|
FLOW_TYPE_FRAGMENT, 0x01, 0x01, 0x82, 0x02
|
|
};
|
|
*nlri = (u8) sizeof(nlri);
|
|
|
|
net_addr_flow4 *input;
|
|
NET_ADDR_FLOW4_(input, ip4_build(5, 6, 7, 0), 24, nlri);
|
|
|
|
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; }";
|
|
|
|
bt_assert(flow4_net_format(b, sizeof(b), input) == strlen(expect));
|
|
bt_debug(" expect: '%s',\n output: '%s'\n", expect, b);
|
|
bt_assert(strcmp(b, expect) == 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
static int
|
|
t_formatting6(void)
|
|
{
|
|
char b[1024];
|
|
|
|
byte nlri[] = {
|
|
0,
|
|
FLOW_TYPE_DST_PREFIX, 103, 61, 0x01, 0x12, 0x34, 0x56, 0x78, 0x98,
|
|
FLOW_TYPE_SRC_PREFIX, 8, 0, 0xc0,
|
|
FLOW_TYPE_NEXT_HEADER, 0x81, 0x06,
|
|
FLOW_TYPE_PORT, 0x03, 20, 0x45, 40, 0x91, 0x01, 0x11,
|
|
FLOW_TYPE_LABEL, 0xa4, 0x00, 0x07, 0xa1, 0x20,
|
|
};
|
|
*nlri = (u8) sizeof(nlri);
|
|
|
|
net_addr_flow6 *input;
|
|
NET_ADDR_FLOW6_(input, ip6_build(0, 1, 0x12345678, 0x98000000), 103, nlri);
|
|
|
|
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; }";
|
|
|
|
bt_assert(flow6_net_format(b, sizeof(b), input) == strlen(expect));
|
|
bt_debug(" expect: '%s',\n output: '%s'\n", expect, b);
|
|
bt_assert(strcmp(b, expect) == 0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void resource_sys_init(void);
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
bt_init(argc, argv);
|
|
resource_sys_init();
|
|
|
|
bt_test_suite(t_read_length, "Testing get NLRI length");
|
|
bt_test_suite(t_write_length, "Testing set NLRI length");
|
|
bt_test_suite(t_first_part, "Searching first part in net_addr_flow");
|
|
bt_test_suite(t_iterators4, "Testing iterators (IPv4)");
|
|
bt_test_suite(t_iterators6, "Testing iterators (IPv6)");
|
|
bt_test_suite(t_accessors4, "Testing accessors (IPv4)");
|
|
bt_test_suite(t_accessors6, "Testing accessors (IPv6)");
|
|
bt_test_suite(t_validation4, "Testing validation (IPv4)");
|
|
bt_test_suite(t_validation6, "Testing validation (IPv6)");
|
|
bt_test_suite(t_builder4, "Inserting components into existing Flow Specification (IPv4)");
|
|
bt_test_suite(t_builder6, "Inserting components into existing Flow Specification (IPv6)");
|
|
bt_test_suite(t_formatting4, "Formatting Flow Specification (IPv4) into text representation");
|
|
bt_test_suite(t_formatting6, "Formatting Flow Specification (IPv6) into text representation");
|
|
|
|
return bt_exit_value();
|
|
}
|