Safe API Framework 0.1.0 build 384e6ae
Layered API framework for safety-related applications (ERTMS RBC reference targeting CENELEC EN 50128 SIL 4)
Loading...
Searching...
No Matches
rte_site_role.c File Reference

See rte_site_role.h. Moved from RBC_GP's ab_gp_channel_negotiate.c (ADR-040 step 2): same link handling, same frame layout, same decisions, same log text; the application-specific parts (state codec, what a promotion takes over, readiness) are the Site Role Client's callbacks and local facts. More...

Include dependency graph for rte_site_role.c:

Go to the source code of this file.

Macros

#define SITE_ROLE_TRACE_LINE_MAX   256U
#define SITE_ROLE_SERVICE_DRAIN   4U

Functions

static void trace_line (const rte_site_role_t *rs, const char *line)
static void log_event (const rte_site_role_t *rs, rte_log_level_t level, uint32_t cycle, const char *source, const char *destination, const char *type, const char *info, const char *extra)
static size_t state_size (const rte_site_role_t *rs)
static void encode_frame (rte_site_role_t *rs, bool faulted, bool single_mode, uint32_t cycle, bool live)
static void report_change (rte_site_role_t *rs, rte_site_role_change_kind_t kind, rte_site_role_reason_t reason, bool apply_state)
static void promote_to_online (rte_site_role_t *rs, const char *message, rte_site_role_reason_t reason)
static void demote_to_standby (rte_site_role_t *rs, const char *message, rte_site_role_reason_t reason)
static void renegotiate_from_deadlock (rte_site_role_t *rs, rte_site_role_reason_t reason)
static void on_negotiator_state_change (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)
static rte_status_t open_link_once (rte_site_role_t *rs, rte_duration_ms_t timeout_ms)
static rte_status_t open_link_blocking (rte_site_role_t *rs)
static rte_status_t init_channel_and_negotiator (rte_site_role_t *rs, bool resume_standby)
static void close_link (rte_site_role_t *rs)
static rte_status_t reconnect (rte_site_role_t *rs)
static bool send_frame (rte_site_role_t *rs, uint32_t cycle)
static rte_status_t receive_frame (rte_site_role_t *rs, uint32_t cycle, bool quiet)
static void handle_send_miss_and_link_teardown (rte_site_role_t *rs, uint32_t cycle, bool send_ok, rte_status_t receive_status)
static void update_standby_warmth (rte_site_role_t *rs, uint32_t cycle)
static void poll_sibling_source (rte_site_role_t *rs, uint32_t cycle)
static bool sibling_reachable (const rte_site_role_t *rs)
static void fill_sibling_facts (const rte_site_role_t *rs, const rte_site_role_local_t *local, rte_site_role_input_t *in)
static void check_sibling_after_decision (rte_site_role_t *rs, uint32_t cycle, const rte_site_role_local_t *local)
static void startup_role_from_sibling (rte_site_role_t *rs, bool *resume_standby)
static void build_decision_input (const rte_site_role_t *rs, const rte_site_role_local_t *local, rte_site_role_input_t *in)
static bool reason_changed (const rte_site_role_t *rs, rte_site_role_reason_t reason)
static void set_reason (rte_site_role_t *rs, rte_site_role_reason_t reason)
static void run_site_role_decision (rte_site_role_t *rs, uint32_t cycle, const rte_site_role_local_t *local)
static void take_local (rte_site_role_t *rs, const rte_site_role_local_t *local)
static uint32_t read_u32_le (const uint8_t *in)
static uint32_t challenge_lifetime (const rte_site_role_t *rs)
static void draw_challenge (rte_site_role_t *rs, uint32_t cycle)
static void refresh_challenge (rte_site_role_t *rs, uint32_t cycle)
static void record_takeover_confirmation (rte_site_role_t *rs, uint32_t cycle, const char *how)
static void trace_ignored_while_online (const rte_site_role_t *rs)
static rte_site_role_token_result_t check_token (const rte_site_role_t *rs, const uint8_t *token, size_t token_len)
static const char * token_result_text (rte_site_role_token_result_t result)
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()).

Detailed Description

