Re-integrate v0.13.0 routing code as "integrated default BDM"

This makes µD3TN behave the same as v0.13.0 when executed without an
additional commandline argument. A new commandline argument `-d` /
`--external-dispatch` is added, which enables the use of external BDMs.
The default forwarding implementation is now again provided using the
v0.13 code, extracted from e1621765a4 and
adapted to the new agent-based forwarding implementation.

Central changes to the old code include:

- A new "Routing Agent" that handles incoming configuration commands,
  FIB updates, and BDM dispatch requests.
- The use of the BDM authorization flag to authorize contact
  configuration commands.
- The Contact Manager now only triggers the creation and removal of
  links / FIB entries; bundle dispatch is triggered through the FIB and
  BDM callback functions of the Routing Agent.
- The fragmentation logic is adapted to store the original bundle along
  with an offset and length value, instead of pre-creating and storing
  the fragments.
- The bundle re-scheduling logic integrated into the Routing Agent is
  simplified and does not support changing the fragmentation parameters.
  A new function is added to the Router that searches for a new route
  for such fragments that were already scheduled at some point,
  considering them as un-fragmentable bundle with overridden fragment
  offset and length.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This commit is contained in:
Felix Walter 2024-07-03 16:33:02 +02:00
parent ad4f56b62d
commit 87be9749af
35 changed files with 1144 additions and 1002 deletions

View file

@ -122,10 +122,7 @@ build-library:
- pip install -e "python-ud3tn-utils"
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --insecure-config & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
- pytest test/integration
- kill -TERM $DISPATCHER_PID
unit-test-posix-debug:
stage: functional_test
@ -179,8 +176,6 @@ unit-test-posix-freebsd:
- pip install -e "python-ud3tn-utils"
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --insecure-config & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
- pytest test/integration
- CLA=tcpspp pytest test/integration
- kill -TERM $UD3TN_PID
@ -209,9 +204,29 @@ integration-test-posix-thread-sanitizer:
- pip install -e "python-ud3tn-utils"
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --insecure-config & DISPATCHER_PID=$!
- pytest test/integration
- kill -TERM $UD3TN_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN_PID
integration-test-posix-extdispatch:
stage: functional_test
when: always
image: registry.gitlab.com/d3tn/ud3tn-docker-images/ci-python-clang:3.8-bookworm
script:
- bash test/dockerfiles/prepare_for_test.sh . /ud3tn_build TOOLCHAIN=clang sanitize-strict=yes
- cd /ud3tn_build
- rm -f ./ud3tn.socket ./ud3tn.aap2.socket
- UBSAN_OPTIONS=print_stacktrace=1 build/posix/ud3tn -L 4 -c "sqlite:file::memory:?cache=shared;tcpclv3:*,4556;tcpspp:*,4223,false,1;smtcp:*,4222,false;mtcp:*,4224" --allow-remote-config --external-dispatch & UD3TN_PID=$!
- source /ud3tn_venv/bin/activate
- pip install -e "pyd3tn"
- pip install -e "python-ud3tn-utils"
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
- aap2-bdm-ud3tn-routing --insecure-config -vv & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
- pytest test/integration
- CLA=tcpspp pytest test/integration
- kill -TERM $UD3TN_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN_PID
@ -224,9 +239,10 @@ integration-test-posix-release:
- bash test/dockerfiles/prepare_for_test.sh . /ud3tn_build type=release optimize=yes
- cd /ud3tn_build
- rm -f ./ud3tn.socket ./ud3tn.aap2.socket
# NOTE: Here we use the external dispatcher to test also the AAPv2 secret handling
# NOTE: TEST_AAP2_BDM_SECRET is also recognized by the integration test
- export TEST_AAP2_BDM_SECRET=very_secure_secret
- build/posix/ud3tn -L 3 --bdm-secret-var TEST_AAP2_BDM_SECRET --allow-remote-config &
- build/posix/ud3tn -L 3 --bdm-secret-var TEST_AAP2_BDM_SECRET --allow-remote-config --external-dispatch &
- source /ud3tn_venv/bin/activate
- pip install -e "pyd3tn"
- pip install -e "python-ud3tn-utils"
@ -253,8 +269,6 @@ integration-test-posix-macos:
- source .venv/bin/activate
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --insecure-config & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
- pytest test/integration
- kill -TERM $UD3TN_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
@ -386,13 +400,10 @@ mtcp-test:
- pip install -e "python-ud3tn-utils"
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! nc -z localhost 4224; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --insecure-config & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
- python tools/cla/mtcp_test.py -t mtcp --payload TESTPAYLOAD &
- timeout -v 5 python tools/cla/mtcp_sink.py --count 1 --verify-pl TESTPAYLOAD
- sleep 0.2
- kill -TERM $UD3TN_PID
- kill -TERM $DISPATCHER_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN_PID
@ -414,14 +425,11 @@ fragment-reassembly-test:
- while ! nc -z localhost 4223; do sleep 0.1; done
- while ! [ -r ./ud3tn1.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn2.socket ]; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --socket ud3tn1.aap2.socket & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
- aap2-config --socket ud3tn1.aap2.socket --schedule 2 1 140 --schedule 4 1 140 dtn://ud3tn2.dtn/ mtcp:localhost:4223
- aap-send --socket ud3tn1.socket dtn://ud3tn2.dtn/sink THISISAVERYLONGBUNDLEPAYLOADWHICHWILLBEFRAGMENTED -v
- timeout -v 5 aap-receive --socket ud3tn2.socket --agentid sink --count 1 --verify-pl THISISAVERYLONGBUNDLEPAYLOADWHICHWILLBEFRAGMENTED --newline -vv
- kill -TERM $UD3TN1_PID
- kill -TERM $UD3TN2_PID
- kill -TERM $DISPATCHER_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN1_PID
- wait $UD3TN2_PID
@ -435,7 +443,8 @@ fragment-mbs-test:
- cd /ud3tn_build
- rm -f ./ud3tn.socket
- rm -f ./ud3tn.aap2.socket
- UBSAN_OPTIONS=print_stacktrace=1 build/posix/ud3tn -L 4 -c "mtcp:*,4222" -m 110 & UD3TN_PID=$!
# NOTE: No dispatcher needed - testing that it also works without it here
- UBSAN_OPTIONS=print_stacktrace=1 build/posix/ud3tn -L 4 -c "mtcp:*,4222" -m 110 --external-dispatch & UD3TN_PID=$!
- source /ud3tn_venv/bin/activate
- pip install -e "pyd3tn"
- pip install -e "python-ud3tn-utils"
@ -468,8 +477,6 @@ ipv6-compatibility-test:
- while ! nc -z localhost 4223; do sleep 0.1; done
- while ! nc -z localhost 4242; do sleep 0.1; done
- while ! nc -z localhost 4243; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --socket ud3tn1.aap2.socket & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
# Check v6 via AAP to ud3tn1 and via MTCP to ud3tn2
- aap-config --tcp '::1' 4242 --schedule 2 1 140 --schedule 4 1 140 dtn://ud3tn2.dtn/ 'mtcp:[::1]:4223'
# Check v4 via AAP to ud3tn1
@ -480,7 +487,6 @@ ipv6-compatibility-test:
- "if timeout -v 1 python test/functional/aap_test.py --tcp '::1' 4243; then echo 'Error: Should not be able to connect via IPv6 here.'; false; else true; fi"
- kill -TERM $UD3TN1_PID
- kill -TERM $UD3TN2_PID
- kill -TERM $DISPATCHER_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN1_PID
- wait $UD3TN2_PID
@ -558,11 +564,8 @@ integration-test-valgrind-memory-check:
- pip install -e "python-ud3tn-utils"
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
- aap2-bdm-ud3tn-routing -vv --insecure-config & DISPATCHER_PID=$!
- sleep 1 # give the dispatcher some time to start
- pytest test/integration
- kill -TERM $UD3TN_PID
- kill -TERM $DISPATCHER_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN_PID
@ -611,7 +614,7 @@ coverage-test:
- rm -f ./ud3tn.socket ./ud3tn.aap2.socket
- make unittest-posix coverage=yes
- timeout 60 build/posix/testud3tn
- build/posix/ud3tn --allow-remote-config & UD3TN_PID=$!
- build/posix/ud3tn --allow-remote-config --external-dispatch & UD3TN_PID=$!
- source /ud3tn_venv/bin/activate
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
@ -622,6 +625,15 @@ coverage-test:
- kill -TERM $DISPATCHER_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN_PID
- rm -f ./ud3tn.socket ./ud3tn.aap2.socket
- build/posix/ud3tn --allow-remote-config & UD3TN_PID=$!
- source /ud3tn_venv/bin/activate
- while ! [ -r ./ud3tn.socket ]; do sleep 0.1; done
- while ! [ -r ./ud3tn.aap2.socket ]; do sleep 0.1; done
- pytest test/integration
- kill -TERM $UD3TN_PID
- echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
- wait $UD3TN_PID
- gcovr --xml-pretty --exclude-unreachable-branches --gcov-ignore-parse-errors --print-summary -o coverage.xml --root .
- cp -v coverage.xml "$project_dir/"
coverage: /^\s*lines:\s*\d+.\d+\%/

View file

@ -1,100 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "agents/config_agent.h"
#include "agents/config_parser.h"
#include "ud3tn/agent_manager.h"
#include "ud3tn/bundle_processor.h"
#include "ud3tn/common.h"
#include "ud3tn/eid.h"
#include "platform/hal_io.h"
#include "platform/hal_types.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct config_parser parser;
struct config_agent_params {
const char *local_eid;
bool allow_remote_configuration;
};
static void callback(struct bundle_adu data, void *param, const void *ctx)
{
(void)ctx;
struct config_agent_params *const ca_param = param;
if (!ca_param->allow_remote_configuration) {
char *const node_id = get_node_id(data.source);
if (!node_id || strncmp(ca_param->local_eid, node_id,
strlen(ca_param->local_eid)) != 0) {
LOGF_WARN(
"ConfigAgent: Dropped config message from foreign endpoint \"%s\"",
data.source
);
free(node_id);
return;
}
free(node_id);
}
config_parser_reset(&parser);
config_parser_read(
&parser,
data.payload,
data.length
);
bundle_adu_free_members(data);
}
int config_agent_setup(
QueueIdentifier_t bundle_processor_signaling_queue,
const char *local_eid,
bool allow_remote_configuration,
void *bundle_processor_context)
{
const int is_ipn = get_eid_scheme(local_eid) == EID_SCHEME_IPN;
ASSERT(config_parser_init(
&parser,
&bundle_processor_handle_router_command,
bundle_processor_context
));
struct config_agent_params *const ca_param = malloc(
sizeof(struct config_agent_params)
);
ca_param->local_eid = local_eid;
ca_param->allow_remote_configuration = allow_remote_configuration;
const struct agent agent = {
.auth_trx = true,
.is_subscriber = true,
.sink_identifier = (
is_ipn
? AGENT_ID_CONFIG_IPN
: AGENT_ID_CONFIG_DTN
),
.trx_callback = callback,
.param = ca_param,
};
const int rv = bundle_processor_perform_agent_action_async(
bundle_processor_signaling_queue,
BP_SIGNAL_AGENT_REGISTER,
agent
);
if (rv) {
free(ca_param);
config_parser_reset(&parser);
}
return rv;
}

View file

