RTE RBC 2oo2 Reference Application 0.1.0 build 0006685
SIL 4 2oo2 Dual-Site Fault-Tolerant ERTMS Radio Block Centre Reference Architecture
Loading...
Searching...
No Matches
ab_gp_channel.c File Reference

Channel A / channel B com layer using native RTE rte_channel_service. More...

#include "ab_gp_channel.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "rte/redundancy/checkpoint/rte_checkpoint.h"
#include "rte/redundancy/channel_service/rte_channel_service.h"
#include "rte/redundancy/channel_service/rte_channel_service_flow_osadapter.h"
#include "rte/posix_osadapter/rte_posix_osadapter_channel_service.h"
#include "rte/protocol_adapter_dds/rte_protocol_adapter_dds.h"
#include "rte_osadapter/flow/rte_osadapter_flow.h"
#include "rte/oal/log/rte_log.h"
#include "rte/oal/memory/rte_mem_util.h"
#include "rte/utils/safestate/rte_safestate.h"
#include "../../common/common_config.h"
#include "../../common/rbc_util_frame.h"
#include "ab_gp_channel_checkpoint.h"
#include "ab_gp_channel_crosscompare.h"
#include "ab_gp_channel_dual.h"
#include "ab_gp_channel_negotiate.h"
#include "ab_gp_standby_policy.h"
#include "ab_gp_channel_types.h"
#include "ab_gp_channel_util.h"
#include "ab_gp_channel_payload.h"
#include "ab_gp_km114_relay.h"
#include "../ga_interface/ga_interface.h"
#include "../main/ab_gp_ga_hooks.h"
#include "../train/ab_gp_train.h"
#include "../ertms_procedures/ab_gp_ertms_engine.h"
Include dependency graph for ab_gp_channel.c:

Go to the source code of this file.

Functions