See rte_site_role.h. Moved from RBC_GP's ab_gp_channel_negotiate.c (ADR-040 step 2): same link handling, same frame layout, same decisions, same log text; the application-specific parts (state codec, what a promotion takes over, readiness) are the Site Role Client's callbacks and local facts.

Design note kept from the original: the negotiator (rte_dual_negotiator, ADR-020) settles the startup role and is logged every cycle as a diagnostic of the link's health. After startup the role is driven only by rte_site_role_decide() over the facts gathered here; the negotiator's own state can legitimately differ from the role after a FAULTED-driven promotion, because it has no view of that override.

Definition in file rte_site_role.c.

Macro Definition Documentation

◆ SITE_ROLE_TRACE_LINE_MAX

#define SITE_ROLE_TRACE_LINE_MAX   256U

Definition at line 22 of file rte_site_role.c.

◆ SITE_ROLE_SERVICE_DRAIN

#define SITE_ROLE_SERVICE_DRAIN   4U

Definition at line 23 of file rte_site_role.c.

Function Documentation

◆ trace_line()

void trace_line ( const rte_site_role_t * rs,
const char * line )
static

Definition at line 27 of file rte_site_role.c.

◆ log_event()

void log_event ( const rte_site_role_t * rs,
rte_log_level_t level,
uint32_t cycle,
const char * source,
const char * destination,
const char * type,
const char * info,
const char * extra )
static

Definition at line 35 of file rte_site_role.c.

◆ state_size()

size_t state_size ( const rte_site_role_t * rs)
static

Definition at line 43 of file rte_site_role.c.

◆ encode_frame()

void encode_frame ( rte_site_role_t * rs,
bool faulted,
bool single_mode,
uint32_t cycle,
bool live )
static

Definition at line 48 of file rte_site_role.c.

◆ report_change()

void report_change ( rte_site_role_t * rs,
rte_site_role_change_kind_t kind,
rte_site_role_reason_t reason,
bool apply_state )
static

Definition at line 66 of file rte_site_role.c.

◆ promote_to_online()

void promote_to_online ( rte_site_role_t * rs,
const char * message,
rte_site_role_reason_t reason )
static

Definition at line 90 of file rte_site_role.c.

◆ demote_to_standby()

void demote_to_standby ( rte_site_role_t * rs,
const char * message,
rte_site_role_reason_t reason )
static

Definition at line 104 of file rte_site_role.c.

◆ renegotiate_from_deadlock()

void renegotiate_from_deadlock ( rte_site_role_t * rs,
rte_site_role_reason_t reason )
static

Both sites FAULTED: the same deterministic, symmetric rule on both sides - WEST ONLINE, EAST STANDBY.

Definition at line 117 of file rte_site_role.c.

◆ on_negotiator_state_change()

void on_negotiator_state_change ( 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 )
static

Definition at line 132 of file rte_site_role.c.

◆ open_link_once()

rte_status_t open_link_once ( rte_site_role_t * rs,
rte_duration_ms_t timeout_ms )
static

Definition at line 153 of file rte_site_role.c.

◆ open_link_blocking()

rte_status_t open_link_blocking ( rte_site_role_t * rs)
static

Startup: the listen side opens once; the connect side retries until startup_timeout_ms (container start order is not guaranteed).

Definition at line 168 of file rte_site_role.c.

◆ init_channel_and_negotiator()

rte_status_t init_channel_and_negotiator ( rte_site_role_t * rs,
bool resume_standby )
static

(Re)initializes the dual channel and the negotiator over the open link. A reconnect resumes this channel's own identity (startup timestamp, and ONLINE if it is ONLINE) instead of re-litigating the startup tie-break; a start-up next to a running A/B sibling resumes the site's role the same way (REQ-SITEROLE-017: ONLINE when the sibling is ONLINE, STANDBY through resume_standby otherwise). A reconnect passes resume_standby false: a STANDBY reconnect keeps re-deciding from its resumed timestamp.

Definition at line 200 of file rte_site_role.c.

◆ close_link()

void close_link ( rte_site_role_t * rs)
static

Definition at line 254 of file rte_site_role.c.

◆ reconnect()

rte_status_t reconnect ( rte_site_role_t * rs)
static

