|
Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
|
Site role service (ADR-040 step 2): the inter-site link, ONLINE/STANDBY negotiation, partner supervision, dispatcher takeover handling, warm-standby snapshot sync and the FAULTED flush - the mechanism the Capella model places in RTE Redundancy Services. The application is a declarative Site Role Client: it supplies its local facts (faulted, single-channel, readiness, A/B sibling) and its state codec, and is told when its role changes. The decision rules are rte_site_role_policy.h. More...
#include <stdbool.h>#include <stddef.h>#include <stdint.h>#include "rte/oal/netlink/rte_netlink.h"#include "rte/redundancy/dual/rte_dual_channel.h"#include "rte/redundancy/dual/rte_dual_negotiator.h"#include "rte/redundancy/site_role/rte_site_role_policy.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_site_role_local_t |
| struct | rte_site_role_change_t |
| struct | rte_site_role_sibling_t |
| struct | rte_site_role_config_t |
| struct | rte_site_role_status_t |
| struct | rte_site_role_t |
Macros | |
| #define | RTE_SITE_ROLE_FRAME_OVERHEAD 7U |
| #define | RTE_SITE_ROLE_FRAME_STATE_OFFSET 6U |
| #define | RTE_SITE_ROLE_VALID_MARKER 0xA5U |
| #define | RTE_SITE_ROLE_SINGLE_MODE_DUAL 0U |
| #define | RTE_SITE_ROLE_SINGLE_MODE_SINGLE 1U |
| #define | RTE_SITE_ROLE_TOKEN_MSG_LEN 16U |
| #define | RTE_SITE_ROLE_TOKEN_MAC_LEN 8U |
| #define | RTE_SITE_ROLE_TOKEN_LEN (RTE_SITE_ROLE_TOKEN_MSG_LEN + RTE_SITE_ROLE_TOKEN_MAC_LEN) |
| #define | RTE_SITE_ROLE_TOKEN_VERSION 1U |
| #define | RTE_SITE_ROLE_CHALLENGE_LIFETIME_DEFAULT_CYCLES 240U |
| #define | RTE_SITE_ROLE_SIBLING_MISMATCH_LIMIT 3U |
| #define | RTE_SITE_ROLE_SIBLING_REACH_DEFAULT_CYCLES 3U |
Typedefs | |
| typedef rte_status_t(*) | rte_site_role_encode_state_fn(void *user, uint8_t *out, size_t size, bool live) |
| typedef bool(*) | rte_site_role_receive_state_fn(void *user, const uint8_t *in, size_t size, bool valid) |
| typedef void(*) | rte_site_role_change_fn(void *user, const rte_site_role_change_t *change) |
| typedef void(*) | rte_site_role_trace_fn(void *user, const char *line) |
| typedef void(*) | rte_site_role_delay_fn(void *user, uint32_t ms) |
| typedef bool(*) | rte_site_role_verify_mac_fn(void *user, const uint8_t *msg, size_t msg_len, const uint8_t mac[RTE_SITE_ROLE_TOKEN_MAC_LEN]) |
| typedef bool(*) | rte_site_role_sibling_source_fn(void *user, rte_site_role_sibling_t *out) |
Functions | |
| rte_status_t | rte_site_role_init (rte_site_role_t *rs, const rte_site_role_config_t *cfg) |
| Validates and stores the configuration. Opens nothing. | |
| rte_status_t | rte_site_role_start (rte_site_role_t *rs) |
| Opens the link (blocking, bounded by startup_timeout_ms) and runs the startup negotiation until it settles (older startup timestamp wins). Setup phase only. | |
| void | rte_site_role_execute (rte_site_role_t *rs, uint32_t cycle, const rte_site_role_local_t *local) |
| One cycle: reconnect if needed, exchange frames, update the standby state, decide and apply the role. | |
| void | rte_site_role_service_link (rte_site_role_t *rs, uint32_t cycle) |
| Fast tick: drains up to 4 frames so acknowledgements do not depend on the two sites' cycle phase. | |
| void | rte_site_role_sync_standby (rte_site_role_t *rs, uint32_t cycle, const rte_site_role_local_t *local) |
| ONLINE, warm/hot standby: sends this cycle's snapshot before the output commit and tracks the ack. | |
| void | rte_site_role_on_takeover_confirm (rte_site_role_t *rs, uint32_t cycle) |
| Records an unauthenticated dispatcher confirmation that the other site is not ONLINE (ignored while ONLINE). Interim path: refused (and logged) when a MAC verifier is configured - use rte_site_role_on_takeover_token(). | |
| rte_site_role_token_result_t | rte_site_role_on_takeover_token (rte_site_role_t *rs, uint32_t cycle, const uint8_t *token, size_t token_len) |
| Verifies a takeover confirmation token (REQ-SITEROLE-015) and, when it is valid, records the confirmation exactly like rte_site_role_on_takeover_confirm() and draws a new challenge. Every outcome is logged. | |
| bool | rte_site_role_takeover_challenge (const rte_site_role_t *rs, uint32_t *out) |
| This channel's current takeover challenge, for the application's status line (the issuer MACs it). | |
| void | rte_site_role_note_lost_contact (rte_site_role_t *rs) |
| The application stalled while ONLINE long enough for the counterpart to have taken over: yield if it is. | |
| void | rte_site_role_flush_faulted (rte_site_role_t *rs, bool single_mode) |
| Best-effort final frame with faulted=1 before the process reboots, so the counterpart can promote. | |
| rte_site_role_sibling_verdict_t | rte_site_role_check_sibling (rte_site_role_t *rs, uint32_t cycle, bool own_single_mode, const rte_site_role_sibling_t *sibling) |
| A/B role agreement (REQ-SITEROLE-014): compares this channel's role and single_mode with its sibling's. | |
| rte_site_role_sibling_verdict_t | rte_site_role_sibling_verdict (const rte_site_role_t *rs) |
| The A/B agreement verdict of the check run by the last rte_site_role_execute() (REQ-SITEROLE-016). | |
| void | rte_site_role_shutdown (rte_site_role_t *rs) |
| Closes the link. Idempotent. | |
| bool | rte_site_role_is_online (const rte_site_role_t *rs) |
| void | rte_site_role_get_status (const rte_site_role_t *rs, rte_site_role_status_t *out) |
| Fills a status snapshot for monitors. | |
| void | rte_site_role_get_negotiator_states (const rte_site_role_t *rs, rte_dual_state_t *own, rte_dual_state_t *peer) |
| The underlying negotiator's own and peer states (diagnostic only; the role is rte_site_role_is_online()). | |
Site role service (ADR-040 step 2): the inter-site link, ONLINE/STANDBY negotiation, partner supervision, dispatcher takeover handling, warm-standby snapshot sync and the FAULTED flush - the mechanism the Capella model places in RTE Redundancy Services. The application is a declarative Site Role Client: it supplies its local facts (faulted, single-channel, readiness, A/B sibling) and its state codec, and is told when its role changes. The decision rules are rte_site_role_policy.h.
Moved from RBC_GP's ab_gp_channel_negotiate.c with the behaviour, the wire layout and the log text unchanged. Driven by the application at its own cycle points (ADR-040 decision 2, option A): rte_site_role_execute() once per cycle, rte_site_role_service_link() from the fast tick, rte_site_role_sync_standby() before the output commit.
Frame on the link (one rte_dual_channel DATA frame, frame_size bytes): faulted(1) | single_mode(1) | cycle(4, little endian) | application state(frame_size - 7) | valid(1) The state region carries the application's live state only while this channel is ONLINE (an empty state otherwise); valid marks a snapshot the receiving side may adopt on promotion.
REQ-SITEROLE-010: no dynamic allocation; the caller supplies the state storage and both frame buffers. REQ-SITEROLE-011: the role changes only through rte_site_role_decide() (or the startup negotiation); every change is reported to the application's change callback before the next call returns. REQ-SITEROLE-012: a per-cycle reconnect attempt is bounded by reconnect_attempt_ms; only rte_site_role_start() blocks, bounded by startup_timeout_ms. REQ-SITEROLE-014: the role of this channel and of its A/B sibling must agree (2oo2): a disagreement in {online, single_mode} for RTE_SITE_ROLE_SIBLING_MISMATCH_LIMIT consecutive checks is a fault (rte_site_role_check_sibling() returns RTE_SITE_ROLE_SIBLING_FAULT); one agreeing check resets the count. The application reacts (safe-state reboot) until the fault reaction moves too. REQ-SITEROLE-016: with a sibling source configured (ADR-040 step 5b), the service polls it once per rte_site_role_execute(), derives the A/B sibling's online, ready and reachable facts itself (reachable = a site-state frame within sibling_reach_cycles, default RTE_SITE_ROLE_SIBLING_REACH_DEFAULT_CYCLES, cycles), runs the REQ-SITEROLE-014 check after the role decision of the same cycle and exposes the verdict through rte_site_role_sibling_verdict(). Without a source the application-supplied facts and rte_site_role_check_sibling() apply unchanged. REQ-SITEROLE-017: with a sibling source configured, rte_site_role_start() polls it once before the inter-site negotiation; a known sibling frame decides the start-up role - ONLINE when the sibling reports ONLINE, STANDBY otherwise - with the negotiator seeded to that state, so this channel does not evaluate the REQ-DUAL-NEGOTIATOR-003 tie-break. The frame's ready and single_mode take no part; without a frame, or without a source, the tie-break applies unchanged. The startup timestamp is never changed by this rule. REQ-SITEROLE-013: the link is closed for reconnect after send_miss_threshold consecutive unacknowledged sends or on any receive failure other than a timeout; a STANDBY channel then marks the counterpart unresponsive and stays STANDBY (silence alone never promotes, REQ-SITEROLE-003). REQ-SITEROLE-015: with a MAC verifier configured, a dispatcher takeover confirmation is accepted only as a token (RTE_SITE_ROLE_TOKEN_LEN bytes) whose version, site id and channel id match this channel, whose challenge equals this channel's current challenge and whose MAC the verifier accepts; the challenge is random (rte_random), changes after every accepted token and after challenge_lifetime_cycles, and no token is accepted while no challenge could be drawn. The unauthenticated rte_site_role_on_takeover_confirm() is then refused.
Definition in file rte_site_role.h.
| #define RTE_SITE_ROLE_FRAME_OVERHEAD 7U |
Bytes of framing around the application state: faulted, single_mode, cycle (4) before it, valid after it.
Definition at line 68 of file rte_site_role.h.
| #define RTE_SITE_ROLE_FRAME_STATE_OFFSET 6U |
Offset of the application state region in the frame.
Definition at line 70 of file rte_site_role.h.
| #define RTE_SITE_ROLE_VALID_MARKER 0xA5U |
Value of the trailing byte of a frame that carries a valid ONLINE snapshot.
Definition at line 72 of file rte_site_role.h.
| #define RTE_SITE_ROLE_SINGLE_MODE_DUAL 0U |
single_mode byte values on the wire.
Definition at line 74 of file rte_site_role.h.
| #define RTE_SITE_ROLE_SINGLE_MODE_SINGLE 1U |
Definition at line 75 of file rte_site_role.h.
| #define RTE_SITE_ROLE_TOKEN_MSG_LEN 16U |
Definition at line 129 of file rte_site_role.h.
| #define RTE_SITE_ROLE_TOKEN_MAC_LEN 8U |
Definition at line 130 of file rte_site_role.h.
| #define RTE_SITE_ROLE_TOKEN_LEN (RTE_SITE_ROLE_TOKEN_MSG_LEN + RTE_SITE_ROLE_TOKEN_MAC_LEN) |
Definition at line 131 of file rte_site_role.h.
| #define RTE_SITE_ROLE_TOKEN_VERSION 1U |
Definition at line 132 of file rte_site_role.h.
| #define RTE_SITE_ROLE_CHALLENGE_LIFETIME_DEFAULT_CYCLES 240U |
Challenge lifetime used when the configuration leaves it 0.
Definition at line 134 of file rte_site_role.h.
| #define RTE_SITE_ROLE_SIBLING_MISMATCH_LIMIT 3U |
Consecutive disagreeing A/B checks that make a fault (REQ-SITEROLE-014).
Definition at line 154 of file rte_site_role.h.
| #define RTE_SITE_ROLE_SIBLING_REACH_DEFAULT_CYCLES 3U |
Sibling reachability window used when the configuration leaves sibling_reach_cycles 0 (REQ-SITEROLE-016): a site-state frame within the last 3 cycles.
Definition at line 157 of file rte_site_role.h.
| typedef rte_status_t(*) rte_site_role_encode_state_fn(void *user, uint8_t *out, size_t size, bool live) |
Fills the state region (size bytes, zeroed before the call) for every outgoing frame: from the application's live state when live is true (this channel is ONLINE), otherwise from an empty state (the receiver decodes every frame, so the region always carries a well-formed encoding).
Definition at line 110 of file rte_site_role.h.
| typedef bool(*) rte_site_role_receive_state_fn(void *user, const uint8_t *in, size_t size, bool valid) |
Decodes a received state region; when valid, the application keeps it as the snapshot to adopt on promotion. Returning false drops the whole frame (nothing about the counterpart is updated).
Definition at line 113 of file rte_site_role.h.
| typedef void(*) rte_site_role_change_fn(void *user, const rte_site_role_change_t *change) |
Reports a role change. With apply_state the application takes over its snapshot (or starts cold without one).
Definition at line 115 of file rte_site_role.h.
| typedef void(*) rte_site_role_trace_fn(void *user, const char *line) |
One diagnostic console line (already formatted, ends with a newline).
Definition at line 117 of file rte_site_role.h.
| typedef void(*) rte_site_role_delay_fn(void *user, uint32_t ms) |
Waits ms milliseconds; used only by the blocking startup connect retry.
Definition at line 119 of file rte_site_role.h.
| typedef bool(*) rte_site_role_verify_mac_fn(void *user, const uint8_t *msg, size_t msg_len, const uint8_t mac[RTE_SITE_ROLE_TOKEN_MAC_LEN]) |
Checks the issuer's MAC over a token message with the site's takeover key, which the application holds (RTE does not depend on a crypto library). Returns true only for a matching MAC.
Definition at line 138 of file rte_site_role.h.
| typedef bool(*) rte_site_role_sibling_source_fn(void *user, rte_site_role_sibling_t *out) |
Sibling site-state source (REQ-SITEROLE-016), polled once per rte_site_role_execute(): fills out (with known true) and returns true when a site-state frame from the A/B sibling arrived since the previous call; returns false and leaves out untouched otherwise.
Definition at line 172 of file rte_site_role.h.
What kind of role change the change callback reports.
Definition at line 89 of file rte_site_role.h.
Result of rte_site_role_on_takeover_token().
Definition at line 142 of file rte_site_role.h.
Result of rte_site_role_check_sibling() and of the per-cycle check with a sibling source.
Definition at line 175 of file rte_site_role.h.
| rte_status_t rte_site_role_init | ( | rte_site_role_t * | rs, |
| const rte_site_role_config_t * | cfg ) |
Validates and stores the configuration. Opens nothing.
Definition at line 777 of file rte_site_role.c.
| rte_status_t rte_site_role_start | ( | rte_site_role_t * | rs | ) |
Opens the link (blocking, bounded by startup_timeout_ms) and runs the startup negotiation until it settles (older startup timestamp wins). Setup phase only.
Start-up role from the A/B sibling (REQ-SITEROLE-017): with a sibling source configured, the source is polled once before the link is opened. A known sibling frame decides the role: sibling ONLINE -> this channel starts ONLINE, sibling STANDBY (ready or not) -> STANDBY; the negotiator is seeded to that state and does not evaluate the timestamp tie-break. The frame's ready (REQ-SITEROLE-002 gates promotions, not the start-up role) and single_mode (REQ-SITEROLE-014, checked from the first rte_site_role_execute()) are not consulted. No frame yet, or no source: the REQ-DUAL-NEGOTIATOR-003 tie-break as before. The startup timestamp is unchanged in every case.
| rs | Service state, initialized by rte_site_role_init(). NULL returns RTE_STATUS_INVALID_PARAM. |
Definition at line 805 of file rte_site_role.c.
| void rte_site_role_execute | ( | rte_site_role_t * | rs, |
| uint32_t | cycle, | ||
| const rte_site_role_local_t * | local ) |
One cycle: reconnect if needed, exchange frames, update the standby state, decide and apply the role.
Definition at line 890 of file rte_site_role.c.
| void rte_site_role_service_link | ( | rte_site_role_t * | rs, |
| uint32_t | cycle ) |
Fast tick: drains up to 4 frames so acknowledgements do not depend on the two sites' cycle phase.
Definition at line 947 of file rte_site_role.c.
| void rte_site_role_sync_standby | ( | rte_site_role_t * | rs, |
| uint32_t | cycle, | ||
| const rte_site_role_local_t * | local ) |
ONLINE, warm/hot standby: sends this cycle's snapshot before the output commit and tracks the ack.
Definition at line 967 of file rte_site_role.c.
| void rte_site_role_on_takeover_confirm | ( | rte_site_role_t * | rs, |
| uint32_t | cycle ) |
Records an unauthenticated dispatcher confirmation that the other site is not ONLINE (ignored while ONLINE). Interim path: refused (and logged) when a MAC verifier is configured - use rte_site_role_on_takeover_token().
Definition at line 1015 of file rte_site_role.c.
| rte_site_role_token_result_t rte_site_role_on_takeover_token | ( | rte_site_role_t * | rs, |
| uint32_t | cycle, | ||
| const uint8_t * | token, | ||
| size_t | token_len ) |
Verifies a takeover confirmation token (REQ-SITEROLE-015) and, when it is valid, records the confirmation exactly like rte_site_role_on_takeover_confirm() and draws a new challenge. Every outcome is logged.
| token | RTE_SITE_ROLE_TOKEN_LEN bytes as described above |
| token_len | number of bytes in token |
Definition at line 1041 of file rte_site_role.c.
| bool rte_site_role_takeover_challenge | ( | const rte_site_role_t * | rs, |
| uint32_t * | out ) |
This channel's current takeover challenge, for the application's status line (the issuer MACs it).
| out | receives the challenge |
Definition at line 1075 of file rte_site_role.c.
| void rte_site_role_note_lost_contact | ( | rte_site_role_t * | rs | ) |
The application stalled while ONLINE long enough for the counterpart to have taken over: yield if it is.
Definition at line 1085 of file rte_site_role.c.
| void rte_site_role_flush_faulted | ( | rte_site_role_t * | rs, |
| bool | single_mode ) |
Best-effort final frame with faulted=1 before the process reboots, so the counterpart can promote.
Definition at line 1093 of file rte_site_role.c.
| rte_site_role_sibling_verdict_t rte_site_role_check_sibling | ( | rte_site_role_t * | rs, |
| uint32_t | cycle, | ||
| bool | own_single_mode, | ||
| const rte_site_role_sibling_t * | sibling ) |
A/B role agreement (REQ-SITEROLE-014): compares this channel's role and single_mode with its sibling's.
| own_single_mode | this channel's single-channel mode at the time of the check |
Definition at line 1110 of file rte_site_role.c.
| rte_site_role_sibling_verdict_t rte_site_role_sibling_verdict | ( | const rte_site_role_t * | rs | ) |
The A/B agreement verdict of the check run by the last rte_site_role_execute() (REQ-SITEROLE-016).
| rs | the service; may be NULL |
Definition at line 1160 of file rte_site_role.c.
| void rte_site_role_shutdown | ( | rte_site_role_t * | rs | ) |
Closes the link. Idempotent.
Definition at line 1165 of file rte_site_role.c.
| bool rte_site_role_is_online | ( | const rte_site_role_t * | rs | ) |
Definition at line 1173 of file rte_site_role.c.
| void rte_site_role_get_status | ( | const rte_site_role_t * | rs, |
| rte_site_role_status_t * | out ) |
Fills a status snapshot for monitors.
Definition at line 1178 of file rte_site_role.c.
| void rte_site_role_get_negotiator_states | ( | const rte_site_role_t * | rs, |
| rte_dual_state_t * | own, | ||
| rte_dual_state_t * | peer ) |
The underlying negotiator's own and peer states (diagnostic only; the role is rte_site_role_is_online()).
Definition at line 1194 of file rte_site_role.c.