Compare commits

...

16 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] f1b3d63727
Merge remote-tracking branch 'origin/main' into refactor/centralize-env-vars
# Conflicts:
#	mooncake-pg/src/connection_poller.cpp
#	mooncake-transfer-engine/src/config.cpp

Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>
2026-04-12 16:54:33 +00:00
copilot-swe-agent[bot] c187d54a33
Fix CI build error and address review comments
- Add GetRedisUsername() to Environ class (fixes build error)
- Fix GID index: use -1 default, implement NCCL_IB_GID_INDEX fallback in Environ
- Fix supportFabricMem() inverted logic in hip_transport.cpp
- Fix nvlink_transport.cpp to use GetNvlinkFabricMemEnabled()
- Initialize raw pointers to nullptr in cxl_transport_test.cpp
- Add cxl_available_ skip guard to EvictOperation test

Agent-Logs-Url: https://github.com/kvcache-ai/Mooncake/sessions/5e01cb95-be84-4d4e-b719-867bebb19497

Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>
2026-04-03 11:20:36 +00:00
Teng Ma 28efa8ec07 Merge main into refactor/centralize-env-vars
Resolved conflict in transfer_metadata_plugin.cpp by centralizing
Redis environment variable handling through Environ::Get() API.
Added username support to match main branch's authentication capabilities.
2026-04-02 01:08:27 +08:00
Teng Ma ad1c46731c Merge main, resolve conflicts, and centralize max_mr_size env var 2026-03-25 10:50:28 +08:00
Teng Ma 36ea87a5a9 Merge origin2/main into refactor/centralize-env-vars
Resolved conflict by removing ha_helper.cpp which was deleted in main
2026-03-23 17:28:00 +08:00
Teng Ma 062aaa7f0f
Merge branch 'main' into refactor/centralize-env-vars 2026-03-21 17:50:19 +08:00
Copilot a4d62f56f0
[FIX] Fix MC_USE_NVLINK_IPC handling: distinguish unset vs explicit "0" for fabric-memory mode (#1686)
* Initial plan

* Fix GetUseNvlinkIpc to distinguish unset vs explicit 0 for MC_USE_NVLINK_IPC

Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>
2026-03-18 13:20:41 +08:00
Copilot 085bf6f29b
[TE][Store] fix: restore dynamic CXL env handling after env refactor (#1665)
* Initial plan

* fix: restore dynamic CXL env handling in TE

Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>

* fix: clarify TE RDMA transport selection

Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: stmatengss <11641725+stmatengss@users.noreply.github.com>
2026-03-16 13:30:42 +08:00
Teng Ma a9cbc6ca98 Merge remote-tracking branch 'origin/main' into refactor/centralize-env-vars
# Conflicts:
#	mooncake-transfer-engine/src/transfer_engine_impl.cpp
2026-03-16 00:41:33 +08:00
Teng Ma f66ffd6e36 update 2026-03-13 23:52:28 +08:00
Teng Ma 6eeb018d2c update 2026-02-26 01:18:28 +08:00
Teng Ma 5dcbaa1ce9 update 2026-02-26 00:27:47 +08:00
Anatolii Rozanov d85cc04f07 [TE/HIP] Do not check MC_USE_NVLINK_IPC in HIP transport 2026-02-23 13:06:05 +00:00
Teng Ma b220000763 [Bugfix] Skip CXL tests gracefully when hardware unavailable
Fix CXL hardware-dependent tests to skip instead of failing when CXL
devices are not available in CI environments.

Changes:
- mooncake-transfer-engine/tests/cxl_transport_test.cpp: Use GTEST_SKIP()
  when CXL transport installation fails
- mooncake-store/tests/cxl_client_integration_test.cpp: Skip test suite
  when CXL client creation fails, preventing segfault

This allows tests to pass (as skipped) in environments without CXL
hardware while still running properly on systems with actual devices.
2026-02-12 14:42:59 +08:00
Teng Ma 77202ae7a5 Fix compilation errors in refactor/centralize-env-vars branch
- Fix undefined variable 'value' in rpc_communicator.cpp, replace with 'rpc_protocol'
- Fix malformed InitializeMetricsConfig() function in transfer_engine_impl.cpp
- Fix malformed parseMetricsInterval() function in client_metric.cpp
- Add mooncake_common library link to transfer_engine CMakeLists.txt
- Add mooncake:: namespace qualifier to Environ::Get() calls in master.cpp

All compilation and linking errors resolved. Build completes successfully.
2026-02-12 10:59:24 +08:00
Teng Ma 5470980215 [Refactor] Centralize environment variable handling across components
Refactored environment variable access across mooncake-store and
mooncake-transfer-engine to use centralized GetEnv() functions from
mooncake-common/environ.h. This improves code maintainability and
reduces duplication.

Changes:
- Extended mooncake-common/environ.h with additional env var getters
- Updated config.cpp to use centralized env var functions (342 insertions, 404 deletions)
- Migrated all components to use GetEnv() instead of direct getenv() calls
- Affected components: client_metric, client_service, ha_helper, master,
  transfer_engine, topology, and all transport implementations
2026-02-11 23:33:19 +08:00
29 changed files with 553 additions and 481 deletions

View File

@ -45,7 +45,15 @@ include(${CMAKE_CURRENT_LIST_DIR}/limit_jobs.cmake)
option(ENABLE_SCCACHE "Whether to open sccache" OFF)
if (ENABLE_SCCACHE)
find_program(SCCACHE sccache REQUIRED)
if (DEFINED ENV{SCCACHE_PATH} AND EXISTS "$ENV{SCCACHE_PATH}")
set(SCCACHE "$ENV{SCCACHE_PATH}")
else()
find_program(SCCACHE sccache)
endif()
if (NOT SCCACHE)
message(WARNING "ENABLE_SCCACHE=ON but sccache is not found; continue without compiler launcher")
endif()
endif()
if(SCCACHE AND ENABLE_SCCACHE)
message(STATUS "Building with SCCACHE enabled")

View File

@ -33,6 +33,7 @@ class Environ {
int GetHandshakeListenBacklog() const { return handshake_listen_backlog_; }
int GetHandshakeMaxLength() const { return handshake_max_length_; }
std::string GetLogDir() const { return log_dir_; }
std::string GetRedisUsername() const { return redis_username_; }
std::string GetRedisPassword() const { return redis_password_; }
int GetRedisDbIndex() const { return redis_db_index_; }
int GetFragmentRatio() const { return fragment_ratio_; }
@ -49,6 +50,54 @@ class Environ {
bool GetForceMnnvl() const { return force_mnnvl_; }
bool GetIntraNvlink() const { return intra_nvlink_; }
bool GetPathRoundrobin() const { return path_roundrobin_; }
std::string GetCustomTopoJson() const { return custom_topo_json_; }
uint64_t GetMaxMrSize() const { return max_mr_size_; }
std::string GetCxlDevPath() const {
return GetString("MC_CXL_DEV_PATH", cxl_dev_path_);
}
std::string GetCxlDevSize() const {
return GetString("MC_CXL_DEV_SIZE", cxl_dev_size_);
}
bool GetDisableGpuDirectRdma() const { return disable_gpu_direct_rdma_; }
bool GetEnableMnnvl() const { return enable_mnnvl_; }
int GetHandshakePort() const { return handshake_port_; }
int GetHipNumEvents() const { return hip_num_events_; }
int GetHipNumStreams() const { return hip_num_streams_; }
bool GetIntranodeNvlink() const { return intranode_nvlink_; }
bool GetLegacyRpcPortBinding() const { return legacy_rpc_port_binding_; }
std::string GetMetadataClusterId() const { return metadata_cluster_id_; }
size_t GetMinRegSize() const { return min_reg_size_; }
std::string GetMsAutoDisc() const {
return GetString("MC_MS_AUTO_DISC", ms_auto_disc_);
}
std::string GetMsFilters() const { return ms_filters_; }
std::string GetRpcProtocol() const { return rpc_protocol_; }
int GetSliceTimeout() const { return slice_timeout_; }
std::string GetStoreClientMetric() const { return store_client_metric_; }
int GetStoreClientMetricInterval() const {
return store_client_metric_interval_;
}
std::string GetStoreClusterId() const { return store_cluster_id_; }
std::string GetStoreHugepageSize() const { return store_hugepage_size_; }
std::string GetStoreMemcpy() const { return store_memcpy_; }
std::string GetStoreUseHugepage() const { return store_use_hugepage_; }
std::string GetTcpBindAddress() const { return tcp_bind_address_; }
std::string GetTeMetric() const { return te_metric_; }
int GetTeMetricIntervalSeconds() const {
return te_metric_interval_seconds_;
}
std::string GetTentConf() const { return tent_conf_; }
int GetTransferTimeout() const { return transfer_timeout_; }
bool GetUseHipIpc() const { return use_hip_ipc_; }
bool GetUseNvlinkIpc() const { return use_nvlink_ipc_; }
// Returns true only when MC_USE_NVLINK_IPC is explicitly set to "0",
// which opts in to fabric-memory mode on MNNVL clusters.
bool GetNvlinkFabricMemEnabled() const {
return use_nvlink_ipc_raw_ == "0";
}
bool GetUseTent() const { return use_tent_; }
bool GetUseTev1() const { return use_tev1_; }
std::string GetYltLogLevel() const { return ylt_log_level_; }
private:
Environ();
@ -85,6 +134,7 @@ class Environ {
int handshake_listen_backlog_;
int handshake_max_length_;
std::string log_dir_;
std::string redis_username_;
std::string redis_password_;
int redis_db_index_;
int fragment_ratio_;
@ -99,6 +149,40 @@ class Environ {
bool force_mnnvl_;
bool intra_nvlink_;
bool path_roundrobin_;
std::string custom_topo_json_;
uint64_t max_mr_size_;
std::string cxl_dev_path_;
std::string cxl_dev_size_;
bool disable_gpu_direct_rdma_;
bool enable_mnnvl_;
int handshake_port_;
int hip_num_events_;
int hip_num_streams_;
bool intranode_nvlink_;
bool legacy_rpc_port_binding_;
std::string metadata_cluster_id_;
size_t min_reg_size_;
std::string ms_auto_disc_;
std::string ms_filters_;
std::string rpc_protocol_;
int slice_timeout_;
std::string store_client_metric_;
int store_client_metric_interval_;
std::string store_cluster_id_;
std::string store_hugepage_size_;
std::string store_memcpy_;
std::string store_use_hugepage_;
std::string tcp_bind_address_;
std::string te_metric_;
int te_metric_interval_seconds_;
std::string tent_conf_;
int transfer_timeout_;
bool use_hip_ipc_;
bool use_nvlink_ipc_;
std::string use_nvlink_ipc_raw_;
bool use_tent_;
bool use_tev1_;
std::string ylt_log_level_;
};
} // namespace mooncake

View File

@ -50,7 +50,11 @@ Environ::Environ() {
ib_port_ = GetInt("MC_IB_PORT", 1);
ib_tc_ = GetInt("MC_IB_TC", -1);
ib_pci_relaxed_ordering_ = GetInt("MC_IB_PCI_RELAXED_ORDERING", 0);
gid_index_ = GetInt("MC_GID_INDEX", 3);
gid_index_ = GetInt("MC_GID_INDEX", -1);
if (gid_index_ == -1) {
// Fall back to NCCL_IB_GID_INDEX when MC_GID_INDEX is not set
gid_index_ = GetInt("NCCL_IB_GID_INDEX", -1);
}
max_cqe_per_ctx_ = GetInt("MC_MAX_CQE_PER_CTX", 4096);
max_ep_per_ctx_ = GetInt("MC_MAX_EP_PER_CTX", 65536);
num_qp_per_ep_ = GetInt("MC_NUM_QP_PER_EP", 2);
@ -66,6 +70,7 @@ Environ::Environ() {
handshake_listen_backlog_ = GetInt("MC_HANDSHAKE_LISTEN_BACKLOG", 128);
handshake_max_length_ = GetInt("MC_HANDSHAKE_MAX_LENGTH", 1048576);
log_dir_ = GetString("MC_LOG_DIR", "");
redis_username_ = GetString("MC_REDIS_USERNAME", "");
redis_password_ = GetString("MC_REDIS_PASSWORD", "");
redis_db_index_ = GetInt("MC_REDIS_DB_INDEX", 0);
fragment_ratio_ = GetInt("MC_FRAGMENT_RATIO", 4);
@ -81,6 +86,41 @@ Environ::Environ() {
force_mnnvl_ = GetBool("MC_FORCE_MNNVL", false);
intra_nvlink_ = GetBool("MC_INTRA_NVLINK", false);
path_roundrobin_ = GetBool("MC_PATH_ROUNDROBIN", false);
custom_topo_json_ = GetString("MC_CUSTOM_TOPO_JSON", "");
max_mr_size_ = GetSizeT("MC_MAX_MR_SIZE", 0);
cxl_dev_path_ = GetString("MC_CXL_DEV_PATH", "");
cxl_dev_size_ = GetString("MC_CXL_DEV_SIZE", "");
disable_gpu_direct_rdma_ = GetBool("MC_DISABLE_GPU_DIRECT_RDMA", false);
enable_mnnvl_ = GetBool("MC_ENABLE_MNNVL", false);
handshake_port_ = GetInt("MC_HANDSHAKE_PORT", 0);
hip_num_events_ = GetInt("MC_HIP_NUM_EVENTS", 0);
hip_num_streams_ = GetInt("MC_HIP_NUM_STREAMS", 0);
intranode_nvlink_ = GetBool("MC_INTRANODE_NVLINK", false);
legacy_rpc_port_binding_ = GetBool("MC_LEGACY_RPC_PORT_BINDING", false);
metadata_cluster_id_ = GetString("MC_METADATA_CLUSTER_ID", "");
min_reg_size_ = GetSizeT("MC_MIN_REG_SIZE", 0);
ms_auto_disc_ = GetString("MC_MS_AUTO_DISC", "");
ms_filters_ = GetString("MC_MS_FILTERS", "");
rpc_protocol_ = GetString("MC_RPC_PROTOCOL", "");
slice_timeout_ = GetInt("MC_SLICE_TIMEOUT", 0);
store_client_metric_ = GetString("MC_STORE_CLIENT_METRIC", "");
store_client_metric_interval_ =
GetInt("MC_STORE_CLIENT_METRIC_INTERVAL", 0);
store_cluster_id_ = GetString("MC_STORE_CLUSTER_ID", "");
store_hugepage_size_ = GetString("MC_STORE_HUGEPAGE_SIZE", "");
store_memcpy_ = GetString("MC_STORE_MEMCPY", "");
store_use_hugepage_ = GetString("MC_STORE_USE_HUGEPAGE", "");
tcp_bind_address_ = GetString("MC_TCP_BIND_ADDRESS", "");
te_metric_ = GetString("MC_TE_METRIC", "");
te_metric_interval_seconds_ = GetInt("MC_TE_METRIC_INTERVAL_SECONDS", 0);
tent_conf_ = GetString("MC_TENT_CONF", "");
transfer_timeout_ = GetInt("MC_TRANSFER_TIMEOUT", 0);
use_hip_ipc_ = GetBool("MC_USE_HIP_IPC", true);
use_nvlink_ipc_ = GetBool("MC_USE_NVLINK_IPC", false);
use_nvlink_ipc_raw_ = GetString("MC_USE_NVLINK_IPC", "");
use_tent_ = GetBool("MC_USE_TENT", false);
use_tev1_ = GetBool("MC_USE_TEV1", false);
ylt_log_level_ = GetString("MC_YLT_LOG_LEVEL", "");
}
} // namespace mooncake

View File

@ -34,6 +34,7 @@ setup(
include_dirs=[
os.path.join(current_dir, "include"),
os.path.join(current_dir, "../mooncake-transfer-engine/include"),
os.path.join(current_dir, "../mooncake-common/include"),
],
sources=[
"src/ep_py.cpp",

View File

@ -1,16 +1,14 @@
#include <mooncake_ep_buffer.h>
#include <arpa/inet.h>
#include <glog/logging.h>
#include "environ.h"
namespace mooncake {
// Check if all GPUs support fabric memory handles (MNNVL).
// Mirrors the check in nvlink_transport.cpp.
static bool supportFabricMem() {
const char* nvlink_ipc = getenv("MC_USE_NVLINK_IPC");
bool fabric_enabled = nvlink_ipc && strcmp(nvlink_ipc, "0") == 0;
if (!fabric_enabled) return false;
if (!Environ::Get().GetNvlinkFabricMemEnabled()) return false;
int num_devices = 0;
cudaError_t err = cudaGetDeviceCount(&num_devices);

View File

@ -33,8 +33,9 @@ fi
EXT_LDFLAGS="-L$BUILD_DIR/mooncake-transfer-engine/src"
EXT_LDFLAGS+=" -L$BUILD_DIR/mooncake-transfer-engine/src/common/base"
EXT_LDFLAGS+=" -L$BUILD_DIR/mooncake-common/src"
EXT_LDFLAGS+=" -L$BUILD_DIR/mooncake-asio"
EXT_LDFLAGS+=" -ltransfer_engine -lbase -lasio -lstdc++ -lnuma -lglog -libverbs -ljsoncpp"
EXT_LDFLAGS+=" -ltransfer_engine -lmooncake_common -lbase -lasio -lstdc++ -lnuma -lglog -libverbs -ljsoncpp"
if [ -d "/usr/local/cuda/lib64/stubs" ]; then
EXT_LDFLAGS+=" -L/usr/local/cuda/lib64/stubs"

View File

@ -34,6 +34,7 @@ setup(
include_dirs=[
os.path.join(current_dir, "include"),
os.path.join(current_dir, "../mooncake-transfer-engine/include"),
os.path.join(current_dir, "../mooncake-common/include"),
],
sources=[
"src/pg_py.cpp",

View File

@ -15,6 +15,7 @@
#include <limits>
#include "memory_location.h"
#include "mooncake_worker.cuh"
#include "environ.h"
#include "pg_utils.h"
namespace mooncake {
@ -24,10 +25,7 @@ namespace mooncake {
// NVLink transport can only access cuMemCreate(FABRIC) memory
// cross-node -- CPU heap buffers are invisible to remote peers.
static bool supportFabricMem() {
const char* nvlink_ipc = getenv("MC_USE_NVLINK_IPC");
bool fabric_enabled = nvlink_ipc && strcmp(nvlink_ipc, "0") == 0;
if (!fabric_enabled) return false;
if (!Environ::Get().GetNvlinkFabricMemEnabled()) return false;
int num_devices = 0;
cudaError_t err = cudaGetDeviceCount(&num_devices);

View File

@ -7,6 +7,8 @@
#include <cstdlib>
#include <thread>
#include "environ.h"
namespace mooncake {
namespace {
@ -19,8 +21,8 @@ std::string toLower(const std::string& str) {
}
bool parseMetricsEnabled() {
const char* metric_env = std::getenv("MC_STORE_CLIENT_METRIC");
if (!metric_env) {
std::string metric_env = Environ::Get().GetStoreClientMetric();
if (metric_env.empty()) {
return true;
}
std::string value = toLower(metric_env);
@ -29,27 +31,15 @@ bool parseMetricsEnabled() {
}
uint64_t parseMetricsInterval() {
const char* interval_env = std::getenv("MC_STORE_CLIENT_METRIC_INTERVAL");
if (!interval_env) {
// Default to disabled
return 0;
}
try {
uint64_t interval = std::stoull(interval_env);
if (interval == 0) {
LOG(INFO) << "Client metrics reporting disabled (interval=0) via "
"MC_STORE_CLIENT_METRIC_INTERVAL";
} else {
LOG(INFO) << "Client metrics interval set to " << interval
<< "s via MC_STORE_CLIENT_METRIC_INTERVAL";
}
return interval;
} catch (const std::exception& e) {
LOG(WARNING) << "Failed to parse MC_STORE_CLIENT_METRIC_INTERVAL: "
<< interval_env << ", disabling metrics reporting";
return 0;
int interval = Environ::Get().GetStoreClientMetricInterval();
if (interval == 0) {
LOG(INFO) << "Client metrics reporting disabled (interval=0) via "
"MC_STORE_CLIENT_METRIC_INTERVAL";
} else if (interval > 0) {
LOG(INFO) << "Client metrics interval set to " << interval
<< "s via MC_STORE_CLIENT_METRIC_INTERVAL";
}
return interval >= 0 ? static_cast<uint64_t>(interval) : 0;
}
} // anonymous namespace

View File

@ -16,6 +16,7 @@
#include <set>
#include <ylt/struct_json/json_reader.h>
#include "environ.h"
#include "transfer_engine.h"
#include "topology.h"
#include "transfer_task.h"
@ -127,8 +128,8 @@ Client::~Client() {
}
static std::optional<bool> get_auto_discover() {
const char* ev_ad = std::getenv("MC_MS_AUTO_DISC");
if (ev_ad) {
std::string ev_ad = Environ::Get().GetMsAutoDisc();
if (!ev_ad.empty()) {
int iv = std::stoi(ev_ad);
if (iv == 1) {
LOG(INFO) << "auto discovery set by env MC_MS_AUTO_DISC";
@ -160,12 +161,13 @@ static inline void rtrim(std::string& s) {
static std::vector<std::string> get_auto_discover_filters() {
std::vector<std::string> whitelst_filters;
char* ev_ad = std::getenv("MC_MS_FILTERS");
if (ev_ad) {
std::string ev_ad = Environ::Get().GetMsFilters();
if (!ev_ad.empty()) {
LOG(INFO) << "whitelist filters: " << ev_ad;
char delimiter = ',';
char* end = ev_ad + std::strlen(ev_ad);
char *start = ev_ad, *pos = ev_ad;
const char* start = ev_ad.c_str();
const char* end = start + ev_ad.length();
const char* pos = start;
while ((pos = std::find(start, end, delimiter)) != end) {
std::string str(start, pos);
ltrim(str);
@ -173,7 +175,7 @@ static std::vector<std::string> get_auto_discover_filters() {
whitelst_filters.emplace_back(std::move(str));
start = pos + 1;
}
if (start != (end + 1)) {
if (start != end) {
std::string str(start, end);
ltrim(str);
rtrim(str);
@ -361,8 +363,8 @@ ErrorCode Client::InitTransferEngine(
const std::optional<std::string>& device_names) {
// Check if using TENT mode - TENT handles transport configuration
// internally
bool use_tent = (std::getenv("MC_USE_TENT") != nullptr) ||
(std::getenv("MC_USE_TEV1") != nullptr);
auto& env = Environ::Get();
bool use_tent = env.GetUseTent() || env.GetUseTev1();
bool auto_discover = false;
if (!use_tent) {
@ -392,8 +394,8 @@ ErrorCode Client::InitTransferEngine(
auto filters = get_auto_discover_filters();
transfer_engine_->setWhitelistFilters(std::move(filters));
} else {
const char* env_filters = std::getenv("MC_MS_FILTERS");
if (env_filters && *env_filters != '\0') {
std::string env_filters = env.GetMsFilters();
if (!env_filters.empty()) {
LOG(WARNING)
<< "MC_MS_FILTERS is set but auto discovery is disabled; "
<< "ignoring whitelist: " << env_filters;

View File

@ -9,6 +9,7 @@
#include <ylt/easylog/record.hpp>
#include "default_config.h"
#include "environ.h"
#include "duration_utils.h"
#include "ha/leadership/master_service_supervisor.h"
#include "http_metadata_server.h"
@ -848,9 +849,9 @@ int main(int argc, char* argv[]) {
return 1;
}
const char* value = std::getenv("MC_RPC_PROTOCOL");
std::string rpc_protocol = mooncake::Environ::Get().GetRpcProtocol();
std::string protocol = "tcp";
if (value && std::string_view(value) == "rdma") {
if (rpc_protocol == "rdma") {
protocol = "rdma";
}
LOG(INFO)
@ -947,8 +948,8 @@ int main(int argc, char* argv[]) {
master_config.rpc_address,
std::chrono::seconds(master_config.rpc_conn_timeout_seconds),
master_config.rpc_enable_tcp_no_delay);
const char* value = std::getenv("MC_RPC_PROTOCOL");
if (value && std::string_view(value) == "rdma") {
std::string rpc_protocol = mooncake::Environ::Get().GetRpcProtocol();
if (rpc_protocol == "rdma") {
server.init_ibv();
}
auto wrapped_master_service =

View File

@ -20,6 +20,7 @@
#include "real_client.h"
#include "client_buffer.hpp"
#include "config.h"
#include "environ.h"
#include "mutex.h"
#include "types.h"
#include "utils.h"

View File

@ -4,6 +4,7 @@
#include <algorithm>
#include <cstdlib>
#include "environ.h"
#include "transfer_engine.h"
#include "transport/transport.h"
@ -410,22 +411,21 @@ TransferSubmitter::TransferSubmitter(TransferEngine& engine,
fileread_pool_(std::make_unique<FilereadWorkerPool>(backend)),
transfer_metric_(transfer_metric) {
// Read MC_STORE_MEMCPY environment variable, default to false (disabled)
const char* env_value = std::getenv("MC_STORE_MEMCPY");
if (env_value == nullptr) {
std::string env_value = Environ::Get().GetStoreMemcpy();
if (env_value.empty()) {
memcpy_enabled_ = false; // Default: disabled
} else {
std::string env_str(env_value);
// Convert to lowercase for case-insensitive comparison
std::transform(env_str.begin(), env_str.end(), env_str.begin(),
std::transform(env_value.begin(), env_value.end(), env_value.begin(),
::tolower);
if (env_str == "false" || env_str == "0" || env_str == "no" ||
env_str == "off") {
if (env_value == "false" || env_value == "0" || env_value == "no" ||
env_value == "off") {
memcpy_enabled_ = false;
} else if (env_str == "true" || env_str == "1" || env_str == "yes" ||
env_str == "on") {
} else if (env_value == "true" || env_value == "1" ||
env_value == "yes" || env_value == "on") {
memcpy_enabled_ = true;
} else {
LOG(WARNING) << "Invalid value for MC_STORE_MEMCPY: " << env_str
LOG(WARNING) << "Invalid value for MC_STORE_MEMCPY: " << env_value
<< ", defaulting to enabled";
memcpy_enabled_ = true;
}

View File

@ -101,9 +101,9 @@ class ClientIntegrationTestCxl : public ::testing::Test {
std::nullopt, // RDMA device names (auto-discovery)
master_address_);
EXPECT_TRUE(client_opt.has_value())
<< "Failed to create client with host_name: " << host_name;
if (!client_opt.has_value()) {
LOG(WARNING) << "Failed to create client with host_name: "
<< host_name;
return nullptr;
}
return client_opt.value();
@ -160,6 +160,11 @@ class ClientIntegrationTestCxl : public ::testing::Test {
}
static void InitializeSegment() {
// Skip if client creation failed (CXL device unavailable)
if (test_client_ == nullptr) {
return;
}
// init local buffer allocator
client_buffer_allocator_ =
std::make_unique<SimpleAllocator>(128 * 1024 * 1024);
@ -202,7 +207,13 @@ class ClientIntegrationTestCxl : public ::testing::Test {
google::AddLogSink(test_client_sink);
test_client_ = CreateClient("localhost:17813");
ASSERT_TRUE(test_client_ != nullptr);
if (test_client_ == nullptr) {
google::RemoveLogSink(test_client_sink);
delete test_client_sink;
cxl_available_ = false;
LOG(WARNING) << "CXL device not available, tests will be skipped";
return;
}
// Wait for logs to flush
std::this_thread::sleep_for(std::chrono::milliseconds(200));
@ -251,6 +262,7 @@ class ClientIntegrationTestCxl : public ::testing::Test {
static std::string metadata_url_;
static UUID test_client_id_;
static inline bool is_cxl = false;
static inline bool cxl_available_ = true;
static int tmp_fd;
};
@ -269,6 +281,9 @@ int ClientIntegrationTestCxl::tmp_fd = -1;
// Test basic Put/Get operations through the client
TEST_F(ClientIntegrationTestCxl, BasicPutGetOperations) {
if (!cxl_available_) {
GTEST_SKIP() << "CXL device not available";
}
const std::string test_data = "Hello, World!";
const std::string key = "test_key";
void* buffer = client_buffer_allocator_->allocate(test_data.size());
@ -317,6 +332,9 @@ TEST_F(ClientIntegrationTestCxl, BasicPutGetOperations) {
// Test batch Put/Get operations through the client
TEST_F(ClientIntegrationTestCxl, BatchPutGetOperations) {
if (!cxl_available_) {
GTEST_SKIP() << "CXL device not available";
}
int batch_sz = 10;
std::vector<std::string> keys;
std::vector<std::string> test_data_list;
@ -406,6 +424,9 @@ TEST_F(ClientIntegrationTestCxl, BatchPutGetOperations) {
// Test Evict operation through the client
TEST_F(ClientIntegrationTestCxl, EvictOperation) {
if (!cxl_available_) {
GTEST_SKIP() << "CXL device not available";
}
// Test data
const size_t test_data_size = 1ULL * 1024 * 1024;
const size_t test_total_size = 1000ULL * 1024 * 1024;

View File

@ -9,6 +9,10 @@ if (NOT GLOBAL_CONFIG)
include(../mooncake-common/FindGLOG.cmake)
include(../mooncake-common/common.cmake)
# Build mooncake_common for standalone transfer engine build.
# transfer_engine links against the mooncake_common target.
add_subdirectory(../mooncake-common ${CMAKE_CURRENT_BINARY_DIR}/mooncake-common)
# Build asio_shared library for standalone build
# Set compile definitions before add_subdirectory to ensure proper compilation
add_compile_definitions(ASIO_SEPARATE_COMPILATION ASIO_DYN_LINK)

View File

@ -85,10 +85,10 @@ class CxlTransport : public Transport {
bool validateMemoryBounds(void *dest, void *src, size_t size);
private:
void *cxl_base_addr;
size_t cxl_dev_size;
char *cxl_dev_path;
void *cxl_base_addr = nullptr;
size_t cxl_dev_size = 0;
std::string cxl_dev_path;
};
} // namespace mooncake
#endif
#endif

View File

@ -55,6 +55,7 @@ target_link_libraries(
JsonCpp::JsonCpp
numa
asio_shared
mooncake_common
yalantinglibs::yalantinglibs)
if(USE_BAREX)

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include "config.h"
#include "environ.h"
#include <cstring>
#include <cstdio>
@ -22,240 +23,124 @@
namespace mooncake {
void loadGlobalConfig(GlobalConfig &config) {
const char *num_cq_per_ctx_env = std::getenv("MC_NUM_CQ_PER_CTX");
if (num_cq_per_ctx_env) {
int val = atoi(num_cq_per_ctx_env);
if (val > 0 && val < 256) {
config.num_cq_per_ctx = val;
// In URMA, JFC and JFCE are bound one-to-one.
config.num_jfc_per_ctx = val;
config.num_jfce_per_ctx = val;
} else
LOG(WARNING)
<< "Ignore value from environment variable MC_NUM_CQ_PER_CTX";
auto &env = Environ::Get();
int num_cq_per_ctx = env.GetNumCqPerCtx();
if (num_cq_per_ctx > 0 && num_cq_per_ctx < 256) {
config.num_cq_per_ctx = num_cq_per_ctx;
// In URMA, JFC and JFCE are bound one-to-one.
config.num_jfc_per_ctx = num_cq_per_ctx;
config.num_jfce_per_ctx = num_cq_per_ctx;
}
const char *num_comp_channels_per_ctx_env =
std::getenv("MC_NUM_COMP_CHANNELS_PER_CTX");
if (num_comp_channels_per_ctx_env) {
int val = atoi(num_comp_channels_per_ctx_env);
if (val > 0 && val < 256)
config.num_comp_channels_per_ctx = val;
else
LOG(WARNING) << "Ignore value from environment variable "
"MC_NUM_COMP_CHANNELS_PER_CTX";
int num_comp_channels_per_ctx = env.GetNumCompChannelsPerCtx();
if (num_comp_channels_per_ctx > 0 && num_comp_channels_per_ctx < 256)
config.num_comp_channels_per_ctx = num_comp_channels_per_ctx;
int port = env.GetIbPort();
if (port >= 0 && port < 256) config.port = uint8_t(port);
int gid_index = env.GetGidIndex();
if (gid_index >= 0 && gid_index < 256) config.gid_index = gid_index;
int max_cqe_per_ctx = env.GetMaxCqePerCtx();
if (max_cqe_per_ctx > 0 && max_cqe_per_ctx <= UINT16_MAX)
config.max_cqe = max_cqe_per_ctx;
int max_ep_per_ctx = env.GetMaxEpPerCtx();
if (max_ep_per_ctx > 0 && max_ep_per_ctx <= UINT16_MAX)
config.max_ep_per_ctx = max_ep_per_ctx;
int num_qp_per_ep = env.GetNumQpPerEp();
if (num_qp_per_ep > 0 && num_qp_per_ep < 256)
config.num_qp_per_ep = num_qp_per_ep;
int max_sge = env.GetMaxSge();
if (max_sge > 0 && max_sge <= UINT16_MAX) config.max_sge = max_sge;
int max_wr = env.GetMaxWr();
if (max_wr > 0 && max_wr <= UINT16_MAX) config.max_wr = max_wr;
int max_inline = env.GetMaxInline();
if (max_inline >= 0 && max_inline <= UINT16_MAX)
config.max_inline = max_inline;
int mtu = env.GetMtu();
if (mtu == 512)
config.mtu_length = IBV_MTU_512;
else if (mtu == 1024)
config.mtu_length = IBV_MTU_1024;
else if (mtu == 2048)
config.mtu_length = IBV_MTU_2048;
else if (mtu == 4096)
config.mtu_length = IBV_MTU_4096;
else if (mtu != 0) {
LOG(ERROR) << "Ignore value from environment variable MC_MTU, it "
"should be 512|1024|2048|4096";
exit(EXIT_FAILURE);
}
const char *port_env = std::getenv("MC_IB_PORT");
if (port_env) {
int val = atoi(port_env);
if (val >= 0 && val < 256)
config.port = uint8_t(val);
else
LOG(WARNING) << "Ignore value from environment variable MC_IB_PORT";
int handshake_port = env.GetHandshakePort();
if (handshake_port > 0 && handshake_port < 65536)
config.handshake_port = handshake_port;
int workers_per_ctx = env.GetWorkersPerCtx();
if (workers_per_ctx > 0 && workers_per_ctx <= 8)
config.workers_per_ctx = workers_per_ctx;
size_t slice_size = env.GetSliceSize();
if (slice_size > 0) config.slice_size = slice_size;
size_t min_reg_size = env.GetMinRegSize();
if (min_reg_size > 0) {
config.eic_max_block_size = min_reg_size;
LOG(INFO) << "Barex set MC_MIN_REG_SIZE=" << min_reg_size;
}
const char *gid_index_env = std::getenv("MC_GID_INDEX");
if (!gid_index_env) gid_index_env = std::getenv("NCCL_IB_GID_INDEX");
int retry_cnt = env.GetRetryCnt();
if (retry_cnt > 0 && retry_cnt < 128) config.retry_cnt = retry_cnt;
if (gid_index_env) {
int val = atoi(gid_index_env);
if (val >= 0 && val < 256)
config.gid_index = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_GID_INDEX";
uint64_t max_mr_size = env.GetMaxMrSize();
if (max_mr_size > 0) {
config.max_mr_size = max_mr_size;
}
const char *max_cqe_per_ctx_env = std::getenv("MC_MAX_CQE_PER_CTX");
if (max_cqe_per_ctx_env) {
size_t val = atoi(max_cqe_per_ctx_env);
if (val > 0 && val <= UINT16_MAX)
config.max_cqe = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_MAX_CQE_PER_CTX";
}
const char *max_ep_per_ctx_env = std::getenv("MC_MAX_EP_PER_CTX");
if (max_ep_per_ctx_env) {
size_t val = atoi(max_ep_per_ctx_env);
if (val > 0 && val <= UINT16_MAX)
config.max_ep_per_ctx = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_MAX_EP_PER_CTX";
}
const char *num_qp_per_ep_env = std::getenv("MC_NUM_QP_PER_EP");
if (num_qp_per_ep_env) {
int val = atoi(num_qp_per_ep_env);
if (val > 0 && val < 256)
config.num_qp_per_ep = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_NUM_QP_PER_EP";
}
const char *max_sge_env = std::getenv("MC_MAX_SGE");
if (max_sge_env) {
size_t val = atoi(max_sge_env);
if (val > 0 && val <= UINT16_MAX)
config.max_sge = val;
else
LOG(WARNING) << "Ignore value from environment variable MC_MAX_SGE";
}
const char *max_wr_env = std::getenv("MC_MAX_WR");
if (max_wr_env) {
size_t val = atoi(max_wr_env);
if (val > 0 && val <= UINT16_MAX)
config.max_wr = val;
else
LOG(WARNING) << "Ignore value from environment variable MC_MAX_WR";
}
const char *max_inline_env = std::getenv("MC_MAX_INLINE");
if (max_inline_env) {
size_t val = atoi(max_inline_env);
if (val <= UINT16_MAX)
config.max_inline = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_MAX_INLINE";
}
const char *mtu_length_env = std::getenv("MC_MTU");
if (mtu_length_env) {
size_t val = atoi(mtu_length_env);
if (val == 512)
config.mtu_length = IBV_MTU_512;
else if (val == 1024)
config.mtu_length = IBV_MTU_1024;
else if (val == 2048)
config.mtu_length = IBV_MTU_2048;
else if (val == 4096)
config.mtu_length = IBV_MTU_4096;
else {
LOG(ERROR) << "Ignore value from environment variable MC_MTU, it "
"should be 512|1024|2048|4096";
exit(EXIT_FAILURE);
}
}
const char *handshake_port_env = std::getenv("MC_HANDSHAKE_PORT");
if (handshake_port_env) {
int val = atoi(handshake_port_env);
if (val > 0 && val < 65536)
config.handshake_port = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_HANDSHAKE_PORT";
}
const char *workers_per_ctx_env = std::getenv("MC_WORKERS_PER_CTX");
if (workers_per_ctx_env) {
size_t val = atoi(workers_per_ctx_env);
if (val > 0 && val <= 8)
config.workers_per_ctx = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_WORKERS_PER_CTX";
}
const char *slice_size_env = std::getenv("MC_SLICE_SIZE");
if (slice_size_env) {
size_t val = atoi(slice_size_env);
if (val > 0)
config.slice_size = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_SLICE_SIZE";
}
const char *min_reg_size_env = std::getenv("MC_MIN_REG_SIZE");
if (min_reg_size_env) {
size_t val = atoll(min_reg_size_env);
if (val > 0) {
config.eic_max_block_size = val;
LOG(INFO) << "Barex set MC_MIN_REG_SIZE=" << val;
} else
LOG(WARNING)
<< "Ignore value from environment variable MC_MIN_REG_SIZE";
}
const char *max_mr_size_env = std::getenv("MC_MAX_MR_SIZE");
if (max_mr_size_env) {
uint64_t val = atoll(max_mr_size_env);
if (val > 0) {
config.max_mr_size = val;
} else {
LOG(WARNING)
<< "Ignore value from environment variable MC_MAX_MR_SIZE";
}
}
const char *retry_cnt_env = std::getenv("MC_RETRY_CNT");
if (retry_cnt_env) {
size_t val = atoi(retry_cnt_env);
if (val > 0 && val < 128)
config.retry_cnt = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_RETRY_CNT";
}
const char *disable_metacache = std::getenv("MC_DISABLE_METACACHE");
if (disable_metacache) {
if (env.GetDisableMetacache()) {
config.metacache = false;
}
const char *handshake_listen_backlog =
std::getenv("MC_HANDSHAKE_LISTEN_BACKLOG");
if (handshake_listen_backlog) {
int val = std::stoi(handshake_listen_backlog);
if (val > 0) {
config.handshake_listen_backlog = val;
} else {
LOG(WARNING) << "Ignore value from environment variable "
"MC_HANDSHAKE_LISTEN_BACKLOG";
}
int handshake_listen_backlog = env.GetHandshakeListenBacklog();
if (handshake_listen_backlog > 0) {
config.handshake_listen_backlog = handshake_listen_backlog;
}
const char *log_level = std::getenv("MC_LOG_LEVEL");
std::string log_level = env.GetLogLevel();
config.trace = false;
if (log_level) {
if (strcmp(log_level, "TRACE") == 0) {
if (!log_level.empty()) {
if (log_level == "TRACE") {
config.log_level = google::INFO;
config.trace = true;
}
if (strcmp(log_level, "INFO") == 0)
} else if (log_level == "INFO")
config.log_level = google::INFO;
else if (strcmp(log_level, "WARNING") == 0)
else if (log_level == "WARNING")
config.log_level = google::WARNING;
else if (strcmp(log_level, "ERROR") == 0)
else if (log_level == "ERROR")
config.log_level = google::ERROR;
}
FLAGS_minloglevel = config.log_level;
const char *slice_timeout_env = std::getenv("MC_SLICE_TIMEOUT");
if (slice_timeout_env) {
int val = atoi(slice_timeout_env);
if (val > 0 && val < 65536)
config.slice_timeout = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_SLICE_TIMEOUT";
}
int slice_timeout = env.GetSliceTimeout();
if (slice_timeout > 0 && slice_timeout < 65536)
config.slice_timeout = slice_timeout;
const char *log_dir_path = std::getenv("MC_LOG_DIR");
if (log_dir_path) {
std::string log_dir_path = env.GetLogDir();
if (!log_dir_path.empty()) {
google::InitGoogleLogging("mooncake-transfer-engine");
if (opendir(log_dir_path) == NULL) {
if (opendir(log_dir_path.c_str()) == NULL) {
LOG(WARNING)
<< "Path [" << log_dir_path
<< "] is not a valid directory path. Still logging to stderr.";
} else if (access(log_dir_path, W_OK) != 0) {
} else if (access(log_dir_path.c_str(), W_OK) != 0) {
LOG(WARNING)
<< "Path [" << log_dir_path
<< "] is not a permitted directory path for the current user. \
@ -267,98 +152,60 @@ void loadGlobalConfig(GlobalConfig &config) {
}
}
const char *min_port_env = std::getenv("MC_MIN_PRC_PORT");
if (min_port_env) {
int val = atoi(min_port_env);
if (val > 0 && val < 65536)
config.rpc_min_port = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_PRC_MIN_PORT";
}
int min_prc_port = env.GetMinPrcPort();
if (min_prc_port > 0 && min_prc_port < 65536)
config.rpc_min_port = min_prc_port;
const char *max_port_env = std::getenv("MC_MAX_PRC_PORT");
if (max_port_env) {
int val = atoi(max_port_env);
if (val > 0 && val < 65536)
config.rpc_max_port = val;
else
LOG(WARNING)
<< "Ignore value from environment variable MC_PRC_MAX_PORT";
}
int max_prc_port = env.GetMaxPrcPort();
if (max_prc_port > 0 && max_prc_port < 65536)
config.rpc_max_port = max_prc_port;
if (std::getenv("MC_USE_IPV6")) {
if (env.GetUseIpv6()) {
config.use_ipv6 = true;
}
const char *fragment_ratio = std::getenv("MC_FRAGMENT_RATIO");
if (fragment_ratio) {
size_t val = atoi(fragment_ratio);
if (val > 0 && val < config.slice_size)
config.fragment_limit = config.slice_size / val;
else {
LOG(WARNING) << "Ignore value from environment variable "
"MC_FRAGMENT_RATIO and set it to 4 as default";
config.fragment_limit = config.slice_size / 4;
}
int fragment_ratio = env.GetFragmentRatio();
if (fragment_ratio > 0 && fragment_ratio < (int)config.slice_size)
config.fragment_limit = config.slice_size / fragment_ratio;
else if (fragment_ratio != 0) {
LOG(WARNING) << "Ignore value from environment variable "
"MC_FRAGMENT_RATIO and set it to 4 as default";
config.fragment_limit = config.slice_size / 4;
}
if (std::getenv("MC_ENABLE_DEST_DEVICE_AFFINITY")) {
if (env.GetEnableDestDeviceAffinity()) {
config.enable_dest_device_affinity = true;
}
const char *enable_parallel_reg_mr =
std::getenv("MC_ENABLE_PARALLEL_REG_MR");
if (enable_parallel_reg_mr) {
int val = atoi(enable_parallel_reg_mr);
if (val >= -1 && val <= 1) {
config.parallel_reg_mr = val;
} else {
LOG(WARNING) << "Ignore value from environment variable "
"MC_ENABLE_PARALLEL_REG_MR";
}
int enable_parallel_reg_mr = env.GetEnableParallelRegMr();
if (enable_parallel_reg_mr >= -1 && enable_parallel_reg_mr <= 1) {
config.parallel_reg_mr = enable_parallel_reg_mr;
}
const char *endpoint_store_type_env = std::getenv("MC_ENDPOINT_STORE_TYPE");
if (endpoint_store_type_env) {
if (strcmp(endpoint_store_type_env, "FIFO") == 0) {
config.endpoint_store_type = EndpointStoreType::FIFO;
} else if (strcmp(endpoint_store_type_env, "SIEVE") == 0) {
config.endpoint_store_type = EndpointStoreType::SIEVE;
} else {
LOG(WARNING) << "Ignore value from environment variable "
"MC_ENDPOINT_STORE_TYPE, it should be FIFO|SIEVE";
}
std::string endpoint_store_type = env.GetEndpointStoreType();
if (endpoint_store_type == "FIFO") {
config.endpoint_store_type = EndpointStoreType::FIFO;
} else if (endpoint_store_type == "SIEVE") {
config.endpoint_store_type = EndpointStoreType::SIEVE;
} else if (!endpoint_store_type.empty()) {
LOG(WARNING) << "Ignore value from environment variable "
"MC_ENDPOINT_STORE_TYPE, it should be FIFO|SIEVE";
}
const char *traffic_class_env = std::getenv("MC_IB_TC");
if (traffic_class_env) {
try {
int val = std::stoi(traffic_class_env);
if (val >= 0 && val <= 255) {
config.ib_traffic_class = val;
} else {
LOG(WARNING)
<< "Ignore value from environment variable MC_IB_TC, "
<< "value " << traffic_class_env
<< " out of range (should be 0-255)";
}
} catch (const std::exception &e) {
LOG(WARNING) << "Invalid MC_IB_TC environment value: "
<< traffic_class_env << ". Error: " << e.what();
}
int ib_tc = env.GetIbTc();
if (ib_tc >= 0 && ib_tc <= 255) {
config.ib_traffic_class = ib_tc;
} else if (ib_tc < -1) {
LOG(WARNING) << "Ignore value from environment variable MC_IB_TC, "
<< "value out of range (should be 0-255)";
}
const char *ib_relaxed_ordering_env =
std::getenv("MC_IB_PCI_RELAXED_ORDERING");
if (ib_relaxed_ordering_env) {
int val = atoi(ib_relaxed_ordering_env);
if (val >= 0 && val <= 2)
config.ib_pci_relaxed_ordering_mode = val;
else
LOG(WARNING) << "Ignore value from environment variable "
"MC_IB_PCI_RELAXED_ORDERING, it should be 0|1|2";
}
int ib_pci_relaxed_ordering = env.GetIbPciRelaxedOrdering();
if (ib_pci_relaxed_ordering >= 0 && ib_pci_relaxed_ordering <= 2)
config.ib_pci_relaxed_ordering_mode = ib_pci_relaxed_ordering;
else if (ib_pci_relaxed_ordering != 0)
LOG(WARNING) << "Ignore value from environment variable "
"MC_IB_PCI_RELAXED_ORDERING, it should be 0|1|2";
}
std::string mtuLengthToString(ibv_mtu mtu) {

View File

@ -32,6 +32,7 @@
#include <sys/stat.h>
#include "cuda_alike.h"
#include "environ.h"
#include "memory_location.h"
#include "topology.h"
#ifdef USE_UB
@ -445,14 +446,7 @@ static std::vector<TopologyEntry> discoverCudaTopology(
}
#endif
Topology::Topology() {
auto str = getenv("MC_PATH_ROUNDROBIN");
if (str && (strcmp(str, "1") == 0 || strcasecmp(str, "true") == 0)) {
use_round_robin_ = true;
} else {
use_round_robin_ = false;
}
}
Topology::Topology() { use_round_robin_ = Environ::Get().GetPathRoundrobin(); }
Topology::~Topology() {}

View File

@ -211,6 +211,7 @@ std::shared_ptr<Topology> TransferEngine::getLocalTopology() {
#else
#include "transfer_engine.h"
#include "transfer_engine_impl.h"
#include "environ.h"
#include "tent/transfer_engine.h"
#include "tent/common/config.h"
@ -219,7 +220,8 @@ std::shared_ptr<Topology> TransferEngine::getLocalTopology() {
namespace mooncake {
TransferEngine::TransferEngine(bool auto_discover) {
if (getenv("MC_USE_TENT") || getenv("MC_USE_TEV1")) {
auto& env = Environ::Get();
if (env.GetUseTent() || env.GetUseTev1()) {
use_tent_ = true;
}
if (!use_tent_) {
@ -229,7 +231,8 @@ TransferEngine::TransferEngine(bool auto_discover) {
TransferEngine::TransferEngine(bool auto_discover,
const std::vector<std::string>& filter) {
if (getenv("MC_USE_TENT") || getenv("MC_USE_TEV1")) {
auto& env = Environ::Get();
if (env.GetUseTent() || env.GetUseTev1()) {
use_tent_ = true;
}
if (!use_tent_) {

View File

@ -27,6 +27,7 @@
#include <sstream>
#endif
#include "environ.h"
#include "transfer_metadata_plugin.h"
#include "transport/transport.h"
#include "transport/barex_transport/barex_transport.h"
@ -107,8 +108,8 @@ int TransferEngineImpl::init(const std::string& metadata_conn_string,
local_server_name_ = local_server_name;
#endif
if (getenv("MC_LEGACY_RPC_PORT_BINDING") ||
metadata_conn_string == P2PHANDSHAKE) {
auto& env = Environ::Get();
if (env.GetLegacyRpcPortBinding() || metadata_conn_string == P2PHANDSHAKE) {
rpc_binding_method = "legacy/P2P";
desc.ip_or_host_name = host_name;
desc.rpc_port = port;
@ -146,9 +147,9 @@ int TransferEngineImpl::init(const std::string& metadata_conn_string,
} else {
rpc_binding_method = "new RPC mapping";
(void)(ip_or_host_name);
auto* ip_address = getenv("MC_TCP_BIND_ADDRESS");
if (ip_address)
desc.ip_or_host_name = ip_address;
std::string tcp_bind_address = env.GetTcpBindAddress();
if (!tcp_bind_address.empty())
desc.ip_or_host_name = tcp_bind_address;
else {
auto ip_list = findLocalIpAddresses();
if (ip_list.empty()) {
@ -213,7 +214,7 @@ int TransferEngineImpl::init(const std::string& metadata_conn_string,
#if defined(USE_CXL) && !defined(USE_ASCEND) && \
!defined(USE_ASCEND_HETEROGENEOUS)
if (std::getenv("MC_CXL_DEV_PATH") != nullptr) {
if (!env.GetCxlDevPath().empty()) {
Transport* cxl_transport =
multi_transports_->installTransport("cxl", local_topology_);
if (!cxl_transport) {
@ -225,15 +226,16 @@ int TransferEngineImpl::init(const std::string& metadata_conn_string,
if (auto_discover_) {
LOG(INFO) << "Auto-discovering topology...";
if (getenv("MC_CUSTOM_TOPO_JSON")) {
auto path = getenv("MC_CUSTOM_TOPO_JSON");
LOG(INFO) << "Using custom topology from: " << path;
auto topo_json = loadTopologyJsonFile(path);
std::string custom_topo_json = env.GetCustomTopoJson();
if (!custom_topo_json.empty()) {
LOG(INFO) << "Using custom topology from: " << custom_topo_json;
auto topo_json = loadTopologyJsonFile(custom_topo_json);
if (!topo_json.empty()) {
local_topology_->parse(topo_json);
} else {
LOG(WARNING) << "Failed to load custom topology from " << path
<< ", falling back to auto-detect.";
LOG(WARNING)
<< "Failed to load custom topology from "
<< custom_topo_json << ", falling back to auto-detect.";
local_topology_->discover(filter_);
}
} else {
@ -259,11 +261,9 @@ int TransferEngineImpl::init(const std::string& metadata_conn_string,
return -1;
}
#elif defined(USE_MNNVL) || defined(USE_INTRA_NVLINK)
const char* force_mnnvl = getenv("MC_FORCE_MNNVL");
const char* intra_env = getenv("MC_INTRANODE_NVLINK");
// Explicit env var overrides take priority over HCA auto-detection
if (intra_env) {
bool force_mnnvl = env.GetForceMnnvl();
bool intranode_nvlink = env.GetIntranodeNvlink();
if (intranode_nvlink) {
Transport* t =
multi_transports_->installTransport("nvlink_intra", nullptr);
if (!t) {
@ -292,9 +292,8 @@ int TransferEngineImpl::init(const std::string& metadata_conn_string,
}
#else
if (local_topology_->getHcaList().size() > 0 &&
!getenv("MC_FORCE_TCP") ||
getenv("MC_FORCE_HCA")) {
if ((local_topology_->getHcaList().size() > 0 && !env.GetForceTcp()) ||
env.GetForceHca()) {
// only install RDMA transport when there is at least one HCA
Transport* rdma_transport = nullptr;
if (use_barex_) {
@ -703,34 +702,21 @@ static std::string toLower(const std::string& s) {
}
void TransferEngineImpl::InitializeMetricsConfig() {
auto& env = Environ::Get();
// Check if metrics reporting is enabled via environment variable
const char* metric_env = getenv("MC_TE_METRIC");
if (metric_env) {
std::string metric_env = env.GetTeMetric();
if (!metric_env.empty()) {
std::string value = toLower(metric_env);
metrics_enabled_ = (value == "1" || value == "true" || value == "yes" ||
value == "on");
}
// Check for custom reporting interval
const char* interval_env = getenv("MC_TE_METRIC_INTERVAL_SECONDS");
if (interval_env) {
try {
int interval = std::stoi(interval_env);
if (interval > 0) {
metrics_interval_seconds_ = static_cast<uint64_t>(interval);
LOG(INFO) << "Metrics reporting interval set to "
<< metrics_interval_seconds_ << " seconds";
} else {
LOG(WARNING)
<< "Invalid MC_TE_METRIC_INTERVAL_SECONDS value: "
<< interval_env << ", must be positive. Using default: "
<< metrics_interval_seconds_;
}
} catch (const std::exception& e) {
LOG(WARNING) << "Failed to parse MC_TE_METRIC_INTERVAL_SECONDS: "
<< interval_env
<< ", using default: " << metrics_interval_seconds_;
}
int interval = env.GetTeMetricIntervalSeconds();
if (interval > 0) {
metrics_interval_seconds_ = static_cast<uint64_t>(interval);
LOG(INFO) << "Metrics reporting interval set to "
<< metrics_interval_seconds_ << " seconds";
}
}

View File

@ -22,6 +22,7 @@
#include "common.h"
#include "config.h"
#include "environ.h"
#include "error.h"
#include "transfer_metadata_plugin.h"
@ -121,8 +122,8 @@ TransferMetadata::TransferMetadata(const std::string &conn_string) {
std::string protocol = extractProtocolFromConnString(conn_string);
std::string custom_key;
const char *custom_prefix = std::getenv("MC_METADATA_CLUSTER_ID");
if (custom_prefix != nullptr && strlen(custom_prefix) > 0) {
std::string custom_prefix = Environ::Get().GetMetadataClusterId();
if (!custom_prefix.empty()) {
custom_key = custom_prefix;
if (!custom_key.empty() && custom_key.back() != '/') {

View File

@ -47,6 +47,7 @@
#include "common.h"
#include "config.h"
#include "environ.h"
#include "error.h"
// Helper function to parse JSON string using thread-safe CharReaderBuilder
@ -550,28 +551,17 @@ std::shared_ptr<MetadataStoragePlugin> MetadataStoragePlugin::Create(
#ifdef USE_REDIS
if (parsed_conn_string.first == "redis") {
const char *username = std::getenv("MC_REDIS_USERNAME");
std::string username_str = username ? username : "";
const char *password = std::getenv("MC_REDIS_PASSWORD");
std::string password_str = password ? password : "";
auto &env = Environ::Get();
std::string username_str = env.GetRedisUsername();
std::string password_str = env.GetRedisPassword();
uint8_t db_index = 0;
const char *db_index_str = std::getenv("MC_REDIS_DB_INDEX");
if (db_index_str) {
try {
int index = std::stoi(db_index_str);
if (index >= 0 && index <= 255) {
db_index = static_cast<uint8_t>(index);
} else {
LOG(WARNING) << "Invalid Redis DB index: " << index
<< ", using default 0";
}
} catch (const std::exception &e) {
LOG(WARNING)
<< "Failed to parse MC_REDIS_DB_INDEX: " << e.what()
<< ", using default 0";
}
int db_index_val = env.GetRedisDbIndex();
if (db_index_val >= 0 && db_index_val <= 255) {
db_index = static_cast<uint8_t>(db_index_val);
} else if (db_index_val != 0) {
LOG(WARNING) << "Invalid Redis DB index: " << db_index_val
<< ", using default 0";
}
return std::make_shared<RedisStoragePlugin>(

View File

@ -27,6 +27,7 @@
#include <regex>
#include "common.h"
#include "environ.h"
#include "transfer_engine.h"
#include "transfer_metadata.h"
#include "transport/transport.h"
@ -41,11 +42,11 @@ CxlTransport::CxlTransport() {
// cxl_dev_path = "/dev/dax0.0";
// cxl_dev_size = 1024 * 1024 * 1024;
// get from env
const char *env_cxl_dev_path = std::getenv("MC_CXL_DEV_PATH");
std::string env_cxl_dev_path = Environ::Get().GetCxlDevPath();
if (env_cxl_dev_path) {
if (!env_cxl_dev_path.empty()) {
LOG(INFO) << "MC_CXL_DEV_PATH: " << env_cxl_dev_path;
cxl_dev_path = (char *)env_cxl_dev_path;
cxl_dev_path = env_cxl_dev_path;
cxl_dev_size = cxlGetDeviceSize();
}
}
@ -60,13 +61,13 @@ CxlTransport::~CxlTransport() {
size_t CxlTransport::cxlGetDeviceSize() {
// for now, get cxl_shm size from env
const char *env_cxl_dev_size = std::getenv("MC_CXL_DEV_SIZE");
std::string env_cxl_dev_size = Environ::Get().GetCxlDevSize();
if (env_cxl_dev_size) {
if (!env_cxl_dev_size.empty()) {
LOG(INFO) << "MC_CXL_DEV_SIZE: " << env_cxl_dev_size;
char *end = nullptr;
unsigned long long val = strtoull(env_cxl_dev_size, &end, 10);
if (end != env_cxl_dev_size && *end == '\0')
unsigned long long val = strtoull(env_cxl_dev_size.c_str(), &end, 10);
if (end != env_cxl_dev_size.c_str() && *end == '\0')
return static_cast<size_t>(val);
} else {
// try to read dev size from sys
@ -75,8 +76,7 @@ size_t CxlTransport::cxlGetDeviceSize() {
std::regex dax_pattern(R"(dax\d+\.\d+)");
std::smatch match;
std::string dev_name;
std::string str_cxl_dev_path = std::string(cxl_dev_path);
if (std::regex_search(str_cxl_dev_path, match, dax_pattern)) {
if (std::regex_search(cxl_dev_path, match, dax_pattern)) {
dev_name = match.str();
} else {
LOG(ERROR) << "Can not find CXL device name in path: "
@ -167,11 +167,11 @@ bool CxlTransport::isAddressInCxlRange(void *addr) {
}
int CxlTransport::cxlDevInit() {
if (!cxl_dev_path || !cxl_dev_size) {
if (cxl_dev_path.empty() || !cxl_dev_size) {
LOG(ERROR) << "CxlTransport: cxl_dev_path or cxl_dev_size is null.";
return -1;
}
int fd = open(cxl_dev_path, O_RDWR);
int fd = open(cxl_dev_path.c_str(), O_RDWR);
if (fd == -1) {
LOG(ERROR) << "CxlTransport: Cannot open cxl device."
<< strerror(errno);

View File

@ -27,6 +27,7 @@
#include "common.h"
#include "common/serialization.h"
#include "config.h"
#include "environ.h"
#include "transfer_metadata.h"
#include "transport/transport.h"
@ -286,53 +287,34 @@ static void setupP2PAccess(int num_devices) {
}
static int getNumStreams() {
const char *env = getenv("MC_HIP_NUM_STREAMS");
if (env) {
try {
int value = std::stoi(env);
if (value > 0) {
return value;
}
LOG(WARNING) << "MC_HIP_NUM_STREAMS value " << value
<< " must be positive, using default "
<< kDefaultNumStreams;
} catch (...) {
LOG(WARNING) << "Invalid MC_HIP_NUM_STREAMS value, using default "
<< kDefaultNumStreams;
}
int num_streams = Environ::Get().GetHipNumStreams();
if (num_streams > 0) {
return num_streams;
} else if (num_streams < 0) {
LOG(WARNING) << "MC_HIP_NUM_STREAMS value " << num_streams
<< " must be positive, using default "
<< kDefaultNumStreams;
}
return kDefaultNumStreams;
}
static int getNumEvents() {
const char *env = getenv("MC_HIP_NUM_EVENTS");
if (env) {
try {
int value = std::stoi(env);
if (value > 0) {
return value;
}
LOG(WARNING) << "MC_HIP_NUM_EVENTS value " << value
<< " must be positive, using default "
<< kDefaultNumEvents;
} catch (...) {
LOG(WARNING) << "Invalid MC_HIP_NUM_EVENTS value, using default "
<< kDefaultNumEvents;
}
int num_events = Environ::Get().GetHipNumEvents();
if (num_events > 0) {
return num_events;
} else if (num_events < 0) {
LOG(WARNING) << "MC_HIP_NUM_EVENTS value " << num_events
<< " must be positive, using default "
<< kDefaultNumEvents;
}
return kDefaultNumEvents;
}
static bool supportFabricMem() {
// By default, use IPC mode. Fabric memory is enabled only when
// MC_USE_HIP_IPC=0 or MC_USE_NVLINK_IPC=0 is explicitly set.
const char *hip_ipc = getenv("MC_USE_HIP_IPC");
const char *nvlink_ipc = getenv("MC_USE_NVLINK_IPC");
bool fabric_enabled = (hip_ipc && strcmp(hip_ipc, "0") == 0) ||
(nvlink_ipc && strcmp(nvlink_ipc, "0") == 0);
if (!fabric_enabled) {
// By default, use IPC mode
// Fabric memory is enabled only when MC_USE_HIP_IPC=false
bool hip_ipc = Environ::Get().GetUseHipIpc();
if (hip_ipc) {
return false;
}

View File

@ -28,10 +28,13 @@
#include "common.h"
#include "common/serialization.h"
#include "config.h"
#include "error.h"
#include "transfer_engine.h"
#include "transfer_metadata.h"
#include "transport/transport.h"
#if defined(USE_CUDA)
static bool checkCudaErrorReturn(cudaError_t result, const char *message) {
if (result != cudaSuccess) {
LOG(ERROR) << message << " (Error code: " << result << " - "
@ -453,3 +456,100 @@ void IntraNodeNvlinkTransport::freePinnedLocalMemory(void *ptr) {
}
} // namespace mooncake
#else
namespace mooncake {
IntraNodeNvlinkTransport::IntraNodeNvlinkTransport() {}
IntraNodeNvlinkTransport::~IntraNodeNvlinkTransport() {}
int IntraNodeNvlinkTransport::install(
std::string &local_server_name, std::shared_ptr<TransferMetadata> metadata,
std::shared_ptr<Topology> topology) {
(void)local_server_name;
(void)metadata;
(void)topology;
LOG(ERROR) << "IntraNodeNvlinkTransport requires USE_CUDA=ON";
return ERR_NOT_IMPLEMENTED;
}
Status IntraNodeNvlinkTransport::submitTransfer(
BatchID batch_id, const std::vector<TransferRequest> &entries) {
(void)batch_id;
(void)entries;
return Status::NotImplemented(
"IntraNodeNvlinkTransport requires USE_CUDA=ON");
}
Status IntraNodeNvlinkTransport::getTransferStatus(BatchID batch_id,
size_t task_id,
TransferStatus &status) {
(void)batch_id;
(void)task_id;
(void)status;
return Status::NotImplemented(
"IntraNodeNvlinkTransport requires USE_CUDA=ON");
}
Status IntraNodeNvlinkTransport::submitTransferTask(
const std::vector<TransferTask *> &task_list) {
(void)task_list;
return Status::NotImplemented(
"IntraNodeNvlinkTransport requires USE_CUDA=ON");
}
int IntraNodeNvlinkTransport::registerLocalMemory(void *addr, size_t length,
const std::string &location,
bool remote_accessible,
bool update_metadata) {
(void)addr;
(void)length;
(void)location;
(void)remote_accessible;
(void)update_metadata;
return ERR_NOT_IMPLEMENTED;
}
int IntraNodeNvlinkTransport::unregisterLocalMemory(void *addr,
bool update_metadata) {
(void)addr;
(void)update_metadata;
return ERR_NOT_IMPLEMENTED;
}
int IntraNodeNvlinkTransport::registerLocalMemoryBatch(
const std::vector<Transport::BufferEntry> &buffer_list,
const std::string &location) {
(void)buffer_list;
(void)location;
return ERR_NOT_IMPLEMENTED;
}
int IntraNodeNvlinkTransport::unregisterLocalMemoryBatch(
const std::vector<void *> &addr_list) {
(void)addr_list;
return ERR_NOT_IMPLEMENTED;
}
int IntraNodeNvlinkTransport::relocateSharedMemoryAddress(uint64_t &dest_addr,
uint64_t length,
uint64_t target_id) {
(void)dest_addr;
(void)length;
(void)target_id;
return ERR_NOT_IMPLEMENTED;
}
void *IntraNodeNvlinkTransport::allocatePinnedLocalMemory(size_t size) {
(void)size;
LOG(ERROR) << "IntraNodeNvlinkTransport requires USE_CUDA=ON";
return nullptr;
}
void IntraNodeNvlinkTransport::freePinnedLocalMemory(void *ptr) { (void)ptr; }
} // namespace mooncake
#endif

View File

@ -28,6 +28,7 @@
#include "common.h"
#include "common/serialization.h"
#include "config.h"
#include "environ.h"
#include "transfer_engine.h"
#include "transfer_metadata.h"
#include "transport/transport.h"
@ -55,7 +56,7 @@ static int getNumDevices() {
}
static bool supportFabricMem() {
if (getenv("MC_USE_NVLINK_IPC")) return false;
if (!Environ::Get().GetNvlinkFabricMemEnabled()) return false;
int num_devices = 0;
cudaError_t err = cudaGetDeviceCount(&num_devices);

View File

@ -11,6 +11,7 @@
#include <pybind11/pytypes.h>
#include "async_simple/coro/SyncAwait.h"
#include "default_config.h"
#include "environ.h"
namespace mooncake {
namespace py = pybind11;
@ -50,8 +51,8 @@ bool RpcCommunicator::initialize(const RpcCommunicatorConfig& config) {
// Initialize client pools with proper configuration
coro_io::client_pool<coro_rpc::coro_rpc_client>::pool_config pool_conf{};
const char* value = std::getenv("MC_RPC_PROTOCOL");
if (value && std::string_view(value) == "rdma") {
std::string rpc_protocol = Environ::Get().GetRpcProtocol();
if (rpc_protocol == "rdma") {
pool_conf.client_config.socket_config =
coro_io::ib_socket_t::config_t{};
}
@ -68,7 +69,7 @@ bool RpcCommunicator::initialize(const RpcCommunicatorConfig& config) {
config.thread_count, config.listen_address,
std::chrono::seconds(config.timeout_seconds));
if (value && std::string_view(value) == "rdma") {
if (rpc_protocol == "rdma") {
if (server_) {
try {
server_->init_ibv();
@ -93,8 +94,8 @@ bool RpcCommunicator::initialize(const RpcCommunicatorConfig& config) {
&RpcCommunicator::handleTensorTransfer>(this);
}
LOG(INFO) << "Environment variable MC_RPC_PROTOCOL is set to "
<< (value ? value : "not set");
if (value && std::string_view(value) == "rdma") {
<< (rpc_protocol.empty() ? "not set" : rpc_protocol);
if (rpc_protocol == "rdma") {
LOG(INFO) << "Using RDMA transport for RPC communication";
} else {
LOG(INFO) << "Using TCP transport for RPC communication";

View File

@ -60,18 +60,19 @@ class CXLTransportTest : public ::testing::Test {
std::shared_ptr<mooncake::TransferMetadata> metadata_client;
int tmp_fd = -1;
uint8_t *addr = nullptr;
uint8_t *base_addr;
uint8_t *base_addr = nullptr;
std::pair<std::string, uint16_t> hostname_port;
std::unique_ptr<mooncake::TransferEngine> engine;
const size_t offset_1 = 2 * 1024 * 1024;
const size_t offset_2 = 6 * 1024 * 1024;
const size_t len = 2 * 1024 * 1024;
CxlTransport *cxl_xport;
Transport *xport;
void **args;
CxlTransport *cxl_xport = nullptr;
Transport *xport = nullptr;
void **args = nullptr;
mooncake::Transport::SegmentID segment_id;
std::shared_ptr<TransferMetadata::SegmentDesc> segment_desc;
const size_t kDataLength = 4 * 1024;
bool cxl_available = true;
protected:
void SetUp() override {
@ -86,7 +87,8 @@ class CXLTransportTest : public ::testing::Test {
// Set device name from gflags parameter
setenv("MC_CXL_DEV_PATH", FLAGS_device_name.c_str(), 1);
setenv("MC_CXL_DEV_SIZE", std::to_string(FLAGS_device_size).c_str(), 1);
std::string device_size_str = std::to_string(FLAGS_device_size);
setenv("MC_CXL_DEV_SIZE", device_size_str.c_str(), 1);
// cxl setup
engine = std::make_unique<TransferEngine>(false);
@ -99,7 +101,11 @@ class CXLTransportTest : public ::testing::Test {
args = (void **)malloc(2 * sizeof(void *));
args[0] = nullptr;
xport = engine->installTransport("cxl", args);
ASSERT_NE(xport, nullptr);
if (xport == nullptr) {
cxl_available = false;
LOG(WARNING) << "CXL device not available, tests will be skipped";
return;
}
cxl_xport = dynamic_cast<CxlTransport *>(xport);
base_addr = (uint8_t *)cxl_xport->getCxlBaseAddr();
@ -117,13 +123,20 @@ class CXLTransportTest : public ::testing::Test {
close(tmp_fd);
unlink(FLAGS_device_name.c_str());
}
free(args);
if (args) {
free(args);
}
google::ShutdownGoogleLogging();
freeMemoryPool(addr, kDataLength);
if (addr) {
freeMemoryPool(addr, kDataLength);
}
}
};
TEST_F(CXLTransportTest, MultiWrite) {
if (!cxl_available) {
GTEST_SKIP() << "CXL device not available";
}
int times = 10;
while (times--) {
for (size_t offset = 0; offset < kDataLength; ++offset)
@ -159,6 +172,9 @@ TEST_F(CXLTransportTest, MultiWrite) {
}
TEST_F(CXLTransportTest, MultipleRead) {
if (!cxl_available) {
GTEST_SKIP() << "CXL device not available";
}
int times = 10;
while (times--) {
for (size_t offset = 0; offset < kDataLength; ++offset)