Commit c77a9a40 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Process Create SM Context Request colliding with an existing SM Context

parent 7369359d
......@@ -770,23 +770,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
return;
}
//Step 4. Verify the session is already existed
if (is_scid_2_smf_context(supi64, dnn, snssai, pdu_session_id)) {
//TODO: should delete the local context (including and any associated resources in the UPF and PCF) and create a new one
Logger::smf_app().warn(
"PDU Session already existed (SUPI " SUPI_64_FMT ", DNN %s, NSSAI (sst %d, sd %s), PDU Session ID %d)",
supi64, dnn.c_str(), snssai.sST, snssai.sD.c_str(), pdu_session_id);
//TODO: temporary disable this action to test with AMF
/*
//trigger to send reply to AMF
trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_406_NOT_ACCEPTABLE, smreq->pid,
N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
return;
*/
}
//Step 5. create a context for this supi if not existed, otherwise update
//Step 4. create a context for this supi if not existed, otherwise update
std::shared_ptr<smf_context> sc = { };
if (is_supi_2_smf_context(supi64)) {
Logger::smf_app().debug("Update SMF context with SUPI " SUPI_64_FMT "",
......@@ -802,7 +786,7 @@ void smf_app::handle_pdu_session_create_sm_context_request(
set_supi_2_smf_context(supi64, sc);
}
//Step 6. Create/update context with dnn information
//Step 5. Create/update context with dnn information
std::shared_ptr<dnn_context> sd = { };
if (!sc.get()->find_dnn_context(snssai, dnn, sd)) {
......@@ -818,6 +802,16 @@ void smf_app::handle_pdu_session_create_sm_context_request(
}
}
//Step 6. if colliding with an existing SM context (session is already existed and request type is INITIAL_REQUEST)
//Delete the local context (including and any associated resources in the UPF and PCF) and create a new one
if (is_scid_2_smf_context(supi64, dnn, snssai, pdu_session_id) && (request_type.compare("INITIAL_REQUEST") == 0)) {
//remove smf_pdu_session (including all flows associated to this session)
sd.get()->remove_pdu_session(pdu_session_id);
Logger::smf_app().warn(
"PDU Session already existed (SUPI " SUPI_64_FMT ", DNN %s, NSSAI (sst %d, sd %s), PDU Session ID %d)",
supi64, dnn.c_str(), snssai.sST, snssai.sD.c_str(), pdu_session_id);
}
//Step 7. retrieve Session Management Subscription data from UDM if not available (step 4, section 4.3.2 3GPP TS 23.502)
std::string dnn_selection_mode = smreq->req.get_dnn_selection_mode();
//if the Session Management Subscription data is not available, get from configuration file or UDM
......
......@@ -171,11 +171,12 @@ void smf_pdu_session::get_paa(paa_t &paa) {
void smf_pdu_session::add_qos_flow(const smf_qos_flow &flow) {
if ((flow.qfi.qfi >= QOS_FLOW_IDENTIFIER_FIRST )
and (flow.qfi.qfi <= QOS_FLOW_IDENTIFIER_LAST )) {
Logger::smf_app().trace("QoS Flow (flow Id %d) has been added successfully",
flow.qfi.qfi);
std::unique_lock lock(m_pdu_session_mutex);
qos_flows.erase(flow.qfi.qfi);
qos_flows.insert(
std::pair<uint8_t, smf_qos_flow>((uint8_t) flow.qfi.qfi, flow));
Logger::smf_app().trace("QoS Flow (flow Id %d) has been added successfully",
flow.qfi.qfi);
} else {
Logger::smf_app().error("Failed to add QoS flow (flow Id %d), invalid QFI",
flow.qfi.qfi);
......@@ -185,6 +186,7 @@ void smf_pdu_session::add_qos_flow(const smf_qos_flow &flow) {
//------------------------------------------------------------------------------
bool smf_pdu_session::get_qos_flow(const pfcp::pdr_id_t &pdr_id,
smf_qos_flow &q) {
std::shared_lock lock(m_pdu_session_mutex);
for (auto it : qos_flows) {
if (it.second.pdr_id_ul.rule_id == pdr_id.rule_id) {
q = it.second;
......@@ -201,6 +203,7 @@ bool smf_pdu_session::get_qos_flow(const pfcp::pdr_id_t &pdr_id,
//------------------------------------------------------------------------------
bool smf_pdu_session::get_qos_flow(const pfcp::far_id_t &far_id,
smf_qos_flow &q) {
std::shared_lock lock(m_pdu_session_mutex);
for (auto it : qos_flows) {
if ((it.second.far_id_ul.first)
&& (it.second.far_id_ul.second.far_id == far_id.far_id)) {
......@@ -218,6 +221,7 @@ bool smf_pdu_session::get_qos_flow(const pfcp::far_id_t &far_id,
//------------------------------------------------------------------------------
bool smf_pdu_session::get_qos_flow(const pfcp::qfi_t &qfi, smf_qos_flow &q) {
std::shared_lock lock(m_pdu_session_mutex);
for (auto it : qos_flows) {
if (it.second.qfi == qfi) {
q = it.second;
......@@ -240,6 +244,7 @@ bool smf_pdu_session::get_default_qos_flow(smf_qos_flow &flow) {
//------------------------------------------------------------------------------
void smf_pdu_session::get_qos_flows(std::vector<smf_qos_flow> &flows) {
std::unique_lock lock(m_pdu_session_mutex);
flows.clear();
for (auto it : qos_flows) {
flows.push_back(it.second);
......@@ -249,6 +254,7 @@ void smf_pdu_session::get_qos_flows(std::vector<smf_qos_flow> &flows) {
//------------------------------------------------------------------------------
bool smf_pdu_session::find_qos_flow(const pfcp::pdr_id_t &pdr_id,
smf_qos_flow &flow) {
std::shared_lock lock(m_pdu_session_mutex);
for (std::map<uint8_t, smf_qos_flow>::iterator it = qos_flows.begin();
it != qos_flows.end(); ++it) {
if ((it->second.pdr_id_ul == pdr_id) || (it->second.pdr_id_dl == pdr_id)) {
......@@ -261,6 +267,7 @@ bool smf_pdu_session::find_qos_flow(const pfcp::pdr_id_t &pdr_id,
//------------------------------------------------------------------------------
void smf_pdu_session::remove_qos_flow(const pfcp::qfi_t &qfi) {
std::unique_lock lock(m_pdu_session_mutex);
smf_qos_flow &flow = qos_flows[qfi.qfi];
flow.deallocate_ressources();
qos_flows.erase(qfi.qfi);
......@@ -268,11 +275,22 @@ void smf_pdu_session::remove_qos_flow(const pfcp::qfi_t &qfi) {
//------------------------------------------------------------------------------
void smf_pdu_session::remove_qos_flow(smf_qos_flow &flow) {
std::unique_lock lock(m_pdu_session_mutex);
pfcp::qfi_t qfi = { .qfi = flow.qfi.qfi };
flow.deallocate_ressources();
qos_flows.erase(qfi.qfi);
}
//------------------------------------------------------------------------------
void smf_pdu_session::remove_qos_flows() {
std::unique_lock lock(m_pdu_session_mutex);
for (std::map<uint8_t, smf_qos_flow>::iterator it = qos_flows.begin();
it != qos_flows.end(); ++it) {
it->second.deallocate_ressources();
}
qos_flows.clear();
}
//------------------------------------------------------------------------------
void smf_pdu_session::deallocate_ressources(const std::string &dnn) {
......@@ -375,11 +393,13 @@ void smf_pdu_session::set_pdu_session_status(
Logger::smf_app().info(
"Set PDU Session Status to %s",
pdu_session_status_e2str[static_cast<int>(status)].c_str());
std::unique_lock lock(m_pdu_session_mutex);
pdu_session_status = status;
}
//------------------------------------------------------------------------------
pdu_session_status_e smf_pdu_session::get_pdu_session_status() const {
std::shared_lock lock(m_pdu_session_mutex);
return pdu_session_status;
}
......@@ -387,11 +407,13 @@ pdu_session_status_e smf_pdu_session::get_pdu_session_status() const {
void smf_pdu_session::set_upCnx_state(const upCnx_state_e &state) {
Logger::smf_app().info("Set upCnxState to %s",
upCnx_state_e2str[static_cast<int>(state)].c_str());
std::unique_lock lock(m_pdu_session_mutex);
upCnx_state = state;
}
//------------------------------------------------------------------------------
upCnx_state_e smf_pdu_session::get_upCnx_state() const {
std::shared_lock lock(m_pdu_session_mutex);
return upCnx_state;
}
......@@ -403,6 +425,7 @@ pdn_type_t smf_pdu_session::get_pdn_type() const {
//------------------------------------------------------------------------------
void smf_pdu_session::get_qos_rules_to_be_synchronised(
std::vector<QOSRulesIE> &rules) const {
std::shared_lock lock(m_pdu_session_mutex);
for (auto it : qos_rules_to_be_synchronised) {
if (qos_rules.count(it) > 0)
rules.push_back(qos_rules.at(it));
......@@ -414,6 +437,7 @@ void smf_pdu_session::get_qos_rules(const pfcp::qfi_t &qfi,
std::vector<QOSRulesIE> &rules) const {
Logger::smf_app().info("Get QoS Rules associated with Flow with QFI %d",
qfi.qfi);
std::shared_lock lock(m_pdu_session_mutex);
for (auto it : qos_rules) {
if (it.second.qosflowidentifer == qfi.qfi)
rules.push_back(qos_rules.at(it.first));
......@@ -424,6 +448,7 @@ void smf_pdu_session::get_qos_rules(const pfcp::qfi_t &qfi,
bool smf_pdu_session::get_default_qos_rule(QOSRulesIE &qos_rule) const {
Logger::smf_app().info("Get default QoS Rule this PDU Session (ID %d)",
pdu_session_id);
std::shared_lock lock(m_pdu_session_mutex);
for (auto it : qos_rules) {
if (it.second.dqrbit == THE_QOS_RULE_IS_DEFAULT_QOS_RULE) {
qos_rule = it.second;
......@@ -437,6 +462,7 @@ bool smf_pdu_session::get_default_qos_rule(QOSRulesIE &qos_rule) const {
bool smf_pdu_session::get_qos_rule(const uint8_t rule_id,
QOSRulesIE &qos_rule) const {
Logger::smf_app().info("Find QoS Rule with Rule Id %d", (uint8_t) rule_id);
std::shared_lock lock(m_pdu_session_mutex);
if (qos_rules.count(rule_id) > 0) {
qos_rule = qos_rules.at(rule_id);
}
......@@ -445,6 +471,8 @@ bool smf_pdu_session::get_qos_rule(const uint8_t rule_id,
//------------------------------------------------------------------------------
void smf_pdu_session::update_qos_rule(const QOSRulesIE &qos_rule) {
std::unique_lock lock(m_pdu_session_mutex, std::defer_lock); // Do not lock it first
Logger::smf_app().info("Update QoS Rule with Rule Id %d",
(uint8_t) qos_rule.qosruleidentifer);
uint8_t rule_id = qos_rule.qosruleidentifer;
......@@ -452,6 +480,7 @@ void smf_pdu_session::update_qos_rule(const QOSRulesIE &qos_rule) {
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
if (qos_rules.count(rule_id) > 0) {
lock.lock(); // Lock it here
qos_rules.erase(rule_id);
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, qos_rule));
//marked to be synchronised with UE
......@@ -470,10 +499,11 @@ void smf_pdu_session::update_qos_rule(const QOSRulesIE &qos_rule) {
//------------------------------------------------------------------------------
void smf_pdu_session::mark_qos_rule_to_be_synchronised(const uint8_t rule_id) {
std::unique_lock lock(m_pdu_session_mutex, std::defer_lock); // Do not lock it first
if ((rule_id >= QOS_RULE_IDENTIFIER_FIRST )
and (rule_id <= QOS_RULE_IDENTIFIER_LAST )) {
if (qos_rules.count(rule_id) > 0) {
lock.lock(); // Lock it here
qos_rules_to_be_synchronised.push_back(rule_id);
Logger::smf_app().trace(
"smf_pdu_session::mark_qos_rule_to_be_synchronised(%d) success",
......@@ -493,6 +523,7 @@ void smf_pdu_session::mark_qos_rule_to_be_synchronised(const uint8_t rule_id) {
//------------------------------------------------------------------------------
void smf_pdu_session::add_qos_rule(const QOSRulesIE &qos_rule) {
std::unique_lock lock(m_pdu_session_mutex, std::defer_lock); // Do not lock it first
Logger::smf_app().info("Add QoS Rule with Rule Id %d",
(uint8_t) qos_rule.qosruleidentifer);
uint8_t rule_id = qos_rule.qosruleidentifer;
......@@ -503,6 +534,7 @@ void smf_pdu_session::add_qos_rule(const QOSRulesIE &qos_rule) {
Logger::smf_app().error("Failed to add rule (Id %d), rule existed",
rule_id);
} else {
lock.lock(); // Lock it here
qos_rules.insert(std::pair<uint8_t, QOSRulesIE>(rule_id, qos_rule));
Logger::smf_app().trace("Rule (Id %d) has been added successfully",
rule_id);
......@@ -518,6 +550,7 @@ void smf_pdu_session::add_qos_rule(const QOSRulesIE &qos_rule) {
void session_management_subscription::insert_dnn_configuration(
const std::string &dnn,
std::shared_ptr<dnn_configuration_t> &dnn_configuration) {
std::unique_lock lock(m_mutex);
dnn_configurations.insert(
std::pair<std::string, std::shared_ptr<dnn_configuration_t>>(
dnn, dnn_configuration));
......@@ -528,6 +561,7 @@ void session_management_subscription::find_dnn_configuration(
const std::string &dnn,
std::shared_ptr<dnn_configuration_t> &dnn_configuration) const {
Logger::smf_app().info("Find DNN configuration with DNN %s", dnn.c_str());
std::shared_lock lock(m_mutex);
if (dnn_configurations.count(dnn) > 0) {
dnn_configuration = dnn_configurations.at(dnn);
}
......@@ -536,6 +570,7 @@ void session_management_subscription::find_dnn_configuration(
//------------------------------------------------------------------------------
bool session_management_subscription::dnn_configuration(
const std::string &dnn) const {
std::shared_lock lock(m_mutex);
if (dnn_configurations.count(dnn) > 0) {
return true;
} else {
......@@ -1226,15 +1261,7 @@ void smf_context::handle_pdu_session_create_sm_context_request(
sp.get()->amf_id = smreq->req.get_serving_nf_id(); //amf id
sd->insert_pdu_session(sp);
} else {
Logger::smf_app().debug("PDU session is already existed!");
//TODO: temporary disable this action to test with AMF
/*
//trigger to send reply to AMF
smf_app_inst->trigger_http_response(
http_status_code_e::HTTP_STATUS_CODE_406_NOT_ACCEPTABLE, smreq->pid,
N11_SESSION_CREATE_SM_CONTEXT_RESPONSE);
return;
*/
Logger::smf_app().warn("PDU session is already existed!");
}
//TODO: if "Integrity Protection is required", check UE Integrity Protection Maximum Data Rate
......@@ -2824,7 +2851,7 @@ bool dnn_context::find_pdu_session(
std::shared_ptr<smf_pdu_session> &pdu_session) {
pdu_session = { };
std::unique_lock<std::recursive_mutex> lock(m_context);
std::shared_lock lock(m_context);
for (auto it : pdu_sessions) {
if (pdu_session_id == it->pdu_session_id) {
pdu_session = it;
......@@ -2836,12 +2863,26 @@ bool dnn_context::find_pdu_session(
//------------------------------------------------------------------------------
void dnn_context::insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp) {
std::unique_lock<std::recursive_mutex> lock(m_context);
std::unique_lock lock(m_context);
pdu_sessions.push_back(sp);
}
//------------------------------------------------------------------------------
bool dnn_context::remove_pdu_session(const uint32_t pdu_session_id) {
std::unique_lock lock(m_context);
for (auto it = pdu_sessions.begin(); it != pdu_sessions.end(); ++it) {
if (pdu_session_id == (*it).get()->pdu_session_id) {
(*it).get()->remove_qos_flows();
(*it).get()->clear();
pdu_sessions.erase(it);
return true;
}
}
return false;
}
//------------------------------------------------------------------------------
size_t dnn_context::get_number_pdu_sessions() const {
std::shared_lock lock(m_context);
return pdu_sessions.size();
}
......
......@@ -233,6 +233,12 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
*/
void remove_qos_flow(smf_qos_flow &flow);
/*
* Remove all QoS flow associated with this PDU Session
* @return void
*/
void remove_qos_flows();
/*
* Set current status of PDU Session
* @param [const pdu_session_status_e &] status: status to be set
......@@ -428,8 +434,7 @@ class smf_pdu_session : public std::enable_shared_from_this<smf_pdu_session> {
uint8_t number_of_supported_packet_filters; //number_of_supported_packet_filters
util::uint_generator<uint32_t> qos_rule_id_generator;
// Recursive lock
mutable std::recursive_mutex m_pdu_session_mutex;
mutable std::shared_mutex m_pdu_session_mutex;
};
......@@ -438,7 +443,8 @@ class session_management_subscription {
session_management_subscription(snssai_t snssai)
:
single_nssai(snssai),
dnn_configurations() {
dnn_configurations(),
m_mutex() {
}
/*
......@@ -471,6 +477,7 @@ class session_management_subscription {
private:
snssai_t single_nssai;
std::map<std::string, std::shared_ptr<dnn_configuration_t>> dnn_configurations; //dnn <->dnn_configuration
mutable std::shared_mutex m_mutex;
};
/*
......@@ -513,6 +520,14 @@ class dnn_context {
*/
void insert_pdu_session(std::shared_ptr<smf_pdu_session> &sp);
/*
* Delete a PDU Session identified by its ID
* @param [const uint32_t] pdu_session_id
* @return bool: return true if the pdu session is deleted, otherwise, return false
*/
bool remove_pdu_session(const uint32_t pdu_session_id);
/*
* Get number of pdu sessions associated with this context (dnn and Nssai)
* @param void
......@@ -531,7 +546,7 @@ class dnn_context {
std::string dnn_in_use; // The DNN currently used, as received from the AMF
snssai_t nssai;
std::vector<std::shared_ptr<smf_pdu_session>> pdu_sessions; //Store all PDU Sessions associated with this DNN context
mutable std::recursive_mutex m_context;
mutable std::shared_mutex m_context;
};
class smf_context;
......
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