Commit ff5a1a97 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen
Browse files

Add smf

parent d426b2e3
......@@ -83,15 +83,39 @@ void NFInstanceIDDocumentApiImpl::update_nf_instance(
const std::string &nfInstanceID, const std::vector<PatchItem> &patchItem,
Pistache::Http::ResponseWriter &response) {
Logger::nrf_sbi().info(
"Got a request to register an NF instance, Instance ID: %s",
"Got a request to update an NF instance, Instance ID: %s",
nfInstanceID.c_str());
int http_code = 0;
m_nrf_app->handle_update_nf_instance(nfInstanceID, patchItem, http_code, 1);
ProblemDetails problem_details = { };
m_nrf_app->handle_update_nf_instance(nfInstanceID, patchItem, http_code, 1,
problem_details);
nlohmann::json json_data = { };
//to_json(json_data, nf_profile);
response.send(Pistache::Http::Code::Ok, json_data.dump().c_str());
std::string content_type = "application/json";
std::shared_ptr<nrf_profile> profile = m_nrf_app->find_nf_profile(
nfInstanceID);
if (http_code != HTTP_STATUS_CODE_200_OK) {
to_json(json_data, problem_details);
content_type = "application/problem+json";
} else {
//convert the profile to Json
profile.get()->to_json(json_data);
}
Logger::nrf_sbi().debug("Json data: %s", json_data.dump().c_str());
//content type
response.headers().add < Pistache::Http::Header::ContentType
> (Pistache::Http::Mime::MediaType(content_type));
//Location header
response.headers().add < Pistache::Http::Header::Location
> (m_address + base + nrf_cfg.sbi_api_version + "/nf-instances/"
+ nfInstanceID);
response.send(Pistache::Http::Code(http_code), json_data.dump().c_str());
}
}
......
......@@ -126,4 +126,5 @@ typedef struct smf_info_s {
std::vector<snssai_smf_info_item_t> snssai_smf_info_list;
} smf_info_t;
#endif
......@@ -131,6 +131,29 @@ bool api_conv::profile_api_to_amf_profile(
}
break;
case NF_TYPE_SMF: {
Logger::nrf_app().debug("............SMF profile, SMF Info");
profile.get()->set_nf_type(NF_TYPE_SMF);
smf_info_t info = { };
SmfInfo smf_info_api = api_profile.getSmfInfo();
for (auto s : smf_info_api.getSNssaiSmfInfoList()) {
snssai_smf_info_item_t snssai = { };
snssai.snssai.sD = s.getSNssai().getSd();
snssai.snssai.sST = s.getSNssai().getSst();
Logger::nrf_app().debug(".......................NSSAI SD: %s, SST: %d",
snssai.snssai.sD.c_str(), snssai.snssai.sST);
for (auto d : s.getDnnSmfInfoList()) {
dnn_smf_info_item_t dnn = {};
dnn.dnn = d.getDnn();
snssai.dnn_smf_info_list.push_back(dnn);
Logger::nrf_app().debug("......................DNN: %s",
dnn.dnn.c_str());
}
info.snssai_smf_info_list.push_back(snssai);
}
(std::static_pointer_cast < smf_profile > (profile)).get()->add_smf_info(
info);
}
break;
......@@ -207,9 +230,9 @@ patch_op_type_t api_conv::string_to_patch_operation(const std::string &str) {
return PATCH_OP_UNKNOWN;
}
bool api_conv::validate_uuid(const std::string &str) {
//should be verified with Capital letter
static const std::regex e("[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}");
return regex_match(str, e);
static const std::regex e(
"[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}");
return regex_match(str, e);
}
......@@ -82,7 +82,7 @@ void nrf_app::handle_register_nf_instance(
break;
case NF_TYPE_SMF: {
//TODO:
sn = std::make_shared<smf_profile>();
}
break;
......@@ -102,23 +102,8 @@ void nrf_app::handle_register_nf_instance(
//add to the DB
add_nf_profile(nf_instance_id, sn);
Logger::nrf_app().debug("Added/Updated NF Profile to the DB");
switch (type) {
case NF_TYPE_AMF: {
std::static_pointer_cast < amf_profile > (sn).get()->display();
}
break;
case NF_TYPE_SMF: {
std::static_pointer_cast < smf_profile > (sn).get()->display();
}
break;
default: {
sn.get()->display();
}
}
//display the info
sn.get()->display();
} else {
//error
Logger::nrf_app().warn(
......@@ -131,10 +116,10 @@ void nrf_app::handle_register_nf_instance(
}
//------------------------------------------------------------------------------
void nrf_app::handle_update_nf_instance(const std::string &nf_instance_id,
const std::vector<PatchItem> &patchItem,
int &http_code,
const uint8_t http_version) {
void nrf_app::handle_update_nf_instance(
const std::string &nf_instance_id, const std::vector<PatchItem> &patchItem,
int &http_code, const uint8_t http_version,
oai::nrf::model::ProblemDetails &problem_details) {
Logger::nrf_app().info("Handle Update NF Instance request (HTTP version %d)",
http_version);
......@@ -142,81 +127,73 @@ void nrf_app::handle_update_nf_instance(const std::string &nf_instance_id,
//Find the profile corresponding to the instance ID
std::shared_ptr<nrf_profile> sn = { };
sn = find_nf_profile(nf_instance_id);
bool op_success = true;
if (sn.get() != nullptr) {
for (auto p : patchItem) {
patch_op_type_t op = api_conv::string_to_patch_operation(p.getOp());
//Verify Path
if ((p.getPath().substr(0, 1).compare("/") != 0)
or (p.getPath().length() < 2)) {
Logger::nrf_app().warn("Bad value for operation path: %s ",
p.getPath().c_str());
http_code = HTTP_STATUS_CODE_400_BAD_REQUEST;
problem_details.setCause(
protocol_application_error_e2str[MANDATORY_IE_INCORRECT]);
return;
}
std::string path = p.getPath().substr(1);
switch (op) {
case PATCH_OP_REPLACE: {
switch (sn.get()->get_nf_type()) {
case NF_TYPE_AMF: {
Logger::nrf_app().debug("Update a AMF profile");
if (std::static_pointer_cast < amf_profile
> (sn)->replace_profile_info(path, p.getValue()))
update_nf_profile(nf_instance_id, sn);
}
break;
case NF_TYPE_SMF: {
}
break;
default: {
Logger::nrf_app().warn("Unknown NF type!");
}
if (sn.get()->replace_profile_info(path, p.getValue())) {
update_nf_profile(nf_instance_id, sn);
http_code = HTTP_STATUS_CODE_200_OK;
} else {
op_success = false;
}
}
case PATCH_OP_ADD: {
switch (sn.get()->get_nf_type()) {
case NF_TYPE_AMF: {
Logger::nrf_app().debug("Update a AMF profile");
if (std::static_pointer_cast < amf_profile
> (sn)->add_profile_info(path, p.getValue()))
update_nf_profile(nf_instance_id, sn);
}
break;
case NF_TYPE_SMF: {
}
break;
default: {
Logger::nrf_app().warn("Unknown NF type!");
}
break;
case PATCH_OP_ADD: {
if (sn.get()->add_profile_info(path, p.getValue())) {
update_nf_profile(nf_instance_id, sn);
http_code = HTTP_STATUS_CODE_200_OK;
} else {
op_success = false;
}
}
case PATCH_OP_REMOVE: {
switch (sn.get()->get_nf_type()) {
case NF_TYPE_AMF: {
Logger::nrf_app().debug("Update a AMF profile");
if (std::static_pointer_cast < amf_profile
> (sn)->remove_profile_info(path))
update_nf_profile(nf_instance_id, sn);
}
break;
case NF_TYPE_SMF: {
}
break;
default: {
Logger::nrf_app().warn("Unknown NF type!");
}
break;
case PATCH_OP_REMOVE: {
if (sn.get()->remove_profile_info(path)) {
update_nf_profile(nf_instance_id, sn);
http_code = HTTP_STATUS_CODE_200_OK;
} else {
op_success = false;
}
}
break;
default: {
Logger::nrf_app().warn("Requested operation is not valid!");
}
}
if (!op_success) {
http_code = HTTP_STATUS_CODE_400_BAD_REQUEST;
problem_details.setCause(
protocol_application_error_e2str[MANDATORY_IE_INCORRECT]);
}
}
} else {
Logger::nrf_app().debug("NF Profile with ID %s does not exit",
nf_instance_id.c_str());
http_code = HTTP_STATUS_CODE_404_NOT_FOUND;
problem_details.setCause(
protocol_application_error_e2str[RESOURCE_URI_STRUCTURE_NOT_FOUND]);
}
}
......@@ -238,7 +215,7 @@ void nrf_app::handle_get_nf_instances(const std::string &nf_type,
}
for (auto profile : profiles) {
(std::static_pointer_cast < amf_profile > (profile)).get()->display();
profile.get()->display();
}
}
......
......@@ -52,16 +52,17 @@ class nrf_app {
/*
* Handle a Register NF Instance request
* @param [const std::string &] nf_instance_id: Instance ID
* @param [const oai::nrf::model::NFProfile &] nf_profile: NF profile
* @param [NFProfile &] nf_profile: NF profile
* @param [int &] http_code: HTTP code used to return to the consumer
* @param [const uint8_t] http_version: HTTP version
* @param [ProblemDetails &] problem_details: Store details of the error
* @return void
*/
void handle_register_nf_instance(
const std::string &nf_instance_id,
const oai::nrf::model::NFProfile &nf_profile, int &http_code,
const NFProfile &nf_profile, int &http_code,
const uint8_t http_version,
oai::nrf::model::ProblemDetails &problem_details);
ProblemDetails &problem_details);
/*
* Handle a Get NF Instance Information
......@@ -81,11 +82,14 @@ class nrf_app {
* @param [const std::vector<PatchItem> &] patchItem: List of modifications need to be applied
* @param [int &] http_code: HTTP code used to return to the consumer
* @param [const uint8_t] http_version: HTTP version
* @param [ProblemDetails &] problem_details: Store details of the error
* @return void
*/
void handle_update_nf_instance(const std::string &nf_instance_id,
const std::vector<PatchItem> &patchItem,
int &http_code, const uint8_t http_version);
void handle_update_nf_instance(
const std::string &nf_instance_id,
const std::vector<PatchItem> &patchItem, int &http_code,
const uint8_t http_version,
ProblemDetails &problem_details);
/*
* Insert a nrf profile
* @param [const std::string &] profile_id: Profile ID
......
......@@ -202,6 +202,7 @@ void nrf_profile::display() {
}
}
//------------------------------------------------------------------------------
bool nrf_profile::replace_profile_info(const std::string &path,
const std::string &value) {
......@@ -227,6 +228,7 @@ bool nrf_profile::replace_profile_info(const std::string &path,
heartBeat_timer = std::stoi(value);
return true;
} catch (const std::exception &err) {
Logger::nrf_app().debug("Bad value!");
return false;
}
}
......@@ -236,6 +238,7 @@ bool nrf_profile::replace_profile_info(const std::string &path,
priority = (uint16_t) std::stoi(value);
return true;
} catch (const std::exception &err) {
Logger::nrf_app().debug("Bad value!");
return false;
}
}
......@@ -245,11 +248,22 @@ bool nrf_profile::replace_profile_info(const std::string &path,
capacity = (uint16_t) std::stoi(value);
return true;
} catch (const std::exception &err) {
Logger::nrf_app().debug("Bad value!");
return false;
}
}
Logger::nrf_app().debug("Member (%s) not found!", path.c_str());
//Replace an array
if (path.compare("ipv4Addresses") == 0) {
Logger::nrf_app().info("Does not support this operation for ipv4Addresses");
return false;
}
if (path.compare("sNssais") == 0) {
Logger::nrf_app().info("Does not support this operation for sNssais");
return false;
}
return false;
}
......@@ -260,6 +274,53 @@ bool nrf_profile::add_profile_info(const std::string &path,
"Add an array element (value, array member), or a new member (value, member): %s, %s",
value.c_str(), path.c_str());
//update an existing member
if (path.compare("nfInstanceName") == 0) {
nf_instance_name = value;
return true;
}
if (path.compare("nfStatus") == 0) {
nf_status = value;
return true;
}
if (path.compare("nfType") == 0) {
nf_type = api_conv::string_to_nf_type(value);
return true;
}
if (path.compare("heartBeatTimer") == 0) {
try {
heartBeat_timer = std::stoi(value);
return true;
} catch (const std::exception &err) {
Logger::nrf_app().debug("Bad value!");
return false;
}
}
if (path.compare("priority") == 0) {
try {
priority = (uint16_t) std::stoi(value);
return true;
} catch (const std::exception &err) {
Logger::nrf_app().debug("Bad value!");
return false;
}
}
if (path.compare("capacity") == 0) {
try {
capacity = (uint16_t) std::stoi(value);
return true;
} catch (const std::exception &err) {
Logger::nrf_app().debug("Bad value!");
return false;
}
}
//add an element to a list
if (path.compare("ipv4Addresses") == 0) {
std::string address = value;
struct in_addr addr4 = { };
......@@ -269,32 +330,25 @@ bool nrf_profile::add_profile_info(const std::string &path,
} else {
Logger::nrf_app().warn("Address conversion: Bad value %s",
util::trim(address).c_str());
return false;
}
Logger::nrf_app().debug("Added IPv4 Addr: %s", address.c_str());
ipv4_addresses.push_back(addr4);
return true;
}
if (path.compare("snssais") == 0) {
//add an element to a list of json object
if (path.compare("sNssais") == 0) {
Logger::nrf_app().info("Does not support this operation for snssais");
return false;
}
if ((path.compare("nfInstanceName") == 0) or (path.compare("nfStatus") == 0)
or (path.compare("nfType") == 0) or (path.compare("heartBeatTimer") == 0)
or (path.compare("priority") == 0) or (path.compare("capacity") == 0)) {
Logger::nrf_app().info("Does not support this operation, member (%s) exit!",
path.c_str());
return false;
}
//add new member
json_data[path] = value;
return true;
return false;
}
//------------------------------------------------------------------------------
bool nrf_profile::remove_profile_info(const std::string &path) {
bool nrf_profile::remove_profile_info(
const std::string &path) {
Logger::nrf_app().debug("Remove an array element or a member: %s",
path.c_str());
......@@ -356,7 +410,7 @@ bool nrf_profile::remove_profile_info(const std::string &path) {
}
}
if (path.find("snssais") != std::string::npos) {
if (path.find("sNssais") != std::string::npos) {
Logger::nrf_app().info("Does not support this operation for snssais");
return false;
}
......@@ -365,6 +419,35 @@ bool nrf_profile::remove_profile_info(const std::string &path) {
return false;
}
//------------------------------------------------------------------------------
void nrf_profile::to_json(nlohmann::json &data) const {
data["nfInstanceId"] = nf_instance_id;
data["nfInstanceName"] = nf_instance_name;
data["nfType"] = nf_type_e2str[nf_type];
data["nfStatus"] = nf_status;
data["heartBeatTimer"] = heartBeat_timer;
//SNSSAIs
data["sNssais"] = nlohmann::json::array();
for (auto s : snssais) {
nlohmann::json tmp = { };
tmp["sst"] = s.sST;
tmp["sd"] = s.sD;
;
data["sNssais"].push_back(tmp);
}
//ipv4_addresses
data["ipv4Addresses"] = nlohmann::json::array();
for (auto address : ipv4_addresses) {
nlohmann::json tmp = inet_ntoa(address);
data["ipv4Addresses"].push_back(tmp);
}
data["priority"] = priority;
data["capacity"] = capacity;
data["json_data"] = json_data;
}
//------------------------------------------------------------------------------
void amf_profile::add_amf_info(const amf_info_t &info) {
amf_info = info;
......@@ -379,40 +462,123 @@ void amf_profile::get_amf_info(amf_info_t &infos) const {
void amf_profile::display() {
nrf_profile::display();
Logger::nrf_app().debug("............AMF Set ID: %s, AMF Region ID: %s",
amf_info.amf_set_id.c_str(),
amf_info.amf_region_id.c_str());
Logger::nrf_app().debug("............AMF Info");
Logger::nrf_app().debug(
".....................AMF Set ID: %s, AMF Region ID: %s",
amf_info.amf_set_id.c_str(), amf_info.amf_region_id.c_str());
for (auto g : amf_info.guami_list) {
Logger::nrf_app().debug("............AMF GUAMI, AMF_ID: %s",
Logger::nrf_app().debug(".....................AMF GUAMI List, AMF_ID: %s",
g.amf_id.c_str());
Logger::nrf_app().debug("....................., PLMN (MCC: %s, MNC: %s)",
g.plmn.mcc.c_str(), g.plmn.mnc.c_str());
Logger::nrf_app().debug(
"........................AMF GUAMI List, PLMN (MCC: %s, MNC: %s)",
g.plmn.mcc.c_str(), g.plmn.mnc.c_str());
}
}
//------------------------------------------------------------------------------
bool amf_profile::replace_profile_info(const std::string &path,
const std::string &value) {
nrf_profile::replace_profile_info(path, value);
//TODO with AMF part
bool result = nrf_profile::replace_profile_info(path, value);
if (result)
return true;
//for AMF info
if (path.compare("amfInfo") == 0) {
Logger::nrf_app().debug("Does not support this operation for amfInfo");
return false;
}
if ((path.compare("nfInstanceId") != 0)
and (path.compare("nfInstanceName") != 0)
and (path.compare("nfType") != 0) and (path.compare("nfStatus") != 0)
and (path.compare("heartBeatTimer") != 0)
and (path.compare("sNssais") != 0)
and (path.compare("ipv4Addresses") != 0)
and (path.compare("priority") != 0) and (path.compare("capacity") != 0)
and (path.compare("priority") != 0) and (path.compare("amfInfo") != 0)) {
Logger::nrf_app().debug("Member (%s) not found!", path.c_str());
return false;
}
return false;
}
//------------------------------------------------------------------------------
bool amf_profile::add_profile_info(const std::string &path,
const std::string &value) {
nrf_profile::add_profile_info(path, value);
//TODO with AMF part
bool result = nrf_profile::add_profile_info(path, value);
if (result)
return true;
//add an element to a list of json object
if (path.compare("amfInfo") == 0) {
Logger::nrf_app().info("Does not support this operation for amfInfo");
return false;
}
if ((path.compare("nfInstanceId") != 0)
and (path.compare("nfInstanceName") != 0)
and (path.compare("nfType") != 0) and (path.compare("nfStatus") != 0)
and (path.compare("heartBeatTimer") != 0)
and (path.compare("sNssais") != 0)
and (path.compare("ipv4Addresses") != 0)
and (path.compare("priority") != 0) and (path.compare("capacity") != 0)
and (path.compare("priority") != 0) and (path.compare("amfInfo") != 0)) {
Logger::nrf_app().debug("Add new member: %s", path.c_str());
//add new member
json_data[path] = value;
return true;
}
return false;
}
//------------------------------------------------------------------------------
bool amf_profile::remove_profile_info(
const std::string &path) {
bool result = nrf_profile::remove_profile_info(path);
if (result)
return true;
//for AMF info
if (path.compare("amfInfo") == 0) {
Logger::nrf_app().debug("Does not support this operation for amfInfo");
return false;
}
if ((path.compare("nfInstanceId") != 0)
and (path.compare("nfInstanceName") != 0)
and (path.compare("nfType") != 0) and (path.compare("nfStatus") != 0)
and (path.compare("heartBeatTimer") != 0)
and (path.compare("sNssais") != 0)
and (path.compare("ipv4Addresses") != 0)
and (path.compare("priority") != 0) and (path.compare("capacity") != 0)
and (path.compare("priority") != 0) and (path.compare("amfInfo") != 0)) {
Logger::nrf_app().debug("Member (%s) not found!", path.c_str());