Commit graph

216 commits

Author SHA1 Message Date
Felix Walter
78bef1a089 Refactor FIB: Separate node entry from CLA link
The FIB fulfils two purposes: 1) map node IDs to next-hop CLA addresses
and 2) store the current status of a link associated with a given CLA
address.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-08-23 11:59:02 +02:00
Felix Walter
ccbeac91f3 Unify and document compile-time options of compat. router
This prefixes all compile-time options of the compat. router with
`ROUTER_` and adds them to config.mk.example so they can be easily
discovered and adapted.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-15 00:46:14 +02:00
Felix Walter
87be9749af 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>
2024-07-15 00:46:14 +02:00
Felix Walter
ad4f56b62d Re-import v0.13.0 router code
This adds the code from e1621765a4 back
into the tree unchanged, but moved into two new directories, in
preparation of the following commit, which adds a routing agent on this
basis, to make it possible to review the diff properly.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-15 00:46:14 +02:00
Felix Walter
379ad048e8 bundle_processor: Allow for directly calling FIB and dispatch functions
In agents performing such functions we do not need to add elements to
the queue if we can directly call the corresponding BP function.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-15 00:46:14 +02:00
Felix Walter
4021d07c27 agent_manager: Remove flexible array member from dispatch_result
It prevents us from declaring the array in a function body without
malloc() and also has a possible risk out-of-bounds accesses when not
used carefully.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-15 00:46:14 +02:00
Felix Walter
c2fef74ea9 bundle: Allow 64-bit bundle payload lengths
The bundle block length, fragment offset, and total ADU length fields
were using 32-bit uint types, effectively reducing the maximum bundle
payload size to 4 GiB. This changes the field types to 64-bit uint, so
we can support larger bundles.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-15 00:46:10 +02:00
Felix Walter
767ecfd0e0 bundle_processor: Remove unnecessary signal types
These are leftovers from an earlier design of the agent manager.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-05 12:40:20 +02:00
Felix Walter
bd9b92b823 bundle_processor: Enforce a maximum number of fragments
This ensures that internal counters do not overflow and we can prevent
DoS by BDM responses containing lots of next hops (e.g. in case of BDM
bugs) to some extent.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-04 16:03:31 +02:00
Felix Walter
234787d69f cmdline: Do not launch TCPSPP CLA by default
The main reason here is to not initialize a CLA that has a hard limit on
the maximum bundle size (TCPSPP) by default. TCPSPP is rarely used anyway,
so we can disable it and save some memory in the default configuration.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-04 16:01:42 +02:00
Felix Walter
ee59a74443 aap2, cla, cmdline: Pass maximum bundle size to BDM
We should be able to honor the fragmentation threshold again. This
passes the maximum bundle size variable to the AAPv2 agent. The value is
determined as the minimum of all maximum bundle sizes reported by the
CLAs and the one specified on the command line, with the special case
of the value 0, which means a maximum bundle size of 2^64 ("unlimited").

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-04 16:00:30 +02:00
Felix Walter
b0f2f79e3c Revert "cmdline: Remove max-bundle-size argument"
This reverts commit 8249d0f6ff.

We will use this feature through a new field provided by AAP 2.0.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-07-04 16:00:26 +02:00
Felix Walter
7e810fa4c4 AAPv1: Set the BDM auth. flag if remote config is allowed
This keeps AAPv1 compatible for configuring our BDMs if we set the
additional flag.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-26 13:32:23 +02:00
Felix Walter
2dcf3b35d9 aap2: Secure the control of the storage and BDMs through AAP 2.0
With the addition of the storage agent and the compat. BDM we have the
issue that two new agents accept configuration through bundles, which
cannot check that those bundles come from trustworthy sources. In the
past we restricted contact configuration messages to local clients and
performed an "EID spoofing detection" so that we could check the source
EID - if it is the same as the local node ID, we allowed the
configuration bundle to be processed. With AAPv2 and potentially more
security-relevant components (such as BDMs) appearing in the future, we
need a new mechanism.

The idea behind the implemented mechanism is to reuse the existing AAP
2.0 shared-secret authentication that is applied for BDMs themselves
also for sending configuration messages: We add the possibility to
register an AAP 2.0 RPC agent (one that sends commands *toward* uD3TN)
with the "dispatch" authorization flag. This client can then request a
special flag to be added when sending bundles. The new flag is only
added internally by uD3TN to its in-memory data structure and is
delivered to all internal agents as well as AAP 2.0 clients receiving
the marked bundles. Those agents and clients (such as the sqlite/storage
agent) can then easily check for the flag to be present and thus
determine whether the bundle comes from an authenticated and authorized
source.

