Commit a144c1de authored by dukl's avatar dukl

handle abnormal conditions

parent e4f2b911
/*
* 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 amf_app.cpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#include "amf_app.hpp" #include "amf_app.hpp"
#include <stdexcept>
#include <iostream>
#include <cstdlib>
#include "itti.hpp" #include "itti.hpp"
#include "ngap_app.hpp" #include "ngap_app.hpp"
#include "amf_config.hpp" #include "amf_config.hpp"
#include "amf_n2.hpp" #include "amf_n2.hpp"
#include "amf_n1.hpp" #include "amf_n1.hpp"
#include "amf_n11.hpp" #include "amf_n11.hpp"
#include <stdexcept>
#include <iostream>
#include <cstdlib>
#include "amf_statistics.hpp" #include "amf_statistics.hpp"
#include "DLNASTransport.hpp" #include "DLNASTransport.hpp"
using namespace ngap; using namespace ngap;
...@@ -47,161 +18,160 @@ using namespace amf_application; ...@@ -47,161 +18,160 @@ using namespace amf_application;
using namespace config; using namespace config;
extern void print_buffer(const std::string app, const std::string commit, uint8_t *buf, int len); extern void print_buffer(const std::string app, const std::string commit, uint8_t *buf, int len);
extern amf_app *amf_app_inst; extern amf_app * amf_app_inst;
extern itti_mw *itti_inst; extern itti_mw * itti_inst;
amf_n2 *amf_n2_inst = nullptr; amf_n2 * amf_n2_inst = nullptr;
amf_n1 *amf_n1_inst = nullptr; amf_n1 * amf_n1_inst = nullptr;
amf_n11 *amf_n11_inst = nullptr; amf_n11 * amf_n11_inst = nullptr;
extern amf_config amf_cfg; extern amf_config amf_cfg;
extern statistics stacs; extern statistics stacs;
void amf_app_task(void*); void amf_app_task(void*);
uint32_t golbal_tmsi = 1; uint32_t golbal_tmsi = 1;
//------------------------------------------------------------------------------ amf_app::amf_app(const amf_config &amf_cfg){
amf_app::amf_app(const amf_config &amf_cfg) { Logger::amf_app().startup("Creating amf application functionality layer");
Logger::amf_app().startup("Creating AMF application functionality layer"); if(itti_inst->create_task(TASK_AMF_APP, amf_app_task, nullptr)){
if (itti_inst->create_task(TASK_AMF_APP, amf_app_task, nullptr)) { Logger::amf_app().error( "Cannot create task TASK_AMF_APP" );
Logger::amf_app().error("Cannot create task TASK_AMF_APP"); throw std::runtime_error( "Cannot create task TASK_AMF_APP" );
throw std::runtime_error("Cannot create task TASK_AMF_APP");
} }
try{
try { amf_n2_inst = new amf_n2(std::string(inet_ntoa(amf_cfg.n2.addr4)),amf_cfg.n2.port);
}catch(std::exception& e){
Logger::amf_app().error( "Cannot create amf n2 interface: %s", e.what() );
throw;
}
try{
amf_n1_inst = new amf_n1(); amf_n1_inst = new amf_n1();
amf_n2_inst = new amf_n2(std::string(inet_ntoa(amf_cfg.n2.addr4)), amf_cfg.n2.port); }catch(std::exception& e){
Logger::amf_app().error( "Cannot create amf n1 interface: %s", e.what() );
}
try{
amf_n11_inst = new amf_n11(); amf_n11_inst = new amf_n11();
} catch (std::exception &e) { }catch(std::exception& e){
Logger::amf_app().error("Cannot create AMF APP: %s", e.what()); Logger::amf_app().error( "Cannot create amf n11 interface: %s", e.what() );
throw;
} }
timer_id_t tid = itti_inst->timer_setup(amf_cfg.statistics_interval,0,TASK_AMF_APP,TASK_AMF_APP_PERIODIC_STATISTICS,0);
timer_id_t tid = itti_inst->timer_setup(amf_cfg.statistics_interval, 0, TASK_AMF_APP, TASK_AMF_APP_PERIODIC_STATISTICS, 0); Logger::amf_app().startup( "Started timer(%d)", tid);
Logger::amf_app().startup("Started timer(%d)", tid);
} }
//------------------------------------------------------------------------------ void amf_app::allRegistredModulesInit(const amf_modules & modules){
void amf_app::allRegistredModulesInit(const amf_modules &modules) { Logger::amf_app().info("Initiating all registred modules");
Logger::amf_app().info("Initiating all registered modules");
} }
//------------------------------------------------------------------------------ void amf_app_task(void*){
void amf_app_task(void*) {
const task_id_t task_id = TASK_AMF_APP; const task_id_t task_id = TASK_AMF_APP;
itti_inst->notify_task_ready(task_id); itti_inst->notify_task_ready(task_id);
do { do {
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id); std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get(); auto *msg = shared_msg.get();
timer_id_t tid; timer_id_t tid;
switch (msg->msg_type) { switch(msg->msg_type){
case NAS_SIG_ESTAB_REQ: { case NAS_SIG_ESTAB_REQ:{
Logger::amf_app().debug("Received NAS_SIG_ESTAB_REQ"); Logger::amf_app().debug("Received NAS_SIG_ESTAB_REQ");
itti_nas_signalling_establishment_request *m = dynamic_cast<itti_nas_signalling_establishment_request*>(msg); itti_nas_signalling_establishment_request *m = dynamic_cast<itti_nas_signalling_establishment_request*>(msg);
amf_app_inst->handle_itti_message(ref(*m)); amf_app_inst->handle_itti_message(ref(*m));
} }break;
break;
case N1N2_MESSAGE_TRANSFER_REQ: { case N1N2_MESSAGE_TRANSFER_REQ:{
Logger::amf_app().debug("Received N1N2_MESSAGE_TRANSFER_REQ"); Logger::amf_app().debug("Received N1N2_MESSAGE_TRANSFER_REQ");
itti_n1n2_message_transfer_request *m = dynamic_cast<itti_n1n2_message_transfer_request*>(msg); itti_n1n2_message_transfer_request *m = dynamic_cast<itti_n1n2_message_transfer_request*>(msg);
amf_app_inst->handle_itti_message(ref(*m)); amf_app_inst->handle_itti_message(ref(*m));
} }break;
break;
case TIME_OUT: case TIME_OUT:
if (itti_msg_timeout *to = dynamic_cast<itti_msg_timeout*>(msg)) { if (itti_msg_timeout* to = dynamic_cast<itti_msg_timeout*>(msg)) {
switch (to->arg1_user) { switch(to->arg1_user){
case TASK_AMF_APP_PERIODIC_STATISTICS: case TASK_AMF_APP_PERIODIC_STATISTICS:
tid = itti_inst->timer_setup(amf_cfg.statistics_interval, 0, TASK_AMF_APP, TASK_AMF_APP_PERIODIC_STATISTICS, 0); tid = itti_inst->timer_setup(amf_cfg.statistics_interval,0,TASK_AMF_APP,TASK_AMF_APP_PERIODIC_STATISTICS,0);
//Logger::amf_app().info("statistics(ready to be implemented)");
stacs.display(); stacs.display();
break; break;
default: default:
Logger::amf_app().info("No handler for timer(%d) with arg1_user(%d) ", to->timer_id, to->arg1_user); Logger::amf_app().info( "no handler for timer(%d) with arg1_user(%d) ", to->timer_id, to->arg1_user);
} }
} }
break; break;
default: default:
Logger::amf_app().info("no handler for msg type %d", msg->msg_type); Logger::amf_app().info( "no handler for msg type %d", msg->msg_type);
} }
} while (true); shared_msg.reset();
}while(true);
} }
//------------------------------------------------------------------------------ long amf_app::generate_amf_ue_ngap_id(){
long amf_app::generate_amf_ue_ngap_id() {
long tmp = 0; long tmp = 0;
tmp = __sync_fetch_and_add(&amf_app_ue_ngap_id_generator, 1); tmp = __sync_fetch_and_add(&amf_app_ue_ngap_id_generator,1);
return tmp & 0xffffffffff; return tmp & 0xffffffffff;
} }
//------------------------------------------------------------------------------ /****************************** context management **************************/
bool amf_app::is_amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const { bool amf_app::is_amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx); std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
return bool { amf_ue_ngap_id2ue_ctx.count(amf_ue_ngap_id) > 0 }; return bool{amf_ue_ngap_id2ue_ctx.count(amf_ue_ngap_id) > 0};
} }
//------------------------------------------------------------------------------ std::shared_ptr<ue_context> amf_app::amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const {
std::shared_ptr<ue_context> amf_app::amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx); std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
return amf_ue_ngap_id2ue_ctx.at(amf_ue_ngap_id); return amf_ue_ngap_id2ue_ctx.at(amf_ue_ngap_id);
} }
//------------------------------------------------------------------------------ void amf_app::set_amf_ue_ngap_id_2_ue_context(const long & amf_ue_ngap_id, std::shared_ptr<ue_context> uc){
void amf_app::set_amf_ue_ngap_id_2_ue_context(const long &amf_ue_ngap_id, std::shared_ptr<ue_context> uc) {
std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx); std::shared_lock lock(m_amf_ue_ngap_id2ue_ctx);
amf_ue_ngap_id2ue_ctx[amf_ue_ngap_id] = uc; amf_ue_ngap_id2ue_ctx[amf_ue_ngap_id] = uc;
} }
//------------------------------------------------------------------------------ bool amf_app::is_ran_amf_id_2_ue_context(const string & ue_context_key) const {
bool amf_app::is_ran_amf_id_2_ue_context(const string &ue_context_key) const {
std::shared_lock lock(m_ue_ctx_key); std::shared_lock lock(m_ue_ctx_key);
return bool { ue_ctx_key.count(ue_context_key) > 0 }; return bool{ue_ctx_key.count(ue_context_key) > 0};
} }
//------------------------------------------------------------------------------ std::shared_ptr<ue_context> amf_app::ran_amf_id_2_ue_context(const string & ue_context_key) const{
std::shared_ptr<ue_context> amf_app::ran_amf_id_2_ue_context(const string &ue_context_key) const {
std::shared_lock lock(m_ue_ctx_key); std::shared_lock lock(m_ue_ctx_key);
return ue_ctx_key.at(ue_context_key); return ue_ctx_key.at(ue_context_key);
} }
//------------------------------------------------------------------------------ void amf_app::set_ran_amf_id_2_ue_context(const string & ue_context_key, std::shared_ptr<ue_context> uc){
void amf_app::set_ran_amf_id_2_ue_context(const string &ue_context_key, std::shared_ptr<ue_context> uc) {
std::shared_lock lock(m_ue_ctx_key); std::shared_lock lock(m_ue_ctx_key);
ue_ctx_key[ue_context_key] = uc; ue_ctx_key[ue_context_key] = uc;
} }
/****************************** itti handlers *******************************/
// ITTI handlers void amf_app::handle_itti_message(itti_n1n2_message_transfer_request & itti_msg){
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(itti_n1n2_message_transfer_request &itti_msg) {
//1. encode DL NAS TRANSPORT message(NAS message) //1. encode DL NAS TRANSPORT message(NAS message)
DLNASTransport *dl = new DLNASTransport(); DLNASTransport * dl = new DLNASTransport();
dl->setHeader(PLAIN_5GS_MSG); dl->setHeader(PLAIN_5GS_MSG);
dl->setPayload_Container_Type(N1_SM_INFORMATION); dl->setPayload_Container_Type(N1_SM_INFORMATION);
dl->setPayload_Container((uint8_t*) bdata(itti_msg.n1sm), blength(itti_msg.n1sm)); dl->setPayload_Container((uint8_t*)bdata(itti_msg.n1sm), blength(itti_msg.n1sm));
dl->setPDUSessionId(itti_msg.pdu_session_id); dl->setPDUSessionId(itti_msg.pdu_session_id);
uint8_t nas[1024]; uint8_t nas[1024];
int encoded_size = dl->encode2buffer(nas, 1024); int encoded_size = dl->encode2buffer(nas, 1024);
print_buffer("amf_app", "n1n2 transfer", nas, encoded_size); print_buffer("amf_app", "n1n2 transfer", nas, encoded_size-1);
bstring dl_nas = blk2bstr(nas, encoded_size); bstring dl_nas = blk2bstr(nas,encoded_size);
itti_downlink_nas_transfer *dl_msg = new itti_downlink_nas_transfer(TASK_AMF_APP, TASK_AMF_N1); itti_downlink_nas_transfer * dl_msg = new itti_downlink_nas_transfer(TASK_AMF_APP, TASK_AMF_N1);
Logger::amf_app().debug("new itti_downlink_nas_transfer");
dl_msg->dl_nas = dl_nas; dl_msg->dl_nas = dl_nas;
if (!itti_msg.is_n2sm_set) { if(!itti_msg.is_n2sm_set){
dl_msg->is_n2sm_set = false; dl_msg->is_n2sm_set = false;
} else { }else{
dl_msg->n2sm = itti_msg.n2sm; dl_msg->n2sm = itti_msg.n2sm;
dl_msg->pdu_session_id = itti_msg.pdu_session_id; dl_msg->pdu_session_id = itti_msg.pdu_session_id;
dl_msg->is_n2sm_set = true; dl_msg->is_n2sm_set = true;
} }
Logger::amf_app().debug("itti_msg.is_n2sm_set after");
dl_msg->amf_ue_ngap_id = amf_n1_inst->supi2amfId.at(itti_msg.supi); dl_msg->amf_ue_ngap_id = amf_n1_inst->supi2amfId.at(itti_msg.supi);
dl_msg->ran_ue_ngap_id = amf_n1_inst->supi2ranId.at(itti_msg.supi); dl_msg->ran_ue_ngap_id = amf_n1_inst->supi2ranId.at(itti_msg.supi);
std::shared_ptr<itti_downlink_nas_transfer> i = std::shared_ptr < itti_downlink_nas_transfer > (dl_msg); Logger::amf_app().debug("dl_msg->ran_ue_ngap_id after");
std::shared_ptr<itti_downlink_nas_transfer> i = std::shared_ptr<itti_downlink_nas_transfer>(dl_msg);
int ret = itti_inst->send_msg(i); int ret = itti_inst->send_msg(i);
Logger::amf_app().debug("send_msg");
if (0 != ret) { if (0 != ret) {
Logger::amf_app().error("Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name()); Logger::amf_app().error( "Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
} }
} }
//------------------------------------------------------------------------------ void amf_app::handle_itti_message(itti_nas_signalling_establishment_request & itti_msg){
void amf_app::handle_itti_message(itti_nas_signalling_establishment_request &itti_msg) {
//1. generate amf_ue_ngap_id //1. generate amf_ue_ngap_id
//2. establish ue_context associated with amf_ue_ngap_id //2. establish ue_context associated with amf_ue_ngap_id
//3. store ue-reated core information //3. store ue-reated core information
...@@ -210,40 +180,39 @@ void amf_app::handle_itti_message(itti_nas_signalling_establishment_request &itt ...@@ -210,40 +180,39 @@ void amf_app::handle_itti_message(itti_nas_signalling_establishment_request &itt
std::shared_ptr<ue_context> uc; std::shared_ptr<ue_context> uc;
//check ue context with 5g-s-tmsi //check ue context with 5g-s-tmsi
if ((amf_ue_ngap_id = itti_msg.amf_ue_ngap_id) == -1) { if(amf_ue_ngap_id = itti_msg.amf_ue_ngap_id == -1){
amf_ue_ngap_id = generate_amf_ue_ngap_id(); amf_ue_ngap_id = generate_amf_ue_ngap_id();
} }
string ue_context_key = "app_ue_ranid_" + to_string(itti_msg.ran_ue_ngap_id) + ":amfid_" + to_string(amf_ue_ngap_id); string ue_context_key = "app_ue_ranid_"+to_string(itti_msg.ran_ue_ngap_id)+":amfid_"+to_string(amf_ue_ngap_id);
//if(!is_amf_ue_id_2_ue_context(amf_ue_ngap_id)){ //if(!is_amf_ue_id_2_ue_context(amf_ue_ngap_id)){
if (!is_ran_amf_id_2_ue_context(ue_context_key)) { if(!is_ran_amf_id_2_ue_context(ue_context_key)){
Logger::amf_app().debug("No existing UE Context, Create a new one with ran_amf_id %s", ue_context_key.c_str()); Logger::amf_app().debug("no existed ue_context, Create one with ran_amf_id(%s)", ue_context_key.c_str());
uc = std::shared_ptr < ue_context > (new ue_context()); uc = std::shared_ptr<ue_context>(new ue_context());
//set_amf_ue_ngap_id_2_ue_context(amf_ue_ngap_id, uc); //set_amf_ue_ngap_id_2_ue_context(amf_ue_ngap_id, uc);
set_ran_amf_id_2_ue_context(ue_context_key, uc); set_ran_amf_id_2_ue_context(ue_context_key, uc);
} }
if (uc.get() == nullptr) { if(uc.get() == nullptr){
Logger::amf_app().error("Failed to create ue_context with ran_amf_id %s", ue_context_key.c_str()); Logger::amf_app().error("Failed to create ue_context with ran_amf_id(%s)", ue_context_key.c_str());
} else { }else{
uc.get()->cgi = itti_msg.cgi; uc.get()->cgi = itti_msg.cgi;
uc.get()->tai = itti_msg.tai; uc.get()->tai = itti_msg.tai;
if (itti_msg.rrc_cause != -1) if(itti_msg.rrc_cause != -1)
uc.get()->rrc_estb_cause = (e_Ngap_RRCEstablishmentCause) itti_msg.rrc_cause; uc.get()->rrc_estb_cause = (e_Ngap_RRCEstablishmentCause)itti_msg.rrc_cause;
if (itti_msg.ueCtxReq == -1) if(itti_msg.ueCtxReq == -1)
uc.get()->isUeContextRequest = false; uc.get()->isUeContextRequest = false;
else else
uc.get()->isUeContextRequest = true; uc.get()->isUeContextRequest = true;
uc.get()->ran_ue_ngap_id = itti_msg.ran_ue_ngap_id; uc.get()->ran_ue_ngap_id = itti_msg.ran_ue_ngap_id;
uc.get()->amf_ue_ngap_id = amf_ue_ngap_id; uc.get()->amf_ue_ngap_id = amf_ue_ngap_id;
std::string guti; std::string guti; bool is_guti_valid = false;
bool is_guti_valid = false; if(itti_msg.is_5g_s_tmsi_present){
if (itti_msg.is_5g_s_tmsi_present) {
guti = itti_msg.tai.mcc + itti_msg.tai.mnc + amf_cfg.guami.regionID + itti_msg._5g_s_tmsi; guti = itti_msg.tai.mcc + itti_msg.tai.mnc + amf_cfg.guami.regionID + itti_msg._5g_s_tmsi;
is_guti_valid = true; is_guti_valid = true;
Logger::amf_app().debug("Receiving GUTI %s", guti.c_str()); Logger::amf_app().debug("Receiving guti: %s", guti.c_str());
} }
itti_uplink_nas_data_ind *itti_n1_msg = new itti_uplink_nas_data_ind(TASK_AMF_APP, TASK_AMF_N1); itti_uplink_nas_data_ind * itti_n1_msg = new itti_uplink_nas_data_ind(TASK_AMF_APP, TASK_AMF_N1);
itti_n1_msg->amf_ue_ngap_id = amf_ue_ngap_id; itti_n1_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_n1_msg->ran_ue_ngap_id = itti_msg.ran_ue_ngap_id; itti_n1_msg->ran_ue_ngap_id = itti_msg.ran_ue_ngap_id;
itti_n1_msg->is_nas_signalling_estab_req = true; itti_n1_msg->is_nas_signalling_estab_req = true;
...@@ -251,27 +220,29 @@ void amf_app::handle_itti_message(itti_nas_signalling_establishment_request &itt ...@@ -251,27 +220,29 @@ void amf_app::handle_itti_message(itti_nas_signalling_establishment_request &itt
itti_n1_msg->mcc = itti_msg.tai.mcc; itti_n1_msg->mcc = itti_msg.tai.mcc;
itti_n1_msg->mnc = itti_msg.tai.mnc; itti_n1_msg->mnc = itti_msg.tai.mnc;
itti_n1_msg->is_guti_valid = is_guti_valid; itti_n1_msg->is_guti_valid = is_guti_valid;
if (is_guti_valid) { if(is_guti_valid){
itti_n1_msg->guti = guti; itti_n1_msg->guti = guti;
} }
std::shared_ptr<itti_uplink_nas_data_ind> i = std::shared_ptr < itti_uplink_nas_data_ind > (itti_n1_msg); std::shared_ptr<itti_uplink_nas_data_ind> i = std::shared_ptr<itti_uplink_nas_data_ind>(itti_n1_msg);
int ret = itti_inst->send_msg(i); int ret = itti_inst->send_msg(i);
if (0 != ret) { if (0 != ret) {
Logger::amf_app().error("Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name()); Logger::amf_app().error( "Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
} }
} }
} }
//SMF Client response handlers
//------------------------------------------------------------------------------ /************************ SMF Client response handlers *****************************/
void amf_app::handle_post_sm_context_response_error_400() { void amf_app::handle_post_sm_context_response_error_400(){
Logger::amf_app().error("Post SM context response error 400"); Logger::amf_app().error("post sm context response error 400");
} }
bool amf_app::generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &mnc, uint32_t &tmsi) { bool amf_app::generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &mnc, uint32_t& tmsi){
string ue_context_key = "app_ue_ranid_" + to_string(ranid) + ":amfid_" + to_string(amfid); string ue_context_key = "app_ue_ranid_"+to_string(ranid)+":amfid_"+to_string(amfid);
if (!is_ran_amf_id_2_ue_context(ue_context_key)) { if(!is_ran_amf_id_2_ue_context(ue_context_key)){
Logger::amf_app().error("No UE context for ran_amf_id %s, exit", ue_context_key.c_str()); Logger::amf_app().error("no ue context for ran_amf_id(%s), exit", ue_context_key.c_str());
return false; return false;
} }
std::shared_ptr<ue_context> uc; std::shared_ptr<ue_context> uc;
...@@ -279,6 +250,6 @@ bool amf_app::generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string & ...@@ -279,6 +250,6 @@ bool amf_app::generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &
mcc = uc.get()->tai.mcc; mcc = uc.get()->tai.mcc;
mnc = uc.get()->tai.mnc; mnc = uc.get()->tai.mnc;
tmsi = golbal_tmsi; tmsi = golbal_tmsi;
golbal_tmsi++; golbal_tmsi ++;
return true; return true;
} }
/*
* 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 amf_app.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _AMF_APP_H_ #ifndef _AMF_APP_H_
#define _AMF_APP_H_ #define _AMF_APP_H_
...@@ -41,42 +13,57 @@ ...@@ -41,42 +13,57 @@
#include "ue_context.hpp" #include "ue_context.hpp"
using namespace config; using namespace config;
using namespace std;
static uint32_t amf_app_ue_ngap_id_generator = 1; static uint32_t amf_app_ue_ngap_id_generator = 1;
namespace amf_application { namespace amf_application{
#define TASK_AMF_APP_PERIODIC_STATISTICS (0) #define TASK_AMF_APP_PERIODIC_STATISTICS (0)
class amf_app { class amf_app{
public: public:
explicit amf_app(const amf_config &amf_cfg); explicit amf_app(const amf_config &amf_cfg);
amf_app(amf_app const&) = delete; amf_app(amf_app const&) = delete;
void operator=(amf_app const&) = delete; void operator=(amf_app const&) = delete;
void allRegistredModulesInit(const amf_modules &modules); void allRegistredModulesInit(const amf_modules & modules);
long generate_amf_ue_ngap_id(); long generate_amf_ue_ngap_id();
//itti handlers public://itti handlers
void handle_itti_message(itti_nas_signalling_establishment_request &itti_msg); void handle_itti_message(itti_nas_signalling_establishment_request & itti_msg);
void handle_itti_message(itti_n1n2_message_transfer_request &itti_msg); void handle_itti_message(itti_n1n2_message_transfer_request & itti_msg);
//context management public://context management
std::map<long, std::shared_ptr<ue_context>> amf_ue_ngap_id2ue_ctx; std::map<long, std::shared_ptr<ue_context>> amf_ue_ngap_id2ue_ctx;
mutable std::shared_mutex m_amf_ue_ngap_id2ue_ctx; mutable std::shared_mutex m_amf_ue_ngap_id2ue_ctx;
std::map<std::string, std::shared_ptr<ue_context>> ue_ctx_key; std::map<std::string, std::shared_ptr<ue_context>> ue_ctx_key;
mutable std::shared_mutex m_ue_ctx_key; mutable std::shared_mutex m_ue_ctx_key;
bool is_amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const; bool is_amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const;
std::shared_ptr<ue_context> amf_ue_id_2_ue_context(const long &amf_ue_ngap_id) const; std::shared_ptr<ue_context> amf_ue_id_2_ue_context(const long & amf_ue_ngap_id) const;
void set_amf_ue_ngap_id_2_ue_context(const long &amf_ue_ngap_id, std::shared_ptr<ue_context> uc); void set_amf_ue_ngap_id_2_ue_context(const long & amf_ue_ngap_id, std::shared_ptr<ue_context> uc);
bool is_ran_amf_id_2_ue_context(const std::string &ue_context_key) const; bool is_ran_amf_id_2_ue_context(const string & ue_context_key) const;
std::shared_ptr<ue_context> ran_amf_id_2_ue_context(const std::string &ue_context_key) const; std::shared_ptr<ue_context> ran_amf_id_2_ue_context(const string & ue_context_key) const;
void set_ran_amf_id_2_ue_context(const std::string &ue_context_key, std::shared_ptr<ue_context> uc); void set_ran_amf_id_2_ue_context(const string & ue_context_key, std::shared_ptr<ue_context> uc);
// SMF Client response handlers public:/*** SMF Client response handlers ****/
void handle_post_sm_context_response_error_400(); void handle_post_sm_context_response_error_400();
//others public:
bool generate_5g_guti(uint32_t ranid, long amfid, std::string &mcc, std::string &mnc, uint32_t &tmsi); bool generate_5g_guti(uint32_t ranid, long amfid, string &mcc, string &mnc, uint32_t& tmsi);
}; };
} }
#endif #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 amf_config.cpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#include "amf_config.hpp" #include "amf_config.hpp"
#include "logger.hpp"
#include <iostream>
#include <libconfig.h++> #include <libconfig.h++>
#include "string.hpp" #include "string.hpp"
#include "thread_sched.hpp" #include "thread_sched.hpp"
#include "logger.hpp"
#include "amf_app.hpp" #include "amf_app.hpp"
#include "if.hpp" #include "if.hpp"
#include "3gpp_ts24501.hpp" #include "3gpp_ts24501.hpp"
extern "C"{
extern "C" { #include <arpa/inet.h>
#include <arpa/inet.h> #include <stdbool.h>
#include <stdbool.h> #include <stdlib.h>
#include <stdlib.h> #include <string.h>
#include <string.h> #include <sys/types.h>
#include <sys/types.h> #include <unistd.h>
#include <unistd.h> #include "common_defs.h"
#include "common_defs.h"
} }
#include <iostream>
using namespace libconfig; using namespace libconfig;
using namespace std;
using namespace amf_application; using namespace amf_application;
namespace config { namespace config{
//------------------------------------------------------------------------------ amf_config::amf_config(){
amf_config::amf_config() { }
//TODO: amf_config::~amf_config(){}
} int amf_config::load(const std::string &config_file){
cout<<endl;
//------------------------------------------------------------------------------ Logger::amf_app().debug("Load amf system configuration file(%s)",config_file.c_str());
amf_config::~amf_config() {
}
//------------------------------------------------------------------------------
int amf_config::load(const std::string &config_file) {
Logger::amf_app().debug("\nLoad AMF system configuration file(%s)", config_file.c_str());
Config cfg; Config cfg;
unsigned char buf_in6_addr[sizeof(struct in6_addr)]; unsigned char buf_in6_addr[sizeof (struct in6_addr)];
try { try{
cfg.readFile(config_file.c_str()); cfg.readFile(config_file.c_str());
} catch (const FileIOException &fioex) { }catch(const FileIOException &fioex){
Logger::amf_app().error("I/O error while reading file %s - %s", config_file.c_str(), fioex.what()); Logger::amf_app().error("I/O error while reading file %s - %s", config_file.c_str(), fioex.what());
throw; throw;
} catch (const ParseException &pex) { }catch(const ParseException &pex){
Logger::amf_app().error("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(), pex.getError()); Logger::amf_app().error("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(), pex.getError());
throw; throw;
} }
const Setting &root = cfg.getRoot(); const Setting &root = cfg.getRoot();
try { try{
const Setting &amf_cfg = root[AMF_CONFIG_STRING_AMF_CONFIG]; const Setting& amf_cfg = root[AMF_CONFIG_STRING_AMF_CONFIG];
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s", nfex.what(), nfex.getPath());
return -1; return -1;
} }
const Setting &amf_cfg = root[AMF_CONFIG_STRING_AMF_CONFIG]; const Setting &amf_cfg = root[AMF_CONFIG_STRING_AMF_CONFIG];
try { try{
amf_cfg.lookupValue(AMF_CONFIG_STRING_INSTANCE_ID, instance); amf_cfg.lookupValue(AMF_CONFIG_STRING_INSTANCE_ID, instance);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
amf_cfg.lookupValue(AMF_CONFIG_STRING_STATISTICS_TIMER_INTERVAL, statistics_interval); amf_cfg.lookupValue(AMF_CONFIG_STRING_STATISTICS_TIMER_INTERVAL, statistics_interval);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
amf_cfg.lookupValue(AMF_CONFIG_STRING_PID_DIRECTORY, pid_dir); amf_cfg.lookupValue(AMF_CONFIG_STRING_PID_DIRECTORY, pid_dir);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
amf_cfg.lookupValue(AMF_CONFIG_STRING_AMF_NAME, AMF_Name); amf_cfg.lookupValue(AMF_CONFIG_STRING_AMF_NAME, AMF_Name);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
const Setting &guami_cfg = amf_cfg[AMF_CONFIG_STRING_GUAMI]; const Setting &guami_cfg = amf_cfg[AMF_CONFIG_STRING_GUAMI];
guami_cfg.lookupValue(AMF_CONFIG_STRING_MCC, guami.mcc); guami_cfg.lookupValue(AMF_CONFIG_STRING_MCC, guami.mcc);
guami_cfg.lookupValue(AMF_CONFIG_STRING_MNC, guami.mnc); guami_cfg.lookupValue(AMF_CONFIG_STRING_MNC, guami.mnc);
guami_cfg.lookupValue(AMF_CONFIG_STRING_RegionID, guami.regionID); guami_cfg.lookupValue(AMF_CONFIG_STRING_RegionID, guami.regionID);
guami_cfg.lookupValue(AMF_CONFIG_STRING_AMFSetID, guami.AmfSetID); guami_cfg.lookupValue(AMF_CONFIG_STRING_AMFSetID, guami.AmfSetID);
guami_cfg.lookupValue(AMF_CONFIG_STRING_AMFPointer, guami.AmfPointer); guami_cfg.lookupValue(AMF_CONFIG_STRING_AMFPointer, guami.AmfPointer);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
const Setting &guami_list_cfg = amf_cfg[AMF_CONFIG_STRING_SERVED_GUAMI_LIST]; const Setting &guami_list_cfg = amf_cfg[AMF_CONFIG_STRING_ServedGUAMIList];
int count = guami_list_cfg.getLength(); int count = guami_list_cfg.getLength();
for (int i = 0; i < count; i++) { for(int i=0;i<count;i++){
guami_t guami; guami_t guami;
const Setting &guami_item = guami_list_cfg[i]; const Setting &guami_item = guami_list_cfg[i];
guami_item.lookupValue(AMF_CONFIG_STRING_MCC, guami.mcc); guami_item.lookupValue(AMF_CONFIG_STRING_MCC,guami.mcc);
guami_item.lookupValue(AMF_CONFIG_STRING_MNC, guami.mnc); guami_item.lookupValue(AMF_CONFIG_STRING_MNC,guami.mnc);
guami_item.lookupValue(AMF_CONFIG_STRING_RegionID, guami.regionID); guami_item.lookupValue(AMF_CONFIG_STRING_RegionID,guami.regionID);
guami_item.lookupValue(AMF_CONFIG_STRING_AMFSetID, guami.AmfSetID); guami_item.lookupValue(AMF_CONFIG_STRING_AMFSetID,guami.AmfSetID);
guami_item.lookupValue(AMF_CONFIG_STRING_AMFPointer, guami.AmfPointer); guami_item.lookupValue(AMF_CONFIG_STRING_AMFPointer,guami.AmfPointer);
guami_list.push_back(guami); guami_list.push_back(guami);
} }
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
amf_cfg.lookupValue(AMF_CONFIG_STRING_RELATIVE_AMF_CAPACITY, relativeAMFCapacity); amf_cfg.lookupValue(AMF_CONFIG_STRING_RelativeAMFCapacity, relativeAMFCapacity);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
const Setting &plmn_list_cfg = amf_cfg[AMF_CONFIG_STRING_PLMN_SUPPORT_LIST]; const Setting &plmn_list_cfg = amf_cfg[AMF_CONFIG_STRING_PLMNSupportList];
int count = plmn_list_cfg.getLength(); int count = plmn_list_cfg.getLength();
for (int i = 0; i < count; i++) { for(int i=0;i<count;i++){
plmn_item_t plmn_item; plmn_item_t plmn_item;
const Setting &item = plmn_list_cfg[i]; const Setting & item = plmn_list_cfg[i];
item.lookupValue(AMF_CONFIG_STRING_MCC, plmn_item.mcc); item.lookupValue(AMF_CONFIG_STRING_MCC, plmn_item.mcc);
item.lookupValue(AMF_CONFIG_STRING_MNC, plmn_item.mnc); item.lookupValue(AMF_CONFIG_STRING_MNC, plmn_item.mnc);
item.lookupValue(AMF_CONFIG_STRING_TAC, plmn_item.tac); item.lookupValue(AMF_CONFIG_STRING_TAC, plmn_item.tac);
const Setting &slice_list_cfg = plmn_list_cfg[i][AMF_CONFIG_STRING_SLICE_SUPPORT_LIST]; const Setting &slice_list_cfg = plmn_list_cfg[i][AMF_CONFIG_STRING_SliceSupportList];
int numOfSlice = slice_list_cfg.getLength(); int numOfSlice = slice_list_cfg.getLength();
for (int j = 0; j < numOfSlice; j++) { for(int j=0;j<numOfSlice;j++){
slice_t slice; slice_t slice;
const Setting &slice_item = slice_list_cfg[j]; const Setting & slice_item = slice_list_cfg[j];
slice_item.lookupValue(AMF_CONFIG_STRING_SST, slice.sST); slice_item.lookupValue(AMF_CONFIG_STRING_SST, slice.sST);
slice_item.lookupValue(AMF_CONFIG_STRING_SD, slice.sD); slice_item.lookupValue(AMF_CONFIG_STRING_SD, slice.sD);
plmn_item.slice_list.push_back(slice); plmn_item.slice_list.push_back(slice);
} }
plmn_list.push_back(plmn_item); plmn_list.push_back(plmn_item);
} }
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try{
const Setting &new_if_cfg = amf_cfg[AMF_CONFIG_STRING_INTERFACES]; const Setting &new_if_cfg = amf_cfg[AMF_CONFIG_STRING_INTERFACES];
const Setting &n2_amf_cfg = new_if_cfg[AMF_CONFIG_STRING_INTERFACE_NGAP_AMF]; const Setting &n2_amf_cfg = new_if_cfg[AMF_CONFIG_STRING_INTERFACE_NGAP_AMF];
load_interface(n2_amf_cfg, n2); load_interface(n2_amf_cfg, n2);
const Setting &n11_cfg = new_if_cfg[AMF_CONFIG_STRING_INTERFACE_N11]; const Setting &n11_cfg = new_if_cfg[AMF_CONFIG_STRING_INTERFACE_N11];
load_interface(n11_cfg, n11);
const Setting &smf_addr_pool = n11_cfg[AMF_CONFIG_STRING_SMF_INSTANCES_POOL]; const Setting &smf_addr_pool = n11_cfg[AMF_CONFIG_STRING_SMF_INSTANCES_POOL];
int count = smf_addr_pool.getLength(); int count = smf_addr_pool.getLength();
for (int i = 0; i < count; i++) { for(int i=0; i< count; i++){
const Setting &smf_addr_item = smf_addr_pool[i]; const Setting & smf_addr_item = smf_addr_pool[i];
smf_inst_t smf_inst; smf_inst_t smf_inst; string selected;
std::string selected;
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_ID, smf_inst.id); smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_ID, smf_inst.id);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, smf_inst.ipv4); smf_addr_item.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, smf_inst.ipv4);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_PORT, smf_inst.port); smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_PORT, smf_inst.port);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_VERSION, smf_inst.version); smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_VERSION, smf_inst.version);
smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_SELECTED, selected); smf_addr_item.lookupValue(AMF_CONFIG_STRING_SMF_INSTANCE_SELECTED, selected);
if (!selected.compare("true")) if(!selected.compare("true"))
smf_inst.selected = true; smf_inst.selected = true;
else else
smf_inst.selected = false; smf_inst.selected = false;
smf_pool.push_back(smf_inst); smf_pool.push_back(smf_inst);
} }
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1; return -1;
} }
try { try{
const Setting &core_config = amf_cfg[AMF_CONFIG_STRING_CORE_CONFIGURATION]; const Setting &core_config = amf_cfg[AMF_CONFIG_STRING_CORE_CONFIGURATION];
core_config.lookupValue(AMF_CONFIG_STRING_EMERGENCY_SUPPORT, is_emergency_support); core_config.lookupValue(AMF_CONFIG_STRING_EMERGENCY_SUPPORT, is_emergency_support);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1; return -1;
} }
try { try{
const Setting &auth = amf_cfg[AMF_CONFIG_STRING_AUTHENTICATION]; const Setting &auth = amf_cfg[AMF_CONFIG_STRING_AUTHENTICATION];
auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_SERVER, auth_para.mysql_server); auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_SERVER, auth_para.mysql_server);
auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_USER, auth_para.mysql_user); auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_USER, auth_para.mysql_user);
...@@ -200,149 +163,132 @@ int amf_config::load(const std::string &config_file) { ...@@ -200,149 +163,132 @@ int amf_config::load(const std::string &config_file) {
auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_DB, auth_para.mysql_db); auth.lookupValue(AMF_CONFIG_STRING_AUTH_MYSQL_DB, auth_para.mysql_db);
auth.lookupValue(AMF_CONFIG_STRING_AUTH_OPERATOR_KEY, auth_para.operator_key); auth.lookupValue(AMF_CONFIG_STRING_AUTH_OPERATOR_KEY, auth_para.operator_key);
auth.lookupValue(AMF_CONFIG_STRING_AUTH_RANDOM, auth_para.random); auth.lookupValue(AMF_CONFIG_STRING_AUTH_RANDOM, auth_para.random);
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1; return -1;
} }
try { try{
const Setting &nas = amf_cfg[AMF_CONFIG_STRING_NAS]; const Setting &nas = amf_cfg[AMF_CONFIG_STRING_NAS];
const Setting &intAlg = nas[AMF_CONFIG_STRING_NAS_SUPPORTED_INTEGRITY_ALGORITHM_LIST]; const Setting &intAlg = nas[AMF_CONFIG_STRING_NAS_SUPPORTED_INTEGRITY_ALGORITHM_LIST];
int intCount = intAlg.getLength(); int intCount = intAlg.getLength();
for (int i = 0; i < intCount; i++) { for(int i=0; i<intCount; i++){
std::string intAlgStr = intAlg[i]; string intAlgStr = intAlg[i];
if (!intAlgStr.compare("NIA0")) if(!intAlgStr.compare("NIA0"))
nas_cfg.prefered_integrity_algorithm[i] = IA0_5G; nas_cfg.prefered_integrity_algorithm[i] = IA0_5G;
if (!intAlgStr.compare("NIA1")) if(!intAlgStr.compare("NIA1"))
nas_cfg.prefered_integrity_algorithm[i] = IA1_128_5G; nas_cfg.prefered_integrity_algorithm[i] = IA1_128_5G;
if (!intAlgStr.compare("NIA2")) if(!intAlgStr.compare("NIA2"))
nas_cfg.prefered_integrity_algorithm[i] = IA2_128_5G; nas_cfg.prefered_integrity_algorithm[i] = IA2_128_5G;
} }
for (int i = intCount; i < 8; i++) { for(int i=intCount; i<8; i++){
nas_cfg.prefered_integrity_algorithm[i] = IA0_5G; nas_cfg.prefered_integrity_algorithm[i] = IA0_5G;
} }
const Setting &encAlg = nas[AMF_CONFIG_STRING_NAS_SUPPORTED_CIPHERING_ALGORITHM_LIST]; const Setting &encAlg = nas[AMF_CONFIG_STRING_NAS_SUPPORTED_CIPHERING_ALGORITHM_LIST];
int encCount = encAlg.getLength(); int encCount = encAlg.getLength();
for (int i = 0; i < encCount; i++) { for(int i=0; i<encCount; i++){
std::string encAlgStr = encAlg[i]; string encAlgStr = encAlg[i];
if (!encAlgStr.compare("NEA0")) if(!encAlgStr.compare("NEA0"))
nas_cfg.prefered_ciphering_algorithm[i] = EA0_5G; nas_cfg.prefered_ciphering_algorithm[i] = EA0_5G;
if (!encAlgStr.compare("NEA1")) if(!encAlgStr.compare("NEA1"))
nas_cfg.prefered_ciphering_algorithm[i] = EA1_128_5G; nas_cfg.prefered_ciphering_algorithm[i] = EA1_128_5G;
if (!encAlgStr.compare("NEA2")) if(!encAlgStr.compare("NEA2"))
nas_cfg.prefered_ciphering_algorithm[i] = EA2_128_5G; nas_cfg.prefered_ciphering_algorithm[i] = EA2_128_5G;
} }
for (int i = encCount; i < 8; i++) { for(int i=encCount; i<8; i++){
nas_cfg.prefered_ciphering_algorithm[i] = EA0_5G; nas_cfg.prefered_ciphering_algorithm[i] = EA0_5G;
} }
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
return -1; return -1;
} }
} }
//------------------------------------------------------------------------------
void amf_config::display() {
Logger::config().info("====================== AMF =====================");
Logger::config().info("Configuration AMF:");
Logger::config().info("- Instance ...........................................: %d", instance);
Logger::config().info("- PID dir ............................................: %s", pid_dir.c_str());
Logger::config().info("- AMF NAME............................................: %s", AMF_Name.c_str());
Logger::config().info("- GUAMI (MCC, MNC, Region ID, AMF Set ID, AMF pointer): ");
Logger::config().info(" (%s, %s, %s, %s, %s )", guami.mcc.c_str(), guami.mnc.c_str(), guami.regionID.c_str(), guami.AmfSetID.c_str(), guami.AmfPointer.c_str());
Logger::config().info("- SERVED_GUAMI_LIST...................................: ");
for (int i = 0; i < guami_list.size(); i++) {
Logger::config().info(" (%s, %s, %s , %s, %s)", guami_list[i].mcc.c_str(), guami_list[i].mnc.c_str(), guami_list[i].regionID.c_str(), guami_list[i].AmfSetID.c_str(), guami_list[i].AmfPointer.c_str());
}
Logger::config().info("- RELATIVE_CAPACITY...................................: %d", relativeAMFCapacity);
Logger::config().info("- PLMN_SUPPORT_LIST...................................: ");
for (int i = 0; i < plmn_list.size(); i++) {
Logger::config().info(" (MCC %s, MNC %s) ", plmn_list[i].mcc.c_str(), plmn_list[i].mnc.c_str());
Logger::config().info(" TAC: %d", plmn_list[i].tac);
Logger::config().info(" SLICE_SUPPORT_LIST (SST, SD) ....................: ");
for (int j = 0; j < plmn_list[i].slice_list.size(); j++) {
Logger::config().info(" (%s, %s) ", plmn_list[i].slice_list[j].sST.c_str(), plmn_list[i].slice_list[j].sD.c_str());
}
}
Logger::config().info("- Emergency Support................... ...............: %s", is_emergency_support.c_str());
Logger::config().info("- MYSQL Server Addr...................................: %s", auth_para.mysql_server.c_str());
Logger::config().info("- MYSQL user .........................................: %s", auth_para.mysql_user.c_str());
Logger::config().info("- MYSQL pass .........................................: %s", auth_para.mysql_pass.c_str());
Logger::config().info("- MYSQL db ...........................................: %s", auth_para.mysql_db.c_str());
Logger::config().info("- operator key .......................................: %s", auth_para.operator_key.c_str());
Logger::config().info("- random .............................................: %s", auth_para.random.c_str());
Logger::config().info("- N2 Networking:");
Logger::config().info(" iface ................: %s", n2.if_name.c_str());
Logger::config().info(" ip ...................: %s", inet_ntoa(n2.addr4));
Logger::config().info(" port .................: %d", n2.port);
Logger::config().info("- N11 Networking:");
Logger::config().info(" iface ................: %s", n11.if_name.c_str());
Logger::config().info(" ip ...................: %s",
inet_ntoa(n11.addr4));
Logger::config().info(" port .................: %d", n11.port);
// Logger::config().info(" HTTP2 port ............: %d", n11_http2_port);
Logger::config().info("- Remote SMF Pool.....................................: "); void amf_config::display(){
for (int i = 0; i < smf_pool.size(); i++) { Logger::config().info( "======= BUPTv1.0 =======");
std::string selected; Logger::config().info( "Configuration AMF:");
if (smf_pool[i].selected) Logger::config().info( "- Instance .......................: %d", instance);
selected = "true"; Logger::config().info( "- PID dir ........................: %s", pid_dir.c_str());
else Logger::config().info( "- AMF NAME........................: %s", AMF_Name.c_str());
selected = "false"; Logger::config().info( "- GUAMI...........................: ");
Logger::config().info(" SMF_INSTANCE_ID %d (%s:%s, version %s) is selected: %s", smf_pool[i].id, smf_pool[i].ipv4.c_str(), smf_pool[i].port.c_str(), smf_pool[i].version.c_str(), selected.c_str()); Logger::config().info( " [%s] [%s] [%s] [%s] [%s]", guami.mcc.c_str(),guami.mnc.c_str(),guami.regionID.c_str(),guami.AmfSetID.c_str(),guami.AmfPointer.c_str());
Logger::config().info( "- ServedGUAMIList ................: ");
for(int i=0;i<guami_list.size();i++){
Logger::config().info( " [%s] [%s] [%s] [%s] [%s]", guami_list[i].mcc.c_str(),guami_list[i].mnc.c_str(),guami_list[i].regionID.c_str(),guami_list[i].AmfSetID.c_str(),guami_list[i].AmfPointer.c_str());
}
Logger::config().info( "- RelativeAMFCapacity ............: %d", relativeAMFCapacity);
Logger::config().info( "- PLMNSupportList ................: ");
for(int i=0;i<plmn_list.size();i++){
Logger::config().info( " [%s] [%s] ", plmn_list[i].mcc.c_str(),plmn_list[i].mnc.c_str());
Logger::config().info( " tac[%d]", plmn_list[i].tac);
Logger::config().info( " - SliceSupportList ............: ");
for(int j=0;j<plmn_list[i].slice_list.size();j++){
Logger::config().info( " [%s] [%s] ", plmn_list[i].slice_list[j].sST.c_str(),plmn_list[i].slice_list[j].sD.c_str());
}
}
Logger::config().info( "- Emergency Support ...............: %s", is_emergency_support.c_str());
Logger::config().info( "- MYSQL server ....................: %s", auth_para.mysql_server.c_str());
Logger::config().info( "- MYSQL user ......................: %s", auth_para.mysql_user.c_str());
Logger::config().info( "- MYSQL pass ......................: %s", auth_para.mysql_pass.c_str());
Logger::config().info( "- MYSQL db ........................: %s", auth_para.mysql_db.c_str());
Logger::config().info( "- operator key ....................: %s", auth_para.operator_key.c_str());
Logger::config().info( "- random ..........................: %s", auth_para.random.c_str());
Logger::config().info( "- Remote SMF Pool..................: ");
for(int i=0; i<smf_pool.size(); i++){
string selected;
if(smf_pool[i].selected) selected = "true";
else selected = "false";
Logger::config().info( " SMF_INSTANCE_ID(%d) : (%s:%s) version(%s) is selected(%s)", smf_pool[i].id, smf_pool[i].ipv4.c_str(), smf_pool[i].port.c_str(), smf_pool[i].version.c_str(), selected.c_str());
}
} }
}
//------------------------------------------------------------------------------ int amf_config::load_interface(const libconfig::Setting& if_cfg, interface_cfg_t& cfg){
int amf_config::load_interface(const libconfig::Setting &if_cfg, interface_cfg_t &cfg) {
if_cfg.lookupValue(AMF_CONFIG_STRING_INTERFACE_NAME, cfg.if_name); if_cfg.lookupValue(AMF_CONFIG_STRING_INTERFACE_NAME, cfg.if_name);
util::trim(cfg.if_name); util::trim(cfg.if_name);
if (not boost::iequals(cfg.if_name, "none")) { if (not boost::iequals(cfg.if_name, "none")) {
std::string address = { }; std::string address = {};
if_cfg.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, address); if_cfg.lookupValue(AMF_CONFIG_STRING_IPV4_ADDRESS, address);
util::trim(address); util::trim(address);
if (boost::iequals(address, "read")) { if (boost::iequals(address, "read")) {
if (get_inet_addr_infos_from_iface(cfg.if_name, cfg.addr4, cfg.network4, cfg.mtu)) { if (get_inet_addr_infos_from_iface(cfg.if_name, cfg.addr4, cfg.network4, cfg.mtu)) {
Logger::amf_app().error("Could not read %s network interface configuration", cfg.if_name); Logger::amf_app().error("Could not read %s network interface configuration", cfg.if_name);
return RETURNerror ; return RETURNerror;
} }
} else { } else {
std::vector < std::string > words; std::vector<std::string> words;
boost::split(words, address, boost::is_any_of("/"), boost::token_compress_on); boost::split(words, address, boost::is_any_of("/"), boost::token_compress_on);
if (words.size() != 2) { if (words.size() != 2) {
Logger::amf_app().error("Bad value " AMF_CONFIG_STRING_IPV4_ADDRESS " = %s in config file", address.c_str()); Logger::amf_app().error("Bad value " AMF_CONFIG_STRING_IPV4_ADDRESS " = %s in config file", address.c_str());
return RETURNerror ; return RETURNerror;
} }
unsigned char buf_in_addr[sizeof(struct in6_addr)]; // you never know... unsigned char buf_in_addr[sizeof(struct in6_addr)]; // you never know...
if (inet_pton(AF_INET, util::trim(words.at(0)).c_str(), buf_in_addr) == 1) { if (inet_pton (AF_INET, util::trim(words.at(0)).c_str(), buf_in_addr) == 1) {
memcpy(&cfg.addr4, buf_in_addr, sizeof(struct in_addr)); memcpy (&cfg.addr4, buf_in_addr, sizeof (struct in_addr));
} else { } else {
Logger::amf_app().error("In conversion: Bad value " AMF_CONFIG_STRING_IPV4_ADDRESS " = %s in config file", util::trim(words.at(0)).c_str()); Logger::amf_app().error("In conversion: Bad value " AMF_CONFIG_STRING_IPV4_ADDRESS " = %s in config file", util::trim(words.at(0)).c_str());
return RETURNerror ; return RETURNerror;
} }
cfg.network4.s_addr = htons(ntohs(cfg.addr4.s_addr) & 0xFFFFFFFF << (32 - std::stoi(util::trim(words.at(1))))); cfg.network4.s_addr = htons(ntohs(cfg.addr4.s_addr) & 0xFFFFFFFF << (32 - std::stoi (util::trim(words.at(1)))));
} }
if_cfg.lookupValue(AMF_CONFIG_STRING_PORT, cfg.port); if_cfg.lookupValue(AMF_CONFIG_STRING_SCTP_PORT, cfg.port);
try { try {
const Setting &sched_params_cfg = if_cfg[AMF_CONFIG_STRING_SCHED_PARAMS]; const Setting& sched_params_cfg = if_cfg[AMF_CONFIG_STRING_SCHED_PARAMS];
load_thread_sched_params(sched_params_cfg, cfg.thread_rd_sched_params); load_thread_sched_params(sched_params_cfg, cfg.thread_rd_sched_params);
} catch (const SettingNotFoundException &nfex) { } catch(const SettingNotFoundException &nfex) {
Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
} }
return RETURNok ; return RETURNok;
} }
//------------------------------------------------------------------------------ int amf_config::load_thread_sched_params(const Setting& thread_sched_params_cfg, util::thread_sched_params& cfg)
int amf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg, util::thread_sched_params &cfg) { {
try { try {
thread_sched_params_cfg.lookupValue(AMF_CONFIG_STRING_THREAD_RD_CPU_ID, cfg.cpu_id); thread_sched_params_cfg.lookupValue(AMF_CONFIG_STRING_THREAD_RD_CPU_ID, cfg.cpu_id);
} catch (const SettingNotFoundException &nfex) { } catch(const SettingNotFoundException &nfex) {
Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
try { try {
...@@ -361,9 +307,9 @@ int amf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg, ...@@ -361,9 +307,9 @@ int amf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg,
cfg.sched_policy = SCHED_RR; cfg.sched_policy = SCHED_RR;
} else { } else {
Logger::amf_app().error("thread_rd_sched_policy: %s, unknown in config file", thread_rd_sched_policy.c_str()); Logger::amf_app().error("thread_rd_sched_policy: %s, unknown in config file", thread_rd_sched_policy.c_str());
return RETURNerror ; return RETURNerror;
} }
} catch (const SettingNotFoundException &nfex) { } catch(const SettingNotFoundException &nfex) {
Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
...@@ -371,12 +317,14 @@ int amf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg, ...@@ -371,12 +317,14 @@ int amf_config::load_thread_sched_params(const Setting &thread_sched_params_cfg,
thread_sched_params_cfg.lookupValue(AMF_CONFIG_STRING_THREAD_RD_SCHED_PRIORITY, cfg.sched_priority); thread_sched_params_cfg.lookupValue(AMF_CONFIG_STRING_THREAD_RD_SCHED_PRIORITY, cfg.sched_priority);
if ((cfg.sched_priority > 99) || (cfg.sched_priority < 1)) { if ((cfg.sched_priority > 99) || (cfg.sched_priority < 1)) {
Logger::amf_app().error("thread_rd_sched_priority: %d, must be in interval [1..99] in config file", cfg.sched_priority); Logger::amf_app().error("thread_rd_sched_priority: %d, must be in interval [1..99] in config file", cfg.sched_priority);
return RETURNerror ; return RETURNerror;
} }
} catch (const SettingNotFoundException &nfex) { } catch(const SettingNotFoundException &nfex) {
Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath()); Logger::amf_app().info("%s : %s, using defaults", nfex.what(), nfex.getPath());
} }
return RETURNok ; return RETURNok;
} }
} }
/*
* 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 amf_config.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _AMF_CONFIG_H_ #ifndef _AMF_CONFIG_H_
#define _AMF_CONFIG_H_ #define _AMF_CONFIG_H_
#include "amf_config.hpp"
#include <arpa/inet.h> #include <arpa/inet.h>
#include <libconfig.h++> #include <libconfig.h++>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <mutex> #include <mutex>
#include <vector> #include <vector>
#include <string> #include <string>
#include "thread_sched.hpp"
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include "amf_config.hpp"
#include "thread_sched.hpp"
#define AMF_CONFIG_STRING_AMF_CONFIG "AMF" #define AMF_CONFIG_STRING_AMF_CONFIG "AMF"
#define AMF_CONFIG_STRING_PID_DIRECTORY "PID_DIRECTORY" #define AMF_CONFIG_STRING_PID_DIRECTORY "PID_DIRECTORY"
#define AMF_CONFIG_STRING_INSTANCE_ID "INSTANCE_ID" #define AMF_CONFIG_STRING_INSTANCE_ID "INSTANCE_ID"
...@@ -52,7 +25,7 @@ ...@@ -52,7 +25,7 @@
#define AMF_CONFIG_STRING_INTERFACE_NGAP_AMF "NGAP_AMF" #define AMF_CONFIG_STRING_INTERFACE_NGAP_AMF "NGAP_AMF"
#define AMF_CONFIG_STRING_INTERFACE_NAME "INTERFACE_NAME" #define AMF_CONFIG_STRING_INTERFACE_NAME "INTERFACE_NAME"
#define AMF_CONFIG_STRING_IPV4_ADDRESS "IPV4_ADDRESS" #define AMF_CONFIG_STRING_IPV4_ADDRESS "IPV4_ADDRESS"
#define AMF_CONFIG_STRING_PORT "PORT" #define AMF_CONFIG_STRING_SCTP_PORT "SCTP_PORT"
#define AMF_CONFIG_STRING_PPID "PPID" #define AMF_CONFIG_STRING_PPID "PPID"
#define AMF_CONFIG_STRING_INTERFACE_N11 "N11" #define AMF_CONFIG_STRING_INTERFACE_N11 "N11"
...@@ -69,16 +42,16 @@ ...@@ -69,16 +42,16 @@
#define AMF_CONFIG_STRING_AMF_NAME "AMF_NAME" #define AMF_CONFIG_STRING_AMF_NAME "AMF_NAME"
#define AMF_CONFIG_STRING_GUAMI "GUAMI" #define AMF_CONFIG_STRING_GUAMI "GUAMI"
#define AMF_CONFIG_STRING_SERVED_GUAMI_LIST "SERVED_GUAMI_LIST" #define AMF_CONFIG_STRING_ServedGUAMIList "ServedGUAMIList"
#define AMF_CONFIG_STRING_TAC "TAC" #define AMF_CONFIG_STRING_TAC "TAC"
#define AMF_CONFIG_STRING_MCC "MCC" #define AMF_CONFIG_STRING_MCC "MCC"
#define AMF_CONFIG_STRING_MNC "MNC" #define AMF_CONFIG_STRING_MNC "MNC"
#define AMF_CONFIG_STRING_RegionID "RegionID" #define AMF_CONFIG_STRING_RegionID "RegionID"
#define AMF_CONFIG_STRING_AMFSetID "AMFSetID" #define AMF_CONFIG_STRING_AMFSetID "AMFSetID"
#define AMF_CONFIG_STRING_AMFPointer "AMFPointer" #define AMF_CONFIG_STRING_AMFPointer "AMFPointer"
#define AMF_CONFIG_STRING_RELATIVE_AMF_CAPACITY "RELATIVE_CAPACITY" #define AMF_CONFIG_STRING_RelativeAMFCapacity "RelativeAMFCapacity"
#define AMF_CONFIG_STRING_PLMN_SUPPORT_LIST "PLMN_SUPPORT_LIST" #define AMF_CONFIG_STRING_PLMNSupportList "PLMNSupportList"
#define AMF_CONFIG_STRING_SLICE_SUPPORT_LIST "SLICE_SUPPORT_LIST" #define AMF_CONFIG_STRING_SliceSupportList "SliceSupportList"
#define AMF_CONFIG_STRING_SST "SST" #define AMF_CONFIG_STRING_SST "SST"
#define AMF_CONFIG_STRING_SD "SD" #define AMF_CONFIG_STRING_SD "SD"
#define AMF_CONFIG_STRING_CORE_CONFIGURATION "CORE_CONFIGURATION" #define AMF_CONFIG_STRING_CORE_CONFIGURATION "CORE_CONFIGURATION"
...@@ -94,18 +67,20 @@ ...@@ -94,18 +67,20 @@
#define AMF_CONFIG_STRING_NAS_SUPPORTED_INTEGRITY_ALGORITHM_LIST "ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST" #define AMF_CONFIG_STRING_NAS_SUPPORTED_INTEGRITY_ALGORITHM_LIST "ORDERED_SUPPORTED_INTEGRITY_ALGORITHM_LIST"
#define AMF_CONFIG_STRING_NAS_SUPPORTED_CIPHERING_ALGORITHM_LIST "ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST" #define AMF_CONFIG_STRING_NAS_SUPPORTED_CIPHERING_ALGORITHM_LIST "ORDERED_SUPPORTED_CIPHERING_ALGORITHM_LIST"
using namespace libconfig; using namespace libconfig;
using namespace std;
namespace config { namespace config{
typedef struct { typedef struct{
std::string mysql_server; string mysql_server;
std::string mysql_user; string mysql_user;
std::string mysql_pass; string mysql_pass;
std::string mysql_db; string mysql_db;
std::string operator_key; string operator_key;
std::string random; string random;
} auth_conf; }auth_conf;
typedef struct interface_cfg_s { typedef struct interface_cfg_s {
std::string if_name; std::string if_name;
...@@ -125,64 +100,75 @@ typedef struct itti_cfg_s { ...@@ -125,64 +100,75 @@ typedef struct itti_cfg_s {
util::thread_sched_params async_cmd_sched_params; util::thread_sched_params async_cmd_sched_params;
} itti_cfg_t; } itti_cfg_t;
typedef struct guami_s { typedef struct guami_s{
std::string mcc; string mcc;
std::string mnc; string mnc;
std::string regionID; string regionID;
std::string AmfSetID; string AmfSetID;
std::string AmfPointer; string AmfPointer;
} guami_t; }guami_t;
typedef struct slice_s { typedef struct slice_s{
std::string sST; string sST;
std::string sD; string sD;
} slice_t; }slice_t;
typedef struct plmn_support_item_s { typedef struct plmn_support_item_s{
std::string mcc; string mcc;
std::string mnc; string mnc;
uint32_t tac; uint32_t tac;
std::vector<slice_t> slice_list; vector<slice_t> slice_list;
} plmn_item_t; }plmn_item_t;
typedef struct { typedef struct{
uint8_t prefered_integrity_algorithm[8]; uint8_t prefered_integrity_algorithm[8];
uint8_t prefered_ciphering_algorithm[8]; uint8_t prefered_ciphering_algorithm[8];
} nas_conf_t; }nas_conf_t;
typedef struct { typedef struct{
int id; int id;
std::string ipv4; string ipv4;
std::string port; string port;
std::string version; string version;
bool selected; bool selected;
} smf_inst_t; }smf_inst_t;
class amf_config { class amf_config{
public: public:
amf_config(); amf_config();
~amf_config(); ~amf_config();
int load(const std::string &config_file); int load(const std::string &config_file);
int load_interface(const Setting &if_cfg, interface_cfg_t &cfg); int load_interface(const Setting& if_cfg, interface_cfg_t & cfg);
int load_thread_sched_params(const libconfig::Setting &thread_sched_params_cfg, util::thread_sched_params &cfg); int load_thread_sched_params(const libconfig::Setting& thread_sched_params_cfg, util::thread_sched_params& cfg);
void display(); void display();
public:
unsigned int instance; unsigned int instance;
std::string pid_dir; string pid_dir;
interface_cfg_t n2; interface_cfg_t n2;
interface_cfg_t n11;
itti_cfg_t itti; itti_cfg_t itti;
unsigned int statistics_interval; unsigned int statistics_interval;
std::string AMF_Name; string AMF_Name;
guami_t guami; guami_t guami;
std::vector<guami_t> guami_list; vector<guami_t> guami_list;
unsigned int relativeAMFCapacity; unsigned int relativeAMFCapacity;
std::vector<plmn_item_t> plmn_list; vector<plmn_item_t> plmn_list;
std::string is_emergency_support; string is_emergency_support;
auth_conf auth_para; auth_conf auth_para;
nas_conf_t nas_cfg; nas_conf_t nas_cfg;
std::vector<smf_inst_t> smf_pool; vector<smf_inst_t> smf_pool;
}; };
} }
#endif #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 amf_module_from_config.cpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#include "amf_module_from_config.hpp" #include "amf_module_from_config.hpp"
#include "logger.hpp"
#include <iostream> #include <iostream>
#include <string> #include <string>
using namespace std;
#include "logger.hpp"
namespace config { namespace config{
//------------------------------------------------------------------------------ int amf_modules::load(const std::string &config_file){
int amf_modules::load(const std::string &config_file) { cout<<endl;
Logger::amf_app().debug("\nLoad AMF module configuration file (%s)", config_file.c_str()); Logger::amf_app().debug("Load amf module configuration file(%s)",config_file.c_str());
Config cfg; Config cfg;
try { try{
cfg.readFile(config_file.c_str()); cfg.readFile(config_file.c_str());
} catch (const FileIOException &fioex) { }catch(const FileIOException &fioex){
Logger::amf_app().error("I/O error while reading file %s - %s", config_file.c_str(), fioex.what()); Logger::amf_app().error("I/O error while reading file %s - %s", config_file.c_str(), fioex.what());
throw; throw;
} catch (const ParseException &pex) { }catch(const ParseException &pex){
Logger::amf_app().error("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(), pex.getError()); Logger::amf_app().error("Parse error at %s:%d - %s", pex.getFile(), pex.getLine(), pex.getError());
throw; throw;
} }
const Setting &root = cfg.getRoot(); const Setting &root = cfg.getRoot();
try { try{
const Setting &modules = root[MODULES_CONFIG_STRING_AMF_MODULES]; const Setting& modules = root[MODULES_CONFIG_STRING_AMF_MODULES];
} catch (const SettingNotFoundException &nfex) { }catch(const SettingNotFoundException &nfex){
Logger::amf_app().error("%s : %s", nfex.what(), nfex.getPath()); Logger::amf_app().error("%s : %s", nfex.what(), nfex.getPath());
return -1; return -1;
} }
const Setting &modules = root[MODULES_CONFIG_STRING_AMF_MODULES]; const Setting &modules = root[MODULES_CONFIG_STRING_AMF_MODULES];
const Setting &msg = modules[MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE]; const Setting &msg = modules[MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE];
int count = msg.getLength(); int count = msg.getLength();
for (int i = 0; i < count; i++) { for(int i=0; i< count; i++){
const Setting &item = msg[i]; const Setting & item = msg[i];
std::string typeOfMessage; std::string typeOfMessage;
int procedure_code; int procedure_code;
item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_NAME, msgName); item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_NAME, msgName);
item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_PROCEDURECODE, procedure_code); item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_PROCEDURECODE, procedure_code);
item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_TYPEOFMSG, typeOfMessage); item.lookupValue(MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_TYPEOFMSG, typeOfMessage);
procedureCode = (Ngap_ProcedureCode_t) procedure_code; procedureCode = (Ngap_ProcedureCode_t)procedure_code;
if (!(typeOfMessage.compare("initialMessage"))) { if(!(typeOfMessage.compare("initialMessage"))){
typeOfMsg = Ngap_NGAP_PDU_PR_initiatingMessage; typeOfMsg = Ngap_NGAP_PDU_PR_initiatingMessage;
} else if (!(typeOfMessage.compare("successfuloutcome"))) { }else if(!(typeOfMessage.compare("successfuloutcome"))){
typeOfMsg = Ngap_NGAP_PDU_PR_successfulOutcome; typeOfMsg = Ngap_NGAP_PDU_PR_successfulOutcome;
} else if (!(typeOfMessage.compare("unsuccessfuloutcome"))) { }else if(!(typeOfMessage.compare("unsuccessfuloutcome"))){
typeOfMsg = Ngap_NGAP_PDU_PR_unsuccessfulOutcome; typeOfMsg = Ngap_NGAP_PDU_PR_unsuccessfulOutcome;
} else { }else{
Logger::config().error("wrong NGAP message configuration"); Logger::config().error("wrong NGAP message configuration");
} }
} }
} }
//------------------------------------------------------------------------------ void amf_modules::display(){
void amf_modules::display() { Logger::config().info( "======= AMF Registred Modules =======");
Logger::config().info("======= AMF Registered Modules ======="); Logger::config().info( "NGAP Message Modules Repository(SourceCode) Path( ~/oai-5g-amf/src/ngap/ngapMsgs )");
Logger::config().info("NGAP Message Modules:"); Logger::config().info( "NGAP Message Modules:");
Logger::config().info("- %s(Procedure code %d, Type of Msg %d)\n", msgName.c_str(), procedureCode, typeOfMsg); Logger::config().info( "- %s([%d,%d])\n", msgName.c_str(), procedureCode, typeOfMsg);
} }
} }
/*
* 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 amf_module_from_config.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _AMF_MODULE_FROM_CONFIG_H_ #ifndef _AMF_MODULE_FROM_CONFIG_H_
#define _AMF_MODULE_FROM_CONFIG_H_ #define _AMF_MODULE_FROM_CONFIG_H_
...@@ -44,28 +16,38 @@ ...@@ -44,28 +16,38 @@
#include "Ngap_ProcedureCode.h" #include "Ngap_ProcedureCode.h"
#include "Ngap_NGAP-PDU.h" #include "Ngap_NGAP-PDU.h"
#define MODULES_CONFIG_STRING_AMF_MODULES "MODULES" #define MODULES_CONFIG_STRING_AMF_MODULES "MODULES"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE "NGAP_MESSAGE" #define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE "NGAP_MESSAGE"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_NAME "MSG_NAME" #define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_NAME "MSG_NAME"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_PROCEDURECODE "ProcedureCode" #define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_PROCEDURECODE "ProcedureCode"
#define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_TYPEOFMSG "TypeOfMessage" #define MODULES_CONFIG_STRING_AMF_MODULES_NGAP_MESSAGE_TYPEOFMSG "TypeOfMessage"
using namespace libconfig; using namespace libconfig;
namespace config { namespace config{
class amf_modules { class amf_modules{
public: public:
int load(const std::string &config_file); int load(const std::string &config_file);
void display(); void display();
void makeModulesAlive(); void makeModulesAlive();
private: private:
std::string msgName; //vector to store more msgs std::string msgName;//vector to store more msgs
Ngap_NGAP_PDU_PR typeOfMsg; Ngap_NGAP_PDU_PR typeOfMsg;
Ngap_ProcedureCode_t procedureCode; Ngap_ProcedureCode_t procedureCode;
// NGSetupRequestMsg *ngSetupRequest; // NGSetupRequestMsg *ngSetupRequest;
}; };
} }
#endif #endif
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* 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 amf_n1.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _AMF_N1_H_ #ifndef _AMF_N1_H_
#define _AMF_N1_H_ #define _AMF_N1_H_
#include <map> #include <map>
#include <shared_mutex> #include <shared_mutex>
#include "nas_context.hpp"
#include "pdu_session_context.hpp"
#include "itti_msg_n1.hpp"
#include "bstrlib.h"
#include "3gpp_ts24501.hpp"
#include "amf_statistics.hpp"
#include <pthread.h> #include <pthread.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
...@@ -42,66 +21,77 @@ ...@@ -42,66 +21,77 @@
#include <inttypes.h> #include <inttypes.h>
#include <mysql/mysql.h> #include <mysql/mysql.h>
#include "nas_context.hpp"
#include "pdu_session_context.hpp"
#include "itti_msg_n1.hpp"
#include "bstrlib.h"
#include "3gpp_ts24501.hpp"
#include "amf_statistics.hpp"
#include "amf.hpp"
#include "mysql_db.hpp" #include "mysql_db.hpp"
namespace amf_application { namespace amf_application{
#define NAS_MESSAGE_DOWNLINK 1 #define NAS_MESSAGE_DOWNLINK 1
#define NAS_MESSAGE_UPLINK 0 #define NAS_MESSAGE_UPLINK 0
typedef enum { typedef enum{
PlainNasMsg = 0x0, PlainNasMsg = 0x0,
IntegrityProtected = 0x1, IntegrityProtected = 0x1,
IntegrityProtectedAndCiphered = 0x2, IntegrityProtectedAndCiphered = 0x2,
IntegrityProtectedWithNew5GNASSecurityContext = 0x3, IntegrityProtectedWithNew5GNASSecurityContext = 0x3,
IntegrityProtectedAndCipheredWithNew5GNASSecurityContext = 0x4, IntegrityProtectedAndCipheredWithNew5GNASSecurityContext = 0x4,
} SecurityHeaderType; }SecurityHeaderType;
class amf_n1 { class amf_n1{
public: public:
amf_n1(); amf_n1();
~amf_n1(); ~amf_n1();
void handle_itti_message(itti_uplink_nas_data_ind&); void handle_itti_message(itti_uplink_nas_data_ind&);
void handle_itti_message(itti_downlink_nas_transfer &itti_msg); void handle_itti_message(itti_downlink_nas_transfer & itti_msg);
// nas message decode public: // nas message decode
void nas_signalling_establishment_request_handle(SecurityHeaderType type, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg, std::string snn, uint8_t ulCount); void nas_signalling_establishment_request_handle(SecurityHeaderType type, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg, std::string snn, uint8_t ulCount);
void uplink_nas_msg_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg); void uplink_nas_msg_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
void uplink_nas_msg_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg, plmn_t plmn); bool check_security_header_type(SecurityHeaderType & type, uint8_t *buffer);
bool check_security_header_type(SecurityHeaderType &type, uint8_t *buffer);
public:
std::map<long, std::shared_ptr<nas_context>> amfueid2nas_context; // amf ue ngap id std::map<long, std::shared_ptr<nas_context>> amfueid2nas_context; // amf ue ngap id
std::map<std::string, std::shared_ptr<nas_context>> imsi2nas_context; std::map<string, std::shared_ptr<nas_context>> imsi2nas_context;
std::map<std::string, long> supi2amfId; std::map<std::string, long> supi2amfId;
std::map<std::string, uint32_t> supi2ranId; std::map<std::string, uint32_t> supi2ranId;
std::map<std::string, std::shared_ptr<nas_context>> guti2nas_context; std::map<std::string, std::shared_ptr<nas_context>> guti2nas_context;
mutable std::shared_mutex m_guti2nas_context; mutable std::shared_mutex m_guti2nas_context;
bool is_guti_2_nas_context(const std::string &guti) const; bool is_guti_2_nas_context(const std::string & guti) const;
std::shared_ptr<nas_context> guti_2_nas_context(const std::string &guti) const; std::shared_ptr<nas_context> guti_2_nas_context(const std::string & guti) const;
void set_guti_2_nas_context(const std::string &guti, std::shared_ptr<nas_context> nc); void set_guti_2_nas_context(const std::string & guti, std::shared_ptr<nas_context>nc);
mutable std::shared_mutex m_amfueid2nas_context; mutable std::shared_mutex m_amfueid2nas_context;
bool is_amf_ue_id_2_nas_context(const long &amf_ue_ngap_id) const; bool is_amf_ue_id_2_nas_context(const long & amf_ue_ngap_id) const;
std::shared_ptr<nas_context> amf_ue_id_2_nas_context(const long &amf_ue_ngap_id) const; std::shared_ptr<nas_context> amf_ue_id_2_nas_context(const long & amf_ue_ngap_id) const;
void set_amf_ue_ngap_id_2_nas_context(const long &amf_ue_ngap_id, std::shared_ptr<nas_context> nc); void set_amf_ue_ngap_id_2_nas_context(const long & amf_ue_ngap_id, std::shared_ptr<nas_context> nc);
database_t *db_desc; database_t *db_desc;
//procedures private://nas message handlers
void run_registration_procedure(std::shared_ptr<nas_context> &nc); void ue_initiate_de_registration_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
void registration_request_handle(bool isNasSig, std::shared_ptr<nas_context>nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, std::string snn, bstring reg);
void authentication_response_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
void authentication_failure_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
void security_mode_complete_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas_msg);
void security_mode_reject_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas_msg);
void ul_nas_transport_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
void sha256(unsigned char * message, int msg_len, unsigned char * output);
void service_request_handle(bool isNasSig, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
void identity_response_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
private://authentication vector
bool generate_authentication_vector();
private:
void itti_send_dl_nas_buffer_to_task_n2(bstring & b, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id);
private://response message
void response_registration_reject_msg(uint8_t cause_value, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id);
public://procedures
void run_registration_procedure(std::shared_ptr<nas_context>&nc);
void run_initial_registration_procedure(); void run_initial_registration_procedure();
void run_mobility_registration_update_procedure(std::shared_ptr<nas_context> nc); void run_mobility_registration_update_procedure(std::shared_ptr<nas_context>nc);
//authentication public://authentication
bool auth_vectors_generator(std::shared_ptr<nas_context> &nc); bool auth_vectors_generator(std::shared_ptr<nas_context>&nc);
bool authentication_vectors_generator_in_ausf(std::shared_ptr<nas_context> &nc); bool authentication_vectors_generator_in_ausf(std::shared_ptr<nas_context>&nc);
bool authentication_vectors_generator_in_udm(std::shared_ptr<nas_context> &nc); bool authentication_vectors_generator_in_udm(std::shared_ptr<nas_context>&nc);
//mysql handlers in mysql_db.cpp public://mysql handlers in mysql_db.cpp
bool get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp); bool get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp);
void mysql_push_rand_sqn(std::string imsi, uint8_t *rand_p, uint8_t *sqn); void mysql_push_rand_sqn(std::string imsi, uint8_t *rand_p, uint8_t *sqn);
void mysql_increment_sqn(std::string imsi); void mysql_increment_sqn(std::string imsi);
...@@ -113,33 +103,29 @@ class amf_n1 { ...@@ -113,33 +103,29 @@ class amf_n1 {
bool start_authentication_procedure(std::shared_ptr<nas_context> nc, int vindex, uint8_t ngksi); bool start_authentication_procedure(std::shared_ptr<nas_context> nc, int vindex, uint8_t ngksi);
bool check_nas_common_procedure_on_going(std::shared_ptr<nas_context> nc); bool check_nas_common_procedure_on_going(std::shared_ptr<nas_context> nc);
int security_select_algorithms(uint8_t nea, uint8_t nia, uint8_t &amf_nea, uint8_t &amf_nia); int security_select_algorithms(uint8_t nea, uint8_t nia, uint8_t &amf_nea, uint8_t &amf_nia);
bool start_security_mode_control_procedure(std::shared_ptr<nas_context> nc); bool start_security_mode_control_procedure(std::shared_ptr<nas_context>nc);
void encode_nas_message_protected(nas_secu_ctx *nsc, bool is_secu_ctx_new, uint8_t security_header_type, uint8_t direction, uint8_t *input_nas_buf, int input_nas_len, bstring &encrypted_nas); void encode_nas_message_protected(nas_secu_ctx * nsc, bool is_secu_ctx_new, uint8_t security_header_type, uint8_t direction, uint8_t *input_nas_buf, int input_nas_len, bstring & encrypted_nas);
bool nas_message_integrity_protected(nas_secu_ctx *nsc, uint8_t direction, uint8_t *input_nas, int input_nas_len, uint32_t &mac); bool nas_message_integrity_protected(nas_secu_ctx *nsc, uint8_t direction, uint8_t *input_nas, int input_nas_len, uint32_t &mac);
bool nas_message_cipher_protected(nas_secu_ctx *nsc, uint8_t direction, bstring input_nas, bstring &output_nas); bool nas_message_cipher_protected(nas_secu_ctx *nsc, uint8_t direction, bstring input_nas, bstring &output_nas);
public:
void dump_nas_message(uint8_t *buf, int len); void dump_nas_message(uint8_t *buf, int len);
public:
void ue_authentication_simulator(uint8_t *rand, uint8_t *autn); void ue_authentication_simulator(uint8_t *rand, uint8_t *autn);
void annex_a_4_33501(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], std::string serving_network, uint8_t *output); void annex_a_4_33501(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], std::string serving_network, uint8_t *output);
public:
void send_itti_to_smf_services_consumer(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, uint8_t request_type, uint8_t pdu_session_id, bstring dnn, bstring sm_msg); void send_itti_to_smf_services_consumer(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, uint8_t request_type, uint8_t pdu_session_id, bstring dnn, bstring sm_msg);
void update_ue_information_statics(ue_infos &ueItem, const std::string connStatus, const std::string registerStatus, uint32_t ranid, uint32_t amfid, std::string imsi, std::string guti, std::string mcc, std::string mnc, uint32_t cellId); public:
void update_ue_information_statics(ue_infos &ueItem, const string connStatus, const string registerStatus, uint32_t ranid, uint32_t amfid, string imsi, string guti, string mcc, string mnc, uint32_t cellId);
private: //nas message handlers
void ue_initiate_de_registration_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
void registration_request_handle(bool isNasSig, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, std::string snn, bstring reg);
void authentication_response_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
void authentication_failure_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring plain_msg);
void security_mode_complete_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas_msg);
void security_mode_reject_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas_msg);
void ul_nas_transport_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
void ul_nas_transport_handle(uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas, plmn_t plmn);
void sha256(unsigned char *message, int msg_len, unsigned char *output);
void service_request_handle(bool isNasSig, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id, bstring nas);
//authentication vector
bool generate_authentication_vector();
void itti_send_dl_nas_buffer_to_task_n2(bstring &b, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id);
//response message
void response_registration_reject_msg(uint8_t cause_value, uint32_t ran_ue_ngap_id, long amf_ue_ngap_id);
}; };
} }
#endif #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 amf_n11.cpp
\brief
\author Keliang DU, BUPT, Tien-Thinh NGUYEN, EURECOM
\date 2020
\email: contact@openairinterface.org
*/
#include "amf_n11.hpp" #include "amf_n11.hpp"
#include <curl/curl.h>
#include <nlohmann/json.hpp>
#include "3gpp_ts24501.hpp"
#include "amf.hpp"
#include "amf_config.hpp"
#include "amf_n1.hpp" #include "amf_n1.hpp"
#include "itti.hpp" #include "itti.hpp"
#include "itti_msg_amf_app.hpp" #include "itti_msg_amf_app.hpp"
#include "amf_config.hpp"
#include "nas_context.hpp" #include "nas_context.hpp"
// For smf_client
#include "ApiClient.h" #include <curl/curl.h>
#include "ApiConfiguration.h" #include <nlohmann/json.hpp>
#include "SMContextsCollectionApi.h" /************* for smf_client ***************/
#include "SmContextCreateData.h" #include "SmContextCreateData.h"
#include "mime_parser.hpp" #include "SMContextsCollectionApi.h"
#include "ApiConfiguration.h"
#include "ApiClient.h"
extern "C" { #include "3gpp_ts24501.hpp"
#include "dynamic_memory_check.h"
}
using namespace oai::smf::model; using namespace oai::smf::model;
using namespace oai::smf::api; using namespace oai::smf::api;
using namespace web; using namespace web; // Common features like URIs.
using namespace web::http; // Common features like URIs. using namespace web::http; // Common HTTP functionality
using namespace web::http::client; // Common HTTP functionality using namespace web::http::client;
using namespace config; using namespace config;
using namespace amf_application; using namespace amf_application;
extern itti_mw *itti_inst; extern itti_mw * itti_inst;
extern amf_config amf_cfg; extern amf_config amf_cfg;
extern amf_n11 *amf_n11_inst; extern amf_n11 * amf_n11_inst;
extern amf_n1 *amf_n1_inst;
extern amf_n1 * amf_n1_inst;
extern void msg_str_2_msg_hex(std::string msg, bstring &b); extern void msg_str_2_msg_hex(std::string msg, bstring &b);
extern void convert_string_2_hex(std::string &input, std::string &output); extern void convert_string_2_hex(std::string&input, std::string&output);
extern void print_buffer(const std::string app, const std::string commit, extern void print_buffer(const std::string app, const std::string commit, uint8_t *buf, int len);
uint8_t *buf, int len); extern bool multipart_parser(string input, string &jsonData, string &n1sm, string &n2sm);
extern bool multipart_parser(std::string input, std::string &jsonData, extern unsigned char * format_string_as_hex(std::string str);
std::string &n1sm, std::string &n2sm); //extern std::size_t callback(const char* in, std::size_t size, std::size_t num, std::string* out);
extern unsigned char *format_string_as_hex(std::string str); extern char* bstring2charString(bstring b);
extern char *bstring2charString(bstring b);
std::size_t callback(
//------------------------------------------------------------------------------ const char* in,
std::size_t callback(const char *in, std::size_t size, std::size_t num, std::size_t size,
std::string *out) { std::size_t num,
std::string* out)
{
const std::size_t totalBytes(size * num); const std::size_t totalBytes(size * num);
out->append(in, totalBytes); out->append(in, totalBytes);
return totalBytes; return totalBytes;
} }
//------------------------------------------------------------------------------ void octet_stream_2_hex_stream(uint8_t *buf, int len, string &out){
void octet_stream_2_hex_stream(uint8_t *buf, int len, std::string &out) {
out = ""; out = "";
char *tmp = (char *)calloc(1, 2 * len * sizeof(uint8_t) + 1); char *tmp = (char*)calloc(1, 2*len*sizeof(uint8_t)+1);
for (int i = 0; i < len; i++) { for(int i=0; i<len; i++){
sprintf(tmp + 2 * i, "%02x", buf[i]); sprintf(tmp+2*i, "%02x", buf[i]);
} }
tmp[2 * len] = '\0'; tmp[2*len] = '\0';
out = tmp; out = tmp;
printf("n1sm buffer: %s\n", out.c_str()); printf("n1sm buffer: %s\n", out.c_str());
free(tmp);
} }
/****************************************************/ /****************************************************/
/** used to run NF(s) consumer, like smf_client ****/ /** used to run NF(s) consumer, like smf_client ****/
/***************************************************/ /***************************************************/
void amf_n11_task(void *); void amf_n11_task(void*);
//------------------------------------------------------------------------------ void amf_n11_task(void*){
void amf_n11_task(void *) {
const task_id_t task_id = TASK_AMF_N11; const task_id_t task_id = TASK_AMF_N11;
itti_inst->notify_task_ready(task_id); itti_inst->notify_task_ready(task_id);
do { do{
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id); std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get(); auto *msg = shared_msg.get();
switch (msg->msg_type) { switch(msg->msg_type){
case SMF_SERVICES_CONSUMER: { case SMF_SERVICES_CONSUMER:{
Logger::amf_n1().info("Running SMF_SERVICES_CONSUMER"); Logger::task_amf_n11().info("running SMF_SERVICES_CONSUMER");
itti_smf_services_consumer *m = itti_smf_services_consumer *m = dynamic_cast<itti_smf_services_consumer*>(msg);
dynamic_cast<itti_smf_services_consumer *>(msg);
amf_n11_inst->handle_itti_message(ref(*m)); amf_n11_inst->handle_itti_message(ref(*m));
} break; }break;
case NSMF_PDU_SESSION_UPDATE_SM_CTX: { case NSMF_PDU_SESS_UPDATE_SMCTX:{
Logger::amf_n1().info( Logger::task_amf_n11().info("receive NSMF_PDU_SESS_UPDATE_SMCTX, handling ...");
"Receive Nsmf_PDUSessionUpdateSMContext, handling ..."); itti_nsmf_pdusession_update_sm_context *m = dynamic_cast<itti_nsmf_pdusession_update_sm_context*>(msg);
itti_nsmf_pdusession_update_sm_context *m =
dynamic_cast<itti_nsmf_pdusession_update_sm_context *>(msg);
amf_n11_inst->handle_itti_message(ref(*m)); amf_n11_inst->handle_itti_message(ref(*m));
} break; }break;
case PDU_SESS_RES_SET_RESP: { case PDU_SESS_RES_SET_RESP:{
Logger::amf_n1().info( Logger::task_amf_n11().info("receive PDU_SESS_RES_SET_RESP, handling ...");
"Receive PDU Session Resource Setup Response, handling ..."); itti_pdu_session_resource_setup_response *m = dynamic_cast<itti_pdu_session_resource_setup_response*>(msg);
itti_pdu_session_resource_setup_response *m =
dynamic_cast<itti_pdu_session_resource_setup_response *>(msg);
amf_n11_inst->handle_itti_message(ref(*m)); amf_n11_inst->handle_itti_message(ref(*m));
} break; }break;
case NSMF_PDU_SESS_RELEASE_SMCTX: {
Logger::task_amf_n11().info("receive NSMF_PDU_SESS_RELEASE_SMCTX, handling ...");
itti_nsmf_pdusession_release_sm_context *m = dynamic_cast<itti_nsmf_pdusession_release_sm_context*>(msg);
amf_n11_inst->handle_itti_message(ref(*m));
}break;
} }
} while (true); shared_msg.reset();
}while(true);
} }
//------------------------------------------------------------------------------ amf_n11::amf_n11(){
amf_n11::amf_n11() { if(itti_inst->create_task(TASK_AMF_N11, amf_n11_task, nullptr) ) {
if (itti_inst->create_task(TASK_AMF_N11, amf_n11_task, nullptr)) { Logger::amf_n11().error( "Cannot create task TASK_AMF_N1" );
Logger::amf_n11().error("Cannot create task TASK_AMF_N1"); throw std::runtime_error( "Cannot create task TASK_AMF_N1" );
throw std::runtime_error("Cannot create task TASK_AMF_N1");
} }
Logger::amf_n1().startup("Started"); Logger::task_amf_n11().startup( "Started" );
Logger::amf_n1().debug("Construct amf_n1 successfully"); Logger::task_amf_n11().debug("construct amf_n1 successfully");
} }
//------------------------------------------------------------------------------ amf_n11::~amf_n11(){}
amf_n11::~amf_n11() {}
// itti message handlers
//------------------------------------------------------------------------------
void amf_n11::handle_itti_message(
itti_pdu_session_resource_setup_response &itti_msg) {}
//------------------------------------------------------------------------------ /***************************** itti message handlers *********************************/
void amf_n11::handle_itti_message( void amf_n11::handle_itti_message(itti_pdu_session_resource_setup_response &itti_msg){}
itti_nsmf_pdusession_update_sm_context &itti_msg) { void amf_n11::handle_itti_message(itti_nsmf_pdusession_update_sm_context &itti_msg){
std::string supi = pduid2supi.at(itti_msg.pdu_session_id); //string supi = pduid2supi.at(itti_msg.pdu_session_id);
Logger::amf_n11().debug("Found SUPI %s with PDU Session ID %d", supi.c_str(), string supi = itti_msg.supi;
itti_msg.pdu_session_id); Logger::amf_n11().debug("Try to find supi(%s) from pdusession_id(%d)", supi.c_str(), itti_msg.pdu_session_id);
std::shared_ptr<pdu_session_context> psc; std::shared_ptr<pdu_session_context> psc;
if (is_supi_to_pdu_ctx(supi)) { if(is_supi_to_pdu_ctx(supi)){
psc = supi_to_pdu_ctx(supi); psc = supi_to_pdu_ctx(supi);
} else { }else{
Logger::amf_n11().error( Logger::amf_n11().error("trying to find psu_session_context with supi(%s), Falied", supi.c_str());
"Could not find psu_session_context with SUPI %s, Failed",
supi.c_str());
return; return;
} }
std::string smf_addr; string smf_addr;
if (!psc.get()->smf_available) { if(!psc.get()->smf_avaliable){
if (!smf_selection_from_configuration(smf_addr)) { if(!smf_selection_from_configuration(smf_addr)){
Logger::amf_n11().error("No SMF candidate is available"); Logger::amf_n11().error("No candidate smf is avaliable");
return; return;
} }
} else { }else{
smf_selection_from_context(smf_addr); smf_selection_from_context(smf_addr);
} }
std::string smf_ip_addr, remote_uri; std::shared_ptr<pdu_session_context> context;
context = supi_to_pdu_ctx(supi);
// remove http port from the URI if existed string remote_uri = context.get()->location+ "/modify";
std::size_t found_port = smf_addr.find(":");
if (found_port != std::string::npos)
smf_ip_addr = smf_addr.substr(0, found_port - 1);
else
smf_ip_addr = smf_addr;
std::size_t found = psc.get()->smf_context_location.find(smf_ip_addr);
if (found != std::string::npos)
remote_uri = psc.get()->smf_context_location + "/modify";
else
remote_uri = smf_addr + psc.get()->smf_context_location + "/modify";
Logger::amf_n11().debug("SMF URI: %s", remote_uri.c_str());
nlohmann::json pdu_session_update_request = {}; //remote_uri = smf_addr + "/nsmf-pdusession/v2/sm-contexts/" + "1" + "/modify";//scid
Logger::amf_n11().debug("remote uri================================================%s", remote_uri.c_str());
nlohmann::json pdu_session_update_request;
pdu_session_update_request["n2SmInfoType"] = "PDU_RES_SETUP_RSP"; pdu_session_update_request["n2SmInfoType"] = "PDU_RES_SETUP_RSP";
pdu_session_update_request["n2SmInfo"]["contentId"] = "n2msg"; pdu_session_update_request["n2SmInfo"]["contentId"] = "n2SmMsg";
std::string json_part = pdu_session_update_request.dump(); std::string json_part = pdu_session_update_request.dump();
std::string n2SmMsg; std::string n2SmMsg;
octet_stream_2_hex_stream((uint8_t *)bdata(itti_msg.n2sm), octet_stream_2_hex_stream((uint8_t*)bdata(itti_msg.n2sm), blength(itti_msg.n2sm), n2SmMsg);
blength(itti_msg.n2sm), n2SmMsg); curl_http_client(remote_uri ,json_part, "", n2SmMsg, supi, itti_msg.pdu_session_id);
curl_http_client(remote_uri, json_part, "", n2SmMsg, supi,
itti_msg.pdu_session_id);
} }
//------------------------------------------------------------------------------ void amf_n11::handle_itti_message(itti_smf_services_consumer& smf){
void amf_n11::handle_itti_message(itti_smf_services_consumer &smf) {
std::shared_ptr<nas_context> nc; std::shared_ptr<nas_context> nc;
nc = amf_n1_inst->amf_ue_id_2_nas_context(smf.amf_ue_ngap_id); nc = amf_n1_inst->amf_ue_id_2_nas_context(smf.amf_ue_ngap_id);
std::string supi = "imsi-" + nc.get()->imsi; string supi = "imsi-" + nc.get()->imsi;
std::shared_ptr<pdu_session_context> psc; std::shared_ptr<pdu_session_context> psc;
if (is_supi_to_pdu_ctx(supi)) { if(is_supi_to_pdu_ctx(supi)){
psc = supi_to_pdu_ctx(supi); psc = supi_to_pdu_ctx(supi);
} else { }else{
psc = std::shared_ptr<pdu_session_context>(new pdu_session_context()); psc = std::shared_ptr<pdu_session_context>(new pdu_session_context());
set_supi_to_pdu_ctx(supi, psc); set_supi_to_pdu_ctx(supi, psc);
} }
...@@ -219,300 +169,332 @@ void amf_n11::handle_itti_message(itti_smf_services_consumer &smf) { ...@@ -219,300 +169,332 @@ void amf_n11::handle_itti_message(itti_smf_services_consumer &smf) {
psc.get()->ran_ue_ngap_id = nc.get()->ran_ue_ngap_id; psc.get()->ran_ue_ngap_id = nc.get()->ran_ue_ngap_id;
psc.get()->req_type = smf.req_type; psc.get()->req_type = smf.req_type;
psc.get()->pdu_session_id = smf.pdu_sess_id; psc.get()->pdu_session_id = smf.pdu_sess_id;
psc.get()->snssai.sST = smf.snssai.sST; //psc.get()->isn2sm_avaliable = false;
psc.get()->snssai.sD = smf.snssai.sD; //parse binary dnn and store
psc.get()->plmn.mcc = smf.plmn.mcc;
psc.get()->plmn.mnc = smf.plmn.mnc;
// parse binary dnn and store
std::string dnn = "default"; std::string dnn = "default";
if ((smf.dnn != nullptr) && (blength(smf.dnn) > 0)) { if ((smf.dnn != nullptr) && (blength(smf.dnn) > 0)){
char *tmp = bstring2charString(smf.dnn); char * tmp = bstring2charString(smf.dnn);
dnn = tmp; dnn = tmp;
free_wrapper((void **)&tmp); free (tmp);
tmp = nullptr;
} }
Logger::amf_n11().debug("Requested DNN: %s", dnn.c_str()); Logger::amf_n11().debug("requested DNN: %s", dnn.c_str());
psc.get()->dnn = dnn; psc.get()->dnn = dnn;
std::string smf_addr; if(dnn.compare("ims") == 0){
if (!psc.get()->smf_available) { Logger::amf_n11().debug("add support for IMS");
if (!smf_selection_from_configuration(smf_addr)) {
Logger::amf_n11().error("No candidate for SMF is available");
return; return;
} }
} else {
string smf_addr;
if(!psc.get()->smf_avaliable){
if(!smf_selection_from_configuration(smf_addr)){
Logger::amf_n11().error("No candidate smf is avaliable");
return;
}
}else{
smf_selection_from_context(smf_addr); smf_selection_from_context(smf_addr);
} }
switch (smf.req_type & 0x07) { switch(smf.req_type & 0x07){
case PDU_SESSION_INITIAL_REQUEST: { case PDU_SESSION_INITIAL_REQUEST:{
//get pti
uint8_t *sm_msg = (uint8_t*)bdata(smf.sm_msg);
uint8_t pti = sm_msg[2];
Logger::amf_n1().debug("decoded PTI for PDUSessionEstablishmentRequest(0x%x)", pti);
if(psc.get()->isn1sm_avaliable && psc.get()->isn2sm_avaliable){
itti_n1n2_message_transfer_request * itti_msg = new itti_n1n2_message_transfer_request(TASK_AMF_N11, TASK_AMF_APP);
itti_msg->supi = supi;
uint8_t accept_len = blength(psc.get()->n1sm);
uint8_t *accept = (uint8_t*)calloc(1, accept_len);
memcpy(accept, (uint8_t*)bdata(psc.get()->n1sm), accept_len);
accept[2] = pti;
itti_msg->n1sm = blk2bstr(accept, accept_len);
free(accept);
itti_msg->is_n1sm_set = true;
itti_msg->n2sm = psc.get()->n2sm;
itti_msg->is_n2sm_set = true;
itti_msg->pdu_session_id = psc.get()->pdu_session_id;
std::shared_ptr<itti_n1n2_message_transfer_request> i = std::shared_ptr<itti_n1n2_message_transfer_request>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_server().error( "Could not send ITTI message %s to task TASK_AMF_APP", i->get_msg_name());
}
}else{
psc.get()->isn2sm_avaliable = false;
handle_pdu_session_initial_request(supi, psc, smf_addr, smf.sm_msg, dnn); handle_pdu_session_initial_request(supi, psc, smf_addr, smf.sm_msg, dnn);
} break; }
case EXISTING_PDU_SESSION: { }break;
// TODO: case EXISTING_PDU_SESSION:{
} break; }break;
case PDU_SESSION_MODIFICATION_REQUEST: { case PDU_SESSION_MODIFICATION_REQUEST:{
// TODO: }break;
} break;
} }
} }
//------------------------------------------------------------------------------ void amf_n11::handle_pdu_session_initial_request(string supi, std::shared_ptr<pdu_session_context> psc, string smf_addr, bstring sm_msg, string dnn){
void amf_n11::handle_pdu_session_initial_request( string remote_uri = smf_addr + "/nsmf-pdusession/v2/sm-contexts";
std::string supi, std::shared_ptr<pdu_session_context> psc,
std::string smf_addr, bstring sm_msg, std::string dnn) {
// TODO: Remove hardcoded values
std::string remote_uri = smf_addr + "/nsmf-pdusession/v1/sm-contexts"; // TODO
nlohmann::json pdu_session_establishment_request; nlohmann::json pdu_session_establishment_request;
pdu_session_establishment_request["supi"] = supi.c_str(); pdu_session_establishment_request["supi"] = supi.c_str();
pdu_session_establishment_request["pei"] = "imei-200000000000001"; pdu_session_establishment_request["pei"] = "imei-200000000000001";
pdu_session_establishment_request["gpsi"] = "msisdn-200000000001"; pdu_session_establishment_request["gpsi"] = "msisdn-200000000001";
pdu_session_establishment_request["dnn"] = dnn.c_str(); pdu_session_establishment_request["dnn"] = dnn.c_str();
pdu_session_establishment_request["sNssai"]["sst"] = psc.get()->snssai.sST; pdu_session_establishment_request["sNssai"]["sst"] = 1;
pdu_session_establishment_request["sNssai"]["sd"] = psc.get()->snssai.sD; pdu_session_establishment_request["sNssai"]["sd"] = "0";
pdu_session_establishment_request["pduSessionId"] = psc.get()->pdu_session_id; pdu_session_establishment_request["pduSessionId"] = psc.get()->pdu_session_id;
pdu_session_establishment_request["requestType"] = pdu_session_establishment_request["requestType"] = "INITIAL_REQUEST";
"INITIAL_REQUEST"; // TODO: from SM_MSG
pdu_session_establishment_request["servingNfId"] = "servingNfId"; pdu_session_establishment_request["servingNfId"] = "servingNfId";
pdu_session_establishment_request["servingNetwork"]["mcc"] = //pdu_session_establishment_request["servingNetwork"]["mcc"] = "460";
psc.get()->plmn.mcc; //pdu_session_establishment_request["servingNetwork"]["mnc"] = "011";
pdu_session_establishment_request["servingNetwork"]["mnc"] = pdu_session_establishment_request["servingNetwork"]["mcc"] = "110";
psc.get()->plmn.mnc; pdu_session_establishment_request["servingNetwork"]["mnc"] = "011";
pdu_session_establishment_request["anType"] = "3GPP_ACCESS"; // TODO pdu_session_establishment_request["anType"] = "3GPP_ACCESS";
pdu_session_establishment_request["smContextStatusUri"] = pdu_session_establishment_request["smContextStatusUri"] = "smContextStatusUri";
"smContextStatusUri";
pdu_session_establishment_request["n1MessageContainer"]["n1MessageClass"] = "SM";
pdu_session_establishment_request["n1MessageContainer"]["n1MessageClass"] = pdu_session_establishment_request["n1MessageContainer"]["n1MessageContent"]["contentId"] = "n1SmMsg";
"SM";
pdu_session_establishment_request["n1MessageContainer"]["n1MessageContent"]
["contentId"] = "n1SmMsg";
std::string json_part = pdu_session_establishment_request.dump(); std::string json_part = pdu_session_establishment_request.dump();
std::string n1SmMsg; std::string n1SmMsg;
octet_stream_2_hex_stream((uint8_t *)bdata(sm_msg), blength(sm_msg), n1SmMsg); octet_stream_2_hex_stream((uint8_t*)bdata(sm_msg), blength(sm_msg), n1SmMsg);
curl_http_client(remote_uri, json_part, n1SmMsg, "", supi, bdestroy(sm_msg);
psc.get()->pdu_session_id); curl_http_client(remote_uri ,json_part, n1SmMsg, "", supi, psc.get()->pdu_session_id);
}
void amf_n11::handle_itti_message(itti_nsmf_pdusession_release_sm_context &itti_msg) {
std::shared_ptr<pdu_session_context> psc = supi_to_pdu_ctx(itti_msg.supi);
string smf_addr;
if(!psc.get()->smf_avaliable){
if(!smf_selection_from_configuration(smf_addr)){
Logger::amf_n11().error("No candidate smf is avaliable");
return;
}
}else{
smf_selection_from_context(smf_addr);
}
string remote_uri = psc.get()->location +"release";
nlohmann::json pdu_session_release_request;
pdu_session_release_request["supi"] = itti_msg.supi.c_str();
pdu_session_release_request["dnn"] = psc.get()->dnn.c_str();
pdu_session_release_request["sNssai"]["sst"] = 1;
pdu_session_release_request["sNssai"]["sd"] = "0";
pdu_session_release_request["pduSessionId"] = psc.get()->pdu_session_id;
pdu_session_release_request["cause"] = "REL_DUE_TO_REACTIVATION";
pdu_session_release_request["ngApCause"] = "radioNetwork";
std::string json_part = pdu_session_release_request.dump();
curl_http_client(remote_uri, json_part, "", "", itti_msg.supi, psc.get()->pdu_session_id);
} }
// Context management functions /************************************************* context management functions *********************************/
//------------------------------------------------------------------------------
bool amf_n11::is_supi_to_pdu_ctx(const std::string &supi) const { bool amf_n11::is_supi_to_pdu_ctx(const string &supi) const {
std::shared_lock lock(m_supi2pdu); std::shared_lock lock(m_supi2pdu);
return bool{supi2pdu.count(supi) > 0}; return bool{supi2pdu.count(supi) > 0};
} }
std::shared_ptr<pdu_session_context> std::shared_ptr<pdu_session_context> amf_n11::supi_to_pdu_ctx(const string & supi) const {
amf_n11::supi_to_pdu_ctx(const std::string &supi) const {
std::shared_lock lock(m_supi2pdu); std::shared_lock lock(m_supi2pdu);
return supi2pdu.at(supi); return supi2pdu.at(supi);
} }
//------------------------------------------------------------------------------ void amf_n11::set_supi_to_pdu_ctx(const string &supi, std::shared_ptr<pdu_session_context> psc){
void amf_n11::set_supi_to_pdu_ctx(const string &supi,
std::shared_ptr<pdu_session_context> psc) {
std::shared_lock lock(m_supi2pdu); std::shared_lock lock(m_supi2pdu);
supi2pdu[supi] = psc; supi2pdu[supi] = psc;
} }
// SMF selection /************************************** smf selection ********************************/
//------------------------------------------------------------------------------ bool amf_n11::smf_selection_from_configuration(string & smf_addr){
bool amf_n11::smf_selection_from_configuration(std::string &smf_addr) { for(int i=0; i<amf_cfg.smf_pool.size(); i++){
for (int i = 0; i < amf_cfg.smf_pool.size(); i++) { if(amf_cfg.smf_pool[i].selected){
if (amf_cfg.smf_pool[i].selected) { smf_addr = "http://"+amf_cfg.smf_pool[i].ipv4+":"+amf_cfg.smf_pool[i].port;
// smf_addr = "http://" + amf_cfg.smf_pool[i].ipv4 + ":" +
// amf_cfg.smf_pool[i].port;
smf_addr = amf_cfg.smf_pool[i].ipv4 + ":" + amf_cfg.smf_pool[i].port;
return true; return true;
} }
} }
return false; return false;
} }
bool amf_n11::smf_selection_from_context(string & smf_addr){
//------------------------------------------------------------------------------
bool amf_n11::smf_selection_from_context(std::string &smf_addr) {
// TODO:
} }
// handlers for smf client response /************************************* handlers for smf client response **************************/
//------------------------------------------------------------------------------ void amf_n11::handle_post_sm_context_response_error_400(){}
void amf_n11::handle_post_sm_context_response_error_400() {} void amf_n11::handle_post_sm_context_response_error(long code, string cause, bstring n1sm, string supi, uint8_t pdu_session_id){
print_buffer("amf_n11", "n1 sm", (uint8_t*)bdata(n1sm), blength(n1sm));
//------------------------------------------------------------------------------ itti_n1n2_message_transfer_request *itti_msg = new itti_n1n2_message_transfer_request(TASK_AMF_N11, TASK_AMF_APP);
void amf_n11::handle_post_sm_context_response_error(long code,
std::string cause,
bstring n1sm,
std::string supi,
uint8_t pdu_session_id) {
print_buffer("amf_n11", "n1 sm", (uint8_t *)bdata(n1sm), blength(n1sm));
itti_n1n2_message_transfer_request *itti_msg =
new itti_n1n2_message_transfer_request(TASK_AMF_N11, TASK_AMF_APP);
itti_msg->n1sm = n1sm; itti_msg->n1sm = n1sm;
itti_msg->is_n2sm_set = false; itti_msg->is_n2sm_set = false;
itti_msg->supi = supi; itti_msg->supi = supi;
itti_msg->pdu_session_id = pdu_session_id; itti_msg->pdu_session_id = pdu_session_id;
std::shared_ptr<itti_n1n2_message_transfer_request> i = std::shared_ptr<itti_n1n2_message_transfer_request> i = std::shared_ptr<itti_n1n2_message_transfer_request>(itti_msg);
std::shared_ptr<itti_n1n2_message_transfer_request>(itti_msg);
int ret = itti_inst->send_msg(i); int ret = itti_inst->send_msg(i);
if (0 != ret) { if (0 != ret) {
Logger::amf_n1().error( Logger::amf_n1().error( "Could not send ITTI message %s to task TASK_AMF_APP", i->get_msg_name());
"Could not send ITTI message %s to task TASK_AMF_APP",
i->get_msg_name());
} }
} }
//------------------------------------------------------------------------------ struct header_info{
void amf_n11::curl_http_client(std::string remoteUri, std::string jsonData, char *optbuf;
std::string n1SmMsg, std::string n2SmMsg, char *buffer;
std::string supi, uint8_t pdu_session_id) { int bufsize;
Logger::amf_n11().debug("Call SMF service: %s", remoteUri.c_str()); };
static int HeaderInfoInit(struct header_info &info,std::string &opt,int buffersize)
{
if(opt.size() > 0)
{
info.optbuf = opt.data();
}
else
{
return -1;
}
info.buffer = new char[buffersize];
info.bufsize = 0;
std::shared_ptr<pdu_session_context> psc; return 0;
if (is_supi_to_pdu_ctx(supi)) { }
psc = supi_to_pdu_ctx(supi); static void HeaderInfoDeleteInit(struct header_info &info)
} else { {
Logger::amf_n11().warn("PDU Session context for SUPI %s doesn't exit!", info.optbuf = NULL;
supi.c_str()); delete [] info.buffer;
// TODO: info.bufsize = 0;
} }
static size_t header_callback(char *buffer, size_t size,size_t nitems, void *userdata)
mime_parser parser = {}; {
std::string body; struct header_info *info = (struct header_info *)userdata;
size_t buffer_size = nitems*size;
if ((n1SmMsg.size() > 0) and (n2SmMsg.size() > 0)) {
// prepare the body content for Curl if(info->optbuf && info->buffer && (buffer_size > strlen(info->optbuf)))
parser.create_multipart_related_content(body, jsonData, CURL_MIME_BOUNDARY, {
n1SmMsg, n2SmMsg); if(!strncmp(info->optbuf,buffer,strlen(info->optbuf)))
} else if (n1SmMsg.size() > 0) { // only N1 content {
// prepare the body content for Curl info->bufsize = buffer_size;
parser.create_multipart_related_content( memcpy(info->buffer,buffer,buffer_size);
body, jsonData, CURL_MIME_BOUNDARY, n1SmMsg,
multipart_related_content_part_e::NAS); //delete "\r\n"
} else if (n2SmMsg.size() > 0) { // only N2 content if(info->buffer[info->bufsize -2] == '\r' && info->buffer[info->bufsize-1] == '\n')
// prepare the body content for Curl {
parser.create_multipart_related_content( info->buffer[info->bufsize-2] = '\0';
body, jsonData, CURL_MIME_BOUNDARY, n2SmMsg, info->bufsize -= 2;
multipart_related_content_part_e::NGAP); }
} }
}
Logger::amf_n11().debug("Send HTTP message to SMF with body %s",
body.c_str());
uint32_t str_len = body.length();
char *body_data = (char *)malloc(str_len + 1);
memset(body_data, 0, str_len + 1);
memcpy((void *)body_data, (void *)body.c_str(), str_len);
curl_global_init(CURL_GLOBAL_ALL);
CURL *curl = curl_easy_init();
if (curl) { return buffer_size;
CURLcode res = {}; }
void amf_n11::curl_http_client(string remoteUri, string jsonData, string n1SmMsg, string n2SmMsg, string supi, uint8_t pdu_session_id){
Logger::amf_n11().debug("call smf service operation: %s", remoteUri.c_str());
CURL *curl = curl_easy_init();
if(curl){
CURLcode res;
struct curl_slist *headers = nullptr; struct curl_slist *headers = nullptr;
struct curl_slist *slist = nullptr;
curl_mime *mime;
curl_mime *alt;
curl_mimepart *part;
std::string content_type = "content-type: multipart/related; boundary=" + //headers = curl_slist_append(headers, "charsets: utf-8");
std::string(CURL_MIME_BOUNDARY); headers = curl_slist_append(headers, "content-type: multipart/related");
headers = curl_slist_append(headers, content_type.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_URL, remoteUri.c_str()); curl_easy_setopt(curl, CURLOPT_URL, remoteUri.c_str());
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1); curl_easy_setopt(curl, CURLOPT_HTTPGET,1);
curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, SMF_CURL_TIMEOUT_MS); curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 100L);
curl_easy_setopt(curl, CURLOPT_INTERFACE, amf_cfg.n11.if_name.c_str());
struct header_info locationmsg;
std::string location = "Location";
HeaderInfoInit(locationmsg,location,256);
curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, header_callback);
curl_easy_setopt(curl, CURLOPT_HEADERDATA, &locationmsg);
mime = curl_mime_init(curl);
alt = curl_mime_init(curl);
//part with N1N2MessageTransferReqData (JsonData)
part = curl_mime_addpart(mime);
curl_mime_data(part, jsonData.c_str(), CURL_ZERO_TERMINATED);
curl_mime_type(part, "application/json");
if(n1SmMsg != ""){
Logger::amf_n11().debug("is there ok? n1");
unsigned char *n1_msg_hex = format_string_as_hex(n1SmMsg);
//Logger::amf_n11().debug("n1 msg hex: %s", n1_msg_hex);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n1_msg_hex), n1SmMsg.length()/2);
curl_mime_type(part, "application/vnd.3gpp.5gnas");
//curl_mime_name (part, "n1SmMsg");
}
if(n2SmMsg != ""){
unsigned char *n2_msg_hex = format_string_as_hex(n2SmMsg);
part = curl_mime_addpart(mime);
curl_mime_data(part, reinterpret_cast<const char*>(n2_msg_hex), n2SmMsg.length()/2);
curl_mime_type(part, "application/vnd.3gpp.ngap");
//curl_mime_name (part, "n2SmMsg");
}
curl_easy_setopt(curl, CURLOPT_MIMEPOST, mime);
//res = curl_easy_perform(curl);
// Response information. // Response information.
long httpCode = {0}; long httpCode(0);
std::unique_ptr<std::string> httpData(new std::string()); std::unique_ptr<std::string> httpData(new std::string());
std::unique_ptr<std::string> httpHeaderData(new std::string());
// Hook up data handling function. // Hook up data handling function.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get()); curl_easy_setopt(curl, CURLOPT_WRITEDATA, httpData.get());
curl_easy_setopt(curl, CURLOPT_HEADERDATA, httpHeaderData.get());
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, body.length());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, body_data);
res = curl_easy_perform(curl); res = curl_easy_perform(curl);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
// get cause from the response //get cause from the response
std::string response = *httpData.get(); string response = *httpData.get();
std::string json_data_response = ""; string jsonData = "";
std::string n1sm = ""; string n1sm = "";
std::string n2sm = ""; string n2sm = "";
bool is_response_ok = true; bool is_response_ok = true;
Logger::amf_n11().debug("Get response with httpcode (%d)", httpCode); Logger::amf_n11().debug("Get response with httpcode(%d)", httpCode);
if (httpCode == 0) { if(httpCode == 0){
Logger::amf_n11().error("Cannot get response when calling %s", Logger::amf_n11().error("Cannot get response When calling %s", remoteUri.c_str());
remoteUri.c_str());
// free curl before returning
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
return; return;
} }
if(httpCode != 200 && httpCode != 201){
if (httpCode != 200 && httpCode != 201 && httpCode != 204) {
is_response_ok = false; is_response_ok = false;
if (response.size() < 1) { if(!(multipart_parser(response, jsonData, n1sm, n2sm))){
Logger::amf_n11().error("There's no content in the response"); Logger::amf_n11().error("Could not get the cause from the response");
// TODO: send context response error
return;
} }
if (!(multipart_parser(response, json_data_response, n1sm, n2sm))) {
Logger::amf_n11().error(
"Could not get N1/N2 content from the response");
// TODO:
} }
} else {
// store location of the created context
std::string header_response = *httpHeaderData.get();
std::string CRLF = "\r\n";
std::size_t location_pos = header_response.find("Location");
if (location_pos != std::string::npos) {
std::size_t crlf_pos = header_response.find(CRLF, location_pos);
if (crlf_pos != std::string::npos) {
std::string location = header_response.substr(
location_pos + 10, crlf_pos - (location_pos + 10));
Logger::amf_n11().info("Location of the created SMF context: %s",
location.c_str());
psc.get()->smf_context_location = location;
}
}
}
nlohmann::json response_data = {}; if (httpCode == 201)
{
std::shared_ptr<pdu_session_context> context;
context = supi_to_pdu_ctx(supi);
string locationinfo_string = locationmsg.buffer;
context->location="http://"+locationinfo_string.substr(10,string::npos);
HeaderInfoDeleteInit(locationmsg);
Logger::amf_n11().debug("context.location in 201 response========================================%s===", context->location.c_str());
}
nlohmann::json response_data;
bstring n1sm_hex; bstring n1sm_hex;
if (!is_response_ok) { if(!is_response_ok){
try { response_data = nlohmann::json::parse(jsonData);
response_data = nlohmann::json::parse(json_data_response); Logger::amf_n11().debug("Get response with jsonData: %s", jsonData.c_str());
} catch (nlohmann::json::exception &e) { msg_str_2_msg_hex(n1sm.substr(0, n1sm.length()-2), n1sm_hex);//pdu session establishment reject bugs from SMF
Logger::amf_n11().warn("Could not get Json content from the response"); print_buffer("amf_n11", "Get response with n1sm:", (uint8_t*)bdata(n1sm_hex), blength(n1sm_hex));
// Set the default Cause
response_data["error"]["cause"] = "504 Gateway Timeout"; string cause = response_data["error"]["cause"];
} Logger::amf_n11().error("call Network Function services failure ");
Logger::amf_n11().info("Cause value: %s", cause.c_str());
Logger::amf_n11().debug("Get response with jsonData: %s", if(!cause.compare("DNN_DENIED")) handle_post_sm_context_response_error(httpCode, cause, n1sm_hex, supi, pdu_session_id);
json_data_response.c_str());
msg_str_2_msg_hex(
n1sm.substr(0, n1sm.length() - 2),
n1sm_hex); // pdu session establishment reject bugs from SMF
print_buffer("amf_n11",
"Get response with n1sm:", (uint8_t *)bdata(n1sm_hex),
blength(n1sm_hex));
std::string cause = response_data["error"]["cause"];
Logger::amf_n11().error("Call Network Function services failure");
Logger::amf_n11().debug("Cause value: %s", cause.c_str());
if (!cause.compare("DNN_DENIED"))
handle_post_sm_context_response_error(httpCode, cause, n1sm_hex, supi,
pdu_session_id);
} }
curl_slist_free_all(headers); curl_slist_free_all(headers);
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
curl_mime_free(mime);
} }
curl_global_cleanup();
free_wrapper((void **)&body_data);
} }
/*
* 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 amf_n11.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _AMF_N11_H_ #ifndef _AMF_N11_H_
#define _AMF_N11_H_ #define _AMF_N11_H_
#include "itti_msg_n11.hpp"
#include <map> #include <map>
#include <shared_mutex> #include <shared_mutex>
#include <string>
#include "itti_msg_n11.hpp"
#include "pdu_session_context.hpp" #include "pdu_session_context.hpp"
#include <string>
using namespace std;
namespace amf_application { namespace amf_application{
class amf_n11 { class amf_n11{
public: public:
amf_n11(); amf_n11();
~amf_n11(); ~amf_n11();
public:
void handle_itti_message(itti_smf_services_consumer&); void handle_itti_message(itti_smf_services_consumer &);
void handle_pdu_session_initial_request(std::string supi, std::shared_ptr<pdu_session_context> psc, std::string smf_addr, bstring sm_msg, std::string dnn); void handle_pdu_session_initial_request(string supi, std::shared_ptr<pdu_session_context> psc, string smf_addr, bstring sm_msg, string dnn);
void handle_itti_message(itti_pdu_session_resource_setup_response &itti_msg); void handle_itti_message(itti_pdu_session_resource_setup_response &itti_msg);
void handle_itti_message(itti_nsmf_pdusession_update_sm_context &itti_msg); void handle_itti_message(itti_nsmf_pdusession_update_sm_context &itti_msg);
std::map<std::string, std::shared_ptr<pdu_session_context>> supi2pdu; // amf ue ngap id void handle_itti_message(itti_nsmf_pdusession_release_sm_context &itti_msg);
public:
std::map<string, std::shared_ptr<pdu_session_context>> supi2pdu; // amf ue ngap id
mutable std::shared_mutex m_supi2pdu; mutable std::shared_mutex m_supi2pdu;
bool is_supi_to_pdu_ctx(const std::string &supi) const; bool is_supi_to_pdu_ctx(const string &supi) const;
std::shared_ptr<pdu_session_context> supi_to_pdu_ctx(const std::string &supi) const; std::shared_ptr<pdu_session_context> supi_to_pdu_ctx(const string & supi) const;
void set_supi_to_pdu_ctx(const std::string &supi, std::shared_ptr<pdu_session_context> psc); void set_supi_to_pdu_ctx(const string &supi, std::shared_ptr<pdu_session_context> psc);
std::map<uint8_t, std::string> pduid2supi; public:
std::map<uint8_t, string> pduid2supi;
bool smf_selection_from_configuration(std::string &smf_addr); public:
bool smf_selection_from_context(std::string &smf_addr); bool smf_selection_from_configuration(string & smf_addr);
bool smf_selection_from_context(string & smf_addr);
public:
void handle_post_sm_context_response_error_400(); void handle_post_sm_context_response_error_400();
void handle_post_sm_context_response_error(long code, std::string cause, bstring n1sm, std::string supi, uint8_t pdu_session_id); void handle_post_sm_context_response_error(long code, string cause, bstring n1sm, string supi, uint8_t pdu_session_id);
public:
void curl_http_client(std::string remoteUri, std::string jsonData, std::string n1SmMsg, std::string n2SmMsg, std::string supi, uint8_t pdu_session_id); void curl_http_client(string remoteUri, string jsonData, string n1SmMsg, string n2SmMsg, string supi, uint8_t pdu_session_id);
}; };
} }
#endif #endif
/* //#include <vector>
* 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 amf_n2.cpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#include "amf_n2.hpp" #include "amf_n2.hpp"
#include "amf_n1.hpp"
#include "amf_n11.hpp"
#include "amf_app.hpp"
#include "logger.hpp"
#include "sctp_server.hpp"
#include "itti.hpp"
#include "itti_msg_amf_app.hpp"
#include "amf_config.hpp"
#include "DefaultPagingDRX.hpp" #include "DefaultPagingDRX.hpp"
#include "DownLinkNasTransport.hpp"
#include "InitialContextSetupRequest.hpp"
#include "NGSetupFailure.hpp" #include "NGSetupFailure.hpp"
#include "NGSetupResponse.hpp" #include "NGSetupResponse.hpp"
#include "Ngap_Cause.h" #include "DownLinkNasTransport.hpp"
#include "Ngap_CauseRadioNetwork.h" #include "InitialContextSetupRequest.hpp"
#include "Ngap_TimeToWait.h"
#include "PduSessionResourceSetupRequest.hpp" #include "PduSessionResourceSetupRequest.hpp"
#include "UEContextReleaseCommand.hpp" #include "UEContextReleaseCommand.hpp"
#include "amf_app.hpp" #include "PDUSessionResourceHandoverCommandTransfer.hpp"
#include "amf_config.hpp" #include "PDUSessionResourceReleaseCommandTransfer.hpp"
#include "amf_n1.hpp"
#include "amf_n11.hpp"
#include "amf_statistics.hpp" #include "amf_statistics.hpp"
#include "itti.hpp"
#include "itti_msg_amf_app.hpp"
#include "logger.hpp"
#include "sctp_server.hpp"
extern "C" {
#include "dynamic_memory_check.h"
}
#include "Ngap_Cause.h"
#include "Ngap_CauseRadioNetwork.h"
#include "Ngap_TimeToWait.h"
#include "Ngap_CauseNas.h"
using namespace amf_application; using namespace amf_application;
using namespace std;
using namespace config; using namespace config;
using namespace ngap;
extern itti_mw *itti_inst; extern itti_mw *itti_inst;
extern amf_n2 *amf_n2_inst; extern amf_n2 *amf_n2_inst;
extern amf_n1 *amf_n1_inst; extern amf_n1 *amf_n1_inst;
...@@ -61,214 +35,273 @@ extern amf_n11 *amf_n11_inst; ...@@ -61,214 +35,273 @@ extern amf_n11 *amf_n11_inst;
extern amf_config amf_cfg; extern amf_config amf_cfg;
extern amf_app *amf_app_inst; extern amf_app *amf_app_inst;
extern statistics stacs; extern statistics stacs;
uint32_t ran_id_Global = 0;
uint32_t AMF_TARGET_ran_id_global = 0;
void amf_n2_task(void *); void amf_n2_task(void *);
void amf_n2_task(void *args_p)
//------------------------------------------------------------------------------ {
void amf_n2_task(void *args_p) {
const task_id_t task_id = TASK_AMF_N2; const task_id_t task_id = TASK_AMF_N2;
itti_inst->notify_task_ready(task_id); itti_inst->notify_task_ready(task_id);
do { do
{
std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id); std::shared_ptr<itti_msg> shared_msg = itti_inst->receive_msg(task_id);
auto *msg = shared_msg.get(); auto *msg = shared_msg.get();
switch (msg->msg_type) { switch (msg->msg_type)
case NEW_SCTP_ASSOCIATION: { {
Logger::amf_n2().info("Received NEW_SCTP_ASSOCIATION"); case NEW_SCTP_ASSOCIATION:
itti_new_sctp_association *m = {
dynamic_cast<itti_new_sctp_association *>(msg); Logger::task_amf_n2().info("Received NEW_SCTP_ASSOCIATION");
itti_new_sctp_association *m = dynamic_cast<itti_new_sctp_association *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case NG_SETUP_REQ: { break;
Logger::amf_n2().info("Received NGSetupRequest message, handling"); case NG_SETUP_REQ:
{
Logger::task_amf_n2().info("Received NGSetupRequest message, handling");
itti_ng_setup_request *m = dynamic_cast<itti_ng_setup_request *>(msg); itti_ng_setup_request *m = dynamic_cast<itti_ng_setup_request *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case INITIAL_UE_MSG: { break;
Logger::amf_n2().info("Received INITIAL_UE_MESSAGE message, handling"); case INITIAL_UE_MSG:
{
Logger::task_amf_n2().info("Received INITIAL_UE_MESSAGE message, handling");
itti_initial_ue_message *m = dynamic_cast<itti_initial_ue_message *>(msg); itti_initial_ue_message *m = dynamic_cast<itti_initial_ue_message *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case ITTI_UL_NAS_TRANSPORT: { break;
Logger::amf_n2().info("Received UPLINK_NAS_TRANSPORT message, handling"); case ITTI_UL_NAS_TRANSPORT:
{
Logger::task_amf_n2().info("Received UPLINK_NAS_TRANSPORT message, handling");
itti_ul_nas_transport *m = dynamic_cast<itti_ul_nas_transport *>(msg); itti_ul_nas_transport *m = dynamic_cast<itti_ul_nas_transport *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case ITTI_DL_NAS_TRANSPORT: { break;
Logger::amf_n2().info( case ITTI_DL_NAS_TRANSPORT:
"Encoding DOWNLINK NAS TRANSPORT message, sending "); {
Logger::task_amf_n2().info("Encoding DOWNLINK NAS TRANSPORT message, sending ");
itti_dl_nas_transport *m = dynamic_cast<itti_dl_nas_transport *>(msg); itti_dl_nas_transport *m = dynamic_cast<itti_dl_nas_transport *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case PDU_SESSION_RESOURCE_SETUP_REQUEST: { break;
Logger::amf_n2().info( case PDU_SESSION_RESOURCE_SETUP_REQUEST:
"Encoding PDU SESSION RESOURCE SETUP REQUEST message, sending "); {
itti_pdu_session_resource_setup_request *m = Logger::task_amf_n2().info("Encoding PDU SESSION RESOURCE SETUP REQUEST message, sending ");
dynamic_cast<itti_pdu_session_resource_setup_request *>(msg); itti_pdu_session_resource_setup_request *m = dynamic_cast<itti_pdu_session_resource_setup_request *>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}
break;
case INITIAL_CONTEXT_SETUP_REQUEST:
{
Logger::task_amf_n2().info("Encoding INITIAL CONTEXT SETUP REQUEST message, sending ");
itti_initial_context_setup_request *m = dynamic_cast<itti_initial_context_setup_request *>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}
break;
case UE_CONTEXT_RELEASE_REQUEST:
{
Logger::task_amf_n2().info("Received UE_CONTEXT_RELEASE_REQUEST message, handling");
itti_ue_context_release_request *m = dynamic_cast<itti_ue_context_release_request *>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}
break;
case UE_CONTEXT_RELEASE_COMMAND:
{
Logger::task_amf_n2().info("Received UE_CONTEXT_RELEASE_COMMAND message, handling");
itti_ue_context_release_command *m = dynamic_cast<itti_ue_context_release_command *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case INITIAL_CONTEXT_SETUP_REQUEST: { break;
Logger::amf_n2().info( case PDU_SESSION_RESOURCE_RELEASE_COMMAND:
"Encoding INITIAL CONTEXT SETUP REQUEST message, sending "); {
itti_initial_context_setup_request *m = Logger::task_amf_n2().info("Received PDU_SESSION_RESOURCE_RELEASE_COMMAND message, handling");
dynamic_cast<itti_initial_context_setup_request *>(msg); itti_pdu_session_resource_release_command *m = dynamic_cast<itti_pdu_session_resource_release_command *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case UE_CONTEXT_RELEASE_REQUEST: { break;
Logger::amf_n2().info( case UE_RADIO_CAP_IND:
"Received UE_CONTEXT_RELEASE_REQUEST message, handling"); {
itti_ue_context_release_request *m = Logger::task_amf_n2().info("Received UE_RADIO_CAP_IND message, handling");
dynamic_cast<itti_ue_context_release_request *>(msg); itti_ue_radio_capability_indication *m = dynamic_cast<itti_ue_radio_capability_indication *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
case UE_RADIO_CAP_IND: { break;
Logger::amf_n2().info("Received UE_RADIO_CAP_IND message, handling"); case HANDOVER_REQUIRED:
itti_ue_radio_capability_indication *m = {
dynamic_cast<itti_ue_radio_capability_indication *>(msg); Logger::amf_n2().info("Received HANDOVER_REQUIRED message,handling");
itti_handover_required *m = dynamic_cast<itti_handover_required *>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}
break;
case HANDOVER_REQUEST_ACK:
{
Logger::amf_n2().info("Received HANDOVER_REQUEST_ACK message,handling");
itti_handover_request_Ack *m = dynamic_cast<itti_handover_request_Ack *>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}
break;
case HANDOVER_NOTIFY:
{
Logger::amf_n2().info("Received HANDOVER_NOTIFY message,handling");
itti_handover_notify *m = dynamic_cast<itti_handover_notify *>(msg);
amf_n2_inst->handle_itti_message(ref(*m)); amf_n2_inst->handle_itti_message(ref(*m));
} break; }
break;
case UPLINKRANSTATUSTRANSFER:
{
Logger::amf_n2().info("Received UPLINKRANSTATUSTRANSFER message,handling");
itti_uplinkranstatsutransfer *m = dynamic_cast<itti_uplinkranstatsutransfer *>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
}
default: default:
Logger::amf_n2().info("No handler for msg type %d", msg->msg_type); Logger::task_amf_n2().info("no handler for msg type %d", msg->msg_type);
} }
shared_msg.reset();
} while (true); } while (true);
} }
//------------------------------------------------------------------------------ amf_n2::amf_n2(const string &address, const uint16_t port_num) : ngap_app(address, port_num)
amf_n2::amf_n2(const std::string &address, const uint16_t port_num) {
: ngap_app(address, port_num) { if (itti_inst->create_task(TASK_AMF_N2, amf_n2_task, nullptr))
if (itti_inst->create_task(TASK_AMF_N2, amf_n2_task, nullptr)) { {
Logger::amf_n2().error("Cannot create task TASK_AMF_N2"); Logger::amf_n2().error("Cannot create task TASK_AMF_N2");
throw std::runtime_error("Cannot create task TASK_AMF_N2"); throw std::runtime_error("Cannot create task TASK_AMF_N2");
} }
Logger::amf_n2().startup("Started"); Logger::task_amf_n2().startup("Started");
Logger::amf_n2().debug("Construct amf_n2 successfully"); Logger::task_amf_n2().debug("construct amf_n2 successfully");
} }
//------------------------------------------------------------------------------
amf_n2::~amf_n2() {} amf_n2::~amf_n2() {}
// NGAP Messages Handlers /******************************************************** NGAP Messages Handlers******************************************************************/
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_new_sctp_association &new_assoc) { void amf_n2::handle_itti_message(itti_new_sctp_association &new_assoc) {} //handled in class ngap_app
} // handled in class ngap_app /************************* NG_SETUP_REQUEST Handler **************************/
void amf_n2::handle_itti_message(itti_ng_setup_request &itti_msg)
// NG_SETUP_REQUEST Handler {
//------------------------------------------------------------------------------ Logger::amf_n2().debug("parameters(assoc_id(%d))(stream(%d))", itti_msg.assoc_id, itti_msg.stream);
void amf_n2::handle_itti_message(itti_ng_setup_request &itti_msg) {
Logger::amf_n2().debug("Parameters: assoc_id %d, stream %d",
itti_msg.assoc_id, itti_msg.stream);
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) { if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id))
Logger::amf_n2().error("No existed gNB context with assoc_id(%d)", {
itti_msg.assoc_id); Logger::amf_n2().error("no existed gnb context with assoc_id(%d)", itti_msg.assoc_id);
Logger::amf_n2().debug("itti_msg.ngSetupReq freed");
delete itti_msg.ngSetupReq;
Logger::amf_n2().debug("itti_msg.ngSetupReq and pdu are freed");
return; return;
} }
gc = assoc_id_2_gnb_context(itti_msg.assoc_id); gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
if (gc.get()->ng_state == NGAP_RESETING || if (gc.get()->ng_state == NGAP_RESETING || gc.get()->ng_state == NGAP_SHUTDOWN)
gc.get()->ng_state == NGAP_SHUTDOWN) { {
Logger::amf_n2().warn("Received new association request on an association " Logger::amf_n2().warn("Received new association request on an association that is being %s, ignoring", ng_gnb_state_str[gc.get()->ng_state]);
"that is being %s, ignoring", }
ng_gnb_state_str[gc.get()->ng_state]); else
} else { {
Logger::amf_n2().debug("Update gNB context with assoc id (%d)", Logger::amf_n2().debug("Update gNB context with assoc id (%d)", itti_msg.assoc_id);
itti_msg.assoc_id);
} }
gnb_infos gnbItem; gnb_infos gnbItem;
// Get IE Global RAN Node ID //Get IE Global RAN Node ID
uint32_t gnb_id; uint32_t gnb_id;
std::string gnb_mcc; string gnb_mcc;
std::string gnb_mnc; string gnb_mnc;
if (!itti_msg.ngSetupReq->getGlobalGnbID(gnb_id, gnb_mcc, gnb_mnc)) { if (!itti_msg.ngSetupReq->getGlobalGnbID(gnb_id, gnb_mcc, gnb_mnc))
Logger::amf_n2().error("Missing Mandatory IE GlobalGnbID"); {
Logger::amf_n2().error("Missing Mandontary IE GlobalGnbID");
Logger::amf_n2().debug("itti_msg.ngSetupReq freed");
delete itti_msg.ngSetupReq;
Logger::amf_n2().debug("itti_msg.ngSetupReq and pdu are freed");
return; return;
} }
Logger::amf_n2().debug("IE GlobalGNBID: 0x%x", gnb_id); Logger::amf_n2().debug("IE GlobalGNBID(0x%x)", gnb_id);
gc->globalRanNodeId = gnb_id; gc->globalRanNodeId = gnb_id;
gnbItem.gnb_id = gnb_id; gnbItem.gnb_id = gnb_id;
std::string gnb_name; string gnb_name;
if (!itti_msg.ngSetupReq->getRanNodeName(gnb_name)) { if (!itti_msg.ngSetupReq->getRanNodeName(gnb_name))
{
Logger::amf_n2().warn("IE RanNodeName not existed"); Logger::amf_n2().warn("IE RanNodeName not existed");
} else { }
else
{
gc->gnb_name = gnb_name; gc->gnb_name = gnb_name;
gnbItem.gnb_name = gnb_name; gnbItem.gnb_name = gnb_name;
Logger::amf_n2().debug("IE RanNodeName: %s", gnb_name.c_str()); Logger::amf_n2().debug("IE RanNodeName(%s)", gnb_name.c_str());
} }
int defPagingDrx = itti_msg.ngSetupReq->getDefaultPagingDRX(); int defPagingDrx = itti_msg.ngSetupReq->getDefaultPagingDRX();
if (defPagingDrx == -1) { if (defPagingDrx == -1)
Logger::amf_n2().error("Missing Mandatory IE DefaultPagingDRX"); {
Logger::amf_n2().error("Missing Mandontary IE DefaultPagingDRX");
Logger::amf_n2().debug("itti_msg.ngSetupReq freed");
delete itti_msg.ngSetupReq;
Logger::amf_n2().debug("itti_msg.ngSetupReq and pdu are freed");
return; return;
} }
Logger::amf_n2().debug("IE DefaultPagingDRX: %d", defPagingDrx); Logger::amf_n2().debug("IE DefaultPagingDRX(%d)", defPagingDrx);
vector<SupportedItem_t> s_ta_list; vector<SupportedItem_t> s_ta_list;
if (!itti_msg.ngSetupReq->getSupportedTAList( if (!itti_msg.ngSetupReq->getSupportedTAList(s_ta_list))
s_ta_list)) { // getSupportedTAList { //getSupportedTAList
Logger::amf_n2().debug("itti_msg.ngSetupReq freed");
delete itti_msg.ngSetupReq;
Logger::amf_n2().debug("itti_msg.ngSetupReq and pdu are freed");
return; return;
} }
// TODO: should be removed, since we stored list of common PLMNs
gnbItem.mcc = s_ta_list[0].b_plmn_list[0].mcc; gnbItem.mcc = s_ta_list[0].b_plmn_list[0].mcc;
gnbItem.mnc = s_ta_list[0].b_plmn_list[0].mnc; gnbItem.mnc = s_ta_list[0].b_plmn_list[0].mnc;
gnbItem.tac = s_ta_list[0].tac; gnbItem.tac = s_ta_list[0].tac;
// association GlobalRANNodeID with assoc_id //association GlobalRANNodeID with assoc_id
// store RAN Node Name in gNB context, if present //store RAN Node Name in gNB context, if present
// verify PLMN Identity and TAC with configuration and store supportedTAList //verify PLMN Identity and TAC with configuration and store supportedTAList in gNB context, if verified; else response NG SETUP FAILURE with cause "Unknown PLMN"(9.3.1.2, ts38413)
// in gNB context, if verified; else response NG SETUP FAILURE with cause if (!verifyPlmn(s_ta_list))
// "Unknown PLMN"(9.3.1.2, ts38413) {
std::vector<SupportedItem_t> common_plmn_list = get_common_plmn(s_ta_list); //encode NG SETUP FAILURE MESSAGE and send back
if (common_plmn_list.size() == 0) {
// if (!verifyPlmn(s_ta_list)) {
// encode NG SETUP FAILURE MESSAGE and send back
void *buffer = calloc(1, 1000); void *buffer = calloc(1, 1000);
NGSetupFailureMsg ngSetupFailure; NGSetupFailureMsg ngSetupFailure;
ngSetupFailure.setMessageType(); ngSetupFailure.setMessageType();
ngSetupFailure.setCauseRadioNetwork(Ngap_CauseRadioNetwork_unspecified, ngSetupFailure.setCauseRadioNetwork(Ngap_CauseRadioNetwork_unspecified, Ngap_TimeToWait_v5s);
Ngap_TimeToWait_v5s);
int encoded = ngSetupFailure.encode2buffer((uint8_t *)buffer, 1000); int encoded = ngSetupFailure.encode2buffer((uint8_t *)buffer, 1000);
bstring b = blk2bstr(buffer, encoded); bstring b = blk2bstr(buffer, encoded);
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b); sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b);
Logger::amf_n2().error( Logger::amf_n2().error("no common plmn, encoding NG_SETUP_FAILURE with cause( Unknown PLMN )");
"No common PLMN, encoding NG_SETUP_FAILURE with cause (Unknown PLMN)"); free(buffer);
return; return;
} else {
// store only the common PLMN
gc->s_ta_list = common_plmn_list;
for (auto i : common_plmn_list) {
gnbItem.plmn_list.push_back(i);
} }
else
{
gc->s_ta_list = s_ta_list;
} }
set_gnb_id_2_gnb_context(gnb_id, gc);
// store Paging DRX in gNB context //store Paging DRX in gNB context
Logger::amf_n2().debug("Encoding NG_SETUP_RESPONSE ..."); Logger::amf_n2().debug("encoding NG_SETUP_RESPONSE ...");
// encode NG SETUP RESPONSE message with information stored in configuration //encode NG SETUP RESPONSE message with information stored in configuration file and send_msg
// file and send_msg
void *buffer = calloc(1, 1000); void *buffer = calloc(1, 1000);
NGSetupResponseMsg ngSetupResp; NGSetupResponseMsg ngSetupResp;
ngSetupResp.setMessageType(); ngSetupResp.setMessageType();
ngSetupResp.setAMFName(amf_cfg.AMF_Name); ngSetupResp.setAMFName(amf_cfg.AMF_Name);
ngSetupResp.setRelativeAmfCapacity(amf_cfg.relativeAMFCapacity); ngSetupResp.setRelativeAmfCapacity(amf_cfg.relativeAMFCapacity);
std::vector<struct GuamiItem_s> guami_list; std::vector<struct GuamiItem_s> guami_list;
for (int i = 0; i < amf_cfg.guami_list.size(); i++) { for (int i = 0; i < amf_cfg.guami_list.size(); i++)
{
struct GuamiItem_s tmp; struct GuamiItem_s tmp;
tmp.mcc = amf_cfg.guami_list[i].mcc; tmp.mcc = amf_cfg.guami_list[i].mcc;
tmp.mnc = amf_cfg.guami_list[i].mnc; tmp.mnc = amf_cfg.guami_list[i].mnc;
tmp.regionID = amf_cfg.guami_list[i].regionID; tmp.regionID = amf_cfg.guami_list[i].regionID;
tmp.AmfSetID = amf_cfg.guami_list[i].AmfSetID; tmp.AmfSetID = amf_cfg.guami_list[i].AmfSetID;
tmp.AmfPointer = amf_cfg.guami_list[i].AmfPointer; tmp.AmfPointer = amf_cfg.guami_list[i].AmfPointer;
// tmp.mcc = amf_cfg.guami_list[i].mcc; //tmp.mcc = amf_cfg.guami_list[i].mcc;
guami_list.push_back(tmp); guami_list.push_back(tmp);
} }
ngSetupResp.setGUAMIList(guami_list); ngSetupResp.setGUAMIList(guami_list);
std::vector<PlmnSliceSupport_t> plmn_list; std::vector<PlmnSliceSupport_t> plmn_list;
for (int i = 0; i < amf_cfg.plmn_list.size(); i++) { for (int i = 0; i < amf_cfg.plmn_list.size(); i++)
{
PlmnSliceSupport_t tmp; PlmnSliceSupport_t tmp;
tmp.mcc = amf_cfg.plmn_list[i].mcc; tmp.mcc = amf_cfg.plmn_list[i].mcc;
tmp.mnc = amf_cfg.plmn_list[i].mnc; tmp.mnc = amf_cfg.plmn_list[i].mnc;
for (int j = 0; j < amf_cfg.plmn_list[i].slice_list.size(); j++) { for (int j = 0; j < amf_cfg.plmn_list[i].slice_list.size(); j++)
{
SliceSupportItem_t s_tmp; SliceSupportItem_t s_tmp;
s_tmp.sst = amf_cfg.plmn_list[i].slice_list[j].sST; s_tmp.sst = amf_cfg.plmn_list[i].slice_list[j].sST;
s_tmp.sd = amf_cfg.plmn_list[i].slice_list[j].sD; s_tmp.sd = amf_cfg.plmn_list[i].slice_list[j].sD;
...@@ -280,66 +313,74 @@ void amf_n2::handle_itti_message(itti_ng_setup_request &itti_msg) { ...@@ -280,66 +313,74 @@ void amf_n2::handle_itti_message(itti_ng_setup_request &itti_msg) {
int encoded = ngSetupResp.encode2buffer((uint8_t *)buffer, 1000); int encoded = ngSetupResp.encode2buffer((uint8_t *)buffer, 1000);
bstring b = blk2bstr(buffer, encoded); bstring b = blk2bstr(buffer, encoded);
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b); sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b);
Logger::amf_n2().debug("Sending NG_SETUP_RESPONSE Ok"); Logger::amf_n2().debug("sending NG_SETUP_RESPONSE ok");
free(buffer);
gc.get()->ng_state = NGAP_READY; gc.get()->ng_state = NGAP_READY;
Logger::amf_n2().debug( Logger::amf_n2().debug("gnb with [gnb_id(0x%x), assoc_id(%d)] has been attached to AMF", gc.get()->globalRanNodeId, itti_msg.assoc_id);
"gNB with gNB_id 0x%x, assoc_id %d has been attached to AMF",
gc.get()->globalRanNodeId, itti_msg.assoc_id);
stacs.gNB_connected += 1; stacs.gNB_connected += 1;
stacs.gnbs.push_back(gnbItem); stacs.gnbs.push_back(gnbItem);
delete itti_msg.ngSetupReq;
Logger::amf_n2().debug("itti_msg.ngSetupReq and pdu are freed");
return; return;
} }
//------------------------------------------------------------------------------ /************************* INITIAL_UE_MESSAGE Handler **************************/
// INITIAL_UE_MESSAGE Handler void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg)
void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg) { {
// create ngap-ue context and store in gNB context to store UE information in //create ngap-ue context and store in gNB context to store UE information in gNB, for example, here RAN UE NGAP ID and location information and RRC Establishment Cause
// gNB, for example, here RAN UE NGAP ID and location information and RRC //send NAS-PDU to NAS layer
// Establishment Cause send NAS-PDU to NAS layer Get INITIAL_UE_MESSAGE IEs /*get INITIAL_UE_MESSAGE IEs*/
//check the gNB context on which this UE is attached with assoc_id
// check the gNB context on which this UE is attached with assoc_id itti_nas_signalling_establishment_request *itti_msg = new itti_nas_signalling_establishment_request(TASK_AMF_N2, TASK_AMF_APP);
itti_nas_signalling_establishment_request *itti_msg =
new itti_nas_signalling_establishment_request(TASK_AMF_N2, TASK_AMF_APP);
if (!is_assoc_id_2_gnb_context(init_ue_msg.assoc_id)) { if (!is_assoc_id_2_gnb_context(init_ue_msg.assoc_id))
Logger::amf_n2().error("No existing gNG context with assoc_id (%d)", {
init_ue_msg.assoc_id); Logger::amf_n2().error("no existed gnb context with assoc_id(%d)", init_ue_msg.assoc_id);
delete init_ue_msg.initUeMsg;
Logger::amf_n2().debug("init_ue_msg.initUeMsg freed");
return; return;
} }
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(init_ue_msg.assoc_id); gc = assoc_id_2_gnb_context(init_ue_msg.assoc_id);
if (gc.get()->ng_state == NGAP_RESETING || if (gc.get()->ng_state == NGAP_RESETING || gc.get()->ng_state == NGAP_SHUTDOWN)
gc.get()->ng_state == NGAP_SHUTDOWN) { {
Logger::amf_n2().warn("Received new association request on an association " Logger::amf_n2().warn("Received new association request on an association that is being %s, ignoring", ng_gnb_state_str[gc.get()->ng_state]);
"that is being %s, ignoring", }
ng_gnb_state_str[gc.get()->ng_state]); else if (gc.get()->ng_state != NGAP_READY)
} else if (gc.get()->ng_state != NGAP_READY) { {
Logger::amf_n2().debug("gNB with assoc_id (%d) is illegal", Logger::amf_n2().debug("gNB with assoc_id(%d) is illegal", init_ue_msg.assoc_id);
init_ue_msg.assoc_id); delete init_ue_msg.initUeMsg;
Logger::amf_n2().debug("init_ue_msg.initUeMsg freed");
return; return;
} }
// UE NGAP Context
uint32_t ran_ue_ngap_id; uint32_t ran_ue_ngap_id;
if ((ran_ue_ngap_id = init_ue_msg.initUeMsg->getRanUENgapID()) == -1) { if ((ran_ue_ngap_id = init_ue_msg.initUeMsg->getRanUENgapID()) == -1)
Logger::amf_n2().error("Missing Mandatory IE (RanUeNgapId)"); {
Logger::amf_n2().error("Missing Mondontary IE(RanUeNgapId)");
delete init_ue_msg.initUeMsg;
Logger::amf_n2().debug("init_ue_msg.initUeMsg freed");
return; return;
} }
std::shared_ptr<ue_ngap_context> unc; std::shared_ptr<ue_ngap_context> unc;
if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id)) { if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id))
Logger::amf_n2().debug( {
"Create a new UE NGAP context with ran_ue_ngap_id 0x%x", Logger::amf_n2().debug("Create a new ue ngap context with ran_ue_ngap_id(0x%x)", ran_ue_ngap_id);
ran_ue_ngap_id);
unc = std::shared_ptr<ue_ngap_context>(new ue_ngap_context()); unc = std::shared_ptr<ue_ngap_context>(new ue_ngap_context());
set_ran_ue_ngap_id_2_ue_ngap_context(ran_ue_ngap_id, unc); set_ran_ue_ngap_id_2_ue_ngap_context(ran_ue_ngap_id, unc);
} else { }
else
{
unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id); unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id);
} }
if (unc.get() == nullptr) { if (unc.get() == nullptr)
Logger::amf_n2().error( {
"Failed to get UE NGAP context for ran_ue_ngap_id 0x%x", 21); Logger::amf_n2().error("Failed to get ue ngap context for ran_ue_ngap_id(0x%x)", 21);
} else { }
// store information into UE NGAP context else
{
//store information into ue ngap context
unc.get()->ran_ue_ngap_id = ran_ue_ngap_id; unc.get()->ran_ue_ngap_id = ran_ue_ngap_id;
unc.get()->sctp_stream_recv = init_ue_msg.stream; unc.get()->sctp_stream_recv = init_ue_msg.stream;
unc.get()->sctp_stream_send == gc.get()->next_sctp_stream; unc.get()->sctp_stream_send == gc.get()->next_sctp_stream;
...@@ -349,17 +390,25 @@ void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg) { ...@@ -349,17 +390,25 @@ void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg) {
unc.get()->gnb_assoc_id = init_ue_msg.assoc_id; unc.get()->gnb_assoc_id = init_ue_msg.assoc_id;
NrCgi_t cgi; NrCgi_t cgi;
Tai_t tai; Tai_t tai;
if (init_ue_msg.initUeMsg->getUserLocationInfoNR(cgi, tai)) { if (init_ue_msg.initUeMsg->getUserLocationInfoNR(cgi, tai))
{
itti_msg->cgi = cgi; itti_msg->cgi = cgi;
itti_msg->tai = tai; itti_msg->tai = tai;
} else { }
Logger::amf_n2().error("Missing Mandatory IE UserLocationInfoNR"); else
{
Logger::amf_n2().error("Missing Mondontary IE UserLocationInfoNR");
delete init_ue_msg.initUeMsg;
Logger::amf_n2().debug("init_ue_msg.initUeMsg freed");
return; return;
} }
if (init_ue_msg.initUeMsg->getRRCEstablishmentCause() == -1) { if (init_ue_msg.initUeMsg->getRRCEstablishmentCause() == -1)
{
Logger::amf_n2().warn("IE RRCEstablishmentCause not present"); Logger::amf_n2().warn("IE RRCEstablishmentCause not present");
itti_msg->rrc_cause = -1; // not present itti_msg->rrc_cause = -1; //not present
} else { }
else
{
itti_msg->rrc_cause = init_ue_msg.initUeMsg->getRRCEstablishmentCause(); itti_msg->rrc_cause = init_ue_msg.initUeMsg->getRRCEstablishmentCause();
} }
#if 0 #if 0
...@@ -368,121 +417,116 @@ void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg) { ...@@ -368,121 +417,116 @@ void amf_n2::handle_itti_message(itti_initial_ue_message &init_ue_msg) {
itti_msg->ueCtxReq = -1;//not present itti_msg->ueCtxReq = -1;//not present
}else{ }else{
itti_msg->ueCtxReq = init_ue_msg.initUeMsg->getUeContextRequest(); itti_msg->ueCtxReq = init_ue_msg.initUeMsg->getUeContextRequest();
Logger::amf_n2().debug("testing 12");
} }
#endif #endif
std::string _5g_s_tmsi; std::string _5g_s_tmsi;
if (!init_ue_msg.initUeMsg->get5GS_TMSI(_5g_s_tmsi)) { if (!init_ue_msg.initUeMsg->get5GS_TMSI(_5g_s_tmsi))
{
itti_msg->is_5g_s_tmsi_present = false; itti_msg->is_5g_s_tmsi_present = false;
Logger::amf_n2().debug("5g_s_tmsi not present"); Logger::amf_n2().debug("5g_s_tmsi false");
} else { }
else
{
itti_msg->is_5g_s_tmsi_present = true; itti_msg->is_5g_s_tmsi_present = true;
itti_msg->_5g_s_tmsi = _5g_s_tmsi; itti_msg->_5g_s_tmsi = _5g_s_tmsi;
Logger::amf_n2().debug("5g_s_tmsi present"); Logger::amf_n2().debug("5g_s_tmsi true");
} }
uint8_t *nas_buf; uint8_t *nas_buf;
size_t nas_len = 0; size_t nas_len = 0;
if (init_ue_msg.initUeMsg->getNasPdu(nas_buf, nas_len)) { if (init_ue_msg.initUeMsg->getNasPdu(nas_buf, nas_len))
{
bstring nas = blk2bstr(nas_buf, nas_len); bstring nas = blk2bstr(nas_buf, nas_len);
itti_msg->nas_buf = nas; itti_msg->nas_buf = nas;
} else { }
else
{
Logger::amf_n2().error("Missing IE NAS-PDU"); Logger::amf_n2().error("Missing IE NAS-PDU");
return; return;
} }
} }
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id; itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = -1; itti_msg->amf_ue_ngap_id = -1;
std::shared_ptr<itti_nas_signalling_establishment_request> i = std::shared_ptr<itti_nas_signalling_establishment_request> i = std::shared_ptr<itti_nas_signalling_establishment_request>(itti_msg);
std::shared_ptr<itti_nas_signalling_establishment_request>(itti_msg);
int ret = itti_inst->send_msg(i); int ret = itti_inst->send_msg(i);
if (0 != ret) { if (0 != ret)
Logger::amf_n2().error( {
"Could not send ITTI message %s to task TASK_AMF_APP", Logger::amf_n2().error("Could not send ITTI message %s to task TASK_AMF_APP", i->get_msg_name());
i->get_msg_name());
} }
delete init_ue_msg.initUeMsg;
} }
//------------------------------------------------------------------------------ void amf_n2::handle_itti_message(itti_ul_nas_transport &ul_nas_transport)
void amf_n2::handle_itti_message(itti_ul_nas_transport &ul_nas_transport) { {
unsigned long amf_ue_ngap_id = ul_nas_transport.ulNas->getAmfUeNgapId(); unsigned long amf_ue_ngap_id = ul_nas_transport.ulNas->getAmfUeNgapId();
uint32_t ran_ue_ngap_id = ul_nas_transport.ulNas->getRanUeNgapId(); uint32_t ran_ue_ngap_id = ul_nas_transport.ulNas->getRanUeNgapId();
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
if (!is_assoc_id_2_gnb_context(ul_nas_transport.assoc_id)) { if (!is_assoc_id_2_gnb_context(ul_nas_transport.assoc_id))
Logger::amf_n2().error("gNB with assoc_id(%d) is illegal", {
ul_nas_transport.assoc_id); Logger::amf_n2().error("gnb with assoc_id(%d) is illegal", ul_nas_transport.assoc_id);
return; return;
} }
gc = assoc_id_2_gnb_context(ul_nas_transport.assoc_id); gc = assoc_id_2_gnb_context(ul_nas_transport.assoc_id);
std::shared_ptr<ue_ngap_context> unc; std::shared_ptr<ue_ngap_context> unc;
if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id)) { if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id))
Logger::amf_n2().error("UE with ran_ue_ngap_id(0x%x) is not attached to " {
"gnb with assoc_id (%d)", Logger::amf_n2().error("UE with ran_ue_ngap_id(0x%x) is not attached to gnb with assoc_id(%d)", ran_ue_ngap_id, ul_nas_transport.assoc_id);
ran_ue_ngap_id, ul_nas_transport.assoc_id);
return; return;
} }
if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id)) { if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id))
Logger::amf_n2().error("No UE NGAP context with ran_ue_ngap_id (%d)", {
ran_ue_ngap_id); Logger::amf_n2().error("no ue ngap context with ran_ue_ngap_id(%d)", ran_ue_ngap_id);
return; return;
} }
unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id); unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id);
if (unc.get()->amf_ue_ngap_id != amf_ue_ngap_id) { if (unc.get()->amf_ue_ngap_id != amf_ue_ngap_id)
Logger::amf_n2().error("The requested UE (amf_ue_ngap_id: 0x%x) is not " {
"valid, existed UE which's amf_ue_ngap_id (0x%x)", Logger::amf_n2().error("The requested UE(amf_ue_ngap_id:0x%x) is not valid, existed UE which's amf_ue_ngap_id(0x%x)", amf_ue_ngap_id, unc.get()->amf_ue_ngap_id);
amf_ue_ngap_id, unc.get()->amf_ue_ngap_id); }
} if (unc.get()->ng_ue_state != NGAP_UE_CONNECTED)
if (unc.get()->ng_ue_state != NGAP_UE_CONNECTED) { {
Logger::amf_n2().error("Received NGAP UPLINK_NAS_TRANSPORT while UE in " Logger::amf_n2().error("Received NGAP UPLINK_NAS_TRANSPORT while UE in state != NGAP_UE_CONNECTED");
"state != NGAP_UE_CONNECTED"); //return;
// return; }
} itti_uplink_nas_data_ind *itti_msg = new itti_uplink_nas_data_ind(TASK_AMF_N2, TASK_AMF_N1);
itti_uplink_nas_data_ind *itti_msg =
new itti_uplink_nas_data_ind(TASK_AMF_N2, TASK_AMF_N1);
itti_msg->is_nas_signalling_estab_req = false; itti_msg->is_nas_signalling_estab_req = false;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id; itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id; itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->is_guti_valid = false; itti_msg->is_guti_valid = false;
uint8_t *nas_buf = NULL; uint8_t *nas_buf = NULL;
size_t nas_len = 0; size_t nas_len = 0;
if (ul_nas_transport.ulNas->getNasPdu(nas_buf, nas_len)) { if (ul_nas_transport.ulNas->getNasPdu(nas_buf, nas_len))
{
itti_msg->nas_msg = blk2bstr(nas_buf, nas_len); itti_msg->nas_msg = blk2bstr(nas_buf, nas_len);
} else { }
else
{
Logger::amf_n2().error("Missing IE NAS-PDU"); Logger::amf_n2().error("Missing IE NAS-PDU");
return; return;
} }
// UserLocation std::shared_ptr<itti_uplink_nas_data_ind> i = std::shared_ptr<itti_uplink_nas_data_ind>(itti_msg);
NrCgi_t cgi = {};
Tai_t tai = {};
if (ul_nas_transport.ulNas->getUserLocationInfoNR(cgi, tai)) {
itti_msg->mcc = cgi.mcc;
itti_msg->mnc = cgi.mnc;
} else {
Logger::amf_n2().debug("Missing IE UserLocationInformationNR");
}
std::shared_ptr<itti_uplink_nas_data_ind> i =
std::shared_ptr<itti_uplink_nas_data_ind>(itti_msg);
int ret = itti_inst->send_msg(i); int ret = itti_inst->send_msg(i);
if (0 != ret) { if (0 != ret)
Logger::amf_n2().error("Could not send ITTI message %s to task TASK_AMF_N1", {
i->get_msg_name()); Logger::amf_n2().error("Could not send ITTI message %s to task TASK_AMF_N1", i->get_msg_name());
} }
} }
//------------------------------------------------------------------------------ void amf_n2::handle_itti_message(itti_dl_nas_transport &dl_nas_transport)
void amf_n2::handle_itti_message(itti_dl_nas_transport &dl_nas_transport) { {
std::shared_ptr<ue_ngap_context> unc; std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(dl_nas_transport.ran_ue_ngap_id); unc = ran_ue_id_2_ue_ngap_context(dl_nas_transport.ran_ue_ngap_id);
if (unc.get() == nullptr) { if (unc.get() == nullptr)
Logger::amf_n2().error("Illegal UE with ran_ue_ngap_id (0x%x)", {
dl_nas_transport.ran_ue_ngap_id); Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", dl_nas_transport.ran_ue_ngap_id);
return; return;
} }
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id); gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if (gc.get() == nullptr) { if (gc.get() == nullptr)
Logger::amf_n2().error("Illegal gNB with assoc id (0x%x)", {
unc.get()->gnb_assoc_id); Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return; return;
} }
unc.get()->amf_ue_ngap_id = dl_nas_transport.amf_ue_ngap_id; unc.get()->amf_ue_ngap_id = dl_nas_transport.amf_ue_ngap_id;
...@@ -491,29 +535,29 @@ void amf_n2::handle_itti_message(itti_dl_nas_transport &dl_nas_transport) { ...@@ -491,29 +535,29 @@ void amf_n2::handle_itti_message(itti_dl_nas_transport &dl_nas_transport) {
ngap_msg->setMessageType(); ngap_msg->setMessageType();
ngap_msg->setAmfUeNgapId(dl_nas_transport.amf_ue_ngap_id); ngap_msg->setAmfUeNgapId(dl_nas_transport.amf_ue_ngap_id);
ngap_msg->setRanUeNgapId(dl_nas_transport.ran_ue_ngap_id); ngap_msg->setRanUeNgapId(dl_nas_transport.ran_ue_ngap_id);
ngap_msg->setNasPdu((uint8_t *)bdata(dl_nas_transport.nas), ngap_msg->setNasPdu((uint8_t *)bdata(dl_nas_transport.nas), blength(dl_nas_transport.nas));
blength(dl_nas_transport.nas));
uint8_t buffer[1024]; uint8_t buffer[1024];
int encoded_size = ngap_msg->encode2buffer(buffer, 1024); int encoded_size = ngap_msg->encode2buffer(buffer, 1024);
delete ngap_msg;
bdestroy(dl_nas_transport.nas);
bstring b = blk2bstr(buffer, encoded_size); bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
unc.get()->sctp_stream_send, &b);
} }
//------------------------------------------------------------------------------ void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg)
void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg) { {
std::shared_ptr<ue_ngap_context> unc; std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id); unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
if (unc.get() == nullptr) { if (unc.get() == nullptr)
Logger::amf_n2().error("Illegal UE with ran_ue_ngap_id (0x%x)", {
itti_msg.ran_ue_ngap_id); Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
return; return;
} }
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id); gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if (gc.get() == nullptr) { if (gc.get() == nullptr)
Logger::amf_n2().error("Illegal gNB with assoc id (0x%x)", {
unc.get()->gnb_assoc_id); Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return; return;
} }
InitialContextSetupRequestMsg *msg = new InitialContextSetupRequestMsg(); InitialContextSetupRequestMsg *msg = new InitialContextSetupRequestMsg();
...@@ -531,59 +575,78 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg) { ...@@ -531,59 +575,78 @@ void amf_n2::handle_itti_message(itti_initial_context_setup_request &itti_msg) {
msg->setSecurityKey((uint8_t *)bdata(itti_msg.kgnb)); msg->setSecurityKey((uint8_t *)bdata(itti_msg.kgnb));
msg->setNasPdu((uint8_t *)bdata(itti_msg.nas), blength(itti_msg.nas)); msg->setNasPdu((uint8_t *)bdata(itti_msg.nas), blength(itti_msg.nas));
if (itti_msg.is_sr) { std::vector<S_Nssai> list;
S_Nssai item;
item.sst = "01";
item.sd = "None";
list.push_back(item);
msg->setAllowedNssai(list);
bdestroy(itti_msg.nas);
bdestroy(itti_msg.kgnb);
if (itti_msg.is_sr)
{
bstring ueCapability = gc.get()->ue_radio_cap_ind; bstring ueCapability = gc.get()->ue_radio_cap_ind;
uint8_t *uecap = (uint8_t *)calloc(1, blength(ueCapability) + 1); uint8_t *uecap = (uint8_t *)calloc(1, blength(ueCapability) + 1);
memcpy(uecap, (uint8_t *)bdata(ueCapability), blength(ueCapability)); memcpy(uecap, (uint8_t *)bdata(ueCapability), blength(ueCapability));
uecap[blength(ueCapability)] = '\0'; uecap[blength(ueCapability)] = '\0';
msg->setUERadioCapability(uecap, (size_t)blength(ueCapability)); msg->setUERadioCapability(uecap, (size_t)blength(ueCapability));
Logger::amf_n2().debug("Encoding parameters for Service Request"); free(uecap);
//msg->setUERadioCapability((uint8_t*)bdata(ueCapability), (size_t)blength(ueCapability));
Logger::amf_n2().debug("Encoding parameters for service request");
if (itti_msg.is_pdu_exist)
{
std::vector<PDUSessionResourceSetupRequestItem_t> list; std::vector<PDUSessionResourceSetupRequestItem_t> list;
PDUSessionResourceSetupRequestItem_t item; PDUSessionResourceSetupRequestItem_t item;
item.pduSessionId = itti_msg.pdu_session_id; item.pduSessionId = itti_msg.pdu_session_id;
item.s_nssai.sst = "01"; item.s_nssai.sst = "01";
item.s_nssai.sd = ""; item.s_nssai.sd = "";
item.pduSessionNAS_PDU = NULL; item.pduSessionNAS_PDU = NULL;
if (itti_msg.isn2sm_avaliable)
{
bstring n2sm = itti_msg.n2sm; bstring n2sm = itti_msg.n2sm;
if (blength(itti_msg.n2sm) != 0) { if (blength(itti_msg.n2sm) != 0)
item.pduSessionResourceSetupRequestTransfer.buf = {
(uint8_t *)bdata(itti_msg.n2sm); item.pduSessionResourceSetupRequestTransfer.buf = (uint8_t *)bdata(itti_msg.n2sm);
item.pduSessionResourceSetupRequestTransfer.size = blength(itti_msg.n2sm); item.pduSessionResourceSetupRequestTransfer.size = blength(itti_msg.n2sm);
} else { }
else
{
Logger::amf_n2().error("n2sm empty!"); Logger::amf_n2().error("n2sm empty!");
} }
}
list.push_back(item); list.push_back(item);
msg->setPduSessionResourceSetupRequestList(list); msg->setPduSessionResourceSetupRequestList(list);
msg->setUEAggregateMaxBitRate(0x08a7d8c0, msg->setUEAggregateMaxBitRate(1000000000, 100000000);
0x20989680); // TODO: remove hardcoded value }
} }
uint8_t buffer[10000]; uint8_t buffer[10000];
int encoded_size = msg->encode2buffer(buffer, 10000); int encoded_size = msg->encode2buffer(buffer, 10000);
bstring b = blk2bstr(buffer, encoded_size); bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
unc.get()->sctp_stream_send, &b); delete msg;
} }
//------------------------------------------------------------------------------ void amf_n2::handle_itti_message(itti_pdu_session_resource_setup_request &itti_msg)
void amf_n2::handle_itti_message( {
itti_pdu_session_resource_setup_request &itti_msg) {
std::shared_ptr<ue_ngap_context> unc; std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id); unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
if (unc.get() == nullptr) { if (unc.get() == nullptr)
Logger::amf_n2().error("Illegal UE with ran_ue_ngap_id (0x%x)", {
itti_msg.ran_ue_ngap_id); Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
return; return;
} }
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id); gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if (gc.get() == nullptr) { if (gc.get() == nullptr)
Logger::amf_n2().error("Illegal gNB with assoc id (0x%x)", {
unc.get()->gnb_assoc_id); Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return; return;
} }
PduSessionResourceSetupRequestMsg *psrsr = PduSessionResourceSetupRequestMsg *psrsr = new PduSessionResourceSetupRequestMsg();
new PduSessionResourceSetupRequestMsg();
psrsr->setMessageType(); psrsr->setMessageType();
psrsr->setAmfUeNgapId(itti_msg.amf_ue_ngap_id); psrsr->setAmfUeNgapId(itti_msg.amf_ue_ngap_id);
psrsr->setRanUeNgapId(itti_msg.ran_ue_ngap_id); psrsr->setRanUeNgapId(itti_msg.ran_ue_ngap_id);
...@@ -594,60 +657,26 @@ void amf_n2::handle_itti_message( ...@@ -594,60 +657,26 @@ void amf_n2::handle_itti_message(
uint8_t *nas_pdu = (uint8_t *)calloc(1, blength(itti_msg.nas) + 1); uint8_t *nas_pdu = (uint8_t *)calloc(1, blength(itti_msg.nas) + 1);
memcpy(nas_pdu, (uint8_t *)bdata(itti_msg.nas), blength(itti_msg.nas)); memcpy(nas_pdu, (uint8_t *)bdata(itti_msg.nas), blength(itti_msg.nas));
nas_pdu[blength(itti_msg.nas)] = '\0'; nas_pdu[blength(itti_msg.nas)] = '\0';
item.pduSessionNAS_PDU = nas_pdu; item.pduSessionNAS_PDU = nas_pdu; //(uint8_t*)bdata(itti_msg.nas);
item.sizeofpduSessionNAS_PDU = blength(itti_msg.nas); item.sizeofpduSessionNAS_PDU = blength(itti_msg.nas);
item.s_nssai.sst = "01"; // TODO: get from N1N2msgTranferMsg item.s_nssai.sst = "01";
item.s_nssai.sd = ""; // TODO: get from N1N2msgTranferMsg item.s_nssai.sd = "";
item.pduSessionResourceSetupRequestTransfer.buf = (uint8_t *)bdata(itti_msg.n2sm);
// Get NSSAI from PDU Session Context
std::shared_ptr<nas_context> nc;
if (amf_n1_inst->is_amf_ue_id_2_nas_context(itti_msg.amf_ue_ngap_id))
nc = amf_n1_inst->amf_ue_id_2_nas_context(itti_msg.amf_ue_ngap_id);
else {
Logger::amf_n2().warn("No existed nas_context with amf_ue_ngap_id(0x%x)",
itti_msg.amf_ue_ngap_id);
// TODO:
}
string supi = "imsi-" + nc.get()->imsi;
Logger::amf_n2().debug("SUPI (%s)", supi.c_str());
std::shared_ptr<pdu_session_context> psc;
if (amf_n11_inst->is_supi_to_pdu_ctx(supi)) {
psc = amf_n11_inst->supi_to_pdu_ctx(supi);
} else {
Logger::amf_n2().warn("Cannot get pdu_session_context with SUPI (%s)",
supi.c_str());
}
item.s_nssai.sst = std::to_string(psc.get()->snssai.sST);
item.s_nssai.sd = psc.get()->snssai.sD;
item.pduSessionResourceSetupRequestTransfer.buf =
(uint8_t *)bdata(itti_msg.n2sm);
item.pduSessionResourceSetupRequestTransfer.size = blength(itti_msg.n2sm); item.pduSessionResourceSetupRequestTransfer.size = blength(itti_msg.n2sm);
list.push_back(item); list.push_back(item);
psrsr->setPduSessionResourceSetupRequestList(list); psrsr->setPduSessionResourceSetupRequestList(list);
bdestroy(itti_msg.nas);
size_t buffer_size = 512; // TODO: remove hardcoded value uint8_t buffer[5000];
char *buffer = (char *)calloc(1, buffer_size); int encoded_size = psrsr->encode2buffer(buffer, 5000);
int encoded_size = 0; delete psrsr;
psrsr->encode2buffer_new(buffer, encoded_size);
#if DEBUG_IS_ON
Logger::amf_n2().debug("N2 SM buffer data: ");
for (int i = 0; i < encoded_size; i++)
printf("%02x ", (char)buffer[i]);
#endif
Logger::amf_n2().debug(" (%d bytes) \n", encoded_size);
bstring b = blk2bstr(buffer, encoded_size); bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
unc.get()->sctp_stream_send, &b);
// free memory
free_wrapper((void **)&buffer);
} }
//------------------------------------------------------------------------------ void amf_n2::handle_itti_message(itti_ue_context_release_request &itti_msg)
void amf_n2::handle_itti_message(itti_ue_context_release_request &itti_msg) { {
Logger::amf_n2().debug("Handling UE context release request ..."); Logger::amf_n2().debug("handling ue context release request ...");
unsigned long amf_ue_ngap_id = itti_msg.ueCtxRel->getAmfUeNgapId(); unsigned long amf_ue_ngap_id = itti_msg.ueCtxRel->getAmfUeNgapId();
uint32_t ran_ue_ngap_id = itti_msg.ueCtxRel->getRanUeNgapId(); uint32_t ran_ue_ngap_id = itti_msg.ueCtxRel->getRanUeNgapId();
e_Ngap_CauseRadioNetwork cause; e_Ngap_CauseRadioNetwork cause;
...@@ -658,17 +687,99 @@ void amf_n2::handle_itti_message(itti_ue_context_release_request &itti_msg) { ...@@ -658,17 +687,99 @@ void amf_n2::handle_itti_message(itti_ue_context_release_request &itti_msg) {
ueCtxRelCmd->setCauseRadioNetwork(cause); ueCtxRelCmd->setCauseRadioNetwork(cause);
uint8_t buffer[200]; uint8_t buffer[200];
int encoded_size = ueCtxRelCmd->encode2buffer(buffer, 200); int encoded_size = ueCtxRelCmd->encode2buffer(buffer, 200);
delete ueCtxRelCmd;
bstring b = blk2bstr(buffer, encoded_size); bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b); sctp_s_38412.sctp_send_msg(itti_msg.assoc_id, itti_msg.stream, &b);
delete itti_msg.ueCtxRel;
} }
//------------------------------------------------------------------------------ void amf_n2::handle_itti_message(itti_ue_context_release_command &itti_msg)
void amf_n2::handle_itti_message( {
itti_ue_radio_capability_indication &itti_msg) { Logger::amf_n2().debug("handling ue context release command ...");
std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
if (unc.get() == nullptr)
{
Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
return;
}
std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if (gc.get() == nullptr)
{
Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return;
}
UEContextReleaseCommandMsg *ueCtxRelCmd = new UEContextReleaseCommandMsg();
ueCtxRelCmd->setMessageType();
ueCtxRelCmd->setUeNgapIdPair(itti_msg.amf_ue_ngap_id, itti_msg.ran_ue_ngap_id);
if (itti_msg.cause.getChoiceOfCause() == Ngap_Cause_PR_nas)
{
ueCtxRelCmd->setCauseNas((e_Ngap_CauseNas)itti_msg.cause.getValue());
}
if (itti_msg.cause.getChoiceOfCause() == Ngap_Cause_PR_radioNetwork)
{
ueCtxRelCmd->setCauseRadioNetwork((e_Ngap_CauseRadioNetwork)itti_msg.cause.getValue());
}
uint8_t buffer[200];
int encoded_size = ueCtxRelCmd->encode2buffer(buffer, 200);
delete ueCtxRelCmd;
bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
}
void amf_n2::handle_itti_message(itti_pdu_session_resource_release_command &itti_msg)
{
Logger::amf_n2().debug("handling pdu session resource release command ...");
std::shared_ptr<ue_ngap_context> unc;
unc = ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
if (unc.get() == nullptr)
{
Logger::amf_n2().error("Illegal ue with ran_ue_ngap_id(0x%x)", itti_msg.ran_ue_ngap_id);
return;
}
std::shared_ptr<gnb_context> gc;
gc = assoc_id_2_gnb_context(unc.get()->gnb_assoc_id);
if (gc.get() == nullptr)
{
Logger::amf_n2().error("Illegal gnb with assoc id(0x%x)", unc.get()->gnb_assoc_id);
return;
}
PduSessionResourceReleaseCommand *pdusessionresourcereleasecommand = new PduSessionResourceReleaseCommand();
Logger::amf_n2().error(" handling pdu session resource release command set messagetype");
pdusessionresourcereleasecommand->setMessageType();
pdusessionresourcereleasecommand->setAmfUeNgapId(itti_msg.amf_ue_ngap_id);
pdusessionresourcereleasecommand->setRanUeNgapId(itti_msg.ran_ue_ngap_id);
std::vector<PDUSessionResourceReleaseCommandItem_t> list;
PDUSessionResourceReleaseCommandItem_t item;
PDUSessionResourceReleaseCommandTransfer *transfer = new PDUSessionResourceReleaseCommandTransfer();
uint8_t buffertrans[1000];
transfer->setCauseRadioNetwork(Ngap_CauseRadioNetwork_multiple_PDU_session_ID_instances);
item.pduSessionResourceReleaseCommandTransfer.size = transfer->encode2buffer(buffertrans, 1000);
item.pduSessionResourceReleaseCommandTransfer.buf = buffertrans;
item.pduSessionId = 5;
list.push_back(item);
pdusessionresourcereleasecommand->setPduSessionResourceToReleaseList(list);
Logger::amf_n2().error(" handling pdu session resource release command set amf/ran ngap id%d %d ", itti_msg.amf_ue_ngap_id, itti_msg.ran_ue_ngap_id);
uint8_t buffer[1000];
int encoded_size = pdusessionresourcereleasecommand->encode2buffer(buffer, 200);
Logger::amf_n2().error(" handling pdu session resource release command encoder");
delete pdusessionresourcereleasecommand;
delete transfer;
bstring b = blk2bstr(buffer, encoded_size);
sctp_s_38412.sctp_send_msg(gc.get()->sctp_assoc_id, unc.get()->sctp_stream_send, &b);
}
void amf_n2::handle_itti_message(itti_ue_radio_capability_indication &itti_msg)
{
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) { if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id))
Logger::amf_n2().error("No existed gNB context with assoc_id (%d)", {
itti_msg.assoc_id); Logger::amf_n2().error("no existed gnb context with assoc_id(%d)", itti_msg.assoc_id);
return; return;
} }
gc = assoc_id_2_gnb_context(itti_msg.assoc_id); gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
...@@ -678,61 +789,60 @@ void amf_n2::handle_itti_message( ...@@ -678,61 +789,60 @@ void amf_n2::handle_itti_message(
itti_msg.ueRadioCap->getRanUeNgapId(ran_ue_ngap_id); itti_msg.ueRadioCap->getRanUeNgapId(ran_ue_ngap_id);
uint8_t *ue_radio_cap; uint8_t *ue_radio_cap;
size_t size; size_t size;
if (!itti_msg.ueRadioCap->getUERadioCapability(ue_radio_cap, size)) { if (!itti_msg.ueRadioCap->getUERadioCapability(ue_radio_cap, size))
{
Logger::amf_n2().warn("No IE UERadioCapability"); Logger::amf_n2().warn("No IE UERadioCapability");
} }
gc.get()->ue_radio_cap_ind = blk2bstr(ue_radio_cap, (int)size); gc.get()->ue_radio_cap_ind = blk2bstr(ue_radio_cap, (int)size);
delete itti_msg.ueRadioCap;
} }
/***********************************handover**********************************/
//------------------------------------------------------------------------------ void amf_n2::handle_itti_message(itti_handover_required &itti_msg)
void amf_n2::handle_itti_message(itti_handover_required &itti_msg) { {
unsigned long amf_ue_ngap_id = itti_msg.handvoerRequ->getAmfUeNgapId(); unsigned long amf_ue_ngap_id = itti_msg.handvoerRequ->getAmfUeNgapId();
uint32_t ran_ue_ngap_id = itti_msg.handvoerRequ->getRanUeNgapId(); uint32_t ran_ue_ngap_id = itti_msg.handvoerRequ->getRanUeNgapId();
ran_id_Global = ran_ue_ngap_id;
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) { if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id))
Logger::amf_n2().error("gnb with assoc_id(%d) is illegal", {
itti_msg.assoc_id); Logger::amf_n2().error("gnb with assoc_id(%d) is illegal", itti_msg.assoc_id);
return; return;
} }
gc = assoc_id_2_gnb_context(itti_msg.assoc_id); gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
std::shared_ptr<ue_ngap_context> unc; std::shared_ptr<ue_ngap_context> unc;
if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id)) { if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id))
Logger::amf_n2().error( {
"UE with ran_ue_ngap_id(0x%x) is not attached to gnb with assoc_id(%d)", Logger::amf_n2().error("UE with ran_ue_ngap_id(0x%x) is not attached to gnb with assoc_id(%d)", ran_ue_ngap_id, itti_msg.assoc_id);
ran_ue_ngap_id, itti_msg.assoc_id);
return; return;
} }
if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id)) { if (!is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id))
Logger::amf_n2().error("no ue ngap context with ran_ue_ngap_id(%d)", {
ran_ue_ngap_id); Logger::amf_n2().error("no ue ngap context with ran_ue_ngap_id(%d)", ran_ue_ngap_id);
return; return;
} }
unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id); unc = ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id);
if (unc.get()->amf_ue_ngap_id != amf_ue_ngap_id) { if (unc.get()->amf_ue_ngap_id != amf_ue_ngap_id)
Logger::amf_n2().error("The requested UE(amf_ue_ngap_id:0x%x) is not " {
"valid, existed UE which's amf_ue_ngap_id(0x%x)", Logger::amf_n2().error("The requested UE(amf_ue_ngap_id:0x%x) is not valid, existed UE which's amf_ue_ngap_id(0x%x)", amf_ue_ngap_id, unc.get()->amf_ue_ngap_id);
amf_ue_ngap_id, unc.get()->amf_ue_ngap_id);
} }
if (itti_msg.handvoerRequ->getHandoverType() != Ngap_HandoverType_intra5gs) { if (itti_msg.handvoerRequ->getHandoverType() != Ngap_HandoverType_intra5gs)
Logger::amf_n2().error("Received Handover Required message,but handover " {
"type is not Ngap_HandoverType_intra5gs"); Logger::amf_n2().error("Received Handover Required message,but handover type is not Ngap_HandoverType_intra5gs");
return; return;
} }
if (itti_msg.handvoerRequ->getChoiceOfCause() != Ngap_Cause_PR_radioNetwork) { if (itti_msg.handvoerRequ->getChoiceOfCause() != Ngap_Cause_PR_radioNetwork)
Logger::amf_n2().error( {
"Received Handover Required message,but Cause Of Choice is wrong"); Logger::amf_n2().error("Received Handover Required message,but Cause Of Choice is wrong");
return; return;
} }
if (itti_msg.handvoerRequ->getCauseValue() != if (itti_msg.handvoerRequ->getCauseValue() != Ngap_CauseRadioNetwork_handover_desirable_for_radio_reason)
Ngap_CauseRadioNetwork_handover_desirable_for_radio_reason) { {
Logger::amf_n2().error( Logger::amf_n2().error("Received Handover Required message,but Value of Cause is wrong");
"Received Handover Required message,but Value of Cause is wrong");
return; return;
} }
if (itti_msg.handvoerRequ->getDirectForwardingPathAvailability() != if (itti_msg.handvoerRequ->getDirectForwardingPathAvailability() != Ngap_DirectForwardingPathAvailability_direct_path_available)
Ngap_DirectForwardingPathAvailability_direct_path_available) { {
Logger::amf_n2().error("Received Handover Required message,but " Logger::amf_n2().error("Received Handover Required message,but DirectForwardingPathAvailability is wrong");
"DirectForwardingPathAvailability is wrong");
return; return;
} }
GlobalgNBId *TargetGlobalgNBId = new GlobalgNBId(); GlobalgNBId *TargetGlobalgNBId = new GlobalgNBId();
...@@ -743,9 +853,7 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) { ...@@ -743,9 +853,7 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) {
string mcc, mnc; string mcc, mnc;
plmn->getMcc(mcc); plmn->getMcc(mcc);
plmn->getMnc(mnc); plmn->getMnc(mnc);
printf("handover required:Target ID GlobalRanNodeID PLmn=mcc%s mnc%s " printf("handover required:Target ID GlobalRanNodeID PLmn=mcc%s mnc%s gnbid=%x\n", mcc.c_str(), mnc.c_str(), gnbid->getValue());
"gnbid=%x\n",
mcc.c_str(), mnc.c_str(), gnbid->getValue());
TAI *tai = new TAI(); TAI *tai = new TAI();
itti_msg.handvoerRequ->getTAI(tai); itti_msg.handvoerRequ->getTAI(tai);
PlmnId *plmnOfTAI = new PlmnId(); PlmnId *plmnOfTAI = new PlmnId();
...@@ -754,26 +862,22 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) { ...@@ -754,26 +862,22 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) {
string mccOfselectTAI, mncOfselectTAI; string mccOfselectTAI, mncOfselectTAI;
plmn->getMcc(mccOfselectTAI); plmn->getMcc(mccOfselectTAI);
plmn->getMnc(mncOfselectTAI); plmn->getMnc(mncOfselectTAI);
printf("handover required:Target ID selectedTAI PLmn=mcc%s mnc%s gnbid=%x\n", printf("handover required:Target ID selectedTAI PLmn=mcc%s mnc%s tac=%x\n", mccOfselectTAI.c_str(), mncOfselectTAI.c_str(), tac->getTac());
mccOfselectTAI.c_str(), mncOfselectTAI.c_str(), tac->getTac());
std::vector<PDUSessionResourceItem_t> List_HORqd; std::vector<PDUSessionResourceItem_t> List_HORqd;
if (!itti_msg.handvoerRequ->getPDUSessionResourceList(List_HORqd)) { if (!itti_msg.handvoerRequ->getPDUSessionResourceList(List_HORqd))
Logger::ngap().error( {
"decoding HandoverRequiredMsg getPDUSessionResourceList IE error"); Logger::ngap().error("decoding HandoverRequiredMsg getPDUSessionResourceList IE error");
return; return;
} }
OCTET_STRING_t sourceTotarget; OCTET_STRING_t sourceTotarget;
sourceTotarget = sourceTotarget = itti_msg.handvoerRequ->getSourceToTarget_TransparentContainer();
itti_msg.handvoerRequ->getSourceToTarget_TransparentContainer();
/**********************send handover request to target /**********************send handover request to target gnb*******************************/
* gnb*******************************/
HandoverRequest *handoverrequest = new HandoverRequest(); HandoverRequest *handoverrequest = new HandoverRequest();
handoverrequest->setMessageType(); handoverrequest->setMessageType();
handoverrequest->setAmfUeNgapId(amf_ue_ngap_id); handoverrequest->setAmfUeNgapId(amf_ue_ngap_id);
handoverrequest->setHandoverType(0); handoverrequest->setHandoverType(0);
handoverrequest->setCause( handoverrequest->setCause(Ngap_Cause_PR_radioNetwork, Ngap_CauseRadioNetwork_handover_desirable_for_radio_reason);
Ngap_Cause_PR_radioNetwork,
Ngap_CauseRadioNetwork_handover_desirable_for_radio_reason);
handoverrequest->setUEAggregateMaximumBitRate(300000000, 100000000); handoverrequest->setUEAggregateMaximumBitRate(300000000, 100000000);
handoverrequest->setUESecurityCapabilities(0, 1, 2, 3); handoverrequest->setUESecurityCapabilities(0, 1, 2, 3);
...@@ -798,8 +902,7 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) { ...@@ -798,8 +902,7 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) {
m_aMFPointer->setAMFPointer(guami.AmfPointer); m_aMFPointer->setAMFPointer(guami.AmfPointer);
handoverrequest->setGUAMI(m_plmnId, m_aMFRegionID, m_aMFSetID, m_aMFPointer); handoverrequest->setGUAMI(m_plmnId, m_aMFRegionID, m_aMFSetID, m_aMFPointer);
std::shared_ptr<nas_context> nc = std::shared_ptr<nas_context> nc = amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
nas_secu_ctx *secu = nc.get()->security_ctx; nas_secu_ctx *secu = nc.get()->security_ctx;
uint8_t *kamf = nc.get()->kamf[secu->vector_pointer]; uint8_t *kamf = nc.get()->kamf[secu->vector_pointer];
uint8_t kgnb[32]; uint8_t kgnb[32];
...@@ -810,8 +913,7 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) { ...@@ -810,8 +913,7 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) {
handoverrequest->setSecurityContext(2, (uint8_t *)bdata(kgnb_bs)); handoverrequest->setSecurityContext(2, (uint8_t *)bdata(kgnb_bs));
handoverrequest->setSourceToTarget_TransparentContainer(sourceTotarget); handoverrequest->setSourceToTarget_TransparentContainer(sourceTotarget);
string supi = "imsi-" + nc.get()->imsi; string supi = "imsi-" + nc.get()->imsi;
std::shared_ptr<pdu_session_context> psc = std::shared_ptr<pdu_session_context> psc = amf_n11_inst->supi_to_pdu_ctx(supi);
amf_n11_inst->supi_to_pdu_ctx(supi);
std::vector<PDUSessionResourceSetupRequestItem_t> list; std::vector<PDUSessionResourceSetupRequestItem_t> list;
PDUSessionResourceSetupRequestItem_t item; PDUSessionResourceSetupRequestItem_t item;
item.pduSessionId = psc.get()->pdu_session_id; item.pduSessionId = psc.get()->pdu_session_id;
...@@ -819,11 +921,13 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) { ...@@ -819,11 +921,13 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) {
item.s_nssai.sd = ""; item.s_nssai.sd = "";
item.pduSessionNAS_PDU = NULL; item.pduSessionNAS_PDU = NULL;
bstring n2sm = psc.get()->n2sm; bstring n2sm = psc.get()->n2sm;
if (blength(psc.get()->n2sm) != 0) { if (blength(psc.get()->n2sm) != 0)
item.pduSessionResourceSetupRequestTransfer.buf = {
(uint8_t *)bdata(psc.get()->n2sm); item.pduSessionResourceSetupRequestTransfer.buf = (uint8_t *)bdata(psc.get()->n2sm);
item.pduSessionResourceSetupRequestTransfer.size = blength(psc.get()->n2sm); item.pduSessionResourceSetupRequestTransfer.size = blength(psc.get()->n2sm);
} else { }
else
{
Logger::amf_n2().error("n2sm empty!"); Logger::amf_n2().error("n2sm empty!");
} }
list.push_back(item); list.push_back(item);
...@@ -837,41 +941,43 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) { ...@@ -837,41 +941,43 @@ void amf_n2::handle_itti_message(itti_handover_required &itti_msg) {
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_handover_request_Ack &itti_msg) { void amf_n2::handle_itti_message(itti_handover_request_Ack &itti_msg)
{
unsigned long amf_ue_ngap_id = itti_msg.handoverrequestAck->getAmfUeNgapId(); unsigned long amf_ue_ngap_id = itti_msg.handoverrequestAck->getAmfUeNgapId();
uint32_t ran_ue_ngap_id = itti_msg.handoverrequestAck->getRanUeNgapId(); uint32_t ran_ue_ngap_id = itti_msg.handoverrequestAck->getRanUeNgapId();
Logger::amf_n2().error( AMF_TARGET_ran_id_global = ran_ue_ngap_id;
"handover request ACk ran_ue_ngap_id(0x%d) amf_ue_ngap_id(%d)", Logger::amf_n2().error("handover request Ack ran_ue_ngap_id(0x%d) amf_ue_ngap_id(%d)", ran_ue_ngap_id, amf_ue_ngap_id);
ran_ue_ngap_id, amf_ue_ngap_id);
std::shared_ptr<gnb_context> gc; std::shared_ptr<gnb_context> gc;
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id)) { if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id))
Logger::amf_n2().error("gnb with assoc_id(%d) is illegal", {
itti_msg.assoc_id); Logger::amf_n2().error("gnb with assoc_id(%d) is illegal", itti_msg.assoc_id);
return; return;
} }
gc = assoc_id_2_gnb_context(itti_msg.assoc_id); gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
std::vector<PDUSessionResourceAdmittedItem_t> list; std::vector<PDUSessionResourceAdmittedItem_t> list;
if (!itti_msg.handoverrequestAck->getPDUSessionResourceAdmittedList(list)) { if (!itti_msg.handoverrequestAck->getPDUSessionResourceAdmittedList(list))
Logger::ngap().error( {
"decoding HandoverRequestACK getPDUSessionResourceList IE error"); Logger::ngap().error("decoding HandoverRequestACK getPDUSessionResourceList IE error");
return; return;
} }
OCTET_STRING_t targetTosource; OCTET_STRING_t targetTosource;
targetTosource = targetTosource = itti_msg.handoverrequestAck->getTargetToSource_TransparentContainer();
itti_msg.handoverrequestAck->getTargetToSource_TransparentContainer();
// add-start /**************************add-start**************************/
OCTET_STRING_t handoverRequestAckTransfer; PDUSessionResourceHandoverRequestAckTransfer *PDUHandoverRequestAckTransfer = new PDUSessionResourceHandoverRequestAckTransfer();
handoverRequestAckTransfer = list[0].handoverRequestAcknowledgeTransfer; uint8_t buf[1024];
PDUSessionResourceHandoverRequestAckTransfer *PDUHandoverRequestAckTransfer = cout << list[0].handoverRequestAcknowledgeTransfer.buf << endl;
new PDUSessionResourceHandoverRequestAckTransfer(); cout << list[0].handoverRequestAcknowledgeTransfer.size << endl;
if (!PDUHandoverRequestAckTransfer->decodefromHandoverRequestAckTransfer(
handoverRequestAckTransfer.buf, handoverRequestAckTransfer.size)) { memcpy(buf, list[0].handoverRequestAcknowledgeTransfer.buf, list[0].handoverRequestAcknowledgeTransfer.size);
if (!PDUHandoverRequestAckTransfer->decodefromHandoverRequestAckTransfer(buf, list[0].handoverRequestAcknowledgeTransfer.size))
{
cout << "decode handoverrequestacktransfer error" << endl; cout << "decode handoverrequestacktransfer error" << endl;
return; return;
} }
GtpTunnel_t *gtptunnel = new GtpTunnel_t(); GtpTunnel_t *gtptunnel = new GtpTunnel_t();
if (!PDUHandoverRequestAckTransfer->getUpTransportLayerInformation2( if (!PDUHandoverRequestAckTransfer->getUpTransportLayerInformation2(gtptunnel))
gtptunnel)) { {
cout << "decode GtpTunnel error" << endl; cout << "decode GtpTunnel error" << endl;
return; return;
} }
...@@ -880,67 +986,172 @@ void amf_n2::handle_itti_message(itti_handover_request_Ack &itti_msg) { ...@@ -880,67 +986,172 @@ void amf_n2::handle_itti_message(itti_handover_request_Ack &itti_msg) {
n3_ip_address = gtptunnel->ip_address; n3_ip_address = gtptunnel->ip_address;
teid = gtptunnel->gtp_teid; teid = gtptunnel->gtp_teid;
std::vector<QosFlowLItemWithDataForwarding_t> QosFlowWithDataForwardinglist; std::vector<QosFlowLItemWithDataForwarding_t> QosFlowWithDataForwardinglist;
PDUHandoverRequestAckTransfer->getqosFlowSetupResponseList( PDUHandoverRequestAckTransfer->getqosFlowSetupResponseList(QosFlowWithDataForwardinglist);
QosFlowWithDataForwardinglist);
long qosflowidentifiervalue; long qosflowidentifiervalue;
qosflowidentifiervalue = qosflowidentifiervalue = (long)QosFlowWithDataForwardinglist[0].qosFlowIdentifier;
(long)QosFlowWithDataForwardinglist[0].qosFlowIdentifier; cout << "QFI get is " << qosflowidentifiervalue << endl;
// add-end /**************************add-end**************************/
/**************************send HandoverCommandMsg to Source gnb**************************/
HandoverCommandMsg *handovercommand = new HandoverCommandMsg(); HandoverCommandMsg *handovercommand = new HandoverCommandMsg();
handovercommand->setMessageType(); handovercommand->setMessageType();
handovercommand->setAmfUeNgapId(amf_ue_ngap_id); handovercommand->setAmfUeNgapId(amf_ue_ngap_id);
handovercommand->setRanUeNgapId(ran_ue_ngap_id); handovercommand->setRanUeNgapId(ran_id_Global);
handovercommand->setHandoverType(Ngap_HandoverType_intra5gs); handovercommand->setHandoverType(Ngap_HandoverType_intra5gs);
// handovercommand.setPduSessionResourceHandoverList();//////////////////////////////////////////////////////////////////
handovercommand->setTargetToSource_TransparentContainer(targetTosource); handovercommand->setTargetToSource_TransparentContainer(targetTosource);
std::shared_ptr<nas_context> nc = amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
/**************************setPduSessionResourceHandoverList_PDYSessionID_handovercommandtransfer**************************/
std::vector<PDUSessionResourceHandoverItem_t> handover_list;
PDUSessionResourceHandoverItem_t item;
//set pdu id
item.pduSessionId = list[0].pduSessionId;
//set qosFLowtobeforwardedlist
std::vector<QosFlowToBeForwardedItem_t> forward_list;
QosFlowToBeForwardedItem_t forward_item;
forward_item.QFI = qosflowidentifiervalue;
forward_list.push_back(forward_item);
//set dlforwardingup_tnlinformation
//TransportLayerAddress *transportlayeraddress = new TransportLayerAddress();
//transportlayeraddress->setTransportLayerAddress(n3_ip_address);
//GtpTeid *gtpTeid = new GtpTeid();
//gtpTeid->setGtpTeid(teid);
PDUSessionResourceHandoverCommandTransfer *handovercommandtransfer = new PDUSessionResourceHandoverCommandTransfer();
handovercommandtransfer->setQosFlowToBeForwardedList(forward_list);
GtpTunnel_t uptlinfo;
uptlinfo.gtp_teid = teid;
uptlinfo.ip_address = n3_ip_address;
handovercommandtransfer->setUPTransportLayerInformation(uptlinfo);
uint8_t buffer2[500];
int encoded_size2 = handovercommandtransfer->encodePDUSessionResourceHandoverCommandTransfer(buffer2, 500);
OCTET_STRING_t OCT_handovercommandtransfer;
OCT_handovercommandtransfer.buf = buffer2;
OCT_handovercommandtransfer.size = encoded_size2;
item.HandoverCommandTransfer = OCT_handovercommandtransfer;
handover_list.push_back(item);
handovercommand->setPduSessionResourceHandoverList(handover_list);
/**************************setPduSessionResourceHandoverList_PDYSessionID_handovercommandtransfer-end**************************/
uint8_t buffer[10240]; uint8_t buffer[10240];
int encoded_size = handovercommand->encode2buffer(buffer, 10240); int encoded_size = handovercommand->encode2buffer(buffer, 10240);
bstring b = blk2bstr(buffer, encoded_size); bstring b = blk2bstr(buffer, encoded_size);
std::shared_ptr<nas_context> nc = std::shared_ptr<ue_ngap_context> ngc = ran_ue_id_2_ue_ngap_context(nc.get()->ran_ue_ngap_id);
amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
std::shared_ptr<ue_ngap_context> ngc =
ran_ue_id_2_ue_ngap_context(nc.get()->ran_ue_ngap_id);
sctp_s_38412.sctp_send_msg(ngc.get()->gnb_assoc_id, 0, &b); sctp_s_38412.sctp_send_msg(ngc.get()->gnb_assoc_id, 0, &b);
} }
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_handover_notify &itti_msg) {} void amf_n2::handle_itti_message(itti_handover_notify &itti_msg)
// Context management functions {
//------------------------------------------------------------------------------ unsigned long amf_ue_ngap_id = itti_msg.handovernotify->getAmfUeNgapId();
uint32_t ran_ue_ngap_id = itti_msg.handovernotify->getRanUeNgapId();
Logger::amf_n2().error("handover notify ran_ue_ngap_id(0x%d) amf_ue_ngap_id(%d)", ran_ue_ngap_id, amf_ue_ngap_id);
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id))
{
Logger::amf_n2().error("gnb with assoc_id(%d) is illegal", itti_msg.assoc_id);
return;
}
NrCgi_t NR_CGI = {};
Tai_t TAI = {};
if (!itti_msg.handovernotify->getUserLocationInfoNR(NR_CGI, TAI))
{
Logger::amf_n2().debug("Missing IE UserLocationInformationNR");
return;
}
std::shared_ptr<nas_context> nc = amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
string supi = "imsi-" + nc.get()->imsi;
std::shared_ptr<pdu_session_context> psc = amf_n11_inst->supi_to_pdu_ctx(supi);
itti_nsmf_pdusession_update_sm_context *itti_nsmf_msg = new itti_nsmf_pdusession_update_sm_context(TASK_AMF_N2, TASK_AMF_N11);
itti_nsmf_msg->pdu_session_id = psc.get()->pdu_session_id;
itti_nsmf_msg->n2sm = psc.get()->n2sm;
std::shared_ptr<itti_nsmf_pdusession_update_sm_context> i = std::shared_ptr<itti_nsmf_pdusession_update_sm_context>(itti_nsmf_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret)
{
Logger::ngap().error("Could not send ITTI message %s to task TASK_AMF_N11", i->get_msg_name());
}
}
void amf_n2::handle_itti_message(itti_uplinkranstatsutransfer &itti_msg)
{
unsigned long amf_ue_ngap_id = itti_msg.uplinkrantransfer->getAmfUeNgapId();
Logger::amf_n2().error("uplinkranstatustransfer amf_ue_ngap_id(%d)", amf_ue_ngap_id);
if (!is_assoc_id_2_gnb_context(itti_msg.assoc_id))
{
Logger::amf_n2().error("gnb with assoc_id(%d) is illegal", itti_msg.assoc_id);
return;
}
RANStatusTransferTransparentContainer *ran_status_transfer = (RANStatusTransferTransparentContainer *)calloc(1, sizeof(RANStatusTransferTransparentContainer));
itti_msg.uplinkrantransfer->getRANStatusTransfer_TransparentContainer(ran_status_transfer);
dRBSubjectList *amf_m_list = (dRBSubjectList *)calloc(1, sizeof(dRBSubjectList));
ran_status_transfer->getdRBSubject_list(amf_m_list);
dRBSubjectItem *amf_m_item = (dRBSubjectItem *)calloc(1, sizeof(dRBSubjectItem));
int numofitem = 0;
amf_m_list->getdRBSubjectItem(amf_m_item, numofitem);
dRBStatusDL *amf_DL = (dRBStatusDL *)calloc(1, sizeof(dRBStatusDL));
dRBStatusUL *amf_UL = (dRBStatusUL *)calloc(1, sizeof(dRBStatusUL));
Ngap_DRB_ID_t *amf_dRB_id = (Ngap_DRB_ID_t *)calloc(1, sizeof(Ngap_DRB_ID_t));
amf_m_item->getdRBSubjectItem(amf_dRB_id, amf_UL, amf_DL);
dRBStatusUL18 *UL18 = (dRBStatusUL18 *)calloc(1, sizeof(dRBStatusUL18));
DRBStatusDL18 *DL18 = (DRBStatusDL18 *)calloc(1, sizeof(DRBStatusDL18));
amf_DL->getDRBStatusDL18(DL18);
amf_UL->getdRBStatusUL(UL18);
COUNTValueForPDCP_SN18 *amf_UL_value = (COUNTValueForPDCP_SN18 *)calloc(1, sizeof(COUNTValueForPDCP_SN18));
COUNTValueForPDCP_SN18 *amf_DL_value = (COUNTValueForPDCP_SN18 *)calloc(1, sizeof(COUNTValueForPDCP_SN18));
UL18->getcountvalue(amf_UL_value);
DL18->getcountvalue(amf_DL_value);
long amf_ul_pdcp;
long amf_hfn_ul_pdcp;
amf_UL_value->getvalue(amf_ul_pdcp, amf_hfn_ul_pdcp);
long amf_dl_pdcp;
long amf_hfn_dl_pdcp;
amf_DL_value->getvalue(amf_dl_pdcp, amf_hfn_dl_pdcp);
long amf_drb_id;
amf_drb_id = *amf_dRB_id;
DownlinkRANStatusTransfer *downLinkranstatustransfer = new DownlinkRANStatusTransfer();
downLinkranstatustransfer->setmessagetype();
downLinkranstatustransfer->setAmfUeNgapId(amf_ue_ngap_id);
downLinkranstatustransfer->setRanUeNgapId(AMF_TARGET_ran_id_global);
downLinkranstatustransfer->setRANStatusTransfer_TransparentContainer(amf_drb_id, amf_ul_pdcp, amf_hfn_ul_pdcp, amf_dl_pdcp, amf_hfn_dl_pdcp);
uint8_t buffer[1024];
int encode_size = downLinkranstatustransfer->encodetobuffer(buffer, 1024);
bstring b = blk2bstr(buffer, encode_size);
std::shared_ptr<ue_ngap_context> ngc = ran_ue_id_2_ue_ngap_context(AMF_TARGET_ran_id_global);
sctp_s_38412.sctp_send_msg(ngc.get()->gnb_assoc_id, 0, &b);
}
/************************************************* context management functions *********************************/
bool amf_n2::is_ran_ue_id_2_ue_ngap_context( bool amf_n2::is_ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const
const uint32_t &ran_ue_ngap_id) const { {
std::shared_lock lock(m_ranid2uecontext); std::shared_lock lock(m_ranid2uecontext);
return bool{ranid2uecontext.count(ran_ue_ngap_id) > 0}; return bool{ranid2uecontext.count(ran_ue_ngap_id) > 0};
} }
//------------------------------------------------------------------------------ std::shared_ptr<ue_ngap_context> amf_n2::ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const
std::shared_ptr<ue_ngap_context> {
amf_n2::ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const {
std::shared_lock lock(m_ranid2uecontext); std::shared_lock lock(m_ranid2uecontext);
return ranid2uecontext.at(ran_ue_ngap_id); return ranid2uecontext.at(ran_ue_ngap_id);
} }
//------------------------------------------------------------------------------ void amf_n2::set_ran_ue_ngap_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id, std::shared_ptr<ue_ngap_context> unc)
void amf_n2::set_ran_ue_ngap_id_2_ue_ngap_context( {
const uint32_t &ran_ue_ngap_id, std::shared_ptr<ue_ngap_context> unc) {
std::shared_lock lock(m_ranid2uecontext); std::shared_lock lock(m_ranid2uecontext);
ranid2uecontext[ran_ue_ngap_id] = unc; ranid2uecontext[ran_ue_ngap_id] = unc;
} }
//------------------------------------------------------------------------------ /************************************************* internal analysis functions ***********************************/
// internal analysis functions bool amf_n2::verifyPlmn(vector<SupportedItem_t> list)
bool amf_n2::verifyPlmn(vector<SupportedItem_t> list) { {
for (int i = 0; i < amf_cfg.plmn_list.size(); i++) { for (int i = 0; i < amf_cfg.plmn_list.size(); i++)
for (int j = 0; j < list.size(); j++) { {
Logger::amf_n2().debug("TAC configured %d, TAC received %d", for (int j = 0; j < list.size(); j++)
amf_cfg.plmn_list[i].tac, list[j].tac); {
if (amf_cfg.plmn_list[i].tac != list[j].tac) { Logger::amf_n2().debug("tac configured(%d) -- tac received(%d)", amf_cfg.plmn_list[i].tac, list[j].tac);
if (amf_cfg.plmn_list[i].tac != list[j].tac)
{
continue; continue;
} }
for (int k = 0; k < list[j].b_plmn_list.size(); k++) { for (int k = 0; k < list[j].b_plmn_list.size(); k++)
if (!(list[j].b_plmn_list[k].mcc.compare(amf_cfg.plmn_list[i].mcc)) && {
!(list[j].b_plmn_list[k].mnc.compare(amf_cfg.plmn_list[i].mnc))) { if (!(list[j].b_plmn_list[k].mcc.compare(amf_cfg.plmn_list[i].mcc)) && !(list[j].b_plmn_list[k].mnc.compare(amf_cfg.plmn_list[i].mnc)))
{
return true; return true;
} }
} }
...@@ -948,26 +1159,3 @@ bool amf_n2::verifyPlmn(vector<SupportedItem_t> list) { ...@@ -948,26 +1159,3 @@ bool amf_n2::verifyPlmn(vector<SupportedItem_t> list) {
} }
return false; return false;
} }
//------------------------------------------------------------------------------
std::vector<SupportedItem_t>
amf_n2::get_common_plmn(std::vector<SupportedItem_t> list) {
std::vector<SupportedItem_t> plmn_list = {};
for (int i = 0; i < amf_cfg.plmn_list.size(); i++) {
for (int j = 0; j < list.size(); j++) {
Logger::amf_n2().debug("TAC configured %d, TAC received %d",
amf_cfg.plmn_list[i].tac, list[j].tac);
if (amf_cfg.plmn_list[i].tac != list[j].tac) {
continue;
}
for (int k = 0; k < list[j].b_plmn_list.size(); k++) {
if (!(list[j].b_plmn_list[k].mcc.compare(amf_cfg.plmn_list[i].mcc)) &&
!(list[j].b_plmn_list[k].mnc.compare(amf_cfg.plmn_list[i].mnc))) {
plmn_list.push_back(list[j]);
}
}
}
}
return plmn_list;
}
/*
* 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 amf_n2.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _AMF_N2_H_ #ifndef _AMF_N2_H_
#define _AMF_N2_H_ #define _AMF_N2_H_
#include "HandoverCommandMsg.hpp"
#include "HandoverRequest.hpp"
#include "amf.hpp"
#include "itti_msg_n2.hpp"
#include "ngap_app.hpp" #include "ngap_app.hpp"
#include "itti_msg_n2.hpp"
#include "ue_ngap_context.hpp" #include "ue_ngap_context.hpp"
namespace amf_application { #include "PduSessionResourceReleaseCommand.hpp"
#include "HandoverRequest.hpp"
class amf_n2 : public ngap::ngap_app { #include "HandoverCommandMsg.hpp"
public: #include "DownlinkRANStatusTransfer.hpp"
amf_n2(const std::string &address, const uint16_t port_num); namespace amf_application
{
class amf_n2 : public ngap::ngap_app
{
public:
amf_n2(const string &address, const uint16_t port_num);
~amf_n2(); ~amf_n2();
//void handle_receive(bstring payload, sctp_assoc_id_t assoc_id, sctp_stream_id_t stream, sctp_stream_id_t instreams, sctp_stream_id_t outstreams);
void handle_itti_message(itti_new_sctp_association &new_assoc); void handle_itti_message(itti_new_sctp_association &new_assoc);
void handle_itti_message(itti_ng_setup_request &ngsetupreq); void handle_itti_message(itti_ng_setup_request &ngsetupreq);
void handle_itti_message(itti_initial_ue_message &init_ue_msg); void handle_itti_message(itti_initial_ue_message &init_ue_msg);
...@@ -50,25 +26,22 @@ public: ...@@ -50,25 +26,22 @@ public:
void handle_itti_message(itti_pdu_session_resource_setup_request &itti_msg); void handle_itti_message(itti_pdu_session_resource_setup_request &itti_msg);
void handle_itti_message(itti_ue_context_release_request &itti_msg); void handle_itti_message(itti_ue_context_release_request &itti_msg);
void handle_itti_message(itti_ue_radio_capability_indication &itti_msg); void handle_itti_message(itti_ue_radio_capability_indication &itti_msg);
void handle_itti_message(itti_ue_context_release_command &itti_msg);
void handle_itti_message(itti_pdu_session_resource_release_command &itti_msg);
void handle_itti_message(itti_handover_required &itti_msg); void handle_itti_message(itti_handover_required &itti_msg);
void handle_itti_message(itti_handover_request_Ack &itti_msg); void handle_itti_message(itti_handover_request_Ack &itti_msg);
void handle_itti_message(itti_handover_notify &itti_msg); void handle_itti_message(itti_handover_notify &itti_msg);
bool verifyPlmn(std::vector<SupportedItem_t> list); void handle_itti_message(itti_uplinkranstatsutransfer &itti_msg);
std::vector<SupportedItem_t> bool verifyPlmn(vector<SupportedItem_t> list);
get_common_plmn(std::vector<SupportedItem_t> list);
private: public:
std::map<uint32_t, std::shared_ptr<ue_ngap_context>> std::map<uint32_t, std::shared_ptr<ue_ngap_context>> ranid2uecontext; // ran ue ngap id
ranid2uecontext; // ran ue ngap id
mutable std::shared_mutex m_ranid2uecontext; mutable std::shared_mutex m_ranid2uecontext;
bool is_ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const; bool is_ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const;
std::shared_ptr<ue_ngap_context> std::shared_ptr<ue_ngap_context> ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const;
ran_ue_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id) const; void set_ran_ue_ngap_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id, std::shared_ptr<ue_ngap_context> unc);
void };
set_ran_ue_ngap_id_2_ue_ngap_context(const uint32_t &ran_ue_ngap_id,
std::shared_ptr<ue_ngap_context> unc);
};
} // namespace amf_application } // namespace amf_application
......
/*
* 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 amf_statistics.cpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#include "amf_statistics.hpp" #include "amf_statistics.hpp"
#include "logger.hpp"
#include <iostream> #include <iostream>
using namespace std;
#include "logger.hpp"
//------------------------------------------------------------------------------ void statistics::display(){
void statistics::display() { cout<<endl;
Logger::amf_app().info("");
//Logger::amf_app().info("--------------------------------------------------"); //Logger::amf_app().info("--------------------------------------------------");
//Logger::amf_app().info("| connected gNBs | connected UEs | registered UEs |"); //Logger::amf_app().info("| connected gNBs | connected UEs | registred UEs |");
//Logger::amf_app().info("--------------------------------------------------"); //Logger::amf_app().info("--------------------------------------------------");
//Logger::amf_app().info("| %d | %d | %d |",gNB_connected,UE_connected,UE_registred); //Logger::amf_app().info("| %d | %d | %d |",gNB_connected,UE_connected,UE_registred);
//Logger::amf_app().info("--------------------------------------------------"); //Logger::amf_app().info("--------------------------------------------------");
Logger::amf_app().info("|----------------------------------------------------------------------------------------------------------------|"); Logger::amf_app().info("|--------------------------------------------------------------------------------------------------------------------|");
Logger::amf_app().info("|----------------------------------------------------gNBs' information-------------------------------------------|"); Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------");
Logger::amf_app().info("| Index | Status | Global ID | gNB Name | Tracking Area (PLMN, TAC) |"); Logger::amf_app().info("|----------------------------------------------------gNBs' information--------------------------------------------|");
if (gnbs.size() ==0 ) { for(int i=0; i<gnbs.size(); i++){
Logger::amf_app().info("| - | - | - | - | - |"); Logger::amf_app().info("[index %d][connected][GlobalID: 0x%x][gnb name: %s][Tracking Area: plmn(%s), tac(%d)]", i+1, gnbs[i].gnb_id, gnbs[i].gnb_name.c_str(), (gnbs[i].mcc+gnbs[i].mnc).c_str(), gnbs[i].tac);
} }
Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------"); cout<<endl;
//TODO: Show the list of common PLMNs Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------");
for (int i = 0; i < gnbs.size(); i++) {
Logger::amf_app().info("| %d | Connected | 0x%x | %s | %s, %d | ", i + 1, gnbs[i].gnb_id, gnbs[i].gnb_name.c_str(), (gnbs[i].mcc + gnbs[i].mnc).c_str(), gnbs[i].tac);
}
Logger::amf_app().info("|----------------------------------------------------------------------------------------------------------------|");
Logger::amf_app().info("");
Logger::amf_app().info("|----------------------------------------------------------------------------------------------------------------|");
Logger::amf_app().info("|----------------------------------------------------UEs' information--------------------------------------------|"); Logger::amf_app().info("|----------------------------------------------------UEs' information--------------------------------------------|");
Logger::amf_app().info("| Index | Connection state | Registration state | IMSI | GUTI | RAN UE NGAP ID | AMF UE ID |"); for(int i=0; i<ues.size();i++){
for (int i = 0; i < ues.size(); i++) { Logger::amf_app().info("[index %d][%s][%s][imsi %s][guti %s]", i+1, ues[i].connStatus.c_str(), ues[i].registerStatus.c_str(), ues[i].imsi.c_str(), ues[i].guti.c_str());
Logger::amf_app().info("| %d | %s | %s | %s | %s | %d | %d | ", i + 1, ues[i].connStatus.c_str(), ues[i].registerStatus.c_str(), ues[i].imsi.c_str(), ues[i].guti.c_str(), ues[i].ranid, ues[i].amfid); Logger::amf_app().info("Current ran_ue_ngap_id[%d]; Current amf_ue_ngap_id[%d]", ues[i].ranid, ues[i].amfid);
//Logger::amf_app().info("Current ran_ue_ngap_id[%d]; Current amf_ue_ngap_id[%d]", ues[i].ranid, ues[i].amfid); Logger::amf_app().info("Location[NrCgi][PLMN(%s), cellID(%d)]", (ues[i].mcc+ues[i].mnc).c_str(), ues[i].cellId); cout<<endl;
Logger::amf_app().info("Location [NrCgi][PLMN(%s), cellID(%d)]", (ues[i].mcc + ues[i].mnc).c_str(), ues[i].cellId);
Logger::amf_app().info("");
} }
Logger::amf_app().info("|----------------------------------------------------------------------------------------------------------------|"); Logger::amf_app().info("-----------------------------------------------------------------------------------------------------------------");
Logger::amf_app().info(""); Logger::amf_app().info("|--------------------------------------------------------------------------------------------------------------------|"); cout<<endl;
} }
//------------------------------------------------------------------------------ statistics::statistics(){
statistics::statistics() {
gNB_connected = 0; gNB_connected = 0;
UE_connected = 0; UE_connected = 0;
UE_registred = 0; UE_registred = 0;
} }
//------------------------------------------------------------------------------ statistics::~statistics(){}
statistics::~statistics() {
}
/*
* 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 amf_statistics.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _STATISTICS_H_ #ifndef _STATISTICS_H_
#define _STATISTICS_H_ #define _STATISTICS_H_
...@@ -35,45 +7,49 @@ ...@@ -35,45 +7,49 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include "amf.hpp" using namespace std;
#include "ngap_app.hpp"
typedef struct { typedef struct{
uint32_t gnb_id; uint32_t gnb_id;
//TODO: list of PLMNs string mcc;
std::vector<SupportedItem_t> plmn_list; string mnc;
std::string mcc; string gnb_name;
std::string mnc;
std::string gnb_name;
uint32_t tac; uint32_t tac;
//long nrCellId; //long nrCellId;
} gnb_infos; }gnb_infos;
typedef struct { typedef struct{
std::string connStatus; string connStatus;
std::string registerStatus; string registerStatus;
uint32_t ranid; uint32_t ranid;
long amfid; long amfid;
std::string imsi; string imsi;
std::string guti; string guti;
std::string mcc; string mcc;
std::string mnc; string mnc;
uint32_t cellId; uint32_t cellId;
} ue_infos; }ue_infos;
class statistics { class statistics{
public: public:
void display(); void display();
statistics(); statistics();
~statistics(); ~statistics();
public: public:
uint32_t gNB_connected; uint32_t gNB_connected;
uint32_t UE_connected; uint32_t UE_connected;
uint32_t UE_registred; uint32_t UE_registred;
//uint32_t system_pdu_sessions; //uint32_t system_pdu_sessions;
std::vector<gnb_infos> gnbs; vector<gnb_infos> gnbs;
std::vector<ue_infos> ues; vector<ue_infos> ues;
}; };
#endif #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 mysql_db.cpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#include "amf_n1.hpp" #include "amf_n1.hpp"
#include "logger.hpp" #include "logger.hpp"
#include "amf_config.hpp" #include "amf_config.hpp"
using namespace amf_application; using namespace amf_application;
using namespace config; using namespace config;
extern amf_config amf_cfg; extern amf_config amf_cfg;
//------------------------------------------------------------------------------ bool amf_n1::get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp){//openair-cn/tree/v0.5.0/src/oai_hss/db/db_connector.c
bool amf_n1::get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp) { //openair-cn/tree/v0.5.0/src/oai_hss/db/db_connector.c
MYSQL_RES *res; MYSQL_RES *res;
MYSQL_ROW row; MYSQL_ROW row;
std::string query; std::string query;
if (!db_desc->db_conn) { if(!db_desc->db_conn){
Logger::amf_n1().error("Cannot connect to MySQL DB"); Logger::amf_n1().error("Cannot connect to mysql db");
return false; return false;
} }
query = "SELECT `key`,`sqn`,`rand`,`OPc` FROM `users` WHERE `users`.`imsi`='" + imsi + "' "; query = "SELECT `key`,`sqn`,`rand`,`OPc` FROM `users` WHERE `users`.`imsi`='"+imsi+"' ";
pthread_mutex_lock(&db_desc->db_cs_mutex); Logger::amf_n1().debug("query (%s) in MYSQL", query.c_str());
if (mysql_query(db_desc->db_conn, query.c_str())) { pthread_mutex_lock (&db_desc->db_cs_mutex);
pthread_mutex_unlock(&db_desc->db_cs_mutex); if(mysql_query(db_desc->db_conn, query.c_str())){
Logger::amf_n1().error("Query execution failed: %s\n", mysql_error(db_desc->db_conn)); pthread_mutex_unlock (&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s\n", mysql_error (db_desc->db_conn));
return false; return false;
} }
res = mysql_store_result(db_desc->db_conn); res = mysql_store_result (db_desc->db_conn);
pthread_mutex_unlock(&db_desc->db_cs_mutex); pthread_mutex_unlock (&db_desc->db_cs_mutex);
if (!res) { if(!res){
Logger::amf_n1().error("Data fetched from MySQL is not present"); Logger::amf_n1().error("data fetched from mysql is not present");
return false; return false;
} }
if (row = mysql_fetch_row(res)) { if(row = mysql_fetch_row(res)){
if (row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL) { if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL){
Logger::amf_n1().error("row data failed"); Logger::amf_n1().error("row data failed");
return false; return false;
} }
memcpy(resp.key, row[0], KEY_LENGTH); memcpy (resp.key, row[0], KEY_LENGTH);
uint64_t sqn = 0; uint64_t sqn = 0;
sqn = atoll(row[1]); sqn = atoll(row[1]);
resp.sqn[0] = (sqn & (255UL << 40)) >> 40; resp.sqn[0] = (sqn & (255UL << 40)) >> 40;
...@@ -72,118 +43,115 @@ bool amf_n1::get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp) { / ...@@ -72,118 +43,115 @@ bool amf_n1::get_mysql_auth_info(std::string imsi, mysql_auth_info_t &resp) { /
resp.sqn[3] = (sqn & (255UL << 16)) >> 16; resp.sqn[3] = (sqn & (255UL << 16)) >> 16;
resp.sqn[4] = (sqn & (255UL << 8)) >> 8; resp.sqn[4] = (sqn & (255UL << 8)) >> 8;
resp.sqn[5] = (sqn & 0xff); resp.sqn[5] = (sqn & 0xff);
memcpy(resp.rand, row[2], RAND_LENGTH); memcpy (resp.rand, row[2], RAND_LENGTH);
memcpy(resp.opc, row[3], KEY_LENGTH); memcpy (resp.opc, row[3], KEY_LENGTH);
} }
mysql_free_result(res); mysql_free_result (res);
return true; return true;
} }
//------------------------------------------------------------------------------
bool amf_n1::connect_to_mysql() { bool amf_n1::connect_to_mysql(){
const int mysql_reconnect_val = 1; const int mysql_reconnect_val = 1;
db_desc = (database_t*) calloc(1, sizeof(database_t)); db_desc = (database_t*)calloc(1, sizeof(database_t));
if (!db_desc) { if(!db_desc){
Logger::amf_n1().error("An error occurs when allocating memory for DB_DESC"); Logger::amf_n1().error("An error occurs when calloc");
return false; return false;
} }
pthread_mutex_init(&db_desc->db_cs_mutex, NULL); pthread_mutex_init (&db_desc->db_cs_mutex, NULL);
db_desc->server = amf_cfg.auth_para.mysql_server; db_desc->server = amf_cfg.auth_para.mysql_server;
db_desc->user = amf_cfg.auth_para.mysql_user; db_desc->user = amf_cfg.auth_para.mysql_user;
db_desc->password = amf_cfg.auth_para.mysql_pass; db_desc->password = amf_cfg.auth_para.mysql_pass;
db_desc->database = amf_cfg.auth_para.mysql_db; db_desc->database = amf_cfg.auth_para.mysql_db;
db_desc->db_conn = mysql_init(NULL); db_desc->db_conn = mysql_init (NULL);
mysql_options(db_desc->db_conn, MYSQL_OPT_RECONNECT, &mysql_reconnect_val); mysql_options (db_desc->db_conn, MYSQL_OPT_RECONNECT, &mysql_reconnect_val);
if (!mysql_real_connect(db_desc->db_conn, db_desc->server.c_str(), db_desc->user.c_str(), db_desc->password.c_str(), db_desc->database.c_str(), 0, NULL, 0)) { if (!mysql_real_connect (db_desc->db_conn, db_desc->server.c_str(), db_desc->user.c_str(), db_desc->password.c_str(), db_desc->database.c_str(), 0, NULL, 0)) {
Logger::amf_n1().error("An error occurred while connecting to db: %s", mysql_error(db_desc->db_conn)); Logger::amf_n1().error("An error occured while connecting to db: %s", mysql_error (db_desc->db_conn));
mysql_thread_end(); mysql_thread_end();
return false; return false;
} }
mysql_set_server_option(db_desc->db_conn, MYSQL_OPTION_MULTI_STATEMENTS_ON); mysql_set_server_option (db_desc->db_conn, MYSQL_OPTION_MULTI_STATEMENTS_ON);
return true; return true;
} }
void amf_n1::mysql_push_rand_sqn(std::string imsi, uint8_t *rand_p, uint8_t *sqn){
//------------------------------------------------------------------------------
void amf_n1::mysql_push_rand_sqn(std::string imsi, uint8_t *rand_p, uint8_t *sqn) {
int status = 0; int status = 0;
MYSQL_RES *res; MYSQL_RES *res;
char query[1000]; char query[1000];
int query_length = 0; int query_length = 0;
uint64_t sqn_decimal = 0; uint64_t sqn_decimal = 0;
if (!db_desc->db_conn) { if(!db_desc->db_conn){
Logger::amf_n1().error("Cannot connect to MySQL DB"); Logger::amf_n1().error("Cannot connect to mysql");
return; return;
} }
if (!sqn || !rand_p) { if(!sqn || !rand_p){
Logger::amf_n1().error("Need sqn and rand"); Logger::amf_n1().error("need sqn and rand");
return; return;
} }
sqn_decimal = ((uint64_t) sqn[0] << 40) | ((uint64_t) sqn[1] << 32) | ((uint64_t) sqn[2] << 24) | (sqn[3] << 16) | (sqn[4] << 8) | sqn[5]; sqn_decimal = ((uint64_t) sqn[0] << 40) | ((uint64_t) sqn[1] << 32) | ((uint64_t) sqn[2] << 24) | (sqn[3] << 16) | (sqn[4] << 8) | sqn[5];
query_length = sprintf(query, "UPDATE `users` SET `rand`=UNHEX('"); query_length = sprintf (query, "UPDATE `users` SET `rand`=UNHEX('");
for (int i = 0; i < RAND_LENGTH; i++) { for (int i = 0; i < RAND_LENGTH; i++) {
query_length += sprintf(&query[query_length], "%02x", rand_p[i]); query_length += sprintf (&query[query_length], "%02x", rand_p[i]);
} }
query_length += sprintf (&query[query_length], "'),`sqn`=%" PRIu64, sqn_decimal); query_length += sprintf (&query[query_length], "'),`sqn`=%" PRIu64, sqn_decimal);
query_length += sprintf(&query[query_length], " WHERE `users`.`imsi`='%s'", imsi.c_str()); query_length += sprintf (&query[query_length], " WHERE `users`.`imsi`='%s'", imsi.c_str());
pthread_mutex_lock(&db_desc->db_cs_mutex); pthread_mutex_lock (&db_desc->db_cs_mutex);
if (mysql_query(db_desc->db_conn, query)) { if (mysql_query (db_desc->db_conn, query)) {
pthread_mutex_unlock(&db_desc->db_cs_mutex); pthread_mutex_unlock (&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s", mysql_error(db_desc->db_conn)); Logger::amf_n1().error("Query execution failed: %s", mysql_error (db_desc->db_conn));
return; return;
} }
do { do{
res = mysql_store_result(db_desc->db_conn); res = mysql_store_result (db_desc->db_conn);
if (res) { if(res){
mysql_free_result(res); mysql_free_result (res);
} else { }else{
if (mysql_field_count(db_desc->db_conn) == 0) { if(mysql_field_count (db_desc->db_conn) == 0) {
Logger::amf_n1().error("[MySQL] %lld rows affected", mysql_affected_rows(db_desc->db_conn)); Logger::amf_n1().error("%lld rows affected", mysql_affected_rows (db_desc->db_conn));
} else { /* some error occurred */ }else{ /* some error occurred */
Logger::amf_n1().error("Could not retrieve result set"); Logger::amf_n1().error("Could not retrieve result set");
break; break;
} }
} }
if ((status = mysql_next_result(db_desc->db_conn)) > 0) if ((status = mysql_next_result (db_desc->db_conn)) > 0)
Logger::amf_n1().error("Could not execute statement"); Logger::amf_n1().error("Could not execute statement");
} while (status == 0); }while(status == 0);
pthread_mutex_unlock(&db_desc->db_cs_mutex); pthread_mutex_unlock (&db_desc->db_cs_mutex);
return; return;
} }
//------------------------------------------------------------------------------ void amf_n1::mysql_increment_sqn(std::string imsi){
void amf_n1::mysql_increment_sqn(std::string imsi) {
int status; int status;
MYSQL_RES *res; MYSQL_RES *res;
char query[1000]; char query[1000];
if (db_desc->db_conn == NULL) { if (db_desc->db_conn == NULL) {
Logger::amf_n1().error("Cannot connect to MySQL DB"); Logger::amf_n1().error("Cannot connect to mysql");
return; return;
} }
sprintf(query, "UPDATE `users` SET `sqn` = `sqn` + 32 WHERE `users`.`imsi`='%s'", imsi.c_str()); sprintf (query, "UPDATE `users` SET `sqn` = `sqn` + 32 WHERE `users`.`imsi`='%s'", imsi.c_str());
pthread_mutex_lock(&db_desc->db_cs_mutex); pthread_mutex_lock(&db_desc->db_cs_mutex);
if (mysql_query(db_desc->db_conn, query)) { if (mysql_query (db_desc->db_conn, query)) {
pthread_mutex_unlock(&db_desc->db_cs_mutex); pthread_mutex_unlock (&db_desc->db_cs_mutex);
Logger::amf_n1().error("Query execution failed: %s", mysql_error(db_desc->db_conn)); Logger::amf_n1().error("Query execution failed: %s", mysql_error (db_desc->db_conn));
return; return;
} }
do { do{
res = mysql_store_result(db_desc->db_conn); res = mysql_store_result (db_desc->db_conn);
if (res) { if (res) {
mysql_free_result(res); mysql_free_result (res);
} else { } else {
if (mysql_field_count(db_desc->db_conn) == 0) { if (mysql_field_count (db_desc->db_conn) == 0) {
Logger::amf_n1().error("[MySQL] %lld rows affected", mysql_affected_rows(db_desc->db_conn)); Logger::amf_n1().error("%lld rows affected", mysql_affected_rows (db_desc->db_conn));
} else { } else {
Logger::amf_n1().error("Could not retrieve result set"); Logger::amf_n1().error("Could not retrieve result set");
break; break;
} }
} }
if ((status = mysql_next_result(db_desc->db_conn)) > 0) if ((status = mysql_next_result (db_desc->db_conn)) > 0)
Logger::amf_n1().error("Could not execute statement"); Logger::amf_n1().error("Could not execute statement");
} while (status == 0); }while(status == 0);
pthread_mutex_unlock(&db_desc->db_cs_mutex); pthread_mutex_unlock (&db_desc->db_cs_mutex);
return; return;
} }
/*
* 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 mysql_db.hpp
\brief
\author Keliang DU, BUPT
\date 2020
\email: contact@openairinterface.org
*/
#ifndef _MYSQL_DB_HANDLERS_H_ #ifndef _MYSQL_DB_HANDLERS_H_
#define _MYSQL_DB_HANDLERS_H_ #define _MYSQL_DB_HANDLERS_H_
...@@ -38,15 +10,15 @@ ...@@ -38,15 +10,15 @@
#define KEY_LENGTH (16) #define KEY_LENGTH (16)
#define SQN_LENGTH (6) #define SQN_LENGTH (6)
#define RAND_LENGTH (16) #define RAND_LENGTH (16)
typedef struct { typedef struct{
uint8_t key[KEY_LENGTH]; uint8_t key[KEY_LENGTH];
uint8_t sqn[SQN_LENGTH]; uint8_t sqn[SQN_LENGTH];
uint8_t opc[KEY_LENGTH]; uint8_t opc[KEY_LENGTH];
uint8_t rand[RAND_LENGTH]; uint8_t rand[RAND_LENGTH];
} mysql_auth_info_t; }mysql_auth_info_t;
typedef struct { typedef struct {
//mysql reference connector object /* The mysql reference connector object */
MYSQL *db_conn; MYSQL *db_conn;
std::string server; std::string server;
std::string user; std::string user;
......
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