Uses pandoc to convert the manpage into a markdown document and add it
to the mkdocs documentation.
Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
Otherwise, we may get dependency conflicts, depending on the order in
which we install the modules and requirements file with pip.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
We should not need to wait between setting up individual contacts, as
the commands are even sent to different BPA instances. We only need to
wait after configuring the contacts and before sending the bundle, so
that the contact has definitely started.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
We must ensure that the receiving end can start before injecting
bundles, otherwise this becomes a race condition. We saw this issue in
the ION-BIBE interoperability test.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
- Use format strings
- Use enum field instead of magic number
- Cast to enum type
- Add type annotations to parse functions
- Improve docstrings mentioning Set types where function accepts Iterable
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
As discussed in #215.
Note: The basis of this code has been AI-generated using Claude Sonnet 4,
but it was reviewed line-by-line and heavily refactored.
Prompts:
- "Create a new integration test in `test/integration` that tests the
newly-introduced status report feature. The test should send a bundle with
a set report-to EID, which may be the (local) sender. The created status
report should then be received and checked that it contains the
correct data."
- There is an issue in `_wait_for_status_report`: `sub_client.receive_msg`
can block indefinitely and there is no possibility to specify a timeout.
However, you could make the test async which allows aborting the receive
function. There is an async AAP2 client and an example for a test based
on it in `test_aap2_async_client.py`.
- I updated the test file. Adapt it so it passes the flake8 check which
gives the following errors: (pasted line-length issues)
- Extend the check of the received status report in the test by parsing it
as valid BPv7 (RFC 9171) status report. An implementation that can be
used for serializing status reports can be found in lines 525-566 of
`pyd3tn/bundle7.py`. The status report is in CBOR format. We use the
`cbor2` library in the project. The BPv7 spec can be found here:
https://www.rfc-editor.org/rfc/rfc9171.html#name-bundle-status-reports
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This adds a `from_cbor` method to the `BundleStatusReport` class so
binary status reports can be parsed.
Note: Some of this code has been AI-generated using Claude Sonnet 4, but
it was reviewed line-by-line and then heavily refactored.
Prompt: "Write a `from_cbor` function that can be added to the
`BundleStatusReport` class in `bundle7.py` so we get suitable status
report parsing logic there."
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
The constructor for BundleStatusReport always required a bundle, so that
it was not possible to create a standalone status report instance. A
`from_bundle` method is added that provides the old behavior.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
There are many use cases where status reports generated locally should
be delivered locally.
Note: As the bundles now need to be passed to `bundle_dispatch`, it would
have been needed to remove the `const` qualifier of that method, as it
mutates the BP state (for checking for duplicates and adding bundle fragments
to the reassembly list). To prevent this from being necessary, an alternative
function is introduced that does not perform such a check and does not
support fragments.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This enables AAP 2.0 clients to receive status reports with a new ADU
flag (as we already deliver BIBE bundles). Moreover, it allows clients
to set a report-to EID and sets all of the status report flags on newly
created bundles in case a report-to EID is provided.
Closes: #241
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This way we do not need to specify it everywhere. Due to the new Jansson
(JSON library) dependency, we need it also for the simple builds, as
buildpack-deps only provides sqlite beside basic build tools.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
The JSON parser unit test heavily uses multiline strings so we can read
the embedded JSON properly. It seems there is no better way to make
checkpatch happy here.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This adds the JSON parser logic as an alternative to the custom legacy
format and also adds necessary tests.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
- add sqlite and jansson dependencies, which were missing
- use newest supported Python release
Closes: #238
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This adds a function to decode JSON configuration via Jansson to the
router agent. The JSON functionality and, thus, the dependency on
Jansson, can be disabled during the build process by setting the
`DISABLE_JSON` compile-time flag (see `config.mk.example` for details).
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This introduces a JSON contact configuration format for the
deterministic first-contact forwarding (DFCF) implementation as a modern
alternative to our homebrewn configuration messages. For now, it is only
supported in the external DFCF BDM, but integration into the "router
agent" is planned.
Example JSON configuration string (from our tests):
```
{
"command": "ADD",
"node_id": "dtn://ud3tn2.dtn/",
"cla_addr": "mtcp:127.0.0.1:4223",
"reachable_eids": [
"ipn:1.0"
],
"contact_list": [
{
"start": 1401519306972,
"end": 1401519316972,
"data_rate": 2400,
"reachable_eids": [
"dtn://66553/",
"dtn://89326/"
]
},
{
"start": 1401519506972,
"end": 1401519516972,
"data_rate": 1200,
"reachable_eids": [
"dtn://12349/",
"dtn://89326/"
]
}
]
}
```
Closes: #15
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
We implicitly expected all incoming config message data structures to
contain a list of contacts as well as a list of reachable EIDs in both the
config message and each contact in the contact list itself. This may not
always be the case if the config command does not contain such fields.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
Previously it was not possible to disable SQLite because of a linker
error. Also, `sqlite3.h` was always required to be present. This adds
an example to `config.mk.example` and fixes both issues.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This adds a test for the new JSON-based query feature of the BDM. The
test is only enabled in the debug integration test for the external
dispatcher and does not run by default, as it does not specify an AAP
2.0 secret and also does not work with the built-in DFCF forwarding
module.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
Previously, we were relying on a race condition for re-scheduling: if a
suitable contact is ongoing, even if it is in the process of being
dropped, it will be considered for re-scheduling a bundle.
This explicitly ignores the contact being dropped.
Due to the increased complexity, `_calc_bundle_schedule` is refactored
slightly.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
When we update an existing contact, e.g, to change the set of reachable
EIDs, we delete the previous entry, cancel the task, and add a new
entry. For this to work, we must wait for the task to terminate after
cancellation.
Additionally, we relax the check for which contacts to update to include
contacts that compare equal, which might be the case if only the
"reachable EIDs" list is different.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This would result in conflicts. We previously used an assertion to
ensure it, however, this could be triggered by external config commands
and crashed the BDM.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
If the link cannot be established, we need a timeout to remove the
contact from the active contacts set.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This re-impplements the QUERY command through our configuration
interface so we can get the contact plan back out of the BDM.
aap2_config.py is extended such that it allows for querying and deleting
contacts.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
As this can also be used for the built-in routing agent, we provide the
functionality in the shared Python module.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
It only controls how status reports should look like, not which status
reports are requested. We only want to check for the latter. ION appears
to always set this flag.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
This adds a `bundle_is_valid` function checking for further MUST
constraints defined by the spec., which further processing inside uD3TN
may depend on.
Signed-off-by: Felix Walter <felix.walter@d3tn.com>
Regenerates the Python protobuf bindings with the updated `protoc`.
```sh
make aap2-proto-headers
make storage-agent-proto-headers
```
Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>
As Python 3.8 is end-of-life and the latest python-protobuf package
requires at least Python 3.9, the minimum Python version is set to 3.9.
Signed-off-by: Maximilian Nitsch <maximilian.nitsch@d3tn.com>