Note: The `adu_flags` field for the BundleADU AAP 2.0 message is now a
`repeated` field to represent the option of multiple flags being present
(Protobuf does not support bit fields for this purpose).

Fixes: #187

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-26 10:23:17 +02:00
Felix Walter
2f17075ff3
Merge branch 'feature/sqlite-in-memory-db'
See !174
2024-06-26 10:04:30 +02:00
Maximilian Nitsch
ed6bdcbf96 SQLiteCLA: Support volatile in-memory database
Adds support for a volatile in-memory database by enabling support for
URI-based database file names. Since the in-memory DB can only be
accessed within the process, the integration tests are changed so that
external SQL queries are only performed when a persistent DB file is
used.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-26 09:28:45 +02:00
Felix Walter
3ae2f06c3a bundle_processor: Work with the original bundle on TX events
We do not want to deal with the complexity of recursive fragmentation
when potentially re-dispatching fragments. Additionally, we need to be
able to properly report forwarding success or failure as per BP. This is
achieved by tracking everything based on the original bundle and
associating created fragments with it.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-25 10:25:14 +02:00
Felix Walter
3fc93b6507 aap2: Pass the next-hop node ID and CLA address to the BDM
When transmission had been attempted and generated a "TX
success/failure" result, the BDM will need the information which
transmission is affected by the generated dispatch. Additionally, the
term "DispatchRequest" is imprecise, as uD3TN does not require the BDM
to dispatch the bundle in any case (it can do so, but especially after
TX success/failure, oftentimes, it is intended to just proceed with
normal bundle processing).

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-25 10:25:12 +02:00
Felix Walter
512c8b9e19 bundle_processor: Log when re-dispatching a locally-fragmented bundle
This adds a flag to the bundle data structure indicating whether the
bundle is a fragment created in the current process. Based on that, a
log message is issued when re-dispatching such a bundle, as this may
be a BDM bug. We should evaluate whether or not to forbid this
altogether in the future.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-25 10:23:46 +02:00
Felix Walter
67715310c6 bundle: Remove unused field
This was never used in the new version of AAP 2.0 - we will decide
whether or not to dispatch externally based on a flag in the FIB in the
future.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-25 10:23:46 +02:00
Felix Walter
d57981d9a0
Merge branch 'hotfix/sqlite-agent-header-inconsistency'
See !169
2024-06-25 10:23:02 +02:00
Felix Walter
d238804c6a
Merge branch 'hotfix/bundle-serializer-result'
See !167
2024-06-25 10:20:59 +02:00
Felix Walter
261d1b1346 sqlite_agent: Fix inconsistency in function definition
It was adapted in the C file but not in the header.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 12:45:02 +02:00
Felix Walter
7b959e4cb8 aap2, FIB: Implement direct dispatch
This adds a "flags" field to the FIB link, allowing for configuring a
link for "direct dispatch", i.e., to make it usable without first
contacting a BDM. It is important to make this optional as otherwise
contact-based routing and QoS could not be implemented properly via a
BDM.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 12:39:59 +02:00
Felix Walter
e8a319a277 TX: Allow the bundle serializers to indicate failure if CLA fails
If the write method of the CLA fails, the serailizers will now return
early and this failure is handled properly by the TX task.

In the case of the BPv6 serializer, we add the necessary flow control to
the `write_bytes` macro, to prevent needing a conditional for every
write* or serialize* statement.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 12:38:15 +02:00
Felix Walter
4de60633ba cla: Increase default CONTACT_TX_TASK_QUEUE_LENGTH to 100
Some CLAs may block sending to the underlying layer, e.g., the storage
CLA may wait for the DB to become ready. This increases the default
queue length to prevent blocking the BP in such cases.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 11:16:07 +02:00
Felix Walter
8aaf458a1f cla_sqlite: Set busy timeout to 100 ms
Read transactions need a short, blocking, lock for the database, during
which no write transaction can be started - this means the interaction
of the agent, TX, and RX tasks may block each other if anything takes
longer than 1 ms. Thus, we increase the timeout for blocking locks to
100 ms to significantly reduce that probability.

