mirror of
https://gitlab.com/d3tn/ud3tn.git
synced 2026-08-13 12:33:27 +02:00
The FIB fulfils two purposes: 1) map node IDs to next-hop CLA addresses and 2) store the current status of a link associated with a given CLA address. Signed-off-by: Felix Walter <felix.walter@d3tn.com>
320 lines
10 KiB
C
320 lines
10 KiB
C
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
#include "ud3tn/fib.h"
|
|
|
|
#include "testud3tn_unity.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <string.h>
|
|
|
|
TEST_GROUP(fib);
|
|
|
|
static struct fib *fib;
|
|
|
|
static const char *TEST_CLA_ADDR_1 = "mtcp:test.example:1234";
|
|
static const char *TEST_CLA_ADDR_2 = "mtcp:test.example:5678";
|
|
static const char *TEST_CLA_ADDR_3 = "tcpclv3:127.0.0.1:1234";
|
|
static const char *TEST_CLA_ADDR_4 = "tcpspp:";
|
|
|
|
static const char *TEST_NODE_ID_1 = "ipn:1.0";
|
|
static const char *TEST_NODE_ID_2 = "ipn:2.0";
|
|
static const char *TEST_NODE_ID_3 = "dtn://node3.dtn/";
|
|
static const char *TEST_NODE_ID_4 = "myscheme:node4";
|
|
|
|
TEST_SETUP(fib)
|
|
{
|
|
fib = fib_alloc();
|
|
}
|
|
|
|
TEST_TEAR_DOWN(fib)
|
|
{
|
|
fib_free(fib);
|
|
}
|
|
|
|
TEST(fib, fib_insert_lookup_remove_link)
|
|
{
|
|
struct fib_link *r, *r2;
|
|
|
|
// Add a single element
|
|
r = fib_insert_link(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(r);
|
|
TEST_ASSERT_NOT_EQUAL(TEST_CLA_ADDR_1, r->cla_addr);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_1, r->cla_addr);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_UNSPECIFIED, r->status);
|
|
r->status = FIB_LINK_STATUS_UP;
|
|
// Try to insert it twice
|
|
r2 = fib_insert_link(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_EQUAL_PTR(r, r2);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_1, r->cla_addr);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_UP, r->status);
|
|
r2 = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_EQUAL_PTR(r, r2);
|
|
// Add a second element
|
|
r = fib_insert_link(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NOT_NULL(r);
|
|
TEST_ASSERT_NOT_EQUAL(TEST_CLA_ADDR_2, r->cla_addr);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_2, r->cla_addr);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_UNSPECIFIED, r->status);
|
|
TEST_ASSERT_NOT_EQUAL(r2, r);
|
|
r2 = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_EQUAL_PTR(r, r2);
|
|
r->status = FIB_LINK_STATUS_DOWN;
|
|
r2 = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_DOWN, r2->status);
|
|
// Remove something that does not exist
|
|
TEST_ASSERT_FALSE(fib_remove_link(fib, TEST_CLA_ADDR_3));
|
|
// Remove first element, check that second remains
|
|
TEST_ASSERT_TRUE(fib_remove_link(fib, TEST_CLA_ADDR_1));
|
|
r = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NULL(r);
|
|
r = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NOT_NULL(r);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_2, r->cla_addr);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_DOWN, r->status);
|
|
// Remove rest, twice
|
|
TEST_ASSERT_TRUE(fib_remove_link(fib, TEST_CLA_ADDR_2));
|
|
r = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NULL(r);
|
|
TEST_ASSERT_FALSE(fib_remove_link(fib, TEST_CLA_ADDR_2));
|
|
r = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NULL(r);
|
|
// Try re-insert
|
|
r = fib_insert_link(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NOT_NULL(r);
|
|
r2 = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_EQUAL_PTR(r, r2);
|
|
}
|
|
|
|
TEST(fib, fib_insert_lookup_remove_node)
|
|
{
|
|
struct fib_entry *r, *r2;
|
|
struct fib_link *l, *l2;
|
|
|
|
// Add a single element
|
|
r = fib_insert_node(fib, TEST_NODE_ID_1, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(r);
|
|
TEST_ASSERT_NOT_EQUAL(TEST_CLA_ADDR_1, r->cla_addr);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_1, r->cla_addr);
|
|
TEST_ASSERT_EQUAL(FIB_ENTRY_FLAG_NONE, r->flags);
|
|
l = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(l);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_UNSPECIFIED, l->status);
|
|
l->status = FIB_LINK_STATUS_UP;
|
|
// Try to insert it twice
|
|
r2 = fib_insert_node(fib, TEST_NODE_ID_1, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(r2);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_1, r2->cla_addr);
|
|
l2 = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_EQUAL_PTR(l, l2);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_UP, l2->status);
|
|
r = fib_lookup_node(fib, TEST_NODE_ID_1);
|
|
TEST_ASSERT_EQUAL_PTR(r2, r);
|
|
// Change the CLA address
|
|
r = fib_insert_node(fib, TEST_NODE_ID_1, TEST_CLA_ADDR_4);
|
|
TEST_ASSERT_NOT_EQUAL(r2, r);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_4, r->cla_addr);
|
|
l = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_4);
|
|
TEST_ASSERT_NOT_NULL(l);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_UNSPECIFIED, l->status);
|
|
// Make link active so it does not get deleted with the node.
|
|
l->status = FIB_LINK_STATUS_UP;
|
|
// Check that Link and status is kept
|
|
l = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(l);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_UP, l->status);
|
|
// Add a second element, Link first
|
|
l = fib_insert_link(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NOT_NULL(l);
|
|
TEST_ASSERT_NULL(fib_lookup_node(fib, TEST_NODE_ID_2));
|
|
r2 = fib_insert_node(fib, TEST_NODE_ID_2, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NOT_NULL(r2);
|
|
l2 = fib_lookup_cla_addr(fib, r2->cla_addr);
|
|
TEST_ASSERT_EQUAL_PTR(l, l2);
|
|
l->status = FIB_LINK_STATUS_DOWN;
|
|
r2 = fib_lookup_node(fib, TEST_NODE_ID_2);
|
|
TEST_ASSERT_NOT_NULL(r2);
|
|
l2 = fib_lookup_cla_addr(fib, r2->cla_addr);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_DOWN, l2->status);
|
|
// Remove something that does not exist
|
|
TEST_ASSERT_FALSE(fib_remove_node(fib, TEST_NODE_ID_3, false));
|
|
// Remove an existing and mapped Link -> fails
|
|
TEST_ASSERT_FALSE(fib_remove_link(fib, TEST_CLA_ADDR_4));
|
|
// Remove first element, check that second remains
|
|
TEST_ASSERT_TRUE(fib_remove_node(fib, TEST_NODE_ID_1, false));
|
|
r = fib_lookup_node(fib, TEST_NODE_ID_1);
|
|
TEST_ASSERT_NULL(r);
|
|
r = fib_lookup_node(fib, TEST_NODE_ID_2);
|
|
TEST_ASSERT_NOT_NULL(r);
|
|
TEST_ASSERT_EQUAL_STRING(TEST_CLA_ADDR_2, r->cla_addr);
|
|
l = fib_lookup_cla_addr(fib, r->cla_addr);
|
|
TEST_ASSERT_NOT_NULL(l);
|
|
TEST_ASSERT_EQUAL(FIB_LINK_STATUS_DOWN, l->status);
|
|
// Check that Links are still there
|
|
l = fib_lookup_cla_addr(fib, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(l);
|
|
TEST_ASSERT_NOT_NULL(fib_lookup_cla_addr(fib, TEST_CLA_ADDR_4));
|
|
// Check that association is re-created
|
|
r = fib_insert_node(fib, TEST_NODE_ID_1, TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(r);
|
|
l2 = fib_lookup_cla_addr(fib, r->cla_addr);
|
|
TEST_ASSERT_EQUAL_PTR(l, l2);
|
|
// Check removal of all mappings
|
|
fib_insert_node(fib, TEST_NODE_ID_1, TEST_CLA_ADDR_2);
|
|
// This should delete also TEST_NODE_ID_2 (maps to CLA addr. 2)
|
|
TEST_ASSERT_TRUE(fib_remove_node(fib, TEST_NODE_ID_1, true));
|
|
TEST_ASSERT_NULL(fib_lookup_node(fib, TEST_NODE_ID_1));
|
|
TEST_ASSERT_NULL(fib_lookup_node(fib, TEST_NODE_ID_2));
|
|
// Remove a 2nd time -> should fail
|
|
TEST_ASSERT_FALSE(fib_remove_node(fib, TEST_NODE_ID_2, false));
|
|
TEST_ASSERT_FALSE(fib_remove_node(fib, TEST_NODE_ID_2, true));
|
|
TEST_ASSERT_NULL(fib_lookup_node(fib, TEST_NODE_ID_2));
|
|
TEST_ASSERT_FALSE(fib_remove_node(fib, TEST_NODE_ID_1, false));
|
|
TEST_ASSERT_FALSE(fib_remove_node(fib, TEST_NODE_ID_1, true));
|
|
TEST_ASSERT_NULL(fib_lookup_node(fib, TEST_NODE_ID_1));
|
|
}
|
|
|
|
#define FIB_FOREACH_TEST_COUNT 4
|
|
|
|
struct fib_foreach_test_ctx {
|
|
const char **expected_node_ids;
|
|
struct fib_entry **expected_entries;
|
|
struct fib_link **expected_links;
|
|
bool *evaluated;
|
|
int i, max, tested_count;
|
|
};
|
|
|
|
bool fib_foreach_test_fun(void *context, const char *node_id,
|
|
const struct fib_entry *entry,
|
|
const struct fib_link *link)
|
|
{
|
|
struct fib_foreach_test_ctx *ctx = context;
|
|
|
|
for (int i = 0; i < ctx->tested_count; i++) {
|
|
if (!strcmp(ctx->expected_node_ids[i], node_id)) {
|
|
TEST_ASSERT_EQUAL_PTR(
|
|
ctx->expected_entries[i],
|
|
entry
|
|
);
|
|
TEST_ASSERT_EQUAL_PTR(
|
|
ctx->expected_links[i],
|
|
link
|
|
);
|
|
ctx->evaluated[i] = true;
|
|
ctx->i++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ctx->i >= ctx->max)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
TEST(fib, fib_foreach)
|
|
{
|
|
const char *nids[FIB_FOREACH_TEST_COUNT] = {
|
|
TEST_NODE_ID_1,
|
|
TEST_NODE_ID_2,
|
|
TEST_NODE_ID_3,
|
|
TEST_NODE_ID_4,
|
|
};
|
|
struct fib_entry *e[FIB_FOREACH_TEST_COUNT];
|
|
struct fib_link *el[FIB_FOREACH_TEST_COUNT];
|
|
bool was_evaluated[FIB_FOREACH_TEST_COUNT] = {};
|
|
|
|
e[0] = fib_insert_node(fib, nids[0], TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(e[0]);
|
|
el[0] = fib_lookup_cla_addr(fib, e[0]->cla_addr);
|
|
TEST_ASSERT_NOT_NULL(el[0]);
|
|
e[1] = fib_insert_node(fib, nids[1], TEST_CLA_ADDR_1);
|
|
TEST_ASSERT_NOT_NULL(e[1]);
|
|
el[1] = fib_lookup_cla_addr(fib, e[1]->cla_addr);
|
|
TEST_ASSERT_NOT_NULL(el[1]);
|
|
TEST_ASSERT_EQUAL_PTR(el[0], el[1]);
|
|
el[2] = fib_insert_link(fib, TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NOT_NULL(el[2]);
|
|
e[2] = fib_insert_node(fib, nids[2], TEST_CLA_ADDR_2);
|
|
TEST_ASSERT_NOT_NULL(e[2]);
|
|
TEST_ASSERT_EQUAL_PTR(el[2], fib_lookup_cla_addr(fib, e[2]->cla_addr));
|
|
e[3] = fib_insert_node(fib, nids[3], TEST_CLA_ADDR_3);
|
|
TEST_ASSERT_NOT_NULL(e[3]);
|
|
el[3] = fib_lookup_cla_addr(fib, e[3]->cla_addr);
|
|
TEST_ASSERT_NOT_NULL(el[3]);
|
|
|
|
const struct fib_foreach_test_ctx ctx_proto = {
|
|
.expected_node_ids = nids,
|
|
.expected_entries = e,
|
|
.expected_links = el,
|
|
.evaluated = was_evaluated,
|
|
.i = 0,
|
|
.max = FIB_FOREACH_TEST_COUNT,
|
|
.tested_count = FIB_FOREACH_TEST_COUNT,
|
|
};
|
|
struct fib_foreach_test_ctx ctx = ctx_proto;
|
|
int true_count;
|
|
|
|
fib_foreach(fib, fib_foreach_test_fun, &ctx, NULL);
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
TEST_ASSERT_TRUE(ctx.evaluated[i]);
|
|
TEST_ASSERT_EQUAL_INT(FIB_FOREACH_TEST_COUNT, ctx.i);
|
|
|
|
ctx = ctx_proto;
|
|
ctx.max = 0;
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
ctx.evaluated[i] = false;
|
|
|
|
fib_foreach(fib, fib_foreach_test_fun, &ctx, NULL);
|
|
true_count = 0;
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
if (ctx.evaluated[i])
|
|
true_count++;
|
|
// Due to the definition of fib_foreach_test_fun and the nature of the
|
|
// callback mechanism, the callback will always be called at least once
|
|
// as long as there are elements inside the FIB.
|
|
TEST_ASSERT_EQUAL_INT(1, true_count);
|
|
TEST_ASSERT_EQUAL_INT(1, ctx.i);
|
|
|
|
ctx = ctx_proto;
|
|
ctx.max = 3;
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
ctx.evaluated[i] = false;
|
|
|
|
fib_foreach(fib, fib_foreach_test_fun, &ctx, NULL);
|
|
true_count = 0;
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
if (ctx.evaluated[i])
|
|
true_count++;
|
|
TEST_ASSERT_EQUAL_INT(3, true_count);
|
|
TEST_ASSERT_EQUAL_INT(3, ctx.i);
|
|
|
|
ctx = ctx_proto;
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
ctx.evaluated[i] = false;
|
|
|
|
fib_foreach(fib, fib_foreach_test_fun, &ctx, TEST_CLA_ADDR_1);
|
|
for (int i = 0; i < 2; i++)
|
|
TEST_ASSERT_TRUE(ctx.evaluated[i]);
|
|
for (int i = 2; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
TEST_ASSERT_FALSE(ctx.evaluated[i]);
|
|
|
|
ctx = ctx_proto;
|
|
ctx.max = 1;
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
ctx.evaluated[i] = false;
|
|
|
|
fib_foreach(fib, fib_foreach_test_fun, &ctx, TEST_CLA_ADDR_1);
|
|
true_count = 0;
|
|
for (int i = 0; i < FIB_FOREACH_TEST_COUNT; i++)
|
|
if (ctx.evaluated[i])
|
|
true_count++;
|
|
TEST_ASSERT_EQUAL_INT(1, true_count);
|
|
TEST_ASSERT_EQUAL_INT(1, ctx.i);
|
|
}
|
|
|
|
TEST_GROUP_RUNNER(fib)
|
|
{
|
|
RUN_TEST_CASE(fib, fib_insert_lookup_remove_link);
|
|
RUN_TEST_CASE(fib, fib_insert_lookup_remove_node);
|
|
RUN_TEST_CASE(fib, fib_foreach);
|
|
}
|