@ -1,11 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "agents/config_parser.h"
#include "routing/compat/config_parser.h"
#include "routing/compat/node.h"
#include "routing/compat/router.h"
#include "platform/hal_io.h"
#include "ud3tn/eid.h"
#include "ud3tn/node.h"
#include "ud3tn/router.h"
#include <stdbool.h>
#include <stddef.h>
@ -33,8 +33,6 @@ static const uint8_t DEFAULT_EID_BUFFER_SIZE = 16;
static const uint8_t DEFAULT_CLA_ADDR_BUFFER_SIZE = 21;
static const uint8_t DEFAULT_INT_BUFFER_SIZE = 16;
static void send_router_command(struct config_parser *parser);
static void begin_read_data_eid(
struct config_parser *parser, struct endpoint_list **target)
{
@ -473,9 +471,6 @@ static void config_parser_read_byte(struct config_parser *parser, uint8_t byte)
} else {
read_command(parser, *(char *)(&byte));
}
if (parser->basedata->status == PARSER_STATUS_DONE)
send_router_command(parser);
}
size_t config_parser_read(struct config_parser *parser,
@ -484,7 +479,6 @@ size_t config_parser_read(struct config_parser *parser,
size_t i = 0;
while (i < length) {
config_parser_read_byte(parser, buffer[i]);
if (parser->basedata->status != PARSER_STATUS_GOOD &&
parser->basedata->status != PARSER_STATUS_DONE) {
LOGF_WARN(
@ -495,7 +489,10 @@ size_t config_parser_read(struct config_parser *parser,
config_parser_reset(parser);
return length;
}
config_parser_read_byte(parser, buffer[i]);
i++;
if (parser->basedata->status == PARSER_STATUS_DONE)
break;
}
return i;
@ -533,31 +530,14 @@ enum ud3tn_result config_parser_reset(struct config_parser *parser)
return UD3TN_OK;
}
struct parser *config_parser_init(
struct config_parser *parser,
void (*send_callback)(void *, struct router_command *), void *param)
struct parser *config_parser_init(struct config_parser *parser)
{
parser->basedata = malloc(sizeof(struct parser));
if (parser->basedata == NULL)
return NULL;
parser->send_callback = send_callback;
parser->send_param = param;
parser->basedata->status = PARSER_STATUS_ERROR;
parser->router_command = NULL;
if (config_parser_reset(parser) != UD3TN_OK)
return NULL;
return parser->basedata;
}
static void send_router_command(struct config_parser *parser)
{
struct router_command *ptr;
if (parser->send_callback == NULL)
return;
ptr = parser->router_command;
/* Unset router cmd, the recipient has to take care of it... */
parser->router_command = NULL;
parser->send_callback(parser->send_param, ptr);
/* Don't reset the parser here as the input task must know the state */
}

View file

@ -1,8 +1,9 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "routing/compat/contact_manager.h"
#include "routing/compat/node.h"
#include "routing/compat/routing_table.h"
#include "ud3tn/common.h"
#include "ud3tn/contact_manager.h"
#include "ud3tn/node.h"
#include "ud3tn/routing_table.h"
#include "cla/cla.h"
#include "cla/cla_contact_tx_task.h"
@ -28,9 +29,9 @@ struct contact_manager_task_parameters {
};
struct contact_info {
struct contact *contact;
char *eid;
char *cla_addr;
uint64_t to_ms;
};
struct contact_manager_context {
@ -46,7 +47,9 @@ static bool contact_active(
int8_t i;
for (i = 0; i < ctx->current_contact_count; i++) {
if (ctx->current_contacts[i].contact == contact)
if (!strcmp(ctx->current_contacts[i].eid, contact->node->eid) &&
ctx->current_contacts[i].to_ms == contact->to_ms
)
return true;
}
return false;
@ -61,11 +64,8 @@ static int8_t remove_expired_contacts(
int8_t i, c, removed = 0;
for (i = ctx->current_contact_count - 1; i >= 0; i--) {
if (ctx->current_contacts[i].contact->to_ms <=
current_timestamp_ms) {
if (ctx->current_contacts[i].to_ms <= current_timestamp_ms) {
ASSERT(i <= MAX_CONCURRENT_CONTACTS);
/* Unset "active" constraint */
ctx->current_contacts[i].contact->active = 0;
/* The TX task takes care of re-scheduling */
list[removed++] = ctx->current_contacts[i];
/* If it's not the last element, we have to move mem */
@ -97,26 +97,23 @@ static uint8_t check_upcoming(
return 0;
}
/* Set "active" constraint, "blocking" the contact */
c->active = 1;
/* Add contact */
ctx->current_contacts[ctx->current_contact_count].contact = c;
ctx->current_contacts[ctx->current_contact_count].eid = strdup(
c->node->eid
);
if (!ctx->current_contacts[ctx->current_contact_count].eid) {
LOG_ERROR("ContactManager: Failed to copy EID");
LOG_WARN("ContactManager: Failed to copy EID");
return 0;
}
ctx->current_contacts[ctx->current_contact_count].cla_addr = strdup(
c->node->cla_addr
);
if (!ctx->current_contacts[ctx->current_contact_count].cla_addr) {
LOG_ERROR("ContactManager: Failed to copy CLA address");
LOG_WARN("ContactManager: Failed to copy CLA address");
free(ctx->current_contacts[ctx->current_contact_count].eid);
return 0;
}
ctx->current_contacts[ctx->current_contact_count].to_ms = c->to_ms;
list[index] = ctx->current_contacts[ctx->current_contact_count];
ctx->current_contact_count++;
@ -162,121 +159,20 @@ static int8_t process_upcoming_list(
return added;
}
static int hand_over_contact_bundles(
struct contact_manager_context *const ctx, Semaphore_t semphr, int8_t i)
static void check_for_contacts(
struct contact_manager_context *const ctx,
struct contact_list **contact_list,
Semaphore_t semphr, QueueIdentifier_t bp_queue)
{
struct contact_info cinfo = ctx->current_contacts[i];
struct contact_info added_contacts[MAX_CONCURRENT_CONTACTS];
struct contact_info removed_contacts[MAX_CONCURRENT_CONTACTS];
const uint64_t current_timestamp_ms = hal_time_get_timestamp_ms();
ASSERT(semphr != NULL);
ASSERT(bp_queue != NULL);
hal_semaphore_take_blocking(semphr);
// NOTE: cinfo.contact MAY not be valid at this point!
struct node_table_entry *n = routing_table_lookup_eid(cinfo.eid);
struct contact_list *cl = (n != NULL) ? n->contacts : NULL;
bool found = false;
while (cl) {
if (cl->data == cinfo.contact) {
found = true;
break;
}
cl = cl->next;
}
if (!found) {
LOGF_WARN(
"ContactManager: Could not find contact %p to \"%s\" via \"%s\", discarding record",
cinfo.contact,
cinfo.eid,
cinfo.cla_addr
);
// Remove invalid contact info
free(cinfo.eid);
free(cinfo.cla_addr);
if (i < ctx->current_contact_count - 1) {
memmove(
&ctx->current_contacts[i],
&ctx->current_contacts[i + 1],
sizeof(struct contact_info) * (
ctx->current_contact_count - 1 - i
)
);
}
ctx->current_contact_count--;
hal_semaphore_release(semphr);
return 0;
}
// Contact found and valid -> continue!
if (cinfo.contact->contact_bundles == NULL) {
hal_semaphore_release(semphr);
return 1;
}
ASSERT(cinfo.cla_addr != NULL);
// Try to obtain a handler
struct cla_config *cla_config = cla_config_get(cinfo.cla_addr);
if (!cla_config) {
LOGF_WARN(
"ContactManager: Could not obtain CLA for address \"%s\"",
cinfo.cla_addr
);
hal_semaphore_release(semphr);
return 1;
}
struct cla_tx_queue tx_queue = cla_config->vtable->cla_get_tx_queue(
cla_config,
cinfo.eid,
cinfo.cla_addr
);
if (!tx_queue.tx_queue_handle) {
LOGF_WARN(
"ContactManager: Could not obtain queue for TX to \"%s\" via \"%s\"",
cinfo.eid,
cinfo.cla_addr
);
// Re-scheduling will be done by routerTask or transmission will
// occur after signal of new connection.
hal_semaphore_release(semphr);
return 1;
}
LOGF_INFO(
"ContactManager: Queuing bundles for contact with \"%s\".",
cinfo.eid
);
struct cla_contact_tx_task_command command = {
.type = TX_COMMAND_BUNDLES,
// Take over the bundles as we can now push them into the queue
// that is protected by the CLA semaphore.
.bundles = cinfo.contact->contact_bundles,
};
// Ensure the Router does not interfere. We own the list now and the
// TX task will free it.
cinfo.contact->contact_bundles = NULL;
// Now we can also let the BP do its thing again...
hal_semaphore_release(semphr);
// NOTE: From now on, cinfo.contact MAY become invalid again!
command.cla_address = strdup(cinfo.cla_addr);
hal_queue_push_to_back(tx_queue.tx_queue_handle, &command);
hal_semaphore_release(tx_queue.tx_queue_sem); // taken by get_tx_queue
return 1;
}
static uint8_t check_for_contacts(
struct contact_manager_context *const ctx,
struct contact_list *contact_list,
struct contact_info removed_contacts[])
{
int8_t i;
static struct contact_info added_contacts[MAX_CONCURRENT_CONTACTS];
const uint64_t current_timestamp_ms = hal_time_get_timestamp_ms();
const int8_t removed_count = remove_expired_contacts(
ctx,
current_timestamp_ms,
@ -284,102 +180,70 @@ static uint8_t check_for_contacts(
);
const int8_t added_count = process_upcoming_list(
ctx,
contact_list,
*contact_list, // dereference only when we have the semaphore!
current_timestamp_ms,
added_contacts
);
hal_semaphore_release(semphr);
ASSERT(ctx->next_contact_time_ms > current_timestamp_ms);
for (i = 0; i < added_count; i++) {
for (int8_t i = 0; i < added_count; i++) {
LOGF_INFO(
"ContactManager: Scheduled contact with \"%s\" started (%p).",
added_contacts[i].eid,
added_contacts[i].contact
"ContactManager: Scheduled contact with \"%s\" started.",
added_contacts[i].eid
);
struct cla_config *cla_config = cla_config_get(
added_contacts[i].cla_addr
struct fib_association *req = malloc(
sizeof(struct fib_association)
);
if (!cla_config) {
LOGF_WARN(
"ContactManager: Could not obtain CLA for address \"%s\"",
added_contacts[i].cla_addr
);
} else {
cla_config->vtable->cla_start_scheduled_contact(
cla_config,
added_contacts[i].eid,
added_contacts[i].cla_addr
);
}
if (!req)
break;
req->status = FIB_LINK_STATUS_ACTIVE;
req->flags = FIB_LINK_FLAG_NONE;
req->node_id = strdup(added_contacts[i].eid);
req->cla_addr = strdup(added_contacts[i].cla_addr);
bundle_processor_inform(
bp_queue,
(struct bundle_processor_signal){
.type = BP_SIGNAL_FIB_UPDATE_REQUEST,
.fib_request = req,
}
);
// cppcheck-suppress memleak
}
for (i = 0; i < removed_count; i++) {
for (int8_t i = 0; i < removed_count; i++) {
LOGF_INFO(
"ContactManager: Scheduled contact with \"%s\" ended (%p).",
removed_contacts[i].eid,
removed_contacts[i].contact
"ContactManager: Scheduled contact with \"%s\" ended.",
removed_contacts[i].eid
);
struct cla_config *cla_config = cla_config_get(
removed_contacts[i].cla_addr
struct fib_association *req = malloc(
sizeof(struct fib_association)
);
if (!cla_config) {
LOGF_WARN(
"ContactManager: Could not obtain CLA for address \"%s\"",
removed_contacts[i].cla_addr
);
} else {
cla_config->vtable->cla_end_scheduled_contact(
cla_config,
removed_contacts[i].eid,
removed_contacts[i].cla_addr
);
}
free(removed_contacts[i].eid);
free(removed_contacts[i].cla_addr);
}
return removed_count;
}
if (!req)
break;
/* We assume that contact_list will not change. */
static void manage_contacts(
struct contact_manager_context *const ctx,
struct contact_list **contact_list, enum contact_manager_signal signal,
Semaphore_t semphr, QueueIdentifier_t bp_queue)
{
struct contact_info removed_list[MAX_CONCURRENT_CONTACTS];
int8_t removed, i;
req->status = FIB_LINK_STATUS_TEARDOWN;
req->flags = FIB_LINK_FLAG_NONE;
req->node_id = removed_contacts[i].eid;
req->cla_addr = removed_contacts[i].cla_addr;
ASSERT(semphr != NULL);
ASSERT(bp_queue != NULL);
bundle_processor_inform(
bp_queue,
(struct bundle_processor_signal){
.type = BP_SIGNAL_FIB_UPDATE_REQUEST,
.fib_request = req,
}
);
// NOTE: CM_SIGNAL_UNKNOWN has both flags
if (HAS_FLAG(signal, CM_SIGNAL_UPDATE_CONTACT_LIST)) {
hal_semaphore_take_blocking(semphr);
removed = check_for_contacts(ctx, *contact_list, removed_list);
hal_semaphore_release(semphr);
for (i = 0; i < removed; i++) {
/* The contact has to be deleted first... */
bundle_processor_inform(
bp_queue,
(struct bundle_processor_signal) {
.type = BP_SIGNAL_CONTACT_OVER,
.contact = removed_list[i].contact,
}
);
}
}
// NOTE: CM_SIGNAL_UNKNOWN has both flags
if (HAS_FLAG(signal, CM_SIGNAL_PROCESS_CURRENT_BUNDLES)) {
for (int8_t i = 0; i < ctx->current_contact_count; ) {
// NOTE this may either return 1 or 0, the latter if it
// deleted an item & modified ctx->current_contact_count
i += hand_over_contact_bundles(ctx, semphr, i);
}
removed_contacts[i].eid = NULL;
removed_contacts[i].cla_addr = NULL;
}
}
@ -387,7 +251,7 @@ static void contact_manager_task(void *cm_parameters)
{
struct contact_manager_task_parameters *parameters =
(struct contact_manager_task_parameters *)cm_parameters;
enum contact_manager_signal signal = CM_SIGNAL_NONE;
int signal;
uint64_t cur_time_ms, next_time_ms;
int64_t delay_ms;
struct contact_manager_context ctx = {
@ -400,16 +264,12 @@ static void contact_manager_task(void *cm_parameters)
abort();
}
for (;;) {
if (signal != CM_SIGNAL_NONE) {
manage_contacts(
&ctx,
parameters->contact_list_ptr,
signal,
parameters->semaphore,
parameters->bp_queue
);
}
signal = CM_SIGNAL_UNKNOWN;
check_for_contacts(
&ctx,
parameters->contact_list_ptr,
parameters->semaphore,
parameters->bp_queue
);
cur_time_ms = hal_time_get_timestamp_ms();
delay_ms = -1; // infinite blocking on queue
if (ctx.next_contact_time_ms < UINT64_MAX) {
@ -450,7 +310,7 @@ struct contact_manager_params contact_manager_start(
if (semaphore == NULL)
return ret;
hal_semaphore_release(semaphore);
queue = hal_queue_create(1, sizeof(enum contact_manager_signal));
queue = hal_queue_create(1, sizeof(int));
if (queue == NULL) {
hal_semaphore_delete(semaphore);
return ret;

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "routing/compat/node.h"
#include "ud3tn/common.h"
#include "ud3tn/node.h"
#include "ud3tn/result.h"
#include "platform/hal_time.h"
@ -51,9 +52,9 @@ struct contact *contact_create(struct node *node)
ret->remaining_capacity_p0 = 0;
ret->remaining_capacity_p1 = 0;
ret->remaining_capacity_p2 = 0;
ret->link_active = false;
ret->contact_endpoints = NULL;
ret->contact_bundles = NULL;
ret->active = 0;
return ret;
}
@ -65,7 +66,6 @@ static void free_contact_internal(
if (contact == NULL)
return;
ASSERT(contact->active == 0);
if (free_eid_list) {
cur_eid = contact->contact_endpoints;
while (cur_eid != NULL)
@ -419,10 +419,6 @@ struct contact_list *contact_list_difference(
*cur_slot = l->next;
l->next = *deleted;
*deleted = l;
} else if ((*cur_slot)->data->active) {
l = *cur_slot;
*cur_slot = l->next;
free(l);
} else {
*cur_slot = contact_list_free_internal(
*cur_slot,

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "routing/compat/node.h"
#include "routing/compat/router.h"
#include "routing/compat/routing_table.h"
#include "ud3tn/bundle.h"
#include "ud3tn/common.h"
#include "ud3tn/eid.h"
#include "ud3tn/node.h"
#include "ud3tn/router.h"
#include "ud3tn/routing_table.h"
#include "cla/cla.h"
@ -18,7 +19,6 @@
static struct router_config RC = {
.global_mbs = ROUTER_GLOBAL_MBS,
.fragment_min_payload = FRAGMENT_MIN_PAYLOAD,
.router_min_contacts_htab = ROUTER_MIN_CONTACTS_HTAB,
};
struct router_config router_get_config(void)
@ -61,16 +61,16 @@ struct contact_list *router_lookup_destination(char *const dest)
static inline struct max_fragment_size_result {
uint32_t max_fragment_size;
uint32_t payload_capacity;
uint64_t payload_capacity;
} router_get_max_reasonable_fragment_size(
struct contact_list *contacts, uint32_t full_size,
uint32_t max_fragment_min_size, uint32_t payload_size,
struct contact_list *contacts, uint64_t full_size,
uint64_t max_fragment_min_size, uint64_t payload_size,
enum bundle_routing_priority priority, uint64_t exp_time)
{
uint32_t payload_capacity = 0;
uint64_t payload_capacity = 0;
uint32_t max_frag_size = UINT32_MAX;
uint32_t min_capacity, c_capacity;
int32_t c_pay_capacity;
uint64_t min_capacity, c_capacity;
int64_t c_pay_capacity;
struct contact *c;
(void)exp_time;
@ -81,7 +81,22 @@ static inline struct max_fragment_size_result {
contacts = contacts->next;
//if (c->to_s > exp_time)
// break;
c_capacity = ROUTER_CONTACT_CAPACITY(c, priority);
const int32_t rccap = ROUTER_CONTACT_CAPACITY(c, priority);
// The return value of `contact_get_remaining_capacity_bytes`
// is `INT32_MAX` is we assume an "infinite capacity" contact
// As this determines the 64-bit payload capacity below and we
// can use larger values here, we set the capacity value to
// UINT64_MAX in this case.
if (rccap == INT32_MAX)
c_capacity = UINT64_MAX;
else if (rccap < 0)
c_capacity = 0;
else
c_capacity = rccap;
// If size_t is smaller than uint64_t we need to cap the value.
if (c_capacity > SIZE_MAX)
c_capacity = SIZE_MAX;
if (c_capacity < min_capacity)
continue;
@ -93,12 +108,20 @@ static inline struct max_fragment_size_result {
if (!cla_config)
continue;
const size_t c_mbs = MIN(
MIN(
(size_t)c_capacity,
cla_config->vtable->cla_mbs_get(cla_config)
),
RC.global_mbs
const uint64_t cla_mbs_bytes = cla_config->vtable->cla_mbs_get(
cla_config
);
const uint64_t bp_mbs_bytes = RC.global_mbs;
const uint64_t mbs_bytes = (
(bp_mbs_bytes == 0) ? cla_mbs_bytes : (
(cla_mbs_bytes == 0)
? bp_mbs_bytes
: MIN(bp_mbs_bytes, cla_mbs_bytes)
)
);
const size_t c_mbs = mbs_bytes == 0 ? (size_t)c_capacity : MIN(
(size_t)c_capacity,
mbs_bytes
);
// Contact of "infinite" capacity -> max. frag. size == MBS
@ -122,6 +145,10 @@ static inline struct max_fragment_size_result {
break;
}
}
if (max_frag_size >= INT32_MAX)
max_frag_size = INT32_MAX; // "infinite"
return (struct max_fragment_size_result){
payload_capacity < payload_size ? 0 : max_frag_size,
payload_capacity,
@ -129,18 +156,19 @@ static inline struct max_fragment_size_result {
}
uint8_t router_calculate_fragment_route(
struct fragment_route *res, uint32_t size,
struct contact_list *contacts, uint32_t preprocessed_size,
struct fragment_route *res, uint64_t size,
struct contact_list *contacts, uint64_t preprocessed_size,
enum bundle_routing_priority priority, uint64_t exp_time_ms,
struct contact **excluded_contacts, uint8_t excluded_contacts_count)
{
const uint64_t time_ms = hal_time_get_timestamp_ms();
uint32_t cap;
uint64_t cap;
uint8_t d, i;
struct contact *c;
(void)priority;
res->contact = NULL;
res->preemption_improved = 0;
while (contacts != NULL) {
c = contacts->data;
contacts = contacts->next;
@ -155,6 +183,9 @@ uint8_t router_calculate_fragment_route(
if (c->to_ms <= time_ms)
continue;
cap = ROUTER_CONTACT_CAPACITY(c, 0);
// "infinite" capacity contact
if (cap == INT32_MAX)
cap = UINT64_MAX;
if (preprocessed_size != 0) {
if (preprocessed_size >= cap) {
preprocessed_size -= cap;
@ -165,9 +196,6 @@ uint8_t router_calculate_fragment_route(
}
}
if (cap < size) {
if ((ROUTER_CONTACT_CAPACITY(c, priority)
- preprocessed_size) >= size)
res->preemption_improved++;
preprocessed_size = 0;
continue;
}
@ -179,7 +207,7 @@ uint8_t router_calculate_fragment_route(
static inline void router_get_first_route_nonfrag(
struct router_result *res, struct contact_list *contacts,
struct bundle *bundle, uint32_t bundle_size,
struct bundle *bundle, uint64_t bundle_size,
uint64_t expiration_time_ms)
{
res->fragment_results[0].payload_size = bundle->payload_block->length;
@ -188,28 +216,26 @@ static inline void router_get_first_route_nonfrag(
&res->fragment_results[0], bundle_size,
contacts, 0, ROUTER_BUNDLE_PRIORITY(bundle), expiration_time_ms,
NULL, 0)
) {
)
res->fragments = 1;
res->preemption_improved = res->fragment_results[0].preemption_improved;
}
}
static inline void router_get_first_route_frag(
struct router_result *res, struct contact_list *contacts,
struct bundle *bundle, uint32_t bundle_size,
struct bundle *bundle, uint64_t bundle_size,
uint64_t expiration_time_ms,
uint32_t max_frag_sz, uint32_t first_frag_sz, uint32_t last_frag_sz)
uint64_t max_frag_sz, uint64_t first_frag_sz, uint64_t last_frag_sz)
{
uint32_t mid_frag_sz, next_frag_sz, remaining_pay, processed_sz;
int32_t min_pay, max_pay;
int32_t success, index;
uint64_t mid_frag_sz, next_frag_sz, remaining_pay, processed_sz;
int64_t min_pay, max_pay;
int64_t success, index;
/* Determine fragment minimum sizes */
mid_frag_sz = bundle_get_mid_fragment_min_size(bundle);
next_frag_sz = first_frag_sz;
if (next_frag_sz > max_frag_sz || last_frag_sz > max_frag_sz) {
LOGF_INFO(
"Router: Cannot fragment because max. frag. size of %lu bytes is smaller than bundle headers (first = %lu, mid = %lu, last = %lu)",
LOGF_DEBUG(
"Router: Cannot fragment because max. frag. size of %llu bytes is smaller than bundle headers (first = %llu, mid = %llu, last = %llu)",
max_frag_sz,
next_frag_sz,
mid_frag_sz,
@ -223,8 +249,8 @@ static inline void router_get_first_route_frag(
min_pay = MIN(remaining_pay, RC.fragment_min_payload);
max_pay = max_frag_sz - next_frag_sz;
if (max_pay < min_pay) {
LOGF_INFO(
"Router: Cannot fragment because minimum amount of payload (%lu bytes) will not fit in fragment with maximum payload size of %lu bytes",
LOGF_DEBUG(
"Router: Cannot fragment because minimum amount of payload (%llu bytes) will not fit in fragment with maximum payload size of %llu bytes",
min_pay,
max_pay
);
@ -236,7 +262,7 @@ static inline void router_get_first_route_frag(
remaining_pay = 0;
} else {
/* Another fragment */
max_pay = MIN((int32_t)remaining_pay, max_pay);
max_pay = MIN((int64_t)remaining_pay, max_pay);
res->fragment_results[res->fragments++].payload_size = max_pay;
remaining_pay -= max_pay;
next_frag_sz = mid_frag_sz;
@ -249,7 +275,6 @@ static inline void router_get_first_route_frag(
/* Determine routes */
success = 0;
res->preemption_improved = 0;
processed_sz = 0;
for (index = 0; index < res->fragments; index++) {
bundle_size = res->fragment_results[index].payload_size;
@ -263,28 +288,25 @@ static inline void router_get_first_route_frag(
&res->fragment_results[index], bundle_size,
contacts, processed_sz, ROUTER_BUNDLE_PRIORITY(bundle),
expiration_time_ms, NULL, 0);
res->preemption_improved +=
res->fragment_results[index].preemption_improved;
processed_sz += bundle_size;
}
if (success != res->fragments)
res->fragments = 0;
}
/* max. ~200 bytes on stack */
struct router_result router_get_first_route(struct bundle *bundle)
{
const uint64_t expiration_time_ms = bundle_get_expiration_time_ms(
bundle
);
struct router_result res;
struct contact_list *contacts =
router_lookup_destination(bundle->destination);
struct contact_list *contacts = router_lookup_destination(
bundle->destination
);
res.fragments = 0;
res.preemption_improved = 0;
if (contacts == NULL) {
LOGF_INFO(
LOGF_DEBUG(
"Router: Could not determine a node over which the destination \"%s\" for bundle %p is reachable",
bundle->destination,
bundle
@ -292,11 +314,11 @@ struct router_result router_get_first_route(struct bundle *bundle)
return res;
}
const uint32_t bundle_size = bundle_get_serialized_size(bundle);
const uint32_t first_frag_sz = bundle_get_first_fragment_min_size(
const uint64_t bundle_size = bundle_get_serialized_size(bundle);
const uint64_t first_frag_sz = bundle_get_first_fragment_min_size(
bundle
);
const uint32_t last_frag_sz = bundle_get_last_fragment_min_size(bundle);
const uint64_t last_frag_sz = bundle_get_last_fragment_min_size(bundle);
const struct max_fragment_size_result mrfs =
router_get_max_reasonable_fragment_size(
@ -310,7 +332,7 @@ struct router_result router_get_first_route(struct bundle *bundle)
if (mrfs.max_fragment_size == 0) {
LOGF_DEBUG(
"Router: Contact payload capacity (%lu bytes) too low for bundle %p of size %lu bytes (min. frag. sz. = %lu, payload sz. = %lu)",
"Router: Contact payload capacity (%llu bytes) too low for bundle %p of size %llu bytes (min. frag. sz. = %llu, payload sz. = %llu)",
mrfs.payload_capacity,
bundle,
bundle_size,
@ -320,7 +342,7 @@ struct router_result router_get_first_route(struct bundle *bundle)
goto finish;
} else if (mrfs.max_fragment_size != INT32_MAX) {
LOGF_DEBUG(
"Router: Determined max. frag size of %lu bytes for bundle %p of size %lu bytes (payload sz. = %lu)",
"Router: Determined max. frag size of %lu bytes for bundle %p of size %llu bytes (payload sz. = %llu)",
mrfs.max_fragment_size,
bundle,
bundle_size,
@ -328,7 +350,7 @@ struct router_result router_get_first_route(struct bundle *bundle)
);
} else {
LOGF_DEBUG(
"Router: Determined infinite max. frag size for bundle of size %lu bytes (payload sz. = %lu)",
"Router: Determined infinite max. frag size for bundle of size %llu bytes (payload sz. = %llu)",
bundle_size,
bundle->payload_block->length
);
@ -344,8 +366,8 @@ struct router_result router_get_first_route(struct bundle *bundle)
mrfs.max_fragment_size, first_frag_sz, last_frag_sz);
if (!res.fragments)
LOGF_INFO(
"Router: No feasible route found for bundle %p to \"%s\" with size of %lu bytes",
LOGF_DEBUG(
"Router: No feasible route found for bundle %p to \"%s\" with size of %llu bytes",
bundle,
bundle->destination,
bundle_size
@ -361,69 +383,125 @@ finish:
return res;
}
/* For use with caching of routes */
struct router_result router_try_reuse(
struct router_result route, struct bundle *bundle)
static size_t get_serialized_size_frag(
struct bundle *b,
uint64_t frag_offset, uint64_t frag_length)
{
uint64_t header_size;
// Would be a bug - fragment would end after end of bundle.
ASSERT(frag_offset + frag_length <= b->payload_block->length);
if (frag_offset == 0)
header_size = bundle_get_first_fragment_min_size(b);
else if (frag_offset + frag_length == b->payload_block->length)
header_size = bundle_get_last_fragment_min_size(b);
else
header_size = bundle_get_mid_fragment_min_size(b);
return header_size + frag_length;
}
struct router_result router_get_resched_route(
struct bundle *bundle,
const uint64_t frag_offset, const uint64_t frag_length)
{
const uint64_t time_ms = hal_time_get_timestamp_ms();
const uint64_t expiration_time_ms = bundle_get_expiration_time_ms(
bundle
);
uint32_t remaining_pay = bundle->payload_block->length;
uint32_t size, min_cap;
struct fragment_route *fr;
int32_t f;
struct router_result res;
struct contact_list *contacts = router_lookup_destination(
bundle->destination
);
if (route.fragments == 0)
return route;
/* Not fragmented */
if (bundle_must_not_fragment(bundle) || route.fragments == 1) {
size = bundle_get_serialized_size(bundle);
fr = &route.fragment_results[0];
fr->payload_size = remaining_pay;
if (fr->contact->to_ms <= time_ms ||
fr->contact->to_ms > expiration_time_ms ||
ROUTER_CONTACT_CAPACITY(fr->contact, 0) < (int32_t)size)
route.fragments = 0;
return route;
res.fragments = 0;
if (contacts == NULL) {
LOGF_DEBUG(
"Router: Could not determine a node over which the destination \"%s\" for re-scheduling bundle %p [%llu, %llu] is reachable",
bundle->destination,
bundle,
frag_offset,
frag_offset + frag_length
);
return res;
}
/* Fragmented */
for (f = 0; f < route.fragments; f++) {
if (f == 0)
size = bundle_get_first_fragment_min_size(bundle);
else if (f == route.fragments - 1)
size = bundle_get_last_fragment_min_size(bundle);
else
size = bundle_get_mid_fragment_min_size(bundle);
fr = &route.fragment_results[f];
min_cap = UINT32_MAX;
if (fr->contact->to_ms <= time_ms ||
fr->contact->to_ms > expiration_time_ms ||
(ROUTER_CONTACT_CAPACITY(fr->contact, 0) <
(int32_t)(size + RC.fragment_min_payload))) {
route.fragments = 0;
return route;
}
min_cap = MIN(min_cap,
ROUTER_CONTACT_CAPACITY(fr->contact, 0)
- size);
fr->payload_size = MIN(remaining_pay, min_cap);
remaining_pay -= fr->payload_size;
if (remaining_pay == 0) {
route.fragments = f - 1;
return route;
}
const uint64_t bundle_size = get_serialized_size_frag(
bundle,
frag_offset,
frag_length
);
const struct max_fragment_size_result mrfs =
router_get_max_reasonable_fragment_size(
contacts,
bundle_size,
bundle_size - frag_length,
frag_length,
ROUTER_BUNDLE_PRIORITY(bundle),
expiration_time_ms
);
if (mrfs.max_fragment_size == 0) {
LOGF_DEBUG(
"Router: Contact payload capacity (%llu bytes) too low for re-scheduling bundle %p [%llu, %llu] of size %llu bytes",
mrfs.payload_capacity,
bundle,
frag_offset,
frag_offset + frag_length,
bundle_size
);
goto finish;
} else if (mrfs.max_fragment_size != INT32_MAX) {
LOGF_DEBUG(
"Router: Determined max. frag size of %lu bytes for re-scheduling bundle %p [%llu, %llu] of size %llu bytes",
mrfs.max_fragment_size,
bundle,
frag_offset,
frag_offset + frag_length,
bundle_size
);
} else {
LOGF_DEBUG(
"Router: Determined infinite max. frag size for re-scheduling bundle %p [%llu, %llu] of size %llu bytes",
bundle,
frag_offset,
frag_offset + frag_length,
bundle_size
);
}
if (remaining_pay != 0)
route.fragments = 0;
return route;
router_get_first_route_nonfrag(
&res,
contacts,
bundle,
bundle_size,
expiration_time_ms
);
if (!res.fragments)
LOGF_DEBUG(
"Router: No feasible route found for re-scheduling bundle %p [%llu, %llu] to \"%s\" with size of %llu bytes",
bundle,
frag_offset,
frag_offset + frag_length,
bundle->destination,
bundle_size
);
finish:
while (contacts) {
struct contact_list *const tmp = contacts->next;
free(contacts);
contacts = tmp;
}
return res;
}
enum ud3tn_result router_add_bundle_to_contact(
struct contact *contact, struct bundle *b)
struct contact *contact, struct bundle *b,
uint64_t frag_offset, uint64_t frag_length)
{
struct routed_bundle_list *new_entry, **cur_entry;
@ -437,6 +515,8 @@ enum ud3tn_result router_add_bundle_to_contact(
if (new_entry == NULL)
return UD3TN_FAIL;
new_entry->data = b;
new_entry->frag_offset = frag_offset;
new_entry->frag_length = frag_length;
new_entry->next = NULL;
cur_entry = &contact->contact_bundles;
/* Go to end of list (=> FIFO) */
@ -453,7 +533,11 @@ enum ud3tn_result router_add_bundle_to_contact(
if (contact->remaining_capacity_p0 == INT32_MAX)
return UD3TN_OK;
const size_t bundle_size = bundle_get_serialized_size(b);
const size_t bundle_size = get_serialized_size_frag(
b,
frag_offset,
frag_length
);
const enum bundle_routing_priority prio =
bundle_get_routing_priority(b);
@ -467,7 +551,8 @@ enum ud3tn_result router_add_bundle_to_contact(
}
enum ud3tn_result router_remove_bundle_from_contact(
struct contact *contact, struct bundle *bundle)
struct contact *contact, struct bundle *bundle,
uint64_t frag_offset, uint64_t frag_length)
{
struct routed_bundle_list **cur_entry, *tmp;
@ -478,7 +563,10 @@ enum ud3tn_result router_remove_bundle_from_contact(
/* Find bundle */
while (*cur_entry != NULL) {
ASSERT((*cur_entry)->data != NULL);
if ((*cur_entry)->data == bundle) {
if ((*cur_entry)->data == bundle &&
(*cur_entry)->frag_offset == frag_offset &&
(*cur_entry)->frag_length == frag_length
) {
tmp = *cur_entry;
*cur_entry = (*cur_entry)->next;
free(tmp);
@ -486,8 +574,11 @@ enum ud3tn_result router_remove_bundle_from_contact(
if (contact->remaining_capacity_p0 == INT32_MAX)
continue;
const size_t bundle_size =
bundle_get_serialized_size(bundle);
const size_t bundle_size = get_serialized_size_frag(
bundle,
frag_offset,
frag_length
);
const enum bundle_routing_priority prio =
bundle_get_routing_priority(bundle);

View file

@ -0,0 +1,587 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "routing/compat/config_parser.h"
#include "routing/compat/contact_manager.h"
#include "routing/compat/router_agent.h"
#include "ud3tn/agent_manager.h"
#include "ud3tn/bundle_processor.h"
#include "ud3tn/common.h"
#include "ud3tn/eid.h"
#include "platform/hal_io.h"
#include "platform/hal_queue.h"
#include "platform/hal_semaphore.h"
#include "platform/hal_time.h"
#include "platform/hal_types.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static struct config_parser parser;
struct router_agent_params {
const char *aap2_admin_secret;
bool allow_remote_configuration;
struct contact_manager_params cm_param;
};
// BUNDLE HANDLING
struct bundle_processing_result {
int32_t status_or_fragments;
struct bundle *fragments[ROUTER_MAX_FRAGMENTS];
};
#define BUNDLE_RESULT_NO_ROUTE 0
#define BUNDLE_RESULT_NO_TIMELY_CONTACTS -1
#define BUNDLE_RESULT_NO_MEMORY -2
#define BUNDLE_RESULT_INVALID -3
#define BUNDLE_RESULT_EXPIRED -4
static void hand_over_contact_bundles(
struct contact *const contact,
struct router_agent_params *const ra_param,
const void *const bp_context)
{
(void)ra_param;
LOGF_DEBUG(
"RouterAgent: Dispatching bundles for contact with \"%s\".",
contact->node->eid
);
struct routed_bundle_list *rbl = contact->contact_bundles;
contact->contact_bundles = NULL;
while (rbl) {
struct dispatch_next_hop dnh = {
.node_id = contact->node->eid,
.fragment_offset = rbl->frag_offset,
.fragment_length = rbl->frag_length,
};
struct dispatch_result dr = {
.orig_reason = DISPATCH_REASON_NO_FIB_ENTRY,
.next_hop_count = 1,
.next_hops = &dnh,
};
rbl->data->forwarding_refcount--;
bundle_processor_execute_bdm_dispatch(
bp_context,
rbl->data,
&dr
);
struct routed_bundle_list *const tmp = rbl;
rbl = tmp->next;
free(tmp);
}
}
struct resched_func_param {
const void *bp_context;
struct router_agent_params *ra_param;
};
static void cra_bundle_resched_func(
void *const param,
struct bundle *bundle,
uint64_t frag_offset,
uint64_t frag_length)
{
struct resched_func_param *const rfp = param;
// NOTE that re-scheduling may be triggered by a dropped connection
// if there is a scheduled contact but it apparently ended earlier.
// In this case, we allow re-scheduling for the very same contact
// as it will try to re-connect. However, if there is a better contact,
// this one shall be used...
struct router_result route = router_get_resched_route(
bundle,
frag_offset,
frag_length
);
if (route.fragments == 0)
goto resched_failed;
ASSERT(route.fragment_results[0].payload_size == frag_length);
const enum ud3tn_result ratc_rv = router_add_bundle_to_contact(
route.fragment_results[0].contact,
bundle,
frag_offset,
frag_length
);
if (ratc_rv != UD3TN_OK) {
LOGF_WARN(
"RouterAgent: Failed to add bundle %p to contact",
bundle
);
goto resched_failed;
}
LOGF_DEBUG(
"RouterAgent: Added re-scheduled bundle %p [%llu, %llu] to contact at %llu",
bundle,
frag_offset,
frag_offset + frag_length,
route.fragment_results[0].contact->from_ms
);
if (route.fragment_results[0].contact->link_active) {
LOGF_DEBUG(
"RouterAgent: Issuing immediate dispatch for contact at %llu",
route.fragment_results[0].contact->from_ms
);
hand_over_contact_bundles(
route.fragment_results[0].contact,
rfp->ra_param,
rfp->bp_context
);
}
return;
resched_failed:
LOGF_DEBUG(
"RouterAgent: Bundle re-scheduling failed. Dropping bundle %p [%llu, %llu].",
bundle,
frag_offset,
frag_offset + frag_length
);
// Decrement the refcount as we incremented it also for
// the reference *we* kept (that was scheduled in the contact).
bundle->forwarding_refcount--;
struct dispatch_result dr = {
.orig_reason = DISPATCH_REASON_TX_FAILED,
.next_hop_count = 0,
.next_hops = NULL,
};
// NOTE that this function is typically called with the
// semaphore still held, so it must be ensured that no
// transitive dispatch request is processed.
bundle_processor_execute_bdm_dispatch(
rfp->bp_context,
bundle,
&dr
);
}
static void wake_up_contact_manager(QueueIdentifier_t cm_queue)
{
int cm_signal = 1;
// This never blocks and we ignore the return value: If there already
// is something in the queue, the CM is about to be triggered, which is
// what we want to achieve here.
hal_queue_try_push_to_back(cm_queue, &cm_signal, 0);
}
static void rx_callback(
struct bundle_adu data,
void *const param, const void *const bp_context)
{
struct router_agent_params *const ra_param = param;
if (!ra_param->allow_remote_configuration && !data.bdm_auth_validated) {
LOGF_DEBUG(
"RouterAgent: Dropped unauthorized config message from \"%s\"",
data.source
);
bundle_adu_free_members(data);
return;
}
config_parser_read(
&parser,
data.payload,
data.length
);
if (parser.basedata->status != PARSER_STATUS_DONE) {
LOGF_DEBUG(
"RouterAgent: Dropped invalid config message from \"%s\"",
data.source
);
config_parser_reset(&parser);
bundle_adu_free_members(data);
return;
}
struct router_command *const cmd = parser.router_command;
parser.router_command = NULL;
config_parser_reset(&parser);
bundle_adu_free_members(data);
hal_semaphore_take_blocking(ra_param->cm_param.semaphore);
bool success = true;
const uint64_t cur_time_s = hal_time_get_timestamp_s();
if (!node_prepare_and_verify(cmd->data, cur_time_s)) {
free_node(cmd->data);
LOGF_WARN("Router: Command (T = %c) is invalid!",
cmd->type);
free(cmd);
return;
}
struct resched_func_param rfp = {
.bp_context = bp_context,
.ra_param = ra_param,
};
struct rescheduling_handle rescheduler = {
.reschedule_func = cra_bundle_resched_func,
.reschedule_func_context = &rfp,
};
switch (cmd->type) {
case ROUTER_COMMAND_ADD:
LOGF_INFO(
"RouterAgent: Processing ADD command for node \"%s\"",
cmd->data->eid
);
success = routing_table_add_node(
cmd->data,
rescheduler
);
break;
case ROUTER_COMMAND_UPDATE:
LOGF_INFO(
"RouterAgent: Processing UPDATE command for node \"%s\"",
cmd->data->eid
);
success = routing_table_replace_node(
cmd->data,
rescheduler
);
break;
case ROUTER_COMMAND_DELETE:
LOGF_INFO(
"RouterAgent: Processing DELETE command for node \"%s\"",
cmd->data->eid
);
success = routing_table_delete_node(
cmd->data,
rescheduler
);
break;
default:
free_node(cmd->data);
success = false;
break;
}
hal_semaphore_release(ra_param->cm_param.semaphore);
if (success) {
LOGF_INFO(
"Router: Command (T = %c) processed.",
cmd->type
);
wake_up_contact_manager(ra_param->cm_param.control_queue);
} else {
LOGF_INFO(
"Router: Processing command (T = %c) failed!",
cmd->type
);
}
free(cmd);
}
static void fib_callback(
const struct fib_entry *const entry,
const char *node_id,
void *param, const void *bp_context)
{
struct router_agent_params *const ra_param = param;
hal_semaphore_take_blocking(ra_param->cm_param.semaphore);
const uint64_t cur_time_ms = hal_time_get_timestamp_ms();
struct resched_func_param rfp = {
.bp_context = bp_context,
.ra_param = ra_param,
};
struct rescheduling_handle rescheduler = {
.reschedule_func = cra_bundle_resched_func,
.reschedule_func_context = &rfp,
};
struct node *node = routing_table_lookup_node(node_id);
if (!node) {
LOGF_DEBUG(
"RouterAgent: Ignoring link update for unknown node ID \"%s\"",
node_id
);
hal_semaphore_release(ra_param->cm_param.semaphore);
return;
}
struct contact_list *cl = node->contacts;
if (entry->status == FIB_LINK_STATUS_ACTIVE) {
// Determine the contact that became active and trigger the
// bundle transmissions.
while (cl) {
if (cl->data->from_ms <= cur_time_ms &&
cl->data->to_ms >= cur_time_ms
) {
cl->data->link_active = true;
hand_over_contact_bundles(
cl->data,
ra_param,
bp_context
);
} else if (cl->data->from_ms > cur_time_ms) {
// The list is ordered - break here.
break;
}
cl = cl->next;
}
} else if (entry->status == FIB_LINK_STATUS_TEARDOWN) {
// For all contacts with the node that are still present but
// expired, execute routing_table_contact_passed.
while (cl) {
if (cl->data->to_ms > cur_time_ms) {
cl->data->link_active = false;
// NOTE: This frees `cl`!
routing_table_contact_passed(
cl->data,
rescheduler
);
// Re-init cl
cl = node->contacts;
continue;
} else if (cl->data->from_ms > cur_time_ms) {
// The list is ordered - break here.
break;
}
cl = cl->next;
}
} else {
LOGF_DEBUG(
"RouterAgent: Ignoring link update with status %d",
entry->status
);
}
hal_semaphore_release(ra_param->cm_param.semaphore);
}
static bool bdm_callback(
struct bundle *const bundle,
enum bundle_dispatch_reason reason,
const char *orig_node_id,
const char *orig_cla_addr,
void *param, const void *bp_context)
{
struct router_agent_params *const ra_param = param;
// Other reasons are currently unsupported and we drop the bundle.
if (reason != DISPATCH_REASON_NO_FIB_ENTRY)
return false;
(void)orig_node_id;
(void)orig_cla_addr;
(void)bp_context;
ASSERT(bundle != NULL);
const uint64_t timestamp_ms = hal_time_get_timestamp_ms();
if (bundle_get_expiration_time_ms(bundle) < timestamp_ms) {
// Bundle is already expired on arrival at the router...
return false;
}
hal_semaphore_take_blocking(ra_param->cm_param.semaphore);
struct router_result route = router_get_first_route(bundle);
uint64_t cur_offset = 0;
for (int i = 0; i < route.fragments; i++) {
const enum ud3tn_result ratc_rv = router_add_bundle_to_contact(
route.fragment_results[i].contact,
bundle,
cur_offset,
route.fragment_results[i].payload_size
);
if (ratc_rv != UD3TN_OK) {
// Remove the already-scheduled fragments again in case
// of failure.
for (int j = i - 1; j >= 0; j--) {
cur_offset -= (
route.fragment_results[j].payload_size
);
router_remove_bundle_from_contact(
route.fragment_results[j].contact,
bundle,
cur_offset,
route.fragment_results[j].payload_size
);
bundle->forwarding_refcount--;
}
LOGF_WARN("RouterAgent: Failed to add bundle %p to contact",
bundle);
break;
}
bundle->forwarding_refcount++;
LOGF_DEBUG(
"RouterAgent: Added fragment of bundle %p [%llu, %llu] to contact at %llu",
bundle,
cur_offset,
cur_offset + route.fragment_results[i].payload_size,
route.fragment_results[i].contact->from_ms
);
if (route.fragment_results[i].contact->link_active) {
LOGF_DEBUG(
"RouterAgent: Issuing immediate dispatch for contact at %llu",
route.fragment_results[i].contact->from_ms
);
hand_over_contact_bundles(
route.fragment_results[i].contact,
ra_param,
bp_context
);
}
cur_offset += route.fragment_results[i].payload_size;
}
hal_semaphore_release(ra_param->cm_param.semaphore);
LOGF_DEBUG(
"RouterAgent: Bundle %p [ %s ] [ frag = %d ]",
bundle,
(route.fragments < 1) ? "ERR" : "OK",
route.fragments
);
return route.fragments != 0 ? true : false;
}
int compat_router_agent_setup(
const struct bundle_agent_interface *bai,
bool allow_remote_configuration,
const char *aap2_admin_secret)
{
const int is_ipn = get_eid_scheme(bai->local_eid) == EID_SCHEME_IPN;
struct router_agent_params *const ra_param = malloc(
sizeof(struct router_agent_params)
);
if (!ra_param) {
LOG_ERROR("RouterAgent: Memory allocation failed!");
return -1;
}
ra_param->aap2_admin_secret = aap2_admin_secret;
ra_param->allow_remote_configuration = allow_remote_configuration;
struct parser *const config_parser_base = config_parser_init(&parser);
if (!config_parser_base) {
LOG_ERROR("RouterAgent: Could not initialize config parser!");
free(ra_param);
return -1;
}
if (routing_table_init() != UD3TN_OK) {
LOG_ERROR("RouterAgent: Could not initialize routing table!");
free(ra_param);
return -1;
}
// NOTE: Compared to v0.13, the Contact Manager only starts and
// terminates contacts (issuing the relevant FIB commands). Handing
// over bundles to the BP for dispatch is done in response to the
// FIB callback.
ra_param->cm_param = contact_manager_start(
bai->bundle_signaling_queue,
routing_table_get_raw_contact_list_ptr()
);
if (ra_param->cm_param.task_creation_result != UD3TN_OK) {
LOG_ERROR("RouterAgent: Failed to start Contact Manager!");
free(ra_param);
return -1;
}
const struct agent agent = {
.auth_trx = true,
.auth_fib = true,
.auth_bdm = true,
.is_subscriber = true,
.sink_identifier = (
is_ipn
? AGENT_ID_CONFIG_IPN
: AGENT_ID_CONFIG_DTN
),
.trx_callback = rx_callback,
.fib_callback = fib_callback,
.bdm_callback = bdm_callback,
.param = ra_param,
.secret = aap2_admin_secret,
};
const int rv = bundle_processor_perform_agent_action_async(
bai->bundle_signaling_queue,
BP_SIGNAL_AGENT_REGISTER,
agent
);
if (rv) {
LOG_ERROR("RouterAgent: BP failed to register SUB agent!");
free(ra_param);
config_parser_reset(&parser);
return rv;
}
const struct agent agent_rpc = {
.auth_trx = false,
.auth_fib = true,
.auth_bdm = true,
.is_subscriber = false,
.sink_identifier = (
is_ipn
? AGENT_ID_CONFIG_IPN
: AGENT_ID_CONFIG_DTN
),
.secret = aap2_admin_secret,
};
const int rv_rpc = bundle_processor_perform_agent_action_async(
bai->bundle_signaling_queue,
BP_SIGNAL_AGENT_REGISTER,
agent_rpc
);
if (rv_rpc) {
LOG_ERROR("RouterAgent: BP failed to register RPC agent!");
bundle_processor_perform_agent_action_async(
bai->bundle_signaling_queue,
BP_SIGNAL_AGENT_DEREGISTER,
agent
);
free(ra_param);
return rv_rpc;
}
return 0;
}

View file

@ -1,235 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "ud3tn/bundle.h"
#include "ud3tn/bundle_fragmenter.h"
#include "ud3tn/common.h"
#include "ud3tn/node.h"
#include "ud3tn/router.h"
#include "ud3tn/routing_table.h"
#include "platform/hal_io.h"
#include "platform/hal_time.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
// COMMAND HANDLING
static bool process_router_command(
struct router_command *router_cmd,
struct rescheduling_handle rescheduler)
{
switch (router_cmd->type) {
case ROUTER_COMMAND_ADD:
return routing_table_add_node(
router_cmd->data,
rescheduler
);
case ROUTER_COMMAND_UPDATE:
return routing_table_replace_node(
router_cmd->data,
rescheduler
);
case ROUTER_COMMAND_DELETE:
return routing_table_delete_node(
router_cmd->data,
rescheduler
);
default:
free_node(router_cmd->data);
return false;
}
}
enum ud3tn_result router_process_command(
struct router_command *command,
struct rescheduling_handle rescheduler)
{
bool success = true;
const uint64_t cur_time_s = hal_time_get_timestamp_s();
if (!node_prepare_and_verify(command->data, cur_time_s)) {
free_node(command->data);
LOGF_WARN("Router: Command (T = %c) is invalid!",
command->type);
free(command);
return UD3TN_FAIL;
}
success = process_router_command(
command,
rescheduler
);
if (success) {
LOGF_DEBUG(
"Router: Command (T = %c) processed.",
command->type
);
} else {
LOGF_DEBUG(
"Router: Processing command (T = %c) failed!",
command->type
);
}
free(command);
return success ? UD3TN_OK : UD3TN_FAIL;
}
// BUNDLE HANDLING
struct bundle_processing_result {
int32_t status_or_fragments;
struct bundle *fragments[ROUTER_MAX_FRAGMENTS];
};
#define BUNDLE_RESULT_NO_ROUTE 0
#define BUNDLE_RESULT_NO_TIMELY_CONTACTS -1
#define BUNDLE_RESULT_NO_MEMORY -2
#define BUNDLE_RESULT_INVALID -3
#define BUNDLE_RESULT_EXPIRED -4
static inline enum router_result_status br_to_rrs(int8_t bh_result)
{
switch (bh_result) {
case BUNDLE_RESULT_NO_ROUTE:
return ROUTER_RESULT_NO_ROUTE;
case BUNDLE_RESULT_NO_MEMORY:
return ROUTER_RESULT_NO_MEMORY;
case BUNDLE_RESULT_EXPIRED:
return ROUTER_RESULT_EXPIRED;
case BUNDLE_RESULT_NO_TIMELY_CONTACTS:
default:
return ROUTER_RESULT_NO_TIMELY_CONTACTS;
}
}
static struct bundle_processing_result apply_fragmentation(
struct bundle *bundle, struct router_result route);
static struct bundle_processing_result process_bundle(struct bundle *bundle)
{
struct router_result route;
struct bundle_processing_result result = {
.status_or_fragments = BUNDLE_RESULT_NO_ROUTE
};
ASSERT(bundle != NULL);
const uint64_t timestamp_ms = hal_time_get_timestamp_ms();
if (bundle_get_expiration_time_ms(bundle) < timestamp_ms) {
// Bundle is already expired on arrival at the router...
result.status_or_fragments = BUNDLE_RESULT_EXPIRED;
return result;
}
route = router_get_first_route(bundle);
if (route.fragments == 1) {
result.fragments[0] = bundle;
if (router_add_bundle_to_contact(
route.fragment_results[0].contact,
bundle) == UD3TN_OK)
result.status_or_fragments = 1;
else
result.status_or_fragments = BUNDLE_RESULT_NO_MEMORY;
} else if (route.fragments && !bundle_must_not_fragment(bundle)) {
// Only fragment if it is allowed -- if not, there is no route.
result = apply_fragmentation(bundle, route);
}
return result;
}
static struct bundle_processing_result apply_fragmentation(
struct bundle *bundle, struct router_result route)
{
struct bundle *frags[ROUTER_MAX_FRAGMENTS];
uint32_t size;
int32_t f, g;
int32_t fragments = route.fragments;
struct bundle_processing_result result = {
.status_or_fragments = BUNDLE_RESULT_NO_MEMORY
};
/* Create fragments */
frags[0] = bundlefragmenter_initialize_first_fragment(bundle);
if (frags[0] == NULL)
return result;
for (f = 0; f < fragments - 1; f++) {
/* Determine minimal fragmented bundle size */
if (f == 0)
size = bundle_get_first_fragment_min_size(bundle);
else
size = bundle_get_mid_fragment_min_size(bundle);
frags[f + 1] = bundlefragmenter_fragment_bundle(frags[f],
size + route.fragment_results[f].payload_size);
if (frags[f + 1] == NULL) {
for (g = 0; g <= f; g++)
bundle_free(frags[g]);
return result;
} else if (frags[f] == frags[f + 1]) {
// Not fragmented b/c not needed - the router does some
// conservative estimations regarding size of CBOR ints
// that may lead to fewer actual fragments here.
// Just update the count accordingly and do not schedule
// the rest.
fragments = f + 1;
route.fragments = fragments;
frags[fragments] = NULL;
break;
}
}
/* Add to route */
for (f = 0; f < fragments; f++) {
if (router_add_bundle_to_contact(
route.fragment_results[f].contact,
frags[f]) != UD3TN_OK) {
LOGF_INFO(
"Router: Scheduling bundle %p failed, dropping all fragments.",
bundle
);
// Remove from all previously-scheduled routes
for (g = 0; g < f; g++)
router_remove_bundle_from_contact(
route.fragment_results[g].contact,
frags[g]
);
// Drop _all_ fragments
for (g = 0; g < fragments; g++)
bundle_free(frags[g]);
return result;
}
}
/* Success - remove bundle */
bundle_free(bundle);
for (f = 0; f < fragments; f++)
result.fragments[f] = frags[f];
result.status_or_fragments = fragments;
return result;
}
enum router_result_status router_route_bundle(struct bundle *b)
{
struct bundle_processing_result proc_result = {
.status_or_fragments = BUNDLE_RESULT_INVALID
};
if (b != NULL)
proc_result = process_bundle(b);
LOGF_DEBUG(
"Router: Bundle %p [ %s ] [ frag = %d ]",
b,
(proc_result.status_or_fragments < 1) ? "ERR" : "OK",
proc_result.status_or_fragments
);
if (proc_result.status_or_fragments < 1)
return br_to_rrs(proc_result.status_or_fragments);
return ROUTER_RESULT_OK;
}

View file

@ -1,9 +1,10 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "routing/compat/node.h"
#include "routing/compat/router.h"
#include "routing/compat/routing_table.h"
#include "ud3tn/bundle.h"
#include "ud3tn/common.h"
#include "ud3tn/node.h"
#include "ud3tn/router.h"
#include "ud3tn/routing_table.h"
#include "ud3tn/simplehtab.h"
#include <stdbool.h>
@ -87,23 +88,6 @@ struct node_table_entry *routing_table_lookup_eid(const char *eid)
}
uint8_t routing_table_lookup_hot_node(
struct node **target, uint8_t max)
{
struct node_list *cur = node_list;
uint8_t c = 0;
while (cur != NULL) {
if (HAS_FLAG(cur->node->flags, NODE_FLAG_INTERNET_ACCESS)) {
target[c] = cur->node;
if (++c == max)
break;
}
cur = cur->next;
}
return c;
}
/* NODE LIST MODIFICATION */
static void add_node_to_tables(struct node *node);
static void remove_node_from_tables(struct node *node, bool drop_contacts,
@ -235,7 +219,7 @@ bool routing_table_delete_node(
{
struct node_list **entry_ptr, *old_node_entry;
struct node *cur_node;
struct contact_list *modified = NULL, *deleted = NULL, *next, *tmp;
struct contact_list *modified = NULL, *deleted = NULL, *next;
entry_ptr = get_node_entry_ptr_by_eid(new_node->eid);
if (entry_ptr != NULL) {
@ -258,6 +242,8 @@ bool routing_table_delete_node(
cur_node->contacts = contact_list_difference(
cur_node->contacts, new_node->contacts,
&modified, &deleted);
/* Add node again before re-scheduling bundles */
add_node_to_tables(cur_node);
/* Process modified contacts */
while (modified != NULL) {
reschedule_bundles(
@ -270,15 +256,8 @@ bool routing_table_delete_node(
while (deleted != NULL) {
reschedule_bundles(
deleted->data, rescheduler);
if (deleted->data->active) {
tmp = deleted;
deleted = tmp->next;
free(tmp);
} else {
deleted = contact_list_free(deleted);
}
deleted = contact_list_free(deleted);
}
add_node_to_tables(cur_node);
free_node(new_node);
}
return true;
@ -349,16 +328,6 @@ static void remove_node_from_tables(struct node *node, bool drop_contacts,
if (drop_contacts) {
reschedule_bundles(cur_contact->data,
rescheduler);
// If the contact is active, un-associate it to prevent
// freeing it right now.
if (cur_contact->data->active) {
cur_contact->data->node = NULL;
*cur_slot = cur_contact->next;
free(cur_contact);
// List item was replaced by next item,
// process this one now...
continue;
}
}
cur_slot = &(*cur_slot)->next;
}
@ -486,8 +455,10 @@ void routing_table_contact_passed(
if (contact->node != NULL) {
while (contact->contact_bundles != NULL) {
rescheduler.reschedule_func(
rescheduler.reschedule_func_context,
contact->contact_bundles->data,
rescheduler.reschedule_func_context
contact->contact_bundles->frag_offset,
contact->contact_bundles->frag_length
);
tmp = contact->contact_bundles->next;
free(contact->contact_bundles);
@ -502,19 +473,27 @@ void routing_table_contact_passed(
static void reschedule_bundles(
struct contact *contact, struct rescheduling_handle rescheduler)
{
struct bundle *b;
ASSERT(contact != NULL);
if (!contact)
return;
/* Empty the bundle list and queue them in for re-scheduling */
while (contact->contact_bundles != NULL) {
b = contact->contact_bundles->data;
router_remove_bundle_from_contact(contact, b);
struct bundle *const bdl = contact->contact_bundles->data;
const uint64_t f_offset = contact->contact_bundles->frag_offset;
const uint64_t f_length = contact->contact_bundles->frag_length;
router_remove_bundle_from_contact(
contact,
bdl,
f_offset,
f_length
);
rescheduler.reschedule_func(
b,
rescheduler.reschedule_func_context
rescheduler.reschedule_func_context,
bdl,
f_offset,
f_length
);
}
}

View file

@ -61,6 +61,11 @@ struct bp_context {
} *known_bundle_list;
};
struct fib_update_params {
const char *cla_addr;
struct bp_context *bp_context;
};
/* DECLARATIONS */
static inline void handle_signal(
@ -70,6 +75,9 @@ static inline void handle_signal(
static bool send_fib_to_agent(
void *context, const char *node_id,
const struct fib_entry *link);
static bool send_fib_updates_to_agent(
void *param, const char *node_id,
const struct fib_entry *link);
static enum ud3tn_result bundle_dispatch(
struct bp_context *const ctx, struct bundle *bundle);
@ -305,6 +313,7 @@ static inline void handle_signal(
struct agent_manager_parameters *aaps;
agent_no_t agent_feedback;
struct fib_entry *fib_entry;
struct fib_update_params fup = { .bp_context = ctx };
struct bundle *bundle;
switch (signal.type) {
@ -321,13 +330,14 @@ static inline void handle_signal(
} else {
bundle = signal.bundle;
}
bundle->forwarding_refcount--;
LOGF_DEBUG(
"BundleProcessor: TX of bundle %p to %s via %s OK",
"BundleProcessor: TX of bundle %p to %s via %s OK (-> %d references)",
bundle,
signal.peer_node_id,
signal.peer_cla_addr
signal.peer_cla_addr,
bundle->forwarding_refcount
);
bundle->forwarding_refcount--;
// If the handover fails, declare success immediately.
if (agent_handover_to_dispatch(
ctx->agent_manager,
@ -351,13 +361,14 @@ static inline void handle_signal(
} else {
bundle = signal.bundle;
}
bundle->forwarding_refcount--;
LOGF_DEBUG(
"BundleProcessor: TX of bundle %p to %s via %s FAILED",
"BundleProcessor: TX of bundle %p to %s via %s FAILED (-> %d references)",
bundle,
signal.peer_node_id,
signal.peer_cla_addr
signal.peer_cla_addr,
bundle->forwarding_refcount
);
bundle->forwarding_refcount--;
if (agent_handover_to_dispatch(
ctx->agent_manager,
bundle,
@ -414,7 +425,8 @@ static inline void handle_signal(
);
fib_entry = fib_insert_link(ctx->fib, signal.peer_cla_addr);
fib_entry->status = FIB_LINK_STATUS_ACTIVE;
agent_send_fib_info(ctx->agent_manager, fib_entry, NULL, ctx);
fup.cla_addr = fib_entry->cla_addr;
fib_foreach(ctx->fib, send_fib_updates_to_agent, &fup);
free(signal.peer_cla_addr);
break;
case BP_SIGNAL_LINK_DOWN:
@ -422,17 +434,13 @@ static inline void handle_signal(
"BundleProcessor: Marking link to CLA address \"%s\" as inactive",
signal.peer_cla_addr
);
fib_remove_cla_addr(ctx->fib, signal.peer_cla_addr);
fib_entry = malloc(sizeof(struct fib_entry));
ASSERT(fib_entry != NULL);
if (fib_entry == NULL)
break;
// allocation ownership moved
fib_entry->cla_addr = signal.peer_cla_addr;
fib_entry = fib_insert_link(ctx->fib, signal.peer_cla_addr);
fib_entry->status = FIB_LINK_STATUS_TEARDOWN;
fib_entry->flags = FIB_LINK_FLAG_NONE;
agent_send_fib_info(ctx->agent_manager, fib_entry, NULL, ctx);
free(fib_entry);
fup.cla_addr = fib_entry->cla_addr;
fib_foreach(ctx->fib, send_fib_updates_to_agent, &fup);
// TODO: This drops the flags associated with the entry. We
// should associate the flags with the node, not the CLA addr.
fib_remove_cla_addr(ctx->fib, signal.peer_cla_addr);
free(signal.peer_cla_addr);
break;
case BP_SIGNAL_BUNDLE_BDM_DISPATCH:
@ -689,6 +697,26 @@ static bool send_fib_to_agent(void *context, const char *node_id,
return true;
}
static bool send_fib_updates_to_agent(
void *param, const char *node_id,
const struct fib_entry *link)
{
struct fib_update_params *p = param;
// TODO: Make this more efficient, e.g., by putting a mapping of
// CLA address -> EIDs pointing to it into the FIB.
if (strcmp(link->cla_addr, p->cla_addr) == 0) {
agent_send_fib_info(
p->bp_context->agent_manager,
link,
node_id,
p->bp_context
);
}
return true;
}
/* BUNDLE HANDLING */
/* 5.3 */
@ -1332,6 +1360,7 @@ static void bundle_delete(
/* 5.15 (BPv7-bis) */
static void bundle_discard(struct bundle *bundle)
{
LOGF_DEBUG("BundleProcessor: Discarding bundle %p", bundle);
bundle_drop(bundle);
}

View file

@ -58,6 +58,7 @@ const struct ud3tn_cmdline_options *parse_cmdline(int argc, char *argv[])
result->aap2_socket = NULL;
result->aap2_bdm_secret = NULL;
result->bundle_version = DEFAULT_BUNDLE_VERSION;
result->external_dispatch = false;
result->status_reporting = false;
result->allow_remote_configuration = false;
result->exit_immediately = false;
@ -69,7 +70,7 @@ const struct ud3tn_cmdline_options *parse_cmdline(int argc, char *argv[])
result->eid = NULL;
result->cla_options = NULL;
const char *GETOPT_SHORTOPTS = ":a:b:c:e:l:L:m:p:s:S:x:rRhu";
const char *GETOPT_SHORTOPTS = ":a:b:c:e:l:L:m:p:s:S:x:rRhud";
int option_index = 0;
if (!argv || argc <= 1)
@ -100,6 +101,9 @@ const struct ud3tn_cmdline_options *parse_cmdline(int argc, char *argv[])
}
result->cla_options = strdup(optarg);
break;
case 'd':
result->external_dispatch = true;
break;
case 'e':
if (!optarg || validate_local_eid(optarg) != UD3TN_OK ||
strcmp("dtn:none", optarg) == 0) {
@ -261,6 +265,7 @@ static void shorten_long_cli_options(const int argc, char *argv[])
{"--bp-version", "-b"},
{"--cla", "-c"},
{"--eid", "-e"},
{"--external-dispatch", "-d"},
{"--help", "-h"},
{"--lifetime", "-l"},
{"--max-bundle-size", "-m"},
@ -287,7 +292,8 @@ static void print_usage_text(void)
const char *usage_text = "Usage: ud3tn\n"
" [-a HOST, --aap-host HOST] [-p PORT, --aap-port PORT]\n"
" [-b 6|7, --bp-version 6|7] [-c CLA_OPTIONS, --cla CLA_OPTIONS]\n"
" [-e EID, --eid EID] [-h, --help] [-l SECONDS, --lifetime SECONDS]\n"
" [-d, --external-dispatch] [-e EID, --eid EID]\n"
" [-h, --help] [-l SECONDS, --lifetime SECONDS]\n"
" [-m BYTES, --max-bundle-size BYTES] [-r, --status-reports]\n"
" [-R, --allow-remote-config] [-L " LOG_LEVELS ", --log-level " LOG_LEVELS "]\n"
" [-s PATH --aap-socket PATH] [-S PATH --aap2-socket PATH]\n"
@ -305,6 +311,7 @@ static void print_help_text(void)
" -b, --bp-version 6|7 bundle protocol version of bundles created via AAP\n"
" -c, --cla CLA_OPTIONS configure the CLA subsystem according to the\n"
" syntax documented in the man page\n"
" -d, --external-dispatch do not load the internal minimal router, allow for using an AAP 2.0 BDM\n"
" -e, --eid EID local endpoint identifier\n"
" -h, --help print this text and exit\n"
" -l, --lifetime SECONDS lifetime of bundles created via AAP\n"

View file

@ -12,6 +12,8 @@
#include "cla/cla.h"
#include "routing/compat/router_agent.h"
#include "platform/hal_io.h"
#include "platform/hal_platform.h"
#include "platform/hal_queue.h"
@ -167,6 +169,19 @@ void start_tasks(const struct ud3tn_cmdline_options *const opt)
abort();
}
if (!opt->external_dispatch) {
const int cra_rv = compat_router_agent_setup(
&bundle_agent_interface,
opt->allow_remote_configuration,
opt->aap2_bdm_secret
);
if (cra_rv) {
LOG_ERROR("INIT: Router could not be initialized!");
abort();
}
}
daemon_mode = true;
}

View file

@ -25,6 +25,9 @@ new bundles
provides parameters to the available CLA subsystem according to the
syntax documented below
.TP
-d, --external-dispatch
do not load the internal minimal router, allow for using an AAP 2.0 BDM
.TP
-e, --eid EID
the EID (node ID) which is used by the started ud3tn instance itself
.TP

View file

@ -1,33 +0,0 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifndef CONFIGAGENT_H_INCLUDED
#define CONFIGAGENT_H_INCLUDED
#include "platform/hal_types.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define CONFIG_AGENT_QUEUE_SIZE 100
#define CONFIG_AGENT_TASK_PRIORITY 2
// Default Agent IDs.
#ifndef AGENT_ID_CONFIG_DTN
#define AGENT_ID_CONFIG_DTN "config"
#endif // AGENT_ID_CONFIG_DTN
#ifndef AGENT_ID_CONFIG_IPN
#define AGENT_ID_CONFIG_IPN "9000"
#endif // AGENT_ID_CONFIG_IPN
struct config_agent_item {
uint8_t *data;
size_t data_length;
};
int config_agent_setup(
QueueIdentifier_t bundle_processor_signaling_queue,
const char *local_eid,
bool allow_remote_configuration,
void *bundle_processor_context);
#endif /* CONFIGAGENT_H_INCLUDED */

View file

@ -1,10 +1,11 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifndef CONFIGPARSER_H_INCLUDED
#define CONFIGPARSER_H_INCLUDED
#ifndef RTCOMPAT_CONFIGPARSER_H_INCLUDED
#define RTCOMPAT_CONFIGPARSER_H_INCLUDED
#include "ud3tn/parser.h"
#include "ud3tn/result.h"
#include "ud3tn/router.h"
#include "routing/compat/router.h"
#include <stdint.h>
@ -39,8 +40,6 @@ enum config_parser_stage {
struct config_parser {
struct parser *basedata;
void (*send_callback)(void *, struct router_command *);
void *send_param;
enum config_parser_stage stage;
struct router_command *router_command;
int current_index;
@ -49,11 +48,9 @@ struct config_parser {
struct contact_list *current_contact;
};
struct parser *config_parser_init(
struct config_parser *parser,
void (*send_callback)(void *, struct router_command *), void *param);
struct parser *config_parser_init(struct config_parser *parser);
size_t config_parser_read(struct config_parser *parser,
const uint8_t *buffer, size_t length);
enum ud3tn_result config_parser_reset(struct config_parser *parser);
#endif /* CONFIGPARSER_H_INCLUDED */
#endif // RTCOMPAT_CONFIGPARSER_H_INCLUDED

View file

@ -1,9 +1,10 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifndef CONTACTMANAGER_H_INCLUDED
#define CONTACTMANAGER_H_INCLUDED
#ifndef RTCOMPAT_CONTACTMANAGER_H_INCLUDED
#define RTCOMPAT_CONTACTMANAGER_H_INCLUDED
#include "ud3tn/common.h"
#include "ud3tn/node.h"
#include "routing/compat/node.h"
#include "platform/hal_types.h"
@ -20,16 +21,8 @@ struct contact_manager_params {
QueueIdentifier_t control_queue;
};
/* Flags what should be checked */
enum contact_manager_signal {
CM_SIGNAL_NONE = 0x0,
CM_SIGNAL_UPDATE_CONTACT_LIST = 0x1,
CM_SIGNAL_PROCESS_CURRENT_BUNDLES = 0x2,
CM_SIGNAL_UNKNOWN = 0x3
};
struct contact_manager_params contact_manager_start(
QueueIdentifier_t bp_queue,
struct contact_list **clistptr);
#endif /* CONTACTMANAGER_H_INCLUDED */
#endif // RTCOMPAT_CONTACTMANAGER_H_INCLUDED

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifndef NODE_H_INCLUDED
#define NODE_H_INCLUDED
#ifndef RTCOMPAT_NODE_H_INCLUDED
#define RTCOMPAT_NODE_H_INCLUDED
#include "ud3tn/bundle.h"
#include "ud3tn/result.h"
@ -9,6 +9,8 @@
struct routed_bundle_list {
struct bundle *data;
uint64_t frag_offset;
uint64_t frag_length;
struct routed_bundle_list *next;
};
@ -21,9 +23,9 @@ struct contact {
int32_t remaining_capacity_p0;
int32_t remaining_capacity_p1;
int32_t remaining_capacity_p2;
bool link_active;
struct endpoint_list *contact_endpoints;
struct routed_bundle_list *contact_bundles;
int8_t active;
};
struct contact_list {
@ -93,4 +95,4 @@ int add_contact_to_ordered_list(
int remove_contact_from_list(
struct contact_list **list, struct contact *contact);
#endif // NODE_H_INCLUDED
#endif // RTCOMPAT_NODE_H_INCLUDED

View file

@ -1,21 +1,22 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifndef ROUTER_H_INCLUDED
#define ROUTER_H_INCLUDED
#ifndef RTCOMPAT_ROUTER_H_INCLUDED
#define RTCOMPAT_ROUTER_H_INCLUDED
#include "platform/hal_types.h"
#include "ud3tn/bundle.h"
#include "ud3tn/common.h"
#include "ud3tn/contact_manager.h"
#include "ud3tn/node.h"
#include "ud3tn/routing_table.h"
#include "routing/compat/contact_manager.h"
#include "routing/compat/node.h"
#include "routing/compat/routing_table.h"
#include <stddef.h>
#include <stdint.h>
// Maximum number of fragments created by the router.
#ifndef ROUTER_MAX_FRAGMENTS
#define ROUTER_MAX_FRAGMENTS 10
#define ROUTER_MAX_FRAGMENTS 512
#endif // ROUTER_MAX_FRAGMENTS
// Default maximum bundle size.
@ -28,29 +29,20 @@
#define FRAGMENT_MIN_PAYLOAD 8
#endif // FRAGMENT_MIN_PAYLOAD
// Below this, the default route will be used
#ifndef ROUTER_MIN_CONTACTS_HTAB
#define ROUTER_MIN_CONTACTS_HTAB 10
#endif // ROUTER_MIN_CONTACTS_HTAB
struct router_config {
size_t global_mbs;
uint16_t fragment_min_payload;
uint8_t router_min_contacts_htab;
uint8_t router_min_contacts_nbf;
};
struct fragment_route {
uint32_t payload_size;
uint64_t payload_size;
struct contact *contact;
uint8_t preemption_improved;
};
/* With MAX_FRAGMENTS = 3 and MAX_CONTACTS = 5: 92 bytes on stack */
struct router_result {
struct fragment_route fragment_results[ROUTER_MAX_FRAGMENTS];
int32_t fragments;
uint8_t preemption_improved;
};
#define ROUTER_BUNDLE_PRIORITY(bundle) (bundle_get_routing_priority(bundle))
@ -62,19 +54,22 @@ void router_update_config(struct router_config config);
struct contact_list *router_lookup_destination(char *dest);
uint8_t router_calculate_fragment_route(
struct fragment_route *res, uint32_t size,
struct contact_list *contacts, uint32_t preprocessed_size,
struct fragment_route *res, uint64_t size,
struct contact_list *contacts, uint64_t preprocessed_size,
enum bundle_routing_priority priority, uint64_t exp_time,
struct contact **excluded_contacts, uint8_t excluded_contacts_count);
struct router_result router_get_first_route(struct bundle *bundle);
struct router_result router_try_reuse(
struct router_result route, struct bundle *bundle);
struct router_result router_get_resched_route(
struct bundle *bundle,
const uint64_t frag_offset, const uint64_t frag_length);
enum ud3tn_result router_add_bundle_to_contact(
struct contact *contact, struct bundle *b);
struct contact *contact, struct bundle *b,
uint64_t frag_offset, uint64_t frag_length);
enum ud3tn_result router_remove_bundle_from_contact(
struct contact *contact, struct bundle *bundle);
struct contact *contact, struct bundle *bundle,
uint64_t frag_offset, uint64_t frag_length);
/* BP-side API */
@ -91,23 +86,4 @@ struct router_command {
struct node *data;
};
struct bundle_tx_result {
char *peer_cla_addr;
struct bundle *bundle;
};
enum router_result_status {
ROUTER_RESULT_OK,
ROUTER_RESULT_NO_ROUTE,
ROUTER_RESULT_NO_TIMELY_CONTACTS,
ROUTER_RESULT_NO_MEMORY,
ROUTER_RESULT_EXPIRED,
};
enum ud3tn_result router_process_command(
struct router_command *command,
struct rescheduling_handle rescheduler);
enum router_result_status router_route_bundle(
struct bundle *b);
#endif /* ROUTER_H_INCLUDED */
#endif /* RTCOMPAT_ROUTER_H_INCLUDED */

View file

@ -0,0 +1,24 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifndef RTCOMPAT_ROUTER_AGENT_H_INCLUDED
#define RTCOMPAT_ROUTER_AGENT_H_INCLUDED
#include "ud3tn/bundle_processor.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
// Default Agent IDs.
#ifndef AGENT_ID_CONFIG_DTN
#define AGENT_ID_CONFIG_DTN "config"
#endif // AGENT_ID_CONFIG_DTN
#ifndef AGENT_ID_CONFIG_IPN
#define AGENT_ID_CONFIG_IPN "9000"
#endif // AGENT_ID_CONFIG_IPN
int compat_router_agent_setup(
const struct bundle_agent_interface *bundle_agent_interface,
bool allow_remote_configuration,
const char *aap2_admin_secret);
#endif // RTCOMPAT_ROUTER_AGENT_H_INCLUDED

View file

@ -1,11 +1,12 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#ifndef ROUTINGTABLE_H_INCLUDED
#define ROUTINGTABLE_H_INCLUDED
#ifndef RTCOMPAT_ROUTINGTABLE_H_INCLUDED
#define RTCOMPAT_ROUTINGTABLE_H_INCLUDED
#include "ud3tn/bundle.h"
#include "ud3tn/node.h"
#include "ud3tn/result.h"
#include "routing/compat/node.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@ -21,12 +22,14 @@ struct node_table_entry {
};
typedef void (*reschedule_func_t)(
struct bundle *,
const void *reschedule_func_context
void *context,
struct bundle *bundle,
uint64_t frag_offset,
uint64_t frag_length
);
struct rescheduling_handle {
reschedule_func_t reschedule_func;
const void *reschedule_func_context;
void *reschedule_func_context;
};
enum ud3tn_result routing_table_init(void);
@ -34,10 +37,6 @@ void routing_table_free(void);
struct node *routing_table_lookup_node(const char *eid);
struct node_table_entry *routing_table_lookup_eid(const char *eid);
uint8_t routing_table_lookup_eid_in_nbf(
char *eid, struct node **target, uint8_t max);
uint8_t routing_table_lookup_hot_node(
struct node **target, uint8_t max);
bool routing_table_add_node(
struct node *new_node, struct rescheduling_handle rescheduler);
@ -54,4 +53,4 @@ void routing_table_delete_contact(struct contact *contact);
void routing_table_contact_passed(
struct contact *contact, struct rescheduling_handle rescheduler);
#endif /* ROUTINGTABLE_H_INCLUDED */
#endif // RTCOMPAT_ROUTINGTABLE_H_INCLUDED

View file

@ -64,6 +64,7 @@ struct ud3tn_cmdline_options {
char *aap2_bdm_secret;
uint8_t bundle_version;
uint8_t log_level;
bool external_dispatch;
bool status_reporting;
bool allow_remote_configuration;
bool exit_immediately; // after parsing --help or --usage etc.

View file

@ -16,6 +16,7 @@ $(eval $(call addComponentWithRules,components/bundle7))
$(eval $(call addComponentWithRules,components/cla))
$(eval $(call addComponentWithRules,components/cla/$(PLATFORM)))
$(eval $(call addComponentWithRules,components/platform/$(PLATFORM)))
$(eval $(call addComponentWithRules,components/routing/compat))
$(eval $(call addComponentWithRules,components/spp))
$(eval $(call addComponentWithRules,components/ud3tn))

View file

@ -95,6 +95,12 @@ let
type = lib.types.str;
};
externalDispatch = lib.mkOption {
description = "Do not load the internal minimal router, allow for using an AAP 2.0 BDM.";
default = false;
type = lib.types.bool;
};
lifetime = lib.mkOption {
description = "Lifetime in seconds of bundles created via AAP.";
default = 86400;
@ -184,6 +190,7 @@ let
++ lib.optional (cfg.aap.host != null) "--aap-host ${cfg.aap.host}"
++ lib.optional (cfg.aap.port != null) "--aap-port ${toString cfg.aap.port}"
++ lib.optional cfg.allowRemoteConfig "--allow-remote-config"
++ lib.optional cfg.externalDispatch "--external-dispatch"
++ lib.optional cfg.statusReports "--status-reports"
);
};
@ -234,6 +241,7 @@ in
};
};
eid = "dtn://ud3tn-b.dtn/";
externalDispatch = true;
lifetime = 43200;
logLevel = 3;
maxBundleSize = 4294967295; # u32_max

View file

@ -57,6 +57,7 @@
logLevel = 3;
maxBundleSize = 4294967295; # u32_max
statusReports = true;
externalDispatch = true;
};
};
};

View file

@ -40,15 +40,9 @@ exit_handler() {
echo ">>> uD3TN1 LOGFILE"
cat "/tmp/ud3tn1.log" || true
echo
echo ">>> uD3TN1 DISP LOGFILE"
cat "/tmp/disp_ud3tn1.log" || true
echo
echo ">>> uD3TN2 LOGFILE"
cat "/tmp/ud3tn2.log" || true
echo
echo ">>> uD3TN2 DISP LOGFILE"
cat "/tmp/disp_ud3tn2.log" || true
echo
echo ">>> DTN7 LOGFILE"
cat "/tmp/dtn7.log" || true
echo
@ -63,20 +57,14 @@ trap exit_handler EXIT
# Start first uD3TN instance (uD3TN1)
echo "Starting first uD3TN instance ..."
"$UD3TN_DIR/build/posix/ud3tn" --eid "$UD3TN1_EID" --bp-version "$BP_VERSION" --aap-port 4242 -S "$UD3TN_DIR/ud3tn1.aap2.socket" --cla "sqlite:ud3tn1.sqlite;mtcp:127.0.0.1,4224" -L 4 > /tmp/ud3tn1.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" --eid "$UD3TN1_EID" --bp-version "$BP_VERSION" --aap-port 4242 -S "$UD3TN_DIR/ud3tn1.aap2.socket" --cla "sqlite:ud3tn1.sqlite;mtcp:127.0.0.1,4224" -L 4 --allow-remote-config > /tmp/ud3tn1.log 2>&1 &
UD3TN1_PID=$!
# Start second uD3TN instance (uD3TN2)
echo "Starting second uD3TN instance ..."
"$UD3TN_DIR/build/posix/ud3tn" --eid "$UD3TN2_EID" --bp-version "$BP_VERSION" --aap-port 4243 -S "$UD3TN_DIR/ud3tn2.aap2.socket" --cla "sqlite:ud3tn2.sqlite;mtcp:127.0.0.1,4225" -L 4 > /tmp/ud3tn2.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" --eid "$UD3TN2_EID" --bp-version "$BP_VERSION" --aap-port 4243 -S "$UD3TN_DIR/ud3tn2.aap2.socket" --cla "sqlite:ud3tn2.sqlite;mtcp:127.0.0.1,4225" -L 4 --allow-remote-config > /tmp/ud3tn2.log 2>&1 &
UD3TN2_PID=$!
sleep 1 # give ud3tn some time to start
# Start compat. dispatchers for both instances
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn1.aap2.socket" > /tmp/disp_ud3tn1.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn2.aap2.socket" > /tmp/disp_ud3tn2.log 2>&1 &
sleep 1 # give the dispatchers some time to start
# Start DTN7 instance (along with contact to uD3TN1 via config file for later use)
echo "Starting DTN7 instance ..."
dtnd --nodeid "$DTN7_EID" --routing "$DTN7_ROUTING" --cla "$DTN7_CLA" --endpoint "$DTN7_ENDPOINT" --config "$DTN7_CONFIG_FILE" > /tmp/dtn7.log 2>&1 &

View file

@ -25,27 +25,15 @@ exit_handler() {
echo ">>> LOWER1 LOGFILE"
cat "/tmp/lower1.log" || true
echo
echo ">>> LOWER1 DISP LOGFILE"
cat "/tmp/disp_lower1.log" || true
echo
echo ">>> LOWER2 LOGFILE"
cat "/tmp/lower2.log" || true
echo
echo ">>> LOWER2 DISP LOGFILE"
cat "/tmp/disp_lower2.log" || true
echo
echo ">>> UPPER1 LOGFILE"
cat "/tmp/upper1.log" || true
echo
echo ">>> UPPER1 DISP LOGFILE"
cat "/tmp/disp_upper1.log" || true
echo
echo ">>> UPPER2 LOGFILE"
cat "/tmp/upper2.log" || true
echo
echo ">>> UPPER2 DISP LOGFILE"
cat "/tmp/disp_upper2.log" || true
echo
echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
wait $UD3TN1_PID
@ -57,32 +45,24 @@ exit_handler() {
rm -f /tmp/*.log
# Start first uD3TN instance (lower1)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4242 -S "$UD3TN_DIR/ud3tn1.aap2.socket" -e "dtn://lower1.dtn/" -c "sqlite:ud3tn1.sqlite;mtcp:127.0.0.1,4224" -L 4 > /tmp/lower1.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4242 -S "$UD3TN_DIR/ud3tn1.aap2.socket" -e "dtn://lower1.dtn/" -c "sqlite:ud3tn1.sqlite;mtcp:127.0.0.1,4224" -L 4 --allow-remote-config > /tmp/lower1.log 2>&1 &
UD3TN1_PID=$!
sleep 1
# Start second uD3TN instance (upper1)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4243 -S "$UD3TN_DIR/ud3tn2.aap2.socket" -e "dtn://upper1.dtn/" -c "sqlite:ud3tn2.sqlite;bibe:," -L 4 > /tmp/upper1.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4243 -S "$UD3TN_DIR/ud3tn2.aap2.socket" -e "dtn://upper1.dtn/" -c "sqlite:ud3tn2.sqlite;bibe:," -L 4 --allow-remote-config > /tmp/upper1.log 2>&1 &
UD3TN2_PID=$!
sleep 1
# Start third uD3TN instance (lower2)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4244 -S "$UD3TN_DIR/ud3tn3.aap2.socket" -e "dtn://lower2.dtn/" -c "sqlite:ud3tn3.sqlite;mtcp:127.0.0.1,4225" -L 4 > /tmp/lower2.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4244 -S "$UD3TN_DIR/ud3tn3.aap2.socket" -e "dtn://lower2.dtn/" -c "sqlite:ud3tn3.sqlite;mtcp:127.0.0.1,4225" -L 4 --allow-remote-config > /tmp/lower2.log 2>&1 &
UD3TN3_PID=$!
sleep 1
# Start fourth uD3TN instance (upper2)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4245 -S "$UD3TN_DIR/ud3tn4.aap2.socket" -e "dtn://upper2.dtn/" -c "sqlite:ud3tn4.sqlite;bibe:," -L 4 > /tmp/upper2.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4245 -S "$UD3TN_DIR/ud3tn4.aap2.socket" -e "dtn://upper2.dtn/" -c "sqlite:ud3tn4.sqlite;bibe:," -L 4 --allow-remote-config > /tmp/upper2.log 2>&1 &
UD3TN4_PID=$!
sleep 1 # give ud3tn some time to start
# Start compat. dispatchers for all instances
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn1.aap2.socket" > /tmp/disp_lower1.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn2.aap2.socket" > /tmp/disp_upper1.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn3.aap2.socket" > /tmp/disp_lower2.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn4.aap2.socket" > /tmp/disp_upper2.log 2>&1 &
sleep 1 # give the dispatchers some time to start
trap exit_handler EXIT
# Configure contacts

View file

@ -42,12 +42,12 @@ case "$1" in
;;
esac
"$UD3TN_DIR/build/posix/ud3tn" -L 4 -e "dtn://ud3tn1.dtn/" $CLA_CONFIG > "$TEST_DIR/ud3tn1.log" 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -L 4 --external-dispatch -e "dtn://ud3tn1.dtn/" $CLA_CONFIG > "$TEST_DIR/ud3tn1.log" 2>&1 &
UD3TN1_PID=$!
sleep 1
# Start second uD3TN instance (ud3tn2)
"$UD3TN_DIR/build/posix/ud3tn" -L 4 -e "dtn://ud3tn2.dtn/" -c "mtcp:127.0.0.1,4225" -s "$UD3TN_DIR/ud3tn2.aap.socket" -S "$UD3TN_DIR/ud3tn2.aap2.socket" > "$TEST_DIR/ud3tn2.log" 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -L 4 --external-dispatch -e "dtn://ud3tn2.dtn/" -c "mtcp:127.0.0.1,4225" -s "$UD3TN_DIR/ud3tn2.aap.socket" -S "$UD3TN_DIR/ud3tn2.aap2.socket" > "$TEST_DIR/ud3tn2.log" 2>&1 &
UD3TN2_PID=$!
sleep 1

View file

@ -133,7 +133,8 @@ def test_re_scheduling_drop_smtcp_bundle7():
incoming_eid,
payload_data,
))
# Wait 1s (between ct), then, drop 1st contact -> re-scheduling
# Wait 1s (between ct), then, drop 2nd contact first and 1st
# contact afterwards -> re-scheduling becomes impossible -> drop
time.sleep(1)
_drop_contact(conn, serialize_func, c2)
_drop_contact(conn, serialize_func, c1)

View file

@ -26,27 +26,15 @@ exit_handler() {
echo ">>> LOWER1 LOGFILE"
cat "/tmp/lower1.log" || true
echo
echo ">>> LOWER1 DISP LOGFILE"
cat "/tmp/disp_lower1.log" || true
echo
echo ">>> LOWER2 LOGFILE"
cat "/tmp/lower2.log" || true
echo
echo ">>> LOWER2 DISP LOGFILE"
cat "/tmp/disp_lower2.log" || true
echo
echo ">>> UPPER1 LOGFILE"
cat "/tmp/upper1.log" || true
echo
echo ">>> UPPER1 DISP LOGFILE"
cat "/tmp/disp_upper1.log" || true
echo
echo ">>> UPPER2 LOGFILE"
cat "/tmp/upper2.log" || true
echo
echo ">>> UPPER2 DISP LOGFILE"
cat "/tmp/disp_upper2.log" || true
echo
echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
wait $UD3TN1_PID
@ -59,29 +47,21 @@ rm -f ion.log
rm -f /tmp/ion*log /tmp/ud3tn*.log
# Start first uD3TN instance (lower1)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4242 -S "$UD3TN_DIR/ud3tn1.aap2.socket" -e dtn://lower1.dtn/ -c "sqlite:ud3tn1.sqlite;tcpclv3:127.0.0.1,4555;mtcp:127.0.0.1,4224" -L 4 > /tmp/lower1.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4242 -S "$UD3TN_DIR/ud3tn1.aap2.socket" -e dtn://lower1.dtn/ -c "sqlite:ud3tn1.sqlite;tcpclv3:127.0.0.1,4555;mtcp:127.0.0.1,4224" -L 4 --allow-remote-config > /tmp/lower1.log 2>&1 &
UD3TN1_PID=$!
# Start second uD3TN instance (upper1)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4243 -S "$UD3TN_DIR/ud3tn2.aap2.socket" -e dtn://upper1.dtn/ -c "sqlite:ud3tn2.sqlite;bibe:," -L 4 > /tmp/upper1.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4243 -S "$UD3TN_DIR/ud3tn2.aap2.socket" -e dtn://upper1.dtn/ -c "sqlite:ud3tn2.sqlite;bibe:," -L 4 --allow-remote-config > /tmp/upper1.log 2>&1 &
UD3TN2_PID=$!
# Start third uD3TN instance (lower2)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4244 -S "$UD3TN_DIR/ud3tn3.aap2.socket" -e dtn://lower2.dtn/ -c "sqlite:ud3tn3.sqlite;tcpclv3:127.0.0.1,4554" -L 4 > /tmp/lower2.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4244 -S "$UD3TN_DIR/ud3tn3.aap2.socket" -e dtn://lower2.dtn/ -c "sqlite:ud3tn3.sqlite;tcpclv3:127.0.0.1,4554" -L 4 --allow-remote-config > /tmp/lower2.log 2>&1 &
UD3TN3_PID=$!
# Start fourth uD3TN instance (upper2)
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4245 -S "$UD3TN_DIR/ud3tn4.aap2.socket" -e dtn://upper2.dtn/ -c "sqlite:ud3tn4.sqlite;bibe:," -L 4 > /tmp/upper2.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -a localhost -p 4245 -S "$UD3TN_DIR/ud3tn4.aap2.socket" -e dtn://upper2.dtn/ -c "sqlite:ud3tn4.sqlite;bibe:," -L 4 --allow-remote-config > /tmp/upper2.log 2>&1 &
UD3TN4_PID=$!
sleep 1 # give ud3tn some time to start
# Start compat. dispatchers for all instances
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn1.aap2.socket" > /tmp/disp_lower1.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn2.aap2.socket" > /tmp/disp_upper1.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn3.aap2.socket" > /tmp/disp_lower2.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn4.aap2.socket" > /tmp/disp_upper2.log 2>&1 &
sleep 1 # give the dispatchers some time to start
# Start ION instance
ulimit -n 512 # fix behavior on systems with a huge limit (e.g. if the container runtime does not change the kernel default), see: #121
ionstart -I test/ion_interoperability/bibe_forwarding_test/ionstart.rc

View file

@ -59,15 +59,9 @@ exit_handler() {
echo ">>> uD3TN1 LOGFILE"
cat "/tmp/ud3tn1.log" || true
echo
echo ">>> uD3TN1 DISP LOGFILE"
cat "/tmp/disp_ud3tn1.log" || true
echo
echo ">>> uD3TN2 LOGFILE"
cat "/tmp/ud3tn2.log" || true
echo
echo ">>> uD3TN2 DISP LOGFILE"
cat "/tmp/disp_ud3tn2.log" || true
echo
echo "Waiting for uD3TN to exit gracefully - if it doesn't, check for sanitizer warnings."
wait $UD3TN1_PID
@ -78,19 +72,13 @@ rm -f ion.log
rm -f /tmp/ion*log /tmp/ud3tn*.log
# Start first uD3TN instance (uD3TN1)
"$UD3TN_DIR/build/posix/ud3tn" -s "$UD3TN_DIR/ud3tn1.socket" -S "$UD3TN_DIR/ud3tn1.aap2.socket" -c "sqlite:ud3tn1.sqlite;tcpclv3:127.0.0.1,4555" -b $BP_VERSION -e "$UD3TN1_EID" -L 4 > /tmp/ud3tn1.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -s "$UD3TN_DIR/ud3tn1.socket" -S "$UD3TN_DIR/ud3tn1.aap2.socket" -c "sqlite:ud3tn1.sqlite;tcpclv3:127.0.0.1,4555" -b $BP_VERSION -e "$UD3TN1_EID" -L 4 --allow-remote-config > /tmp/ud3tn1.log 2>&1 &
UD3TN1_PID=$!
# Start second uD3TN instance (uD3TN2)
"$UD3TN_DIR/build/posix/ud3tn" -s "$UD3TN_DIR/ud3tn2.socket" -S "$UD3TN_DIR/ud3tn2.aap2.socket" -c "sqlite:ud3tn2.sqlite;tcpclv3:127.0.0.1,4554" -b $BP_VERSION -e "$UD3TN2_EID" -L 4 > /tmp/ud3tn2.log 2>&1 &
"$UD3TN_DIR/build/posix/ud3tn" -s "$UD3TN_DIR/ud3tn2.socket" -S "$UD3TN_DIR/ud3tn2.aap2.socket" -c "sqlite:ud3tn2.sqlite;tcpclv3:127.0.0.1,4554" -b $BP_VERSION -e "$UD3TN2_EID" -L 4 --allow-remote-config > /tmp/ud3tn2.log 2>&1 &
UD3TN2_PID=$!
sleep 1 # give ud3tn some time to start
# Start compat. dispatchers for all instances
aap2-bdm-ud3tn-routing -vv --socket "$UD3TN_DIR/ud3tn1.aap2.socket" > /tmp/disp_ud3tn1.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --socket "$UD3TN_DIR/ud3tn2.aap2.socket" > /tmp/disp_ud3tn2.log 2>&1 &
sleep 1 # give the dispatchers some time to start
# Start ION instance
ulimit -n 512 # fix behavior on systems with a huge limit (e.g. if the container runtime does not change the kernel default), see: #121
ionstart -I test/ion_interoperability/minimal_forwarding_test/$ION_SCRIPT_NAME

View file

@ -43,15 +43,9 @@ exit_handler() {
echo ">>> uD3TN1 LOGFILE"
cat "/tmp/ud3tn1.log" || true
echo
echo ">>> uD3TN1 DISP LOGFILE"
cat "/tmp/disp_ud3tn1.log" || true
echo
echo ">>> uD3TN2 LOGFILE"
cat "/tmp/ud3tn2.log" || true
echo
echo ">>> uD3TN2 DISP LOGFILE"
cat "/tmp/disp_ud3tn2.log" || true
echo
rm -f -r $TMPDIR
}
@ -68,12 +62,6 @@ UD3TN1_PID=$!
"$UD3TN_DIR/build/posix/ud3tn" -s $UD3TN_DIR/ud3tn2.socket -S $UD3TN_DIR/ud3tn2.aap2.socket -c "sqlite:ud3tn2.sqlite;tcpclv3:127.0.0.1,4558" -b $BP_VERSION -e "$UD3TN2_EID" -L 4 > /tmp/ud3tn2.log 2>&1 &
UD3TN2_PID=$!
sleep 1 # give ud3tn some time to start
# Start compat. dispatchers for both instances
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn1.aap2.socket" > /tmp/disp_ud3tn1.log 2>&1 &
aap2-bdm-ud3tn-routing -vv --insecure-config --socket "$UD3TN_DIR/ud3tn2.aap2.socket" > /tmp/disp_ud3tn2.log 2>&1 &
sleep 1 # give the dispatchers some time to start
# Start HDTN
"$HDTN_SOURCE_ROOT/build/module/hdtn_one_process/hdtn-one-process" --hdtn-config-file=$HDTN_CONFIG_FILE --contact-plan-file=$HDTN_CONTACT_PLAN > /tmp/hdtn.log 2>&1 &
HDTN_PID=$!
@ -82,7 +70,7 @@ trap exit_handler EXIT
# Configure contact to HDTN in uD3TN1 which allows to reach uD3TN2
sleep 0.5
aap-config --socket $UD3TN_DIR/ud3tn1.socket --schedule 1 3600 10000 --reaches "$UD3TN2_EID" "$HDTN_EID" tcpclv3:127.0.0.1:4556
aap2-config --socket $UD3TN_DIR/ud3tn1.aap2.socket --schedule 1 3600 10000 --reaches "$UD3TN2_EID" "$HDTN_EID" tcpclv3:127.0.0.1:4556
# Send a bundle to uD3TN1, addressed to uD3TN2
PAYLOAD="THISISTHEBUNDLEPAYLOAD"
@ -108,7 +96,7 @@ $HDTN_SOURCE_ROOT/build/common/bpcodec/apps/bpreceivefile --save-directory=$TMPD
HDTNSINK_PID=$!
# Configure contact to HDTN in uD3TN1 which allows to reach HDTN_bpreceivefile
aap-config --socket $UD3TN_DIR/ud3tn1.socket --schedule 1 3600 10000 --reaches "$UD3TN2_EID" "$HDTN_EID" tcpclv3:127.0.0.1:4556
aap2-config --socket $UD3TN_DIR/ud3tn1.aap2.socket --schedule 1 3600 10000 --reaches "$UD3TN2_EID" "$HDTN_EID" tcpclv3:127.0.0.1:4556
# Send bundle which contains `hdtn_payload.txt` to HDTN_bpreceivefile
(sleep 2 && (cat $UD3TN_DIR/received_payload.txt | aap-send --socket $UD3TN_DIR/ud3tn1.socket --agentid "$SOURCE_AGENTID" "$SINK_EID"))&

View file

@ -23,13 +23,13 @@ export AAP2_ADM_SECRET
set -e
if [[ -z "$1" || -z "$2" || -z "$3" || -z "$4" ]]; then
echo "Usage: $0 <ud3tn-dir> <runas-user> <bundle-count> <bundle-size-bytes> [use-bdm (1|0)]" >&2
echo "Usage: $0 <ud3tn-dir> <runas-user> <bundle-count> <bundle-size-bytes> [static|compat|bdm]" >&2
fi
if [[ -z "$5" ]]; then
bdm=0
mode=static
else
bdm=$5
mode=$5
fi
if [[ "$EUID" -ne 0 ]]; then
@ -42,7 +42,6 @@ WORK_DIR="$1"
RUNAS_USER=$2
BUNDLE_COUNT=$3
BUNDLE_SIZE=$4
USE_BDM=$bdm
SOCK_DIR="$(mktemp -d)"
echo "Sockets and logs will be stored here: $SOCK_DIR" >&2
@ -108,16 +107,22 @@ ip -netns $NS2 link set dev $VE2 up
ip -netns $NS1 addr add "$IP1/24" dev $VE1
ip -netns $NS2 addr add "$IP2/24" dev $VE2
ip netns exec $NS1 sudo -u $RUNAS_USER AAP2_ADM_SECRET=$AAP2_ADM_SECRET "$WORK_DIR/build/posix/ud3tn" $UFLAG --bdm-secret-var AAP2_ADM_SECRET -c "sqlite:$SOCK_DIR/ud3tn1.sqlite;mtcp:$IP1,4222" -e "dtn://ud3tn1.dtn/" -s "$SOCK_DIR/ud3tn1.socket" -S "$SOCK_DIR/ud3tn1.aap2.socket" > "$SOCK_DIR/ud3tn1.log" 2>&1 &
if [[ $mode == "bdm" ]]; then
EXT_DISPATCH_FLAG="--external-dispatch"
else
EXT_DISPATCH_FLAG=""
fi
ip netns exec $NS1 sudo -u $RUNAS_USER AAP2_ADM_SECRET=$AAP2_ADM_SECRET "$WORK_DIR/build/posix/ud3tn" $UFLAG --bdm-secret-var AAP2_ADM_SECRET -c "sqlite:$SOCK_DIR/ud3tn1.sqlite;mtcp:$IP1,4222" -e "dtn://ud3tn1.dtn/" -s "$SOCK_DIR/ud3tn1.socket" -S "$SOCK_DIR/ud3tn1.aap2.socket" $EXT_DISPATCH_FLAG > "$SOCK_DIR/ud3tn1.log" 2>&1 &
UD3TN_1=$!
ip netns exec $NS2 sudo -u $RUNAS_USER AAP2_ADM_SECRET=$AAP2_ADM_SECRET "$WORK_DIR/build/posix/ud3tn" $UFLAG --bdm-secret-var AAP2_ADM_SECRET -c "sqlite:$SOCK_DIR/ud3tn2.sqlite;mtcp:$IP2,4222" -e "dtn://ud3tn2.dtn/" -s "$SOCK_DIR/ud3tn2.socket" -S "$SOCK_DIR/ud3tn2.aap2.socket" > "$SOCK_DIR/ud3tn2.log" 2>&1 &
ip netns exec $NS2 sudo -u $RUNAS_USER AAP2_ADM_SECRET=$AAP2_ADM_SECRET "$WORK_DIR/build/posix/ud3tn" $UFLAG --bdm-secret-var AAP2_ADM_SECRET -c "sqlite:$SOCK_DIR/ud3tn2.sqlite;mtcp:$IP2,4222" -e "dtn://ud3tn2.dtn/" -s "$SOCK_DIR/ud3tn2.socket" -S "$SOCK_DIR/ud3tn2.aap2.socket" $EXT_DISPATCH_FLAG > "$SOCK_DIR/ud3tn2.log" 2>&1 &
UD3TN_2=$!
ip netns exec $NS1 sudo -u $RUNAS_USER AAP2_ADM_SECRET=$AAP2_ADM_SECRET "$WORK_DIR/build/posix/ud3tn" $UFLAG --bdm-secret-var AAP2_ADM_SECRET -c "sqlite:$SOCK_DIR/ud3tn3.sqlite;mtcp:$IP1,4223" -e "dtn://ud3tn3.dtn/" -s "$SOCK_DIR/ud3tn3.socket" -S "$SOCK_DIR/ud3tn3.aap2.socket" > "$SOCK_DIR/ud3tn3.log" 2>&1 &
ip netns exec $NS1 sudo -u $RUNAS_USER AAP2_ADM_SECRET=$AAP2_ADM_SECRET "$WORK_DIR/build/posix/ud3tn" $UFLAG --bdm-secret-var AAP2_ADM_SECRET -c "sqlite:$SOCK_DIR/ud3tn3.sqlite;mtcp:$IP1,4223" -e "dtn://ud3tn3.dtn/" -s "$SOCK_DIR/ud3tn3.socket" -S "$SOCK_DIR/ud3tn3.aap2.socket" $EXT_DISPATCH_FLAG > "$SOCK_DIR/ud3tn3.log" 2>&1 &
UD3TN_3=$!
sleep 1 # give ud3tn some time to start
if [[ $USE_BDM == 1 ]]; then
if [[ $mode == "bdm" ]]; then
echo "MODE: BDM CONTACT DISPATCH" >&2
# Start BDMs and wait a bit for them to start
@ -137,11 +142,24 @@ if [[ $USE_BDM == 1 ]]; then
else
echo "MODE: FIB DISPATCH" >&2
echo "Configuring FIB links to send bundles in a loop." >&2
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_configure_link.py" --socket "$SOCK_DIR/ud3tn1.aap2.socket" --secret-var AAP2_ADM_SECRET ipn:1.0 "mtcp:$IP2:4222" $PYFLAG > /dev/null
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_configure_link.py" --socket "$SOCK_DIR/ud3tn2.aap2.socket" --secret-var AAP2_ADM_SECRET ipn:1.0 "mtcp:$IP1:4222" $PYFLAG > /dev/null
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_configure_link.py" --socket "$SOCK_DIR/ud3tn3.aap2.socket" --secret-var AAP2_ADM_SECRET ipn:1.0 "mtcp:$IP1:4222" $PYFLAG > /dev/null
if [[ $mode == "compat" ]]; then
echo "MODE: COMPAT ROUTER DISPATCH" >&2
# Configure
echo "Configuring contacts to send bundles in a loop." >&2
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_config.py" --socket "$SOCK_DIR/ud3tn1.aap2.socket" --secret-var AAP2_ADM_SECRET --schedule 3 100000000 10000000000000 --reaches ipn:1.1 dtn://ud3tn2.dtn/ "mtcp:$IP2:4222" $PYFLAG > /dev/null
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_config.py" --socket "$SOCK_DIR/ud3tn2.aap2.socket" --secret-var AAP2_ADM_SECRET --schedule 1 100000000 10000000000000 --reaches ipn:1.1 dtn://ud3tn1.dtn/ "mtcp:$IP1:4222" $PYFLAG > /dev/null
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_config.py" --socket "$SOCK_DIR/ud3tn3.aap2.socket" --secret-var AAP2_ADM_SECRET --schedule 1 100000000 10000000000000 --reaches ipn:1.1 dtn://ud3tn1.dtn/ "mtcp:$IP1:4222" $PYFLAG > /dev/null
else
echo "MODE: FIB DISPATCH" >&2
echo "Configuring FIB links to send bundles in a loop." >&2
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_configure_link.py" --socket "$SOCK_DIR/ud3tn1.aap2.socket" --secret-var AAP2_ADM_SECRET ipn:1.0 "mtcp:$IP2:4222" $PYFLAG > /dev/null
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_configure_link.py" --socket "$SOCK_DIR/ud3tn2.aap2.socket" --secret-var AAP2_ADM_SECRET ipn:1.0 "mtcp:$IP1:4222" $PYFLAG > /dev/null
"$WORK_DIR/.venv/bin/python" "$WORK_DIR/python-ud3tn-utils/ud3tn_utils/aap2/bin/aap2_configure_link.py" --socket "$SOCK_DIR/ud3tn3.aap2.socket" --secret-var AAP2_ADM_SECRET ipn:1.0 "mtcp:$IP1:4222" $PYFLAG > /dev/null
fi
fi

View file

@ -27,6 +27,8 @@ void testud3tn(void)
RUN_TEST_GROUP(bibe_parser);
RUN_TEST_GROUP(bibe_validation);
RUN_TEST_GROUP(bundle);
RUN_TEST_GROUP(node);
RUN_TEST_GROUP(routingTable);
#ifdef PLATFORM_POSIX
RUN_TEST_GROUP(simple_queue);
#endif // PLATFORM_POSIX

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "ud3tn/node.h"
#include "routing/compat/node.h"
#include "platform/hal_time.h"

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause OR Apache-2.0
#include "ud3tn/bundle_processor.h"
#include "ud3tn/node.h"
#include "ud3tn/routing_table.h"
#include "routing/compat/node.h"
#include "routing/compat/routing_table.h"
#include "util/llsort.h"
@ -41,10 +41,14 @@ static struct contact *c1, *c2, *c3, *c5, *c6, *c7,
static struct rescheduling_handle rescheduler;
static void rescheduling_mock(struct bundle *b, const void *ctx)
static void rescheduling_mock(
void *ctx, struct bundle *b,
uint64_t frag_offset, uint64_t frag_length)
{
(void)b;
(void)ctx;
(void)frag_offset;
(void)frag_length;
}
TEST_SETUP(routingTable)