See: https://www.sqlite.org/src/doc/204dbc15a682125c/doc/wal-lock.md

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 11:16:07 +02:00
Felix Walter
8249d0f6ff cmdline: Remove max-bundle-size argument
We are not using it anymore. As the BDM decides on anything related to
fragmentation, the parameter perspectively needs to be passed there,
either directly or through the mechanism we use for the minimum bundle
size (the `BundleDispatchInfo` message as part of the `DispatchRequest`
message).

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
72d3806066 aap2_agent: Switch to simple_queue to enforce clean termination
This enables a clean termination of all agent connections on program
exit without memory leaks that might previously occur due to the "pipe
queue" still holding some data (pointer to allocated memory) when
close() is called on the pipe. For that purpose, the "pipe queue" is
replaced by our standard hal_queue implementation, which also has a
higher performance as it does not require a syscall on every read/write
operation.

As hal_queue does not support poll() (it does not provide a fd), we
cannot check whether the socket has been closed by a subscribing AAP2
client while concurrently waiting for the internal queue. As an
alternative, this implements a liveliness check, which checks the sub.
connection opportunistically from the agent manager: When a new
registration is requested, existing registrations are first
"health-checked" and removed if down, so the new connection can take
over if an old one is down and this was not detected previously.

Based on the new infrastructure, a clean termination routine is
implemented that terminates all tasks transitively by terminating the
listener.

An AAP2 connection handler ("comm task") can terminate in two ways:
1. During runtime, when the connection is closed, it must clean up its own
   resources.
2. On program termination, all connections must be cleanly closed and
   all outstanding mesages handled.

For 1., we keep using detached threads and allow them to release all the
resources. This commit mainly introduces a mechanism for 2.: A list
tracking all comm. tasks is added that can be used to terminate and wait
for all of them on program termination. A "termination flag" indicates
whether tasks should clean up by themselves or the listener task takes
it over. Everything needs to be protected by mutexes for safe
concurrency.

There is specific handling for macOS, which does not signal other
threads clocking on a socket that the socket has been closed when
calling shutdown() but only when calling close() - thus, close() is
executed earlier on macOS. Also, macOS does not unblock poll() when the
socket is close()d, so we do not use it anymore to wait for data on an
RPC connection, but rather set SO_RCVTIMEO for active-client (RPC)
connections to enforce the keepalive timeout.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
972d62f9d8 hal_task: Add hal_task_wait function to join threads
This enables us to wait for threads to exit cleanly.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
03f144b45d agents: Allow checking for liveliness
This enables us to check if an agent connection went down synchronously
when trying to register a new agent, removing the need to wait until
uD3TN detects it on its own (if it even can).

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
b9aff2400d config: Set default bundle processor queue length to 4000
This makes it much more unlikely that the queue fills up, even under
high load. We however still need a long-term solution for the loop
issues sketched in #189.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
38d5d7d96f cla_sqlite: Register and create FIB entry on launch
This is required to allow bundles being forwarded to storage by
specifying the storage node (a configuration parameter) as next hop.

The CLA initialization is modified slightly to register the CLA before
executing `cla_launch` to ensure that the bundle processor knows about
it when it is executed.

This also moves the Sqlite CLA initialization to the `sqlite_launch`
function because the CLA has to be known ("registered") before we send
a signal to the BP (which is done during link creation).

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
89a6fad064 init: Load SQLite CLA by default
For working with BDMs we need it.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
2adc3ab7e8 bundle_fragmenter: Always create new fragments with offset + length
Previously the fragmentation logic was very specific to uD3TN's
forwarding approach, modifying the original bundle in the process. With
BDMs supporting fragmentation we must make this more flexible. Thus, we
now pass an offset and length and always create a copy of the required
contents based on the original bundle.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-21 10:36:30 +02:00
Felix Walter
6d2f204af5 Replace integrated next-hop forwarding with AAP 2.0
This adds functionality to dispatch bundles and control the FIB to AAP
2.0 and the bundle processor, replacing the old "router" completely.
AAP 2.0 is extended slightly to enable fragmentation.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-17 13:33:32 +02:00
Felix Walter
271ff4aa4f agent_manager: Extend by FIB and BDM mgmt., simplify, make testable
- Implement management of FIB and BDM agents:
  * add administrative secret which is required for registering FIB and
    BDM agents
  * allow registering reverse-direction agents for TX/RX of ADUs when
    passing the admin secret
  * add cmdline option to pass the admin secret via an env variable
  * make administrative secret optional in debug builds