One bounded reconnect attempt per cycle on the cyclic executive's own thread (REQ-SITEROLE-012): with a silent counterpart a longer bound stretched every cycle of the site, also the ONLINE one.

Definition at line 265 of file rte_site_role.c.

◆ send_frame()

bool send_frame ( rte_site_role_t * rs,
uint32_t cycle )
static

Definition at line 289 of file rte_site_role.c.

◆ receive_frame()

rte_status_t receive_frame ( rte_site_role_t * rs,
uint32_t cycle,
bool quiet )
static

Definition at line 307 of file rte_site_role.c.

◆ handle_send_miss_and_link_teardown()

void handle_send_miss_and_link_teardown ( rte_site_role_t * rs,
uint32_t cycle,
bool send_ok,
rte_status_t receive_status )
static

REQ-SITEROLE-013: closes the link after send_miss_threshold consecutive unacknowledged sends (one lost UDP datagram is routine) or at once on a receive failure other than a timeout (ADR-027).

Definition at line 374 of file rte_site_role.c.

◆ update_standby_warmth()

void update_standby_warmth ( rte_site_role_t * rs,
uint32_t cycle )
static

STANDBY, once per cycle: drops a snapshot that has gone stale (STANDBY goes cold) and logs the warm transition.

Definition at line 423 of file rte_site_role.c.

◆ poll_sibling_source()

void poll_sibling_source ( rte_site_role_t * rs,
uint32_t cycle )
static

Polls the sibling source once per cycle; a fresh frame is stamped with this cycle.

Definition at line 457 of file rte_site_role.c.

◆ sibling_reachable()

bool sibling_reachable ( const rte_site_role_t * rs)
static

The sibling's frame counts as reachable while it is at most sibling_reach_cycles old (the rule GP applied to its peer link: "frame within the last 3 cycles"). A cycle number that went back (a state transfer renumbers cycles) makes the frame stale rather than letting the unsigned difference wrap.

Definition at line 471 of file rte_site_role.c.

◆ fill_sibling_facts()

void fill_sibling_facts ( const rte_site_role_t * rs,
const rte_site_role_local_t * local,
rte_site_role_input_t * in )
static

With a source, the sibling facts are derived here; without one the application's local facts apply (step 3).

Definition at line 478 of file rte_site_role.c.

◆ check_sibling_after_decision()

void check_sibling_after_decision ( rte_site_role_t * rs,
uint32_t cycle,
const rte_site_role_local_t * local )
static

After the role decision of this cycle (REQ-SITEROLE-014 against the role just decided): the same check, log lines and NEGOTIATION_MISMATCH event the application ran itself in step 3. Without a source the verdict stays UNKNOWN.

Definition at line 497 of file rte_site_role.c.

◆ startup_role_from_sibling()

void startup_role_from_sibling ( rte_site_role_t * rs,
bool * resume_standby )
static

Start-up role from the A/B sibling (REQ-SITEROLE-017), after the cycle-0 poll: a known sibling frame decides the start-up role - ONLINE when the sibling reports ONLINE, STANDBY otherwise (resume_standby) - so this channel joins the site's role instead of evaluating the timestamp tie-break. The frame's ready and single_mode take no part. Without a frame the tie-break runs as before; without a source nothing changes.

Definition at line 509 of file rte_site_role.c.

◆ build_decision_input()

void build_decision_input ( const rte_site_role_t * rs,
const rte_site_role_local_t * local,
rte_site_role_input_t * in )
static

Definition at line 539 of file rte_site_role.c.

◆ reason_changed()

bool reason_changed ( const rte_site_role_t * rs,
rte_site_role_reason_t reason )
static

Definition at line 560 of file rte_site_role.c.

◆ set_reason()

void set_reason ( rte_site_role_t * rs,
rte_site_role_reason_t reason )
static

Definition at line 565 of file rte_site_role.c.

◆ run_site_role_decision()

void run_site_role_decision ( rte_site_role_t * rs,
uint32_t cycle,
const rte_site_role_local_t * local )
static

Gathers the facts, asks rte_site_role_decide(), applies the one action it returns (REQ-SITEROLE-011).

Definition at line 572 of file rte_site_role.c.

◆ take_local()

