Skip to content

feat(bgp): optional attribute-255 clock on announcements - #2

Merged
digizeph merged 1 commit into
feat/collector-revisionfrom
feat/attr255-clock
Sep 29, 2026
Merged

digizeph merged 1 commit into
feat/collector-revisionfrom
feat/attr255-clock

Conversation

@digizeph

Copy link
Copy Markdown
Member

Adds an optional per-prefix clock carried in attribute 255 (reserved for development, RFC 2042).

A [[prefixes]] entry with dev_attr255_interval_secs = N attaches a 13-byte payload to that prefix's announcements and re-announces it every N seconds. The field is optional, absent means no attribute, and 0 is rejected by config validation.

Payload layout: BGPKIT magic (6) + version (1) + refresh round (2, big-endian) + unix seconds (4, big-endian). The round is redundant with the timestamp once the interval is known, but it makes a single sample self-contained: a collector can count missed refreshes without knowing the cadence, and two samples reveal it. The container is deliberately not another originator's shape, so a code-255 sample is attributable from the payload alone.

The attribute is originated with OPTIONAL|TRANSITIVE explicitly, rather than Development's .into() default, which also sets PARTIAL. The first downstream speaker that does not recognize the attribute sets PARTIAL per RFC 4271, so collector copies of the same update can read e0 ff 0d .... Whether they do, and where the payload stops changing, is the measurement this exists for. Originating an unknown optional-transitive attribute is DFZ-visible by construction, so it stays scoped to our own prefixes and is detachable by re-announcing without it.

Runtime interaction: one refresh task per distinct interval re-dispatches the announcement and re-reads the effective prefix set on each tick, so a runtime suppression silences the clock and prefix add on a configured network keeps it. Clearing the field and reloading detaches the attribute; scheduling a newly added or changed interval takes effect after a daemon restart.

Tests cover the payload vector, the encoded bytes plus parse-back flags, the config roundtrip with zero rejection, and the socket-level refresh and runtime re-add paths.

Base is feat/collector-revision; retarget to main once that branch lands.

Note on CI: the Rust workflow only triggers for pull requests based on main, so this PR runs no CI. Local results on this commit: cargo fmt --check clean, cargo clippy --all-targets --all-features -- -D warnings clean, cargo test --all-features 49 passed / 0 failed (42 lib, 6 acceptance_peer, 1 archive_integration).

A `[[prefixes]]` entry with `dev_attr255_interval_secs = N` attaches attribute
255 (reserved for development, RFC 2042) carrying a 13-byte BGPKIT clock
payload (`BGPKIT` magic, version, refresh round, unix seconds) to that
prefix's announcements, re-announced every N seconds.

The refresh task is scheduled per distinct interval at startup and re-reads
the effective originated set on each tick, so a runtime suppression silences
it and `prefix add` keeps the configured clock for the same network. The
attribute is originated with OPTIONAL|TRANSITIVE; downstream speakers set
PARTIAL per RFC 4271. Config validation rejects a refresh interval of 0.

Tests: a fixed payload vector (including the 65,536 round wrap), encoded wire
bytes plus a parse-back flag check, config roundtrip and zero-reject, and
socket-level acceptance coverage where a refresh advances the embedded time
and a runtime re-add keeps the clock.
@digizeph
digizeph requested a balanced review from Copilot and removed request for Copilot September 29, 2026 01:55
@digizeph
digizeph merged commit 25b4577 into feat/collector-revision Sep 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant