blob: 7afec0a37d1762dc8c358ab0e1196f22abc97f11 [file] [log] [blame] [edit]
/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION &
* AFFILIATES. All rights reserved. SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mockupResponder.hpp"
#include "base.h"
#include "device-capability-discovery.h"
#include "device-configuration.h"
#include "diagnostics.h"
#include "firmware-utils.h"
#include "network-ports.h"
#include "pci-links.h"
#include "platform-environmental.h"
#include "gpmMetricsList.hpp"
#include "types.hpp"
#include "utils.hpp"
#include <endian.h>
#include <sys/socket.h>
#include <phosphor-logging/lg2.hpp>
#include <cstdint>
#include <ctime>
#include <functional>
using namespace utils;
namespace MockupResponder
{
MockupResponder::MockupResponder(bool verbose, sdeventplus::Event& event,
sdbusplus::asio::object_server& server,
eid_t eid, uint8_t deviceType,
uint8_t instanceId) :
event(event), verbose(verbose), server(server), eventReceiverEid(0),
globalEventGenerationSetting(GLOBAL_EVENT_GENERATION_DISABLE),
state({
{}, // writeProtected
0, // istMode
{
{RP_IN_SYSTEM_TEST, {}},
{RP_FUSING_MODE, {}},
{RP_CONFIDENTIAL_COMPUTE, {}},
{RP_BAR0_FIREWALL, {}},
{RP_CONFIDENTIAL_COMPUTE_DEV_MODE, {}},
{RP_TOTAL_GPU_POWER_CURRENT_LIMIT, {}},
{RP_TOTAL_GPU_POWER_RATED_LIMIT, {}},
{RP_TOTAL_GPU_POWER_MAX_LIMIT, {}},
{RP_TOTAL_GPU_POWER_MIN_LIMIT, {}},
{RP_CLOCK_LIMIT, {}},
{RP_NVLINK_DISABLE, {}},
{RP_ECC_ENABLE, {}},
{RP_PCIE_VF_CONFIGURATION, {}},
{RP_ROW_REMAPPING_ALLOWED, {}},
{RP_ROW_REMAPPING_FEATURE, {}},
{RP_HBM_FREQUENCY_CHANGE, {}},
{RP_HULK_LICENSE_UPDATE, {}},
{RP_FORCE_TEST_COUPLING, {}},
{RP_BAR0_TYPE_CONFIG, {}},
{RP_EDPP_SCALING_FACTOR, {}},
{RP_POWER_SMOOTHING_PRIVILEGE_LEVEL_1, {}},
{RP_POWER_SMOOTHING_PRIVILEGE_LEVEL_2, {}},
{RP_EGM_MODE, {}},
{RP_INFOROM_RECREATE_ALLOW_INB, {}},
}, // prcKnobs
{
0, // mode
0, // persistent
}, // errorInjectionMode
{
0, // offset
0, // error_injection_id
0, // fault_reason_bit_map
}, // errorInjectionPayload
{
{NSM_DEV_ID_GPU,
{
{EI_MEMORY_ERRORS, false},
{EI_THERMAL_ERRORS, false},
}},
{NSM_DEV_ID_SWITCH,
{
{EI_NVLINK_ERRORS, false},
}},
{NSM_DEV_ID_PCIE_BRIDGE,
{
{EI_PCI_ERRORS, false},
{EI_NVLINK_ERRORS, false},
}},
{NSM_DEV_ID_MCTP_BRIDGE,
{
{EI_FATAL_ERRORS, false},
}},
}, // errorInjection
0, // migMode
0, // eccMode
})
{
std::string path = "/xyz/openbmc_project/NSM/" + std::to_string(eid);
iface = server.add_interface(path, "xyz.openbmc_project.NSM.Device");
iface->register_method("genRediscoveryEvent", [&](uint8_t eid, bool ackr) {
sendRediscoveryEvent(eid, ackr);
});
iface->register_method("genRawEvent",
[&](uint8_t eid, uint8_t nsmType, bool ackr,
uint8_t ver, uint8_t eventId, uint8_t eventClass,
uint16_t eventState) {
sendNsmEvent(eid, nsmType, ackr, ver, eventId, eventClass, eventState,
0, NULL);
});
iface->register_method("genXIDEvent",
[&](uint8_t eid, bool ackr, uint8_t flag,
uint32_t reason, uint32_t sequence_number,
uint64_t timestamp, std::string message_text) {
sendXIDEvent(eid, ackr, flag, reason, sequence_number, timestamp,
message_text);
});
iface->register_method(
"genResetRequiredEvent",
[&](uint8_t eid, bool ackr) { sendResetRequiredEvent(eid, ackr); });
iface->register_method(
"genThreasholdEvent",
[&](uint8_t dest, bool ackr, bool port_rcv_errors_threshold,
bool port_xmit_discard_threshold, bool symbol_ber_threshold,
bool port_rcv_remote_physical_errors_threshold,
bool port_rcv_switch_relay_errors_threshold,
bool effective_ber_threshold,
bool estimated_effective_ber_threshold, uint8_t portNumber) {
sendThreasholdEvent(
dest, ackr, port_rcv_errors_threshold, port_xmit_discard_threshold,
symbol_ber_threshold, port_rcv_remote_physical_errors_threshold,
port_rcv_switch_relay_errors_threshold, effective_ber_threshold,
estimated_effective_ber_threshold, portNumber);
});
iface->register_method("genFabricManagerStateEvent",
[&](uint8_t eid, bool ackr, uint8_t state,
uint8_t status, uint64_t last_restart_time,
uint64_t last_restart_duration) {
sendFabricManagerStateEvent(eid, ackr, state, status, last_restart_time,
last_restart_duration);
});
iface->initialize();
mockEid = eid;
mockDeviceType = deviceType;
mockInstanceId = instanceId;
sockFd = initSocket();
}
int MockupResponder::initSocket()
{
if (verbose)
{
lg2::info("connect to Mockup EID({EID})", "EID", mockEid);
}
auto fd = ::socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (fd == -1)
{
return false;
}
struct sockaddr_un addr{};
addr.sun_family = AF_UNIX;
memcpy(addr.sun_path, MCTP_SOCKET_PATH, sizeof(MCTP_SOCKET_PATH) - 1);
if (::connect(fd, (struct sockaddr*)&addr,
sizeof(MCTP_SOCKET_PATH) + sizeof(addr.sun_family) - 1) == -1)
{
lg2::error(
"connect() error to mctp-demux-daemon, errno = {ERROR}, {STRERROR}",
"ERROR", errno, "STRERROR", std::strerror(errno));
close(fd);
return -1;
}
uint8_t prefix = MCTP_MSG_EMU_PREFIX;
uint8_t type = MCTP_MSG_TYPE_VDM;
ssize_t ret = ::write(fd, &prefix, sizeof(uint8_t));
if (ret < 0)
{
lg2::error(
"Failed to write mockup prefix code to socket, errno = {ERROR}, {STRERROR}",
"ERROR", errno, "STRERROR", strerror(errno));
close(fd);
return -1;
}
ret = ::write(fd, &type, sizeof(uint8_t));
if (ret < 0)
{
lg2::error(
"Failed to write VDM type code to socket, errno = {ERROR}, {STRERROR}",
"ERROR", errno, "STRERROR", strerror(errno));
close(fd);
return -1;
}
ret = ::write(fd, &mockEid, sizeof(uint8_t));
if (ret == -1)
{
lg2::error("Failed to write eid to socket, errno = {ERROR}, {STRERROR}",
"ERROR", errno, "STRERROR", strerror(errno));
close(fd);
return -1;
}
auto callback = [this](sdeventplus::source::IO& io, int fd,
uint32_t revents) mutable {
if (!(revents & EPOLLIN))
{
return;
}
ssize_t peekedLength = recv(fd, nullptr, 0, MSG_PEEK | MSG_TRUNC);
if (peekedLength == 0)
{
io.get_event().exit(0);
}
else if (peekedLength <= -1)
{
lg2::error("recv system call failed");
return;
}
std::vector<uint8_t> requestMsg(peekedLength);
auto recvDataLength = recv(fd, static_cast<void*>(requestMsg.data()),
peekedLength, 0);
if (recvDataLength != peekedLength)
{
lg2::error("Failure to read peeked length packet. peekedLength="
"{PEEKEDLENGTH} recvDataLength={RECVDATALENGTH}",
"PEEKEDLENGTH", peekedLength, "RECVDATALENGTH",
recvDataLength);
return;
}
if (requestMsg[2] != MCTP_MSG_TYPE_VDM)
{
lg2::error("Received non VDM message type={TYPE}", "TYPE",
requestMsg[2]);
return;
}
if (verbose)
{
utils::printBuffer(utils::Rx, &requestMsg[3], requestMsg.size() - 3,
requestMsg[0], requestMsg[1]);
}
// Outgoing message.
iovec iov[2]{};
// This structure contains the parameter information for the
// response message.
msghdr msg{};
// process message and send response
std::optional<Response> longRunningEvent;
auto response = processRxMsg(requestMsg, longRunningEvent);
if (response)
{
constexpr uint8_t tagOwnerBitPos = 3;
constexpr uint8_t tagOwnerMask = ~(1 << tagOwnerBitPos);
// Set tag owner bit to 0 for NSM responses
requestMsg[0] = requestMsg[0] & tagOwnerMask;
iov[0].iov_base = &requestMsg[0];
iov[0].iov_len = sizeof(requestMsg[0]) + sizeof(requestMsg[1]) +
sizeof(requestMsg[2]);
iov[1].iov_base = (*response).data();
iov[1].iov_len = (*response).size();
msg.msg_iov = iov;
msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
if (verbose)
{
utils::printBuffer(utils::Tx, *response, requestMsg[0],
requestMsg[1]);
}
int result = sendmsg(fd, &msg, 0);
if (result < 0)
{
lg2::error("sendmsg system call failed");
}
}
if (longRunningEvent)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
auto eid = requestMsg[1];
auto rc = mctpSockSend(eid, *longRunningEvent);
if (rc != NSM_SUCCESS)
{
lg2::error("mctpSockSend() failed, rc={RC}", "RC", rc);
}
}
};
io = std::make_unique<sdeventplus::source::IO>(event, fd, EPOLLIN,
std::move(callback));
return fd;
}
std::optional<Response>
MockupResponder::processRxMsg(const Request& rxMsg,
std::optional<Request>& longRunningEvent)
{
nsm_header_info hdrFields{};
auto hdr =
reinterpret_cast<const nsm_msg_hdr*>(rxMsg.data() + MCTP_DEMUX_PREFIX);
if (NSM_SUCCESS != unpack_nsm_header(hdr, &hdrFields))
{
lg2::error("Empty NSM request header");
return std::nullopt;
}
if (NSM_EVENT_ACKNOWLEDGMENT == hdrFields.nsm_msg_type)
{
if (verbose)
{
lg2::info("received NSM event acknowledgement length={LEN}", "LEN",
rxMsg.size());
}
return std::nullopt;
}
if (NSM_REQUEST == hdrFields.nsm_msg_type)
{
if (verbose)
{
lg2::info("received NSM request length={LEN}", "LEN", rxMsg.size());
}
}
auto request = reinterpret_cast<const nsm_msg*>(hdr);
size_t requestLen = rxMsg.size() - MCTP_DEMUX_PREFIX;
auto nvidiaMsgType = request->hdr.nvidia_msg_type;
auto command = request->payload[0];
if (verbose)
{
lg2::info("nsm msg type={TYPE} command code={COMMAND}", "TYPE",
nvidiaMsgType, "COMMAND", command);
}
switch (nvidiaMsgType)
{
case NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY:
switch (command)
{
case NSM_PING:
return pingHandler(request, requestLen);
case NSM_SUPPORTED_NVIDIA_MESSAGE_TYPES:
return getSupportNvidiaMessageTypesHandler(request,
requestLen);
case NSM_SUPPORTED_COMMAND_CODES:
return getSupportCommandCodeHandler(request, requestLen);
case NSM_QUERY_DEVICE_IDENTIFICATION:
return queryDeviceIdentificationHandler(request,
requestLen);
case NSM_GET_EVENT_SUBSCRIPTION:
return getEventSubscription(request, requestLen);
case NSM_SET_EVENT_SUBSCRIPTION:
return setEventSubscription(request, requestLen);
case NSM_SET_CURRENT_EVENT_SOURCES:
return setCurrentEventSources(request, requestLen);
case NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT:
return configureEventAcknowledgement(request, requestLen);
case NSM_GET_HISTOGRAM_FORMAT:
return getHistogramFormatHandler(request, requestLen);
case NSM_GET_HISTOGRAM_DATA:
return getHistogramDataHandler(request, requestLen);
default:
lg2::error(
"unsupported Command:{CMD} request length={LEN}, msgType={TYPE}",
"CMD", command, "LEN", requestLen, "TYPE",
nvidiaMsgType);
return unsupportedCommandHandler(request, requestLen);
}
break;
case NSM_TYPE_NETWORK_PORT:
switch (command)
{
case NSM_GET_PORT_TELEMETRY_COUNTER:
return getPortTelemetryCounterHandler(request, requestLen);
case NSM_QUERY_PORT_CHARACTERISTICS:
return queryPortCharacteristicsHandler(request, requestLen);
case NSM_QUERY_PORT_STATUS:
return queryPortStatusHandler(request, requestLen);
case NSM_GET_FABRIC_MANAGER_STATE:
return getFabricManagerStateHandler(request, requestLen);
case NSM_QUERY_PORTS_AVAILABLE:
return queryPortsAvailableHandler(request, requestLen);
case NSM_SET_PORT_DISABLE_FUTURE:
return setPortDisableFutureHandler(request, requestLen);
case NSM_GET_PORT_DISABLE_FUTURE:
return getPortDisableFutureHandler(request, requestLen);
case NSM_GET_POWER_MODE:
return getPowerModeHandler(request, requestLen);
case NSM_SET_POWER_MODE:
return setPowerModeHandler(request, requestLen);
case NSM_GET_SWITCH_ISOLATION_MODE:
return getSwitchIsolationMode(request, requestLen);
case NSM_SET_SWITCH_ISOLATION_MODE:
return setSwitchIsolationMode(request, requestLen);
case NSM_GET_ETH_PORT_TELEMETRY_COUNTER:
return getEthPortTelemetryCounterHandler(request,
requestLen);
case NSM_GET_NETWORK_ADDRESSES:
return getPortNetworkAddressesHandler(request, requestLen);
case NSM_GET_PORT_ECC_COUNTERS:
return getPortEccCountersHandler(request, requestLen);
default:
lg2::error(
"unsupported Command:{CMD} request length={LEN}, msgType={TYPE}",
"CMD", command, "LEN", requestLen, "TYPE",
nvidiaMsgType);
return unsupportedCommandHandler(request, requestLen);
}
break;
case NSM_TYPE_PLATFORM_ENVIRONMENTAL:
switch (command)
{
case NSM_GET_INVENTORY_INFORMATION:
return getInventoryInformationHandler(request, requestLen);
case NSM_GET_TEMPERATURE_READING:
return getTemperatureReadingHandler(request, requestLen);
case NSM_READ_THERMAL_PARAMETER:
return readThermalParameterHandler(request, requestLen);
case NSM_GET_POWER:
return getCurrentPowerDrawHandler(request, requestLen);
case NSM_GET_MAX_OBSERVED_POWER:
return getMaxObservedPowerHandler(request, requestLen);
case NSM_GET_ENERGY_COUNT:
return getCurrentEnergyCountHandler(request, requestLen);
case NSM_GET_VOLTAGE:
return getVoltageHandler(request, requestLen);
case NSM_GET_ALTITUDE_PRESSURE:
return getAltitudePressureHandler(request, requestLen);
case NSM_GET_DRIVER_INFO:
return getDriverInfoHandler(request, requestLen);
case NSM_GET_MIG_MODE:
return getMigModeHandler(request, requestLen, true,
longRunningEvent);
case NSM_SET_MIG_MODE:
return setMigModeHandler(request, requestLen, true,
longRunningEvent);
case NSM_GET_ECC_MODE:
return getEccModeHandler(request, requestLen, true,
longRunningEvent);
case NSM_SET_ECC_MODE:
return setEccModeHandler(request, requestLen, true,
longRunningEvent);
case NSM_GET_ECC_ERROR_COUNTS:
return getEccErrorCountsHandler(request, requestLen);
case NSM_GET_PROGRAMMABLE_EDPP_SCALING_FACTOR:
return getEDPpScalingFactorHandler(request, requestLen);
case NSM_SET_PROGRAMMABLE_EDPP_SCALING_FACTOR:
return setEDPpScalingFactorHandler(request, requestLen);
case NSM_GET_CLOCK_LIMIT:
return getClockLimitHandler(request, requestLen);
case NSM_SET_CLOCK_LIMIT:
return setClockLimitHandler(request, requestLen);
case NSM_GET_CURRENT_CLOCK_FREQUENCY:
return getCurrClockFreqHandler(request, requestLen);
case NSM_GET_CLOCK_EVENT_REASON_CODES:
return getProcessorThrottleReasonHandler(request,
requestLen);
case NSM_GET_ACCUMULATED_GPU_UTILIZATION_TIME:
return getAccumCpuUtilTimeHandler(request, requestLen);
case NSM_GET_CURRENT_UTILIZATION:
return getCurrentUtilizationHandler(request, requestLen,
true, longRunningEvent);
case NSM_SET_POWER_LIMITS:
return setPowerLimitHandler(request, requestLen);
case NSM_GET_POWER_LIMITS:
return getPowerLimitHandler(request, requestLen);
case NSM_GET_CLOCK_OUTPUT_ENABLE_STATE:
return getClockOutputEnableStateHandler(request,
requestLen);
case NSM_GET_ROW_REMAP_STATE_FLAGS:
return getRowRemapStateHandler(request, requestLen);
case NSM_GET_ROW_REMAPPING_COUNTS:
return getRowRemappingCountsHandler(request, requestLen);
case NSM_GET_ROW_REMAP_AVAILABILITY:
return getRowRemapAvailabilityHandler(request, requestLen);
case NSM_GET_MEMORY_CAPACITY_UTILIZATION:
return getMemoryCapacityUtilHandler(request, requestLen,
true, longRunningEvent);
case NSM_QUERY_AGGREGATE_GPM_METRICS:
return queryAggregatedGPMMetrics(request, requestLen);
case NSM_QUERY_PER_INSTANCE_GPM_METRICS:
return queryPerInstanceGPMMetrics(request, requestLen);
case NSM_GET_VIOLATION_DURATION:
return getViolationDurationHandler(request, requestLen,
true, longRunningEvent);
/*
** Power Smoothing related Mockups
*/
case NSM_PWR_SMOOTHING_TOGGLE_FEATURESTATE:
return toggleFeatureState(request, requestLen);
case NSM_PWR_SMOOTHING_GET_FEATURE_INFO:
return getPowerSmoothingFeatureInfo(request, requestLen);
case NSM_PWR_SMOOTHING_GET_HARDWARE_CIRCUITRY_LIFETIME_USAGE:
return getHwCircuiteryUsage(request, requestLen);
case NSM_PWR_SMOOTHING_GET_CURRENT_PROFILE_INFORMATION:
return getCurrentProfileInfo(request, requestLen);
case NSM_PWR_SMOOTHING_QUERY_ADMIN_OVERRIDE:
return getQueryAdminOverride(request, requestLen);
case NSM_PWR_SMOOTHING_SET_ACTIVE_PRESET_PROFILE:
return setActivePresetProfile(request, requestLen);
case NSM_PWR_SMOOTHING_SETUP_ADMIN_OVERRIDE:
return setupAdminOverride(request, requestLen);
case NSM_PWR_SMOOTHING_APPLY_ADMIN_OVERRIDE:
return applyAdminOverride(request, requestLen);
case NSM_PWR_SMOOTHING_TOGGLE_IMMEDIATE_RAMP_DOWN:
return toggleImmediateRampDown(request, requestLen);
case NSM_PWR_SMOOTHING_GET_PRESET_PROFILE_INFORMATION:
return getPresetProfileInfo(request, requestLen);
case NSM_PWR_SMOOTHING_UPDATE_PRESET_PROFILE_PARAMETERS:
return updatePresetProfileParams(request, requestLen);
/*
** Workload Power profile mock responder
*/
case NSM_ENABLE_WORKLOAD_POWER_PROFILE:
return enableWorkloadPowerProfile(request, requestLen);
case NSM_DISABLE_WORKLOAD_POWER_PROFILE:
return disableWorkloadPowerProfile(request, requestLen);
case NSM_GET_WORKLOAD_POWER_PROFILE_STATUS_INFO:
return getWorkLoadProfileStatusInfo(request, requestLen);
case NSM_GET_WORKLOAD_POWER_PROFILE_INFO:
return getWorkloadPowerProfileInfo(request, requestLen);
default:
lg2::error(
"unsupported Command:{CMD} request length={LEN}, msgType={TYPE}",
"CMD", command, "LEN", requestLen, "TYPE",
nvidiaMsgType);
return unsupportedCommandHandler(request, requestLen);
}
break;
case NSM_TYPE_PCI_LINK:
switch (command)
{
case NSM_QUERY_SCALAR_GROUP_TELEMETRY_V1:
return queryScalarGroupTelemetryHandler(request,
requestLen);
case NSM_ASSERT_PCIE_FUNDAMENTAL_RESET:
return pcieFundamentalResetHandler(request, requestLen);
case NSM_CLEAR_DATA_SOURCE_V1:
return clearScalarDataSourceHandler(request, requestLen);
case NSM_QUERY_AVAILABLE_CLEARABLE_SCALAR_DATA_SOURCES:
return queryAvailableAndClearableScalarGroupHandler(
request, requestLen);
case NSM_LIST_AVAILABLE_PCIE_PORTS:
return getListAvailablePciePortsHandler(request,
requestLen);
case NSM_MULTIPORT_QUERY_SCALAR_GROUP_TELEMETRY_V2:
return queryMultiportScalarGroupTelemetryHandler(
request, requestLen);
default:
lg2::error(
"unsupported Command:{CMD} request length={LEN}, msgType={TYPE}",
"CMD", command, "LEN", requestLen, "TYPE",
nvidiaMsgType);
return unsupportedCommandHandler(request, requestLen);
}
break;
case NSM_TYPE_DIAGNOSTIC:
switch (command)
{
case NSM_GET_DEVICE_RESET_STATISTICS:
return queryAggregatedResetMetrics(request, requestLen);
case NSM_QUERY_TOKEN_PARAMETERS:
return queryTokenParametersHandler(request, requestLen);
case NSM_PROVIDE_TOKEN:
return provideTokenHandler(request, requestLen);
case NSM_DISABLE_TOKENS:
return disableTokensHandler(request, requestLen);
case NSM_QUERY_TOKEN_STATUS:
return queryTokenStatusHandler(request, requestLen);
case NSM_QUERY_DEVICE_IDS:
return queryDeviceIdsHandler(request, requestLen);
case NSM_RESET_NETWORK_DEVICE:
return resetNetworkDeviceHandler(request, requestLen);
case NSM_ENABLE_DISABLE_WP:
return enableDisableWriteProtectedHandler(request,
requestLen);
case NSM_GET_DEVICE_DIAGNOSTICS:
return getDeviceDiagnosticsHandler(request, requestLen);
case NSM_GET_NETWORK_DEVICE_DEBUG_INFO:
return getNetworkDeviceDebugInfoHandler(request,
requestLen);
case NSM_ERASE_TRACE:
return eraseTraceHandler(request, requestLen);
case NSM_GET_NETWORK_DEVICE_LOG_INFO:
return getNetworkDeviceLogInfoHandler(request, requestLen);
case NSM_ERASE_DEBUG_INFO:
return eraseDebugInfoHandler(request, requestLen);
default:
lg2::error(
"unsupported Command:{CMD} request length={LEN}, msgType={TYPE}",
"CMD", command, "LEN", requestLen, "TYPE",
nvidiaMsgType);
return unsupportedCommandHandler(request, requestLen);
}
break;
case NSM_TYPE_DEVICE_CONFIGURATION:
switch (command)
{
case NSM_GET_ERROR_INJECTION_MODE_V1:
return getErrorInjectionModeV1Handler(request, requestLen);
case NSM_SET_ERROR_INJECTION_MODE_V1:
return setErrorInjectionModeV1Handler(request, requestLen);
case NSM_GET_SUPPORTED_ERROR_INJECTION_TYPES_V1:
return getSupportedErrorInjectionTypesV1Handler(request,
requestLen);
case NSM_SET_CURRENT_ERROR_INJECTION_TYPES_V1:
return setCurrentErrorInjectionTypesV1Handler(request,
requestLen);
case NSM_GET_CURRENT_ERROR_INJECTION_TYPES_V1:
return getCurrentErrorInjectionTypesV1Handler(request,
requestLen);
case NSM_GET_ERROR_INJECTION_PAYLOAD:
return getErrorInjectionPayloadHandler(request, requestLen);
case NSM_SET_ERROR_INJECTION_PAYLOAD:
return setErrorInjectionPayloadHandler(request, requestLen);
case NSM_ACTIVATE_ERROR_INJECTION:
return activateErrorInjectionHandler(request, requestLen);
case NSM_GET_RECONFIGURATION_PERMISSIONS_V1:
return getReconfigurationPermissionsV1Handler(request,
requestLen);
case NSM_SET_RECONFIGURATION_PERMISSIONS_V1:
return setReconfigurationPermissionsV1Handler(request,
requestLen);
case NSM_GET_CONFIDENTIAL_COMPUTE_MODE_V1:
return getConfidentialComputeModeHandler(request,
requestLen);
case NSM_SET_CONFIDENTIAL_COMPUTE_MODE_V1:
return setConfidentialComputeModeHandler(request,
requestLen);
case NSM_ENABLE_DISABLE_GPU_IST_MODE:
return enableDisableGpuIstModeHandler(request, requestLen);
case NSM_GET_FPGA_DIAGNOSTICS_SETTINGS:
return getFpgaDiagnosticsSettingsHandler(request,
requestLen);
default:
lg2::error(
"unsupported Command:{CMD} request length={LEN}, msgType={TYPE}",
"CMD", command, "LEN", requestLen, "TYPE",
nvidiaMsgType);
return unsupportedCommandHandler(request, requestLen);
}
break;
case NSM_TYPE_FIRMWARE:
switch (command)
{
case NSM_FW_GET_EROT_STATE_INFORMATION:
return getRotInformation(request, requestLen);
case NSM_FW_IRREVERSABLE_CONFIGURATION:
return irreversibleConfig(request, requestLen);
case NSM_FW_QUERY_CODE_AUTH_KEY_PERM:
return codeAuthKeyPermQueryHandler(request, requestLen);
case NSM_FW_UPDATE_CODE_AUTH_KEY_PERM:
return codeAuthKeyPermUpdateHandler(request, requestLen);
case NSM_FW_QUERY_MIN_SECURITY_VERSION_NUMBER:
return queryFirmwareSecurityVersion(request, requestLen);
case NSM_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER:
return updateMinSecurityVersion(request, requestLen);
default:
lg2::error(
"unsupported Command:{CMD} request length={LEN}, msgType={TYPE}",
"CMD", command, "LEN", requestLen, "TYPE",
nvidiaMsgType);
return unsupportedCommandHandler(request, requestLen);
}
default:
lg2::error("unsupported Message:{TYPE} request length={LEN}",
"TYPE", nvidiaMsgType, "LEN", requestLen);
return unsupportedCommandHandler(request, requestLen);
}
return std::nullopt;
}
bool pmDisabled()
{
// touch /tmp/pm-disabled for disable persistent mode
// rm /tmp/pm-disabled for enable persistent mode
return std::filesystem::exists("/tmp/pm-disabled");
}
Response unsupportedResponse(uint8_t instanceId, uint8_t nvidiaMessageType,
uint8_t commandCode)
{
Response response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_non_success_resp),
0);
encode_common_resp(instanceId, NSM_ERR_UNSUPPORTED_COMMAND_CODE, ERR_NULL,
nvidiaMessageType, commandCode,
reinterpret_cast<nsm_msg*>(response.data()));
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::unsupportedCommandHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("unsupportedCommand: request length={LEN}", "LEN",
requestLen);
}
return unsupportedResponse(requestMsg->hdr.instance_id,
requestMsg->hdr.nvidia_msg_type,
requestMsg->payload[0]);
}
std::optional<std::vector<uint8_t>>
MockupResponder::pingHandler(const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info("pingHandler: request length={LEN}", "LEN", requestLen);
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = 0;
[[maybe_unused]] auto rc = encode_ping_resp(requestMsg->hdr.instance_id,
reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getSupportNvidiaMessageTypesHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info("getSupportNvidiaMessageTypesHandler: request length={LEN}",
"LEN", requestLen);
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_supported_nvidia_message_types_resp),
0);
// this is to mock that type-0, 1, 2, 3, 4 and 5 are supported
bitfield8_t types[SUPPORTED_MSG_TYPE_DATA_SIZE] = {
0x3F, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
uint8_t cc = NSM_SUCCESS;
uint16_t reason_code = ERR_NULL;
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_get_supported_nvidia_message_types_resp(
requestMsg->hdr.instance_id, cc, reason_code, types, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getSupportCommandCodeHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getSupportCommandCodeHandler: request length={LEN}", "LEN",
requestLen);
}
auto nvidiaMsgType =
reinterpret_cast<const nsm_get_supported_command_codes_req*>(
requestMsg->payload)
->nvidia_message_type;
if (nvidiaMsgType >= NUM_NSM_TYPES)
{
lg2::error(
"getSupportCommandCodeHandler: request msg type={MSG} is not supported",
"MSG", nvidiaMsgType);
return std::nullopt;
}
std::map<uint8_t, std::map<uint8_t, std::vector<uint8_t>>>
supportedCommands = {
{NSM_DEV_ID_BASEBOARD,
{
{0, {0, 1, 2, 9, 10}},
{1, {}},
{2, {4, 96}},
{3, {0, 2, 3, 4, 12, 15, 97, 106}},
{4, {101}},
{5, {98, 100}},
{6, {1}},
}},
{NSM_DEV_ID_SWITCH,
{
{0,
{0, 1, 2, 5, 6, 7, 9, 10, NSM_DISCOVER_HISTOGRAM,
NSM_GET_HISTOGRAM_FORMAT, NSM_GET_HISTOGRAM_DATA}},
{1, {1, 8, 9, 10, 11, 14, 68, 69}},
{2, {4}},
{3, {12}},
{4,
{NSM_GET_NETWORK_DEVICE_DEBUG_INFO, NSM_ERASE_TRACE,
NSM_GET_NETWORK_DEVICE_LOG_INFO, NSM_RESET_NETWORK_DEVICE,
NSM_QUERY_TOKEN_PARAMETERS, NSM_ERASE_DEBUG_INFO,
NSM_PROVIDE_TOKEN, NSM_DISABLE_TOKENS,
NSM_QUERY_TOKEN_STATUS, NSM_QUERY_DEVICE_IDS}},
{5, {3, 4, 5, 6, 7}},
}},
{NSM_DEV_ID_PCIE_BRIDGE,
{
{0, {0, 1, 2, 5, 6, 7, 9, 10}},
{1,
{1, NSM_GET_ETH_PORT_TELEMETRY_COUNTER,
NSM_GET_NETWORK_ADDRESSES, NSM_GET_PORT_ECC_COUNTERS}},
{NSM_TYPE_PCI_LINK,
{
NSM_QUERY_SCALAR_GROUP_TELEMETRY_V1,
NSM_LIST_AVAILABLE_PCIE_PORTS,
NSM_MULTIPORT_QUERY_SCALAR_GROUP_TELEMETRY_V2,
}},
{3, {12, 14, 97}},
{4,
{NSM_GET_NETWORK_DEVICE_DEBUG_INFO, NSM_ERASE_TRACE,
NSM_GET_NETWORK_DEVICE_LOG_INFO, NSM_QUERY_TOKEN_PARAMETERS,
NSM_PROVIDE_TOKEN, NSM_DISABLE_TOKENS,
NSM_QUERY_TOKEN_STATUS, NSM_QUERY_DEVICE_IDS}},
{5, {3, 4, 5, 6, 7}},
}},
{NSM_DEV_ID_GPU,
{
{0,
{0, 1, 2, 5, 6, 7, 9, 10, NSM_DISCOVER_HISTOGRAM,
NSM_GET_HISTOGRAM_FORMAT, NSM_GET_HISTOGRAM_DATA}},
{1, {1, 65, 66, 67, 68, 69}},
{2, {2, 4, 5}},
{3, {0, 2, 3, 6, 7, 8, 9, 10, 11, 12, 14,
15, 16, 17, 69, 70, 71, 73, 74, 77, 78, 79,
97, 118, 113, 114, 115, 116, 117, 119, 120, 121, 122,
123, 124, 125, 126, 127, 163, 164, 165, 166, 172, 173}},
{4,
{0, NSM_GET_DEVICE_DIAGNOSTICS,
NSM_GET_NETWORK_DEVICE_DEBUG_INFO, NSM_ERASE_TRACE,
NSM_GET_NETWORK_DEVICE_LOG_INFO, NSM_ERASE_DEBUG_INFO}},
{5, {3, 4, 5, 6, 7, 8, 9, 64, 65}},
{6, {1, 2, 3, 4, 5, 6}},
}},
{NSM_DEV_ID_EROT,
{
{0, {0, 1, 2, 9}},
{6,
{NSM_FW_GET_EROT_STATE_INFORMATION,
NSM_FW_IRREVERSABLE_CONFIGURATION,
NSM_FW_QUERY_CODE_AUTH_KEY_PERM,
NSM_FW_UPDATE_CODE_AUTH_KEY_PERM,
NSM_FW_QUERY_MIN_SECURITY_VERSION_NUMBER,
NSM_FW_UPDATE_MIN_SECURITY_VERSION_NUMBER}},
}},
{NSM_DEV_ID_MCTP_BRIDGE,
{
{NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY,
{
NSM_PING,
NSM_SUPPORTED_NVIDIA_MESSAGE_TYPES,
NSM_SUPPORTED_COMMAND_CODES,
NSM_SUPPORTED_EVENT_SOURCES,
NSM_QUERY_DEVICE_IDENTIFICATION,
NSM_CONFIGURE_EVENT_ACKNOWLEDGEMENT,
}},
{NSM_TYPE_PLATFORM_ENVIRONMENTAL,
{
NSM_GET_TEMPERATURE_READING,
NSM_READ_THERMAL_PARAMETER,
NSM_GET_POWER,
NSM_GET_INVENTORY_INFORMATION,
}},
{NSM_TYPE_DIAGNOSTIC,
{
NSM_GET_DEVICE_RESET_STATISTICS,
NSM_GET_DEVICE_DIAGNOSTICS,
}},
{NSM_TYPE_DEVICE_CONFIGURATION,
{
NSM_SET_ERROR_INJECTION_MODE_V1,
NSM_GET_ERROR_INJECTION_MODE_V1,
NSM_GET_SUPPORTED_ERROR_INJECTION_TYPES_V1,
NSM_SET_CURRENT_ERROR_INJECTION_TYPES_V1,
NSM_GET_CURRENT_ERROR_INJECTION_TYPES_V1,
NSM_GET_ERROR_INJECTION_PAYLOAD,
NSM_SET_ERROR_INJECTION_PAYLOAD,
NSM_ACTIVATE_ERROR_INJECTION,
}},
}},
};
bitfield8_t commandCodes[SUPPORTED_COMMAND_CODE_DATA_SIZE] = {0};
for (auto command : supportedCommands[mockDeviceType][nvidiaMsgType])
{
commandCodes[command / 8].byte |= 1 << (command % 8);
}
uint8_t cc = NSM_SUCCESS;
uint16_t reasonCode = ERR_NULL;
Response response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_supported_command_codes_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_get_supported_command_codes_resp(
requestMsg->hdr.instance_id, cc, reasonCode, commandCodes, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
void populateFrom(std::vector<uint8_t>& property, const std::string& data)
{
property.resize(data.length());
std::copy(data.data(), data.data() + data.length(), property.data());
}
void populateFrom(std::vector<uint8_t>& property, const uint32_t& data)
{
property.resize(sizeof(data));
std::copy((uint8_t*)&data, (uint8_t*)&data + sizeof(data), property.data());
}
void MockupResponder::generateDummyGUID(const uint8_t eid, uint8_t* data)
{
// just adding eid for first byte and rest is zero
memcpy(data, &eid, sizeof(eid));
}
std::vector<uint8_t> MockupResponder::getProperty(uint8_t propertyIdentifier)
{
std::vector<uint8_t> property;
switch (propertyIdentifier)
{
case BOARD_PART_NUMBER:
populateFrom(property, "MCX750500B-0D00_DK");
break;
case FRU_PART_NUMBER:
populateFrom(property, "FRU50500B-0D00_DK");
break;
case SERIAL_NUMBER:
populateFrom(property, "SN123456789");
break;
case MARKETING_NAME:
populateFrom(property, "NV123");
break;
case BUILD_DATE:
populateFrom(property, "2022-08-06T00:00:00Z");
break;
case DEVICE_GUID:
property = std::vector<uint8_t>{0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00};
generateDummyGUID(mockEid, property.data());
break;
case ASSET_TAG:
populateFrom(property, "MCX750500B-0D00_DK");
break;
case INFO_ROM_VERSION:
populateFrom(property, "128");
break;
case PRODUCT_LENGTH:
populateFrom(property, 850);
break;
case PRODUCT_WIDTH:
populateFrom(property, 730);
break;
case PRODUCT_HEIGHT:
populateFrom(property, 2600);
break;
case RATED_MODULE_POWER_LIMIT:
populateFrom(property, 5555);
break;
case MAXIMUM_MODULE_POWER_LIMIT:
populateFrom(property, 8788);
break;
case MINIMUM_MODULE_POWER_LIMIT:
populateFrom(property, 2754);
break;
case MINIMUM_DEVICE_POWER_LIMIT:
populateFrom(property, 10000);
break;
case MAXIMUM_DEVICE_POWER_LIMIT:
populateFrom(property, 100000);
break;
case RATED_DEVICE_POWER_LIMIT:
populateFrom(property, 80000);
break;
case MINIMUM_EDPP_SCALING_FACTOR:
property.push_back(19);
break;
case MAXIMUM_EDPP_SCALING_FACTOR:
property.push_back(86);
break;
case MINIMUM_GRAPHICS_CLOCK_LIMIT:
populateFrom(property, 100);
break;
case DEFAULT_BOOST_CLOCKS:
populateFrom(property, 30000);
break;
case DEFAULT_BASE_CLOCKS:
populateFrom(property, 300);
break;
case MAXIMUM_GRAPHICS_CLOCK_LIMIT:
populateFrom(property, 5000);
break;
case MINIMUM_MEMORY_CLOCK_LIMIT:
populateFrom(property, 150);
break;
case MAXIMUM_MEMORY_CLOCK_LIMIT:
populateFrom(property, 1500);
break;
case PCIERETIMER_0_EEPROM_VERSION:
case PCIERETIMER_1_EEPROM_VERSION:
case PCIERETIMER_2_EEPROM_VERSION:
case PCIERETIMER_3_EEPROM_VERSION:
case PCIERETIMER_4_EEPROM_VERSION:
case PCIERETIMER_5_EEPROM_VERSION:
case PCIERETIMER_6_EEPROM_VERSION:
case PCIERETIMER_7_EEPROM_VERSION:
property = std::vector<uint8_t>{0x01, 0x00, 0x1a, 0x00,
0x00, 0x00, 0x0a, 0x00};
break;
case DEVICE_PART_NUMBER:
populateFrom(property, "A1");
break;
case MAXIMUM_MEMORY_CAPACITY:
populateFrom(property, 200000);
break;
default:
break;
}
return property;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPortTelemetryCounterHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPortTelemetryCounterHandler: request length={LEN}", "LEN",
requestLen);
}
uint8_t portNumber = 0;
auto rc = decode_get_port_telemetry_counter_req(requestMsg, requestLen,
&portNumber);
if (rc != NSM_SW_SUCCESS)
{
if (verbose)
{
lg2::error("decode_get_port_telemetry_counter_req failed: rc={RC}",
"RC", rc);
}
return std::nullopt;
}
// mock data to send [that is 28 counter data]
uint32_t supportedCounterData = 0xFFFFFFFF;
std::vector<uint64_t> data{
10000000001, 10000000002, 10000000003, 10000000004, 10000000005,
10000000006, 10000000007, 10000000008, 10000000009, 10000000010,
10000000011, 10000000012, 10000000013, 10000000014, 10000000015,
10000000016, 10000000017, 10000000018, 10000000019, 10000000020,
10000000021, 10000000022, 10000000023, 10000000024, 10000000025,
10000000026, 10000000027, 10000000028, 10000000029, 10000000030,
10000000031, 10000000032};
nsm_port_counter_data portTelData = {};
std::memcpy(&portTelData, &supportedCounterData,
sizeof(nsm_supported_port_counter));
std::memcpy(&portTelData.port_rcv_pkts, data.data(),
data.size() * sizeof(uint64_t));
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) +
sizeof(nsm_common_resp) +
sizeof(nsm_port_counter_data),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_port_telemetry_counter_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
&portTelData, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_port_telemetry_counter_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryPortCharacteristicsHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("queryPortCharacteristicsHandler: request length={LEN}",
"LEN", requestLen);
}
uint8_t portNumber = 0;
auto rc = decode_query_port_characteristics_req(requestMsg, requestLen,
&portNumber);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_query_port_characteristics_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
// mock data to send
struct nsm_port_characteristics_data portCharData;
portCharData.port_status.link_state = 1;
portCharData.port_status.sub_link_state = 6;
portCharData.port_status.rx_detect_state = 1;
portCharData.port_status.port_down_reason_code =
NSM_PORT_DOWN_REASON_CODE_HI_SER_BER;
portCharData.nv_port_line_rate_mbps = 2500;
portCharData.nv_port_data_rate_kbps = 3000;
portCharData.status_lane_info = 225;
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_query_port_characteristics_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_port_characteristics_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
&portCharData, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_query_port_characteristics_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryPortStatusHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("queryPortStatusHandler: request length={LEN}", "LEN",
requestLen);
}
uint8_t portNumber = 0;
auto rc = decode_query_port_status_req(requestMsg, requestLen, &portNumber);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_query_port_status_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
uint16_t reason_code = ERR_NULL;
uint8_t port_state = NSM_PORTSTATE_UP;
uint8_t port_status = NSM_PORTSTATUS_ENABLED;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_query_port_status_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_port_status_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, port_state, port_status,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_query_port_status_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getFabricManagerStateHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getFabricManagerStateHandler: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_fabric_manager_state_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_fabric_manager_state_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
// mock data to send
std::vector<uint8_t> data{
0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
auto fmStateData =
reinterpret_cast<nsm_fabric_manager_state_data*>(data.data());
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_fabric_manager_state_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_fabric_manager_state_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
fmStateData, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_fabric_manager_state_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryPortsAvailableHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("queryPortsAvailableHandler: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_query_ports_available_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_query_ports_available_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
// mock data to send
uint16_t reason_code = ERR_NULL;
uint8_t number_of_ports = 6;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_query_ports_available_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_ports_available_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
number_of_ports, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_query_ports_available_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setPortDisableFutureHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setPortDisableFutureHandler: request length={LEN}", "LEN",
requestLen);
}
bitfield8_t portMask[PORT_MASK_DATA_SIZE];
auto rc = decode_set_port_disable_future_req(requestMsg, requestLen,
&portMask[0]);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_port_disable_future_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
// mock data to send
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_set_port_disable_future_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_set_port_disable_future_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_query_ports_available_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPortDisableFutureHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPortDisableFutureHandler: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_port_disable_future_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_port_disable_future_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
// mock data to send
uint8_t cc = NSM_SUCCESS;
uint16_t reason_code = ERR_NULL;
bitfield8_t mask[PORT_MASK_DATA_SIZE] = {
0xFF, 0xFF, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_port_disable_future_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_port_disable_future_resp(requestMsg->hdr.instance_id, cc,
reason_code, mask, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_port_disable_future_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPowerModeHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPowerModeHandler: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_power_mode_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_power_mode_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
// mock data to send
std::vector<uint8_t> data{0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01,
0x05, 0x00, 0x06, 0x00, 0x07, 0x00};
auto powerModeData =
reinterpret_cast<struct nsm_power_mode_data*>(data.data());
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_power_mode_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_power_mode_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, powerModeData, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_power_mode_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setPowerModeHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setPowerModeHandler: request length={LEN}", "LEN",
requestLen);
}
struct nsm_power_mode_data data;
auto rc = decode_set_power_mode_req(requestMsg, requestLen, &data);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_power_mode_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_set_power_mode_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_set_power_mode_resp(requestMsg->hdr.instance_id, reason_code,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_set_power_mode_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getSwitchIsolationMode(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getSwitchIsolationMode: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_switch_isolation_mode_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_switch_isolation_mode_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
uint8_t isolation_mode = 1;
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_switch_isolation_mode_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_switch_isolation_mode_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
isolation_mode, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_switch_isolation_mode_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setSwitchIsolationMode(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setSwitchIsolationMode: request length={LEN}", "LEN",
requestLen);
}
uint8_t isolationMode;
auto rc = decode_set_switch_isolation_mode_req(requestMsg, requestLen,
&isolationMode);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_switch_isolation_mode_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_set_switch_isolation_mode_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_set_switch_isolation_mode_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getInventoryInformationHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getInventoryInformationHandler: request length={LEN}", "LEN",
requestLen);
}
uint8_t propertyIdentifier = 0;
auto rc = decode_get_inventory_information_req(requestMsg, requestLen,
&propertyIdentifier);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_inventory_information_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
auto property = getProperty(propertyIdentifier);
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + NSM_RESPONSE_CONVENTION_LEN + property.size(), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_inventory_information_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, property.size(),
(uint8_t*)property.data(), responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_inventory_information_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryDeviceIdentificationHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("queryDeviceIdentificationHandler: request length={LEN}",
"LEN", requestLen);
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_query_device_identification_resp), 0);
uint8_t cc = NSM_SUCCESS;
uint16_t reason_code = ERR_NULL;
uint8_t mockupDeviceIdentification = mockDeviceType;
uint8_t mockupDeviceInstance = mockInstanceId;
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_query_device_identification_resp(
requestMsg->hdr.instance_id, cc, reason_code,
mockupDeviceIdentification, mockupDeviceInstance, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getTemperatureReadingHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request = reinterpret_cast<const nsm_get_temperature_reading_req*>(
requestMsg->payload);
uint8_t sensor_id{request->sensor_id};
if (verbose)
{
lg2::info(
"getTemperatureReadingHandler: Sensor_Id={ID}, request length={LEN}",
"LEN", requestLen, "ID", sensor_id);
}
if (sensor_id == 255)
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_aggregate_resp(
requestMsg->hdr.instance_id, request->hdr.command, NSM_SUCCESS, 2,
responseMsg);
uint8_t reading[4]{};
size_t consumed_len;
std::array<uint8_t, 50> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
// add sample 1
rc = encode_aggregate_temperature_reading_data(46.189, reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0, true, reading, 4, nsm_sample,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 2
rc = encode_aggregate_temperature_reading_data(-0.343878, reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(39, true, reading, 4, nsm_sample,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
return response;
}
else
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_temperature_reading_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
[[maybe_unused]] auto rc = encode_get_temperature_reading_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, 78,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
}
std::optional<std::vector<uint8_t>>
MockupResponder::readThermalParameterHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request = reinterpret_cast<const nsm_read_thermal_parameter_req*>(
requestMsg->payload);
if (requestLen <
sizeof(nsm_msg_hdr) + sizeof(nsm_read_thermal_parameter_req))
{
if (verbose)
{
lg2::info(
"readThermalParameterHandler: invalid command request length of {LEN}.",
"LEN", requestLen);
}
return std::nullopt;
}
uint8_t parameter_id{request->parameter_id};
if (verbose)
{
lg2::info(
"readThermalParameterHandler: Parameter_Id={ID}, request length={LEN}",
"LEN", requestLen, "ID", parameter_id);
}
if (parameter_id == 255)
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_aggregate_resp(
requestMsg->hdr.instance_id, request->hdr.command, NSM_SUCCESS, 2,
responseMsg);
uint8_t reading[4]{};
size_t consumed_len;
std::array<uint8_t, 50> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
// add sample 1
rc = encode_aggregate_thermal_parameter_data(110, reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0, true, reading, 4, nsm_sample,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 2
rc = encode_aggregate_thermal_parameter_data(-40, reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(39, true, reading, 4, nsm_sample,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
return response;
}
else
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(struct nsm_read_thermal_parameter_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
[[maybe_unused]] auto rc = encode_read_thermal_parameter_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, -10,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
}
std::optional<std::vector<uint8_t>>
MockupResponder::getCurrentPowerDrawHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request = reinterpret_cast<const nsm_get_current_power_draw_req*>(
requestMsg->payload);
uint8_t sensor_id{request->sensor_id};
if (verbose)
{
lg2::info(
"getCurrentPowerDrawHandler: Sensor_Id={ID}, request length={LEN}",
"LEN", requestLen, "ID", sensor_id);
}
if (sensor_id == 255)
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_aggregate_resp(
requestMsg->hdr.instance_id, request->hdr.command, NSM_SUCCESS, 3,
responseMsg);
const auto now = std::chrono::system_clock::now();
std::time_t newt = std::chrono::system_clock::to_time_t(now);
const auto timestamp = static_cast<uint64_t>(newt);
const uint32_t power[2]{25890, 17023};
uint8_t reading[8]{};
size_t consumed_len;
std::array<uint8_t, 50> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
// add sample 1
rc = encode_aggregate_timestamp_data(timestamp, reading, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0xFF, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 2
rc = encode_aggregate_get_current_power_draw_reading(power[0], reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 3
rc = encode_aggregate_get_current_power_draw_reading(power[1], reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(10, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
return response;
}
else
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_current_power_draw_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
uint32_t power{15870};
[[maybe_unused]] auto rc = encode_get_current_power_draw_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, power,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
}
std::optional<std::vector<uint8_t>>
MockupResponder::getMaxObservedPowerHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request = reinterpret_cast<const nsm_get_max_observed_power_req*>(
requestMsg->payload);
uint8_t sensor_id{request->sensor_id};
if (verbose)
{
lg2::info(
"getMaxObservedPowerHandler: Sensor_Id={ID}, request length={LEN}",
"LEN", requestLen, "ID", sensor_id);
}
if (sensor_id == 255)
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_aggregate_resp(
requestMsg->hdr.instance_id, request->hdr.command, NSM_SUCCESS, 3,
responseMsg);
const auto now = std::chrono::system_clock::now();
std::time_t newt = std::chrono::system_clock::to_time_t(now);
const auto timestamp = static_cast<uint64_t>(newt);
const uint32_t power[2]{701890, 682023};
uint8_t reading[8]{};
size_t consumed_len;
std::array<uint8_t, 50> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
// add sample 1
rc = encode_aggregate_timestamp_data(timestamp, reading, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0xFF, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 2
rc = encode_aggregate_get_current_power_draw_reading(power[0], reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 3
rc = encode_aggregate_get_current_power_draw_reading(power[1], reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(10, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
return response;
}
else
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_max_observed_power_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
uint32_t power{692870};
[[maybe_unused]] auto rc = encode_get_max_observed_power_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, power,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
}
std::optional<std::vector<uint8_t>>
MockupResponder::getDriverInfoHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getDriverInfoHandler: request length={LEN}", "LEN",
requestLen);
}
// Assuming decode_get_driver_info_req
auto rc = decode_get_driver_info_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_driver_info_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
// Prepare mock driver info data
std::string data = "MockDriverVersion 1.0.0";
std::vector<uint8_t> driver_info_data;
driver_info_data.resize(data.length() + 2); // +2 for state and null string
driver_info_data[0] = 2; // driver state
int index = 1;
for (char& c : data)
{
driver_info_data[index++] = static_cast<uint8_t>(c);
}
// Add null character at the end, position is data.length() + 1 due
// to starting at index 0
driver_info_data[data.length() + 1] = static_cast<uint8_t>('\0');
if (verbose)
{
lg2::info("Mock driver info - State: {STATE}, Version: {VERSION}",
"STATE", 2, "VERSION", data);
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) +
NSM_RESPONSE_CONVENTION_LEN +
driver_info_data.size(),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_driver_info_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, driver_info_data.size(),
(uint8_t*)driver_info_data.data(),
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_driver_info_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<Response>
MockupResponder::getMigModeHandler(const nsm_msg* requestMsg,
size_t requestLen, bool isLongRunning,
std::optional<Request>& longRunningEvent)
{
if (verbose)
{
lg2::info("getMigModeHandler: request length={LEN}", "LEN", requestLen);
}
auto rc = decode_common_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode request for getMigModeHandler failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
if (pmDisabled())
{
return unsupportedResponse(requestMsg->hdr.instance_id,
NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_MIG_MODE);
}
bitfield8_t flags;
flags.byte = state.migMode;
Response response(
isLongRunning
? /*common resp*/ (sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp))
: /* regular resp */ (sizeof(nsm_msg_hdr) +
sizeof(nsm_get_MIG_mode_resp)),
0);
if (isLongRunning)
{
auto commonMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_common_resp(requestMsg->hdr.instance_id, NSM_ACCEPTED,
ERR_NULL, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_MIG_MODE, commonMsg);
assert(rc == NSM_SW_SUCCESS);
longRunningEvent =
Response((sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_long_running_resp) + sizeof(bitfield8_t)),
0);
auto eventMsg = reinterpret_cast<nsm_msg*>(longRunningEvent->data());
auto eventRc = encode_get_MIG_mode_event_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, &flags,
eventMsg);
assert(eventRc == NSM_SW_SUCCESS);
}
else
{
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_MIG_mode_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
ERR_NULL, &flags, responseMsg);
}
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_MIG_mode_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<Response>
MockupResponder::setMigModeHandler(const nsm_msg* requestMsg,
size_t requestLen, bool isLongRunning,
std::optional<Request>& longRunningEvent)
{
auto rc = decode_set_MIG_mode_req(requestMsg, requestLen, &state.migMode);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_MIG_mode_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
if (pmDisabled())
{
return unsupportedResponse(requestMsg->hdr.instance_id,
NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_SET_MIG_MODE);
}
Response response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_set_MIG_mode_resp(requestMsg->hdr.instance_id,
isLongRunning ? NSM_ACCEPTED : NSM_SUCCESS,
ERR_NULL, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (isLongRunning)
{
longRunningEvent = Response((sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_long_running_resp)),
0);
auto eventMsg = reinterpret_cast<nsm_msg*>(longRunningEvent->data());
auto eventRc = encode_set_MIG_mode_event_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, eventMsg);
assert(eventRc == NSM_SW_SUCCESS);
}
return response;
}
std::optional<Response>
MockupResponder::getEccModeHandler(const nsm_msg* requestMsg,
size_t requestLen, bool isLongRunning,
std::optional<Request>& longRunningEvent)
{
auto rc = decode_common_req(requestMsg, requestLen);
if (rc)
{
lg2::error("decode request for getEccModeHandler failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
if (pmDisabled())
{
return unsupportedResponse(requestMsg->hdr.instance_id,
NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_ECC_MODE);
}
bitfield8_t flags;
flags.byte = state.eccMode;
Response response(
isLongRunning
? /*common resp*/ (sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp))
: /* regular resp */ (sizeof(nsm_msg_hdr) +
sizeof(nsm_get_ECC_mode_resp)),
0);
if (isLongRunning)
{
auto commonMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_common_resp(requestMsg->hdr.instance_id, NSM_ACCEPTED,
ERR_NULL, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_ECC_MODE, commonMsg);
assert(rc == NSM_SW_SUCCESS);
longRunningEvent =
Response((sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_long_running_resp) + sizeof(bitfield8_t)),
0);
auto eventMsg = reinterpret_cast<nsm_msg*>(longRunningEvent->data());
auto eventRc = encode_get_ECC_mode_event_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, &flags,
eventMsg);
assert(eventRc == NSM_SW_SUCCESS);
}
else
{
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_ECC_mode_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
ERR_NULL, &flags, responseMsg);
}
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_ECC_mode_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<Response>
MockupResponder::setEccModeHandler(const nsm_msg* requestMsg,
size_t requestLen, bool isLongRunning,
std::optional<Request>& longRunningEvent)
{
auto rc = decode_set_ECC_mode_req(requestMsg, requestLen, &state.eccMode);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_ECC_mode_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
if (pmDisabled())
{
return unsupportedResponse(requestMsg->hdr.instance_id,
NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_SET_ECC_MODE);
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_set_ECC_mode_resp(requestMsg->hdr.instance_id,
isLongRunning ? NSM_ACCEPTED : NSM_SUCCESS,
reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (isLongRunning)
{
longRunningEvent = Response((sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_long_running_resp)),
0);
auto eventMsg = reinterpret_cast<nsm_msg*>(longRunningEvent->data());
auto eventRc = encode_set_ECC_mode_event_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, eventMsg);
assert(eventRc == NSM_SW_SUCCESS);
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getEccErrorCountsHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto rc = decode_common_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error(
"decode requset for getEccErrorCountsHandler failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
struct nsm_ECC_error_counts errorCounts;
errorCounts.flags.byte = 132;
errorCounts.sram_corrected = 1234;
errorCounts.sram_uncorrected_secded = 4532;
errorCounts.sram_uncorrected_parity = 6567;
errorCounts.dram_corrected = 9876;
errorCounts.dram_uncorrected = 9654;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_ECC_error_counts_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_ECC_error_counts_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
&errorCounts, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_ECC_error_counts_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getEventSubscription(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getEventSubscription: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_nsm_get_event_subscription_req(requestMsg, requestLen);
if (rc != NSM_SUCCESS)
{
lg2::error("decode_nsm_get_event_subscription_req failed RC={RC}", "RC",
rc);
return std::nullopt;
}
Response response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_event_subscription_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_nsm_get_event_subscription_resp(
requestMsg->hdr.instance_id,
eventReceiverEid == 0 ? NSM_ERROR : NSM_SUCCESS, ERR_NULL,
eventReceiverEid, responseMsg);
assert(rc == NSM_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setEventSubscription(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setEventSubscription: request length={LEN}", "LEN",
requestLen);
}
uint8_t globalSetting = 0;
uint8_t receiverEid = 0;
auto rc = decode_nsm_set_event_subscription_req(
requestMsg, requestLen, &globalSetting, &receiverEid);
if (rc != NSM_SUCCESS)
{
lg2::error("decode_nsm_set_event_subscription_req failed RC={RC}", "RC",
rc);
}
globalEventGenerationSetting = globalSetting;
eventReceiverEid = receiverEid;
if (verbose)
{
lg2::info("setEventSubscription: setting={SETTING} ReceiverEID={EID}",
"SETTING", globalEventGenerationSetting, "EID",
eventReceiverEid);
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + NSM_RESPONSE_CONVENTION_LEN, 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_cc_only_resp(
requestMsg->hdr.instance_id, NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY,
NSM_SET_EVENT_SUBSCRIPTION, NSM_SUCCESS, ERR_NULL, responseMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("encode_cc_only_resp failed RC={RC}", "RC", rc);
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setCurrentEventSources(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setCurrentEventSources: request length={LEN}", "LEN",
requestLen);
}
uint8_t nvidiaMessageType = 0;
bitfield8_t* event_sources;
auto rc = decode_nsm_set_current_event_source_req(
requestMsg, requestLen, &nvidiaMessageType, &event_sources);
if (rc != NSM_SUCCESS)
{
lg2::error("decode_nsm_set_current_event_source_req failed RC={RC}",
"RC", rc);
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + NSM_RESPONSE_CONVENTION_LEN, 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_cc_only_resp(
requestMsg->hdr.instance_id, NSM_TYPE_DEVICE_CAPABILITY_DISCOVERY,
NSM_SET_CURRENT_EVENT_SOURCES, NSM_SUCCESS, ERR_NULL, responseMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("encode_cc_only_resp failed RC={RC}", "RC", rc);
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::configureEventAcknowledgement(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("configureEventAcknowledgement: request length={LEN}", "LEN",
requestLen);
}
uint8_t nvidiaMessageType = 0;
bitfield8_t* currentEventSourcesAcknowledgementMask;
auto rc = decode_nsm_configure_event_acknowledgement_req(
requestMsg, requestLen, &nvidiaMessageType,
&currentEventSourcesAcknowledgementMask);
if (rc != NSM_SUCCESS)
{
lg2::error(
"decode_nsm_configure_event_acknowledgement_req failed RC={RC}",
"RC", rc);
}
if (verbose)
{
lg2::info(
"receive configureEventAcknowledgement request, nvidiaMessageType={MSGTYPE} mask[0]={M0} mask[1]={M1}",
"MSGTYPE", nvidiaMessageType, "M0",
currentEventSourcesAcknowledgementMask[0].byte, "M1",
currentEventSourcesAcknowledgementMask[1].byte);
}
std::vector<bitfield8_t> newEventSourcesAcknowledgementMask(8);
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_configure_event_acknowledgement_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_nsm_configure_event_acknowledgement_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS,
newEventSourcesAcknowledgementMask.data(), responseMsg);
assert(rc == NSM_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPowerSmoothingFeatureInfo(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPowerSmoothingFeatureInfo: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_powersmoothing_featinfo_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_powersmoothing_featinfo_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
struct nsm_pwr_smoothing_featureinfo_data feat;
feat.feature_flag = 7;
feat.currentTmpSetting = 100000;
feat.currentTmpFloorSetting = 200000;
feat.maxTmpFloorSettingInPercent = doubleToNvUFXP4_12(0.95);
feat.minTmpFloorSettingInPercent = doubleToNvUFXP4_12(0.2);
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_power_smoothing_feat_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_powersmoothing_featinfo_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
&feat, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_powersmoothing_featinfo_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getHwCircuiteryUsage(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getHwCircuiteryUsage: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_hardware_lifetime_cricuitry_req(requestMsg,
requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_hardware_lifetime_cricuitry_req: rc={RC}", "RC",
rc);
return std::nullopt;
}
struct nsm_hardwarecircuitry_data lifetimeusage;
lifetimeusage.reading = doubleToNvUFXP8_24(40.45);
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_hardwareciruitry_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("getHwCircuiteryUsage: instanceId={INSTANCEID}", "INSTANCEID",
requestMsg->hdr.instance_id);
rc = encode_get_hardware_lifetime_cricuitry_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, &lifetimeusage,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_query_admin_override_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getCurrentProfileInfo(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getCurrentProfileInfo: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_current_profile_info_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_current_profile_info_req: rc={RC}", "RC", rc);
return std::nullopt;
}
struct nsm_get_current_profile_data profileData;
profileData.current_active_profile_id = 2;
profileData.admin_override_mask.bits.tmp_floor_override = 1;
profileData.admin_override_mask.bits.rampup_rate_override = 1;
profileData.admin_override_mask.bits.rampdown_rate_override = 0;
profileData.admin_override_mask.bits.hysteresis_value_override = 0;
profileData.current_percent_tmp_floor = doubleToNvUFXP4_12(0.3);
profileData.current_rampup_rate_in_miliwatts_per_second = 180;
profileData.current_rampdown_rate_in_miliwatts_per_second = 200;
profileData.current_rampdown_hysteresis_value_in_milisec = 150;
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_current_profile_info_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("getCurrentProfileInfo: instanceId={INSTANCEID}", "INSTANCEID",
requestMsg->hdr.instance_id);
rc = encode_get_current_profile_info_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
&profileData, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_current_profile_info_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getQueryAdminOverride(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getQueryAdminOverride: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_query_admin_override_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_query_admin_override_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
nsm_admin_override_data adminProfileData = {};
adminProfileData.admin_override_percent_tmp_floor = 0;
adminProfileData.admin_override_ramup_rate_in_miliwatts_per_second = 180;
adminProfileData.admin_override_rampdown_rate_in_miliwatts_per_second = 150;
adminProfileData.admin_override_rampdown_hysteresis_value_in_milisec = 200;
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_query_admin_override_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("getQueryAdminOverride: instanceId={INSTANCEID}", "INSTANCEID",
requestMsg->hdr.instance_id);
rc = encode_query_admin_override_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
&adminProfileData, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_query_admin_override_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setActivePresetProfile(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t profile_id;
auto rc = decode_set_active_preset_profile_req(requestMsg, requestLen,
&profile_id);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_active_preset_profile_req: rc={RC}", "RC", rc);
return std::nullopt;
}
if (verbose)
{
lg2::info(
"setActivePresetProfile: profile_id={PROFILE_ID}, request length={LEN}",
"LEN", requestLen, "PROFILE_ID", profile_id);
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("setActivePresetProfile: instanceId={INSTANCEID}", "INSTANCEID",
requestMsg->hdr.instance_id);
rc = encode_set_active_preset_profile_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_set_active_preset_profile_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setupAdminOverride(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t parameter_id;
uint32_t param_value;
auto rc = decode_setup_admin_override_req(requestMsg, requestLen,
&parameter_id, &param_value);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_setup_admin_override_req: rc={RC}", "RC", rc);
return std::nullopt;
}
if (verbose)
{
lg2::info("setupAdminOverride: request length={LEN}", "LEN",
requestLen);
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
if (parameter_id == 0)
{
uint16_t val = param_value >> 16;
lg2::error(
"setupAdminOverride: instanceId={INSTANCEID}, parameterId={PARAMETERID}, parameterValue={PARAMETERVALUE}",
"INSTANCEID", requestMsg->hdr.instance_id, "PARAMETERID",
parameter_id, "PARAMETERVALUE", val);
}
else
{
lg2::error(
"setupAdminOverride: instanceId={INSTANCEID}, parameterId={PARAMETERID}, parameterValue={PARAMETERVALUE}",
"INSTANCEID", requestMsg->hdr.instance_id, "PARAMETERID",
parameter_id, "PARAMETERVALUE", param_value);
}
rc = encode_setup_admin_override_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_apply_admin_override_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::applyAdminOverride(const nsm_msg* requestMsg,
size_t requestLen)
{
auto rc = decode_apply_admin_override_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_apply_admin_override_req: rc={RC}", "RC", rc);
return std::nullopt;
}
if (verbose)
{
lg2::info("applyAdminOverride: request length={LEN}", "LEN",
requestLen);
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("applyAdminOverride: instanceId={INSTANCEID}", "INSTANCEID",
requestMsg->hdr.instance_id);
rc = encode_apply_admin_override_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_apply_admin_override_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::toggleImmediateRampDown(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t ramp_down_toggle;
auto rc = decode_toggle_immediate_rampdown_req(requestMsg, requestLen,
&ramp_down_toggle);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_toggle_immediate_rampdown_req: rc={RC}", "RC", rc);
return std::nullopt;
}
if (verbose)
{
lg2::info("toggleImmediateRampDown: request length={LEN}", "LEN",
requestLen);
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error(
"toggleImmediateRampDown: instanceId={INSTANCEID}, ramp_down_toggle={RAMPDOWNTOGGLE}",
"INSTANCEID", requestMsg->hdr.instance_id, "RAMPDOWNTOGGLE",
ramp_down_toggle);
rc = encode_toggle_immediate_rampdown_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_toggle_immediate_rampdown_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::toggleFeatureState(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t feature_state;
auto rc = decode_toggle_feature_state_req(requestMsg, requestLen,
&feature_state);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_toggle_feature_state_req: rc={RC}", "RC", rc);
return std::nullopt;
}
lg2::error(
"toggleFeatureState: feature_state={FEATURE_STATE}, request length={LEN}",
"LEN", requestLen, "FEATURE_STATE", feature_state);
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("toggleFeatureState: instanceId={INSTANCEID}", "INSTANCEID",
requestMsg->hdr.instance_id);
rc = encode_toggle_feature_state_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_toggle_feature_state_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPresetProfileInfo(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPresetProfileInfo: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_preset_profile_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_preset_profile_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
const int supported_number_of_profile = 4;
struct nsm_get_all_preset_profile_meta_data profile_meta_data;
profile_meta_data.max_profiles_supported = supported_number_of_profile;
struct nsm_preset_profile_data profiles[supported_number_of_profile];
for (int i = 0; i < supported_number_of_profile; i++)
{
profiles[i].tmp_floor_setting_in_percent =
doubleToNvUFXP4_12(0.1 * (i + 1));
profiles[i].ramp_up_rate_in_miliwattspersec = 20 * (i + 1);
profiles[i].ramp_down_rate_in_miliwattspersec = 30 * (i + 1);
profiles[i].ramp_hysterisis_rate_in_milisec = 40 * (i + 1);
}
uint16_t meta_data_size =
sizeof(struct nsm_get_all_preset_profile_meta_data);
uint16_t profile_data_size = sizeof(struct nsm_preset_profile_data);
// data size is sum of metadata + number of profiles * size of one
// profile
uint16_t data_size = meta_data_size +
supported_number_of_profile * profile_data_size;
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(struct nsm_common_resp) + data_size, 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_preset_profile_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
&profile_meta_data, profiles, profile_meta_data.max_profiles_supported,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_preset_profile_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::updatePresetProfileParams(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("updatePresetProfileParams: request length={LEN}", "LEN",
requestLen);
}
size_t s = sizeof(struct nsm_msg_hdr) +
sizeof(struct nsm_update_preset_profile_req);
if (verbose)
{
lg2::info("updatePresetProfileParams: request length={LEN}", "LEN", s);
}
uint8_t profile_id;
uint8_t parameter_id;
uint32_t param_value;
auto rc = decode_update_preset_profile_param_req(
requestMsg, requestLen, &profile_id, &parameter_id, &param_value);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_update_preset_profile_param_req: rc={RC}", "RC", rc);
return std::nullopt;
}
if (verbose)
{
lg2::info("updatePresetProfileParams: request length={LEN}", "LEN",
requestLen);
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
if (parameter_id == 0)
{
uint16_t val = param_value >> 16;
lg2::error(
"updatePresetProfileParams: instanceId={INSTANCEID}, profileId={PROFILEID}, parameterId={PARAMETERID}, parameterValue={PARAMETERVALUE}",
"INSTANCEID", requestMsg->hdr.instance_id, "PROFILEID", profile_id,
"PARAMETERID", parameter_id, "PARAMETERVALUE", val);
}
else
{
lg2::error(
"updatePresetProfileParams: instanceId={INSTANCEID}, profileId={PROFILEID}, parameterId={PARAMETERID}, parameterValue={PARAMETERVALUE}",
"INSTANCEID", requestMsg->hdr.instance_id, "PROFILEID", profile_id,
"PARAMETERID", parameter_id, "PARAMETERVALUE", param_value);
}
rc = encode_update_preset_profile_param_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_update_preset_profile_param_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::enableWorkloadPowerProfile(const nsm_msg* requestMsg,
size_t requestLen)
{
bitfield256_t profile_mask;
auto rc = decode_enable_workload_power_profile_req(requestMsg, requestLen,
&profile_mask);
if (verbose)
{
lg2::info("enableWorkloadPowerProfile: request length={LEN}", "LEN",
requestLen);
}
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_enable_workload_power_profile_req: rc={RC}", "RC",
rc);
return std::nullopt;
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("enableWorkloadPowerProfile: instanceId={INSTANCEID}",
"INSTANCEID", requestMsg->hdr.instance_id);
for (int i = 0; i < 8; i++)
{
lg2::error("ProfileMask = {MASK}", "MASK", lg2::hex,
profile_mask.fields[i].byte);
}
rc = encode_enable_workload_power_profile_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_enable_workload_power_profile_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::disableWorkloadPowerProfile(const nsm_msg* requestMsg,
size_t requestLen)
{
bitfield256_t profile_mask;
auto rc = decode_disable_workload_power_profile_req(requestMsg, requestLen,
&profile_mask);
if (verbose)
{
lg2::info("disableWorkloadPowerProfile: request length={LEN}", "LEN",
requestLen);
}
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_disable_workload_power_profile_req: rc={RC}", "RC",
rc);
return std::nullopt;
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("disableWorkloadPowerProfile: instanceId={INSTANCEID}",
"INSTANCEID", requestMsg->hdr.instance_id);
for (int i = 0; i < 8; i++)
{
lg2::error("ProfileMask = {MASK}", "MASK", lg2::hex,
profile_mask.fields[i].byte);
}
rc = encode_disable_workload_power_profile_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_enable_workload_power_profile_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getWorkLoadProfileStatusInfo(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getWorkLoadProfileStatusInfo: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_workload_power_profile_status_req(requestMsg,
requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_current_profile_info_req: rc={RC}", "RC", rc);
return std::nullopt;
}
struct workload_power_profile_status profileData;
for (int i = 0; i < 8; i++)
{
profileData.supported_profile_mask.fields[i].byte = 0x0000000a;
profileData.requested_profile_maks.fields[i].byte = 0x0000000b;
profileData.enforced_profile_mask.fields[i].byte = 0x0000000c;
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_workload_power_profile_status_info_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
lg2::error("getWorkLoadProfileStatusInfo: instanceId={INSTANCEID}",
"INSTANCEID", requestMsg->hdr.instance_id);
rc = encode_get_workload_power_profile_status_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, &profileData,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_get_workload_power_profile_status_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getWorkloadPowerProfileInfo(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getWorkloadPowerProfileInfo: request length={LEN}", "LEN",
requestLen);
}
uint16_t identifier;
uint16_t LAST_PAGE_ID = 3;
auto rc = decode_get_workload_power_profile_info_req(requestMsg, requestLen,
&identifier);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_workload_power_profile_info_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
const int supported_number_of_profile_per_page = 5;
if (verbose)
{
lg2::info("getWorkloadPowerProfileInfo: identifier in req = {ID}", "ID",
identifier);
}
struct nsm_all_workload_power_profile_meta_data profile_meta_data;
profile_meta_data.number_of_profiles = supported_number_of_profile_per_page;
if (identifier == LAST_PAGE_ID)
{
profile_meta_data.next_identifier =
0; // last page will have next_identifier as 0
}
else
{
profile_meta_data.next_identifier = identifier + 1;
}
struct nsm_workload_power_profile_data
profiles[supported_number_of_profile_per_page];
int startIdentifier = identifier * supported_number_of_profile_per_page;
int endIdentifier = (identifier + 1) * supported_number_of_profile_per_page;
for (int i = startIdentifier; i < endIdentifier; i++)
{
profiles[i - startIdentifier].profile_id = i;
profiles[i - startIdentifier].priority = i + 1;
for (int nthbyte = 0; nthbyte < 8; nthbyte++)
{
profiles[i - startIdentifier].conflict_mask.fields[nthbyte].byte =
0x0000000a;
}
}
uint16_t meta_data_size =
sizeof(struct nsm_all_workload_power_profile_meta_data);
uint16_t profile_data_size = sizeof(struct nsm_workload_power_profile_data);
// data size is sum of metadata + number of profiles * size of one profile
uint16_t data_size = meta_data_size + supported_number_of_profile_per_page *
profile_data_size;
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(struct nsm_common_resp) + data_size, 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_workload_power_profile_info_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
&profile_meta_data, profiles, profile_meta_data.number_of_profiles,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_get_workload_power_profile_info_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
template <class T>
void Logger(bool verbose, const char* msg, const T& data)
{
if (verbose)
{
std::stringstream s;
s << data;
std::cout << msg << s.str() << std::endl;
}
}
int MockupResponder::mctpSockSend(uint8_t destEid,
std::vector<uint8_t>& requestMsg)
{
if (sockFd < 0)
{
lg2::error("mctpSockSend failed, invalid sockFd");
return NSM_ERROR;
}
msghdr msg{};
iovec iov[2]{};
uint8_t prefix[3];
prefix[0] = MCTP_MSG_TAG_REQ;
prefix[1] = destEid;
prefix[2] = MCTP_MSG_TYPE_VDM;
iov[0].iov_base = &prefix[0];
iov[0].iov_len = sizeof(prefix);
iov[1].iov_base = requestMsg.data();
iov[1].iov_len = requestMsg.size();
msg.msg_iov = iov;
msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
if (verbose)
{
utils::printBuffer(utils::Tx, requestMsg, prefix[0], prefix[1]);
}
auto rc = sendmsg(sockFd, &msg, 0);
if (rc < 0)
{
lg2::error("sendmsg system call failed rc={RC}", "RC", rc);
return NSM_ERROR;
}
return NSM_SUCCESS;
}
void MockupResponder::sendRediscoveryEvent(uint8_t dest, bool ackr)
{
if (verbose)
{
lg2::info("sendRediscoveryEvent dest eid={EID}", "EID", dest);
}
uint8_t instanceId = 23;
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN);
auto msg = reinterpret_cast<nsm_msg*>(eventMsg.data());
auto rc = encode_nsm_rediscovery_event(instanceId, ackr, msg);
if (rc != NSM_SUCCESS)
{
lg2::error("sendRediscoveryEvent failed");
}
rc = mctpSockSend(dest, eventMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("mctpSockSend() failed, rc={RC}", "RC", rc);
}
}
void MockupResponder::sendXIDEvent(uint8_t dest, bool ackr, uint8_t flag,
uint32_t reason, uint32_t sequence_number,
uint64_t timestamp, std::string message_text)
{
if (verbose)
{
lg2::info("sendXIDEvent dest eid={EID}", "EID", dest);
}
uint8_t instanceId = 23;
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_xid_event_payload) +
message_text.size());
auto msg = reinterpret_cast<nsm_msg*>(eventMsg.data());
const nsm_xid_event_payload payload{.flag = flag,
.reserved = {},
.reason = reason,
.sequence_number = sequence_number,
.timestamp = timestamp};
auto rc = encode_nsm_xid_event(instanceId, ackr, payload,
message_text.data(), message_text.size(),
msg);
if (rc != NSM_SUCCESS)
{
lg2::error("sendXIDEvent failed");
}
rc = mctpSockSend(dest, eventMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("mctpSockSend() failed, rc={RC}", "RC", rc);
}
}
void MockupResponder::sendResetRequiredEvent(uint8_t dest, bool ackr)
{
if (verbose)
{
lg2::info("sendResetRequiredEvent dest eid={EID}", "EID", dest);
}
uint8_t instanceId = 23;
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN);
auto msg = reinterpret_cast<nsm_msg*>(eventMsg.data());
auto rc = encode_nsm_reset_required_event(instanceId, ackr, msg);
if (rc != NSM_SUCCESS)
{
lg2::error("sendResetRequiredEvent failed");
}
rc = mctpSockSend(dest, eventMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("mctpSockSend() failed, rc={RC}", "RC", rc);
}
}
void MockupResponder::sendFabricManagerStateEvent(
uint8_t dest, bool ackr, uint8_t state, uint8_t status,
uint64_t last_restart_time, uint64_t last_restart_duration)
{
if (verbose)
{
lg2::info("sendFabricManagerStateEvent dest eid={EID}", "EID", dest);
}
uint8_t instanceId = 25;
std::vector<uint8_t> eventMsg(
sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_get_fabric_manager_state_event_payload));
auto msg = reinterpret_cast<nsm_msg*>(eventMsg.data());
const nsm_get_fabric_manager_state_event_payload payload{
.fm_state = state,
.report_status = status,
.last_restart_timestamp = last_restart_time,
.duration_since_last_restart_sec = last_restart_duration};
auto rc = encode_nsm_get_fabric_manager_state_event(instanceId, ackr,
payload, msg);
if (rc != NSM_SUCCESS)
{
lg2::error("sendFabricManagerStateEvent failed");
}
rc = mctpSockSend(dest, eventMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("mctpSockSend() failed, rc={RC}", "RC", rc);
}
}
void MockupResponder::sendNsmEvent(uint8_t dest, uint8_t nsmType, bool ackr,
uint8_t ver, uint8_t eventId,
uint8_t eventClass, uint16_t eventState,
uint8_t dataSize, uint8_t* data)
{
if (verbose)
{
lg2::info("sendNsmEvent dest eid={EID}", "EID", dest);
}
uint8_t instanceId = 23;
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
dataSize);
auto msg = reinterpret_cast<nsm_msg*>(eventMsg.data());
auto rc = encode_nsm_event(instanceId, nsmType, ackr, ver, eventId,
eventClass, eventState, dataSize, data, msg);
if (rc != NSM_SUCCESS)
{
lg2::error("sendNsmEvent failed");
}
rc = mctpSockSend(dest, eventMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("mctpSockSend() failed, rc={RC}", "RC", rc);
}
}
void MockupResponder::sendThreasholdEvent(
uint8_t dest, bool ackr, bool port_rcv_errors_threshold,
bool port_xmit_discard_threshold, bool symbol_ber_threshold,
bool port_rcv_remote_physical_errors_threshold,
bool port_rcv_switch_relay_errors_threshold, bool effective_ber_threshold,
bool estimated_effective_ber_threshold, uint8_t portNumber)
{
const nsm_health_event_payload payload = {
.portNumber = portNumber,
.reserved1 = 0,
.port_rcv_errors_threshold = port_rcv_errors_threshold,
.port_xmit_discard_threshold = port_xmit_discard_threshold,
.symbol_ber_threshold = symbol_ber_threshold,
.port_rcv_remote_physical_errors_threshold =
port_rcv_remote_physical_errors_threshold,
.port_rcv_switch_relay_errors_threshold =
port_rcv_switch_relay_errors_threshold,
.effective_ber_threshold = effective_ber_threshold,
.estimated_effective_ber_threshold = estimated_effective_ber_threshold,
.reserved2 = 0};
if (verbose)
{
lg2::info("sendThreasholdEvent dest eid={EID}", "EID", dest);
}
std::vector<uint8_t> eventMsg(sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_health_event_payload));
auto msg = reinterpret_cast<nsm_msg*>(eventMsg.data());
auto rc = encode_nsm_health_event(mockInstanceId, ackr, &payload, msg);
if (rc != NSM_SUCCESS)
{
lg2::error("sendThreasholdEvent failed");
}
rc = mctpSockSend(dest, eventMsg);
if (rc != NSM_SUCCESS)
{
lg2::error("mctpSockSend() failed, rc={RC}", "RC", rc);
}
}
std::optional<std::vector<uint8_t>>
MockupResponder::getCurrentEnergyCountHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request = reinterpret_cast<const nsm_get_current_energy_count_req*>(
requestMsg->payload);
uint8_t sensor_id{request->sensor_id};
if (verbose)
{
lg2::info(
"getCurrentEnergyCountHandler: Sensor_Id={ID}, request length={LEN}",
"LEN", requestLen, "ID", sensor_id);
}
if (sensor_id == 255)
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_aggregate_resp(
requestMsg->hdr.instance_id, request->hdr.command, NSM_SUCCESS, 2,
responseMsg);
const uint64_t energy[2]{25890, 17023};
uint8_t reading[8]{};
size_t consumed_len{};
std::array<uint8_t, 50> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
// add sample 1
rc = encode_aggregate_energy_count_data(energy[0], reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 2
rc = encode_aggregate_energy_count_data(energy[1], reading,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(45, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
return response;
}
else
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_current_energy_count_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
uint32_t energy{15870};
[[maybe_unused]] auto rc = encode_get_current_energy_count_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, energy,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
}
std::optional<std::vector<uint8_t>>
MockupResponder::getVoltageHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request =
reinterpret_cast<const nsm_get_voltage_req*>(requestMsg->payload);
uint8_t sensor_id{request->sensor_id};
if (verbose)
{
lg2::info("getVoltageHandler: Sensor_Id={ID}, request length={LEN}",
"LEN", requestLen, "ID", sensor_id);
}
if (sensor_id == 255)
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
[[maybe_unused]] auto rc = encode_aggregate_resp(
requestMsg->hdr.instance_id, request->hdr.command, NSM_SUCCESS, 2,
responseMsg);
const uint32_t voltage[2]{32438470, 57978897};
uint8_t reading[8]{};
size_t consumed_len{};
std::array<uint8_t, 50> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
// add sample 1
rc = encode_aggregate_voltage_data(voltage[0], reading, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(0, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
// add sample 2
rc = encode_aggregate_voltage_data(voltage[1], reading, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(33, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
return response;
}
else
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_voltage_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
uint32_t voltage{25347808};
[[maybe_unused]] auto rc =
encode_get_voltage_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, voltage, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
}
std::optional<std::vector<uint8_t>>
MockupResponder::getAltitudePressureHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getAltitudePressureHandler: request length={LEN}", "LEN",
requestLen);
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_altitude_pressure_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
uint32_t pressure{943730};
auto rc = encode_get_altitude_pressure_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
pressure, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
void getScalarTelemetryGroup0Data(
struct nsm_query_scalar_group_telemetry_group_0* data)
{
data->pci_vendor_id = 1234;
data->pci_device_id = 4321;
data->pci_subsystem_vendor_id = 3;
data->pci_subsystem_device_id = 3;
}
void getScalarTelemetryGroup1Data(
struct nsm_query_scalar_group_telemetry_group_1* data)
{
data->negotiated_link_speed = 3;
data->negotiated_link_width = 3;
data->target_link_speed = 3;
data->max_link_speed = 4;
data->max_link_width = 5;
}
void getScalarTelemetryGroup2Data(
struct nsm_query_scalar_group_telemetry_group_2* data)
{
data->non_fatal_errors = 1111;
data->fatal_errors = 2222;
data->unsupported_request_count = 3333;
data->correctable_errors = 4444;
}
void getScalarTelemetryGroup3Data(
struct nsm_query_scalar_group_telemetry_group_3* data)
{
data->L0ToRecoveryCount = 8769;
}
void getScalarTelemetryGroup4Data(
struct nsm_query_scalar_group_telemetry_group_4* data)
{
data->recv_err_cnt = 100;
data->NAK_recv_cnt = 200;
data->NAK_sent_cnt = 300;
data->bad_TLP_cnt = 400;
data->replay_rollover_cnt = 500;
data->FC_timeout_err_cnt = 600;
data->replay_cnt = 700;
}
void getScalarTelemetryGroup5Data(
struct nsm_query_scalar_group_telemetry_group_5* data)
{
data->PCIeTXDwords = 8769000;
data->PCIeRXDwords = 876654;
}
void getScalarTelemetryGroup6Data(
struct nsm_query_scalar_group_telemetry_group_6* data)
{
data->ltssm_state = 0x11;
data->invalid_flit_counter = 111;
}
void getScalarTelemetryGroup8Data(
struct nsm_query_scalar_group_telemetry_group_8* data)
{
for (int idx = 1; idx <= TOTAL_PCIE_LANE_COUNT; idx++)
{
data->error_counts[idx - 1] = 200 * idx;
}
}
void getScalarTelemetryGroup9Data(
struct nsm_query_scalar_group_telemetry_group_9* data)
{
data->aer_uncorrectable_error_status = 500;
data->aer_correctable_error_status = 590;
}
void getScalarTelemetryGroup10Data(
nsm_query_scalar_group_telemetry_group_10* data)
{
data->outbound_read_tlp_count = 100100;
data->dwords_transferred_in_outbound_read_tlp_high = 2;
data->dwords_transferred_in_outbound_read_tlp_low = 200200;
data->outbound_write_tlp_count = 300300;
data->dwords_transferred_in_outbound_write_tlp_high = 4;
data->dwords_transferred_in_outbound_write_tlp_low = 400400;
data->outbound_completion_tlp_count = 500500;
data->dwords_transferred_in_outbound_completion = 600600;
data->read_requests_dropped_tag_unavailable = 700700;
data->read_requests_dropped_credit_exhaustion = 800800;
data->read_requests_dropped_credit_not_posted = 900900;
}
std::optional<Response> MockupResponder::getQueryScalarGroupTelemetryResponse(
uint8_t requestInstanceId, uint32_t groupId)
{
#define encode_query_scalar_group_telemetry_v1_group_resp(GROUP_ID) \
{ \
Response response( \
sizeof(nsm_msg_hdr) + \
sizeof( \
nsm_query_scalar_group_telemetry_v1_group_##GROUP_ID##_resp), \
0); \
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data()); \
nsm_query_scalar_group_telemetry_group_##GROUP_ID data; \
getScalarTelemetryGroup##GROUP_ID##Data(&data); \
auto rc = \
encode_query_scalar_group_telemetry_v1_group##GROUP_ID##_resp( \
requestInstanceId, NSM_SUCCESS, ERR_NULL, &data, responseMsg); \
if (rc != NSM_SW_SUCCESS) \
{ \
lg2::error( \
"encode_query_scalar_group_telemetry_v1_group{GROUPID}_resp failed: rc={RC}", \
"GROUPID", GROUP_ID, "RC", rc); \
return std::nullopt; \
} \
return response; \
}
switch (groupId)
{
case GROUP_ID_0:
encode_query_scalar_group_telemetry_v1_group_resp(0);
case GROUP_ID_1:
encode_query_scalar_group_telemetry_v1_group_resp(1);
case GROUP_ID_2:
encode_query_scalar_group_telemetry_v1_group_resp(2);
case GROUP_ID_3:
encode_query_scalar_group_telemetry_v1_group_resp(3);
case GROUP_ID_4:
encode_query_scalar_group_telemetry_v1_group_resp(4);
case GROUP_ID_5:
encode_query_scalar_group_telemetry_v1_group_resp(5);
case GROUP_ID_6:
encode_query_scalar_group_telemetry_v1_group_resp(6);
case GROUP_ID_8:
encode_query_scalar_group_telemetry_v1_group_resp(8);
case GROUP_ID_9:
encode_query_scalar_group_telemetry_v1_group_resp(9);
case GROUP_ID_10:
encode_query_scalar_group_telemetry_v1_group_resp(10);
default:
break;
}
return std::nullopt;
}
std::optional<Response>
MockupResponder::queryScalarGroupTelemetryHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t deviceId;
uint8_t groupIndex;
auto rc = decode_query_scalar_group_telemetry_v1_req(
requestMsg, requestLen, &deviceId, &groupIndex);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_query_scalar_group_telemetry_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
else if (verbose)
{
lg2::info(
"queryScalarGroupTelemetryHandler: deviceId={DEVICEID}, groupIndex={GROUPINDEX}",
"DEVICEID", deviceId, "GROUPINDEX", groupIndex);
}
return getQueryScalarGroupTelemetryResponse(requestMsg->hdr.instance_id,
groupIndex);
}
std::optional<Response>
MockupResponder::queryMultiportScalarGroupTelemetryHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
nsm_multiport_query_scalar_group_telemetry_v2_req_data data;
auto rc = decode_multiport_query_scalar_group_telemetry_v1_req(
requestMsg, requestLen, &data);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"decode_multiport_query_scalar_group_telemetry_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
else if (verbose)
{
lg2::info(
"queryMultiportScalarGroupTelemetryHandler: groupIndex={GROUPINDEX}, type={TYPE}, upstreamPortIndex={UPSTREAMPORTINDEX}, index={INDEX}",
"GROUPINDEX", int(data.group_index), "TYPE", int(data.type),
"UPSTREAMPORTINDEX", int(data.upstream_port_index), "INDEX",
int(data.index));
}
auto response = getQueryScalarGroupTelemetryResponse(
requestMsg->hdr.instance_id, data.group_index);
if (response)
{
auto responseMsg = reinterpret_cast<nsm_msg*>(response->data());
// Encoded responses functions in
// `MockupResponder::getQueryScalarGroupTelemetryResponse` uses
// hardcoded command value `NSM_QUERY_SCALAR_GROUP_TELEMETRY_V1` We need
// to set the command to `NSM_MULTIPORT_QUERY_SCALAR_GROUP_TELEMETRY_V2`
// for multiport query unit test coverage
auto resp = reinterpret_cast<nsm_query_scalar_group_telemetry_v1_resp*>(
responseMsg->payload);
resp->hdr.command = NSM_MULTIPORT_QUERY_SCALAR_GROUP_TELEMETRY_V2;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryAvailableAndClearableScalarGroupHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
uint8_t device_index;
uint8_t group_id;
auto rc = decode_query_available_clearable_scalar_data_sources_v1_req(
requestMsg, requestLen, &device_index, &group_id);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"decode_query_available_clearable_scalar_data_sources_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
uint16_t reason_code = ERR_NULL;
switch (group_id)
{
case GROUP_ID_2:
{
uint8_t mask_length = 1;
bitfield8_t available_source[1];
bitfield8_t clearable_source[1];
available_source[0].byte = 5;
clearable_source[0].byte = 63;
uint16_t data_size = 3;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(
nsm_query_available_clearable_scalar_data_sources_v1_resp) +
2 * mask_length * sizeof(uint8_t),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_available_clearable_scalar_data_sources_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
data_size, mask_length, (uint8_t*)available_source,
(uint8_t*)clearable_source, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_query_available_clearable_scalar_data_sources_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GROUP_ID_3:
{
uint8_t mask_length = 1;
bitfield8_t available_source[1];
bitfield8_t clearable_source[1];
available_source[0].byte = 15;
clearable_source[0].byte = 63;
uint16_t data_size = 3;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(
nsm_query_available_clearable_scalar_data_sources_v1_resp) +
2 * mask_length * sizeof(uint8_t),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_available_clearable_scalar_data_sources_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
data_size, mask_length, (uint8_t*)available_source,
(uint8_t*)clearable_source, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_query_available_clearable_scalar_data_sources_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GROUP_ID_4:
{
uint8_t mask_length = 1;
bitfield8_t available_source[1];
bitfield8_t clearable_source[1];
available_source[0].byte = 32;
clearable_source[0].byte = 63;
uint16_t data_size = 3;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(
nsm_query_available_clearable_scalar_data_sources_v1_resp) +
2 * mask_length * sizeof(uint8_t),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_available_clearable_scalar_data_sources_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
data_size, mask_length, (uint8_t*)available_source,
(uint8_t*)clearable_source, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_query_available_clearable_scalar_data_sources_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GROUP_ID_8:
{
uint8_t mask_length = 1;
bitfield8_t available_source[1];
bitfield8_t clearable_source[1];
available_source[0].byte = 9;
clearable_source[0].byte = 63;
uint16_t data_size = 3;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(
nsm_query_available_clearable_scalar_data_sources_v1_resp) +
2 * mask_length * sizeof(uint8_t),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_available_clearable_scalar_data_sources_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
data_size, mask_length, (uint8_t*)available_source,
(uint8_t*)clearable_source, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_query_available_clearable_scalar_data_sources_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GROUP_ID_9:
{
uint8_t mask_length = 1;
bitfield8_t available_source[1];
bitfield8_t clearable_source[1];
available_source[0].byte = 21;
clearable_source[0].byte = 63;
uint16_t data_size = 3;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(
nsm_query_available_clearable_scalar_data_sources_v1_resp) +
2 * mask_length * sizeof(uint8_t),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_query_available_clearable_scalar_data_sources_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
data_size, mask_length, (uint8_t*)available_source,
(uint8_t*)clearable_source, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_query_available_clearable_scalar_data_sources_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
default:
break;
}
return std::nullopt;
}
std::optional<std::vector<uint8_t>>
MockupResponder::pcieFundamentalResetHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t device_index;
uint8_t action;
auto rc = decode_assert_pcie_fundamental_reset_req(requestMsg, requestLen,
&device_index, &action);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_assert_pcie_fundamental_reset_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_assert_pcie_fundamental_reset_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_assert_pcie_fundamental_reset_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::clearScalarDataSourceHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t device_index;
uint8_t groupId;
uint8_t dsId;
auto rc = decode_clear_data_source_v1_req(requestMsg, requestLen,
&device_index, &groupId, &dsId);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_clear_data_source_v1_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_clear_data_source_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_clear_data_source_v1_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getEDPpScalingFactorHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
[[maybe_unused]] auto rc = decode_common_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"decode request for getEDPpScalingFactorHandler failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
struct nsm_EDPp_scaling_factors scaling_factors;
scaling_factors.persistent_scaling_factor = 70;
scaling_factors.oneshot_scaling_factor = 90;
scaling_factors.enforced_scaling_factor = 60;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_programmable_EDPp_scaling_factor_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_programmable_EDPp_scaling_factor_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, &scaling_factors,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_get_programmable_EDPp_scaling_factor_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setEDPpScalingFactorHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t action;
uint8_t persistence;
uint8_t scaling_factor;
auto rc = decode_set_programmable_EDPp_scaling_factor_req(
requestMsg, requestLen, &action, &persistence, &scaling_factor);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"decode_set_programmable_EDPp_scaling_factor_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_set_programmable_EDPp_scaling_factor_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error(
"encode_set_programmable_EDPp_scaling_factor_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getClockLimitHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t clock_id;
auto rc = decode_get_clock_limit_req(requestMsg, requestLen, &clock_id);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("decode_get_clock_limit_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
if (clock_id != GRAPHICS_CLOCK && clock_id != MEMORY_CLOCK)
{
lg2::error("getClockLimitHandler: invalid clock_id = {CLOCK_ID}",
"CLOCKID", clock_id);
return std::nullopt;
}
struct nsm_clock_limit clockLimit;
clockLimit.requested_limit_min = 800;
clockLimit.requested_limit_max = 1800;
clockLimit.present_limit_min = 200;
clockLimit.present_limit_max = 2000;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_clock_limit_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_clock_limit_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, &clockLimit, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_clock_limit_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setClockLimitHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t clock_id;
uint8_t flags;
uint32_t limit_min;
uint32_t limit_max;
auto rc = decode_set_clock_limit_req(requestMsg, requestLen, &clock_id,
&flags, &limit_min, &limit_max);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_clock_limit_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_set_clock_limit_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_set_clock_limit_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getCurrClockFreqHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t clock_id;
auto rc = decode_get_curr_clock_freq_req(requestMsg, requestLen, &clock_id);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("decode req for getCurrClockFreqHandler failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
if (clock_id != GRAPHICS_CLOCK && clock_id != MEMORY_CLOCK)
{
lg2::error("getCurrClockFreqHandler: invalid clock_id = {CLOCK_ID}",
"CLOCKID", clock_id);
return std::nullopt;
}
uint32_t clockFreq = 970;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_curr_clock_freq_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_curr_clock_freq_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code, &clockFreq,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_curr_clock_freq_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getProcessorThrottleReasonHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info("getProcessorThrottleReasonHandler: request length={LEN}",
"LEN", requestLen);
}
auto rc = decode_get_current_clock_event_reason_code_req(requestMsg,
requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"decode_get_current_clock_event_reason_code_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
bitfield32_t flags;
flags.byte = 63;
if (verbose)
{
lg2::info("value of flag is {FLAGS}", "FLAGS", flags.byte);
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_clock_event_reason_code_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_current_clock_event_reason_code_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, &flags,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error(
"encode_get_current_clock_event_reason_code_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPowerLimitHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPowerLimitHandler: request length={LEN}", "LEN",
requestLen);
}
uint32_t id;
auto rc = decode_get_power_limit_req(requestMsg, requestLen, &id);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_power_limit_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
assert(rc == NSM_SW_SUCCESS);
// limits are in miliwatts
uint32_t requested_persistent_limit = 10000;
uint32_t requested_oneshot_limit = 15000;
uint32_t enforced_limit = 12500;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_power_limit_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_power_limit_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, requested_persistent_limit,
requested_oneshot_limit, enforced_limit,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_power_limit_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setPowerLimitHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setPowerLimitHandler: request length={LEN}", "LEN",
requestLen);
}
uint32_t id;
uint8_t action;
uint8_t persistent;
uint32_t power_limit;
auto rc = decode_set_power_limit_req(requestMsg, requestLen, &id, &action,
&persistent, &power_limit);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_power_limit_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_set_power_limit_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_set_power_limit_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getAccumCpuUtilTimeHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto rc = decode_common_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("decode req for getAccumCpuUtilTimeHandler failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
uint32_t context_util_time = 4987;
uint32_t SM_util_time = 2564;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_accum_GPU_util_time_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_accum_GPU_util_time_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
&context_util_time, &SM_util_time, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_accum_GPU_util_time_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<Response> MockupResponder::getCurrentUtilizationHandler(
const nsm_msg* requestMsg, size_t requestLen, bool isLongRunning,
std::optional<Request>& longRunningEvent)
{
auto rc = decode_common_req(requestMsg, requestLen);
if (rc)
{
lg2::error(
"decode req for getCurrentUtilizationHandler failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
if (pmDisabled())
{
return unsupportedResponse(requestMsg->hdr.instance_id,
NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_CURRENT_UTILIZATION);
}
nsm_get_current_utilization_data data{36, 75};
Response response(
isLongRunning
? /*common resp*/ (sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp))
: /* regular resp */ (sizeof(nsm_msg_hdr) +
sizeof(nsm_get_current_utilization_resp)),
0);
if (isLongRunning)
{
auto commonMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_common_resp(requestMsg->hdr.instance_id, NSM_ACCEPTED,
ERR_NULL, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_CURRENT_UTILIZATION, commonMsg);
assert(rc == NSM_SW_SUCCESS);
longRunningEvent = Response((sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_long_running_resp) +
sizeof(nsm_get_current_utilization_data)),
0);
auto eventMsg = reinterpret_cast<nsm_msg*>(longRunningEvent->data());
auto eventRc = encode_get_current_utilization_event_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, &data,
eventMsg);
assert(eventRc == NSM_SW_SUCCESS);
}
else
{
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_current_utilization_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, ERR_NULL, &data,
responseMsg);
}
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_current_utilization_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getRowRemapStateHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto rc = decode_get_row_remap_state_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_row_remap_state_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
bitfield8_t flags;
flags.byte = 13;
if (verbose)
{
lg2::info("value of flag is {FLAGS}", "FLAGS", flags.byte);
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_row_remap_state_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_row_remap_state_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code, &flags,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_row_remap_state_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getRowRemappingCountsHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto rc = decode_get_row_remapping_counts_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("decode_get_row_remapping_counts_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
uint32_t correctable_error = 4987;
uint32_t uncorrectable_error = 2564;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_row_remapping_counts_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_row_remapping_counts_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
correctable_error, uncorrectable_error, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_row_remapping_counts_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getRowRemapAvailabilityHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto rc = decode_get_row_remap_availability_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("decode_get_row_remap_availability_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
struct nsm_row_remap_availability data;
data.high_remapping = 100;
data.low_remapping = 200;
data.max_remapping = 300;
data.no_remapping = 400;
data.partial_remapping = 500;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_row_remap_availability_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_row_remap_availability_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code, &data,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_row_remap_availability_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<Response> MockupResponder::getMemoryCapacityUtilHandler(
const nsm_msg* requestMsg, size_t requestLen, bool isLongRunning,
std::optional<Request>& longRunningEvent)
{
if (verbose)
{
lg2::info("getMemoryCapacityUtilHandler: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_memory_capacity_util_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_memory_capacity_util_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
if (pmDisabled())
{
return unsupportedResponse(requestMsg->hdr.instance_id,
NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_MEMORY_CAPACITY_UTILIZATION);
}
struct nsm_memory_capacity_utilization data;
data.reserved_memory = 2345567;
data.used_memory = 128888;
Response response(
isLongRunning
? /*common resp*/ (sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp))
: /* regular resp */ (sizeof(nsm_msg_hdr) +
sizeof(nsm_get_memory_capacity_util_resp)),
0);
if (isLongRunning)
{
auto commonMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_common_resp(requestMsg->hdr.instance_id, NSM_ACCEPTED,
ERR_NULL, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_MEMORY_CAPACITY_UTILIZATION, commonMsg);
assert(rc == NSM_SW_SUCCESS);
longRunningEvent = Response((sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_long_running_resp) +
sizeof(nsm_memory_capacity_utilization)),
0);
auto eventMsg = reinterpret_cast<nsm_msg*>(longRunningEvent->data());
auto eventRc = encode_get_memory_capacity_util_event_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, &data,
eventMsg);
assert(eventRc == NSM_SW_SUCCESS);
}
else
{
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_memory_capacity_util_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, ERR_NULL, &data,
responseMsg);
}
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_memory_capacity_util_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getClockOutputEnableStateHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getClockOutputEnableStateHandler: request length={LEN}",
"LEN", requestLen);
}
uint8_t index = 0;
auto rc = decode_get_clock_output_enable_state_req(requestMsg, requestLen,
&index);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("decode_get_clock_output_enable_state_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
if (index != PCIE_CLKBUF_INDEX && index != NVHS_CLKBUF_INDEX &&
index != IBLINK_CLKBUF_INDEX)
{
lg2::error("getClockOutputEnableStateHandler: invalid index = {INDEX}",
"INDEX", index);
return std::nullopt;
}
uint32_t clk_buf_data = 0xABABABAB;
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_clock_output_enabled_state_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_clock_output_enable_state_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
clk_buf_data, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_clock_output_enable_state_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getFpgaDiagnosticsSettingsHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info("getFpgaDiagnosticsSettingsHandler: request length={LEN}",
"LEN", requestLen);
}
fpga_diagnostics_settings_data_index data_index;
[[maybe_unused]] auto rc = decode_get_fpga_diagnostics_settings_req(
requestMsg, requestLen, &data_index);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getFpgaDiagnosticsSettingsHandler: decode_query_scalar_group_telemetry_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
switch (data_index)
{
case GET_WP_SETTINGS:
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(nsm_fpga_diagnostics_settings_wp_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_fpga_diagnostics_settings_wp_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
&state.writeProtected, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getFpgaDiagnosticsSettingsHandler: encode_get_fpga_diagnostics_settings_wp_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GET_WP_JUMPER_PRESENCE:
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(nsm_fpga_diagnostics_settings_wp_jumper_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
struct nsm_fpga_diagnostics_settings_wp_jumper data = {0, 0};
uint16_t reason_code = ERR_NULL;
rc = encode_get_fpga_diagnostics_settings_wp_jumper_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, &data,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getFpgaDiagnosticsSettingsHandler: encode_get_fpga_diagnostics_settings_wp_jumper_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GET_POWER_SUPPLY_STATUS:
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_power_supply_status_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_power_supply_status_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code,
0b00110011, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getFpgaDiagnosticsSettingsHandler: encode_get_power_supply_status_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GET_GPU_PRESENCE:
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_gpu_presence_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_gpu_presence_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
0b11111111, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getFpgaDiagnosticsSettingsHandler: encode_get_gpu_presence_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GET_GPU_POWER_STATUS:
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_gpu_power_status_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_gpu_power_status_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
0b11110111, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getFpgaDiagnosticsSettingsHandler: encode_get_gpu_power_status_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
case GET_GPU_IST_MODE_SETTINGS:
{
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_gpu_ist_mode_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_gpu_ist_mode_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reason_code,
state.istMode, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getFpgaDiagnosticsSettingsHandler: encode_get_gpu_ist_mode_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
default:
break;
}
return std::nullopt;
}
std::optional<std::vector<uint8_t>>
MockupResponder::enableDisableWriteProtectedHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info("enableDisableWriteProtectedHandler: request length={LEN}",
"LEN", requestLen);
}
diagnostics_enable_disable_wp_data_index data_index;
uint8_t value = 0;
[[maybe_unused]] auto rc = decode_enable_disable_wp_req(
requestMsg, requestLen, &data_index, &value);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"enableDisableWriteProtectedHandler: decode_enable_disable_wp_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
auto& writeProtected = state.writeProtected;
switch (data_index)
{
case BASEBOARD_FRU_EEPROM:
case CX7_FRU_EEPROM:
case HMC_FRU_EEPROM:
writeProtected.baseboard = value;
break;
case HMC_SPI_FLASH:
writeProtected.hmc = value;
break;
case PEX_SW_EEPROM:
writeProtected.pex = value;
break;
case CX8_SPI_FLASH:
writeProtected.cx8 = value;
break;
case RETIMER_EEPROM:
writeProtected.retimer = value;
writeProtected.retimer1 = value;
writeProtected.retimer2 = value;
writeProtected.retimer3 = value;
writeProtected.retimer4 = value;
writeProtected.retimer5 = value;
writeProtected.retimer6 = value;
writeProtected.retimer7 = value;
writeProtected.retimer8 = value;
break;
case NVSW_EEPROM_BOTH:
writeProtected.nvSwitch = value;
writeProtected.nvSwitch1 = value;
writeProtected.nvSwitch2 = value;
break;
case NVSW_EEPROM_1:
writeProtected.nvSwitch1 = value;
writeProtected.nvSwitch = writeProtected.nvSwitch1 |
writeProtected.nvSwitch2;
break;
case NVSW_EEPROM_2:
writeProtected.nvSwitch2 = value;
writeProtected.nvSwitch = writeProtected.nvSwitch1 |
writeProtected.nvSwitch2;
break;
case GPU_1_4_SPI_FLASH:
writeProtected.gpu1_4 = value;
writeProtected.gpu1 = value;
writeProtected.gpu2 = value;
writeProtected.gpu3 = value;
writeProtected.gpu4 = value;
break;
case GPU_5_8_SPI_FLASH:
writeProtected.gpu5_8 = value;
writeProtected.gpu5 = value;
writeProtected.gpu6 = value;
writeProtected.gpu7 = value;
writeProtected.gpu8 = value;
break;
case GPU_SPI_FLASH:
writeProtected.gpu1_4 = value;
writeProtected.gpu5_8 = value;
writeProtected.gpu9_12 = value;
writeProtected.gpu13_16 = value;
writeProtected.gpu1 = value;
writeProtected.gpu2 = value;
writeProtected.gpu3 = value;
writeProtected.gpu4 = value;
writeProtected.gpu5 = value;
writeProtected.gpu6 = value;
writeProtected.gpu7 = value;
writeProtected.gpu8 = value;
writeProtected.gpu9 = value;
writeProtected.gpu10 = value;
writeProtected.gpu11 = value;
writeProtected.gpu12 = value;
writeProtected.gpu13 = value;
writeProtected.gpu14 = value;
writeProtected.gpu15 = value;
writeProtected.gpu16 = value;
break;
case GPU_SPI_FLASH_1:
writeProtected.gpu1 = value;
writeProtected.gpu1_4 = writeProtected.gpu1 | writeProtected.gpu2 |
writeProtected.gpu3 | writeProtected.gpu4;
break;
case GPU_SPI_FLASH_2:
writeProtected.gpu2 = value;
writeProtected.gpu1_4 = writeProtected.gpu1 | writeProtected.gpu2 |
writeProtected.gpu3 | writeProtected.gpu4;
break;
case GPU_SPI_FLASH_3:
writeProtected.gpu3 = value;
writeProtected.gpu1_4 = writeProtected.gpu1 | writeProtected.gpu2 |
writeProtected.gpu3 | writeProtected.gpu4;
break;
case GPU_SPI_FLASH_4:
writeProtected.gpu4 = value;
writeProtected.gpu1_4 = writeProtected.gpu1 | writeProtected.gpu2 |
writeProtected.gpu3 | writeProtected.gpu4;
break;
case GPU_SPI_FLASH_5:
writeProtected.gpu5 = value;
writeProtected.gpu5_8 = writeProtected.gpu5 | writeProtected.gpu6 |
writeProtected.gpu7 | writeProtected.gpu8;
break;
case GPU_SPI_FLASH_6:
writeProtected.gpu6 = value;
writeProtected.gpu5_8 = writeProtected.gpu5 | writeProtected.gpu6 |
writeProtected.gpu7 | writeProtected.gpu8;
break;
case GPU_SPI_FLASH_7:
writeProtected.gpu7 = value;
writeProtected.gpu5_8 = writeProtected.gpu5 | writeProtected.gpu6 |
writeProtected.gpu7 | writeProtected.gpu8;
break;
case GPU_SPI_FLASH_8:
writeProtected.gpu8 = value;
writeProtected.gpu5_8 = writeProtected.gpu5 | writeProtected.gpu6 |
writeProtected.gpu7 | writeProtected.gpu8;
break;
case RETIMER_EEPROM_1:
writeProtected.retimer1 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case RETIMER_EEPROM_2:
writeProtected.retimer2 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case RETIMER_EEPROM_3:
writeProtected.retimer3 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case RETIMER_EEPROM_4:
writeProtected.retimer4 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case RETIMER_EEPROM_5:
writeProtected.retimer5 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case RETIMER_EEPROM_6:
writeProtected.retimer6 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case RETIMER_EEPROM_7:
writeProtected.retimer7 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case RETIMER_EEPROM_8:
writeProtected.retimer8 = value;
writeProtected.retimer =
writeProtected.retimer1 | writeProtected.retimer2 |
writeProtected.retimer3 | writeProtected.retimer4 |
writeProtected.retimer5 | writeProtected.retimer6 |
writeProtected.retimer7 | writeProtected.retimer8;
break;
case CPU_SPI_FLASH_1:
writeProtected.cpu1 = value;
writeProtected.cpu1_4 = writeProtected.cpu1 | writeProtected.cpu2 |
writeProtected.cpu3 | writeProtected.cpu4;
break;
case CPU_SPI_FLASH_2:
writeProtected.cpu2 = value;
writeProtected.cpu1_4 = writeProtected.cpu1 | writeProtected.cpu2 |
writeProtected.cpu3 | writeProtected.cpu4;
break;
case CPU_SPI_FLASH_3:
writeProtected.cpu3 = value;
writeProtected.cpu1_4 = writeProtected.cpu1 | writeProtected.cpu2 |
writeProtected.cpu3 | writeProtected.cpu4;
break;
case CPU_SPI_FLASH_4:
writeProtected.cpu4 = value;
writeProtected.cpu1_4 = writeProtected.cpu1 | writeProtected.cpu2 |
writeProtected.cpu3 | writeProtected.cpu4;
break;
default:
lg2::error(
"enableDisableWriteProtectedHandler: Invalid Data Index");
break;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_enable_disable_wp_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"enableDisableWriteProtectedHandler: encode_enable_disable_wp_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getDeviceDiagnosticsHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t handle = 0;
auto rc = decode_get_device_diagnostics_req(requestMsg, requestLen,
&handle);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_device_diagnostics_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
if (verbose)
{
lg2::info("getDeviceDiagnosticsHandler: request length={LEN}, "
"handle={HANDLE}",
"LEN", requestLen, "HANDLE", handle);
}
std::string segmentData = "Hello World, this is device diagnostics info";
Response response(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_device_diagnostics_resp) - 1 +
segmentData.size(),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reasonCode = ERR_NULL;
uint8_t nextHandle =
handle == 0 ? 1 : 0xFF; // mockup responder will send only 2 segments
rc = encode_get_device_diagnostics_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reasonCode,
(uint8_t*)segmentData.data(), segmentData.size(), nextHandle,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_device_diagnostics_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getNetworkDeviceDebugInfoHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t debugType = 0;
uint32_t handle = 0;
auto rc = decode_get_network_device_debug_info_req(requestMsg, requestLen,
&debugType, &handle);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_network_device_debug_info_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
if (verbose)
{
lg2::info("getNetworkDeviceDebugInfoHandler: request length={LEN}, "
"debugType={DEBUG_TYPE}, handle={HANDLE}",
"LEN", requestLen, "DEBUG_TYPE", debugType, "HANDLE", handle);
}
std::string segmentData = "Hello World, this is device debug info data.";
uint16_t reasonCode = ERR_NULL;
uint32_t nextHandle =
handle == 0 ? 1 : 0; // mockup responder will send only 2 segments
Response response(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_network_device_debug_info_resp) - 1 +
segmentData.size(),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_network_device_debug_info_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reasonCode,
(uint8_t*)segmentData.data(), segmentData.size(), nextHandle,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_network_device_debug_info_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::eraseTraceHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("eraseTraceHandler: request length={LEN}", "LEN", requestLen);
}
auto rc = decode_erase_trace_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_erase_trace_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_erase_trace_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_erase_trace_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, ERASE_TRACE_DATA_ERASED,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_erase_trace_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getNetworkDeviceLogInfoHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint32_t handle = 0;
auto rc = decode_get_network_device_log_info_req(requestMsg, requestLen,
&handle);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_network_device_log_info_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
if (verbose)
{
lg2::info("getNetworkDeviceLogInfoHandler: request length={LEN}, "
"handle={HANDLE}",
"LEN", requestLen, "HANDLE", handle);
}
// this is some dummy data segment with random size
// It says "Hello World, this is device log info data."
std::string logData = "Hello World, this is device log info data.";
uint16_t reasonCode = ERR_NULL;
uint32_t nextHandle = 0; // mockup responder will send only 1 log info
nsm_device_log_info_breakdown logInfo;
logInfo.lost_events = 02;
logInfo.unused = 00;
logInfo.synced_time = 00;
logInfo.reserved1 = 00;
logInfo.reserved2 = 00;
logInfo.time_high = 100;
logInfo.time_low = 200;
logInfo.entry_prefix = 33;
logInfo.length = (logData.size() / 4);
logInfo.entry_suffix = 444;
Response response(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_network_device_log_info_resp) - 1 +
logData.size(),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_network_device_log_info_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reasonCode, nextHandle,
logInfo, (uint8_t*)logData.data(), logData.size(), responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_network_device_log_info_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::eraseDebugInfoHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("eraseDebugInfoHandler: request length={LEN}", "LEN",
requestLen);
}
uint8_t info_type;
auto rc = decode_erase_debug_info_req(requestMsg, requestLen, &info_type);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_erase_debug_info_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_erase_debug_info_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_erase_debug_info_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, ERASE_TRACE_DATA_ERASED,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_erase_debug_info_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryAggregatedResetMetrics(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("queryResetMetrics: request length={LEN}", "LEN", requestLen);
}
// Decode the request message (assuming decode function exists)
auto rc = decode_get_device_reset_statistics_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
// Initialize response vector
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
response.reserve(256);
uint16_t samplesCount{};
// Iterate through mock reset metric data
for (const auto& [tag, mockValue] : resetMetricsMockTable)
{
++samplesCount;
uint8_t reading[64]{};
size_t sample_len{};
std::array<uint8_t, 256> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
if (tag == 7) // Special case for "LastResetType" (enum8)
{
rc = encode_reset_enum_data(static_cast<uint8_t>(mockValue),
reading, &sample_len);
}
else if (tag == 8) // Special case for boot reason (256 bytes)
{
rc = encode_reset_count_256data(bootReasonMockValue.data(), reading,
&sample_len);
}
else // General case for reset counts (uint16_t)
{
rc = encode_reset_count_data(static_cast<uint16_t>(mockValue),
reading, &sample_len);
}
assert(rc == NSM_SW_SUCCESS);
// Encode the sample into the response
rc = encode_aggregate_resp_sample(tag, true, reading, sample_len,
nsm_sample, &sample_len);
assert(rc == NSM_SW_SUCCESS);
// Add the sample to the response vector
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), sample_len));
}
// Finalize the aggregate response
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_aggregate_resp(requestMsg->hdr.instance_id,
NSM_GET_DEVICE_RESET_STATISTICS, NSM_SUCCESS,
samplesCount, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryAggregatedGPMMetrics(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request = reinterpret_cast<const nsm_query_aggregate_gpm_metrics_req*>(
requestMsg->payload);
if (verbose)
{
lg2::info("queryAggregatedGPMMetrics: request length={LEN}", "LEN",
requestLen);
}
uint8_t retrieval_source;
uint8_t gpu_instance;
uint8_t compute_instance;
const uint8_t* metrics_bitfield;
size_t metrics_bitfield_length;
auto rc = decode_query_aggregate_gpm_metrics_req(
requestMsg, requestLen, &retrieval_source, &gpu_instance,
&compute_instance, &metrics_bitfield, &metrics_bitfield_length);
assert(rc == NSM_SW_SUCCESS);
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
response.reserve(256);
uint16_t samplesCount{};
for (size_t i{}; i < metrics_bitfield_length; ++i)
{
for (uint8_t j{}; j < 8; ++j)
{
if (metrics_bitfield[i] & 1 << j)
{
const uint8_t metric_id = 8 * i + j;
const auto info = metricsTable.find(metric_id);
if (info == metricsTable.end())
{
continue;
}
++samplesCount;
uint8_t reading[64]{};
size_t sample_len{};
std::array<uint8_t, 256> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
switch (info->second.unit)
{
case GPMMetricsUnit::PERCENTAGE:
rc = encode_aggregate_gpm_metric_percentage_data(
info->second.mockValue, reading, &sample_len);
assert(rc == NSM_SW_SUCCESS);
break;
case GPMMetricsUnit::BANDWIDTH:
rc = encode_aggregate_gpm_metric_bandwidth_data(
info->second.mockValue, reading, &sample_len);
assert(rc == NSM_SW_SUCCESS);
break;
}
rc = encode_aggregate_resp_sample(metric_id, true, reading,
sample_len, nsm_sample,
&sample_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), sample_len));
}
}
}
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_aggregate_resp(requestMsg->hdr.instance_id,
request->hdr.command, NSM_SUCCESS, samplesCount,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::queryPerInstanceGPMMetrics(const nsm_msg* requestMsg,
size_t requestLen)
{
auto request =
reinterpret_cast<const nsm_query_per_instance_gpm_metrics_req*>(
requestMsg->payload);
if (verbose)
{
lg2::info("queryPerInstanceGPMMetrics: request length={LEN}", "LEN",
requestLen);
}
uint8_t retrieval_source;
uint8_t gpu_instance;
uint8_t compute_instance;
uint8_t metric_id;
uint32_t instance_bitfield;
auto rc = decode_query_per_instance_gpm_metrics_req(
requestMsg, requestLen, &retrieval_source, &gpu_instance,
&compute_instance, &metric_id, &instance_bitfield);
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
response.reserve(256);
uint16_t samplesCount{};
const auto info = metricsTable.find(metric_id);
if (info == metricsTable.end())
{
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_cc_only_resp(requestMsg->hdr.instance_id,
requestMsg->hdr.nvidia_msg_type,
request->hdr.command, NSM_ERR_INVALID_DATA,
ERR_NOT_SUPPORTED, responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
for (size_t i{}; i < 32; ++i)
{
if (instance_bitfield & 1 << i)
{
++samplesCount;
uint8_t reading[64]{};
size_t consumed_len{};
std::array<uint8_t, 256> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
switch (info->second.unit)
{
case GPMMetricsUnit::PERCENTAGE:
{
auto val = info->second.mockValue * (i + 1);
val -= 100 * (static_cast<int>(val) / 100);
rc = encode_aggregate_gpm_metric_percentage_data(
val, reading, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
break;
}
case GPMMetricsUnit::BANDWIDTH:
{
// To obtain a unique value for each instance
// Metric, base Metric value is multiplied by
// instance number and then the module of base 10 is
// taken on that number.
constexpr uint64_t mod = 10 * 1024 * 1024 * 128;
auto val = info->second.mockValue * (i + 1);
val -= mod * (static_cast<uint64_t>(val) / mod);
rc = encode_aggregate_gpm_metric_bandwidth_data(
val, reading, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
break;
}
}
rc = encode_aggregate_resp_sample(i, true, reading, consumed_len,
nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
}
}
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_aggregate_resp(requestMsg->hdr.instance_id,
request->hdr.command, NSM_SUCCESS, samplesCount,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::enableDisableGpuIstModeHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("enableDisableGpuIstModeHandler: request length={LEN}", "LEN",
requestLen);
}
uint8_t device_index;
uint8_t value = 0;
[[maybe_unused]] auto rc = decode_enable_disable_gpu_ist_mode_req(
requestMsg, requestLen, &device_index, &value);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"enableDisableGpuIstModeHandler: decode_enable_disable_gpu_ist_mode_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
auto& istMode = state.istMode;
if (device_index < 8)
{
istMode = value ? (istMode | (1 << device_index))
: (istMode & (0 << device_index));
}
else if (device_index == ALL_GPUS_DEVICE_INDEX)
{
istMode = value ? 0b11111111 : 0b00000000;
}
else
{
lg2::error("enableDisableGpuIstModeHandler: Invalid Device Index");
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_enable_disable_gpu_ist_mode_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"enableDisableGpuIstModeHandler: encode_enable_disable_gpu_ist_mode_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getReconfigurationPermissionsV1Handler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info(
"getReconfigurationPermissionsV1Handler: request length={LEN}",
"LEN", requestLen);
}
reconfiguration_permissions_v1_index settingsIndex;
[[maybe_unused]] auto rc = decode_get_reconfiguration_permissions_v1_req(
requestMsg, requestLen, &settingsIndex);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getReconfigurationPermissionsV1Handler: decode_get_reconfiguration_permissions_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
if (settingsIndex > RP_INFOROM_RECREATE_ALLOW_INB)
{
lg2::error(
"getReconfigurationPermissionsV1Handler: Invalid Settings Index");
return std::nullopt;
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) +
sizeof(nsm_get_reconfiguration_permissions_v1_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reasonCode = ERR_NULL;
rc = encode_get_reconfiguration_permissions_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reasonCode,
&state.prcKnobs[settingsIndex], responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getReconfigurationPermissionsV1Handler: encode_get_reconfiguration_permissions_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setReconfigurationPermissionsV1Handler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info(
"setReconfigurationPermissionsV1Handler: request length={LEN}",
"LEN", requestLen);
}
reconfiguration_permissions_v1_index settingsIndex;
reconfiguration_permissions_v1_setting configuration;
uint8_t permission;
[[maybe_unused]] auto rc = decode_set_reconfiguration_permissions_v1_req(
requestMsg, requestLen, &settingsIndex, &configuration, &permission);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"setReconfigurationPermissionsV1Handler: decode_set_reconfiguration_permissions_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
if (settingsIndex > RP_INFOROM_RECREATE_ALLOW_INB)
{
lg2::error(
"setReconfigurationPermissionsV1Handler: Invalid Settings Index");
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reasonCode = ERR_NULL;
rc = encode_set_reconfiguration_permissions_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reasonCode, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"enableDisableGpuIstModeHandler: encode_set_reconfiguration_permissions_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
switch (configuration)
{
case RP_ONESHOOT_HOT_RESET:
if (permission & 1)
{
state.prcKnobs[settingsIndex].host_oneshot = 1;
}
if ((permission >> 1) & 1)
{
state.prcKnobs[settingsIndex].DOE_oneshot = 1;
}
break;
case RP_PERSISTENT:
if (permission & 1)
{
state.prcKnobs[settingsIndex].host_persistent = 1;
}
if ((permission >> 1) & 1)
{
state.prcKnobs[settingsIndex].DOE_persistent = 1;
}
break;
case RP_ONESHOT_FLR:
if (permission & 1)
{
state.prcKnobs[settingsIndex].host_flr_persistent = 1;
}
if ((permission >> 1) & 1)
{
state.prcKnobs[settingsIndex].DOE_flr_persistent = 1;
}
break;
default:
lg2::error(
"setReconfigurationPermissionsV1Handler: invalid configuration: configuration={CONF}",
"CONF", int(configuration));
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getConfidentialComputeModeHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
auto rc = decode_get_confidential_compute_mode_v1_req(requestMsg,
requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"decode request for getConfidentialComputeModeHandler failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
uint8_t current_mode = 2;
uint8_t pending_mode = 2;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_confidential_compute_mode_v1_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_confidential_compute_mode_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, current_mode,
pending_mode, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error(
"encode_get_confidential_compute_mode_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setConfidentialComputeModeHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
uint8_t mode;
auto rc = decode_set_confidential_compute_mode_v1_req(requestMsg,
requestLen, &mode);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"decode request for setConfidentialComputeModeHandler failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_set_confidential_compute_mode_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error(
"encode_set_confidential_compute_mode_v1_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setErrorInjectionModeV1Handler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setErrorInjectionModeV1Handler: request length={LEN}", "LEN",
requestLen);
}
uint8_t mode = 0;
auto rc = decode_set_error_injection_mode_v1_req(requestMsg, requestLen,
&mode);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"setErrorInjectionModeV1Handler: decode_set_error_injection_mode_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
state.errorInjectionMode.mode = mode;
Response response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_set_error_injection_mode_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, responseMsg);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getErrorInjectionModeV1Handler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getErrorInjectionModeV1Handler: request length={LEN}", "LEN",
requestLen);
}
auto rc = decode_get_error_injection_mode_v1_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getErrorInjectionModeV1Handler: decode_get_error_injection_mode_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
Response response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_error_injection_mode_v1_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_error_injection_mode_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL,
&state.errorInjectionMode, responseMsg);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getSupportedErrorInjectionTypesV1Handler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info(
"getSupportedErrorInjectionTypesV1Handler: request length={LEN}",
"LEN", requestLen);
}
auto rc = decode_get_error_injection_types_v1_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getSupportedErrorInjectionTypesV1Handler: decode_get_error_injection_types_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
Response response(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_error_injection_types_mask_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
nsm_error_injection_types_mask supportedTypes = {0, 0, 0, 0, 0, 0, 0, 0};
auto errorInjectionIt = state.errorInjection.find(mockDeviceType);
if (errorInjectionIt != state.errorInjection.end())
{
for (const auto& [type, _] : errorInjectionIt->second)
{
supportedTypes.mask[type / 8] |= (1 << (type % 8));
}
}
rc = encode_get_supported_error_injection_types_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, &supportedTypes,
responseMsg);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setCurrentErrorInjectionTypesV1Handler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info(
"setCurrentdErrorInjectionTypesV1Handler: request length={LEN}",
"LEN", requestLen);
}
nsm_error_injection_types_mask data;
auto rc = decode_set_current_error_injection_types_v1_req(
requestMsg, requestLen, &data);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"setCurrentErrorInjectionTypesV1Handler: decode_set_error_injection_types_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
Response response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
auto errorInjectionIt = state.errorInjection.find(mockDeviceType);
if (errorInjectionIt != state.errorInjection.end())
{
bool error = false;
auto& errorInjectionTypes = errorInjectionIt->second;
// check for errors;
for (size_t i = 0; i < 64 && !error; i++)
{
bool enabled = (data.mask[i / 8] >> (i % 8)) & 0x01;
// set error if bit is enabled, but not supported
error = enabled &&
errorInjectionTypes.find(error_injection_type(i)) ==
errorInjectionTypes.end();
}
if (error)
{
response.resize(sizeof(nsm_msg_hdr) +
sizeof(nsm_common_non_success_resp));
rc = encode_common_resp(
requestMsg->hdr.instance_id, NSM_ERR_INVALID_DATA, ERR_NULL,
NSM_TYPE_DEVICE_CONFIGURATION,
NSM_SET_CURRENT_ERROR_INJECTION_TYPES_V1, responseMsg);
return response;
}
else
{
for (auto& [type, enabled] : errorInjectionTypes)
{
enabled = (data.mask[type / 8] >> (type % 8)) & 0x01;
}
}
}
rc = encode_set_current_error_injection_types_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, responseMsg);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getCurrentErrorInjectionTypesV1Handler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info(
"getCurrentdErrorInjectionTypesV1Handler: request length={LEN}",
"LEN", requestLen);
}
auto rc = decode_get_error_injection_types_v1_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getCurrentErrorInjectionTypesV1Handler: decode_get_error_injection_types_v1_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
Response response(sizeof(nsm_msg_hdr) +
sizeof(nsm_get_error_injection_types_mask_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
nsm_error_injection_types_mask enabledTypes = {0, 0, 0, 0, 0, 0, 0, 0};
auto errorInjectionIt = state.errorInjection.find(mockDeviceType);
if (errorInjectionIt != state.errorInjection.end())
{
for (const auto& [type, enabled] : errorInjectionIt->second)
{
enabledTypes.mask[type / 8] |= (uint8_t(enabled) << (type % 8));
}
}
rc = encode_get_current_error_injection_types_v1_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, &enabledTypes,
responseMsg);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getErrorInjectionPayloadHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getErrorInjectionPayloadHandler: request length={LEN}",
"LEN", requestLen);
}
uint32_t error_injection_id = 0;
auto rc = decode_get_error_injection_payload_req(requestMsg, requestLen,
&error_injection_id);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"getErrorInjectionPayloadHandler: decode_get_error_injection_payload_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
Response response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_error_injection_payload_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_error_injection_payload_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL,
&state.errorInjectionPayload, responseMsg);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setErrorInjectionPayloadHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("setErrorInjectionPayloadHandler: request length={LEN}",
"LEN", requestLen);
}
nsm_error_injection_payload data;
auto rc = decode_set_error_injection_payload_req(requestMsg, requestLen,
&data);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"setErrorInjectionPayloadHandler: decode_set_error_injection_payload_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
state.errorInjectionPayload = data;
Response response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_set_error_injection_payload_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, responseMsg);
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::activateErrorInjectionHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
auto rc = decode_activate_error_injection_payload_req(requestMsg,
requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"activateErrorInjectionHandler: decode_activate_error_injection_payload_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
Response response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_activate_error_injection_payload_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, responseMsg);
return response;
}
std::optional<Response> MockupResponder::getViolationDurationHandler(
const nsm_msg* requestMsg, size_t requestLen, bool isLongRunning,
std::optional<Request>& longRunningEvent)
{
auto rc = decode_get_violation_duration_req(requestMsg, requestLen);
if (rc)
{
lg2::error("decode_get_violation_duration_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
if (pmDisabled())
{
return unsupportedResponse(requestMsg->hdr.instance_id,
NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_VIOLATION_DURATION);
}
struct nsm_violation_duration data;
data.supported_counter.byte = 255;
data.hw_violation_duration = 2000000;
data.global_sw_violation_duration = 3000000;
data.power_violation_duration = 4000000;
data.thermal_violation_duration = 5000000;
data.counter4 = 6000000;
data.counter5 = 7000000;
data.counter6 = 8000000;
data.counter7 = 9000000;
Response response(
isLongRunning
? /*common resp*/ (sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp))
: /* regular resp */ (sizeof(nsm_msg_hdr) +
sizeof(nsm_get_violation_duration_resp)),
0);
if (isLongRunning)
{
auto commonMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_common_resp(requestMsg->hdr.instance_id, NSM_ACCEPTED,
ERR_NULL, NSM_TYPE_PLATFORM_ENVIRONMENTAL,
NSM_GET_VIOLATION_DURATION, commonMsg);
assert(rc == NSM_SW_SUCCESS);
longRunningEvent = Response((sizeof(nsm_msg_hdr) + NSM_EVENT_MIN_LEN +
sizeof(nsm_long_running_resp) +
sizeof(nsm_violation_duration)),
0);
auto eventMsg = reinterpret_cast<nsm_msg*>(longRunningEvent->data());
auto eventRc = encode_get_violation_duration_event_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, ERR_NULL, &data,
eventMsg);
assert(eventRc == NSM_SW_SUCCESS);
}
else
{
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_violation_duration_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, ERR_NULL, &data,
responseMsg);
}
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_violation_duration_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::resetNetworkDeviceHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("resetNetworkDeviceHandler: request length={LEN}", "LEN",
requestLen);
}
uint8_t mode = 0;
auto rc = decode_reset_network_device_req(requestMsg, requestLen, &mode);
if (rc != NSM_SW_SUCCESS)
{
if (verbose)
{
lg2::error("decode_reset_network_device_req failed: rc={RC}", "RC",
rc);
}
return std::nullopt;
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_reset_network_device_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_reset_network_device_resp(requestMsg->hdr.instance_id,
reason_code, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_reset_network_device_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getEgmModeHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getEgmModeHandler: request length={LEN}", "LEN", requestLen);
}
auto rc = decode_common_req(requestMsg, requestLen);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode request for getEgmModeHandler failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
bitfield8_t flags;
flags.byte = 1;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_get_EGM_mode_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_get_EGM_mode_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, &flags, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_EGM_mode_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::setEgmModeHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
uint8_t requested_mode;
auto rc = decode_set_EGM_mode_req(requestMsg, requestLen, &requested_mode);
assert(rc == NSM_SW_SUCCESS);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_set_EGM_mode_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) + sizeof(nsm_common_resp),
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reason_code = ERR_NULL;
rc = encode_set_EGM_mode_resp(requestMsg->hdr.instance_id, NSM_SUCCESS,
reason_code, responseMsg);
assert(rc == NSM_SW_SUCCESS);
if (rc)
{
lg2::error("encode_get_EGM_mode_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getHistogramFormatHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getHistogramFormatHandler: request length={LEN}", "LEN",
requestLen);
}
uint32_t histogramId;
uint16_t parameter;
auto rc = decode_get_histogram_format_req(requestMsg, requestLen,
&histogramId, &parameter);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_histogram_format_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
struct nsm_histogram_format_metadata metaData;
uint16_t reason_code = ERR_NULL;
std::vector<uint32_t> bucketOffsets = {00, 15, 30, 45, 60, 75};
uint32_t totalBucketSize = bucketOffsets.size() * sizeof(bucketOffsets[0]);
metaData.num_of_buckets = bucketOffsets.size();
metaData.min_sampling_time = 16;
metaData.accumulation_cycle = 12;
metaData.increment_duration = 111;
metaData.bucket_unit_of_measure = NSM_BUCKET_UNIT_WATTS;
metaData.bucket_data_type = NvU32;
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(struct nsm_common_resp) +
sizeof(struct nsm_histogram_format_metadata) + totalBucketSize,
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_histogram_format_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, &metaData,
reinterpret_cast<uint8_t*>(bucketOffsets.data()), totalBucketSize,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_histogram_format_resp failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getHistogramDataHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getHistogramDataHandler: request length={LEN}", "LEN",
requestLen);
}
uint32_t histogramId;
uint16_t parameter;
auto rc = decode_get_histogram_data_req(requestMsg, requestLen,
&histogramId, &parameter);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_histogram_data_req failed: rc={RC}", "RC", rc);
return std::nullopt;
}
std::vector<uint32_t> bucketData = {11, 22, 33, 55, 66, 77};
uint16_t numOfBuckets = bucketData.size();
uint8_t bucketDataType = NvU32;
uint32_t bucketDataSize = bucketData.size() * sizeof(bucketData[0]);
uint16_t reason_code = ERR_NULL;
std::vector<uint8_t> response(sizeof(nsm_msg_hdr) +
NSM_RESPONSE_CONVENTION_LEN +
sizeof(numOfBuckets) + bucketDataSize + 1,
0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_get_histogram_data_resp(
requestMsg->hdr.instance_id, NSM_SUCCESS, reason_code, bucketDataType,
numOfBuckets, reinterpret_cast<uint8_t*>(bucketData.data()),
bucketDataSize, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_get_histogram_data_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return response;
}
std::optional<Response>
MockupResponder::getListAvailablePciePortsHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getListAvailablePciePortsHandler: request length={LEN}",
"LEN", requestLen);
}
auto rc = decode_list_available_pcie_ports_req(requestMsg, requestLen);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_list_available_pcie_ports_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
Response response(NSM_LIST_AVAILABLE_PCIE_PORTS_RESPONSE_MIN_LEN, 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
uint16_t reasonCode = ERR_NULL;
nsm_list_available_pcie_ports_info info{1, {{1, 2}}};
rc = encode_list_available_pcie_ports_resp(requestMsg->hdr.instance_id,
NSM_SUCCESS, reasonCode, &info,
responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_list_available_pcie_ports_resp failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getEthPortTelemetryCounterHandler(
const nsm_msg* requestMsg, size_t requestLen)
{
if (verbose)
{
lg2::info("getEthPortTelemetryCounterHandler: request length={LEN}",
"LEN", requestLen);
}
uint16_t portNumber = 0;
auto rc = decode_get_eth_port_telemetry_counter_req(requestMsg, requestLen,
&portNumber);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_eth_port_telemetry_counter_req failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
const size_t maxResponseSize =
ETH_PORT_TELEMETRY_COUNTER_ENABLED_COUNT * sizeof(uint64_t) +
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp);
static std::vector<uint8_t> ethPortTelemetryCounterResponse(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
ethPortTelemetryCounterResponse.reserve(maxResponseSize);
ethPortTelemetryCounterResponse.clear();
if (((ethPortTelemetryCounterResponse.capacity() - sizeof(nsm_msg_hdr) -
sizeof(nsm_aggregate_resp)) >
ETH_PORT_TELEMETRY_COUNTER_ENABLED_COUNT * sizeof(uint64_t)))
{
lg2::error(
"Response capacity more than maximum aggregate response size");
return std::nullopt;
}
uint16_t samplesCount = 0;
for (uint8_t tag = 0; tag < ETH_PORT_TELEMETRY_COUNTER_ENABLED_COUNT; ++tag)
{
++samplesCount;
std::array<uint8_t, 256> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
size_t sample_len = 0;
switch (tag)
{
case ETHERNET_PORT_COUNTER_TAG_RX_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_UNICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_MULTICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_BROADCAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_UNICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_MULTICAST_BYTES:
case ETHERNET_PORT_COUNTER_TAG_TX_BROADCAST_BYTES:
{
nsm_ethernet_port_counter_data mockValue{
.ethernet_port_counter_data_64bit = static_cast<uint64_t>(
2000000 + tag * 10)}; // Mock value for 64 bit counter
uint8_t reading[sizeof(uint64_t)] = {};
sample_len = sizeof(reading);
rc = encode_aggregate_eth_port_telemetry_data(
tag, &mockValue, reading, &sample_len);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_aggregate_eth_port_telemetry_data failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
rc = encode_aggregate_resp_sample(
tag, true, reading, sample_len, nsm_sample, &sample_len);
break;
}
case ETHERNET_PORT_COUNTER_TAG_RX_FCS_ERRORS:
case ETHERNET_PORT_COUNTER_TAG_RX_ALIGNMENT_ERRORS:
case ETHERNET_PORT_COUNTER_TAG_RX_FALSE_CARRIER_DETECTIONS:
case ETHERNET_PORT_COUNTER_TAG_RX_RUNT_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_JABBER_BYTES:
case ETHERNET_PORT_COUNTER_TAG_RX_XON_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_XOFF_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_TX_XON_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_TX_XOFF_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_SINGLE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_MULTIPLE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_LATE_COLLISION_FRAMES:
case ETHERNET_PORT_COUNTER_TAG_RX_EXCESSIVE_COLLISION_FRAMES:
{
nsm_ethernet_port_counter_data mockValue{
.ethernet_port_counter_data_32bit = static_cast<uint32_t>(
2000000 + tag * 10)}; // Mock value for 32 bit counter
uint8_t reading[sizeof(uint32_t)] = {};
sample_len = sizeof(reading);
rc = encode_aggregate_eth_port_telemetry_data(
tag, &mockValue, reading, &sample_len);
if (rc != NSM_SW_SUCCESS)
{
lg2::error(
"encode_aggregate_eth_port_telemetry_data failed: rc={RC}",
"RC", rc);
return std::nullopt;
}
rc = encode_aggregate_resp_sample(
tag, true, reading, sample_len, nsm_sample, &sample_len);
break;
}
}
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_aggregate_resp_sample failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
if ((ethPortTelemetryCounterResponse.size() + sample_len) <=
ethPortTelemetryCounterResponse.capacity())
{
ethPortTelemetryCounterResponse.insert(
ethPortTelemetryCounterResponse.end(), sample.begin(),
std::next(sample.begin(), sample_len));
}
else
{
lg2::debug(
"Not enough capacity in ethPortTelemetryCounterResponse to insert sample");
return std::nullopt;
}
}
auto responseMsg =
reinterpret_cast<nsm_msg*>(ethPortTelemetryCounterResponse.data());
rc = encode_aggregate_resp(requestMsg->hdr.instance_id,
NSM_GET_ETH_PORT_TELEMETRY_COUNTER, NSM_SUCCESS,
samplesCount, responseMsg);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("encode_aggregate_resp failed: rc={RC}", "RC", rc);
return std::nullopt;
}
return ethPortTelemetryCounterResponse;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPortNetworkAddressesHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPortNetworkAddressesHandler: request length={LEN}", "LEN",
requestLen);
}
uint16_t portNumber = 0;
auto rc = decode_get_network_addresses_req(requestMsg, requestLen,
&portNumber);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_network_addresses_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_aggregate_resp(requestMsg->hdr.instance_id,
NSM_GET_NETWORK_ADDRESSES, NSM_SUCCESS, 3,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
std::array<uint8_t, 50> sample;
auto nsmSample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
size_t consumedLen = 0;
network_address_sample_data address = {};
address.link_type = portNumber % 2; // 0 or 1
uint8_t data[1];
size_t dataLen = 0;
rc = encode_aggregate_network_address_data(NSM_TAG_LINK_TYPE, &address,
data, &dataLen);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_LINK_TYPE, true, data, dataLen,
nsmSample, &consumedLen);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumedLen));
switch (address.link_type)
{
case NSM_PORT_PROTOCOL_ETHERNET:
{
network_address_sample_data macAddress = {
.mac_address = {0x1A, 0x2B, 0x1C, 0x3D, 0x4E, 0x5F, 0x00,
0x00}};
uint8_t reading[MAC_ADDRESS_LENGTH]{};
size_t readingLen{};
rc = encode_aggregate_network_address_data(
NSM_TAG_MAC_ADDRESS, &macAddress, reading, &readingLen);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_MAC_ADDRESS, true,
reading, readingLen, nsmSample,
&consumedLen);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumedLen));
network_address_sample_data permanentMacAddress = {
.mac_address = {0x1A, 0x2B, 0x3C, 0x4D, 0x5E, 0x6F, 0x00,
0x00}};
rc = encode_aggregate_network_address_data(
NSM_TAG_PERMANENT_MAC_ADDRESS, &permanentMacAddress, reading,
&readingLen);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_PERMANENT_MAC_ADDRESS,
true, reading, readingLen,
nsmSample, &consumedLen);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumedLen));
break;
}
case NSM_PORT_PROTOCOL_INFINIBAND:
{
network_address_sample_data nodeGuid = {};
nodeGuid.network_identifier_64bit = 0x123456789ABCDEF0;
uint8_t reading[sizeof(uint64_t)]{};
size_t readingLen{};
rc = encode_aggregate_network_address_data(
NSM_TAG_NODE_GUID, &nodeGuid, reading, &readingLen);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_NODE_GUID, true, reading,
readingLen, nsmSample,
&consumedLen);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumedLen));
network_address_sample_data portGuid = {};
portGuid.network_identifier_64bit = 0xABCDEF0123456789;
rc = encode_aggregate_network_address_data(
NSM_TAG_PORT_GUID, &portGuid, reading, &readingLen);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_PORT_GUID, true, reading,
readingLen, nsmSample,
&consumedLen);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumedLen));
break;
}
default:
{
break;
}
}
return response;
}
std::optional<std::vector<uint8_t>>
MockupResponder::getPortEccCountersHandler(const nsm_msg* requestMsg,
size_t requestLen)
{
if (verbose)
{
lg2::info("getPortEccCountersHandler: request length={LEN}", "LEN",
requestLen);
}
uint16_t portNumber = 0;
auto rc = decode_get_port_ecc_counters_req(requestMsg, requestLen,
&portNumber);
if (rc != NSM_SW_SUCCESS)
{
lg2::error("decode_get_port_ecc_counters_req failed: rc={RC}", "RC",
rc);
return std::nullopt;
}
std::vector<uint8_t> response(
sizeof(nsm_msg_hdr) + sizeof(nsm_aggregate_resp), 0);
auto responseMsg = reinterpret_cast<nsm_msg*>(response.data());
rc = encode_aggregate_resp(requestMsg->hdr.instance_id,
NSM_GET_PORT_ECC_COUNTERS, NSM_SUCCESS, 6,
responseMsg);
assert(rc == NSM_SW_SUCCESS);
std::array<uint8_t, 100> sample;
auto nsm_sample =
reinterpret_cast<nsm_aggregate_resp_sample*>(sample.data());
size_t consumed_len = 0;
uint64_t counter_value = 2;
uint8_t data[8];
size_t data_len = 0;
rc = encode_aggregate_port_ecc_counter_data(
NSM_TAG_ECC_RX_SYMBOL_ERRORS_BYTES, 10000000000 + counter_value, data,
&data_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_ECC_RX_SYMBOL_ERRORS_BYTES, true,
data, data_len, nsm_sample,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
counter_value = 8;
rc = encode_aggregate_port_ecc_counter_data(NSM_TAG_ECC_CORRECTED_BITS,
10000000000 + counter_value,
data, &data_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_ECC_CORRECTED_BITS, true, data,
data_len, nsm_sample, &consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
for (int i = 0; i < 4; i++)
{
counter_value = i + 1;
rc = encode_aggregate_port_ecc_counter_data(
NSM_TAG_ECC_RAW_ERRORS_LANE_0 + i, 10000000000 + counter_value,
data, &data_len);
assert(rc == NSM_SW_SUCCESS);
rc = encode_aggregate_resp_sample(NSM_TAG_ECC_RAW_ERRORS_LANE_0 + i,
true, data, data_len, nsm_sample,
&consumed_len);
assert(rc == NSM_SW_SUCCESS);
response.insert(response.end(), sample.begin(),
std::next(sample.begin(), consumed_len));
}
return response;
}
} // namespace MockupResponder