* Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
* ubs-engine is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "ubse_urma_controller_api.h"
#include <netinet/in.h>
#include <securec.h>
#include "ubse_api_server_module.h"
#include "ubse_com_module.h"
#include "ubse_conf.h"
#include "ubse_context.h"
#include "ubse_election.h"
#include "ubse_logger.h"
#include "ubse_pack_util.h"
#include "ubse_serial_util.h"
#include "ubse_urma_controller.h"
#include "ubse_urma_controller_qos.h"
namespace ubse::urmaController {
using namespace ubse::common::def;
using namespace ubse::context;
using namespace api::server;
using namespace ubse::log;
using namespace ubse::utils;
using namespace ubse::election;
using namespace ubse::com;
using namespace ubse::serial;
using namespace ubse::config;
using namespace ubse::urma;
UBSE_DEFINE_THIS_MODULE("ubse");
const uint32_t UBSE_URMA_NAME_MAX = 32;
const uint32_t UBSE_MAX_URMA_PATH_LENGTH = 64;
const size_t MAX_BUFFER_SIZE = 10 * 1024;
const std::string URMA_PERMISSION = "urma";
bool IsUrmaApiSupported()
{
if (UbseIsUrmaSupported()) {
return true;
}
UBSE_LOG_WARN << "URMA feature is unsupported.";
return false;
}
size_t UbseStringCalcSize(const std::string& str, size_t maxLen)
{
size_t len = 0;
len += sizeof(uint32_t);
len += std::min(maxLen, str.size());
return len;
}
UbseResult LocalDevPack(std::vector<std::string>& nameInfos, std::vector<uint32_t> status,
std::vector<uint64_t>& hwResIds, UbseIpcMessage& response)
{
if (nameInfos.size() != status.size() || status.size() != hwResIds.size()) {
UBSE_LOG_ERROR << "nameInfos, status and hwResIds size mismatch";
return UBSE_ERROR_INVAL;
}
size_t infoSize = nameInfos.size();
size_t rspSize = sizeof(uint32_t);
for (auto& s : nameInfos) {
rspSize += UbseStringCalcSize(s, UBSE_URMA_NAME_MAX - 1) + sizeof(uint32_t) + sizeof(uint64_t);
}
response.buffer = new (std::nothrow) uint8_t[rspSize];
response.length = rspSize;
if (response.buffer == nullptr) {
UBSE_LOG_ERROR << "Failed to allocate response buffer for size=" << rspSize;
return UBSE_ERROR_SERIALIZE_FAILED;
}
UbsePackUtil packUtil(response.buffer, response.length);
if (!packUtil.UbsePackUint32(static_cast<uint32_t>(infoSize))) {
UBSE_LOG_ERROR << "Failed to pack infoSize=" << infoSize;
return UBSE_ERROR_SERIALIZE_FAILED;
}
for (size_t i = 0; i < nameInfos.size(); i++) {
if (!packUtil.UbsePackString(nameInfos[i], UBSE_URMA_NAME_MAX - 1)) {
UBSE_LOG_ERROR << "Failed to pack nameInfo[" << i << "]=" << nameInfos[i];
return UBSE_ERROR_SERIALIZE_FAILED;
}
if (!packUtil.UbsePackUint32(status[i])) {
UBSE_LOG_ERROR << "Failed to pack status[" << i << "]=" << status[i];
return UBSE_ERROR_SERIALIZE_FAILED;
}
if (!packUtil.UbsePackUint64(hwResIds[i])) {
UBSE_LOG_ERROR << "Failed to pack hwResIds[" << i << "]=" << hwResIds[i];
return UBSE_ERROR_SERIALIZE_FAILED;
}
}
return UBSE_OK;
}
UbseResult QosGetPack(std::vector<EtsQosConfig>& configs, UbseIpcMessage& response)
{
uint32_t itemCount = static_cast<uint32_t>(configs.size());
size_t rspSize = sizeof(uint32_t) + itemCount * (sizeof(uint32_t) + sizeof(uint32_t));
response.buffer = new (std::nothrow) uint8_t[rspSize];
response.length = rspSize;
if (response.buffer == nullptr) {
UBSE_LOG_ERROR << "Failed to allocate response buffer for size=" << rspSize;
return UBSE_ERROR_SERIALIZE_FAILED;
}
UbsePackUtil packUtil(response.buffer, response.length);
if (!packUtil.UbsePackUint32(itemCount)) {
UBSE_LOG_ERROR << "Failed to pack itemCount=" << itemCount;
delete[] response.buffer;
response.buffer = nullptr;
return UBSE_ERROR_SERIALIZE_FAILED;
}
for (const auto& config : configs) {
uint32_t priorityValue = static_cast<uint32_t>(config.priority);
uint32_t bandwidthGbps = config.bandwidth / NO_1000;
if (!packUtil.UbsePackUint32(priorityValue) || !packUtil.UbsePackUint32(bandwidthGbps)) {
UBSE_LOG_ERROR << "Failed to pack qos config";
delete[] response.buffer;
response.buffer = nullptr;
return UBSE_ERROR_SERIALIZE_FAILED;
}
}
return UBSE_OK;
}
UbseResult UbseUrmaControllerApi::Register()
{
auto ubse_api_server_module = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (ubse_api_server_module == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
auto ret = ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_CLI_DEV_GET, UbseUrmaDevGetByFilter);
ret |=
ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_DEV_ALLOC, UbseUrmaDevAlloc, URMA_PERMISSION);
ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_DEV_FREE, UbseUrmaDevFree, URMA_PERMISSION);
ret |=
ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_DEV_GET, UbseUrmaDevGetLocal, URMA_PERMISSION);
ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_QOS_CREATE, UbseUrmaQosCreateNative,
URMA_PERMISSION);
ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_QOS_GET, UbseUrmaQosQueryNative,
URMA_PERMISSION);
ret |=
ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_QOS_DELETE, UbseUrmaQosDelete, URMA_PERMISSION);
ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_CLI_QOS_CREATE, UbseUrmaQosCreateStream);
ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_CLI_QOS_GET, UbseUrmaQosQueryStream);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "Registration of Urma Controller-API failed," << FormatRetCode(ret);
return ret;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaQosCreateStream(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (req.buffer == nullptr) {
UBSE_LOG_ERROR << "UbseUrmaQosCreateStream request info is null.";
return UBSE_ERROR_NULLPTR;
}
UbseDeSerialization deserializer(req.buffer, req.length);
uint32_t itemCount;
deserializer >> itemCount;
if (!deserializer.Check() || itemCount == NO_0 || itemCount > NO_2) {
UBSE_LOG_ERROR << "Failed to deserialize request parameters, itemCount=" << itemCount;
return UBSE_ERROR_DESERIALIZE_FAILED;
}
std::vector<EtsQosConfig> configs;
configs.reserve(itemCount);
for (uint32_t i = 0; i < itemCount; ++i) {
EtsQosConfig config;
uint32_t priorityValue;
deserializer >> priorityValue >> config.bandwidth;
config.bandwidth *= NO_1000;
if (!deserializer.Check()) {
UBSE_LOG_ERROR << "Failed to deserialize EtsQosConfig at index " << i;
return UBSE_ERROR_DESERIALIZE_FAILED;
}
config.priority = static_cast<EtsPriority>(priorityValue);
configs.push_back(std::move(config));
}
uint32_t ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosCreate(configs);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosCreate failed," << FormatRetCode(ret);
return ret;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {nullptr, 0};
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaQosCreateStream response send failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaQosQueryStream(const UbseIpcMessage& req, const UbseRequestContext& context)
{
std::vector<EtsQosConfig> configs;
auto ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosQuery(configs);
if (ret != UBSE_OK && ret != UBSE_URMACONTRL_ERROR_ETS_TEMPLATE_NOT_APPLIED) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosGet failed," << FormatRetCode(ret);
return ret;
}
UbseSerialization serializer;
uint32_t itemCount = static_cast<uint32_t>(configs.size());
serializer << itemCount;
for (const auto& config : configs) {
uint32_t priorityValue = static_cast<uint32_t>(config.priority);
uint32_t bandwidthGbps = config.bandwidth / NO_1000;
serializer << priorityValue << bandwidthGbps;
}
if (!serializer.Check()) {
UBSE_LOG_ERROR << "Failed to serialize response";
return UBSE_ERROR_SERIALIZE_FAILED;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {serializer.GetBuffer(), static_cast<uint32_t>(serializer.GetLength())};
auto sendRet = apiServerModule->SendResponse(ret, context.requestId, response);
if (sendRet != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaQosQueryStream response send failed," << FormatRetCode(sendRet);
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaQosDelete(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (req.buffer != nullptr || req.length != 0) {
UBSE_LOG_ERROR << "UbseUrmaQosDelete should not have request data.";
return UBSE_ERR_INVALID_ARG;
}
uint32_t ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosDelete();
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosDelete failed," << FormatRetCode(ret);
return ret;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {nullptr, 0};
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaQosDelete response send failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t ParseUrmaDevGetRequest(const UbseIpcMessage& req, uint32_t& nodeId, std::vector<std::string>& deviceNameList)
{
uint32_t deviceListSize;
if (req.buffer == nullptr) {
UBSE_LOG_ERROR << "Ubse Urma Dev Get IPC request buffer is null.";
return UBSE_ERROR_NULLPTR;
}
UbseDeSerialization out{req.buffer, req.length};
out >> nodeId >> deviceListSize;
if (!out.Check() || deviceListSize > NO_1024) {
UBSE_LOG_ERROR << "Failed to deserialize basic parameters (nodeId, urmaType, deviceListSize), deviceListSize="
<< deviceListSize;
return UBSE_ERROR_DESERIALIZE_FAILED;
}
deviceNameList.clear();
deviceNameList.reserve(deviceListSize);
for (uint32_t i = 0; i < deviceListSize; ++i) {
std::string deviceName;
out >> deviceName;
UBSE_LOG_INFO << "deviceName =" << deviceName;
if (!out.Check()) {
UBSE_LOG_ERROR << "Failed to deserialize device name at index " << i;
return UBSE_ERROR_DESERIALIZE_FAILED;
}
deviceNameList.push_back(std::move(deviceName));
}
UBSE_LOG_INFO << "deviceListSize =" << deviceNameList.size();
if (!out.Check()) {
UBSE_LOG_ERROR << "Deserialization check failed after reading all device names";
return UBSE_ERROR_DESERIALIZE_FAILED;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaDevGetByFilter(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (!IsUrmaApiSupported()) {
return UBSE_ERR_NOT_SUPPORTED;
}
uint32_t nodeId{};
std::vector<std::string> deviceNameList;
uint32_t ret = ParseUrmaDevGetRequest(req, nodeId, deviceNameList);
if (ret != UBSE_OK) {
return ret;
}
std::vector<UbseUrmaDevBrief> urmaInfo;
ret = UbseUrmaController::GetInstance().UbseGetUrmaDevsByNodeId(nodeId, urmaInfo);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseGetUrmaDevsByNodeId failed," << FormatRetCode(ret);
return ret;
}
if (!deviceNameList.empty()) {
std::unordered_set<std::string> allowedDevices(deviceNameList.begin(), deviceNameList.end());
std::vector<UbseUrmaDevBrief> filtered;
filtered.reserve(urmaInfo.size());
for (const auto& info : urmaInfo) {
if (allowedDevices.find(info.urmaName) != allowedDevices.end()) {
filtered.push_back(info);
}
}
urmaInfo = std::move(filtered);
}
UbseSerialization ubse_req_serial;
const auto urmaSize = static_cast<uint32_t>(urmaInfo.size());
ubse_req_serial << urmaSize;
for (auto& i : urmaInfo) {
const auto urmaState = static_cast<uint32_t>(i.state);
const auto urmaType = static_cast<uint32_t>(i.bondingType);
ubse_req_serial << i.urmaName << urmaType << i.devEid << i.feNames << i.feEids << urmaState;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {ubse_req_serial.GetBuffer(), static_cast<uint32_t>(ubse_req_serial.GetLength())};
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaDevGetByFilter response send failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
UbseResult AllocRspPack(UbseUrmaDevPath& pathInfos, UbseIpcMessage& response)
{
if (pathInfos.vfePaths.size() != NO_2) {
UBSE_LOG_ERROR << "vfe path is not equal to 2";
return UBSE_ERROR;
}
auto bufferSize = UbseStringCalcSize(pathInfos.bondingPath, UBSE_MAX_URMA_PATH_LENGTH - 1);
for (const auto& path : pathInfos.vfePaths) {
bufferSize += UbseStringCalcSize(path, UBSE_MAX_URMA_PATH_LENGTH - 1);
}
bufferSize += UbseStringCalcSize(pathInfos.bondingEid, UBSE_MAX_URMA_PATH_LENGTH - 1);
if (bufferSize > MAX_BUFFER_SIZE) {
UBSE_LOG_ERROR << "Requested buffer size " << bufferSize << " exceeds limit " << MAX_BUFFER_SIZE;
return UBSE_ERROR_INVAL;
}
response.buffer = new (std::nothrow) uint8_t[bufferSize];
if (response.buffer == nullptr) {
return UBSE_ERROR_NULLPTR;
}
response.length = bufferSize;
UbsePackUtil packUtil(response.buffer, response.length);
if (!packUtil.UbsePackString(pathInfos.bondingPath, UBSE_MAX_URMA_PATH_LENGTH - 1)) {
return UBSE_ERROR;
}
if (!packUtil.UbsePackString(pathInfos.vfePaths[0], UBSE_MAX_URMA_PATH_LENGTH - 1)) {
return UBSE_ERROR;
}
if (!packUtil.UbsePackString(pathInfos.vfePaths[1], UBSE_MAX_URMA_PATH_LENGTH - 1)) {
return UBSE_ERROR;
}
if (!packUtil.UbsePackString(pathInfos.bondingEid, UBSE_MAX_URMA_PATH_LENGTH - 1)) {
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaDevAlloc(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (!IsUrmaApiSupported()) {
return UBSE_ERR_NOT_SUPPORTED;
}
if (req.buffer == nullptr) {
UBSE_LOG_ERROR << "UbseUrmaDevAlloc IPC request info is null.";
return UBSE_ERROR_NULLPTR;
}
const char* str = reinterpret_cast<const char*>(req.buffer);
uint32_t strlen = strnlen(str, UBSE_URMA_NAME_MAX);
if (strlen >= UBSE_URMA_NAME_MAX) {
return UBSE_URMACONTRL_ERROR_DEV_NAME_INVALID;
}
std::string name(str, strlen);
UbseUrmaDevPath devInfos;
uint32_t ret = UbseUrmaController::GetInstance().UbseAllocUrmaDev(name, devInfos);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseAllocUrmaDev failed," << FormatRetCode(ret);
return ret;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {nullptr, 0};
ret = AllocRspPack(devInfos, response);
if (ret != UBSE_OK) {
delete[] response.buffer;
response.buffer = nullptr;
UBSE_LOG_ERROR << "AllocRspPack failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
delete[] response.buffer;
response.buffer = nullptr;
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaDevAlloc response send failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaDevFree(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (!IsUrmaApiSupported()) {
return UBSE_ERR_NOT_SUPPORTED;
}
if (req.buffer == nullptr) {
UBSE_LOG_ERROR << "UbseUrmaDevFree IPC request info is null.";
return UBSE_ERROR_NULLPTR;
}
const char* str = reinterpret_cast<const char*>(req.buffer);
uint32_t strlen = strnlen(str, UBSE_URMA_NAME_MAX);
if (strlen >= UBSE_URMA_NAME_MAX) {
return UBSE_ERROR;
}
std::string name(str, strlen);
uint32_t ret = UbseUrmaController::GetInstance().UbseFreeUrmaDev(name);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseFreeUrmaDev failed," << FormatRetCode(ret);
return ret;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {nullptr, 0};
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaDevFree response send failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaDevGetLocal(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (!IsUrmaApiSupported()) {
return UBSE_ERR_NOT_SUPPORTED;
}
if (req.buffer == nullptr) {
UBSE_LOG_ERROR << "UbseUrmaDevGetLocal IPC request info is null.";
return UBSE_ERROR_NULLPTR;
}
std::vector<std::string> nameInfos;
std::vector<uint32_t> status;
std::vector<uint64_t> hwResIds;
uint32_t ret = UbseUrmaController::GetInstance().UbseUrmaGetDevs(nameInfos, status, hwResIds);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaGetDevs failed," << FormatRetCode(ret);
return ret;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {nullptr, 0};
ret = LocalDevPack(nameInfos, status, hwResIds, response);
if (ret != UBSE_OK) {
delete[] response.buffer;
response.buffer = nullptr;
UBSE_LOG_ERROR << "LocalDevPack failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
delete[] response.buffer;
response.buffer = nullptr;
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaDevGetLocal response send failed." << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t UbseUrmaQosCreateReqUnpack(const uint8_t* buffer, uint32_t len, std::vector<EtsQosConfig>& configs)
{
if (buffer == nullptr) {
return UBSE_ERROR_NULLPTR;
}
const uint8_t* ptr = buffer;
uint32_t remaining = len;
if (remaining < sizeof(uint32_t)) {
UBSE_LOG_ERROR << "Buffer too small for itemCount";
return UBSE_ERROR_DESERIALIZE_FAILED;
}
uint32_t itemCount;
errno_t err = memcpy_s(&itemCount, sizeof(uint32_t), ptr, sizeof(uint32_t));
if (err != EOK) {
UBSE_LOG_ERROR << "Failed to copy itemCount";
return UBSE_ERROR_DESERIALIZE_FAILED;
}
ptr += sizeof(uint32_t);
remaining -= sizeof(uint32_t);
if (itemCount > NO_2) {
UBSE_LOG_ERROR << "Invalid itemCount=" << itemCount;
return UBSE_ERROR_DESERIALIZE_FAILED;
}
configs.reserve(itemCount);
for (uint32_t i = 0; i < itemCount; ++i) {
if (remaining < sizeof(uint32_t) * NO_2) {
UBSE_LOG_ERROR << "Buffer too small for EtsQosConfig[" << i << "]";
return UBSE_ERROR_DESERIALIZE_FAILED;
}
EtsQosConfig config;
uint32_t priorityValue;
err = memcpy_s(&priorityValue, sizeof(uint32_t), ptr, sizeof(uint32_t));
if (err != EOK) {
UBSE_LOG_ERROR << "Failed to copy priority";
return UBSE_ERROR_DESERIALIZE_FAILED;
}
ptr += sizeof(uint32_t);
uint32_t bandwidthValue;
err = memcpy_s(&bandwidthValue, sizeof(uint32_t), ptr, sizeof(uint32_t));
if (err != EOK) {
UBSE_LOG_ERROR << "Failed to copy bandwidth";
return UBSE_ERROR_DESERIALIZE_FAILED;
}
config.bandwidth = bandwidthValue * NO_1000;
config.priority = static_cast<EtsPriority>(priorityValue);
ptr += sizeof(uint32_t);
remaining -= sizeof(uint32_t) * NO_2;
configs.push_back(std::move(config));
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaQosCreateNative(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (req.buffer == nullptr) {
UBSE_LOG_ERROR << "UbseUrmaQosCreateNative request info is null.";
return UBSE_ERROR_NULLPTR;
}
std::vector<EtsQosConfig> configs;
auto ret = UbseUrmaQosCreateReqUnpack(req.buffer, req.length, configs);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "Failed to unpack QosCreate request, ret=" << ret;
return ret;
}
ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosCreate(configs);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosCreate failed," << FormatRetCode(ret);
return ret;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
return UBSE_ERROR_NULLPTR;
}
UbseIpcMessage response = {nullptr, 0};
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaQosCreateNative response send failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
uint32_t UbseUrmaControllerApi::UbseUrmaQosQueryNative(const UbseIpcMessage& req, const UbseRequestContext& context)
{
if (req.buffer != nullptr || req.length != 0) {
UBSE_LOG_ERROR << "UbseUrmaQosQueryNative should not have request data.";
return UBSE_ERR_INVALID_ARG;
}
std::vector<EtsQosConfig> configs;
auto ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosQuery(configs);
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosQuery failed," << FormatRetCode(ret);
return ret;
}
UbseIpcMessage response = {nullptr, 0};
ret = QosGetPack(configs, response);
if (ret != UBSE_OK) {
return ret;
}
auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
if (apiServerModule == nullptr) {
UBSE_LOG_ERROR << "Get api server module failed";
delete[] response.buffer;
response.buffer = nullptr;
return UBSE_ERROR_NULLPTR;
}
ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
delete[] response.buffer;
response.buffer = nullptr;
if (ret != UBSE_OK) {
UBSE_LOG_ERROR << "UbseUrmaQosQueryNative response send failed," << FormatRetCode(ret);
return UBSE_ERROR;
}
return UBSE_OK;
}
}