void take_local ( rte_site_role_t * rs,
const rte_site_role_local_t * local )
static

Definition at line 629 of file rte_site_role.c.

◆ read_u32_le()

uint32_t read_u32_le ( const uint8_t * in)
static

Definition at line 637 of file rte_site_role.c.

◆ challenge_lifetime()

uint32_t challenge_lifetime ( const rte_site_role_t * rs)
static

Definition at line 642 of file rte_site_role.c.

◆ draw_challenge()

void draw_challenge ( rte_site_role_t * rs,
uint32_t cycle )
static

Definition at line 648 of file rte_site_role.c.

◆ refresh_challenge()

void refresh_challenge ( rte_site_role_t * rs,
uint32_t cycle )
static

Definition at line 675 of file rte_site_role.c.

◆ record_takeover_confirmation()

void record_takeover_confirmation ( rte_site_role_t * rs,
uint32_t cycle,
const char * how )
static

Definition at line 688 of file rte_site_role.c.

◆ trace_ignored_while_online()

void trace_ignored_while_online ( const rte_site_role_t * rs)
static

Definition at line 701 of file rte_site_role.c.

◆ check_token()

rte_site_role_token_result_t check_token ( const rte_site_role_t * rs,
const uint8_t * token,
size_t token_len )
static

Definition at line 709 of file rte_site_role.c.

◆ token_result_text()

const char * token_result_text ( rte_site_role_token_result_t result)
static

Definition at line 743 of file rte_site_role.c.

◆ rte_site_role_init()

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.

Returns
RTE_STATUS_OK; RTE_STATUS_INVALID_PARAM for a NULL argument, a missing callback or buffer, or a frame_size not larger than RTE_SITE_ROLE_FRAME_OVERHEAD.

Definition at line 777 of file rte_site_role.c.

◆ rte_site_role_start()

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.

Parameters
rsService state, initialized by rte_site_role_init(). NULL returns RTE_STATUS_INVALID_PARAM.
Returns
RTE_STATUS_OK with the startup role known (rte_site_role_is_online()); the link failure status, or RTE_STATUS_TIMEOUT if the negotiation did not settle (the link is closed again).

Definition at line 805 of file rte_site_role.c.

◆ rte_site_role_execute()

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.

◆ rte_site_role_service_link()

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.

◆ rte_site_role_sync_standby()

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.

◆ rte_site_role_on_takeover_confirm()

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_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.

Parameters
tokenRTE_SITE_ROLE_TOKEN_LEN bytes as described above
token_lennumber of bytes in token
Returns
the verdict; only RTE_SITE_ROLE_TOKEN_ACCEPTED records a confirmation.

Definition at line 1041 of file rte_site_role.c.

◆ rte_site_role_takeover_challenge()

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).

Parameters
outreceives the challenge
Returns
true when a challenge is held; false before the first rte_site_role_execute() or when rte_random failed.

Definition at line 1075 of file rte_site_role.c.

◆ rte_site_role_note_lost_contact()

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.

◆ rte_site_role_flush_faulted()

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_check_sibling()

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.

Parameters
own_single_modethis channel's single-channel mode at the time of the check
Returns
the verdict; on RTE_SITE_ROLE_SIBLING_FAULT the application shall enter its fault reaction (the disagreement has been logged as NEGOTIATION_MISMATCH).

Definition at line 1110 of file rte_site_role.c.

◆ rte_site_role_sibling_verdict()

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).

Parameters
rsthe service; may be NULL
Returns
the verdict; RTE_SITE_ROLE_SIBLING_UNKNOWN with no sibling source configured, before the first execute or for a NULL rs.

Definition at line 1160 of file rte_site_role.c.

◆ rte_site_role_shutdown()

void rte_site_role_shutdown ( rte_site_role_t * rs)

Closes the link. Idempotent.

Definition at line 1165 of file rte_site_role.c.

◆ rte_site_role_is_online()

bool rte_site_role_is_online ( const rte_site_role_t * rs)
Returns
true while this channel is ONLINE.

Definition at line 1173 of file rte_site_role.c.

◆ rte_site_role_get_status()

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.

◆ rte_site_role_get_negotiator_states()

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.