- Register agents by number, as FIB and BDM agents may not have a sink
  ID. Numbers are allocated by the agent_register function.
- Remove global state, add function to de-allocate everything.
- Add comprehensive unit tests.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-17 13:33:31 +02:00
Felix Walter
e72c1fdd74 fib: Implement a simple DTN FIB
This first version only supports a single CLA link per node ID. Apart
from this, multiple mappings from node ID to CLA address (N:1) can be added.

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-17 13:33:31 +02:00
Felix Walter
1a605423c4 simplehtab: Implement an update method and document interface
This implements `htab_update` for replacing existing values.
htab_update will replace the value and return the old value if it was
found. If not, the value will be inserted under the specified key.
The return value is equivalent to `htab_add`.

Additionally, simplehtab now gracefully handles `malloc()` failures
everywhere: On future microcontroller platforms it is well possible that
`malloc()` returns NULL.

Interface documentation is added to `simplehtab.h` for all functions and
data structures intended to be used publicly.

The unit tests are extended to cover the new functionalities and the
*_known functions that are exposed publicly (though they are only
intended for very performance-critical cases).

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-17 13:33:31 +02:00
Felix Walter
3a3b12a8bc aap2: Document compile-time configuration options in config.mk.example
The backlog configuration option is renamed to indicate up front that it
is intended to be passed to listen().

Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-03 14:41:59 +02:00
Felix Walter
332323bed3 Adapt license of new files to AGPL-3.0
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
2024-06-03 13:45:19 +02:00
Maximilian Nitsch
f22162952f SQLiteAgent: Clean-up on termination
Frees the allocated memory and closes the database connection on exit.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
55f762b804 SQLiteCLA: Use WAL journal mode and a busy timeout instead of retries
https://www.sqlite.org/wal.html
https://www.sqlite.org/src/doc/204dbc15a682125c/doc/wal-lock.md

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
6a0a453b2f SQLiteCLA+Agent: Retry SQL statements if BUSY or LOCKED
Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
b7ce5ef89b SQLiteCLA+Agent: Extend StorageCall Protobuf definition
- Introduces a CompoundBundleId to filter exactly one bundle
- Filter bundles either by their ID or selected metadata
- Transfer the entire StorageCall object to the CLA via the agent queue

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
4fa34c69b3 SQLiteCLA+Agent: Execute select statement in CLA
To eliminate potential race conditions where rows are deleted before the
CLA processes them, the select statement is moved from the agent to the
CLA and everything is wrapped in a transaction to read all or nothing.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
589db818ae cla/cla_contact_rx_task: Exclude SQLiteCLA from EID spoofing detection
If bundles that were created by the μD3TN instance itself are stored in
the database via the SQLiteCLA and are received again at a later point
in time, μD3TN recognizes that the source node ID matches its own and
EID spoofing is detected.

This commit adds an exception to perform EID spoofing detection only for
packets that were not received by the SQLiteCLA.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
1321c59c22 sqlite_agent: Add an agent to interact with the SQLiteCLA
The SQLiteAgent enables SQLiteCLA to read packages from the database and
return them to μD3TN. For this purpose, the SQLiteAgent writes commands
to the queue that SQLiteCLA is waiting for.

The SQLiteAgent itself can be controlled by protobuf messages that
describe which action is to be applied to which set of bundles.

Currently the operations "Push" and "Delete" are implemented and a
filter based on a destination EID pattern.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
de33e8cc51 cla_sqlite: Implementation of the SQLite-based storage back-end
The SQLiteCLA makes it possible to write bundles, that are to be sent
via this CLA, to an SQLite database in order to persist them over a
longer period of time and also a restart of μD3TN.

The bundles are saved together with selected metadata (source EID,
destination EID, creation timestamp) in the "bundles" table. A
combination of source EID and creation timestamp is used as the primary
key.

To return bundles to μD3TN, they are read from the database and injected
via the cla_read() function, just like other CLAs that receive bundles.
To trigger this, commands are read from a queue that specify which
bundles are to be read from the database.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00
Maximilian Nitsch
218246e789 cla_sqlite: Add SQLite-based storage CLA skeleton
In order to prepare the implementation of a SQLite-based storage CLA, a
basic structure of this CLA with empty functions is created and
adjustments are made to the configuration/initialization functions and
the build system.

Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
2024-06-03 13:41:58 +02:00