Skip to content
Snippets Groups Projects
Commit ebfca2d3 authored by Stefan Spettel's avatar Stefan Spettel
Browse files

refact(pcf): Created policy_storage class and replace objects with smart ptrs

parent aa8816a2
No related branches found
No related tags found
1 merge request!6feat(pcf): Add possibility to provision PCC rules from file
Showing
with 485 additions and 264 deletions
......@@ -44,4 +44,5 @@ add_library (PCF STATIC
sm_policy/slice_policy_decision.cpp
sm_policy/supi_policy_decision.cpp
sm_policy/dnn_policy_decision.cpp
sm_policy/policy_storage.cpp
)
\ No newline at end of file
......@@ -35,6 +35,7 @@
#include "pcf_client.hpp"
#include "Snssai.h"
#include "TrafficControlData.h"
#include "sm_policy/policy_decision.hpp"
#include <boost/uuid/random_generator.hpp>
#include <boost/uuid/uuid_io.hpp>
......@@ -43,6 +44,7 @@
#include <map>
#include <shared_mutex>
#include <memory>
#include <string>
using namespace oai::pcf::app;
using namespace oai::pcf::app::sm_policy;
......@@ -55,180 +57,24 @@ extern pcf_smpc* pcf_smpc_inst;
extern pcf_config pcf_cfg;
//------------------------------------------------------------------------------
pcf_smpc::pcf_smpc() {
// TODO currently hardcode the policy decisions, should come from UDR or file
SmPolicyDecision decision_supi;
SmPolicyDecision decision_tmp;
std::string supi = "imsi-208950000000032";
std::string dnn = "default";
Snssai snssai;
snssai.setSd("123");
snssai.setSst(222);
create_default_policy_decision(
"supi-rule-internet", "permit out ip from any to assigned",
"default-traffic", "internet-dn", "route-internet", 10, decision_supi);
// to have second PCC rule within same profile
create_default_policy_decision(
"supi-rule-edge", "permit out ip from 8.8.8.8 to assigned",
"edge-traffic", "edge-dn", "route-edge1", 9, decision_tmp);
std::map<std::string, PccRule> pcc_rules_supi = decision_supi.getPccRules();
pcc_rules_supi.insert(std::make_pair(
"supi-rule-edge", decision_tmp.getPccRules()["supi-rule-edge"]));
std::map<std::string, TrafficControlData> traffic_control_decs =
decision_supi.getTraffContDecs();
traffic_control_decs.insert(std::make_pair(
"edge-traffic", decision_tmp.getTraffContDecs()["edge-traffic"]));
decision_supi.setPccRules(pcc_rules_supi);
decision_supi.setTraffContDecs(traffic_control_decs);
SmPolicyDecision decision_dnn;
create_default_policy_decision(
"dnn-rule-internet", "permit out ip from any to assigned",
"default-traffic", "internet-dn", "route-internet", 10, decision_dnn);
SmPolicyDecision decision_slice;
create_default_policy_decision(
"slice-rule-internet", "permit out ip from any to assigned",
"default-traffic", "internet-dn", "route-internet", 10, decision_slice);
SmPolicyDecision decision_default;
create_default_policy_decision(
"default-rule-internet", "permit out ip from any to assigned",
"default-traffic", "internet-dn", "route-internet", 10, decision_default);
supi_policy_decision supi_desc(supi, decision_supi);
m_supi_policy_decisions.insert(std::make_pair(supi, supi_desc));
slice_policy_decision slice_desc(snssai, decision_slice);
m_slice_policy_decisions.insert(std::make_pair(snssai, slice_desc));
dnn_policy_decision dnn_desc(dnn, decision_dnn);
m_dnn_policy_decisions.insert(std::make_pair(dnn, dnn_desc));
default_decision = std::make_unique<policy_decision>(decision_default);
}
void pcf_smpc::create_default_policy_decision(
std::string pcc_rule_name, std::string flow_description, std::string tc_id,
std::string dnai, std::string route_policy_id, int precedence,
SmPolicyDecision& decision) {
PccRule rule;
FlowInformation flow;
flow.setFlowDescription(flow_description);
std::vector<FlowInformation> flow_information;
flow_information.push_back(flow);
// 29.512 5.6.2.6 array only for forwards compatibility, n=1
std::vector<std::string> tc_ids;
tc_ids.push_back(tc_id);
rule.setFlowInfos(flow_information);
rule.setPccRuleId(pcc_rule_name);
rule.setRefTcData(tc_ids);
rule.setPrecedence(precedence);
std::map<std::string, PccRule> pcc_rule_map;
pcc_rule_map[pcc_rule_name] = rule;
decision.setPccRules(pcc_rule_map);
TrafficControlData traffic_control;
traffic_control.setTcId(tc_id);
RouteToLocation route_to_loc;
route_to_loc.setDnai(dnai);
route_to_loc.setRouteProfId(route_policy_id);
std::vector<RouteToLocation> route_to_locs;
route_to_locs.push_back(route_to_loc);
traffic_control.setRouteToLocs(route_to_locs);
std::map<std::string, TrafficControlData> traffic_cont_map;
traffic_cont_map[tc_id] = traffic_control;
decision.setTraffContDecs(traffic_cont_map);
}
bool pcf_smpc::find_policy(
const SmPolicyContextData& context, policy_decision** chosen_decision) {
std::string msg_base =
fmt::format("SM Policy request from SUPI {}: ", context.getSupi());
bool found = true;
// First, check based on SUPI, then DNN, then Slice, then global default rule.
std::shared_lock lock_supi(m_supi_policy_decisions_mutex);
std::unordered_map<std::string, supi_policy_decision>::iterator got_supi =
m_supi_policy_decisions.find(context.getSupi());
if (got_supi == m_supi_policy_decisions.end()) {
Logger::pcf_app().debug(msg_base + "Did not find SUPI policy");
std::shared_lock lock_dnn(m_dnn_policy_decisions_mutex);
std::unordered_map<std::string, dnn_policy_decision>::iterator got_dnn =
m_dnn_policy_decisions.find(context.getDnn());
if (got_dnn == m_dnn_policy_decisions.end()) {
Logger::pcf_app().debug(msg_base + "Did not find DNN policy");
std::shared_lock lock_slice(m_slice_policy_decisions_mutex);
std::unordered_map<Snssai, slice_policy_decision, snssai_hasher>::iterator
got_slice = m_slice_policy_decisions.find(context.getSliceInfo());
if (got_slice == m_slice_policy_decisions.end()) {
Logger::pcf_app().debug(msg_base + "Did not find slice policy");
if (!default_decision) {
Logger::pcf_app().debug(msg_base + "Did not find default policy");
found = false;
} else {
Logger::pcf_app().debug(msg_base + "Decide based on default policy");
*chosen_decision = default_decision.get();
}
} else {
Logger::pcf_app().debug(msg_base + "Decide based on slice");
*chosen_decision = &got_slice->second;
}
} else {
Logger::pcf_app().debug(msg_base + "Decide based on DNN");
*chosen_decision = &got_dnn->second;
}
} else {
Logger::pcf_app().debug(msg_base + "Decide based on SUPI");
*chosen_decision = &got_supi->second;
}
return found;
}
pcf_smpc::pcf_smpc() {}
//------------------------------------------------------------------------------
status_code pcf_smpc::create_sm_policy_handler(
const SmPolicyContextData& context, SmPolicyDecision& decision,
std::string& association_id, std::string& problem_details) {
std::shared_lock lock_supi(m_supi_policy_decisions_mutex);
std::shared_lock lock_dnn(m_dnn_policy_decisions_mutex);
std::shared_lock lock_slice(m_slice_policy_decisions_mutex);
std::shared_ptr<policy_decision> chosen_decision =
m_policy_storage.find_policy(context);
policy_decision* chosen_decision;
bool found = find_policy(context, &chosen_decision);
if (!found) {
if (!chosen_decision) {
problem_details = fmt::format(
"SM policy request from SUPI {}: No policies found", context.getSupi());
return status_code::CONTEXT_DENIED;
}
status_code res = chosen_decision->decide(context, decision);
// we can release the locks here
lock_slice.unlock();
lock_dnn.unlock();
lock_supi.unlock();
std::shared_ptr<SmPolicyDecision> decision_ptr;
status_code res = chosen_decision->decide(context, decision_ptr);
if (res != status_code::CREATED) {
problem_details = fmt::format(
......@@ -237,7 +83,7 @@ status_code pcf_smpc::create_sm_policy_handler(
} else {
association_id = std::to_string(m_association_id_generator.get_uid());
individual_sm_association assoc(context, decision, association_id);
individual_sm_association assoc(context, decision_ptr, association_id);
std::unique_lock lock_assocations(m_associations_mutex);
m_associations.insert(std::make_pair(association_id, assoc));
......@@ -246,6 +92,7 @@ status_code pcf_smpc::create_sm_policy_handler(
"Created Policy Decision for SUPI {} with ID {}", context.getSupi(),
association_id));
}
decision = *decision_ptr;
return res;
}
......@@ -284,7 +131,7 @@ sm_policy::status_code pcf_smpc::get_sm_policy_handler(
return status_code::NOT_FOUND;
}
control.setContext(iter->second.get_sm_policy_context_data());
control.setPolicy(iter->second.get_sm_policy_decision());
control.setPolicy(*(iter->second.get_sm_policy_decision()));
Logger::pcf_app().info(
fmt::format("Retrieved policy association with ID {}", id));
......@@ -307,20 +154,17 @@ sm_policy::status_code pcf_smpc::update_sm_policy_handler(
return status_code::NOT_FOUND;
}
SmPolicyDecision orig_decision = iter->second.get_sm_policy_decision();
std::shared_ptr<SmPolicyDecision> new_decision_ptr;
std::shared_ptr<SmPolicyDecision> orig_decision =
iter->second.get_sm_policy_decision();
SmPolicyContextData orig_context = iter->second.get_sm_policy_context_data();
// find the original decision to redecide
std::shared_lock lock_supi(m_supi_policy_decisions_mutex);
std::shared_lock lock_dnn(m_dnn_policy_decisions_mutex);
std::shared_lock lock_slice(m_slice_policy_decisions_mutex);
policy_decision* chosen_decision;
std::shared_ptr<policy_decision> chosen_decision =
m_policy_storage.find_policy(orig_context);
// this may happen when the policy has been updated/deleted in the meantime.
bool found = find_policy(orig_context, &chosen_decision);
if (!found) {
if (!chosen_decision) {
problem_details = fmt::format(
"SM policy update from SUPI {}: No policies found",
orig_context.getSupi());
......@@ -329,20 +173,18 @@ sm_policy::status_code pcf_smpc::update_sm_policy_handler(
}
status_code res = chosen_decision->redecide(
orig_context, orig_decision, update_context, decision, problem_details);
orig_context, orig_decision, update_context, new_decision_ptr,
problem_details);
// we can release the locks here
lock_slice.unlock();
lock_dnn.unlock();
lock_supi.unlock();
// update the existing context and policy and receive a policy diff
// TODO in TS 23.512 Chapter 4.2.6 it is described that only the diff should
// be returned. here, we return the whole policy object.
individual_sm_association assoc(orig_context, decision, id);
individual_sm_association assoc(orig_context, new_decision_ptr, id);
iter->second = assoc;
// overwrite existing association
m_associations.insert(std::make_pair(id, assoc));
decision = *new_decision_ptr;
return res;
}
......
......@@ -42,12 +42,8 @@
#include "SmPolicyUpdateContextData.h"
#include "sm_policy/pcf_smpc_status_code.hpp"
#include "sm_policy/individual_sm_association.hpp"
#include "sm_policy/policy_decision.hpp"
#include "sm_policy/slice_policy_decision.hpp"
#include "sm_policy/supi_policy_decision.hpp"
#include "sm_policy/dnn_policy_decision.hpp"
#include "sm_policy/snssai_hasher.hpp"
#include "uint_generator.hpp"
#include "sm_policy/policy_storage.hpp"
namespace oai::pcf::app {
......@@ -126,57 +122,15 @@ class pcf_smpc {
std::string& problem_details);
private:
/**
* @brief Finds a policy based on the existing supi, dnn, slice and default
* policies in that order.
* PRECONDITION: Lock all mutexes for the maps
*
* @param context The policy context containing supi, dnn and snssai
* @param chosen_decision pointer to the object implementing the chosen
* decision base class
* @return true if policy found
* @return false if no policy found
*/
bool find_policy(
const oai::pcf::model::SmPolicyContextData& context,
oai::pcf::app::sm_policy::policy_decision** chosen_decision);
/**
* @brief Helper method to create hardcoded policy decisions
*
* @param pcc_rule_name
* @param flow_description
* @param tc_id
* @param steering_policy_id
*/
void create_default_policy_decision(
std::string pcc_rule_name, std::string flow_description,
std::string tc_id, std::string dnai, std::string route_policy_id,
int precedence, oai::pcf::model::SmPolicyDecision& decision);
util::uint_generator<uint32_t> m_association_id_generator;
std::unordered_map<
std::string, oai::pcf::app::sm_policy::individual_sm_association>
m_associations;
std::unordered_map<
oai::pcf::model::Snssai, oai::pcf::app::sm_policy::slice_policy_decision,
oai::pcf::app::sm_policy::snssai_hasher>
m_slice_policy_decisions;
std::unordered_map<std::string, oai::pcf::app::sm_policy::dnn_policy_decision>
m_dnn_policy_decisions;
std::unordered_map<
std::string, oai::pcf::app::sm_policy::supi_policy_decision>
m_supi_policy_decisions;
std::unique_ptr<oai::pcf::app::sm_policy::policy_decision> default_decision;
mutable std::shared_mutex m_associations_mutex;
mutable std::shared_mutex m_slice_policy_decisions_mutex;
mutable std::shared_mutex m_dnn_policy_decisions_mutex;
mutable std::shared_mutex m_supi_policy_decisions_mutex;
oai::pcf::app::sm_policy::policy_storage m_policy_storage;
};
} // namespace oai::pcf::app
#endif /* FILE_PCF_SM_POLICY_CONTROL_SEEN */
......@@ -34,7 +34,8 @@ using namespace oai::pcf::app::sm_policy;
using namespace oai::pcf::app;
status_code dnn_policy_decision::decide(
const SmPolicyContextData& context, SmPolicyDecision& decision) const {
const SmPolicyContextData& context,
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const {
if (context.getDnn() != m_dnn) {
return status_code::CONTEXT_DENIED;
}
......
......@@ -45,7 +45,8 @@ namespace oai::pcf::app::sm_policy {
class dnn_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
public:
explicit dnn_policy_decision(
std::string dnn, oai::pcf::model::SmPolicyDecision decision)
std::string dnn,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision)
: policy_decision(decision) {
m_dnn = dnn;
m_decision = decision;
......@@ -64,7 +65,7 @@ class dnn_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
*/
oai::pcf::app::sm_policy::status_code decide(
const oai::pcf::model::SmPolicyContextData& context,
oai::pcf::model::SmPolicyDecision& decision) const;
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const;
/**
* @brief Get the dnn object
......@@ -74,7 +75,7 @@ class dnn_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
std::string get_dnn() const;
private:
oai::pcf::model::SmPolicyDecision m_decision;
std::shared_ptr<oai::pcf::model::SmPolicyDecision> m_decision;
std::string m_dnn;
};
} // namespace oai::pcf::app::sm_policy
......
......@@ -37,7 +37,8 @@ SmPolicyContextData individual_sm_association::get_sm_policy_context_data()
return m_context;
}
SmPolicyDecision individual_sm_association::get_sm_policy_decision() const {
std::shared_ptr<oai::pcf::model::SmPolicyDecision>
individual_sm_association::get_sm_policy_decision() const {
return m_decision;
}
......@@ -47,7 +48,7 @@ void individual_sm_association::set_sm_policy_context_data(
}
void individual_sm_association::set_sm_policy_decision(
SmPolicyDecision& decision) {
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) {
m_decision = decision;
}
......
......@@ -41,7 +41,8 @@ class individual_sm_association {
public:
explicit individual_sm_association(
oai::pcf::model::SmPolicyContextData context,
oai::pcf::model::SmPolicyDecision decision, std::string id) {
std::shared_ptr<oai::pcf::model::SmPolicyDecision> decision,
std::string id) {
m_decision = decision;
m_context = context;
m_id = id;
......@@ -50,17 +51,19 @@ class individual_sm_association {
virtual ~individual_sm_association() = default;
oai::pcf::model::SmPolicyContextData get_sm_policy_context_data() const;
oai::pcf::model::SmPolicyDecision get_sm_policy_decision() const;
std::shared_ptr<oai::pcf::model::SmPolicyDecision> get_sm_policy_decision()
const;
void set_sm_policy_context_data(
oai::pcf::model::SmPolicyContextData& context);
void set_sm_policy_decision(oai::pcf::model::SmPolicyDecision& decision);
void set_sm_policy_decision(
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision);
std::string get_id() const;
private:
oai::pcf::model::SmPolicyContextData m_context;
oai::pcf::model::SmPolicyDecision m_decision;
std::shared_ptr<oai::pcf::model::SmPolicyDecision> m_decision;
std::string m_id;
};
} // namespace oai::pcf::app::sm_policy
......
......@@ -38,7 +38,8 @@ using namespace oai::pcf::app;
typedef PolicyControlRequestTrigger_anyOf::ePolicyControlRequestTrigger_anyOf E;
status_code policy_decision::decide(
const SmPolicyContextData& context, SmPolicyDecision& decision) const {
const SmPolicyContextData& context,
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const {
// default rule, so just reply with the decision
decision = m_decision;
return status_code::CREATED;
......@@ -46,7 +47,8 @@ status_code policy_decision::decide(
status_code policy_decision::handle_plmn_change(
SmPolicyContextData& orig_context, const SmPolicyUpdateContextData& update,
SmPolicyDecision& decision, std::string& problem_details) {
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details) {
if (update.servingNetworkIsSet()) {
orig_context.setServingNetwork(update.getServingNetwork());
return status_code::OK;
......@@ -57,7 +59,8 @@ status_code policy_decision::handle_plmn_change(
status_code policy_decision::handle_access_type_change(
SmPolicyContextData& orig_context, const SmPolicyUpdateContextData& update,
SmPolicyDecision& decision, std::string& problem_details) {
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details) {
if (update.accessTypeIsSet()) {
orig_context.setAccessType(update.getAccessType());
return status_code::OK;
......@@ -72,7 +75,8 @@ status_code policy_decision::handle_access_type_change(
status_code policy_decision::handle_ip_address_change(
SmPolicyContextData& orig_context, const SmPolicyUpdateContextData& update,
SmPolicyDecision& decision, std::string& problem_details) {
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details) {
problem_details = "";
status_code code = status_code::INVALID_PARAMETERS;
if (update.ipv4AddressIsSet()) {
......@@ -104,7 +108,8 @@ status_code policy_decision::handle_ip_address_change(
status_code policy_decision::handle_rat_type_change(
SmPolicyContextData& orig_context, const SmPolicyUpdateContextData& update,
SmPolicyDecision& decision, std::string& problem_details) {
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details) {
status_code code = status_code::INVALID_PARAMETERS;
if (update.ratTypeIsSet()) {
orig_context.setRatType(update.getRatType());
......@@ -129,9 +134,10 @@ status_code policy_decision::handle_rat_type_change(
status_code policy_decision::redecide(
SmPolicyContextData& original_context,
const SmPolicyDecision& original_decision,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& original_decision,
const SmPolicyUpdateContextData& update_data,
SmPolicyDecision& new_decision, std::string& problem_details) {
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& new_decision,
std::string& problem_details) {
new_decision = m_decision;
status_code status = status_code::OK;
......
......@@ -44,7 +44,8 @@ namespace oai::pcf::app::sm_policy {
*/
class policy_decision {
public:
explicit policy_decision(oai::pcf::model::SmPolicyDecision decision) {
explicit policy_decision(
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) {
m_decision = decision;
}
......@@ -59,7 +60,7 @@ class policy_decision {
*/
virtual oai::pcf::app::sm_policy::status_code decide(
const oai::pcf::model::SmPolicyContextData& context,
oai::pcf::model::SmPolicyDecision& decision) const;
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const;
/**
* @brief Redecides based on the original context, original decision and
......@@ -77,9 +78,10 @@ class policy_decision {
*/
virtual oai::pcf::app::sm_policy::status_code redecide(
oai::pcf::model::SmPolicyContextData& original_context,
const oai::pcf::model::SmPolicyDecision& original_decision,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>&
original_decision,
const oai::pcf::model::SmPolicyUpdateContextData& update_data,
oai::pcf::model::SmPolicyDecision& new_decision,
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& new_decision,
std::string& problem_details);
virtual ~policy_decision();
......@@ -88,29 +90,29 @@ class policy_decision {
oai::pcf::app::sm_policy::status_code handle_plmn_change(
oai::pcf::model::SmPolicyContextData& orig_context,
const oai::pcf::model::SmPolicyUpdateContextData& update,
oai::pcf::model::SmPolicyDecision& decision,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details);
oai::pcf::app::sm_policy::status_code handle_access_type_change(
oai::pcf::model::SmPolicyContextData& orig_context,
const oai::pcf::model::SmPolicyUpdateContextData& update,
oai::pcf::model::SmPolicyDecision& decision,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details);
oai::pcf::app::sm_policy::status_code handle_ip_address_change(
oai::pcf::model::SmPolicyContextData& orig_context,
const oai::pcf::model::SmPolicyUpdateContextData& update,
oai::pcf::model::SmPolicyDecision& decision,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details);
oai::pcf::app::sm_policy::status_code handle_rat_type_change(
oai::pcf::model::SmPolicyContextData& orig_context,
const oai::pcf::model::SmPolicyUpdateContextData& update,
oai::pcf::model::SmPolicyDecision& decision,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision,
std::string& problem_details);
private:
oai::pcf::model::SmPolicyDecision m_decision;
std::shared_ptr<oai::pcf::model::SmPolicyDecision> m_decision;
};
} // namespace oai::pcf::app::sm_policy
#endif
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
*
* 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.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file policy_storage.cpp
\brief
\author Stefan Spettel
\company Openairinterface Software Allianse
\date 2022
\email: stefan.spettel@eurecom.fr
*/
#include "policy_storage.hpp"
#include "logger.hpp"
using namespace oai::pcf::app::sm_policy;
using namespace oai::pcf::model;
void policy_storage::create_default_policy_decision(
std::string pcc_rule_name, std::string flow_description, std::string tc_id,
std::string dnai, std::string route_policy_id, int precedence,
std::shared_ptr<SmPolicyDecision>& decision) {
PccRule rule;
FlowInformation flow;
flow.setFlowDescription(flow_description);
std::vector<FlowInformation> flow_information;
flow_information.push_back(flow);
// 29.512 5.6.2.6 array only for forwards compatibility, n=1
std::vector<std::string> tc_ids;
tc_ids.push_back(tc_id);
rule.setFlowInfos(flow_information);
rule.setPccRuleId(pcc_rule_name);
rule.setRefTcData(tc_ids);
rule.setPrecedence(precedence);
std::map<std::string, PccRule> pcc_rule_map;
pcc_rule_map[pcc_rule_name] = rule;
decision->setPccRules(pcc_rule_map);
TrafficControlData traffic_control;
traffic_control.setTcId(tc_id);
RouteToLocation route_to_loc;
route_to_loc.setDnai(dnai);
route_to_loc.setRouteProfId(route_policy_id);
std::vector<RouteToLocation> route_to_locs;
route_to_locs.push_back(route_to_loc);
traffic_control.setRouteToLocs(route_to_locs);
std::map<std::string, TrafficControlData> traffic_cont_map;
traffic_cont_map[tc_id] = traffic_control;
decision->setTraffContDecs(traffic_cont_map);
}
policy_storage::policy_storage() {
// TODO currently hardcode the policy decisions, should come from UDR or file
std::shared_ptr<SmPolicyDecision> decision_supi =
std::make_shared<SmPolicyDecision>();
std::shared_ptr<SmPolicyDecision> decision_tmp =
std::make_shared<SmPolicyDecision>();
std::string supi = "imsi-208950000000031";
std::string dnn = "default";
Snssai snssai;
snssai.setSd("123");
snssai.setSst(222);
create_default_policy_decision(
"supi-rule-internet", "permit out ip from any to assigned",
"internet-traffic", "access_gnb_1", "routex", 10, decision_supi);
// to have second PCC rule within same profile
create_default_policy_decision(
"supi-rule-edge", "permit out ip from 8.8.8.8 to assigned",
"edge-traffic", "edge-dn", "route-edge1", 9, decision_tmp);
std::map<std::string, PccRule> pcc_rules_supi = decision_supi->getPccRules();
pcc_rules_supi.insert(std::make_pair(
"supi-rule-edge", decision_tmp->getPccRules()["supi-rule-edge"]));
std::map<std::string, TrafficControlData> traffic_control_decs =
decision_supi->getTraffContDecs();
TrafficControlData traffic = traffic_control_decs["internet-traffic"];
std::vector<RouteToLocation> routes;
RouteToLocation route0;
route0.setDnai("access_gnb_1");
RouteToLocation route1;
route1.setDnai("ulcl1");
RouteToLocation route2;
route2.setDnai("iupf1");
RouteToLocation route3;
route3.setDnai("aupf1");
RouteToLocation route4;
route4.setDnai("internet");
RouteToLocation route5;
route5.setDnai("aupf3");
RouteToLocation route6;
route6.setDnai("aupf2");
RouteToLocation route7;
route7.setDnai("edge");
routes.push_back(route0);
routes.push_back(route1);
routes.push_back(route2);
routes.push_back(route3);
routes.push_back(route4);
// routes.push_back(route5);
traffic.setRouteToLocs(routes);
traffic_control_decs["internet-traffic"] = traffic;
TrafficControlData traffic2 = traffic_control_decs["edge-traffic"];
std::vector<RouteToLocation> routes2;
routes2.push_back(route0);
routes2.push_back(route7);
routes2.push_back(route6);
routes2.push_back(route1);
traffic2.setRouteToLocs(routes2);
traffic_control_decs["edge-traffic"] = traffic2;
decision_supi->setTraffContDecs(traffic_control_decs);
decision_supi->setPccRules(pcc_rules_supi);
std::shared_ptr<SmPolicyDecision> decision_dnn =
std::make_shared<SmPolicyDecision>();
create_default_policy_decision(
"dnn-rule-internet", "permit out ip from any to assigned",
"default-traffic", "internet-dn", "route-internet", 10, decision_dnn);
std::shared_ptr<SmPolicyDecision> decision_slice =
std::make_shared<SmPolicyDecision>();
create_default_policy_decision(
"slice-rule-internet", "permit out ip from any to assigned",
"default-traffic", "internet-dn", "route-internet", 10, decision_slice);
std::shared_ptr<SmPolicyDecision> decision_default =
std::make_shared<SmPolicyDecision>();
create_default_policy_decision(
"default-rule-internet", "permit out ip from any to assigned",
"default-traffic", "internet-dn", "route-internet", 10, decision_default);
insert_supi_decision(supi, decision_supi);
insert_dnn_decision(dnn, decision_dnn);
insert_slice_decision(snssai, decision_slice);
default_decision = std::make_shared<policy_decision>(decision_default);
}
void policy_storage::insert_supi_decision(
std::string supi, const std::shared_ptr<SmPolicyDecision>& decision) {
std::unique_lock supi_decision_lock(m_supi_policy_decisions_mutex);
std::shared_ptr<supi_policy_decision> desc =
std::make_shared<supi_policy_decision>(supi, decision);
m_supi_policy_decisions.insert(std::make_pair(supi, desc));
notify_subscribers(desc);
}
void policy_storage::insert_dnn_decision(
std::string dnn, const std::shared_ptr<SmPolicyDecision>& decision) {
std::unique_lock dnn_decision_lock(m_dnn_policy_decisions_mutex);
std::shared_ptr<dnn_policy_decision> desc =
std::make_shared<dnn_policy_decision>(dnn, decision);
m_dnn_policy_decisions.insert(std::make_pair(dnn, desc));
notify_subscribers(desc);
}
void policy_storage::insert_slice_decision(
Snssai slice, const std::shared_ptr<SmPolicyDecision>& decision) {
std::unique_lock slice_decision_lock(m_slice_policy_decisions_mutex);
std::shared_ptr<slice_policy_decision> desc =
std::make_shared<slice_policy_decision>(slice, decision);
m_slice_policy_decisions.insert(std::make_pair(slice, desc));
notify_subscribers(desc);
}
/**
* @brief Finds a policy based on the existing supi, dnn, slice and default
* policies in that order.
*
* @param context The policy context containing supi or dnn or snssai
* @param chosen_decision
* decision base class
* @return pointer to the object implementing the chosen, null in case no
* decision can be found
*/
std::shared_ptr<policy_decision> policy_storage::find_policy(
const oai::pcf::model::SmPolicyContextData& context) {
std::string msg_base = "SM Policy request from SUPI:";
std::string supi = context.getSupi();
std::shared_ptr<policy_decision> res_ptr;
// First, check based on SUPI, then DNN, then Slice, then global default rule.
std::shared_lock lock_supi(m_supi_policy_decisions_mutex);
auto got_supi = m_supi_policy_decisions.find(context.getSupi());
if (got_supi == m_supi_policy_decisions.end()) {
Logger::pcf_app().debug(
"%s %s - Did not find SUPI policy", msg_base.c_str(), supi.c_str());
std::shared_lock lock_dnn(m_dnn_policy_decisions_mutex);
auto got_dnn = m_dnn_policy_decisions.find(context.getDnn());
if (got_dnn == m_dnn_policy_decisions.end()) {
Logger::pcf_app().debug(
"%s %s - Did not find DNN policy", msg_base.c_str(), supi.c_str());
std::shared_lock lock_slice(m_slice_policy_decisions_mutex);
auto got_slice = m_slice_policy_decisions.find(context.getSliceInfo());
if (got_slice == m_slice_policy_decisions.end()) {
Logger::pcf_app().debug(
"%s %s - Did not find slice policy", msg_base.c_str(),
supi.c_str());
if (!default_decision) {
Logger::pcf_app().debug(
"%s %s - Did not find default policy", msg_base.c_str(),
supi.c_str());
return res_ptr; // null
} else {
Logger::pcf_app().debug(
"%s %s - Decide based on default policy", msg_base.c_str(),
supi.c_str());
return default_decision;
}
} else {
Logger::pcf_app().debug("%s Decide based on slice", msg_base.c_str());
return got_slice->second;
}
} else {
Logger::pcf_app().debug("%s Decide based on DNN", msg_base.c_str());
return got_dnn->second;
}
} else {
Logger::pcf_app().debug("%s Decide based on SUPI", msg_base.c_str());
return got_supi->second;
}
return res_ptr;
}
void policy_storage::notify_subscribers(
const std::shared_ptr<policy_decision>& decision) {
// TODO
}
\ No newline at end of file
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.1 (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.openairinterface.org/?page_id=698
*
* 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.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file policy_storage.hpp
\brief
\author Stefan Spettel
\company Openairinterface Software Allianse
\date 2022
\email: stefan.spettel@eurecom.fr
*/
#ifndef FILE_POLICY_STORAGE_SEEN
#define FILE_POLICY_STORAGE_SEEN
#include <string>
#include <memory>
#include <shared_mutex>
#include <unordered_map>
#include "SmPolicyDecision.h"
#include "SmPolicyContextData.h"
#include "Snssai.h"
#include "policy_decision.hpp"
#include "slice_policy_decision.hpp"
#include "dnn_policy_decision.hpp"
#include "supi_policy_decision.hpp"
#include "snssai_hasher.hpp"
namespace oai::pcf::app::sm_policy {
/**
* @brief Class to store policies, either pre-configured using files and/or AF
* or provisioning requests
*
*/
class policy_storage {
private:
/**
* @brief Helper method to create hardcoded policy decisions
*
* @param pcc_rule_name
* @param flow_description
* @param tc_id
* @param steering_policy_id
*/
void create_default_policy_decision(
std::string pcc_rule_name, std::string flow_description,
std::string tc_id, std::string dnai, std::string route_policy_id,
int precedence,
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision);
void notify_subscribers(const std::shared_ptr<policy_decision>& decision);
std::unordered_map<
oai::pcf::model::Snssai,
std::shared_ptr<oai::pcf::app::sm_policy::slice_policy_decision>,
oai::pcf::app::sm_policy::snssai_hasher>
m_slice_policy_decisions;
std::unordered_map<
std::string,
std::shared_ptr<oai::pcf::app::sm_policy::dnn_policy_decision>>
m_dnn_policy_decisions;
std::unordered_map<
std::string,
std::shared_ptr<oai::pcf::app::sm_policy::supi_policy_decision>>
m_supi_policy_decisions;
std::shared_ptr<oai::pcf::app::sm_policy::policy_decision> default_decision;
mutable std::shared_mutex m_slice_policy_decisions_mutex;
mutable std::shared_mutex m_dnn_policy_decisions_mutex;
mutable std::shared_mutex m_supi_policy_decisions_mutex;
public:
explicit policy_storage();
policy_storage(policy_storage const&) = delete;
void operator=(policy_storage const&) = delete;
// TODO methods to update and delete policies
void insert_supi_decision(
std::string supi,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision);
void insert_dnn_decision(
std::string dnn,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision);
void insert_slice_decision(
oai::pcf::model::Snssai,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision);
void set_default_decision(
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision);
std::shared_ptr<policy_decision> find_policy(
const oai::pcf::model::SmPolicyContextData& context);
/**
* @brief Calls the callback when any of the policies have been updated
*
* @param callback
*/
void subscribe_to_decision_change(
std::function<void(const std::shared_ptr<policy_decision>&)> callback);
};
} // namespace oai::pcf::app::sm_policy
#endif
......@@ -34,7 +34,8 @@ using namespace oai::pcf::app::sm_policy;
using namespace oai::pcf::app;
status_code slice_policy_decision::decide(
const SmPolicyContextData& context, SmPolicyDecision& decision) const {
const SmPolicyContextData& context,
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const {
if (context.getSliceInfo() != m_snssai) {
return status_code::CONTEXT_DENIED;
}
......
......@@ -45,7 +45,7 @@ class slice_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
public:
explicit slice_policy_decision(
oai::pcf::model::Snssai snssai,
oai::pcf::model::SmPolicyDecision decision)
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision)
: policy_decision(decision) {
m_snssai = snssai;
m_decision = decision;
......@@ -64,7 +64,7 @@ class slice_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
*/
oai::pcf::app::sm_policy::status_code decide(
const oai::pcf::model::SmPolicyContextData& context,
oai::pcf::model::SmPolicyDecision& decision) const;
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const;
/**
* @brief Get the snssai object
......@@ -74,7 +74,7 @@ class slice_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
oai::pcf::model::Snssai get_snssai() const;
private:
oai::pcf::model::SmPolicyDecision m_decision;
std::shared_ptr<oai::pcf::model::SmPolicyDecision> m_decision;
oai::pcf::model::Snssai m_snssai;
};
} // namespace oai::pcf::app::sm_policy
......
......@@ -34,7 +34,8 @@ using namespace oai::pcf::app::sm_policy;
using namespace oai::pcf::app;
status_code supi_policy_decision::decide(
const SmPolicyContextData& context, SmPolicyDecision& decision) const {
const SmPolicyContextData& context,
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const {
if (context.getSupi() != m_supi) {
return status_code::CONTEXT_DENIED;
}
......
......@@ -45,7 +45,8 @@ namespace oai::pcf::app::sm_policy {
class supi_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
public:
explicit supi_policy_decision(
std::string supi, oai::pcf::model::SmPolicyDecision decision)
std::string supi,
const std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision)
: policy_decision(decision) {
m_supi = supi;
m_decision = decision;
......@@ -64,7 +65,7 @@ class supi_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
*/
oai::pcf::app::sm_policy::status_code decide(
const oai::pcf::model::SmPolicyContextData& context,
oai::pcf::model::SmPolicyDecision& decision) const;
std::shared_ptr<oai::pcf::model::SmPolicyDecision>& decision) const;
/**
* @brief Get the supi object
......@@ -74,7 +75,7 @@ class supi_policy_decision : public oai::pcf::app::sm_policy::policy_decision {
std::string get_supi() const;
private:
oai::pcf::model::SmPolicyDecision m_decision;
std::shared_ptr<oai::pcf::model::SmPolicyDecision> m_decision;
std::string m_supi;
};
} // namespace oai::pcf::app::sm_policy
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment