15#include "rte/redundancy/checkpoint/rte_checkpoint.h"
16#include "rte/redundancy/channel_service/rte_channel_service.h"
17#include "rte/redundancy/channel_service/rte_channel_service_flow_osadapter.h"
18#include "rte/posix_osadapter/rte_posix_osadapter_channel_service.h"
19#include "rte/protocol_adapter_dds/rte_protocol_adapter_dds.h"
20#include "rte_osadapter/flow/rte_osadapter_flow.h"
21#include "rte/oal/log/rte_log.h"
22#include "rte/oal/memory/rte_mem_util.h"
23#include "rte/utils/safestate/rte_safestate.h"
53 if ((strcmp(name,
"ab-peer") == 0) || (strcmp(name,
"ab-crosscompare") == 0))
56 if ((env_host != NULL) && (env_host[0] !=
'\0'))
58 config->host = env_host;
60 else if ((config->host == NULL) || (config->host[0] ==
'\0') ||
61 (strcmp(config->host,
"a-west") == 0) || (strcmp(config->host,
"a-east") == 0))
63 config->host =
"127.0.0.1";
66 else if (strcmp(name,
"ab-negotiate") == 0)
70 env_host = getenv(env_var);
71 if ((env_host != NULL) && (env_host[0] !=
'\0'))
73 config->host = env_host;
75 else if ((config->host == NULL) || (config->host[0] ==
'\0') ||
76 (strcmp(config->host,
"a-west") == 0) || (strcmp(config->host,
"b-west") == 0))
78 config->host =
"127.0.0.1";
84 if ((env_host != NULL) && (env_host[0] !=
'\0'))
86 config->host = env_host;
88 else if ((config->host == NULL) || (config->host[0] ==
'\0') ||
89 (strcmp(config->host,
"c-west") == 0) || (strcmp(config->host,
"c-east") == 0))
91 config->host =
"127.0.0.1";
102 rte_netlink_config_t *config)
104 const rte_channel_def_t *found_ch = NULL;
109 for (ch_i = 0U; ch_i < ctx->
redundancy.channel_count; ch_i++)
111 if (strcmp(ctx->
redundancy.channels[ch_i].name, name) == 0)
118 if (found_ch == NULL)
123 rte_mem_set(config, 0,
sizeof(*config));
124 config->role = (found_ch->role == RTE_CHANNEL_ROLE_CONNECT) ? RTE_NETLINK_ROLE_CONNECT : RTE_NETLINK_ROLE_LISTEN;
125 config->host = (config->role == RTE_NETLINK_ROLE_CONNECT && found_ch->host[0] !=
'\0') ? found_ch->host : NULL;
126 if (config->role == RTE_NETLINK_ROLE_CONNECT)
130 config->port = found_ch->port;
132 if ((strcmp(name,
"ab-peer") == 0) || (strcmp(name,
"ab-crosscompare") == 0))
137 config->connect_timeout_ms = (found_ch->connect_timeout_ms > 0U) ? found_ch->connect_timeout_ms
146 rte_netlink_config_t *config)
152 if (config->role == RTE_NETLINK_ROLE_CONNECT)
156 if ((strcmp(name,
"ab-peer") == 0) || (strcmp(name,
"ab-crosscompare") == 0))
160 else if (config->message_size == 0U)
171 if (strcmp(name,
"ab-relay-train") == 0)
176 if (strcmp(name,
"ab-relay-il") == 0)
181 if (strcmp(name,
"ab-relay-ctc") == 0)
186 if (strcmp(name,
"ab-relay-util") == 0)
215 rte_netlink_config_t *config)
219 rte_mem_set(config, 0,
sizeof(*config));
222 if (strcmp(name,
"ab-peer") == 0)
224 config->role = ctx->
is_role_a ? RTE_NETLINK_ROLE_LISTEN : RTE_NETLINK_ROLE_CONNECT;
228 return RTE_STATUS_OK;
230 if (strcmp(name,
"ab-crosscompare") == 0)
232 config->role = ctx->
is_role_a ? RTE_NETLINK_ROLE_LISTEN : RTE_NETLINK_ROLE_CONNECT;
236 return RTE_STATUS_OK;
240 config->role = RTE_NETLINK_ROLE_CONNECT;
245 return RTE_STATUS_OK;
247 return RTE_STATUS_INVALID_PARAM;
271 rte_netlink_config_t *config)
273 uint16_t formula_port;
275 if (strcmp(name,
"ab-peer") == 0)
279 else if (strcmp(name,
"ab-crosscompare") == 0)
288 if (formula_port != config->port)
292 (void)snprintf(info,
sizeof(info),
"channel=%s config_port=%u formula_port=%u", name,
293 (
unsigned int)config->port, (
unsigned int)formula_port);
295 "CONFIG_DRIFT",
"config-file port ignored - common_config.h formula wins", info);
296 config->port = formula_port;
300static rte_status_t
resolve_channel(
const char *name, rte_netlink_config_t *config,
void *context)
310 return RTE_STATUS_OK;
318 return RTE_STATUS_OK;
342 if (status == RTE_STATUS_OK)
344 (void)rte_protocol_adapter_dds_add_route(name, config->host, config->port);
360 bool supported = (replica_count == 2U) &&
361 ((topology == RTE_REDUNDANCY_TOPOLOGY_2OO2) ||
362 (topology == RTE_REDUNDANCY_TOPOLOGY_2OO2_REDUNDANT));
367 "[%s] redundancy config names topology=%s replicas=%u - not yet implemented "
368 "(only 2oo2/2oo2_redundant with exactly 2 replicas run today)\n",
369 ctx->
role_tag, rte_redundancy_config_topology_to_string(topology), (
unsigned int)replica_count);
398 rte_timestamp_ms_t waited_ms = 0U;
399 const unsigned int retry_delay_ms = 100U;
405 status = rte_channel_service_setup(storage, name);
406 if (status == RTE_STATUS_OK)
409 return RTE_STATUS_OK;
416 waited_ms += retry_delay_ms;
434 const char *file, int32_t line,
const char *message)
438 (
unsigned int)reason, (file != NULL) ? file :
"?", (
int)line,
439 (message != NULL) ?
" - " :
"", (message != NULL) ? message :
"");
441 "-",
"SAFE_HALT", (message != NULL) ? message :
"entering SAFE state", NULL);
448 (message != NULL) ? message :
"entering SAFE state");
450 if (reason == RTE_SAFESTATE_REASON_CHECKPOINT_TIMEOUT)
453 "[%s] checkpoint timeout treated as peer-link-down (REQ-RBC, ADR-029 2.6) - rebooting, not halting\n",
467 const char *env_cfg = getenv(
"RTE_CONFIG_FILE");
469 const char *role_str = is_role_a ?
"a" :
"b";
477 char default_cfg_path[128];
478 (void)snprintf(default_cfg_path,
sizeof(default_cfg_path),
"etc/config/%s_%s.conf", role_str, site_str);
481 (void)snprintf(default_cfg_path,
sizeof(default_cfg_path),
"/etc/sapi/%s_%s.conf", role_str, site_str);
503 const char *env_redundancy_cfg = getenv(
"RTE_REDUNDANCY_CONFIG_FILE");
505 const char *role_str = is_role_a ?
"a" :
"b";
506 char json_cfg_path[128];
507 const char *redundancy_cfg_path = env_redundancy_cfg;
508 rte_status_t redundancy_status;
510 if (redundancy_cfg_path == NULL)
512 (void)snprintf(json_cfg_path,
sizeof(json_cfg_path),
"etc/config/%s_%s.json", role_str, site_str);
513 redundancy_cfg_path = json_cfg_path;
516 redundancy_status = rte_redundancy_config_load(redundancy_cfg_path, &ctx->
redundancy);
517 if ((redundancy_status != RTE_STATUS_OK) && (env_redundancy_cfg == NULL))
519 redundancy_status = rte_redundancy_config_load(
"etc/config/redundancy.json", &ctx->
redundancy);
522 if (redundancy_status == RTE_STATUS_NOT_SUPPORTED)
526 return RTE_STATUS_NOT_SUPPORTED;
528 if (redundancy_status != RTE_STATUS_OK)
531 ctx->
redundancy.topology = RTE_REDUNDANCY_TOPOLOGY_2OO2;
534 ctx->
redundancy.standby_mode = RTE_STANDBY_MODE_COLD;
538 rte_redundancy_config_topology_to_string(ctx->
redundancy.topology),
540 rte_redundancy_config_standby_mode_to_string(ctx->
redundancy.standby_mode));
541 return RTE_STATUS_OK;
559 name =
"ab-relay-train";
563 name =
"ab-relay-il";
567 name =
"ab-relay-util";
571 name =
"ab-relay-ctc";
574 if (status != RTE_STATUS_OK)
576 RTE_EXAMPLE_LOG(
"[%s] relay channel setup failed for %s: %s\n", ctx->
role_tag, name, rte_status_to_string(status));
580 return RTE_STATUS_OK;
588 if (out_handle == NULL)
590 return RTE_STATUS_INVALID_PARAM;
594 rte_mem_set(ctx, 0,
sizeof(*ctx));
613 return RTE_STATUS_NOT_SUPPORTED;
622 status = rte_osadapter_flow_register(rte_protocol_adapter_dds_get_vtable());
623 if (status != RTE_STATUS_OK)
626 rte_status_to_string(status));
630 if (status != RTE_STATUS_OK)
637 if (status != RTE_STATUS_OK)
641 ctx->
is_role_a ?
"B" :
"A",
"LINK",
"peer channel setup failed", NULL);
646 if (status != RTE_STATUS_OK)
650 ctx->
is_role_a ?
"B" :
"A",
"LINK",
"crosscompare channel setup failed", NULL);
655 if (status != RTE_STATUS_OK)
661 return RTE_STATUS_OK;
679 return RTE_STATUS_INVALID_PARAM;
683 rte_channel_config_t checkpoint_vc_cfg;
684 rte_voter_config_t checkpoint_voter_cfg;
691 rte_mem_set(&checkpoint_vc_cfg, 0,
sizeof(checkpoint_vc_cfg));
697 rte_mem_set(&checkpoint_voter_cfg, 0,
sizeof(checkpoint_voter_cfg));
698 checkpoint_voter_cfg.voting_strategy = RTE_VOTING_NMR;
699 checkpoint_voter_cfg.quorum_size = 1U;
703 if (status == RTE_STATUS_OK)
705 status = rte_channel_init(&ctx->
checkpoint_vc, &checkpoint_vc_cfg);
707 if (status == RTE_STATUS_OK)
711 if (status != RTE_STATUS_OK)
713 RTE_EXAMPLE_LOG(
"[%s] checkpoint channel/voter init failed (%s) - built-in checkpoint disabled this run\n",
714 ctx->
role_tag, rte_status_to_string(status));
716 ctx->
is_role_a ?
"B" :
"A",
"CHECKPOINT",
717 "channel/voter init failed - built-in checkpoint disabled this run", NULL);
721 rte_timestamp_ms_t init_now_ms = 0U;
730 (void)rte_timer_now(&init_now_ms);
743 return RTE_STATUS_INVALID_PARAM;
749 return RTE_STATUS_OK;
765 return RTE_STATUS_INVALID_PARAM;
773 uint32_t discarded_ticks = 0U;
778 if (status != RTE_STATUS_OK)
785 return RTE_STATUS_OK;
794 if (status != RTE_STATUS_OK)
797 rte_status_to_string(status));
799 "train session codec registration failed", NULL);
829 if (status != RTE_STATUS_OK)
831 RTE_EXAMPLE_LOG(
"[%s] inter-site negotiation init failed (%s)\n", ctx->
role_tag, rte_status_to_string(status));
833 "NEGOTIATION",
"init failed", NULL);
841 rte_watchdog_config_t wd_cfg;
844 rte_mem_set(&wd_cfg, 0,
sizeof(wd_cfg));
845 wd_cfg.type = RTE_WATCHDOG_CHANNEL;
848 wd_cfg.action = RTE_WATCHDOG_ACTION_REBOOT;
849 status = rte_watchdog_create(&ctx->
watchdog, &wd_cfg);
850 if (status == RTE_STATUS_OK)
852 (void)rte_watchdog_start(ctx->
watchdog);
874 rte_status_to_string(status));
883 rte_timer_config_t timer_cfg;
889 if (status != RTE_STATUS_OK)
892 "cycle tick mutex_create failed", NULL);
896 rte_mem_set(&timer_cfg, 0,
sizeof(timer_cfg));
897 timer_cfg.mode = RTE_TIMER_MODE_PERIODIC;
900 timer_cfg.user_ctx = ctx;
902 if (status != RTE_STATUS_OK)
906 "cycle timer_create failed", NULL);
910 if (status != RTE_STATUS_OK)
914 "cycle timer_start failed", NULL);
922 unsigned int waited_ms;
923 uint32_t pending = 0U;
928 return RTE_STATUS_INVALID_PARAM;
935 while ((status == RTE_STATUS_OK) && (pending == 0U))
943 return RTE_STATUS_TIMEOUT;
947 if (status != RTE_STATUS_OK)
957 const uint32_t missed = (pending > 1U) ? (pending - 1U) : 0U;
959 ctx->
cycle += (missed > 20U) ? 20U : missed;
964 rte_timestamp_ms_t now_ms = 0U;
966 (void)rte_timer_now(&now_ms);
977 rte_timestamp_ms_t wall_now = 0U;
978 rte_timestamp_ms_t stalled_ms = 0U;
980 (void)rte_timer_now(&wall_now);
983 rte_site_role_note_lost_contact(&ctx->
site_role);
984 RTE_EXAMPLE_LOG(
"[%s] stalled for %llu ms while ONLINE - the counterpart may have taken over, yielding if it is ONLINE\n",
985 ctx->
role_tag, (
unsigned long long)stalled_ms);
993 return RTE_STATUS_OK;
1005 rte_timestamp_ms_t now_ms = 0U;
1006 rte_status_t status;
1008 (void)rte_timer_now(&now_ms);
1011 status = RTE_STATUS_TIMEOUT;
1023 (void)rte_timer_now(&now_ms);
1038 uint32_t drained_count = 0U;
1072 while (rte_channel_service_read(&ctx->
com.
relay_channel[kind_idx], util_bytes,
1073 sizeof(util_bytes), 0U) == RTE_STATUS_OK)
1100 rte_mem_set(env_bytes, 0,
sizeof(env_bytes));
1102 env_bytes, read_size, 0U) == RTE_STATUS_OK)
1107 cb(user_ctx, kind, 0U, env_bytes);
1109 rte_mem_set(env_bytes, 0,
sizeof(env_bytes));
1113 return drained_count;
1126 while (rte_channel_service_read(&ctx->
com.
peer_channel, in_bytes,
sizeof(in_bytes), 0U) == RTE_STATUS_OK)
1130 cb(user_ctx, in_bytes[0], &in_bytes[1],
sizeof(in_bytes) - 1U);
1145 while (rte_channel_service_read(&ctx->
com.
crosscompare_channel, in_bytes,
sizeof(in_bytes), 0U) == RTE_STATUS_OK)
1149 cb(user_ctx, in_bytes[0], &in_bytes[1],
sizeof(in_bytes) - 1U);
1159 if ((ctx == NULL) || (payload == NULL) || (size > (
sizeof(out_bytes) - 1U)))
1161 return RTE_STATUS_INVALID_PARAM;
1164 rte_mem_set(out_bytes, 0,
sizeof(out_bytes));
1165 out_bytes[0] = kind;
1166 rte_mem_copy(&out_bytes[1], payload, size);
1172 uint8_t index,
const uint8_t *bytes,
size_t size)
1180 return RTE_STATUS_INVALID_PARAM;
1207 rte_mem_set(padded, 0,
sizeof(padded));
1208 rte_mem_copy(padded, bytes, size);
1209 return rte_channel_service_send(&ctx->
com.
relay_channel[kind], padded,
sizeof(padded),
1225 if (ctx == NULL || bytes == NULL || size == 0U)
1227 return RTE_STATUS_INVALID_PARAM;
1237 return (ctx == NULL) ? NULL : &ctx->
saf_train;
1243 const char *value = getenv(
"RTE_SAFECOMM_TRAIN_RBC_ID");
1250 return RTE_STATUS_INVALID_PARAM;
1252 if ((value == NULL) || (value[0] ==
'\0'))
1255 return RTE_STATUS_OK;
1257 id = strtoul(value, &end, 0);
1258 if ((end == value) || (*end !=
'\0') || (
id == 0UL) || (
id > 0xFFFFFFUL))
1261 "RTE_SAFECOMM_TRAIN_RBC_ID is not a valid ETCS identity - refusing to start", NULL);
1262 return RTE_STATUS_INVALID_PARAM;
1266 const char *keys_path = getenv(
"RTE_SAFECOMM_TRAIN_KEYS_FILE");
1267 uint32_t loaded = 0U;
1270 if ((keys_path != NULL) && (keys_path[0] !=
'\0'))
1275 "RTE_SAFECOMM_TRAIN_KEYS_FILE unreadable or malformed - refusing to start",
1277 return RTE_STATUS_INVALID_PARAM;
1279 (void)snprintf(kinfo,
sizeof(kinfo),
"keys=%u", (
unsigned int)loaded);
1281 "train KMACs loaded from RTE_SAFECOMM_TRAIN_KEYS_FILE", kinfo);
1284 (void)snprintf(info,
sizeof(info),
"rbc_etcs_id=%lu",
id);
1286 "train link protected (Subset-037 SaF terminated in this channel)", info);
1287 return RTE_STATUS_OK;
1291 const char *log_message)
1294 rte_log_level_t log_level;
1296 rte_timestamp_ms_t now_ms = 0U;
1297 rte_status_t status;
1307 log_level = RTE_LOG_LEVEL_WARNING;
1310 log_level = RTE_LOG_LEVEL_ERROR;
1314 log_level = RTE_LOG_LEVEL_INFO;
1321 (log_message != NULL) ? log_message :
"-", NULL);
1323 (void)rte_timer_now(&now_ms);
1331 if (status != RTE_STATUS_OK)
1339 "CTC",
"ALARM_SEND_FAILED", rte_status_to_string(status), NULL);
1350 return RTE_STATUS_INVALID_PARAM;
1371 (void)rte_watchdog_stop(ctx->
watchdog);
1372 (void)rte_watchdog_destroy(ctx->
watchdog);
1387 "channel done", NULL);
1388 return RTE_STATUS_OK;
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 (plai...
static uint32_t message_size_for_relay_kind(rte_example_relay_kind_t rk)
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.
static bool try_resolve_from_redundancy_config(const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
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_cycle_timer_setup(ab_gp_channel_handle_t handle)
Creates and starts periodic cycle timer.
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.
static ab_gp_channel_context_t g_ab_ctx
static void cycle_tick_callback(rte_timer_handle_t handle, void *user_ctx)
static bool ab_gp_supports_redundancy(rte_redundancy_topology_t topology, uint32_t replica_count, void *context)
void ab_gp_channel_close_link(ab_gp_channel_handle_t handle)
Full teardown of a channel opened by ab_gp_channel_open_link().
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.
rte_status_t ab_gp_channel_ga_setup(ab_gp_channel_handle_t handle)
GA registration for ma_logic_adaptation / il / ctc.
static void apply_host_env_override(const char *name, const ab_gp_channel_context_t *ctx, rte_netlink_config_t *config)
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/<r...
rte_status_t ab_gp_channel_negotiate_setup(ab_gp_channel_handle_t handle)
Opens inter-site negotiation link and runs startup tie-break.
static rte_status_t resolve_channel_hardcoded_fallback(const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
static rte_status_t channel_service_setup_with_retry(rte_channel_service_t *storage, const char *name)
static rte_status_t send_util_gated(ab_gp_channel_context_t *ctx, const uint8_t *bytes, size_t size)
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.
const rte_appmanager_checkpoint_config_t * ab_gp_channel_checkpoint_config(ab_gp_channel_handle_t handle)
Accessor for checkpoint config.
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_shutdown(void *context)
rte_appmanager_operations_t::shutdown hook.
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_crosscompare_setup(ab_gp_channel_handle_t handle)
Creates cross-comparator on an already-open channel.
static bool relay_kind_from_name(const char *name, rte_example_relay_kind_t *out_kind)
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(),...
rte_status_t ab_gp_channel_dual_setup(ab_gp_channel_handle_t handle)
Wires dual-transfer liveness watchdog.
rte_status_t ab_gp_channel_init(void *context)
rte_appmanager_operations_t::init hook.
rte_status_t ab_gp_channel_checkpoint_setup(ab_gp_channel_handle_t handle)
Wires AppManager checkpoint mechanism onto peer channel.
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)
rte_status_t ab_gp_channel_train_codec_setup(ab_gp_channel_handle_t handle)
GP-internal registration for train codec.
static bool try_resolve_from_legacy_config(const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
rte_status_t ab_gp_channel_watchdog_setup(ab_gp_channel_handle_t handle)
Arms general health watchdog.
static rte_status_t resolve_channel_flow(const char *name, rte_netlink_config_t *config, void *context)
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_wait_cycle_tick(ab_gp_channel_handle_t handle)
Waits for the periodic cycle timer tick, advances cycle, and refreshes watchdog/checkpoint state.
static void enforce_hardcoded_port(const ab_gp_channel_context_t *ctx, const char *name, rte_netlink_config_t *config)
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...
static rte_status_t resolve_channel(const char *name, rte_netlink_config_t *config, void *context)
struct ab_gp_channel_context_s * ab_gp_channel_handle_t
Opaque handle over this component's own static per-process context.
rte_status_t ab_gp_channel_checkpoint_backend_send(void *channel, const void *data, size_t data_size)
rte_channel_send_fn for the checkpoint transport: wraps the given rte_vital_message_t in a PEER_MSG_K...
rte_status_t ab_gp_channel_checkpoint_backend_recv(void *channel, void *data, size_t data_size, uint32_t timeout_ms)
rte_channel_recv_fn for the checkpoint transport: waits (bounded by timeout_ms) for a PEER_MSG_KIND_C...
rte_channel_t OSAdapter for the built-in AppManager checkpoint (ADR-019 addendum, rewired onto rte_vo...
rte_status_t ab_gp_channel_crosscompare_init(ab_gp_channel_context_t *ctx)
Creates this channel's rte_cross_comparator_t. Called once from ab_gp_channel_crosscompare_setup() (A...
The actual A-vs-B cross-compare decision: does this cycle's own M24/M15 answer match what the peer in...
Everything related to this channel's own "dual transfer" state: the single-mode degradation reaction ...
void ab_gp_channel_negotiate_on_takeover_confirm(ab_gp_channel_context_t *ctx, const char *payload)
Records a dispatcher confirmation that the other site is not ONLINE (from Gateway,...
void ab_gp_channel_negotiate_service_link(ab_gp_channel_context_t *ctx)
Fast internal-cycle service of the negotiation link (warm/hot standby only).
rte_status_t ab_gp_channel_negotiate_init(ab_gp_channel_context_t *ctx)
Opens this channel's own inter-site negotiation link (WEST LISTENs, EAST CONNECTs),...
void ab_gp_channel_negotiate_shutdown(ab_gp_channel_context_t *ctx)
This channel's own West<->East inter-site negotiation link - see ab_gp_channel.c's file header for ho...
Generic, data-blind wire framing for the A<->B peer link's AB_SAMPLE frame (CRC-64-protected,...
Modular type definitions for AB channel components (Com, Train, DB, Redundancy).
#define PEER_WIRE_FRAME_SIZE
void(*) ab_gp_com_peer_frame_cb(void *user_ctx, uint8_t kind, const uint8_t *payload, size_t size)
void ab_gp_channel_sleep_ms(unsigned int ms)
void(*) ab_gp_com_envelope_cb(void *user_ctx, rte_example_relay_kind_t kind, uint8_t index, const uint8_t *bytes)
Declares ab_gp_channel_sleep_ms() - see ab_gp_channel_types.h's own doc on why this tiny helper gets ...
rte_status_t ab_gp_config_load_file(const char *filepath, ab_gp_config_t *out_cfg)
Parses an INI-style configuration file into the static ab_gp_config_t structure.
rte_status_t ab_gp_config_init_defaults(rte_example_site_t site, bool is_role_a, ab_gp_config_t *out_cfg)
Initializes default configuration in memory based on site and role.
rte_status_t ab_gp_config_find_channel(const ab_gp_config_t *cfg, const char *channel_name, rte_netlink_config_t *out_netlink_cfg)
Resolves netlink configuration for a named channel from the parsed config.
rte_status_t ab_gp_cycle_ticks_take(ab_gp_cycle_ticks_t *ticks, uint32_t *out_pending)
Returns every pending tick and clears the count, as one critical section (cycle thread side).
rte_status_t ab_gp_cycle_ticks_teardown(ab_gp_cycle_ticks_t *ticks)
Destroys the mutex. Call only when no other task can post or take any more (the posting timer is dest...
rte_status_t ab_gp_cycle_ticks_setup(ab_gp_cycle_ticks_t *ticks)
Creates the mutex and clears the count. Setup phase only (rte_mutex_create() is a setup-only resource...
rte_status_t ab_gp_cycle_ticks_post(ab_gp_cycle_ticks_t *ticks)
Adds one tick (timer callback side). The count saturates at UINT32_MAX.
void ab_gp_ertms_engine_init(ab_gp_db_t *db)
Initializes the ERTMS procedure engine and all train contexts.
Unified ERTMS Subset-026 Chapter 5 Operational Procedure Orchestrator.
void ab_gp_build_ctc_alarm(uint8_t out[RBC_ENVELOPE_WIRE_SIZE], rbc_alarm_severity_t severity, uint32_t code, uint32_t cycle, uint32_t timestamp_ms)
Builds and wire-encodes an outbound CTC_ALARM envelope - GP's own now (moved from GA,...
GP's own dispatch side of the "GP calls into GA" surface - see ga_interface.h's own "functions GP cal...
void ab_gp_km114_relay_on_frame(const rbc_util_frame_t *frame, const char *role_tag, rte_example_site_t site, ab_gp_channel_handle_t handle)
Feeds one decoded RBC_UTIL_TOPIC_KM114_FILE publish frame into the reassembler.
A/B-side receiver for Gateway-relayed Subset-114 off-line KMC file bytes (RBC_UTIL_TOPIC_KM114_FILE,...
bool ab_gp_saf_keys_load_file(const char *path, uint32_t *out_count)
Loads KMACs from a text file: one "<etcs_id> <48 hex chars>" per line (decimal or 0x identity),...
void ab_gp_saf_train_init(ab_gp_saf_train_t *s, bool enabled, bool is_role_a, uint32_t rbc_etcs_id)
Resets s. enabled false makes every other call a no-op / rejection.
bool ab_gp_stall_lost_contact(rte_timestamp_ms_t last_ms, rte_timestamp_ms_t now_ms, bool is_online, rte_timestamp_ms_t *stalled_ms)
Whether a channel that wakes up at a cycle tick has stalled long enough to count as having lost conta...
GP-specific standby and site-link constants, the session-adoption rule and the stall rule.
rte_status_t ab_gp_train_init(void)
Registers this module's own ab_gp_train_session_t codec as a payload collector with com/ (AB/GP/com/a...
A/B's own train lifecycle handling against db/'s runtime table.
bool ab_gp_util_link_gate_is_open(const ab_gp_util_link_gate_t *gate)
Whether an open attempt has succeeded (the link is open for good).
void ab_gp_util_link_gate_on_attempt(ab_gp_util_link_gate_t *gate, rte_timestamp_ms_t now_ms)
Records that an open attempt starts now (call right before the send that triggers the open).
void ab_gp_util_link_gate_on_result(ab_gp_util_link_gate_t *gate, rte_status_t status, rte_timestamp_ms_t now_ms)
Feeds back the result of a send that ran under the gate.
bool ab_gp_util_link_gate_may_attempt(const ab_gp_util_link_gate_t *gate, rte_timestamp_ms_t now_ms)
Whether a send (and with it, before the first success, an open attempt) may run now.
#define RTE_EXAMPLE_REASON_AB_PEER_LINK_DOWN
#define RTE_EXAMPLE_C_HOST_ENV
#define RTE_EXAMPLE_UTIL_OPEN_ATTEMPT_TIMEOUT_MS
#define RTE_EXAMPLE_LOG(...)
#define RTE_EXAMPLE_A_HOST_ENV
#define RTE_EXAMPLE_REMOTE_B_HOST_ENV
#define RBC_ENVELOPE_WIRE_SIZE
#define RBC_TRAIN_ENVELOPE_WIRE_SIZE
#define RTE_EXAMPLE_REMOTE_A_HOST_ENV
#define RTE_EXAMPLE_LINK_TIMEOUT_MS
#define RTE_EXAMPLE_CONNECT_TIMEOUT_MS
THE single door GA (safeAPIRBC2oo2GA, a separate shared-library project) uses to reach GP - GP export...
rte_status_t ab_ga_ma_adaptation_init(ab_gp_train_session_t *sessions, ab_gp_db_t *db, rte_example_site_t site, const char *role_tag)
GA's own single entry point - registers this channel's route- connection validator (ab_gp_ga_register...
ADR-038: the wire frame for the A/B<->C util side channel (RTE_EXAMPLE_RELAY_KIND_UTIL) and the C-sid...
#define RBC_UTIL_TOPIC_KM114_FILE
Gateway -> A/B: raw Subset-114 off-line KMC file bytes, chunked (see rbc_util_km114_relay....
#define RBC_UTIL_FRAME_SIZE
static bool rbc_util_frame_decode(const uint8_t in[RBC_UTIL_FRAME_SIZE], rbc_util_frame_t *out)
Decodes a util frame. Returns false only on a NULL arg or a payload_len past the buffer (a corrupt fr...
#define RBC_UTIL_TOPIC_TAKEOVER_CONFIRM
Gateway -> A/B: the dispatcher has confirmed that the OTHER site is not ONLINE, so a STANDBY whose co...
rbc_alarm_severity_t
Severity of an RBC_MSG_CTC_ALARM envelope (msg_type field on the wire) - deliberately a small,...
@ RBC_ALARM_SEVERITY_WARNING
@ RBC_ALARM_SEVERITY_INFO
@ RBC_ALARM_SEVERITY_ERROR
const char * site_config_name(rte_example_site_t site)
uint16_t site_config_c_port_for_b(rte_example_site_t site, rte_example_relay_kind_t kind)
uint16_t site_config_ab_port(rte_example_site_t site)
const char * site_config_host(const char *env_var_name)
Resolves a CONNECT-role link's target host for this process.
uint16_t site_config_c_port_for_a(rte_example_site_t site, rte_example_relay_kind_t kind)
C's listen port for A's dedicated kind relay link, for this site (rte_example_relay_kind_t's own doc)...
uint16_t site_config_ab_crosscompare_port(rte_example_site_t site)
#define RTE_EXAMPLE_RELAY_KIND_COUNT
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_UTIL
@ RTE_EXAMPLE_RELAY_KIND_CTC
@ RTE_EXAMPLE_RELAY_KIND_IL
@ RTE_EXAMPLE_RELAY_KIND_TRAIN
Central application context owned by composition root (main.c).
rte_site_role_t site_role
rte_appmanager_checkpoint_config_t checkpoint_cfg
ab_gp_train_session_t sessions[RTE_EXAMPLE_MAX_TRAINS]
ab_gp_cycle_ticks_t cycle_ticks
rte_channel_t checkpoint_vc
rte_redundancy_config_t redundancy
char checkpoint_channel_name_buf[16]
void * checkpoint_channel_handle
rte_timestamp_ms_t checkpoint_relaxed_until_ms
ab_gp_saf_train_t saf_train
rte_timer_handle_t cycle_timer_handle
rte_timestamp_ms_t last_cycle_wall_ms
uint32_t last_peer_sample_cycle
rte_voter_t checkpoint_voter
rte_timer_storage_t cycle_timer_storage
ab_gp_util_link_gate_t util_gate
rte_channel_service_t relay_channel[RTE_EXAMPLE_RELAY_KIND_COUNT]
rte_channel_service_t peer_channel
rte_channel_service_t crosscompare_channel
ab_gp_config_timers_t timers
uint32_t checkpoint_relaxed_max_delay_ms
uint32_t checkpoint_max_delay_ms
uint32_t checkpoint_relax_duration_ms
uint32_t reconnect_attempt_timeout_ms
uint32_t watchdog_timeout_ms
One channel's train-link SaF termination.
Gate state; all-zero (or ab_gp_util_link_gate_init()) allows the first attempt at once.
Decoded view of a util frame (payload is a pointer into the caller's buffer, NUL-terminated into payl...
char payload_z[RBC_UTIL_PAYLOAD_MAX+1U]
rbc_util_msg_type_t msg_type