Commit 8a310228 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Validate NSSAIs

parent 13c9b4e5
......@@ -73,7 +73,7 @@ extern "C" {
#include "dynamic_memory_check.h"
}
using namespace oai::amf::model;
// using namespace oai::amf::model;
using namespace nas;
using namespace amf_application;
using namespace config;
......@@ -1436,8 +1436,9 @@ void amf_n1::run_registration_procedure(std::shared_ptr<nas_context>& nc) {
}
nc.get()->ngKsi = ngksi;
}
// TODO: If AMF can't handle this UE, reroute the Registration Request to a
// new AMF Get UE's slice selection subscription from UDM if not available
// If current AMF can't handle this UE, reroute the Registration Request to
// a target AMF
if (reroute_registration_request(nc)) {
return;
}
......@@ -3708,30 +3709,58 @@ bool amf_n1::reroute_registration_request(std::shared_ptr<nas_context>& nc) {
Logger::amf_n1().debug(
"Registration with AMF re-allocation, Reroute Registration Request to "
"the target AMF");
nssai_t nssai = {};
// Get NSSAI from UDM
oai::amf::model::Nssai nssai = {};
if (!get_slice_selection_subscription_data(nc, nssai)) {
Logger::amf_n1().debug(
"Could not get the Slice Selection Subscription Data from UDM");
return false;
}
// Check that AMF can process the Requested NSSAIs or not
if (check_requested_nssai(nc, nssai)) {
Logger::amf_n1().debug(
"Current AMF can handle all the Subscribed NSSAIs, do not need to "
"perform AMF Re-allocation procedure");
return false;
}
// Process NS selection to select the appropriate AMF
oai::amf::model::SliceInfoForRegistration slice_info = {};
oai::amf::model::AuthorizedNetworkSliceInfo authorized_network_slice_info =
{};
std::vector<SubscribedSnssai> subscribed_snssais;
for (auto n : nssai.getDefaultSingleNssais()) {
SubscribedSnssai subscribed_snssai = {};
subscribed_snssai.setSubscribedSnssai(n);
subscribed_snssai.setDefaultIndication(true);
subscribed_snssais.push_back(subscribed_snssai);
}
slice_info.setSubscribedNssai(subscribed_snssais);
// TODO: To be verified
// slice_info.setRequestedNssai(nssai.getDefaultSingleNssais());
if (!get_network_slice_selection(
nc, amf_app_inst->get_nf_instance(), slice_info,
authorized_network_slice_info)) {
Logger::amf_n1().debug(
"Could not get the Network Slice Selection information from NSSF");
return false;
}
// if get_target_amf();
// Find the appropriate target AMF
std::string target_amf = {};
if (get_target_amf(nc, target_amf, authorized_network_slice_info)) {
Logger::amf_n1().debug("Target AMF %s", target_amf.c_str());
// Send N1MessageNotify to the Target AMF
send_n1_message_notity(nc, target_amf);
return true;
} else {
Logger::amf_n1().debug(
"Could not find an appropriate target AMF to handle UE");
return false;
}
return true;
......@@ -3739,15 +3768,64 @@ bool amf_n1::reroute_registration_request(std::shared_ptr<nas_context>& nc) {
//------------------------------------------------------------------------------
bool amf_n1::check_requested_nssai(
const std::shared_ptr<nas_context>& nc, const nssai_t& nssai) const {
// TODO
const std::shared_ptr<nas_context>& nc, oai::amf::model::Nssai& nssai) {
// Check if the AMF can serve all the subscribed S-NSSAIs
return true;
std::shared_ptr<ue_context> uc = {};
if (!find_ue_context(
nc.get()->ran_ue_ngap_id, nc.get()->amf_ue_ngap_id, uc)) {
Logger::amf_n1().warn("Cannot find the UE context");
return false;
}
bool result = false;
for (auto p : amf_cfg.plmn_list) {
// Check PLMN/TAC
if ((uc.get()->tai.mcc.compare(p.mcc) != 0) or
(uc.get()->tai.mnc.compare(p.mnc) != 0) or
(uc.get()->tai.tac != p.tac)) {
continue;
}
result = true;
// Each S-NSSAI in the Default Single NSSAIs must be in the AMF's Slice List
for (auto n : nssai.getDefaultSingleNssais()) {
bool found_nssai = false;
for (auto s : p.slice_list) {
uint8_t sst = 0;
try {
sst = std::stoi(s.sST);
} catch (const std::exception& err) {
Logger::amf_n1().warn("Invalid SST");
continue;
}
if (sst == n.getSst()) {
if ((n.sdIsSet() and (n.getSd().compare(s.sD) == 0)) or
(!n.sdIsSet() and s.sD.empty())) {
found_nssai = true;
Logger::amf_n1().debug(
"Found S-NSSAI (SST %d, SD %s)", sst, n.getSd().c_str());
break;
}
}
}
if (!found_nssai) {
result = false;
break;
}
}
}
return result;
}
//------------------------------------------------------------------------------
bool amf_n1::get_slice_selection_subscription_data(
const std::shared_ptr<nas_context>& nc, nssai_t& nssai) {
const std::shared_ptr<nas_context>& nc, oai::amf::model::Nssai& nssai) {
// TODO: UDM selection (from NRF or configuration file)
if (amf_cfg.support_features.enable_external_udm) {
std::shared_ptr<ue_context> uc = {};
......@@ -3792,9 +3870,12 @@ bool amf_n1::get_slice_selection_subscription_data(
assert(f.has_value());
assert(!f.has_exception());
// Wait for the result from UDM
nlohmann::json nssai = f.get();
if (!nssai.empty()) {
Logger::ngap().debug("Got NSSAI from UDM: %s", nssai.dump().c_str());
nlohmann::json nssai_json = f.get();
if (!nssai_json.empty()) {
Logger::ngap().debug(
"Got NSSAI from UDM: %s", nssai_json.dump().c_str());
from_json(nssai_json, nssai);
return true;
} else {
return false;
}
......@@ -3812,7 +3893,7 @@ bool amf_n1::get_slice_selection_subscription_data(
//------------------------------------------------------------------------------
bool amf_n1::get_slice_selection_subscription_data_from_conf_file(
const std::shared_ptr<nas_context>& nc, nssai_t& nssai) {
const std::shared_ptr<nas_context>& nc, oai::amf::model::Nssai& nssai) {
// TODO:
return true;
}
......@@ -3911,6 +3992,11 @@ bool amf_n1::get_target_amf(
const oai::amf::model::AuthorizedNetworkSliceInfo&
authorized_network_slice_info) {
// Get Target AMF from AuthorizedNetworkSliceInfo
std::string target_amf_set = {};
if (authorized_network_slice_info.targetAmfSetIsSet()) {
target_amf_set = authorized_network_slice_info.getTargetAmfSet();
}
return true;
}
......
......@@ -38,7 +38,6 @@
#include "3gpp_ts24501.hpp"
#include "3gpp_29.503.h"
#include "3gpp_29.531.h"
#include "amf.hpp"
#include "amf_statistics.hpp"
#include "bstrlib.h"
......@@ -52,6 +51,7 @@
#include "itti.hpp"
#include "SliceInfoForRegistration.h"
#include "AuthorizedNetworkSliceInfo.h"
#include "Nssai.h"
namespace amf_application {
......@@ -223,11 +223,11 @@ class amf_n1 {
bool reroute_registration_request(std::shared_ptr<nas_context>& nc);
bool get_slice_selection_subscription_data(
const std::shared_ptr<nas_context>& nc, nssai_t& nssai);
const std::shared_ptr<nas_context>& nc, oai::amf::model::Nssai& nssai);
bool get_slice_selection_subscription_data_from_conf_file(
const std::shared_ptr<nas_context>& nc, nssai_t& nssai);
const std::shared_ptr<nas_context>& nc, oai::amf::model::Nssai& nssai);
bool check_requested_nssai(
const std::shared_ptr<nas_context>& nc, const nssai_t& nssai) const;
const std::shared_ptr<nas_context>& nc, oai::amf::model::Nssai& nssai);
bool get_network_slice_selection(
const std::shared_ptr<nas_context>& nc, const std::string& nf_instance_id,
const oai::amf::model::SliceInfoForRegistration& slice_info,
......
......@@ -1411,8 +1411,8 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
GlobalgNBId* TargetGlobalgNBId = new GlobalgNBId();
itti_msg.handoverReq->getGlobalRanNodeId(TargetGlobalgNBId);
PlmnId* plmn = new PlmnId();
GNB_ID* gnbid = new GNB_ID();
ngap::PlmnId* plmn = new ngap::PlmnId();
GNB_ID* gnbid = new GNB_ID();
TargetGlobalgNBId->getGlobalgNBId(plmn, gnbid);
std::string mcc = {};
std::string mnc = {};
......@@ -1426,8 +1426,8 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
TAI* tai = new TAI();
itti_msg.handoverReq->getTAI(tai);
PlmnId* plmnOfTAI = new PlmnId();
TAC* tac = new TAC();
ngap::PlmnId* plmnOfTAI = new ngap::PlmnId();
TAC* tac = new TAC();
tai->getTAI(plmnOfTAI, tac);
string mccOfselectTAI = {};
string mncOfselectTAI = {};
......@@ -1478,7 +1478,7 @@ bool amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
guami.regionID = amf_cfg.guami.regionID;
guami.AmfSetID = amf_cfg.guami.AmfSetID;
guami.AmfPointer = amf_cfg.guami.AmfPointer;
PlmnId* m_plmnId = new PlmnId();
ngap::PlmnId* m_plmnId = new ngap::PlmnId();
AMFRegionID* m_aMFRegionID = new AMFRegionID();
AMFSetID* m_aMFSetID = new AMFSetID();
AMFPointer* m_aMFPointer = new AMFPointer();
......
......@@ -28,7 +28,6 @@
#include "amf_profile.hpp"
#include "bstrlib.h"
#include "itti_msg.hpp"
#include "3gpp_29.531.h"
#include "SliceInfoForRegistration.h"
class itti_msg_n11 : public itti_msg {
......
/*
* 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
*/
/**
* Nudm_SDM
* Nudm Subscriber Data Management Service. � 2019, 3GPP Organizational Partners
* (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 2.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator
* (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
* the class manually.
*/
#include "Nssai.h"
namespace oai {
namespace amf {
namespace model {
Nssai::Nssai() {
m_SupportedFeatures = "";
m_SupportedFeaturesIsSet = false;
m_SingleNssaisIsSet = false;
}
Nssai::~Nssai() {}
void Nssai::validate() {
// TODO: implement validation
}
void to_json(nlohmann::json& j, const Nssai& o) {
j = nlohmann::json();
if (o.supportedFeaturesIsSet())
j["supportedFeatures"] = o.m_SupportedFeatures;
j["defaultSingleNssais"] = o.m_DefaultSingleNssais;
if (o.singleNssaisIsSet()) j["singleNssais"] = o.m_SingleNssais;
}
void from_json(const nlohmann::json& j, Nssai& o) {
if (j.find("supportedFeatures") != j.end()) {
j.at("supportedFeatures").get_to(o.m_SupportedFeatures);
o.m_SupportedFeaturesIsSet = true;
}
j.at("defaultSingleNssais").get_to(o.m_DefaultSingleNssais);
if (j.find("singleNssais") != j.end()) {
j.at("singleNssais").get_to(o.m_SingleNssais);
o.m_SingleNssaisIsSet = true;
}
}
std::string Nssai::getSupportedFeatures() const {
return m_SupportedFeatures;
}
void Nssai::setSupportedFeatures(std::string const& value) {
m_SupportedFeatures = value;
m_SupportedFeaturesIsSet = true;
}
bool Nssai::supportedFeaturesIsSet() const {
return m_SupportedFeaturesIsSet;
}
void Nssai::unsetSupportedFeatures() {
m_SupportedFeaturesIsSet = false;
}
std::vector<Snssai>& Nssai::getDefaultSingleNssais() {
return m_DefaultSingleNssais;
}
std::vector<Snssai>& Nssai::getSingleNssais() {
return m_SingleNssais;
}
bool Nssai::singleNssaisIsSet() const {
return m_SingleNssaisIsSet;
}
void Nssai::unsetSingleNssais() {
m_SingleNssaisIsSet = false;
}
} // namespace model
} // namespace amf
} // namespace oai
......@@ -4,8 +4,8 @@
* 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
* file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.openairinterface.org/?page_id=698
*
......@@ -18,78 +18,84 @@
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
/*! \file 3gpp_29.531.h
\brief
\author Tien Thinh NGUYEN
\company Eurecom
\email: tien-thinh.nguyen@eurecom.fr
/**
* Nudm_SDM
* Nudm Subscriber Data Management Service. � 2019, 3GPP Organizational Partners
* (ARIB, ATIS, CCSA, ETSI, TSDSI, TTA, TTC). All rights reserved.
*
* The version of the OpenAPI document: 2.1.0.alpha-1
*
*
* NOTE: This class is auto generated by OpenAPI Generator
* (https://openapi-generator.tech). https://openapi-generator.tech Do not edit
* the class manually.
*/
/*
* Nssai.h
*
*
*/
#ifndef FILE_3GPP_29_531_SEEN
#define FILE_3GPP_29_531_SEEN
#include <stdint.h>
#ifndef Nssai_H_
#define Nssai_H_
#include <nlohmann/json.hpp>
#include <string>
#include <vector>
#include "3gpp_23.003.h"
typedef struct subscribed_snssai_s {
snssai_t subscribed_snssai;
} subscribed_snssai_t;
#include "Snssai.h"
using namespace oai::amf::model;
namespace oai {
namespace amf {
namespace model {
typedef struct nsi_information_s {
std::string nrf_id;
// TODO: nsiId
// TODO: nrfNfMgtUri
// TODO: nrfAccessTokenUri
} nsi_information_t;
/// <summary>
///
/// </summary>
class Nssai {
public:
Nssai();
virtual ~Nssai();
typedef struct allowed_snssai_s {
snssai_t allowed_snssai;
std::vector<nsi_information_t> nsi_information_list;
snssai_t mapped_home_snssai;
} allowed_snssai_t;
void validate();
typedef struct allowed_nssai_s {
std::vector<allowed_snssai_t> allowed_snssai_list;
std::string access_type;
} allowed_nssai_t;
/////////////////////////////////////////////
/// Nssai members
typedef struct mapping_of_snssai_s {
snssai_t serving_snssai;
snssai_t home_snssai;
} mapping_of_snssai_t;
/// <summary>
///
/// </summary>
std::string getSupportedFeatures() const;
void setSupportedFeatures(std::string const& value);
bool supportedFeaturesIsSet() const;
void unsetSupportedFeatures();
/// <summary>
///
/// </summary>
std::vector<Snssai>& getDefaultSingleNssais();
/// <summary>
///
/// </summary>
std::vector<Snssai>& getSingleNssais();
bool singleNssaisIsSet() const;
void unsetSingleNssais();
typedef struct slice_info_for_registration_s {
std::vector<subscribed_snssai_t> subscribed_nssai;
std::vector<allowed_nssai_t> allowed_nssai_current_access;
// allowed_nssai_other_access
std::vector<snssai_t> sNssai_for_mapping;
std::vector<snssai_t> requested_nssai;
bool default_configured_snssai_ind;
std::vector<mapping_of_snssai_t> mapping_of_nssai;
bool request_mapping;
} slice_info_for_registration_t;
friend void to_json(nlohmann::json& j, const Nssai& o);
friend void from_json(const nlohmann::json& j, Nssai& o);
typedef struct configured_snssai_s {
snssai_t configured_snssai;
snssai_t mapped_home_snssai;
} configured_snssai_t;
protected:
std::string m_SupportedFeatures;
bool m_SupportedFeaturesIsSet;
std::vector<Snssai> m_DefaultSingleNssais;
typedef struct authorized_network_slice_info_s {
std::vector<allowed_nssai_t> allowed_nssai_list;
std::vector<configured_snssai_t> configured_nssai;
std::string target_amf_set;
std::vector<std::string> candidate_amf_list;
std::vector<snssai_t> rejected_nssai_in_plmn;
std::vector<snssai_t> rejected_nssai_in_ta;
nsi_information_t nsi_information;
// SupportedFeatures
std::string nrf_amf_set;
std::string nrf_amf_set_nf_mgt_uri;
std::string nrf_amf_set_access_token_uri;
std::vector<Snssai> m_SingleNssais;
bool m_SingleNssaisIsSet;
};
} authorized_network_slice_info_t;
} // namespace model
} // namespace amf
} // namespace oai
#endif
#endif /* Nssai_H_ */
......@@ -34,7 +34,7 @@
#include "3gpp_29.518.h"
using namespace amf_application;
using namespace oai::amf::model;
// using namespace oai::amf::model;
namespace xgpp_conv {
/*
......
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