|
Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
|
Dual state negotiator of ADR-020: decides rte_dual_state_t for both this instance and its peer, driven over an attached rte_dual_channel_t's STATE-frame flow. More...
#include <stdbool.h>#include <stdint.h>#include "rte/redundancy/dual/rte_dual_channel.h"#include "rte/redundancy/dual/rte_dual_types.h"#include "rte/utils/status/rte_status.h"#include "rte/utils/types/rte_types.h"Go to the source code of this file.
Data Structures | |
| struct | rte_dual_negotiator_t |
| One rte_dual_negotiator_t instance's state. Caller-owned storage; every field is private - reach it only through the functions below. More... | |
| struct | rte_dual_negotiator_config_t |
| Configuration for rte_dual_negotiator_init(). More... | |
Typedefs | |
| typedef void(*) | rte_dual_negotiator_state_change_callback_t(rte_dual_state_t new_own_state, rte_dual_state_t old_own_state, rte_dual_state_t new_peer_state, rte_dual_state_t old_peer_state, void *user_ctx) |
| Optional callback invoked whenever either the own or the peer rte_dual_state_t changes, from inside rte_dual_negotiator_execute(). | |
Functions | |
| rte_status_t | rte_dual_negotiator_init (rte_dual_negotiator_t *negotiator, const rte_dual_negotiator_config_t *config) |
| Initializes a rte_dual_negotiator_t. Captures this instance's own startup timestamp once (rte_timer_now(), degrading to 0 if no timer OSAdapter is registered - same best-effort posture as rte_log_write_event()'s Timestamp field) for use on every beacon this negotiator ever sends - see rte_dual_state_frame_t's own doc on why this must stay fixed - UNLESS config->resume_own_state/resume_own_startup_timestamp_ms opt into resuming a prior identity instead (see their own doc). peer_state always starts at RTE_DUAL_STATE_IDLE; own_state does too unless a resume was requested. | |
| rte_status_t | rte_dual_negotiator_execute (rte_dual_negotiator_t *negotiator, rte_duration_ms_t receive_timeout_ms) |
| Drives one round of state negotiation: refreshes own_channel_degraded from the attached channel's current rte_dual_channel_get_status(), sends this instance's own beacon, drains and processes every currently-pending inbound STATE frame, then recomputes both own and peer rte_dual_state_t: | |
| rte_dual_state_t | rte_dual_negotiator_get_own_state (const rte_dual_negotiator_t *negotiator) |
| Returns this instance's own current rte_dual_state_t. | |
| rte_dual_state_t | rte_dual_negotiator_get_peer_state (const rte_dual_negotiator_t *negotiator) |
| Returns this instance's last-known view of the peer's rte_dual_state_t. | |
| uint64_t | rte_dual_negotiator_get_own_startup_timestamp_ms (const rte_dual_negotiator_t *negotiator) |
| Returns this instance's own startup timestamp (captured at rte_dual_negotiator_init() time, or resumed from config - see rte_dual_negotiator_config_t::resume_own_startup_timestamp_ms). Diagnostic use (e.g. logging alongside the peer's own, below) - never itself consulted by this module's own tie-break logic after init. | |
| uint64_t | rte_dual_negotiator_get_peer_startup_timestamp_ms (const rte_dual_negotiator_t *negotiator) |
| Returns this instance's last-known view of the peer's own startup timestamp (0/unset until the first valid STATE frame arrives). Diagnostic use only, same posture as rte_dual_negotiator_get_own_startup_timestamp_ms() above. | |
| uint32_t | rte_dual_negotiator_get_own_id (const rte_dual_negotiator_t *negotiator) |
| Returns this instance's own tie-break identifier (rte_dual_negotiator_config_t::own_id at init time). Diagnostic use only. | |
| uint32_t | rte_dual_negotiator_get_peer_id (const rte_dual_negotiator_t *negotiator) |
| Returns the expected peer's tie-break identifier (rte_dual_negotiator_config_t::peer_id at init time). Diagnostic use only. | |
Dual state negotiator of ADR-020: decides rte_dual_state_t for both this instance and its peer, driven over an attached rte_dual_channel_t's STATE-frame flow.
One-directional dependency (ADR-020 section 3): rte_dual_negotiator_t depends on an already-initialized rte_dual_channel_t (given to it at config time) and drives its own periodic beacon traffic through that channel's rte_dual_channel_send_state_frame()/_receive_state_frame() pair; rte_dual_channel_t itself has no knowledge of this module.
Intended call pattern: rte_dual_negotiator_execute() once per application cycle (the same way rte_channel_checkpoint() is driven today - ADR-017), after the application has already driven rte_dual_channel_send()/_receive() for its own real payload traffic that cycle if it has any.
REQ-DUAL-NEGOTIATOR-001: no dynamic allocation; caller supplies storage and an already-initialized rte_dual_channel_t. REQ-DUAL-NEGOTIATOR-002: rte_dual_negotiator_execute() shall never call rte_safestate_enter() itself - deciding what a sustained RTE_DUAL_STATE_UNKNOWN means for safety stays an application policy decision (ADR-020 section 4's "no automatic safety reaction" non-goal). REQ-DUAL-NEGOTIATOR-003: the initial ONLINE-vs-STANDBY decision uses an older-startup-timestamp-wins rule, with own_id/peer_id as a deterministic fallback only on an exact timestamp tie. REQ-DUAL-NEGOTIATOR-004: whichever side is currently STANDBY has its HOT/COLD label derived from the ONLINE side's own channel-degradation bit - never from the STANDBY side's own self-report, and never from the ONLINE side's opinion of itself. REQ-DUAL-NEGOTIATOR-005: loss of peer contact past config->peer_lost_timeout_ms sets peer_state to UNKNOWN; own_state degrades to UNKNOWN too unless it was already ONLINE, which stays ONLINE.
Definition in file rte_dual_negotiator.h.