15#include "rte/oal/log/rte_log.h"
16#include "rte/oal/memory/rte_mem_util.h"
17#include "rte/utils/safestate/rte_safestate.h"
18#include "rte/oal/timer/rte_timer.h"
19#include "rte/redundancy/watchdog/rte_watchdog.h"
66 "SAF",
"could not stage a SaF frame for the train", NULL);
90 if ((poll_ctx != NULL) &&
98 (void)snprintf(info,
sizeof(info),
"train=%u status=%d", (
unsigned int)train_id, (
int)res->
status);
99 rte_log_write_event(RTE_LOG_LEVEL_WARNING,
site_config_name(ctx->site), ctx->cyc_cycle,
"Train",
100 ctx->role_tag,
"SAF",
"frame rejected", info);
103 (void)snprintf(info,
sizeof(info),
"train=%u", (
unsigned int)train_id);
104 rte_log_write_event(RTE_LOG_LEVEL_INFO,
site_config_name(ctx->site), ctx->cyc_cycle,
"Train",
105 ctx->role_tag,
"SAF",
"train released the safe connection", info);
115 uint8_t train_id = 0U;
116 const uint8_t *frame = NULL;
123 ctx->
role_tag,
"SAF",
"SaF envelope dropped (protection off or malformed)", NULL);
131 const uint8_t *bytes)
161 ctx->
role_tag,
"SAF",
"unprotected ERTMS frame dropped", NULL);
171 ctx->cyc_cycle * ctx->config.timers.cycle_period_ms))
177 RTE_EXAMPLE_LOG(
"[%s] cycle %u: rejected malformed/unknown RBC_MSG_ERTMS_ENVELOPE frame (train %u)\n",
178 ctx->role_tag, ctx->cyc_cycle, (
unsigned int)bytes[1]);
179 rte_log_write_event(RTE_LOG_LEVEL_WARNING,
site_config_name(ctx->site), ctx->cyc_cycle,
"Train",
180 ctx->role_tag,
"ERTMS_ENVELOPE",
"rejected malformed/unknown frame", NULL);
192 uint8_t req_level = 0U;
200 rte_log_set_level((rte_log_level_t)req_level);
205 ctx->
role_tag,
"C",
"LOG_LEVEL",
"applied from C",
206 rte_log_level_to_string((rte_log_level_t)req_level));
259 if (size >=
sizeof(rte_vital_message_t))
261 rte_mem_copy(&reply_frame[1], payload,
sizeof(rte_vital_message_t));
279 if (size >=
sizeof(rte_vital_message_t))
325 "promoted to ONLINE", NULL);
331 "demoted to STANDBY", NULL);
348 uint32_t peer_cycle = 0U;
358 if (status == RTE_STATUS_DATA_CORRUPTION)
360 RTE_EXAMPLE_LOG(
"[%s] cycle %u: CRC-64 mismatch on peer link - data cannot be trusted, entering SAFE state\n",
363 "AB_SAMPLE",
"CRC-64 mismatch - entering SAFE state", NULL);
366 else if (status != RTE_STATUS_OK)
369 rte_status_to_string(status));
371 "AB_SAMPLE", rte_status_to_string(status), NULL);
380 RTE_EXAMPLE_LOG(
"[%s] cycle %u: dual transfer received sample from peer (peer_cycle=%u, CRC=OK)\n",
384 "received sample from peer (CRC=OK)", NULL);
402 if (timeout_cycles == 0U)
417 uint8_t own_role_byte;
419 uint32_t drained_count;
426 return RTE_STATUS_INVALID_PARAM;
439 if (status != RTE_STATUS_OK)
448 rte_watchdog_timer_tick();
485 relay_poll.
ctx = ctx;
496 if ((lost & ((uint32_t)1U << i)) != 0U)
500 (void)snprintf(info,
sizeof(info),
"train=%u", (
unsigned int)(i + 1U));
502 ctx->
role_tag,
"SAF",
"safe connection supervision expired - link lost", info);
509 if (drained_count > 0U)
514 if (drained_count == 0U)
516 RTE_EXAMPLE_LOG(
"[%s] cycle %u: no envelopes from C yet - skipping this cycle's decision\n",
519 "ENVELOPE",
"none received", NULL);
523 RTE_EXAMPLE_LOG(
"[%s] cycle %u: [%s] %u envelope(s) received - standby, not processed\n",
525 (
unsigned int)drained_count);
527 "ENVELOPE",
"received - standby, not processed", NULL);
538 return RTE_STATUS_OK;
void ab_gp_channel_poll_peer(ab_gp_channel_handle_t handle, ab_gp_com_peer_frame_cb cb, void *user_ctx)
Polls the A<->B peer channel non-blockingly and invokes cb for every received frame.
rte_status_t ab_gp_channel_send_peer(ab_gp_channel_handle_t handle, const uint8_t *bytes, size_t size)
Sends a frame over the A<->B peer channel.
uint32_t ab_gp_channel_poll_relays(ab_gp_channel_handle_t handle, ab_gp_com_envelope_cb cb, void *user_ctx)
Polls all C relay channels non-blockingly and invokes cb for every received envelope.
rte_status_t ab_gp_channel_wait_cycle_tick(ab_gp_channel_handle_t handle)
Waits for the periodic cycle timer tick, advances cycle, and refreshes watchdog/checkpoint state.
void ab_gp_channel_poll_crosscompare(ab_gp_channel_handle_t handle, ab_gp_com_peer_frame_cb cb, void *user_ctx)
Polls the dedicated A<->B cross-compare channel non-blockingly and invokes cb for every received fram...
struct ab_gp_channel_context_s * ab_gp_channel_handle_t
Opaque handle over this component's own static per-process context.
void ab_gp_channel_crosscompare_check_site_state(ab_gp_channel_context_t *ctx)
Reacts to the A/B role agreement verdict: this channel's own independently-negotiated {online,...
The actual A-vs-B cross-compare decision: does this cycle's own M24/M15 answer match what the peer in...
Shared declarations for the four rte_appmanager_operations_t cyclic-executive hooks this component's ...
rte_status_t ab_gp_channel_pre_execute(void *context)
const char * ab_gp_channel_dual_role_byte_to_string(uint8_t role_byte)
void ab_gp_channel_dual_on_transfer_lost(void *context)
Everything related to this channel's own "dual transfer" state: the single-mode degradation reaction ...
void ab_gp_channel_negotiate_execute(ab_gp_channel_context_t *ctx, uint32_t cycle)
Runs one cycle's worth of inter-site negotiation: drives the negotiator's own STATE-frame exchange (d...
void ab_gp_channel_negotiate_on_startup_ts_frame(ab_gp_channel_context_t *ctx, const uint8_t *payload, size_t size)
Handles a PEER_MSG_KIND_STARTUP_TS frame that arrives after ab_gp_channel_negotiate_init() returned (...
This channel's own West<->East inter-site negotiation link - see ab_gp_channel.c's file header for ho...
rte_status_t ab_gp_channel_payload_decode_ab_sample(uint8_t in[AB_SAMPLE_WIRE_SIZE], uint32_t *out_cycle, void *const dests[AB_GP_CHANNEL_PAYLOAD_MAX_COLLECTORS])
Decodes and CRC-64-verifies an A<->B peer-link sample.
Generic, data-blind wire framing for the A<->B peer link's AB_SAMPLE frame (CRC-64-protected,...
#define AB_GP_CHANNEL_PAYLOAD_MAX_COLLECTORS
void ab_gp_channel_stage_reset(ab_gp_channel_handle_t handle)
Clears this cycle's pending-send queue.
rte_status_t ab_gp_channel_stage_relay(ab_gp_channel_handle_t handle, rte_example_relay_kind_t kind, uint8_t index, const uint8_t *bytes, size_t size)
Queues a relay-link send for this cycle - does not transmit yet.
Stage-then-commit output queue for this cycle's own DECISION output (ADR-034): the peer AB_SAMPLE and...
Modular type definitions for AB channel components (Com, Train, DB, Redundancy).
#define AB_SAMPLE_WIRE_SIZE
#define PEER_WIRE_FRAME_SIZE
#define PEER_MSG_KIND_KM114_DIGEST
#define PEER_MSG_KIND_CHECKPOINT_REQUEST
#define PEER_MSG_KIND_STARTUP_TS
#define PEER_MSG_KIND_AB_SAMPLE
#define PEER_MSG_KIND_CHECKPOINT_REPLY
#define PEER_MSG_KIND_SITE_STATE
#define PEER_MSG_KIND_SAF_RB
bool ab_gp_dispatch_il_envelope(ab_gp_train_session_t *sessions, ab_gp_db_t *db, const uint8_t env_bytes[RBC_ENVELOPE_WIRE_SIZE], uint32_t cycle, rte_example_site_t site, const char *role_tag)
Calls the registered IL envelope handler, if any - see ab_gp_register_il_envelope_handler()'s own doc...
GP's own dispatch side of the "GP calls into GA" surface - see ga_interface.h's own "functions GP cal...
int ab_gp_km114_client_on_peer_digest(const uint8_t *payload, size_t size, const char *role_tag, rte_example_site_t site)
Consumes a PEER_MSG_KIND_KM114_DIGEST frame from the A/B sibling (called from pre_execute....
A/B-side Subset-114 KMC message decoder - step 2 of Platform_Protocol_KM114's "Consumption design" (s...
bool ab_gp_proc_dispatch_train_inbound(ab_gp_channel_handle_t channel, ab_gp_train_session_t sessions[], ab_gp_db_t *db, uint8_t train_id, const uint8_t *payload, size_t payload_len, uint32_t cycle, uint32_t timestamp_ms)
Decodes one RBC_MSG_ERTMS_ENVELOPE payload and dispatches it into the ertms_procedures/ engine,...
Glue between RBC_MSG_ERTMS_ENVELOPE wire frames and the real Subset-026 procedure engine (ab_gp_ertms...
bool ab_gp_saf_envelope_decode(const uint8_t env[RBC_TRAIN_ENVELOPE_WIRE_SIZE], uint8_t *out_train_id, const uint8_t **out_frame, size_t *out_len)
Splits a received RBC_MSG_SAF_ENVELOPE relay frame.
void ab_gp_saf_train_on_peer_rb(ab_gp_saf_train_t *s, const uint8_t *payload, size_t size, uint32_t now_ms, ab_gp_saf_result_t *out)
B only: processes A's PEER_MSG_KIND_SAF_RB payload; answers the parked AU1 when its RA matches.
bool ab_gp_saf_envelope_encode(uint8_t train_id, const uint8_t *frame, size_t frame_len, uint8_t out[RBC_TRAIN_ENVELOPE_WIRE_SIZE])
Builds an RBC_MSG_SAF_ENVELOPE relay frame (RBC_TRAIN_ENVELOPE_WIRE_SIZE bytes).
uint32_t ab_gp_saf_train_supervise(ab_gp_saf_train_t *s, uint32_t now_ms)
Idle-link supervision of every connection in DATA (REQ-SC-004).
void ab_gp_saf_train_on_frame(ab_gp_saf_train_t *s, uint8_t train_id, const uint8_t *frame, size_t frame_len, uint32_t now_ms, ab_gp_saf_result_t *out)
Processes one SaF frame received from train slot train_id (1..RTE_EXAMPLE_MAX_TRAINS).
Train link safe communication (Subset-037 SaF) terminated inside A and B - REQ-SC-001,...
@ AB_GP_SAF_ACTION_REJECTED
@ AB_GP_SAF_ACTION_DISCONNECTED
#define AB_GP_SAF_PEER_RB_SIZE
PEER_MSG_KIND_SAF_RB payload: train_id(1) + RA(8) + RB(8).
bool ab_gp_sibling_state_store(ab_gp_sibling_state_t *st, const uint8_t *payload, size_t size)
Stores a received site-state frame payload: the rule of on_peer_frame_received() (the payload must ca...
The A/B sibling's last site-state frame (PEER_MSG_KIND_SITE_STATE), kept raw and handed to Platform_R...
bool ab_gp_train_apply_envelope(ab_gp_train_session_t sessions[], ab_gp_db_t *db, const uint8_t env_bytes[RBC_ENVELOPE_WIRE_SIZE], uint32_t cycle, bool is_role_a, rte_example_site_t site, const char *role_tag, uint32_t cyc_msg_type_due[], bool cyc_position_reply_due[])
THE single entry point com/'s ab_gp_channel.c calls for every raw envelope popped off its dedicated T...
uint32_t ab_gp_train_payload_collector_id(void)
A/B's own train lifecycle handling against db/'s runtime table.
#define RTE_EXAMPLE_SITE_ROLE_STANDBY
#define RTE_EXAMPLE_LOG(...)
#define RTE_EXAMPLE_REASON_AB_CRC_MISMATCH
#define RTE_EXAMPLE_SITE_ROLE_ONLINE
#define RBC_TRAIN_ENVELOPE_WIRE_SIZE
#define RTE_EXAMPLE_MAX_TRAINS
#define RTE_EXAMPLE_SITE_ROLE_FAULTED
static uint32_t saf_now_ms(const ab_gp_channel_context_t *ctx)
The channel's cycle clock in ms - the same time base ab_gp_proc_dispatch_train_inbound() is given.
static void on_peer_frame_received(void *user_ctx, uint8_t kind, const uint8_t *payload, size_t size)
static void saf_apply_result(ab_gp_channel_context_t *ctx, relay_poll_context_t *poll_ctx, uint8_t train_id, const ab_gp_saf_result_t *res)
Acts on the outcome of one SaF frame (from the train or, for B, A's shared RB).
static void saf_stage_to_train(ab_gp_channel_context_t *ctx, uint8_t train_id, const uint8_t *frame, size_t len)
Stages a SaF frame for a train on the Train relay (committed with this cycle's other outputs,...
static void log_role_transition(ab_gp_channel_context_t *ctx, uint32_t cycle)
Log and record an ONLINE/STANDBY role transition, if one happened this cycle.
static void on_saf_envelope(relay_poll_context_t *poll_ctx, const uint8_t *bytes)
static void on_relay_envelope_received(void *user_ctx, rte_example_relay_kind_t kind, uint8_t index, const uint8_t *bytes)
static void on_crosscompare_frame_received(void *user_ctx, uint8_t kind, const uint8_t *payload, size_t size)
static void check_dual_transfer_timeout(ab_gp_channel_context_t *ctx, uint32_t cycle)
Declare a dual-transfer loss if no peer sample has arrived within the configured timeout.
static void decode_and_apply_peer_sample(ab_gp_channel_context_t *ctx, peer_poll_context_t *peer_poll)
Decode this cycle's dual-transfer peer sample (if any) and apply it to ctx.
static bool rbc_envelope_is_set_log_level(const uint8_t in[RBC_ENVELOPE_WIRE_SIZE], uint8_t *out_level)
true if in is a set-log-level control frame; *out_level (if non-NULL) then receives the requested lev...
static bool rbc_envelope_is_keepalive(const uint8_t in[RBC_ENVELOPE_WIRE_SIZE])
true if in is a keepalive frame - see rbc_envelope_write_keepalive()'s own doc. Callers on the receiv...
const char * site_config_name(rte_example_site_t site)
West/East site identity and the per-site config derived from it (ports, container host lookup) - see ...
rte_example_relay_kind_t
Which client type a C<->A/C<->B relay link/port belongs to - this project's own dedicated-channel-per...
@ RTE_EXAMPLE_RELAY_KIND_IL
@ RTE_EXAMPLE_RELAY_KIND_TRAIN
Central application context owned by composition root (main.c).
uint8_t deferred_peer_frames[AB_GP_DEFERRED_PEER_FRAMES][PEER_WIRE_FRAME_SIZE]
ab_gp_sibling_state_t peer_site_state
uint32_t last_peer_checkpoint_cycle
ab_gp_train_session_t sessions[RTE_EXAMPLE_MAX_TRAINS]
bool cyc_position_reply_due[RTE_EXAMPLE_MAX_TRAINS]
bool has_cached_checkpoint_request
uint32_t cyc_msg_type_due[RTE_EXAMPLE_MAX_TRAINS]
uint32_t last_relay_rx_cycle
ab_gp_train_session_t cyc_peer_sessions[RTE_EXAMPLE_MAX_TRAINS]
bool cyc_have_channel_data
uint8_t cached_checkpoint_reply[sizeof(rte_vital_message_t)]
ab_gp_saf_train_t saf_train
uint8_t deferred_peer_count
uint8_t cached_checkpoint_request[sizeof(rte_vital_message_t)]
bool has_cached_checkpoint_reply
uint32_t last_peer_sample_cycle
ab_gp_config_timers_t timers
uint32_t dual_transfer_timeout_ms
Output of ab_gp_saf_train_on_frame() / _on_peer_rb().
uint8_t app[AB_GP_SAF_PDU_MAX]
uint8_t frame[SAFECOMM_SAF_AU2_LEN]
uint8_t rb_share[AB_GP_SAF_PEER_RB_SIZE]
ab_gp_saf_action_t action
uint8_t peer_bytes[AB_SAMPLE_WIRE_SIZE]
ab_gp_channel_context_t * ctx
ab_gp_channel_context_t * ctx