static void apply_host_env_override (const char *name, const ab_gp_channel_context_t *ctx, rte_netlink_config_t *config)
static bool try_resolve_from_redundancy_config (const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
static bool try_resolve_from_legacy_config (const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
static bool relay_kind_from_name (const char *name, rte_example_relay_kind_t *out_kind)
static uint32_t message_size_for_relay_kind (rte_example_relay_kind_t rk)
static rte_status_t resolve_channel_hardcoded_fallback (const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
static void enforce_hardcoded_port (const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
static rte_status_t resolve_channel (const char *name, rte_netlink_config_t *config, void *context)
static rte_status_t resolve_channel_flow (const char *name, rte_netlink_config_t *config, void *context)
static bool ab_gp_supports_redundancy (rte_redundancy_topology_t topology, uint32_t replica_count, void *context)
static rte_status_t channel_service_setup_with_retry (rte_channel_service_t *storage, const char *name)
static void cycle_tick_callback (rte_timer_handle_t handle, void *user_ctx)
static void ab_gp_channel_safestate_handler (rte_safestate_level_t level, rte_safestate_reason_t reason, const char *file, int32_t line, const char *message)
static void load_legacy_config (ab_gp_channel_context_t *ctx, rte_example_site_t site, bool is_role_a)
 Load the legacy .conf config into ctx->config: RTE_CONFIG_FILE override, or the default etc/config/<role>_<site>.conf with an /etc/sapi/... fallback.
static rte_status_t load_redundancy_config (ab_gp_channel_context_t *ctx, rte_example_site_t site, bool is_role_a)
 Load the app-level redundancy topology config into ctx->redundancy (RCA/OCORA Phase 8).
static rte_status_t open_relay_channels (ab_gp_channel_context_t *ctx)
 Open the relay channel for each rte_example_relay_kind_t.
rte_status_t ab_gp_channel_open_link (bool is_role_a, rte_example_site_t site, ab_gp_channel_handle_t *out_handle)
 Opens this process's own A<->B peer channel and C relay channels.
void ab_gp_channel_close_link (ab_gp_channel_handle_t handle)
 Full teardown of a channel opened by ab_gp_channel_open_link().
rte_status_t ab_gp_channel_checkpoint_setup (ab_gp_channel_handle_t handle)
 Wires AppManager checkpoint mechanism onto peer channel.
rte_status_t ab_gp_channel_dual_setup (ab_gp_channel_handle_t handle)
 Wires dual-transfer liveness watchdog.
const rte_appmanager_checkpoint_config_t * ab_gp_channel_checkpoint_config (ab_gp_channel_handle_t handle)
 Accessor for checkpoint config.
rte_status_t ab_gp_channel_crosscompare_setup (ab_gp_channel_handle_t handle)
 Creates cross-comparator on an already-open channel.
rte_status_t ab_gp_channel_init (void *context)
 rte_appmanager_operations_t::init hook.
rte_status_t ab_gp_channel_train_codec_setup (ab_gp_channel_handle_t handle)
 GP-internal registration for train codec.
rte_status_t ab_gp_channel_ga_setup (ab_gp_channel_handle_t handle)
 GA registration for ma_logic_adaptation / il / ctc.
void ab_gp_channel_relay_queues_setup (ab_gp_channel_handle_t handle)
 Initializes relay queues (no-op in single-threaded channel_service).
rte_status_t ab_gp_channel_negotiate_setup (ab_gp_channel_handle_t handle)
 Opens inter-site negotiation link and runs startup tie-break.
rte_status_t ab_gp_channel_watchdog_setup (ab_gp_channel_handle_t handle)
 Arms general health watchdog.
rte_status_t ab_gp_channel_cycle_timer_setup (ab_gp_channel_handle_t handle)
 Creates and starts periodic cycle timer.
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.
static rte_status_t send_util_gated (ab_gp_channel_context_t *ctx, const uint8_t *bytes, size_t size)
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.
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.
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 frame.
rte_status_t ab_gp_channel_send_crosscompare (ab_gp_channel_handle_t handle, uint8_t kind, const uint8_t *payload, size_t size)
 Sends a frame over the dedicated A<->B cross-compare channel.
rte_status_t ab_gp_channel_send_relay (ab_gp_channel_handle_t handle, rte_example_relay_kind_t kind, uint8_t index, const uint8_t *bytes, size_t size)
 Sends an envelope over a specific C relay channel.
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.
ab_gp_saf_train_t * ab_gp_channel_saf_train (ab_gp_channel_handle_t handle)
 This channel's train-link SaF termination (ab_gp_saf_train.h), or NULL for a NULL handle.
rte_status_t ab_gp_channel_saf_train_setup (ab_gp_channel_handle_t handle)
 Reads RTE_SAFECOMM_TRAIN_RBC_ID and sets up the train-link SaF termination: unset leaves it off (plain ERTMS frames, the behaviour before it existed); set to this RBC's ETCS identity (1..0xFFFFFF, decimal or 0x hex) turns it on.
void ab_gp_channel_raise_ctc_alarm (ab_gp_channel_handle_t handle, rbc_alarm_severity_t severity, uint32_t code, const char *log_message)
 Raises a severity-leveled operational alarm: logs it locally (rte_log_write_event(), same structured Site/Cycle/Source/ Destination/Type/Info convention as every other event this codebase logs) AND forwards it to CTC (RBC_MSG_CTC_ALARM, see that kind's own doc in rbc_wire_types.h), so a human dispatcher sees it too, not just this process's own log.
rte_status_t ab_gp_channel_shutdown (void *context)
 rte_appmanager_operations_t::shutdown hook.

Variables

static ab_gp_channel_context_t g_ab_ctx

Detailed Description

Channel A / channel B com layer using native RTE rte_channel_service.

Single-threaded cyclic executive transport module conforming to CENELEC EN 50128 SIL 4 safety principles and Single Responsibility Principle (SRP).

Definition in file ab_gp_channel.c.

Function Documentation

◆ apply_host_env_override()

void apply_host_env_override ( const char * name,
const ab_gp_channel_context_t * ctx,
rte_netlink_config_t * config )
static

Definition at line 49 of file ab_gp_channel.c.

◆ try_resolve_from_redundancy_config()

bool try_resolve_from_redundancy_config ( const ab_gp_channel_context_t * ctx,
const char * name,
rte_netlink_config_t * config )
static

Definition at line 101 of file ab_gp_channel.c.

◆ try_resolve_from_legacy_config()

bool try_resolve_from_legacy_config ( const ab_gp_channel_context_t * ctx,
const char * name,
rte_netlink_config_t * config )
static

Definition at line 145 of file ab_gp_channel.c.

◆ relay_kind_from_name()

bool relay_kind_from_name ( const char * name,
rte_example_relay_kind_t * out_kind )
static

Definition at line 169 of file ab_gp_channel.c.

◆ message_size_for_relay_kind()

uint32_t message_size_for_relay_kind ( rte_example_relay_kind_t rk)
static

Definition at line 197 of file ab_gp_channel.c.

◆ resolve_channel_hardcoded_fallback()

rte_status_t resolve_channel_hardcoded_fallback ( const ab_gp_channel_context_t * ctx,
const char * name,
rte_netlink_config_t * config )
static

Definition at line 214 of file ab_gp_channel.c.

◆ enforce_hardcoded_port()

void enforce_hardcoded_port ( const ab_gp_channel_context_t * ctx,
const char * name,
rte_netlink_config_t * config )
static

Definition at line 270 of file ab_gp_channel.c.

◆ resolve_channel()

rte_status_t resolve_channel ( const char * name,
rte_netlink_config_t * config,
void * context )
static

Definition at line 300 of file ab_gp_channel.c.

◆ resolve_channel_flow()

rte_status_t resolve_channel_flow ( const char * name,
rte_netlink_config_t * config,
void * context )
static

RCA/OCORA Phase 4 (see docs/rca/ at the workspace root and TODO.md's "RCA/OCORA compatibility" section): wraps resolve_channel() unchanged - same host/port/role/message_size resolution GP has always done - and additionally registers a route with the DDS-stub OSAdapter (safeAPIFlowBackendDDS) so rte_flow_open(name) can find it. A real DDS OSAdapter would need no such route (topics are self-describing via discovery); this wrapper is where that stub-specific wiring belongs, not inside rte_channel_service_flow_osadapter itself (deliberately osadapter-agnostic - see that module's own header doc). Every channel this process opens through rte_channel_service (ab-peer, ab-negotiate, ab-relay-*) shares this ONE resolver, since rte_channel_service has exactly one globally-registered OSAdapter per process - wire-compatible with role C's own still-POSIX-backed relay endpoints, since safeAPIFlowBackendDDS's stub delegates directly to rte_netlink with no extra framing (confirmed by reading dds_send()/dds_receive() - a plain passthrough).

Definition at line 339 of file ab_gp_channel.c.

◆ ab_gp_supports_redundancy()

bool ab_gp_supports_redundancy ( rte_redundancy_topology_t topology,
uint32_t replica_count,
void * context )
static

RCA/OCORA Phase 8 follow-up (see docs/rca/ and TODO.md): GP declares what it can actually run to rte_redundancy_config itself, via rte_redundancy_config_register_capability() - the Platform (the framework's own load()) then owns rejecting an unsupported config, instead of GP's own call site parsing the result and re-implementing the same allowlist check inline. Matches the "Platform decides, the Application only declares" posture rte_voter/rte_cross_comparator's own safestate-transition ownership already established this session.

Definition at line 357 of file ab_gp_channel.c.

◆ channel_service_setup_with_retry()

rte_status_t channel_service_setup_with_retry ( rte_channel_service_t * storage,
const char * name )
static

RCA/OCORA Phase 4: the flow-backed rte_channel_service_setup() path (through safeAPIFlowBackendDDS's dds_open() -> rte_netlink_open()) waits SYNCHRONOUSLY for the peer's HELLO/ACK handshake inside setup() itself, bounded by config->connect_timeout_ms - a real behavioral difference from safeAPIBackendPosix's own channel_service OSAdapter (osadapter_setup() fires the connect/HELLO and returns immediately, deferring ACK consumption to the first osadapter_read() call, so a slow peer never blocks setup()). Found live: with the same reconnect_attempt_timeout_ms=1000 budget every existing .conf file already specifies, "ab-relay-util" (opened last of the 4 relay channels, so most exposed to a loaded host's scheduling jitter) timed out under machine load while the original POSIX-backed path passed cleanly at identical ports - isolated by literally reverting this file's own change and re-running the same test, not assumed. Fixed the same way ab_gp_channel_negotiate.c's own open_connect_with_retry() already handles this exact class of problem for the site-negotiation link: retry setup() in a bounded loop instead of widening the per-attempt timeout (widening was tried and reverted for the A/B checkpoint rendezvous for the same reason - see this project's own CLAUDE.md "A/B checkpoint rendezvous" section - a wider single budget just delays the same failure, retrying actually recovers from a transient scheduling stall).

Definition at line 396 of file ab_gp_channel.c.

◆ cycle_tick_callback()

void cycle_tick_callback ( rte_timer_handle_t handle,
void * user_ctx )
static

Definition at line 426 of file ab_gp_channel.c.

◆ ab_gp_channel_safestate_handler()

void ab_gp_channel_safestate_handler ( rte_safestate_level_t level,
rte_safestate_reason_t reason,
const char * file,
int32_t line,
const char * message )
static

Definition at line 433 of file ab_gp_channel.c.

◆ load_legacy_config()

void load_legacy_config ( ab_gp_channel_context_t * ctx,
rte_example_site_t site,
bool is_role_a )
static

Load the legacy .conf config into ctx->config: RTE_CONFIG_FILE override, or the default etc/config/<role>_<site>.conf with an /etc/sapi/... fallback.

Definition at line 465 of file ab_gp_channel.c.

◆ load_redundancy_config()

rte_status_t load_redundancy_config ( ab_gp_channel_context_t * ctx,
rte_example_site_t site,
bool is_role_a )
static

Load the app-level redundancy topology config into ctx->redundancy (RCA/OCORA Phase 8).

Absent file (the common case today - no deployment ships one yet) is NOT an error - falls back to the hardcoded 2oo2 defaults matching this file's own actual, only-ever-verified behavior, same "file optional, sensible default" posture load_legacy_config()'s own loading uses. A file that IS present but names a topology GP cannot actually run fails startup outright (RTE_STATUS_NOT_SUPPORTED from load() itself, per ab_gp_supports_redundancy()) - honestly reflecting real capability rather than silently accepting a config GP does not implement.

Returns
RTE_STATUS_NOT_SUPPORTED if the on-disk topology is rejected (caller must abort startup); RTE_STATUS_OK otherwise (a load failure just falls back to 2oo2 defaults).

Definition at line 501 of file ab_gp_channel.c.

◆ open_relay_channels()

rte_status_t open_relay_channels ( ab_gp_channel_context_t * ctx)
static

Open the relay channel for each rte_example_relay_kind_t.

Definition at line 547 of file ab_gp_channel.c.

◆ ab_gp_channel_open_link()

rte_status_t ab_gp_channel_open_link ( bool is_role_a,
rte_example_site_t site,
ab_gp_channel_handle_t * out_handle )

Opens this process's own A<->B peer channel and C relay channels.

Definition at line 583 of file ab_gp_channel.c.

◆ ab_gp_channel_close_link()

void ab_gp_channel_close_link ( ab_gp_channel_handle_t handle)

Full teardown of a channel opened by ab_gp_channel_open_link().

Definition at line 664 of file ab_gp_channel.c.

◆ ab_gp_channel_checkpoint_setup()

rte_status_t ab_gp_channel_checkpoint_setup ( ab_gp_channel_handle_t handle)

Wires AppManager checkpoint mechanism onto peer channel.

Definition at line 672 of file ab_gp_channel.c.

◆ ab_gp_channel_dual_setup()

rte_status_t ab_gp_channel_dual_setup ( ab_gp_channel_handle_t handle)

Wires dual-transfer liveness watchdog.

Definition at line 737 of file ab_gp_channel.c.

◆ ab_gp_channel_checkpoint_config()

const rte_appmanager_checkpoint_config_t * ab_gp_channel_checkpoint_config ( ab_gp_channel_handle_t handle)

Accessor for checkpoint config.

Definition at line 752 of file ab_gp_channel.c.

◆ ab_gp_channel_crosscompare_setup()

rte_status_t ab_gp_channel_crosscompare_setup ( ab_gp_channel_handle_t handle)

Creates cross-comparator on an already-open channel.

Definition at line 759 of file ab_gp_channel.c.

◆ ab_gp_channel_init()

rte_status_t ab_gp_channel_init ( void * context)

rte_appmanager_operations_t::init hook.

Definition at line 770 of file ab_gp_channel.c.

◆ ab_gp_channel_train_codec_setup()

rte_status_t ab_gp_channel_train_codec_setup ( ab_gp_channel_handle_t handle)

GP-internal registration for train codec.

Definition at line 788 of file ab_gp_channel.c.

◆ ab_gp_channel_ga_setup()

rte_status_t ab_gp_channel_ga_setup ( ab_gp_channel_handle_t handle)

GA registration for ma_logic_adaptation / il / ctc.

Definition at line 804 of file ab_gp_channel.c.

◆ ab_gp_channel_relay_queues_setup()

void ab_gp_channel_relay_queues_setup ( ab_gp_channel_handle_t handle)

Initializes relay queues (no-op in single-threaded channel_service).

Definition at line 818 of file ab_gp_channel.c.

◆ ab_gp_channel_negotiate_setup()

rte_status_t ab_gp_channel_negotiate_setup ( ab_gp_channel_handle_t handle)

Opens inter-site negotiation link and runs startup tie-break.

Definition at line 823 of file ab_gp_channel.c.

◆ ab_gp_channel_watchdog_setup()

rte_status_t ab_gp_channel_watchdog_setup ( ab_gp_channel_handle_t handle)

Arms general health watchdog.

Definition at line 838 of file ab_gp_channel.c.

◆ ab_gp_channel_cycle_timer_setup()

rte_status_t ab_gp_channel_cycle_timer_setup ( ab_gp_channel_handle_t handle)

Creates and starts periodic cycle timer.

Definition at line 880 of file ab_gp_channel.c.

◆ ab_gp_channel_wait_cycle_tick()

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.

Definition at line 919 of file ab_gp_channel.c.

◆ send_util_gated()

rte_status_t send_util_gated ( ab_gp_channel_context_t * ctx,
const uint8_t * bytes,
size_t size )
static

Definition at line 1002 of file ab_gp_channel.c.

◆ ab_gp_channel_poll_relays()

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.

Returns
Count of envelopes drained across all relay channels this cycle.

Definition at line 1029 of file ab_gp_channel.c.

◆ ab_gp_channel_poll_peer()

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.

Definition at line 1116 of file ab_gp_channel.c.

◆ ab_gp_channel_poll_crosscompare()

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

Definition at line 1135 of file ab_gp_channel.c.

◆ ab_gp_channel_send_crosscompare()

rte_status_t ab_gp_channel_send_crosscompare ( ab_gp_channel_handle_t handle,
uint8_t kind,
const uint8_t * payload,
size_t size )

Sends a frame over the dedicated A<->B cross-compare channel.

Definition at line 1154 of file ab_gp_channel.c.

◆ ab_gp_channel_send_relay()

rte_status_t ab_gp_channel_send_relay ( ab_gp_channel_handle_t handle,
rte_example_relay_kind_t kind,
uint8_t index,
const uint8_t * bytes,
size_t size )

Sends an envelope over a specific C relay channel.

Definition at line 1171 of file ab_gp_channel.c.

◆ ab_gp_channel_send_peer()

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.

Definition at line 1221 of file ab_gp_channel.c.

◆ ab_gp_channel_saf_train()

ab_gp_saf_train_t * ab_gp_channel_saf_train ( ab_gp_channel_handle_t handle)

This channel's train-link SaF termination (ab_gp_saf_train.h), or NULL for a NULL handle.

Definition at line 1233 of file ab_gp_channel.c.

◆ ab_gp_channel_saf_train_setup()

rte_status_t ab_gp_channel_saf_train_setup ( ab_gp_channel_handle_t handle)

Reads RTE_SAFECOMM_TRAIN_RBC_ID and sets up the train-link SaF termination: unset leaves it off (plain ERTMS frames, the behaviour before it existed); set to this RBC's ETCS identity (1..0xFFFFFF, decimal or 0x hex) turns it on.

Returns
RTE_STATUS_OK, or RTE_STATUS_INVALID_PARAM for a value that is set but not a valid identity - the caller treats that as a fatal startup error rather than silently running the link unprotected.

Definition at line 1240 of file ab_gp_channel.c.

◆ ab_gp_channel_raise_ctc_alarm()

void ab_gp_channel_raise_ctc_alarm ( ab_gp_channel_handle_t handle,
rbc_alarm_severity_t severity,
uint32_t code,
const char * log_message )

Raises a severity-leveled operational alarm: logs it locally (rte_log_write_event(), same structured Site/Cycle/Source/ Destination/Type/Info convention as every other event this codebase logs) AND forwards it to CTC (RBC_MSG_CTC_ALARM, see that kind's own doc in rbc_wire_types.h), so a human dispatcher sees it too, not just this process's own log.

Sends immediately (bypasses the ADR-034 checkpoint-gated stage queue, ab_gp_channel_stage.h) - callers reacting to an already-decided fault (about to shut down/reboot) must call this BEFORE ab_gp_channel_shutdown() closes the CTC relay socket, or the alarm never leaves the process. Best-effort: a failed send is logged locally (via rte_log_write_event() above) but does not fail the caller's own fault-reaction sequence - see this function's own .c comment for why blocking a reboot on a diagnostic send would be exactly backwards.

Parameters
handleA valid, already-open channel handle.
severityAlarm severity.
codeCaller-defined numeric reason/fault code (e.g. a rte_safestate_reason_t or RTE_EXAMPLE_REASON_* value) - carried on the wire as-is.
log_messageHuman-readable text for the LOCAL log line only (not carried on the wire - see rbc_wire_types.h's own doc on why RBC_MSG_CTC_ALARM stays coded, not free-text, matching every other kind in this enum). May be NULL.

Definition at line 1290 of file ab_gp_channel.c.

◆ ab_gp_channel_shutdown()

rte_status_t ab_gp_channel_shutdown ( void * context)

rte_appmanager_operations_t::shutdown hook.

Definition at line 1343 of file ab_gp_channel.c.

Variable Documentation

◆ g_ab_ctx

ab_gp_channel_context_t g_ab_ctx
static

Definition at line 41 of file ab_gp_channel.c.