Also adds a bunch of database stringify functions for debugging.
Could use some more testing, but I want to merge first.
fort_SOURCES += rtr/db/delta.c rtr/db/delta.h
fort_SOURCES += rtr/db/deltas_array.c rtr/db/deltas_array.h
fort_SOURCES += rtr/db/roa.c rtr/db/roa.h
-fort_SOURCES += rtr/db/vrp.h
+fort_SOURCES += rtr/db/vrp.c rtr/db/vrp.h
fort_SOURCES += rtr/db/vrps.c rtr/db/vrps.h
fort_SOURCES += slurm/db_slurm.c slurm/db_slurm.h
{
FILE *out = arg;
- switch (vrp->addr_fam) {
- case AF_INET:
- fprintf(out, "AS%u,%s/%u,%u\n", vrp->asn,
- addr2str4(&vrp->prefix.v4, addr_buf), vrp->prefix_length,
- vrp->max_prefix_length);
- break;
- case AF_INET6:
- fprintf(out, "AS%u,%s/%u,%u\n", vrp->asn,
- addr2str6(&vrp->prefix.v6, addr_buf), vrp->prefix_length,
- vrp->max_prefix_length);
- break;
- default:
+ if (vrp->addr_fam != AF_INET && vrp->addr_fam != AF_INET6)
pr_crit("Unknown family type");
- }
+
+ fprintf(out, "AS%u,%s/%u,%u\n", vrp->asn,
+ inet_ntop(vrp->addr_fam, &vrp->prefix, addr_buf, INET6_ADDRSTRLEN),
+ vrp->prefix_length, vrp->max_prefix_length);
return 0;
}
if (!json_out->first)
fprintf(out, ",");
- switch (vrp->addr_fam) {
- case AF_INET:
- fprintf(out,
- "\n { \"asn\" : \"AS%u\", \"prefix\" : \"%s/%u\", \"maxLength\" : %u }",
- vrp->asn,
- addr2str4(&vrp->prefix.v4, addr_buf),
- vrp->prefix_length,
- vrp->max_prefix_length);
- break;
- case AF_INET6:
- fprintf(out,
- "\n { \"asn\" : \"AS%u\", \"prefix\" : \"%s/%u\", \"maxLength\" : %u }",
- vrp->asn,
- addr2str6(&vrp->prefix.v6, addr_buf),
- vrp->prefix_length,
- vrp->max_prefix_length);
- break;
- default:
+ if (vrp->addr_fam != AF_INET && vrp->addr_fam != AF_INET6)
pr_crit("Unknown family type");
- }
+
+ fprintf(out,
+ "\n { \"asn\" : \"AS%u\", \"prefix\" : \"%s/%u\", \"maxLength\" : %u }",
+ vrp->asn,
+ inet_ntop(vrp->addr_fam, &vrp->prefix, addr_buf, INET6_ADDRSTRLEN),
+ vrp->prefix_length,
+ vrp->max_prefix_length);
json_out->first = false;
return 0;
return __foreach_rk(&deltas->rk.removes, cb_rk, arg, FLAG_WITHDRAWAL);
}
+
+void
+deltas_print(struct deltas *deltas)
+{
+ deltas_foreach(deltas, delta_vrp_print, delta_rk_print, NULL);
+}
bool deltas_is_empty(struct deltas *);
int deltas_foreach(struct deltas *, delta_vrp_foreach_cb,
delta_router_key_foreach_cb, void *);
+void deltas_print(struct deltas *);
#endif /* SRC_DELTA_H_ */
#ifndef SRC_RTR_DB_DELTAS_ARRAY_H_
#define SRC_RTR_DB_DELTAS_ARRAY_H_
+#include "serial.h"
#include "rtr/db/delta.h"
struct deltas_array;
--- /dev/null
+#include "rtr/db/vrp.h"
+
+#include <arpa/inet.h>
+
+static void
+print_flag(uint8_t flag)
+{
+ switch (flag) {
+ case FLAG_WITHDRAWAL:
+ printf("- DEL ");
+ break;
+ case FLAG_ANNOUNCEMENT:
+ printf("- ADD ");
+ break;
+ default:
+ printf("- (unknown)");
+ break;
+ }
+}
+
+int
+vrp_print(struct vrp const *roa, void *arg)
+{
+ char buffer[INET6_ADDRSTRLEN];
+ printf("- [ROA ASN:%u Prefix:%s/(%u-%u)]\n", roa->asn,
+ inet_ntop(roa->addr_fam, &roa->prefix, buffer, INET6_ADDRSTRLEN),
+ roa->prefix_length, roa->max_prefix_length);
+ return 0;
+}
+
+int
+delta_vrp_print(struct delta_vrp const *delta, void *arg)
+{
+ print_flag(delta->flags);
+ return vrp_print(&delta->vrp, arg);
+}
+
+int
+router_key_print(struct router_key const *rk, void *arg)
+{
+ printf("- [RK ASN:%u]\n", rk->as);
+ return 0;
+}
+
+int
+delta_rk_print(struct delta_router_key const *delta, void *arg)
+{
+ print_flag(delta->flags);
+ return router_key_print(&delta->router_key, arg);
+}
#include <netinet/in.h>
#include "address.h"
-#include "serial.h"
#include "object/router_key.h"
#define FLAG_WITHDRAWAL 0
#define VRP_EQ(a, b) \
(VRP_ASN_EQ(a, b) && VRP_PREFIX_EQ(a, b) && VRP_MAX_PREFIX_LEN_EQ(a, b))
+/*
+ * A ROA.
+ *
+ * I think it's called "VRP" ("Validated ROA Payload") because it was originally
+ * meant to represent an already validated ROA, and used exclusively by the RTR
+ * code. But it doesn't matter anymore.
+ */
struct vrp {
- uint32_t asn;
+ uint32_t asn;
union {
- struct in_addr v4;
- struct in6_addr v6;
+ struct in_addr v4;
+ struct in6_addr v6;
} prefix;
- uint8_t prefix_length;
- uint8_t max_prefix_length;
- uint8_t addr_fam;
+ uint8_t prefix_length;
+ uint8_t max_prefix_length;
+ uint8_t addr_fam;
};
struct delta_vrp {
};
struct delta_router_key {
- serial_t serial;
struct router_key router_key;
uint8_t flags;
};
typedef int (*delta_router_key_foreach_cb)(struct delta_router_key const *,
void *);
+int vrp_print(struct vrp const *, void *);
+int delta_vrp_print(struct delta_vrp const *, void *);
+int router_key_print(struct router_key const *, void *);
+int delta_rk_print(struct delta_router_key const *, void *);
+
#endif /* SRC_RTR_DB_VRP_H_ */
return state.v1_session_id;
return state.v0_session_id;
}
+
+void
+vrps_print_base(void)
+{
+ vrps_foreach_base(vrp_print, router_key_print, NULL);
+}
uint16_t get_current_session_id(uint8_t);
+void vrps_print_base(void);
+
#endif /* SRC_VRPS_H_ */
pr_op_info("%s ASN: %u", pad, prefix->vrp.asn);
if (prefix->data_flag & SLURM_PFX_FLAG_PREFIX) {
- switch (prefix->vrp.addr_fam) {
- case AF_INET:
- pr_op_info("%s Prefix: %s/%u", pad,
- addr2str4(&prefix->vrp.prefix.v4, addr_buf),
- prefix->vrp.prefix_length);
- break;
- case AF_INET6:
- pr_op_info("%s Prefix: %s/%u", pad,
- addr2str6(&prefix->vrp.prefix.v6, addr_buf),
- prefix->vrp.prefix_length);
- break;
- default:
- pr_crit("Unknown addr family type: %u",
- prefix->vrp.addr_fam);
- }
+ pr_op_info("%s Prefix: %s/%u", pad,
+ inet_ntop(prefix->vrp.addr_fam, &prefix->vrp.prefix,
+ addr_buf, INET6_ADDRSTRLEN), prefix->vrp.prefix_length);
}
if (prefix->data_flag & SLURM_PFX_FLAG_MAX_LENGTH)
{
return 10;
}
+
+unsigned int
+config_get_max_asn_per_pfx(void)
+{
+ return 10;
+}
+
+unsigned int
+config_get_max_pfx_per_asn(void)
+{
+ return 10;
+}
+
#include "log.c"
#include "impersonator.c"
#include "object/router_key.c"
+#include "rtr/db/vrp.c"
#include "rtr/db/delta.c"
#include "rtr/db/db_table.c"
prefix6.len = 120;
/* Duplicates should be transparently not re-added. */
-
ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 32));
- /* Change the max prefix length slightly */
+ /* Change the max prefix length (counts as duplicate) */
prefix4.len = 24;
ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 30));
ck_assert_int_eq(0, rtrhandler_handle_roa_v4(table, 10, &prefix4, 30));
}
END_TEST
-START_TEST(test_merge)
-{
- struct ipv4_prefix prefix4;
- struct ipv6_prefix prefix6;
- struct db_table *left, *right, *merged;
- array_index i;
- int left_count, right_count, total_merged;
-
- left = db_table_create();
- ck_assert_ptr_ne(NULL, left);
- right = db_table_create();
- ck_assert_ptr_ne(NULL, right);
- merged = db_table_create();
- ck_assert_ptr_ne(NULL, merged);
-
- prefix4.addr.s_addr = ADDR1;
- prefix4.len = 24;
- in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
- prefix6.len = 120;
-
- left_count = 0;
- right_count = 0;
- total_merged = 0;
-
- /** Add the same roas on both tables*/
- ck_assert_int_eq(0, rtrhandler_handle_roa_v4(left, 10, &prefix4, 32));
- left_count++;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v4(right, 10, &prefix4, 32));
- right_count++;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v4(left, 11, &prefix4, 32));
- left_count++;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v4(right, 11, &prefix4, 32));
- right_count++;
-
- /** And add distinct roas on each table */
- prefix4.addr.s_addr = ADDR2;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v4(left, 10, &prefix4, 32));
- left_count++;
-
- prefix4.addr.s_addr = ADDR1;
- prefix4.len = 25;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v4(right, 10, &prefix4, 32));
- right_count++;
-
- prefix4.len = 24;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v4(left, 10, &prefix4, 30));
- left_count++;
-
- /* IPv6 */
- ck_assert_int_eq(0, rtrhandler_handle_roa_v6(right, 10, &prefix6, 128));
- right_count++;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v6(left, 11, &prefix6, 128));
- left_count++;
-
- in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 2);
- ck_assert_int_eq(0, rtrhandler_handle_roa_v6(right, 10, &prefix6, 128));
- right_count++;
-
- in6_addr_init(&prefix6.addr, 0x20010DB8u, 0, 0, 1);
- prefix6.len = 121;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v6(left, 10, &prefix6, 128));
- left_count++;
-
- prefix6.len = 120;
- ck_assert_int_eq(0, rtrhandler_handle_roa_v6(right, 10, &prefix6, 127));
- right_count++;
-
- /** Do the merge */
- ck_assert_int_eq(0, db_table_merge(merged, left));
- ck_assert_int_eq(0, db_table_merge(merged, right));
-
- /**
- * Must have:
- * count(left) + count(right) - 2 (duplicated elements)
- */
- total_merged = left_count + right_count - 2;
- ck_assert_int_eq(total_merged, TOTAL_ROAS);
-
- /* Check table contents and that merged table has new memory refs */
- db_table_destroy(left);
- db_table_destroy(right);
-
- memset(roas_found, 0, sizeof(roas_found));
- total_found = 0;
- ck_assert_int_eq(0, db_table_foreach_roa(merged, foreach_cb, NULL));
- ck_assert_int_eq(TOTAL_ROAS, total_found);
- for (i = 0; i < TOTAL_ROAS; i++)
- ck_assert_int_eq(true, roas_found[i]);
-
- db_table_destroy(merged);
-}
-END_TEST
-
Suite *pdu_suite(void)
{
Suite *suite;
- TCase *core, *merge;
+ TCase *core;
core = tcase_create("Core");
tcase_add_test(core, test_basic);
- merge = tcase_create("Merge");
- tcase_add_test(core, test_merge);
-
suite = suite_create("DB Table");
suite_add_tcase(suite, core);
- suite_add_tcase(suite, merge);
return suite;
}
#include "log.c"
#include "impersonator.c"
+#include "rtr/db/vrp.c"
#include "rtr/db/delta.c"
#include "rtr/db/deltas_array.c"
}
int
-__handle_roa_v6(uint32_t as, struct ipv6_prefix const * prefix,
+__handle_roa_v6(uint32_t as, struct ipv6_prefix const *prefix,
uint8_t max_length, void *arg)
{
return rtrhandler_handle_roa_v6(arg, as, prefix, max_length);
#include "output_printer.c"
#include "serial.c"
#include "object/router_key.c"
+#include "rtr/db/vrp.c"
#include "rtr/db/delta.c"
#include "rtr/db/deltas_array.c"
#include "rtr/db/db_table.c"
}
static void
-create_deltas_1to2(serial_t *serial, bool *changed, bool *iterated_entries)
+create_deltas_1to2(void)
{
+ serial_t serial;
+ bool changed;
+ bool iterated_entries[12];
+
ck_assert_int_eq(0, vrps_init());
/* First validation not yet performed: Tell routers to wait */
- ck_assert_int_eq(-EAGAIN, get_last_serial_number(serial));
+ ck_assert_int_eq(-EAGAIN, get_last_serial_number(&serial));
ck_assert_int_eq(-EAGAIN, vrps_foreach_base(vrp_fail, rk_fail,
iterated_entries));
- ck_assert_int_eq(-EAGAIN, vrps_foreach_delta_since(0, serial, dvrp_fail,
- drk_fail, NULL));
+ ck_assert_int_eq(-EAGAIN, vrps_foreach_delta_since(0, &serial,
+ dvrp_fail, drk_fail, NULL));
/* First validation: One tree, no deltas */
- ck_assert_int_eq(0, vrps_update(changed));
+ ck_assert_int_eq(0, vrps_update(&changed));
+ ck_assert(changed);
check_serial(1);
check_base(1, iteration1_base);
check_deltas(1, 1, deltas_1to1);
/* Second validation: One tree, added deltas */
- ck_assert_int_eq(0, vrps_update(changed));
+ ck_assert_int_eq(0, vrps_update(&changed));
+
+ ck_assert(changed);
check_serial(2);
check_base(2, iteration2_base);
check_deltas(1, 2, deltas_1to2);
START_TEST(test_basic)
{
- serial_t serial;
bool changed;
- bool iterated_entries[12];
deltas_lifetime = 5;
- create_deltas_1to2(&serial, &changed, iterated_entries);
+ create_deltas_1to2();
/* Third validation: One tree, removed deltas */
ck_assert_int_eq(0, vrps_update(&changed));
+ ck_assert(changed);
check_serial(3);
check_base(3, iteration3_base);
check_deltas(1, 3, deltas_1to3);
START_TEST(test_delta_forget)
{
- serial_t serial;
bool changed;
- bool iterated_entries[12];
deltas_lifetime = 1;
- create_deltas_1to2(&serial, &changed, iterated_entries);
+ create_deltas_1to2();
/* Third validation: One tree, removed deltas and delta 1 removed */
ck_assert_int_eq(0, vrps_update(&changed));
+ ck_assert(changed);
check_serial(3);
check_base(3, iteration3_base);
check_no_deltas(1);
START_TEST(test_delta_ovrd)
{
- serial_t serial;
bool changed;
- bool iterated_entries[12];
deltas_lifetime = 3;
- create_deltas_1to2(&serial, &changed, iterated_entries);
+ create_deltas_1to2();
/* Third validation: One tree, removed deltas */
ck_assert_int_eq(0, vrps_update(&changed));
+ ck_assert(changed);
check_serial(3);
check_base(3, iteration3_base);
check_deltas(1, 3, deltas_1to3);
/* Fourth validation with deltas that override each other */
ck_assert_int_eq(0, vrps_update(&changed));
+ ck_assert(changed);
check_serial(4);
check_base(4, iteration4_base);
check_deltas(1, 4, deltas_1to4);
#include "rtr/primitive_reader.c"
#include "rtr/primitive_writer.c"
#include "rtr/err_pdu.c"
+#include "rtr/db/vrp.c"
#include "rtr/db/delta.c"
#include "rtr/db/deltas_array.c"
#include "rtr/db/db_table.c"