Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions score/time_slave/src/application/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ cc_binary(
visibility = ["//score/time_slave:__pkg__"],
deps = [
"//score/time_slave/src/application/configuration",
"//score/time_slave/src/common:definitions",
"//score/time_slave/src/common:logging_contexts",
"//score/time_slave/src/gptp:gptp_engine",
"//score/ts_client/src:gptp_ipc",
Expand Down
1 change: 1 addition & 0 deletions score/time_slave/src/application/configuration/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ cc_library(
tags = ["QM"],
visibility = ["//score/time_slave:__subpackages__"],
deps = [
"//score/time_slave/src/common:definitions",
"//score/time_slave/src/common:logging_contexts",
"//score/time_slave/src/gptp:gptp_engine",
"@score_baselibs//score/json",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ TEST(ConfigParserTest, EmptyObjectReturnsDefaults)
EXPECT_EQ(cfg.engine_opts.jump_future_threshold_ns, 500'000'000LL);
EXPECT_EQ(cfg.shm_path, "/gptp_shmem");
EXPECT_FALSE(cfg.engine_opts.phc_config.enabled);
EXPECT_EQ(cfg.qnx.bpf_device_prefix, "/dev/bpf");
EXPECT_EQ(cfg.qnx.bpf_device_prefix, score::ts::env::qnx::kBpfDevicePrefixDefault);
EXPECT_FALSE(cfg.qnx.see_sent);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef SCORE_TIME_SLAVE_CONFIGURATION_TIME_SLAVE_CONFIG_H
#define SCORE_TIME_SLAVE_CONFIGURATION_TIME_SLAVE_CONFIG_H

#include "score/time_slave/src/common/definitions.h"
#include "score/time_slave/src/gptp/gptp_engine.h"
#include "score/time_slave/src/gptp/phc/phc_adjuster.h"

Expand Down Expand Up @@ -42,8 +43,8 @@ struct TimeSlaveConfig
/// QNX-specific settings. Only relevant on QNX builds.
struct QnxSettings
{
std::string bpf_device_prefix = "/dev/bpf"; ///< BPF device path prefix.
bool see_sent = false; ///< Deliver sent frames to RX BPF.
std::string bpf_device_prefix = env::qnx::kBpfDevicePrefixDefault; ///< BPF device path prefix.
bool see_sent = false; ///< Deliver sent frames to RX BPF.
};

QnxSettings qnx{};
Expand Down
19 changes: 12 additions & 7 deletions score/time_slave/src/application/time_slave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "score/mw/log/logging.h"
#include "score/time_slave/src/application/configuration/config_parser.h"
#include "score/time_slave/src/common/definitions.h"
#include "score/time_slave/src/common/logging_contexts.h"

#include <cstdlib>
Expand Down Expand Up @@ -48,13 +49,14 @@ std::int32_t TimeSlave::Initialize(const score::mw::lifecycle::ApplicationContex
{
config_path = cli_config;
}
else if (const char* env_config = std::getenv("TIMESLAVE_CONFIG"); env_config != nullptr && env_config[0] != '\0')
else if (const char* env_config = std::getenv(score::ts::env::kTimeSlaveConfigEnv);
env_config != nullptr && env_config[0] != '\0')
{
config_path = env_config;
}
else
{
config_path = "./etc/time_slave_config.json";
config_path = score::ts::env::kTimeSlaveConfigDefaultPath;
}

TimeSlaveConfig cfg;
Expand All @@ -74,7 +76,8 @@ std::int32_t TimeSlave::Initialize(const score::mw::lifecycle::ApplicationContex
}

// Legacy env-var override: GPTP_IFACE overrides iface_name.
if (const char* iface_env = std::getenv("GPTP_IFACE"); iface_env != nullptr && iface_env[0] != '\0')
if (const char* iface_env = std::getenv(score::ts::env::kGptpInterfaceEnv);
iface_env != nullptr && iface_env[0] != '\0')
{
opts_.iface_name = iface_env;
score::mw::log::LogInfo(kTimeSlaveAppContext) << "Using interface from GPTP_IFACE: " << opts_.iface_name;
Expand All @@ -83,13 +86,15 @@ std::int32_t TimeSlave::Initialize(const score::mw::lifecycle::ApplicationContex
// Apply QNX-specific settings via environment variables (read by the QNX
// raw-socket shim). Pre-existing env vars are never overridden so users can
// still override at the command line.
if (!cfg.qnx.bpf_device_prefix.empty() && std::getenv("SOCK") == nullptr)
// NOTE: do not write to SOCK here. On QNX that variable is used by socket
// APIs; setting it to a BPF device path can break socket/getifaddrs calls.
if (!cfg.qnx.bpf_device_prefix.empty() && std::getenv(score::ts::env::qnx::kBpfDevicePrefixEnv) == nullptr)
{
::setenv("SOCK", cfg.qnx.bpf_device_prefix.c_str(), 0);
::setenv(score::ts::env::qnx::kBpfDevicePrefixEnv, cfg.qnx.bpf_device_prefix.c_str(), 0);
}
if (cfg.qnx.see_sent && std::getenv("QNX_RAW_SEESENT") == nullptr)
if (cfg.qnx.see_sent && std::getenv(score::ts::env::qnx::kRawSeeSentEnv) == nullptr)
{
::setenv("QNX_RAW_SEESENT", "1", 0);
::setenv(score::ts::env::qnx::kRawSeeSentEnv, "1", 0);
}

engine_ = std::make_unique<details::GptpEngine>(opts_);
Expand Down
6 changes: 6 additions & 0 deletions score/time_slave/src/common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ cc_library(
hdrs = ["logging_contexts.h"],
visibility = ["//score/time_slave:__subpackages__"],
)

cc_library(
name = "definitions",
hdrs = ["definitions.h"],
visibility = ["//score/time_slave:__subpackages__"],
)
46 changes: 46 additions & 0 deletions score/time_slave/src/common/definitions.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/********************************************************************************
* Copyright (c) 2026 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Apache License Version 2.0 which is available at
* https://www.apache.org/licenses/LICENSE-2.0
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

#ifndef SCORE_TIME_SLAVE_SRC_COMMON_DEFINITIONS_H
#define SCORE_TIME_SLAVE_SRC_COMMON_DEFINITIONS_H

namespace score::ts::env
{

/// Environment variable name for the TimeSlave configuration file path.
static constexpr auto kTimeSlaveConfigEnv = "TIMESLAVE_CONFIG";

/// Default path for the TimeSlave configuration file.
static constexpr auto kTimeSlaveConfigDefaultPath = "./etc/time_slave_config.json";

/// Environment variable name for the gPTP interface override.
static constexpr auto kGptpInterfaceEnv = "GPTP_IFACE";

namespace qnx
{
/// Environment variable name for the QNX BPF device prefix.
/// Used to override the default BPF device prefix (e.g., "/dev/bpf") for raw socket operations.
static constexpr auto kBpfDevicePrefixEnv = "QNX_BPF_DEVICE_PREFIX";

/// Default QNX BPF device prefix ("/dev/bpf").
static constexpr auto kBpfDevicePrefixDefault = "/dev/bpf";

/// Default QNX BPF device default("/dev/bpf0").
static constexpr auto kBpfDeviceDefault = "/dev/bpf0";

/// Environment variable name for enabling raw SEE sent.
static constexpr auto kRawSeeSentEnv = "QNX_RAW_SEESENT";
} // namespace qnx
} // namespace score::ts::env

#endif // SCORE_TIME_SLAVE_SRC_COMMON_DEFINITIONS_H
1 change: 1 addition & 0 deletions score/time_slave/src/gptp/details/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ cc_library(
":os_syscalls",
":ptp_types",
":raw_socket",
"//score/time_slave/src/common:definitions",
],
)

Expand Down
19 changes: 11 additions & 8 deletions score/time_slave/src/gptp/platform/qnx/qnx_raw_shim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
*
* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

#include "score/time_slave/src/common/definitions.h"

#include <arpa/inet.h>
#include <fcntl.h>
#include <net/bpf.h>
Expand Down Expand Up @@ -199,11 +202,11 @@ static int set_iface_promisc(const char* ifname) noexcept
static int open_tx_loopback_fd(const char* ifname) noexcept
{
char devpath[256]{};
const char* sock_env = std::getenv("SOCK");
if (sock_env != nullptr && sock_env[0] != '\0')
std::snprintf(devpath, sizeof(devpath), "%s/dev/bpf0", sock_env);
const char* bpf_env = std::getenv(score::ts::env::qnx::kBpfDevicePrefixEnv);
if (bpf_env != nullptr && bpf_env[0] != '\0')
std::snprintf(devpath, sizeof(devpath), "%s%s", bpf_env, score::ts::env::qnx::kBpfDeviceDefault);
else
std::snprintf(devpath, sizeof(devpath), "/dev/bpf");
std::snprintf(devpath, sizeof(devpath), score::ts::env::qnx::kBpfDevicePrefixDefault);

const int fd = ::open(devpath, O_RDWR);
if (fd < 0)
Expand Down Expand Up @@ -252,11 +255,11 @@ extern "C" int qnx_raw_open(const char* ifname)
::strlcpy(g_qnx_ctx.iface_name, ifname, sizeof(g_qnx_ctx.iface_name));

char devpath[256]{};
const char* sock_env = std::getenv("SOCK");
if (sock_env != nullptr && sock_env[0] != '\0')
std::snprintf(devpath, sizeof(devpath), "%s/dev/bpf0", sock_env);
const char* bpf_env = std::getenv(score::ts::env::qnx::kBpfDevicePrefixEnv);
if (bpf_env != nullptr && bpf_env[0] != '\0')
std::snprintf(devpath, sizeof(devpath), "%s%s", bpf_env, score::ts::env::qnx::kBpfDeviceDefault);
else
std::snprintf(devpath, sizeof(devpath), "/dev/bpf");
std::snprintf(devpath, sizeof(devpath), score::ts::env::qnx::kBpfDevicePrefixDefault);

int fd = ::open(devpath, O_RDWR);
if (fd < 0)
Expand Down
Loading