Commit 1fbe46ac authored by Stefan Spettel's avatar Stefan Spettel

feat(pcf): Added individual sm policy handling (only remove, not update)

Signed-off-by: default avatarStefan Spettel <stefan.spettel@eurecom.fr>
parent dd0fcfc4
/**
* Npcf_SMPolicyControl API
* Session Management Policy Control Service © 2020, 3GPP Organizational
* Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.1.alpha-5
*
*
* NOTE: This class is auto generated by OpenAPI Generator
* (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
* the class manually.
*/
#include "SmPolicyControl.h"
#include "Helpers.h"
#include <sstream>
namespace oai {
namespace smf_server {
namespace model {
SmPolicyControl::SmPolicyControl() {}
void SmPolicyControl::validate() const {
std::stringstream msg;
if (!validate(msg)) {
// throw
// org::openapitools::server::helpers::ValidationException(msg.str());
}
}
bool SmPolicyControl::validate(std::stringstream& msg) const {
return validate(msg, "");
}
bool SmPolicyControl::validate(
std::stringstream& msg, const std::string& pathPrefix) const {
bool success = true;
const std::string _pathPrefix =
pathPrefix.empty() ? "SmPolicyControl" : pathPrefix;
return success;
}
bool SmPolicyControl::operator==(const SmPolicyControl& rhs) const {
return
(getContext() == rhs.getContext()) &&
(getPolicy() == rhs.getPolicy())
;
}
bool SmPolicyControl::operator!=(const SmPolicyControl& rhs) const {
return !(*this == rhs);
}
void to_json(nlohmann::json& j, const SmPolicyControl& o) {
j = nlohmann::json();
j["context"] = o.m_Context;
j["policy"] = o.m_Policy;
}
void from_json(const nlohmann::json& j, SmPolicyControl& o) {
j.at("context").get_to(o.m_Context);
j.at("policy").get_to(o.m_Policy);
}
SmPolicyContextData SmPolicyControl::getContext() const {
return m_Context;
}
void SmPolicyControl::setContext(SmPolicyContextData const& value) {
m_Context = value;
}
SmPolicyDecision SmPolicyControl::getPolicy() const {
return m_Policy;
}
void SmPolicyControl::setPolicy(SmPolicyDecision const& value) {
m_Policy = value;
}
} // namespace model
} // namespace smf_server
} // namespace oai
/**
* Npcf_SMPolicyControl API
* Session Management Policy Control Service © 2020, 3GPP Organizational
* Partners (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 1.1.1.alpha-5
*
*
* NOTE: This class is auto generated by OpenAPI Generator
* (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
* the class manually.
*/
/*
* SmPolicyControl.h
*
*
*/
#ifndef SmPolicyControl_H_
#define SmPolicyControl_H_
#include "SmPolicyDecision.h"
#include "SmPolicyContextData.h"
#include <nlohmann/json.hpp>
namespace oai {
namespace smf_server {
namespace model {
/// <summary>
///
/// </summary>
class SmPolicyControl {
public:
SmPolicyControl();
virtual ~SmPolicyControl() = default;
/// <summary>
/// Validate the current data in the model. Throws a ValidationException on
/// failure.
/// </summary>
void validate() const;
/// <summary>
/// Validate the current data in the model. Returns false on error and writes
/// an error message into the given stringstream.
/// </summary>
bool validate(std::stringstream& msg) const;
/// <summary>
/// Helper overload for validate. Used when one model stores another model and
/// calls it's validate. Not meant to be called outside that case.
/// </summary>
bool validate(std::stringstream& msg, const std::string& pathPrefix) const;
bool operator==(const SmPolicyControl& rhs) const;
bool operator!=(const SmPolicyControl& rhs) const;
/////////////////////////////////////////////
/// SmPolicyControl members
/// <summary>
///
/// </summary>
SmPolicyContextData getContext() const;
void setContext(SmPolicyContextData const& value);
/// <summary>
///
/// </summary>
SmPolicyDecision getPolicy() const;
void setPolicy(SmPolicyDecision const& value);
friend void to_json(nlohmann::json& j, const SmPolicyControl& o);
friend void from_json(const nlohmann::json& j, SmPolicyControl& o);
protected:
SmPolicyContextData m_Context;
SmPolicyDecision m_Policy;
};
} // namespace model
} // namespace smf_server
} // namespace oai
#endif /* SmPolicyControl_H_ */
......@@ -596,7 +596,7 @@ void to_json(nlohmann::json& j, const SmPolicyUpdateContextData& o) {
// if (o.creditManageStatusIsSet())
// j["creditManageStatus"] = o.m_CreditManageStatus;
// if (o.servNfIdIsSet()) j["servNfId"] = o.m_ServNfId;
// if (o.traceReqIsSet()) j["traceReq"] = o.m_TraceReq;
if (o.traceReqIsSet()) j["traceReq"] = o.m_TraceReq;
// if (o.maPduIndIsSet()) j["maPduInd"] = o.m_MaPduInd;
// if (o.atsssCapabIsSet()) j["atsssCapab"] = o.m_AtsssCapab;
// if (o.tsnBridgeInfoIsSet()) j["tsnBridgeInfo"] = o.m_TsnBridgeInfo;
......@@ -767,10 +767,12 @@ void from_json(const nlohmann::json& j, SmPolicyUpdateContextData& o) {
j.at("servNfId").get_to(o.m_ServNfId);
o.m_ServNfIdIsSet = true;
}
*/
if (j.find("traceReq") != j.end()) {
j.at("traceReq").get_to(o.m_TraceReq);
o.m_TraceReqIsSet = true;
}
/*
if (j.find("maPduInd") != j.end()) {
j.at("maPduInd").get_to(o.m_MaPduInd);
o.m_MaPduIndIsSet = true;
......@@ -1309,6 +1311,7 @@ bool SmPolicyUpdateContextData::servNfIdIsSet() const {
void SmPolicyUpdateContextData::unsetServNfId() {
m_ServNfIdIsSet = false;
}
*/
TraceData SmPolicyUpdateContextData::getTraceReq() const {
return m_TraceReq;
}
......@@ -1322,6 +1325,7 @@ bool SmPolicyUpdateContextData::traceReqIsSet() const {
void SmPolicyUpdateContextData::unsetTraceReq() {
m_TraceReqIsSet = false;
}
/*
MaPduIndication SmPolicyUpdateContextData::getMaPduInd() const {
return m_MaPduInd;
}
......
......@@ -55,6 +55,7 @@
#include "EventNotification.h"
#include "SmPolicyContextData.h"
#include "SmPolicyDecision.h"
#include "SmPolicyDeleteData.h"
#include "PlmnId.h"
#include "Snssai.h"
#include "PduSessionType.h"
......@@ -2234,8 +2235,13 @@ bool smf_context::handle_pdu_session_release_complete(
supi64, sm_context_request.get()->req.get_pdu_session_id(),
sm_context_request.get()->http_version);
// TODO: if dynamic PCC applied, SMF invokes an SM Policy Association
// Termination
// SM Policy Association termination
if (sp->policy_ptr) {
oai::smf_server::model::SmPolicyDeleteData delete_data;
// TODO set data such as release cause, usage reports etc
n7::smf_n7::get_instance().remove_sm_policy_association(
*sp->policy_ptr, delete_data);
}
// TODO: SMF un-subscribes from Session Management Subscription data
// changes notification from UDM by invoking Numd_SDM_Unsubscribe
......
......@@ -34,7 +34,7 @@
#include "3gpp_29.500.h"
#include "ProblemDetails.h"
#include "uint_generator.hpp"
#include "SmPolicyControl.h"
#include <regex>
using namespace smf;
......@@ -112,6 +112,31 @@ sm_policy_status_code smf_n7::create_sm_policy_association(
return res;
}
sm_policy_status_code smf_n7::remove_sm_policy_association(
const policy_association& association,
const SmPolicyDeleteData& delete_data) {
folly::AtomicHashMap<uint32_t, std::shared_ptr<policy_storage>>::iterator it =
policy_storages.find(association.pcf_id);
if (it == policy_storages.end()) {
return sm_policy_status_code::PCF_NOT_AVAILABLE;
}
return it->second->remove_policy_association(association, delete_data);
}
sm_policy_status_code smf_n7::update_sm_policy_association(
policy_association& association,
const SmPolicyUpdateContextData& update_data) {
folly::AtomicHashMap<uint32_t, std::shared_ptr<policy_storage>>::iterator it =
policy_storages.find(association.pcf_id);
if (it == policy_storages.end()) {
return sm_policy_status_code::PCF_NOT_AVAILABLE;
}
return it->second->update_policy_association(update_data, association);
}
smf_n7::~smf_n7() {
Logger::smf_n7().info("Deleting SMF N7 instance...");
}
......@@ -195,15 +220,14 @@ bool smf_pcf_client::discover_pcf_from_config_file(
}
}
sm_policy_status_code smf_pcf_client::create_policy_association(
policy_association& association) {
nlohmann::json json_data;
to_json(json_data, association.context);
Logger::smf_n7().info("Sending PCF SM policy association creation request");
std::string response_data;
std::string response_headers;
http_status_code_e smf_pcf_client::send_request(
const std::string& uri, const std::string& body, std::string& response_body,
std::string& response_headers, std::string method,
bool use_response_headers) {
if (uri == "") {
Logger::smf_n7().warn("PCF URI is not set");
return http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR;
}
// generate a promise for the curl handle
uint32_t promise_id = smf_sbi_inst->generate_promise_id();
......@@ -215,23 +239,44 @@ sm_policy_status_code smf_pcf_client::create_policy_association(
boost::shared_future<uint32_t> f;
f = p->get_future();
smf_sbi_inst->add_promise(promise_id, p);
bool res = false;
// Create a new curl easy handle and add to the multi handle
if (!smf_sbi_inst->curl_create_handle(
root_uri, json_data.dump(), response_data, response_headers, pid_ptr,
"POST", smf_cfg.http_version)) {
if (use_response_headers) {
res = smf_sbi_inst->curl_create_handle(
root_uri, body, response_body, response_headers, pid_ptr, method,
smf_cfg.http_version);
} else {
res = smf_sbi_inst->curl_create_handle(
root_uri, body, response_body, pid_ptr, method, smf_cfg.http_version);
}
if (!res) {
Logger::smf_sbi().warn(
"Could not create a new handle to send message to PCF");
smf_sbi_inst->remove_promise(promise_id);
return sm_policy_status_code::INTERNAL_ERROR;
return http_status_code_e::HTTP_STATUS_CODE_500_INTERNAL_SERVER_ERROR;
}
// Wait for the response
uint32_t response_code = smf_sbi_inst->get_available_response(f);
Logger::smf_sbi().debug("Got result for promise ID %d", promise_id);
Logger::smf_sbi().debug("Response data %s", response_data.c_str());
Logger::smf_n7().debug("Got result for promise ID %d", promise_id);
Logger::smf_n7().debug("Response data %s", response_body.c_str());
return http_status_code_e(response_code);
}
sm_policy_status_code smf_pcf_client::create_policy_association(
policy_association& association) {
nlohmann::json json_data;
to_json(json_data, association.context);
Logger::smf_n7().info("Sending PCF SM policy association creation request");
std::string response_data;
std::string response_headers;
http_status_code_e response_code = send_request(
root_uri, json_data.dump(), response_data, response_headers, "POST",
true);
if (response_code == http_status_code_e::HTTP_STATUS_CODE_201_CREATED) {
std::regex rgx("Location: *(.*)");
......@@ -292,22 +337,91 @@ sm_policy_status_code smf_pcf_client::create_policy_association(
}
sm_policy_status_code smf_pcf_client::remove_policy_association(
uint32_t policy_id, const SmPolicyDeleteData& delete_data) {
// TODO
const policy_association& association,
const SmPolicyDeleteData& delete_data) {
std::string uri = association.pcf_location + "/" + delete_suffix;
nlohmann::json json_data;
to_json(json_data, delete_data);
std::string resp;
http_status_code_e response_code =
send_request(uri, json_data.dump(), resp, resp, "POST", false);
switch (response_code) {
case http_status_code_e::HTTP_STATUS_CODE_204_NO_CONTENT:
Logger::smf_n7().info("Successfully removed PCF Policy Association");
return sm_policy_status_code::OK;
case http_status_code_e::HTTP_STATUS_CODE_404_NOT_FOUND:
Logger::smf_n7().info(
"Could not remove PCF Policy Association. Wrong PCF Location");
return sm_policy_status_code::NOT_FOUND;
default:
Logger::smf_n7().info(
"Could not remove PCF Policy Association: Unknown Return code");
return sm_policy_status_code::INTERNAL_ERROR;
}
}
sm_policy_status_code smf_pcf_client::update_policy_association(
uint32_t policy_id, const SmPolicyUpdateContextData& update_data,
const SmPolicyUpdateContextData& update_data,
policy_association& association) {
// TODO
std::string uri = association.pcf_location + "/" + update_suffix;
std::string resp;
nlohmann::json json_data;
to_json(json_data, update_data);
http_status_code_e response_code =
send_request(uri, json_data.dump(), resp, resp, "POST", false);
nlohmann::json json_resp;
// TODO in the standard it is written that PCF should only update to decision
// but here we overwrite object this works because PCF does the same but it is
// not standard-compliant
switch (response_code) {
case http_status_code_e::HTTP_STATUS_CODE_200_OK:
json_resp = nlohmann::json::parse(resp);
from_json(json_resp, association.decision);
Logger::smf_n7().info("Successfully updated PCF association");
return sm_policy_status_code::OK;
case http_status_code_e::HTTP_STATUS_CODE_404_NOT_FOUND:
Logger::smf_n7().info(
"Could not update PCF Policy Association. Wrong PCF Location");
return sm_policy_status_code::NOT_FOUND;
default:
Logger::smf_n7().info(
"Could not update PCF Policy Association: Unknown Return code");
return sm_policy_status_code::INTERNAL_ERROR;
}
}
sm_policy_status_code smf_pcf_client::get_policy_association(
uint32_t policy_id, policy_association& association) {
// TODO
policy_association& association) {
std::string uri = association.pcf_location;
std::string resp;
std::string empty = "";
http_status_code_e response_code =
send_request(uri, empty, resp, resp, "GET", false);
nlohmann::json j = nlohmann::json::parse(resp);
SmPolicyControl control;
switch (response_code) {
case http_status_code_e::HTTP_STATUS_CODE_200_OK:
from_json(j, control);
association.decision = control.getPolicy();
association.context = control.getContext();
Logger::smf_n7().info("Successfully retrieved PCF Policy Association");
return sm_policy_status_code::OK;
case http_status_code_e::HTTP_STATUS_CODE_404_NOT_FOUND:
Logger::smf_n7().info(
"Could not retrieve PCF Policy Association. Wrong PCF Location");
return sm_policy_status_code::NOT_FOUND;
default:
Logger::smf_n7().info(
"Could not retrieve PCF Policy Association: Unknown Return code");
return sm_policy_status_code::INTERNAL_ERROR;
}
}
smf_pcf_client::~smf_pcf_client() {
......
......@@ -41,6 +41,7 @@
#include "SmPolicyUpdateContextData.h"
#include "SmPolicyDeleteData.h"
#include "smf.h"
#include "3gpp_29.500.h"
namespace smf::n7 {
......@@ -141,41 +142,39 @@ class policy_storage {
/**
* @brief Removes a policy association, identified by the ID,
*
* @param policy_id input: policy ID
* @param policy_association input: must contain PCF location, object is not
* removed
* @param delete_data input: must not be null, but values are optional
* @return sm_policy_status_code OK in case of success, otherwise NOT_FOUND,
* INTERNAL_ERROR, PCF_NOT_AVAILABLE
*/
virtual sm_policy_status_code remove_policy_association(
uint32_t policy_id,
const policy_association& association,
const oai::smf_server::model::SmPolicyDeleteData& delete_data) = 0;
/**
* @brief Updates a policy association, identified by the ID
*
* @param policy_id input: policy ID
* @param update_data input: must not be null and set accordingly to the
* triggers
* @param policy_association output: Updated policy association with new
* context and decision in case of OK status code
* @param policy_association Updated policy association with new
* context and decision in case of OK status code, must contain PCF location
* @return sm_policy_status_code OK in case of success, otherwise NOT_FOUND,
* INTERNAL_ERROR, PCF_NOT_AVAILABLE
*/
virtual sm_policy_status_code update_policy_association(
uint32_t policy_id,
const oai::smf_server::model::SmPolicyUpdateContextData& update_data,
policy_association& association) = 0;
/**
* @brief Get the the policy association together with the original context
*
* @param policy_id input: policy ID
* @param association output: contains the original context and the policy
* decision
* @param association contains the original context and the policy
* decision, must contain policy ID and PCF location
* @return sm_policy_status_code OK in case of success, otherwise NOT_FOUND,
* ITERNAL_ERROR, PCF_NOT_AVAILABLE
*/
virtual sm_policy_status_code get_policy_association(
uint32_t policy_id, policy_association& association) = 0;
policy_association& association) = 0;
};
/**
......@@ -186,6 +185,8 @@ class smf_pcf_client : public policy_storage {
public:
const std::string sm_api_name = "npcf-smpolicycontrol";
const std::string sm_api_policy_resource_part = "sm-policies";
const std::string delete_suffix = "delete";
const std::string update_suffix = "update";
explicit smf_pcf_client(std::string pcf_addr, std::string pcf_api_version) {
root_uri = "http://" + pcf_addr + "/" + sm_api_name + "/" +
......@@ -211,16 +212,15 @@ class smf_pcf_client : public policy_storage {
policy_association& association) override;
sm_policy_status_code remove_policy_association(
uint32_t policy_id,
const policy_association& association,
const oai::smf_server::model::SmPolicyDeleteData& delete_data) override;
sm_policy_status_code update_policy_association(
uint32_t policy_id,
const oai::smf_server::model::SmPolicyUpdateContextData& update_data,
policy_association& association) override;
sm_policy_status_code get_policy_association(
uint32_t policy_id, policy_association& association) override;
policy_association& association) override;
private:
static bool discover_pcf_with_nrf(
......@@ -233,6 +233,11 @@ class smf_pcf_client : public policy_storage {
const oai::smf_server::model::Snssai snssai,
const oai::smf_server::model::PlmnId plmn_id, const std::string dnn);
http_status_code_e send_request(
const std::string& uri, const std::string& body,
std::string& response_body, std::string& response_headers,
std::string method, bool use_response_headers = false);
std::string root_uri;
};
......@@ -282,11 +287,13 @@ class smf_n7 {
* id of the association parameter need to be set
*
* @param association input: pcf_id and id need to be set and exist
* @param delete_data input: Values are optional but cannot be null
* @return sm_policy_status_code OK in case of success, otherwise NOT_FOUND,
* INTERNAL_ERROR, PCF_NOT_AVAILABLE
*/
sm_policy_status_code remove_sm_policy_association(
const policy_association& association);
const policy_association& association,
const oai::smf_server::model::SmPolicyDeleteData& delete_data);
/**
* @brief Updates an SM Policy Association, requires the triggers to be set as
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment