Commit 4ba11030 authored by Tien-Thinh Nguyen's avatar Tien-Thinh Nguyen

Merge branch 'multiple_pdu_sessions' into 'develop'

Multiple pdu sessions

See merge request oai/cn5g/oai-cn5g-amf!17
parents dea91c4c 3c59c697
......@@ -21,6 +21,7 @@
# file build_helper.amf
# brief
# author Laurent Thomas, Lionel GAUTHIER
#
#######################################
################################
......@@ -31,6 +32,50 @@ THIS_SCRIPT_PATH=`dirname $SCRIPT`
source $THIS_SCRIPT_PATH/build_helper
source $THIS_SCRIPT_PATH/build_helper.fb_folly
#-------------------------------------------------------------------------------
#arg1 is force (0 or 1) (no interactive script)
#arg2 is debug (0 or 1) (install debug libraries)
install_cpprestsdk_from_git() {
if [ $1 -eq 0 ]; then
read -p "Do you want to install C++ REST SDK ? <y/N> " prompt
OPTION="-y"
else
prompt='y'
OPTION="-y"
fi
if [ $2 -eq 0 ]; then
debug=0
else
debug=1
fi
if [[ $prompt =~ [yY](es)* ]]
then
GIT_URL=https://github.com/Microsoft/cpprestsdk.git
echo "Install C++ REST SDK from $GIT_URL"
pushd $OPENAIRCN_DIR/build/ext
echo "Downloading C++ REST SDK"
if [[ $OPTION =~ -[yY](es)* ]]
then
$SUDO rm -rf cpprestsdk
fi
git clone $GIT_URL
cd cpprestsdk
git submodule update --init
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
mkdir _build && cd _build
$CMAKE -G Ninja .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTS=OFF -DBUILD_SAMPLES=OFF
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
$SUDO ninja install
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
$SUDO ldconfig -v
popd
fi
return 0
}
#-------------------------------------------------------------------------------
#arg1 is force (0 or 1) (no interactive script)
#arg2 is debug (0 or 1) (install debug libraries)
......@@ -53,6 +98,8 @@ install_fmt() {
git clone https://github.com/fmtlib/fmt.git
ret=$?;[[ $ret -ne 0 ]] && return $ret
cd fmt
# Looks like since Nov 11 commits, we cannot build
git checkout -f 1936dddc3c53c1c0db55a665cf419dc7a257ba62
$CMAKE -DFMT_TEST=FALSE .
ret=$?;[[ $ret -ne 0 ]] && return $ret
make -j `nproc`
......@@ -137,7 +184,11 @@ install_pistache_from_git() {
cd pistache && git checkout e18ed9baeb2145af6f9ea41246cf48054ffd9907
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
mkdir _build && cd _build
$CMAKE -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release ..
$CMAKE -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release \
-DPISTACHE_BUILD_EXAMPLES=false \
-DPISTACHE_BUILD_TESTS=false \
-DPISTACHE_BUILD_DOCS=false \
..
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
make
ret=$?;[[ $ret -ne 0 ]] && popd && return $ret
......@@ -296,7 +347,9 @@ check_install_amf_deps(){
nettle-dev \
libcurl4 \
net-tools \
pkg-config"
pkg-config \
ninja-build \
libasan2"
elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
PACKAGE_LIST="\
guile-devel \
......@@ -318,7 +371,9 @@ check_install_amf_deps(){
nettle-devel \
libcurl-devel \
python2 \
pkgconfig"
pkgconfig \
ninja-build \
libasan"
else
echo_fatal "$OS_DISTRO is not a supported distribution."
fi
......@@ -326,6 +381,9 @@ check_install_amf_deps(){
$SUDO $INSTALLER install $OPTION $PACKAGE_LIST
ret=$?;[[ $ret -ne 0 ]] && return $ret
install_cpprestsdk_from_git $1 $2
ret=$?;[[ $ret -ne 0 ]] && return $ret
# Use fmt lib included in spdlog
install_fmt $1
ret=$?;[[ $ret -ne 0 ]] && return $ret
......
......@@ -49,27 +49,21 @@ install_fb_folly_from_source(){
then
if [[ "$OS_BASEDISTRO" == "fedora" ]]; then
$SUDO $INSTALLER install $OPTION \
gcc-c++ \
$CMAKE \
boost-devel \
libevent-devel \
double-conversion-devel \
glog-devel \
gflags-devel \
snappy-devel \
make \
lz4-devel \
zlib-devel \
binutils-devel \
jemalloc-devel \
openssl-devel \
pkg-config
openssl-devel
ret=$?;[[ $ret -ne 0 ]] && return $ret
elif [[ $OS_DISTRO == "ubuntu" ]]; then
$SUDO $INSTALLER install $OPTION \
g++ \
cmake \
libboost-all-dev \
libevent-dev \
libdouble-conversion-dev \
libgoogle-glog-dev \
......@@ -78,13 +72,10 @@ install_fb_folly_from_source(){
liblz4-dev \
liblzma-dev \
libsnappy-dev \
make \
wget \
wget \
zlib1g-dev \
binutils-dev \
libjemalloc-dev \
libssl-dev \
pkg-config
libjemalloc-dev
ret=$?;[[ $ret -ne 0 ]] && return $ret
fi
......@@ -150,4 +141,3 @@ install_fb_folly_from_source(){
echo_success "End of folly installation"
return 0
}
......@@ -216,6 +216,16 @@ bool amf_app::find_pdu_session_context(
return true;
}
bool amf_app::get_pdu_sessions_context(
const string& supi,
std::vector<std::shared_ptr<pdu_session_context>>& sessions_ctx) {
if (!is_supi_2_ue_context(supi)) return false;
std::shared_ptr<ue_context> uc = {};
uc = supi_2_ue_context(supi);
if (!uc.get()->get_pdu_sessions_context(sessions_ctx)) return false;
return true;
}
//------------------------------------------------------------------------------
void amf_app::handle_itti_message(
itti_n1n2_message_transfer_request& itti_msg) {
......@@ -280,6 +290,17 @@ void amf_app::handle_itti_message(
set_ran_amf_id_2_ue_context(ue_context_key, uc);
}
// Update AMF UE NGAP ID
std::shared_ptr<ue_ngap_context> unc = {};
if (!amf_n2_inst->is_ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id)) {
Logger::amf_n1().error(
"Could not find UE NGAP Context with ran_ue_ngap_id (0x%x)",
itti_msg.ran_ue_ngap_id);
} else {
unc = amf_n2_inst->ran_ue_id_2_ue_ngap_context(itti_msg.ran_ue_ngap_id);
unc.get()->amf_ue_ngap_id = amf_ue_ngap_id;
}
if (uc.get() == nullptr) {
Logger::amf_app().error(
"Failed to create ue_context with ran_amf_id %s",
......
......@@ -92,6 +92,9 @@ class amf_app {
const string& supi, const std::uint8_t pdu_session_id,
std::shared_ptr<pdu_session_context>& psc);
bool get_pdu_sessions_context(
const string& supi,
std::vector<std::shared_ptr<pdu_session_context>>& sessions_ctx);
// SMF Client response handlers
void handle_post_sm_context_response_error_400();
// others
......
......@@ -60,6 +60,7 @@
#include "ConfirmationData.h"
#include "ConfirmationDataResponse.h"
#include <curl/curl.h>
#include <bitset>
extern "C" {
#include "bstrlib.h"
......@@ -121,8 +122,7 @@ amf_n1::amf_n1() {
Logger::amf_n1().error("Cannot create task TASK_AMF_N1");
throw std::runtime_error("Cannot create task TASK_AMF_N1");
}
Logger::amf_n1().startup("Started");
Logger::amf_n1().debug("Construct amf_n1 successfully");
Logger::amf_n1().startup("amf_n1 started");
}
//------------------------------------------------------------------------------
......@@ -302,7 +302,7 @@ void amf_n1::handle_itti_message(itti_uplink_nas_data_ind& nas_data_ind) {
"Received mac32 (0x%x) from the message", mac32_recv);
if (mac32 == mac32_recv) {
isMatched = true;
Logger::amf_n1().error("Integrity matched");
Logger::amf_n1().debug("Integrity matched");
// nc.get()->security_ctx->ul_count.seq_num ++;
}
if (!isMatched) {
......@@ -532,7 +532,14 @@ void amf_n1::identity_response_handle(
void amf_n1::service_request_handle(
bool isNasSig, std::shared_ptr<nas_context> nc, uint32_t ran_ue_ngap_id,
long amf_ue_ngap_id, bstring nas) {
if (!nc.get()) {
string ue_context_key = "app_ue_ranid_" + to_string(ran_ue_ngap_id) +
":amfid_" + to_string(amf_ue_ngap_id);
std::shared_ptr<ue_context> uc;
uc = amf_app_inst->ran_amf_id_2_ue_context(ue_context_key);
if (!nc.get() or (uc.get() == nullptr)) {
Logger::amf_n1().debug(
"Cannot find NAS/UE context, send Service Reject to UE");
// service reject
uint8_t nas[4];
nas[0] = EPD_5GS_MM_MSG;
......@@ -564,45 +571,92 @@ void amf_n1::service_request_handle(
std::unique_ptr<ServiceAccept> serApt = std::make_unique<ServiceAccept>();
serApt->setHeader(PLAIN_5GS_MSG);
string supi = "imsi-" + nc.get()->imsi;
uc.get()->supi = supi;
supi2amfId[supi] = amf_ue_ngap_id;
supi2ranId[supi] = ran_ue_ngap_id;
Logger::amf_n1().debug(
"amf_ue_ngap_id %d, ran_ue_ngap_id %d", amf_ue_ngap_id, ran_ue_ngap_id);
Logger::amf_n1().debug("Key for pdu session context: SUPI %s", supi.c_str());
std::shared_ptr<pdu_session_context> psc;
// get the status of PDU Session context
std::shared_ptr<pdu_session_context> old_psc = {};
if (amf_app_inst->is_supi_2_ue_context(supi)) {
std::shared_ptr<ue_context> old_uc = {};
old_uc = amf_app_inst->supi_2_ue_context(supi);
uc->copy_pdu_sessions(old_uc);
amf_app_inst->set_supi_2_ue_context(supi, uc);
}
/*
//TODO: get the pdu_session_context from AMF_APP based on both SUPI and PDU
Session ID string ue_context_key = "app_ue_ranid_" +
to_string(ran_ue_ngap_id) +
":amfid_" + to_string(amf_ue_ngap_id);
std::shared_ptr<ue_context> uc;
uc = amf_app_inst->ran_amf_id_2_ue_context(ue_context_key);
if (uc.get() !=nullptr){
if (!uc.get()->find_pdu_session_context(pdu_session_id,psc)) {
}
//Update AMF UE NGAP ID
std::shared_ptr<ue_ngap_context> unc = {};
if (!amf_n2_inst->is_ran_ue_id_2_ue_ngap_context(ran_ue_ngap_id)) {
Logger::amf_n1().error(
"Could not find UE NGAP Context with ran_ue_ngap_id (0x%x)",
ran_ue_ngap_id);
} else {
unc.get()->amf_ue_ngap_id = amf_ue_ngap_id;
}
//TO check: in which condition we should have PDU Session ID
*/
// associate SUPI with UC
amf_app_inst->set_supi_2_ue_context(supi, uc);
// Get PDU session status from Service Request
uint16_t pdu_session_status = (uint16_t) serReq->getPduSessionStatus();
if (pdu_session_status == 0) {
// Get PDU Session Status from NAS Message Container if available
bstring plain_msg;
if (serReq->getNasMessageContainer(plain_msg)) {
uint8_t* buf_nas = (uint8_t*) bdata(plain_msg);
uint8_t message_type = *(buf_nas + 2);
Logger::amf_n1().debug("NAS message type 0x%x", message_type);
switch (message_type) {
case REGISTRATION_REQUEST: {
Logger::nas_mm().debug(
"TODO: NAS Message Container contains a Registration Request");
} break;
case SERVICE_REQUEST: {
Logger::nas_mm().debug(
"NAS Message Container contains a Service Request, handling ...");
std::unique_ptr<ServiceRequest> serReqNas =
std::make_unique<ServiceRequest>();
serReqNas->decodefrombuffer(
nullptr, (uint8_t*) bdata(plain_msg), blength(plain_msg));
bdestroy(plain_msg);
if (serReqNas->getPduSessionStatus() > 0) {
pdu_session_status = (uint16_t) serReqNas->getPduSessionStatus();
}
} break;
if (amf_n11_inst->is_supi_to_pdu_ctx(supi)) {
psc = amf_n11_inst->supi_to_pdu_ctx(supi);
if (!psc) {
Logger::amf_n1().error("Cannot get pdu_session_context");
return;
default:
Logger::nas_mm().error(
"NAS Message Container, unknown NAS message 0x%x", message_type);
}
}
} else {
Logger::amf_n1().error(
"Cannot get pdu_session_context with SUPI %s", supi.c_str());
}
// TODO: is_supi_to_pdu_ctx should be removed
if (!amf_n11_inst->is_supi_to_pdu_ctx(supi) || !psc.get()->isn2sm_avaliable) {
Logger::amf_n1().error(
"Cannot get pdu session information with supi (%s)", supi.c_str());
if (amf_n11_inst->is_supi_to_pdu_ctx(supi)) {
psc.get()->isn2sm_avaliable = true;
std::vector<uint8_t> pdu_session_to_be_activated = {};
std::bitset<16> pdu_session_status_bits(pdu_session_status);
for (int i = 0; i < 15; i++) {
if (pdu_session_status_bits.test(i)) {
if (i <= 7)
pdu_session_to_be_activated.push_back(8 + i);
else if (i > 8)
pdu_session_to_be_activated.push_back(i - 8);
}
}
if (pdu_session_to_be_activated.size() > 0) {
for (auto i : pdu_session_to_be_activated)
Logger::amf_n1().debug("PDU session to be activated %d", i);
}
// No PDU Sessions To Be Activated
if (pdu_session_to_be_activated.size() == 0) {
Logger::amf_n1().debug("There is no PDU session to be activated");
serApt->setPDU_session_status(0x0000);
uint8_t buffer[BUFFER_SIZE_256];
int encoded_size = serApt->encode2buffer(buffer, BUFFER_SIZE_256);
......@@ -635,45 +689,61 @@ void amf_n1::service_request_handle(
i->get_msg_name());
}
return;
}
serApt->setPDU_session_status(0x2000);
serApt->setPDU_session_reactivation_result(0x0000);
uint8_t buffer[BUFFER_SIZE_256];
int encoded_size = serApt->encode2buffer(buffer, BUFFER_SIZE_256);
bstring protectedNas;
encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK,
buffer, encoded_size, protectedNas);
uint8_t* kamf = nc.get()->kamf[secu->vector_pointer];
uint8_t kgnb[32];
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8);
Logger::amf_n1().debug("uplink count(%d)", secu->ul_count.seq_num);
print_buffer("amf_n1", "kamf", kamf, 32);
Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb);
bstring kgnb_bs = blk2bstr(kgnb, 32);
itti_initial_context_setup_request* itti_msg =
new itti_initial_context_setup_request(TASK_AMF_N1, TASK_AMF_N2);
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->nas = protectedNas;
itti_msg->kgnb = kgnb_bs;
itti_msg->is_sr = true; // service request indicator
itti_msg->pdu_session_id = psc.get()->pdu_session_id;
itti_msg->is_pdu_exist = true;
if (psc.get()->isn2sm_avaliable) {
itti_msg->n2sm = psc.get()->n2sm;
itti_msg->isn2sm_avaliable = true;
} else {
itti_msg->isn2sm_avaliable = false;
Logger::amf_n1().error("Cannot get pdu session information");
}
std::shared_ptr<itti_initial_context_setup_request> i =
std::shared_ptr<itti_initial_context_setup_request>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n1().error(
"Could not send ITTI message %s to task TASK_AMF_N2",
i->get_msg_name());
// TODO: Contact SMF to activate UP for these sessions
// TODO: modify itti_initial_context_setup_request for supporting multiple
// PDU sessions
std::shared_ptr<pdu_session_context> psc = {};
serApt->setPDU_session_status(serReq->getPduSessionStatus());
serApt->setPDU_session_reactivation_result(0x0000);
uint8_t pdu_session_id = pdu_session_to_be_activated.at(0);
if (!amf_app_inst->find_pdu_session_context(supi, pdu_session_id, psc)) {
Logger::amf_n1().error(
"Cannot get pdu_session_context with SUPI (%s)", supi.c_str());
return;
}
uint8_t buffer[BUFFER_SIZE_256];
int encoded_size = serApt->encode2buffer(buffer, BUFFER_SIZE_256);
bstring protectedNas;
encode_nas_message_protected(
secu, false, INTEGRITY_PROTECTED_AND_CIPHERED, NAS_MESSAGE_DOWNLINK,
buffer, encoded_size, protectedNas);
uint8_t* kamf = nc.get()->kamf[secu->vector_pointer];
uint8_t kgnb[32];
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8);
Logger::amf_n1().debug("uplink count(%d)", secu->ul_count.seq_num);
print_buffer("amf_n1", "kamf", kamf, 32);
Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb);
bstring kgnb_bs = blk2bstr(kgnb, 32);
itti_initial_context_setup_request* itti_msg =
new itti_initial_context_setup_request(TASK_AMF_N1, TASK_AMF_N2);
itti_msg->ran_ue_ngap_id = ran_ue_ngap_id;
itti_msg->amf_ue_ngap_id = amf_ue_ngap_id;
itti_msg->nas = protectedNas;
itti_msg->kgnb = kgnb_bs;
itti_msg->is_sr = true; // service request indicator
itti_msg->pdu_session_id = pdu_session_id;
itti_msg->is_pdu_exist = true;
if (psc.get()->isn2sm_avaliable) {
itti_msg->n2sm = psc.get()->n2sm;
itti_msg->isn2sm_avaliable = true;
} else {
itti_msg->isn2sm_avaliable = false;
Logger::amf_n1().error("Cannot get PDU session information");
}
std::shared_ptr<itti_initial_context_setup_request> i =
std::shared_ptr<itti_initial_context_setup_request>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::amf_n1().error(
"Could not send ITTI message %s to task TASK_AMF_N2",
i->get_msg_name());
}
}
}
......@@ -795,7 +865,7 @@ void amf_n1::registration_request_handle(
nc.get()->serving_network = snn;
nc.get()->is_5g_guti_present = true;
nc.get()->to_be_register_by_new_suci = true;
nc.get()->ngKsi = 100;
nc.get()->ngKsi = 100 & 0xf;
// supi2amfId[("imsi-"+nc.get()->imsi)] = amf_ue_ngap_id;
// supi2ranId[("imsi-"+nc.get()->imsi)] = ran_ue_ngap_id;
}
......@@ -914,8 +984,11 @@ void amf_n1::registration_request_handle(
} break;
case MOBILITY_REGISTRATION_UPDATING: {
// TODO: check if the List Of PDU Sessions To Be Activated is available
// regReq->getPduSessionStatus()
Logger::amf_n1().debug("Network handling mobility registration ...");
run_mobility_registration_update_procedure(nc);
run_mobility_registration_update_procedure(
nc, regReq->getUplinkDataStatus(), regReq->getPduSessionStatus());
} break;
case PERIODIC_REGISTRATION_UPDATING: {
......@@ -1941,12 +2014,15 @@ void amf_n1::encode_nas_message_protected(
case INTEGRITY_PROTECTED_AND_CIPHERED: {
bstring input = blk2bstr(input_nas_buf, input_nas_len);
bstring ciphered;
// balloc(ciphered, blength(input));
nas_message_cipher_protected(nsc, NAS_MESSAGE_DOWNLINK, input, ciphered);
protected_nas_buf[0] = EPD_5GS_MM_MSG;
protected_nas_buf[1] = INTEGRITY_PROTECTED_AND_CIPHERED;
protected_nas_buf[6] = (uint8_t) nsc->dl_count.seq_num;
// if (bdata(ciphered) != nullptr)
memcpy(
&protected_nas_buf[7], (uint8_t*) bdata(ciphered), blength(ciphered));
uint32_t mac32;
if (!(nas_message_integrity_protected(
nsc, NAS_MESSAGE_DOWNLINK, protected_nas_buf + 6,
......@@ -2369,9 +2445,9 @@ void amf_n1::sha256(
//------------------------------------------------------------------------------
void amf_n1::run_mobility_registration_update_procedure(
std::shared_ptr<nas_context> nc) {
std::shared_ptr<nas_context> nc, uint16_t uplink_data_status,
uint16_t pdu_session_status) {
// encoding REGISTRATION ACCEPT
// RegistrationAccept* regAccept = new RegistrationAccept();
std::unique_ptr<RegistrationAccept> regAccept =
std::make_unique<RegistrationAccept>();
regAccept->setHeader(PLAIN_5GS_MSG);
......@@ -2404,8 +2480,6 @@ void amf_n1::run_mobility_registration_update_procedure(
// std::string guti = amf_cfg.guami.mcc + amf_cfg.guami.mnc +
// amf_cfg.guami.regionID + amf_cfg.guami.AmfSetID + amf_cfg.guami.AmfPointer
// + "0001";
std::string guti = "1234567890"; // TODO: need modify
Logger::amf_n1().debug("Allocated GUTI %s", guti.c_str());
regAccept->set_5GS_Network_Feature_Support(0x00, 0x00);
uint8_t buffer[1024] = {0};
......@@ -2426,27 +2500,39 @@ void amf_n1::run_mobility_registration_update_procedure(
string supi = "imsi-" + nc.get()->imsi;
Logger::amf_n1().debug("Key for pdu session context SUPI (%s)", supi.c_str());
std::shared_ptr<pdu_session_context> psc;
/*
//TODO: get the pdu_session_context from AMF_APP based on both SUPI and PDU
Session ID string ue_context_key = "app_ue_ranid_" +
to_string(ran_ue_ngap_id) +
":amfid_" + to_string(amf_ue_ngap_id);
std::shared_ptr<ue_context> uc;
uc = amf_app_inst->ran_amf_id_2_ue_context(ue_context_key);
if (uc.get() !=nullptr){
if (!uc.get()->find_pdu_session_context()) {
}
std::shared_ptr<pdu_session_context> psc = {};
string ue_context_key = "app_ue_ranid_" + to_string(nc->ran_ue_ngap_id) +
":amfid_" + to_string(nc->amf_ue_ngap_id);
std::shared_ptr<ue_context> uc = {};
uc = amf_app_inst->ran_amf_id_2_ue_context(ue_context_key);
if (uc.get() == nullptr) {
Logger::amf_n1().warn(
"Cannot find the UE context with key %s", ue_context_key.c_str());
return;
}
// get PDU session status
std::vector<uint8_t> pdu_session_to_be_activated = {};
std::bitset<16> pdu_session_status_bits((uint16_t) pdu_session_status);
for (int i = 0; i < 15; i++) {
if (pdu_session_status_bits.test(i)) {
if (i <= 7)
pdu_session_to_be_activated.push_back(8 + i);
else if (i > 8)
pdu_session_to_be_activated.push_back(i - 8);
}
//TO check: in which condition we should have PDU Session ID
*/
}
if (amf_n11_inst->is_supi_to_pdu_ctx(supi)) {
psc = amf_n11_inst->supi_to_pdu_ctx(supi);
} else {
Logger::amf_n1().error(
"Cannot get pdu_session_context with SUPI (%s)", supi.c_str());
if (pdu_session_to_be_activated.size() > 0) {
for (auto i : pdu_session_to_be_activated)
Logger::amf_n1().debug("PDU session to be activated %d", i);
}
if (pdu_session_to_be_activated.size() > 0) {
// get PDU session context for 1 PDU session for now
// TODO: multiple PDU sessions
uc->find_pdu_session_context(pdu_session_to_be_activated[0], psc);
}
uint8_t* kamf = nc.get()->kamf[secu->vector_pointer];
......@@ -2454,7 +2540,6 @@ void amf_n1::run_mobility_registration_update_procedure(
uint32_t ulcount = secu->ul_count.seq_num | (secu->ul_count.overflow << 8);
Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb);
print_buffer("amf_n1", "kamf", kamf, 32);
// Authentication_5gaka::derive_kgnb(ulcount, 0x01, kamf, kgnb);
bstring kgnb_bs = blk2bstr(kgnb, 32);
itti_initial_context_setup_request* itti_msg =
new itti_initial_context_setup_request(TASK_AMF_N1, TASK_AMF_N2);
......@@ -2463,8 +2548,12 @@ void amf_n1::run_mobility_registration_update_procedure(
itti_msg->kgnb = kgnb_bs;
itti_msg->nas = protectedNas;
itti_msg->is_sr = true; // service request indicator
itti_msg->pdu_session_id = psc.get()->pdu_session_id;
itti_msg->n2sm = psc.get()->n2sm;
if (psc.get() != nullptr) {
itti_msg->pdu_session_id = psc.get()->pdu_session_id;
itti_msg->n2sm = psc.get()->n2sm;
}
std::shared_ptr<itti_initial_context_setup_request> i =
std::shared_ptr<itti_initial_context_setup_request>(itti_msg);
int ret = itti_inst->send_msg(i);
......
......@@ -104,7 +104,8 @@ class amf_n1 {
void run_registration_procedure(std::shared_ptr<nas_context>& nc);
void run_initial_registration_procedure();
void run_mobility_registration_update_procedure(
std::shared_ptr<nas_context> nc);
std::shared_ptr<nas_context> nc, uint16_t uplink_data_status,
uint16_t pdu_session_status);
// authentication
bool auth_vectors_generator(std::shared_ptr<nas_context>& nc);
......
......@@ -64,6 +64,7 @@ extern amf_config amf_cfg;
extern amf_n11* amf_n11_inst;
extern amf_n1* amf_n1_inst;
extern amf_app* amf_app_inst;
extern statistics stacs;
extern void msg_str_2_msg_hex(std::string msg, bstring& b);
extern void convert_string_2_hex(std::string& input, std::string& output);
......@@ -139,11 +140,10 @@ void amf_n11_task(void*) {
//------------------------------------------------------------------------------
amf_n11::amf_n11() {
if (itti_inst->create_task(TASK_AMF_N11, amf_n11_task, nullptr)) {
Logger::amf_n11().error("Cannot create task TASK_AMF_N1");
throw std::runtime_error("Cannot create task TASK_AMF_N1");
Logger::amf_n11().error("Cannot create task TASK_AMF_N11");
throw std::runtime_error("Cannot create task TASK_AMF_N11");
}
Logger::amf_n11().startup("Started");
Logger::amf_n11().debug("Construct amf_n1 successfully");
Logger::amf_n11().startup("amf_n11 started");
}
//------------------------------------------------------------------------------
......@@ -165,13 +165,12 @@ void amf_n11::handle_itti_message(
if (uc.get() != nullptr) {
supi = uc->supi;
}
// std::string supi = pduid2supi.at(itti_msg.pdu_session_id);
Logger::amf_n11().debug(
"Send PDU Session Update SM Context Request to SMF (SUPI %s, PDU Session "
"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 (!uc.get()->find_pdu_session_context(itti_msg.pdu_session_id, psc)) {
Logger::amf_n11().error(
"Could not find psu_session_context with SUPI %s, Failed",
......@@ -216,6 +215,8 @@ void amf_n11::handle_itti_message(
(uint8_t*) bdata(itti_msg.n2sm), blength(itti_msg.n2sm), n2SmMsg);
curl_http_client(
remote_uri, json_part, "", n2SmMsg, supi, itti_msg.pdu_session_id);
stacs.display();
}
//------------------------------------------------------------------------------
......@@ -237,19 +238,17 @@ void amf_n11::handle_itti_message(itti_smf_services_consumer& smf) {
if (!uc.get()->find_pdu_session_context(smf.pdu_sess_id, psc)) {
psc = std::shared_ptr<pdu_session_context>(new pdu_session_context());
uc.get()->add_pdu_session_context(smf.pdu_sess_id, psc);
set_supi_to_pdu_ctx(supi, psc); // TODO: should be removed
Logger::amf_n11().debug("Create a PDU Session Context");
}
pduid2supi[smf.pdu_sess_id] = supi;
psc.get()->amf_ue_ngap_id = nc.get()->amf_ue_ngap_id;
psc.get()->ran_ue_ngap_id = nc.get()->ran_ue_ngap_id;
psc.get()->req_type = smf.req_type;
psc.get()->pdu_session_id = smf.pdu_sess_id;
psc.get()->snssai.sST = smf.snssai.sST;
psc.get()->snssai.sD = smf.snssai.sD;
psc.get()->plmn.mcc = smf.plmn.mcc;
psc.get()->plmn.mnc = smf.plmn.mnc;
psc.get()->amf_ue_ngap_id = nc.get()->amf_ue_ngap_id;
psc.get()->ran_ue_ngap_id = nc.get()->ran_ue_ngap_id;
psc.get()->req_type = smf.req_type;
psc.get()->pdu_session_id = smf.pdu_sess_id;
psc.get()->snssai.sST = smf.snssai.sST;
psc.get()->snssai.sD = smf.snssai.sD;
psc.get()->plmn.mcc = smf.plmn.mcc;
psc.get()->plmn.mnc = smf.plmn.mnc;
// parse binary dnn and store
std::string dnn = "default";
......@@ -295,6 +294,7 @@ void amf_n11::handle_itti_message(itti_smf_services_consumer& smf) {
Logger::amf_n11().debug(
"Decoded PTI for PDUSessionEstablishmentRequest(0x%x)", pti);
if (psc.get()->isn1sm_avaliable && psc.get()->isn2sm_avaliable) {
// TODO: should be removed
itti_n1n2_message_transfer_request* itti_msg =
new itti_n1n2_message_transfer_request(TASK_AMF_N11, TASK_AMF_APP);
itti_msg->supi = supi;
......@@ -422,11 +422,17 @@ void amf_n11::handle_pdu_session_initial_request(
//------------------------------------------------------------------------------
void amf_n11::handle_itti_message(
itti_nsmf_pdusession_release_sm_context& itti_msg) {
// TTN: Should be replace by new mechanism to support multiple PDU sessions
// Need PDU session ID
std::shared_ptr<pdu_session_context> psc = supi_to_pdu_ctx(itti_msg.supi);
string smf_addr;
std::string smf_api_version;
// TODO: Need PDU session ID
uint8_t pdu_session_id = 1; // Hardcoded
std::shared_ptr<pdu_session_context> psc = {};
if (!amf_app_inst->find_pdu_session_context(
itti_msg.supi, pdu_session_id, psc)) {
Logger::amf_n11().warn(
"PDU Session context for SUPI %s doesn't exit!", itti_msg.supi.c_str());
return;
}
string smf_addr, smf_api_version;
if (!psc.get()->smf_available) {
Logger::amf_n11().error("No SMF is available for this PDU session");
......@@ -449,26 +455,6 @@ void amf_n11::handle_itti_message(
remote_uri, json_part, "", "", itti_msg.supi, psc.get()->pdu_session_id);
}
// Context management functions
//------------------------------------------------------------------------------
bool amf_n11::is_supi_to_pdu_ctx(const std::string& supi) const {
std::shared_lock lock(m_supi2pdu);
return bool{supi2pdu.count(supi) > 0};
}
std::shared_ptr<pdu_session_context> amf_n11::supi_to_pdu_ctx(
const std::string& supi) const {
std::shared_lock lock(m_supi2pdu);
return supi2pdu.at(supi);
}
//------------------------------------------------------------------------------
void amf_n11::set_supi_to_pdu_ctx(
const string& supi, std::shared_ptr<pdu_session_context> psc) {
std::shared_lock lock(m_supi2pdu);
supi2pdu[supi] = psc;
}
// SMF selection
//------------------------------------------------------------------------------
bool amf_n11::smf_selection_from_configuration(
......
......@@ -57,16 +57,6 @@ class amf_n11 {
std::string supi, std::shared_ptr<pdu_session_context> psc,
std::string smf_addr, bstring sm_msg, std::string dnn);
std::map<std::string, std::shared_ptr<pdu_session_context>>
supi2pdu; // amf ue ngap id
mutable std::shared_mutex m_supi2pdu;
bool is_supi_to_pdu_ctx(const std::string& supi) const;
std::shared_ptr<pdu_session_context> supi_to_pdu_ctx(
const std::string& supi) const;
void set_supi_to_pdu_ctx(
const std::string& supi, std::shared_ptr<pdu_session_context> psc);
std::map<uint8_t, std::string> pduid2supi;
bool smf_selection_from_configuration(
std::string& smf_addr, std::string& smf_api_version);
void handle_post_sm_context_response_error_400();
......
......@@ -96,6 +96,16 @@ void amf_n2_task(void* args_p) {
itti_ng_setup_request* m = dynamic_cast<itti_ng_setup_request*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
} break;
case NG_RESET: {
Logger::amf_n2().info("Received NGReset message, handling");
itti_ng_reset* m = dynamic_cast<itti_ng_reset*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
} break;
case NG_SHUTDOWN: {
Logger::amf_n2().info("Received SCTP Shutdown Event, handling");
itti_ng_shutdown* m = dynamic_cast<itti_ng_shutdown*>(msg);
amf_n2_inst->handle_itti_message(ref(*m));
} break;
case INITIAL_UE_MSG: {
Logger::amf_n2().info("Received INITIAL_UE_MESSAGE message, handling");
itti_initial_ue_message* m =
......@@ -191,8 +201,7 @@ amf_n2::amf_n2(const std::string& address, const uint16_t port_num)
Logger::amf_n2().error("Cannot create task TASK_AMF_N2");
throw std::runtime_error("Cannot create task TASK_AMF_N2");
}
Logger::amf_n2().startup("Started");
Logger::amf_n2().debug("Construct amf_n2 successfully");
Logger::amf_n2().startup("amf_n2 started");
}
//------------------------------------------------------------------------------
......@@ -227,19 +236,21 @@ void amf_n2::handle_itti_message(itti_ng_setup_request& itti_msg) {
"Update gNB context with assoc id (%d)", itti_msg.assoc_id);
}
gnb_infos gnbItem;
gnb_infos gnbItem = {};
// Get IE Global RAN Node ID
uint32_t gnb_id;
uint32_t gnb_id = {};
std::string gnb_mcc;
std::string 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 Mandatory IE Global RAN Node ID");
return;
}
Logger::amf_n2().debug("IE GlobalGNBID: 0x%x", gnb_id);
Logger::amf_n2().debug("Global RAN Node ID: 0x%x", gnb_id);
gc->globalRanNodeId = gnb_id;
gnbItem.gnb_id = gnb_id;
gnbItem.mcc = gnb_mcc;
gnbItem.mnc = gnb_mnc;
std::string gnb_name;
if (!itti_msg.ngSetupReq->getRanNodeName(gnb_name)) {
......@@ -257,15 +268,16 @@ void amf_n2::handle_itti_message(itti_ng_setup_request& itti_msg) {
}
Logger::amf_n2().debug("IE DefaultPagingDRX: %d", defPagingDrx);
// Get supported TA List
vector<SupportedItem_t> s_ta_list;
if (!itti_msg.ngSetupReq->getSupportedTAList(
s_ta_list)) { // getSupportedTAList
if (!itti_msg.ngSetupReq->getSupportedTAList(s_ta_list)) {
return;
}
// TODO: should be removed, since we stored list of common PLMNs
gnbItem.mcc = s_ta_list[0].b_plmn_list[0].mcc;
gnbItem.mnc = s_ta_list[0].b_plmn_list[0].mnc;
gnbItem.tac = s_ta_list[0].tac;
// gnbItem.mcc = s_ta_list[0].b_plmn_list[0].mcc;
// gnbItem.mnc = s_ta_list[0].b_plmn_list[0].mnc;
// gnbItem.tac = s_ta_list[0].tac;
// association GlobalRANNodeID with assoc_id
// store RAN Node Name in gNB context, if present
// verify PLMN Identity and TAC with configuration and store supportedTAList
......@@ -340,7 +352,95 @@ void amf_n2::handle_itti_message(itti_ng_setup_request& itti_msg) {
"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.gnbs.push_back(gnbItem);
stacs.gnbs.insert(std::pair<uint32_t, gnb_infos>(gnbItem.gnb_id, gnbItem));
return;
}
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_ng_reset& 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;
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);
return;
}
gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
gc.get()->ng_state = NGAP_RESETING;
// TODO: (8.7.4.2.2, NG Reset initiated by the NG-RAN node @3GPP TS 38.413
// V16.0.0) the AMF shall release all allocated resources on NG related to the
// UE association(s) indicated explicitly or implicitly in the NG RESET
// message and remove the NGAP ID for the indicated UE associations.
ResetType reset_type = {};
itti_msg.ngReset->getResetType(reset_type);
if (reset_type.getResetType() == Ngap_ResetType_PR_nG_Interface) {
// Reset all
// release all the resources related to this interface
for (auto ue_context : ranid2uecontext) {
if (ue_context.second->gnb_assoc_id == itti_msg.assoc_id) {
uint32_t ran_ue_ngap_id = ue_context.second->ran_ue_ngap_id;
long amf_ue_ngap_id = ue_context.second->amf_ue_ngap_id;
// get NAS context
std::shared_ptr<nas_context> nc;
if (amf_n1_inst->is_amf_ue_id_2_nas_context(amf_ue_ngap_id))
nc = amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
else {
Logger::amf_n2().warn(
"No existed nas_context with amf_ue_ngap_id(0x%x)",
amf_ue_ngap_id);
}
stacs.update_5gmm_state(nc.get()->imsi, "5GMM-DEREGISTERED");
}
}
stacs.display();
} else if (
reset_type.getResetType() == Ngap_ResetType_PR_partOfNG_Interface) {
// TODO:
}
return;
}
//------------------------------------------------------------------------------
void amf_n2::handle_itti_message(itti_ng_shutdown& itti_msg) {
std::shared_ptr<gnb_context> gc;
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);
return;
}
gc = assoc_id_2_gnb_context(itti_msg.assoc_id);
gc.get()->ng_state = NGAP_SHUTDOWN;
// Release all the resources related to this interface
for (auto ue_context : ranid2uecontext) {
if (ue_context.second->gnb_assoc_id == itti_msg.assoc_id) {
uint32_t ran_ue_ngap_id = ue_context.second->ran_ue_ngap_id;
long amf_ue_ngap_id = ue_context.second->amf_ue_ngap_id;
// get NAS context
std::shared_ptr<nas_context> nc;
if (amf_n1_inst->is_amf_ue_id_2_nas_context(amf_ue_ngap_id))
nc = amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
else {
Logger::amf_n2().warn(
"No existed nas_context with amf_ue_ngap_id(0x%x)", amf_ue_ngap_id);
}
stacs.update_5gmm_state(nc.get()->imsi, "5GMM-DEREGISTERED");
}
}
// Delete gNB context
remove_gnb_context(itti_msg.assoc_id);
stacs.gnbs.erase(gc.get()->globalRanNodeId);
Logger::amf_n2().debug(
"Remove gNB with association id %d, globalRanNodeId 0x%x",
itti_msg.assoc_id, gc.get()->globalRanNodeId);
stacs.gNB_connected -= 1;
stacs.display();
return;
}
......@@ -495,12 +595,15 @@ void amf_n2::handle_itti_message(itti_ul_nas_transport& ul_nas_transport) {
"which's amf_ue_ngap_id (0x%x)",
amf_ue_ngap_id, unc.get()->amf_ue_ngap_id);
}
if (unc.get()->ng_ue_state != NGAP_UE_CONNECTED) {
Logger::amf_n2().error(
"Received NGAP UPLINK_NAS_TRANSPORT while UE in state != "
"NGAP_UE_CONNECTED");
// return;
}
/*
//TODO: check with a correct NGAP state
if (unc.get()->ng_ue_state != NGAP_UE_CONNECTED) {
Logger::amf_n2().error(
"Received NGAP UPLINK_NAS_TRANSPORT while UE in state != "
"NGAP_UE_CONNECTED");
// return;
}
*/
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;
......@@ -934,8 +1037,8 @@ void amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
plmn->getMcc(mcc);
plmn->getMnc(mnc);
printf(
"Handover required:Target ID GlobalRanNodeID PLmn=mcc%s mnc%s "
"gnbid=%x\n",
"Handover required: Target ID GlobalRanNodeID PLmn (mcc: %s, mnc: %s, "
"gnbid: %ld)\n",
mcc.c_str(), mnc.c_str(), gnbid->getValue());
TAI* tai = new TAI();
itti_msg.handvoerRequ->getTAI(tai);
......@@ -1010,25 +1113,36 @@ void amf_n2::handle_itti_message(itti_handover_required& itti_msg) {
// handoverrequest->setSourceToTarget_TransparentContainer(sourceTotarget);
string supi = "imsi-" + nc.get()->imsi;
// TODO: REMOVE supi_to_pdu_ctx (need PDU Session ID)/ list of PDU Session ID
std::shared_ptr<pdu_session_context> psc =
amf_n11_inst->supi_to_pdu_ctx(supi);
// Get all the active PDU sessions
std::vector<std::shared_ptr<pdu_session_context>> pdu_sessions = {};
if (!amf_app_inst->get_pdu_sessions_context(supi, pdu_sessions)) {
Logger::amf_n2().warn("Error when retrieving the active PDU Sessions!");
}
std::vector<PDUSessionResourceSetupRequestItem_t> list;
PDUSessionResourceSetupRequestItem_t item;
item.pduSessionId = psc.get()->pdu_session_id;
item.s_nssai.sst = "01";
item.s_nssai.sd = "";
item.pduSessionNAS_PDU = NULL;
bstring n2sm = psc.get()->n2sm;
if (blength(psc.get()->n2sm) != 0) {
item.pduSessionResourceSetupRequestTransfer.buf =
(uint8_t*) bdata(psc.get()->n2sm);
item.pduSessionResourceSetupRequestTransfer.size = blength(psc.get()->n2sm);
} else {
Logger::amf_n2().error("n2sm empty!");
if (pdu_sessions.size() > 0) {
for (auto pdu_session : pdu_sessions) {
if (pdu_session.get() != nullptr) {
item.pduSessionId = pdu_session.get()->pdu_session_id;
item.s_nssai.sst = pdu_session.get()->snssai.sST;
item.s_nssai.sd = pdu_session.get()->snssai.sD;
item.pduSessionNAS_PDU = NULL;
bstring n2sm = pdu_session.get()->n2sm;
if (blength(pdu_session.get()->n2sm) != 0) {
item.pduSessionResourceSetupRequestTransfer.buf =
(uint8_t*) bdata(pdu_session.get()->n2sm);
item.pduSessionResourceSetupRequestTransfer.size =
blength(pdu_session.get()->n2sm);
} else {
Logger::amf_n2().error("n2sm empty!");
}
list.push_back(item);
}
}
}
list.push_back(item);
handoverrequest->setPduSessionResourceSetupList(list);
handoverrequest->setAllowedNSSAI(Allowed_Nssai);
handoverrequest->setSourceToTarget_TransparentContainer(sourceTotarget);
......
......@@ -47,6 +47,8 @@ class amf_n2 : public ngap::ngap_app {
~amf_n2();
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_reset&);
void handle_itti_message(itti_ng_shutdown&);
void handle_itti_message(itti_initial_ue_message& init_ue_msg);
void handle_itti_message(itti_ul_nas_transport& ul_nas_transport);
void handle_itti_message(itti_dl_nas_transport& dl_nas_transport);
......
......@@ -33,13 +33,7 @@
//------------------------------------------------------------------------------
void statistics::display() {
Logger::amf_app().info("");
// Logger::amf_app().info("--------------------------------------------------");
// Logger::amf_app().info("| connected gNBs | connected UEs | registered UEs
// |");
// Logger::amf_app().info("--------------------------------------------------");
// Logger::amf_app().info("| %d | %d | %d
// |",gNB_connected,UE_connected,UE_registred);
// Logger::amf_app().info("--------------------------------------------------");
Logger::amf_app().info(
"|-----------------------------------------------------------------------"
"-----------------------------------------|");
......@@ -48,21 +42,26 @@ void statistics::display() {
"information-------------------------------------------|");
Logger::amf_app().info(
"| Index | Status | Global ID | gNB "
"Name | Tracking Area (PLMN, TAC) |");
"Name | PLMN |");
if (gnbs.size() == 0) {
Logger::amf_app().info(
"| - | - | - | "
"- | - |");
"- | - |");
}
// TODO: Show the list of common PLMNs
for (int i = 0; i < gnbs.size(); i++) {
int i = 1;
for (auto const& gnb : gnbs) {
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);
" | %s, %s | ",
i, gnb.second.gnb_id, gnb.second.gnb_name.c_str(),
gnb.second.mcc.c_str(), gnb.second.mnc.c_str());
// Comment out to show the supported TA list
// Logger::amf_app().info(
// "| Supported TA list: %s|", gnb.second.plmn_to_string().c_str());
i++;
}
Logger::amf_app().info(
"|-----------------------------------------------------------------------"
"-----------------------------------------|");
......@@ -78,13 +77,13 @@ void statistics::display() {
"| Index | 5GMM state | IMSI | GUTI | RAN "
"UE NGAP ID | AMF UE ID | PLMN |Cell ID|");
int i = 0;
i = 0;
for (auto const& ue : ue_infos) {
Logger::amf_app().info(
"|%7d|%22s|%18s|%15s|%16d|%11d|%9s|%7d|", i + 1,
"|%7d|%22s|%18s|%15s|%16d|%11d| %3s,%3s |%7d|", i + 1,
ue.second.registerStatus.c_str(), ue.second.imsi.c_str(),
ue.second.guti.c_str(), ue.second.ranid, ue.second.amfid,
(ue.second.mcc + ue.second.mnc).c_str(), ue.second.cellId);
ue.second.mcc.c_str(), ue.second.mnc.c_str(), ue.second.cellId);
i++;
}
Logger::amf_app().info(
......@@ -135,5 +134,6 @@ void statistics::update_5gmm_state(
}
}
void statistics::remove_gnb(const uint32_t gnb_id) {}
//------------------------------------------------------------------------------
statistics::~statistics() {}
......@@ -44,6 +44,22 @@ typedef struct {
std::string gnb_name;
uint32_t tac;
// long nrCellId;
std::string plmn_to_string() const {
std::string s = {};
for (auto supported_item : plmn_list) {
s.append("TAC " + std::to_string(supported_item.tac));
for (auto plmn_slice : supported_item.b_plmn_list) {
s.append("( MCC " + plmn_slice.mcc);
s.append(", MNC " + plmn_slice.mnc);
for (auto slice : plmn_slice.slice_list) {
s.append("(SST " + slice.sst + ", SD " + slice.sd + "),");
}
s.append(")");
}
s.append("),");
}
return s;
}
} gnb_infos;
typedef struct ue_info_s {
......@@ -65,13 +81,14 @@ class statistics {
~statistics();
void update_ue_info(const ue_info_t& ue_info);
void update_5gmm_state(const std::string& imsi, const std::string& state);
void remove_gnb(const uint32_t gnb_id);
public:
uint32_t gNB_connected;
uint32_t UE_connected;
uint32_t UE_registred;
// uint32_t system_pdu_sessions;
std::vector<gnb_infos> gnbs;
std::map<uint32_t, gnb_infos> gnbs;
std::map<std::string, ue_info_t> ue_infos;
};
......
......@@ -155,7 +155,7 @@ void amf_n1::mysql_push_rand_sqn(
mysql_free_result(res);
} else {
if (mysql_field_count(db_desc->db_conn) == 0) {
Logger::amf_n1().error(
Logger::amf_n1().debug(
"[MySQL] %lld rows affected",
mysql_affected_rows(db_desc->db_conn));
} else { /* some error occurred */
......@@ -197,7 +197,7 @@ void amf_n1::mysql_increment_sqn(std::string imsi) {
mysql_free_result(res);
} else {
if (mysql_field_count(db_desc->db_conn) == 0) {
Logger::amf_n1().error(
Logger::amf_n1().debug(
"[MySQL] %lld rows affected",
mysql_affected_rows(db_desc->db_conn));
} else {
......
......@@ -66,7 +66,7 @@ class nas_context {
std::string nas_status;
_5gmm_state_t _5gmm_state;
/************ parameters from Registration request *************/
// parameters from Registration request
uint8_t registration_type : 3;
bool follow_on_req_pending_ind;
uint8_t ngKsi : 4;
......@@ -78,7 +78,7 @@ class nas_context {
std::vector<nas::SNSSAI_t> requestedNssai;
std::string serving_network;
bstring auts;
/************ NAS EP(s) ****************/
// NAS EP(s)
bool is_specific_procedure_for_registration_running;
bool is_specific_procedure_for_deregistration_running;
bool is_specific_procedure_for_eCell_inactivity_running;
......@@ -87,7 +87,7 @@ class nas_context {
bool is_common_procedure_for_security_mode_control_running;
bool is_common_procedure_for_nas_transport_running;
/************ security related ***********/
// security related
#define MAX_5GS_AUTH_VECTORS 1
auc_vector_t _vector[MAX_5GS_AUTH_VECTORS]; /* 5GS authentication vector */
_5G_HE_AV_t _5g_he_av[MAX_5GS_AUTH_VECTORS]; // generated by UDM
......@@ -104,7 +104,7 @@ class nas_context {
// registration
// attempts(clause 5.5.1.2.7/5.5.1.3.7,
// 3gpp ts24.501)
/**************** parameters present? ****************/
// parameters present
bool is_imsi_present;
bool is_5g_guti_present;
bool is_auth_vectors_present;
......
......@@ -52,3 +52,16 @@ void ue_context::add_pdu_session_context(
std::unique_lock lock(m_pdu_session);
pdu_sessions[session_id] = context;
}
void ue_context::copy_pdu_sessions(std::shared_ptr<ue_context>& ue_ctx) {
pdu_sessions = ue_ctx->pdu_sessions;
}
bool ue_context::get_pdu_sessions_context(
std::vector<std::shared_ptr<pdu_session_context>>& sessions_ctx) {
std::shared_lock lock(m_pdu_session);
for (auto s : pdu_sessions) {
sessions_ctx.push_back(s.second);
}
return true;
}
......@@ -54,6 +54,9 @@ class ue_context {
void add_pdu_session_context(
const std::uint8_t& session_id,
const std::shared_ptr<pdu_session_context>& context);
void copy_pdu_sessions(std::shared_ptr<ue_context>& ue_ctx);
bool get_pdu_sessions_context(
std::vector<std::shared_ptr<pdu_session_context>>& sessions_ctx);
public:
uint32_t ran_ue_ngap_id; // 32bits
......
......@@ -61,6 +61,8 @@ typedef enum {
ASYNC_SHELL_CMD = ITTI_MSG_TYPE_FIRST,
NEW_SCTP_ASSOCIATION,
NG_SETUP_REQ,
NG_RESET,
NG_SHUTDOWN,
INITIAL_UE_MSG,
ITTI_UL_NAS_TRANSPORT,
ITTI_DL_NAS_TRANSPORT,
......
......@@ -24,6 +24,7 @@
#include "itti_msg.hpp"
#include "NGSetupRequest.hpp"
#include "NGReset.hpp"
#include "InitialUEMessage.hpp"
#include "UplinkNASTransport.hpp"
#include "UEContextReleaseRequest.hpp"
......@@ -66,6 +67,23 @@ class itti_ng_setup_request : public itti_msg_n2 {
NGSetupRequestMsg* ngSetupReq;
};
class itti_ng_reset : public itti_msg_n2 {
public:
itti_ng_reset(const task_id_t origin, const task_id_t destination)
: itti_msg_n2(NG_RESET, origin, destination) {}
itti_ng_reset(const itti_ng_reset& i) : itti_msg_n2(i) {}
public:
NGResetMsg* ngReset;
};
class itti_ng_shutdown : public itti_msg_n2 {
public:
itti_ng_shutdown(const task_id_t origin, const task_id_t destination)
: itti_msg_n2(NG_SHUTDOWN, origin, destination) {}
itti_ng_shutdown(const itti_ng_shutdown& i) : itti_msg_n2(i) {}
};
class itti_initial_ue_message : public itti_msg_n2 {
public:
itti_initial_ue_message(const task_id_t origin, const task_id_t destination)
......
......@@ -132,7 +132,8 @@ int _5GSMobilityIdentity::_5g_s_tmsi_encode2buffer(uint8_t* buf, int len) {
int _5GSMobilityIdentity::_5g_s_tmsi_decodefrombuffer(uint8_t* buf, int len) {
int decoded_size = 0;
_5g_s_tmsi = (_5G_S_TMSI_t*) calloc(1, sizeof(_5G_S_TMSI_t));
uint8_t octet = *(buf + decoded_size);
decoded_size++; // type of identity
uint8_t octet = *(buf + decoded_size);
decoded_size++;
_5g_s_tmsi->amf_set_id = 0x0000 | ((uint16_t) octet) << 2;
octet = *(buf + decoded_size);
......@@ -264,6 +265,7 @@ int _5GSMobilityIdentity::encode2buffer(uint8_t* buf, int len) {
return _5g_s_tmsi_encode2buffer(buf, len);
} break;
}
return 0;
}
//------------------------------------------------------------------------------
......@@ -522,6 +524,7 @@ int _5GSMobilityIdentity::decodefrombuffer(
return decoded_size;
} break;
}
return 0;
}
//------------------------------------------------------------------------------
......@@ -616,6 +619,7 @@ int _5GSMobilityIdentity::suci_decodefrombuffer(
default: {
} break;
}
return 0;
}
//------------------------------------------------------------------------------
......
......@@ -28,6 +28,7 @@
#include "PDU_Session_Status.hpp"
#include "logger.hpp"
#include "common_defs.h"
using namespace nas;
//------------------------------------------------------------------------------
......@@ -98,14 +99,12 @@ int PDU_Session_Status::decodefrombuffer(
if (is_option) {
decoded_size++;
}
_value = 0x0000;
length = *(buf + decoded_size);
decoded_size++;
_value |= *(buf + decoded_size);
decoded_size++;
_value |= (*(buf + decoded_size)) << 8;
decoded_size++;
Logger::nas_mm().debug("decoded PDU_Session_Status value(0x%4x)", _value);
DECODE_U16(buf + decoded_size, _value, decoded_size);
Logger::nas_mm().debug("decoded PDU_Session_Status value (0x%x)", _value);
Logger::nas_mm().debug("decoded PDU_Session_Status len(%d)", decoded_size);
return decoded_size;
}
......@@ -224,4 +224,5 @@ int DLNASTransport::decodefrombuffer(
}
Logger::nas_mm().debug(
"Decoded DLNASTransport message len (%d)", decoded_size);
return 1;
}
......@@ -199,7 +199,7 @@ int DeregistrationRequest::encode2buffer(uint8_t* buf, int len) {
//------------------------------------------------------------------------------
int DeregistrationRequest::decodefrombuffer(
NasMmPlainHeader* header, uint8_t* buf, int len) {
Logger::nas_mm().debug("****Decoding DeregistrationRequest message****");
Logger::nas_mm().debug("Decoding DeregistrationRequest message");
int decoded_size = 3;
plain_header = header;
ie_deregistrationtype = new _5GSDeregistrationType();
......@@ -213,5 +213,6 @@ int DeregistrationRequest::decodefrombuffer(
decoded_size += ie_5gs_mobility_id->decodefrombuffer(
buf + decoded_size, len - decoded_size, false);
Logger::nas_mm().debug(
"****Decoded DeregistrationRequest message (len %d)****", decoded_size);
"Decoded DeregistrationRequest message (len %d)", decoded_size);
return 1;
}
......@@ -196,4 +196,5 @@ int RegistrationReject::decodefrombuffer(
}
Logger::nas_mm().debug(
"decoded RegistrationReject message len(%d)", decoded_size);
return 1;
}
......@@ -202,7 +202,7 @@ int ServiceRequest::decodefrombuffer(
buf + decoded_size, len - decoded_size, false);
uint8_t octet = *(buf + decoded_size);
Logger::nas_mm().debug("First optional IE (0x%x)", octet);
while (!octet) {
while ((octet != 0x0)) {
switch (octet) {
case 0x40: {
Logger::nas_mm().debug("Decoding ie_uplink_data_status (IEI: 0x40)");
......@@ -241,7 +241,7 @@ int ServiceRequest::decodefrombuffer(
}
Logger::nas_mm().debug(
"Decoded ServiceRequest message len (%d)", decoded_size);
return 1;
return decoded_size;
}
//------------------------------------------------------------------------------
......@@ -251,7 +251,7 @@ uint8_t ServiceRequest::getngKSI() {
a = (ie_ngKSI->getTypeOfSecurityContext()) | ie_ngKSI->getasKeyIdentifier();
return a;
} else {
return -1;
return 0;
}
}
......@@ -269,7 +269,7 @@ uint16_t ServiceRequest::getPduSessionStatus() {
if (ie_PDU_session_status) {
return ie_PDU_session_status->getValue();
} else {
return -1;
return 0;
}
}
......@@ -278,7 +278,7 @@ uint16_t ServiceRequest::getAllowedPduSessionStatus() {
if (ie_allowed_PDU_session_status) {
return ie_allowed_PDU_session_status->getValue();
} else {
return -1;
return 0;
}
}
......@@ -297,7 +297,7 @@ uint8_t ServiceRequest::getServiceType() {
if (ie_service_type)
return ie_service_type->getValue();
else
return -1;
return 0;
}
//------------------------------------------------------------------------------
......
/*
* 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
\brief
\author
\date 2021
\email: contact@openairinterface.org
*/
#include "ResetType.hpp"
#include <iostream>
using namespace std;
namespace ngap {
//------------------------------------------------------------------------------
ResetType::ResetType() {
present = Ngap_ResetType_PR_NOTHING;
nG_Interface = 0;
partOfNG_Interface = nullptr;
ueAssociationLogicalNGConnectionItem = nullptr;
}
//------------------------------------------------------------------------------
ResetType::~ResetType() {}
//------------------------------------------------------------------------------
void ResetType::setResetType(long nG_Interface) {
this->present = Ngap_ResetType_PR_nG_Interface;
this->nG_Interface = nG_Interface;
}
void ResetType::setResetType(
std::vector<UEAssociationLogicalNGConnectionItem> list) {
this->present = Ngap_ResetType_PR_partOfNG_Interface;
UEAssociationLogicalNGConnectionItem* item =
new UEAssociationLogicalNGConnectionItem[list.size()]();
for (int i = 0; i < list.size(); i++) {
item[i].encode(list[i]);
}
}
//------------------------------------------------------------------------------
bool ResetType::encode(Ngap_ResetType_t* type) {
// TODO:
return true;
}
//------------------------------------------------------------------------------
bool ResetType::decode(Ngap_ResetType_t* type) {
present = type->present;
if (type->present == Ngap_ResetType_PR_nG_Interface) {
nG_Interface = (long) type->choice.nG_Interface;
return true;
} else if (type->present == Ngap_ResetType_PR_partOfNG_Interface) {
int num_item = type->choice.partOfNG_Interface->list.count;
partOfNG_Interface = new Ngap_UE_associatedLogicalNG_connectionList();
UEAssociationLogicalNGConnectionItem* item =
new UEAssociationLogicalNGConnectionItem[num_item]();
for (int i = 0; i < num_item; i++) {
if (!item[i].decode(type->choice.partOfNG_Interface->list.array[i]))
return false;
}
} else {
return false;
}
}
//------------------------------------------------------------------------------
void ResetType::getResetType(long& resetType) {
// TODO
}
uint8_t ResetType::getResetType() {
return present;
}
//------------------------------------------------------------------------------
void ResetType::getResetType(
struct Ngap_UE_associatedLogicalNG_connectionList*& list) {
// TODO:
}
//------------------------------------------------------------------------------
void ResetType::setUE_associatedLogicalNG_connectionList(
const std::vector<UEAssociationLogicalNGConnectionItem> list) {
// TODO:
}
} // namespace ngap
/*
* 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
\brief
\author
\date 2021
\email: contact@openairinterface.org
*/
#ifndef _RESET_TYPE_H_
#define _RESET_TYPE_H_
#include "UEAssociationLogicalNGConnectionItem.hpp"
extern "C" {
#include "Ngap_ResetType.h"
}
#include <vector>
namespace ngap {
class ResetType {
public:
ResetType();
virtual ~ResetType();
void setResetType(long);
void setResetType(std::vector<UEAssociationLogicalNGConnectionItem> list);
bool encode(Ngap_ResetType_t* type);
bool decode(Ngap_ResetType_t* type);
void getResetType(long&);
uint8_t getResetType();
void getResetType(struct Ngap_UE_associatedLogicalNG_connectionList*&);
void setUE_associatedLogicalNG_connectionList(
const std::vector<UEAssociationLogicalNGConnectionItem> list);
private:
Ngap_ResetType_PR present;
long nG_Interface;
struct Ngap_UE_associatedLogicalNG_connectionList* partOfNG_Interface;
UEAssociationLogicalNGConnectionItem* ueAssociationLogicalNGConnectionItem;
// struct Ngap_ProtocolIE_SingleContainer *choice_Extensions;
};
} // namespace ngap
#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
\brief
\author
\date 2021
\email: contact@openairinterface.org
*/
#include "UEAssociationLogicalNGConnectionItem.hpp"
extern "C" {
#include "dynamic_memory_check.h"
}
#include <iostream>
using namespace std;
namespace ngap {
UEAssociationLogicalNGConnectionItem::UEAssociationLogicalNGConnectionItem() {
amfUeNgapId = nullptr;
ranUeNgapId = nullptr;
}
//------------------------------------------------------------------------------
void UEAssociationLogicalNGConnectionItem::setAmfUeNgapId(unsigned long id) {
if (!amfUeNgapId) amfUeNgapId = new AMF_UE_NGAP_ID();
amfUeNgapId->setAMF_UE_NGAP_ID(id);
Ngap_DownlinkNASTransport_IEs_t* ie =
(Ngap_DownlinkNASTransport_IEs_t*) calloc(
1, sizeof(Ngap_DownlinkNASTransport_IEs_t));
ie->id = Ngap_ProtocolIE_ID_id_AMF_UE_NGAP_ID;
ie->criticality = Ngap_Criticality_reject;
ie->value.present = Ngap_DownlinkNASTransport_IEs__value_PR_AMF_UE_NGAP_ID;
int ret = amfUeNgapId->encode2AMF_UE_NGAP_ID(ie->value.choice.AMF_UE_NGAP_ID);
if (!ret) {
cout << "encode AMF_UE_NGAP_ID IE error" << endl;
free_wrapper((void**) &ie);
return;
}
}
//------------------------------------------------------------------------------
void UEAssociationLogicalNGConnectionItem::setRanUeNgapId(
uint32_t ran_ue_ngap_id) {
if (!ranUeNgapId) ranUeNgapId = new RAN_UE_NGAP_ID();
ranUeNgapId->setRanUeNgapId(ran_ue_ngap_id);
Ngap_DownlinkNASTransport_IEs_t* ie =
(Ngap_DownlinkNASTransport_IEs_t*) calloc(
1, sizeof(Ngap_DownlinkNASTransport_IEs_t));
ie->id = Ngap_ProtocolIE_ID_id_RAN_UE_NGAP_ID;
ie->criticality = Ngap_Criticality_reject;
ie->value.present = Ngap_DownlinkNASTransport_IEs__value_PR_RAN_UE_NGAP_ID;
int ret = ranUeNgapId->encode2RAN_UE_NGAP_ID(ie->value.choice.RAN_UE_NGAP_ID);
if (!ret) {
cout << "Encode RAN_UE_NGAP_ID IE error" << endl;
free_wrapper((void**) &ie);
return;
}
}
//------------------------------------------------------------------------------
bool UEAssociationLogicalNGConnectionItem::encode(
Ngap_UE_associatedLogicalNG_connectionItem_t& item) {
item.aMF_UE_NGAP_ID = new Ngap_AMF_UE_NGAP_ID_t();
amfUeNgapId->encode2AMF_UE_NGAP_ID(*item.aMF_UE_NGAP_ID);
item.rAN_UE_NGAP_ID = new Ngap_RAN_UE_NGAP_ID_t();
ranUeNgapId->encode2RAN_UE_NGAP_ID(*item.rAN_UE_NGAP_ID);
}
//------------------------------------------------------------------------------
bool UEAssociationLogicalNGConnectionItem::encode(
UEAssociationLogicalNGConnectionItem& item) {
item.amfUeNgapId = new AMF_UE_NGAP_ID();
item.amfUeNgapId = amfUeNgapId;
item.ranUeNgapId = new RAN_UE_NGAP_ID();
item.ranUeNgapId = ranUeNgapId;
}
//------------------------------------------------------------------------------
bool UEAssociationLogicalNGConnectionItem::decode(
Ngap_UE_associatedLogicalNG_connectionItem_t* item) {
amfUeNgapId = new AMF_UE_NGAP_ID();
if (!amfUeNgapId->decodefromAMF_UE_NGAP_ID(*item->aMF_UE_NGAP_ID)) {
cout << "Decoded NGAP AMF_UE_NGAP_ID IE error" << endl;
return false;
}
ranUeNgapId = new RAN_UE_NGAP_ID();
if (!ranUeNgapId->decodefromRAN_UE_NGAP_ID(*item->rAN_UE_NGAP_ID)) {
cout << "Decoded NGAP RAN_UE_NGAP_ID IE error" << endl;
return false;
}
return true;
}
} // namespace ngap
/*
* 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
\brief
\author
\date 2021
\email: contact@openairinterface.org
*/
#ifndef _UE_ASSOCIATION_LOGICAL_NG_CONNECTION_ITEM_H_
#define _UE_ASSOCIATION_LOGICAL_NG_CONNECTION_ITEM_H_
#include "AMF-UE-NGAP-ID.hpp"
#include "RAN-UE-NGAP-ID.hpp"
extern "C" {
#include "Ngap_ProtocolIE-Field.h"
#include "Ngap_UE-associatedLogicalNG-connectionItem.h"
}
namespace ngap {
class UEAssociationLogicalNGConnectionItem {
public:
UEAssociationLogicalNGConnectionItem();
virtual ~UEAssociationLogicalNGConnectionItem(){};
void setAmfUeNgapId(unsigned long id);
void setRanUeNgapId(uint32_t id);
bool encode(Ngap_UE_associatedLogicalNG_connectionItem_t& item);
bool encode(UEAssociationLogicalNGConnectionItem& item);
bool decode(Ngap_UE_associatedLogicalNG_connectionItem_t* item);
private:
AMF_UE_NGAP_ID* amfUeNgapId;
RAN_UE_NGAP_ID* ranUeNgapId;
};
} // namespace ngap
#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
\brief
\author
\date 2021
\email: contact@openairinterface.org
*/
#include "NGReset.hpp"
extern "C" {
#include "constr_TYPE.h"
#include "Ngap_NGAP-PDU.h"
#include "asn_codecs.h"
#include "per_encoder.h"
#include "per_decoder.h"
#include "constraints.h"
#include "dynamic_memory_check.h"
}
#include <iostream>
#include <vector>
using namespace std;
namespace ngap {
//------------------------------------------------------------------------------
NGResetMsg::NGResetMsg() {
ngResetPdu = nullptr;
ngResetIEs = nullptr;
cause = nullptr;
resetType = nullptr;
}
//------------------------------------------------------------------------------
NGResetMsg::~NGResetMsg() {}
//------------------------------------------------------------------------------
void NGResetMsg::setMessageType() {
if (!ngResetPdu)
ngResetPdu = (Ngap_NGAP_PDU_t*) calloc(1, sizeof(Ngap_NGAP_PDU_t));
MessageType NgResetMessageTypeIE;
NgResetMessageTypeIE.setProcedureCode(Ngap_ProcedureCode_id_NGReset);
NgResetMessageTypeIE.setTypeOfMessage(Ngap_NGAP_PDU_PR_initiatingMessage);
NgResetMessageTypeIE.setValuePresent(
Ngap_InitiatingMessage__value_PR_NGReset);
if (NgResetMessageTypeIE.getProcedureCode() ==
Ngap_ProcedureCode_id_NGReset &&
NgResetMessageTypeIE.getTypeOfMessage() ==
Ngap_NGAP_PDU_PR_initiatingMessage) {
NgResetMessageTypeIE.encode2pdu(ngResetPdu);
ngResetIEs = &(ngResetPdu->choice.initiatingMessage->value.choice.NGReset);
} else {
cout << "[Warning] This information doesn't refer to NGReset "
"Message!!!"
<< endl;
}
}
//------------------------------------------------------------------------------
void NGResetMsg::setCause(Ngap_Cause_t cause) {
// this->cause = cause;
}
//------------------------------------------------------------------------------
void NGResetMsg::setResetType(Ngap_ResetType_t resetType) {
// is->resetType = resetType;
}
void NGResetMsg::getCause(Ngap_Cause_t& cause) {
// cause = this->cause;
}
void NGResetMsg::getResetType(Ngap_ResetType_t& resetType) {
// resetType = this->resetType;
}
bool NGResetMsg::getResetType(ResetType& resetType) {
if (!this->resetType) return false;
if (this->resetType->getResetType() == Ngap_ResetType_PR_nG_Interface) {
long ng_interface = 0;
this->resetType->getResetType(ng_interface);
resetType.setResetType(ng_interface);
} else if (
this->resetType->getResetType() == Ngap_ResetType_PR_partOfNG_Interface) {
// TODO
}
}
//------------------------------------------------------------------------------
int NGResetMsg::encode2buffer(uint8_t* buf, int buf_size) {
asn_fprint(stderr, &asn_DEF_Ngap_NGAP_PDU, ngResetPdu);
asn_enc_rval_t er = aper_encode_to_buffer(
&asn_DEF_Ngap_NGAP_PDU, NULL, ngResetPdu, buf, buf_size);
printf("er.encoded(%ld)\n", er.encoded);
return er.encoded;
}
//------------------------------------------------------------------------------
bool NGResetMsg::decodefrompdu(Ngap_NGAP_PDU_t* ngap_msg_pdu) {
ngResetPdu = ngap_msg_pdu;
if (ngResetPdu->present == Ngap_NGAP_PDU_PR_initiatingMessage) {
if (ngResetPdu->choice.initiatingMessage &&
ngResetPdu->choice.initiatingMessage->procedureCode ==
Ngap_ProcedureCode_id_NGReset &&
ngResetPdu->choice.initiatingMessage->criticality ==
Ngap_Criticality_reject &&
ngResetPdu->choice.initiatingMessage->value.present ==
Ngap_InitiatingMessage__value_PR_NGReset) {
ngResetIEs = &ngResetPdu->choice.initiatingMessage->value.choice.NGReset;
for (int i = 0; i < ngResetIEs->protocolIEs.list.count; i++) {
switch (ngResetIEs->protocolIEs.list.array[i]->id) {
case Ngap_ProtocolIE_ID_id_Cause: {
if (ngResetIEs->protocolIEs.list.array[i]->criticality ==
Ngap_Criticality_ignore &&
ngResetIEs->protocolIEs.list.array[i]->value.present ==
Ngap_NGResetIEs__value_PR_Cause) {
cause = new Cause();
if (!cause->decodefromCause(
&ngResetIEs->protocolIEs.list.array[i]
->value.choice.Cause)) {
cout << "Decoded NGAP Cause IE error" << endl;
return false;
}
} else {
cout << "Decoded NGAP Cause IE error" << endl;
return false;
}
} break;
case Ngap_ProtocolIE_ID_id_ResetType: {
if (ngResetIEs->protocolIEs.list.array[i]->criticality ==
Ngap_Criticality_reject &&
ngResetIEs->protocolIEs.list.array[i]->value.present ==
Ngap_NGResetIEs__value_PR_ResetType) {
resetType = new ResetType();
if (!resetType->decode(&ngResetIEs->protocolIEs.list.array[i]
->value.choice.ResetType)) {
cout << "Decoded NGAP ResetType IE error" << endl;
return false;
}
} else {
cout << "Decoded NGAP ResetType IE error" << endl;
return false;
}
} break;
default: {
cout << "Decoded NGAP message PDU error" << endl;
return false;
}
}
}
} else {
cout << "Check NGReset message error!!!";
return false;
}
} else {
cout << "Check NGReset message error!!!";
return false;
}
return true;
}
} // namespace ngap
/*
* 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
\brief
\author
\date 2021
\email: contact@openairinterface.org
*/
#ifndef _NG_RESET_H_
#define _NG_RESET_H_
#include "NgapIEsStruct.hpp"
#include "MessageType.hpp"
#include "Cause.hpp"
#include "ResetType.hpp"
extern "C" {
#include "Ngap_NGAP-PDU.h"
#include "Ngap_ProtocolIE-Field.h"
#include "Ngap_NGSetupRequest.h"
}
namespace ngap {
class NGResetMsg {
public:
NGResetMsg();
virtual ~NGResetMsg();
void setMessageType(); // Initialize the PDU and populate the MessageType;
void setCause(Ngap_Cause_t);
void setResetType(Ngap_ResetType_t);
int encode2buffer(uint8_t* buf, int buf_size);
bool decodefrompdu(Ngap_NGAP_PDU_t* ngap_msg_pdu);
void getCause(Ngap_Cause_t&);
void getResetType(Ngap_ResetType_t&);
bool getResetType(ResetType&);
private:
Ngap_NGAP_PDU_t* ngResetPdu;
Ngap_NGReset_t* ngResetIEs;
Cause* cause;
ResetType* resetType;
};
} // namespace ngap
#endif
......@@ -111,7 +111,7 @@ void PduSessionResourceReleaseResponseMsg::setAmfUeNgapId(unsigned long id) {
ret = ASN_SEQUENCE_ADD(
&pduSessionResourceReleaseResponseIEs->protocolIEs.list, ie);
if (ret != 0) Logger::nas_mm().warn("Encode AMF_UE_NGAP_ID IE error");
//free_wrapper((void**) &ie);
// free_wrapper((void**) &ie);
}
//------------------------------------------------------------------------------
......@@ -138,7 +138,7 @@ void PduSessionResourceReleaseResponseMsg::setRanUeNgapId(
ret = ASN_SEQUENCE_ADD(
&pduSessionResourceReleaseResponseIEs->protocolIEs.list, ie);
if (ret != 0) Logger::nas_mm().warn("Encode RAN_UE_NGAP_ID IE error");
//free_wrapper((void**) &ie);
// free_wrapper((void**) &ie);
}
//------------------------------------------------------------------------------
......@@ -185,7 +185,7 @@ void PduSessionResourceReleaseResponseMsg::setPduSessionResourceReleasedList(
if (ret != 0)
Logger::nas_mm().warn(
"Encode PDUSessionResourceReleasedListRelRes IE error");
//free_wrapper((void**) &ie);
// free_wrapper((void**) &ie);
}
//------------------------------------------------------------------------------
......@@ -231,7 +231,7 @@ void PduSessionResourceReleaseResponseMsg::setUserLocationInfoNR(
&pduSessionResourceReleaseResponseIEs->protocolIEs.list, ie);
if (ret != 0)
Logger::nas_mm().warn("Encode UserLocationInformation IE error");
//free_wrapper((void**) &ie);
// free_wrapper((void**) &ie);
}
//------------------------------------------------------------------------------
......@@ -298,7 +298,7 @@ bool PduSessionResourceReleaseResponseMsg::decodefrompdu(
pduSessionResourceReleaseResponseIEs->protocolIEs.list.array[i]->id) {
case Ngap_ProtocolIE_ID_id_AMF_UE_NGAP_ID: {
if (pduSessionResourceReleaseResponseIEs->protocolIEs.list.array[i]
->criticality == Ngap_Criticality_reject &&
->criticality == Ngap_Criticality_ignore &&
pduSessionResourceReleaseResponseIEs->protocolIEs.list.array[i]
->value.present ==
Ngap_PDUSessionResourceReleaseResponseIEs__value_PR_AMF_UE_NGAP_ID) {
......@@ -318,7 +318,7 @@ bool PduSessionResourceReleaseResponseMsg::decodefrompdu(
case Ngap_ProtocolIE_ID_id_RAN_UE_NGAP_ID: {
if (pduSessionResourceReleaseResponseIEs->protocolIEs.list.array[i]
->criticality == Ngap_Criticality_reject &&
->criticality == Ngap_Criticality_ignore &&
pduSessionResourceReleaseResponseIEs->protocolIEs.list.array[i]
->value.present ==
Ngap_PDUSessionResourceReleaseResponseIEs__value_PR_RAN_UE_NGAP_ID) {
......@@ -338,7 +338,7 @@ bool PduSessionResourceReleaseResponseMsg::decodefrompdu(
case Ngap_ProtocolIE_ID_id_PDUSessionResourceReleasedListRelRes: {
if (pduSessionResourceReleaseResponseIEs->protocolIEs.list.array[i]
->criticality == Ngap_Criticality_reject &&
->criticality == Ngap_Criticality_ignore &&
pduSessionResourceReleaseResponseIEs->protocolIEs.list.array[i]
->value.present ==
Ngap_PDUSessionResourceReleaseResponseIEs__value_PR_PDUSessionResourceReleasedListRelRes) {
......
......@@ -53,13 +53,11 @@ ngap_app::ngap_app(const std::string& address, const uint16_t port_num)
ngap_app::~ngap_app() {}
//------------------------------------------------------------------------------
// received sctp payload and decode it to NGAP message and send itti message to
// TASK_AMF_N2
void ngap_app::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) {
Logger::ngap().debug(
"Handling SCTP payload from sctp_server on assoc_id (%d), stream_id "
"Handling SCTP payload from SCTP Server on assoc_id (%d), stream_id "
"(%d), instreams (%d), outstreams (%d)",
assoc_id, stream, instreams, outstreams);
Ngap_NGAP_PDU_t* ngap_msg_pdu =
......@@ -71,14 +69,13 @@ void ngap_app::handle_receive(
"Decoded NGAP message, procedure code %d, present %d",
ngap_msg_pdu->choice.initiatingMessage->procedureCode,
ngap_msg_pdu->present);
// Handle the message
(*messages_callback[ngap_msg_pdu->choice.initiatingMessage->procedureCode]
[ngap_msg_pdu->present - 1])(
assoc_id, stream, ngap_msg_pdu);
}
//------------------------------------------------------------------------------
// handle new sctp association
// TNL association(clause 8.7.1.1, 3gpp ts38.413)
void ngap_app::handle_sctp_new_association(
sctp_assoc_id_t assoc_id, sctp_stream_id_t instreams,
sctp_stream_id_t outstreams) {
......@@ -114,12 +111,20 @@ void ngap_app::handle_sctp_new_association(
}
}
//------------------------------------------------------------------------------
void ngap_app::handle_sctp_shutdown(sctp_assoc_id_t assoc_id) {
Logger::ngap().debug(
"Handle a SCTP Shutdown event (association id: %d)", assoc_id);
// Handle the message
(*events_callback[0])(assoc_id);
}
//------------------------------------------------------------------------------
uint32_t ngap_app::getPpid() {
return ppid_;
}
// gnb context management
//------------------------------------------------------------------------------
bool ngap_app::is_assoc_id_2_gnb_context(
const sctp_assoc_id_t& assoc_id) const {
......@@ -139,6 +144,7 @@ void ngap_app::set_assoc_id_2_gnb_context(
const sctp_assoc_id_t& assoc_id, std::shared_ptr<gnb_context> gc) {
std::shared_lock lock(m_assoc2gnbContext);
assoc2gnbContext[assoc_id] = gc;
return;
}
//------------------------------------------------------------------------------
......@@ -157,6 +163,16 @@ std::shared_ptr<gnb_context> ngap_app::gnb_id_2_gnb_context(
//------------------------------------------------------------------------------
void ngap_app::set_gnb_id_2_gnb_context(
const long& gnb_id, std::shared_ptr<gnb_context> gc) {
std::shared_lock lock(m_gnbid2gnbContext);
std::unique_lock lock(m_gnbid2gnbContext);
gnbid2gnbContext[gnb_id] = gc;
return;
}
//------------------------------------------------------------------------------
void ngap_app::remove_gnb_context(const long& gnb_id) {
if (is_gnb_id_2_gnb_context(gnb_id)) {
std::unique_lock lock(m_gnbid2gnbContext);
gnbid2gnbContext.erase(gnb_id);
return;
}
}
......@@ -48,13 +48,33 @@ class ngap_app : public sctp_application {
~ngap_app();
uint32_t getPpid();
/*
* Handle SCTP payload (decode it and send ITTI msg to N2)
* @param [bstring] payload: payload
* @param [sctp_assoc_id_t] assoc_id: gNB association ID
* @param [sctp_stream_id_t] stream: stream
* @param [sctp_stream_id_t] instreams: instreams
* @param [sctp_stream_id_t] outstreams: outstreams
* @return void:
*/
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);
/*
* Handle new SCTP TNL Association (clause 8.7.1.1, 3gpp ts38.413)
* @param [sctp_assoc_id_t] assoc_id: gNB association ID
* @param [sctp_stream_id_t] instreams: instreams
* @param [sctp_stream_id_t] outstreams: outstreams
* @return void:
*/
void handle_sctp_new_association(
sctp_assoc_id_t assoc_id, sctp_stream_id_t instreams,
sctp_stream_id_t outstreams);
void handle_sctp_shutdown(sctp_assoc_id_t assoc_id);
// gnb context management
bool is_assoc_id_2_gnb_context(const sctp_assoc_id_t& assoc_id) const;
void set_assoc_id_2_gnb_context(
const sctp_assoc_id_t& assoc_id, std::shared_ptr<gnb_context> gc);
......@@ -65,6 +85,8 @@ class ngap_app : public sctp_application {
const long& gnb_id, std::shared_ptr<gnb_context> gc);
std::shared_ptr<gnb_context> gnb_id_2_gnb_context(const long& gnb_id) const;
void remove_gnb_context(const long& gnb_id);
protected:
sctp_server sctp_s_38412;
uint32_t ppid_;
......
......@@ -39,6 +39,7 @@
#include "itti_msg_n11.hpp"
#include "itti.hpp"
#include "NGSetupRequest.hpp"
#include "NGReset.hpp"
#include "PduSessionResourceSetupResponse.hpp"
#include "PduSessionResourceReleaseResponse.hpp"
#include "InitialContextSetupResponse.hpp"
......@@ -52,11 +53,14 @@ using namespace amf_application;
extern itti_mw* itti_inst;
extern amf_n1* amf_n1_inst;
extern amf_n11* amf_n11_inst;
extern amf_app* amf_app_inst;
typedef int (*ngap_message_decoded_callback)(
const sctp_assoc_id_t assoc_id, const sctp_stream_id_t stream,
struct Ngap_NGAP_PDU* message_p);
typedef void (*ngap_event_callback)(const sctp_assoc_id_t assoc_id);
//------------------------------------------------------------------------------
int ngap_amf_handle_ng_setup_request(
const sctp_assoc_id_t assoc_id, const sctp_stream_id_t stream,
......@@ -403,16 +407,16 @@ int ngap_amf_handle_pdu_session_resource_setup_response(
amf_n1_inst->amf_ue_id_2_nas_context(amf_ue_ngap_id);
string supi = "imsi-" + nct.get()->imsi;
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);
if (!psc) {
Logger::amf_n1().error("connot get pdu_session_context");
return 0;
if (amf_app_inst->find_pdu_session_context(
supi, list_fail[0].pduSessionId, psc)) {
if (psc.get() == nullptr) {
Logger::amf_n1().error("Cannot get pdu_session_context");
return -1;
}
}
psc.get()->isn2sm_avaliable = false;
Logger::ngap().debug(
"receive pdu session resource setup response fail(multi pdu session "
"Receive pdu session resource setup response fail (multi pdu session "
"id),set pdu session context isn2sm_avaliable = false");
/*Logger::ngap().debug("Sending itti ue context release command to
TASK_AMF_N2"); itti_ue_context_release_command * itti_msg = new
......@@ -646,7 +650,27 @@ int nas_non_delivery_indication(
int ng_reset(
const sctp_assoc_id_t assoc_id, const sctp_stream_id_t stream,
struct Ngap_NGAP_PDU* message_p) {
Logger::ngap().debug("Sending itti ng reset to TASK_AMF_N2");
Logger::ngap().debug("Sending ITTI NG Reset to TASK_AMF_N2");
asn_fprint(stderr, &asn_DEF_Ngap_NGAP_PDU, message_p);
NGResetMsg* ngReset = new NGResetMsg();
if (!ngReset->decodefrompdu(message_p)) {
Logger::ngap().error("Decoding NGReset message error");
return -1;
}
itti_ng_reset* itti_msg = new itti_ng_reset(TASK_NGAP, TASK_AMF_N2);
itti_msg->assoc_id = assoc_id;
itti_msg->stream = stream;
itti_msg->ngReset = ngReset;
std::shared_ptr<itti_ng_reset> i = std::shared_ptr<itti_ng_reset>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::ngap().error(
"Could not send ITTI message %s to task TASK_AMF_N2",
i->get_msg_name());
}
return 0;
}
......@@ -979,4 +1003,27 @@ ngap_message_decoded_callback messages_callback[][3] = {
};
//------------------------------------------------------------------------------
void ngap_sctp_shutdown(const sctp_assoc_id_t assoc_id) {
Logger::ngap().debug("Sending ITTI SCTP Shutdown event to TASK_AMF_N2");
itti_ng_shutdown* itti_msg = new itti_ng_shutdown(TASK_NGAP, TASK_AMF_N2);
itti_msg->assoc_id = assoc_id;
std::shared_ptr<itti_ng_shutdown> i =
std::shared_ptr<itti_ng_shutdown>(itti_msg);
int ret = itti_inst->send_msg(i);
if (0 != ret) {
Logger::ngap().error(
"Could not send ITTI message %s to task TASK_AMF_N2",
i->get_msg_name());
}
return;
}
//------------------------------------------------------------------------------
ngap_event_callback events_callback[][1] = {
{ngap_sctp_shutdown},
{0} /*reserved*/
};
#endif
......@@ -6,7 +6,7 @@ using namespace oai::amf::api;
void AMFApiServer::init(size_t thr) {
auto opts = Pistache::Http::Endpoint::options().threads(thr);
opts.flags(Pistache::Tcp::Options::ReuseAddr);
opts.maxPayload(PISTACHE_SERVER_MAX_PAYLOAD);
opts.maxRequestSize(PISTACHE_SERVER_MAX_PAYLOAD);
m_httpEndpoint->init(opts);
m_individualSubscriptionDocumentApiImpl->init();
m_individualUeContextDocumentApiImpl->init();
......
......@@ -175,9 +175,8 @@ int sctp_server::sctp_read_from_socket(int sd, uint32_t ppid) {
switch (snp->sn_header.sn_type) {
case SCTP_SHUTDOWN_EVENT: {
Logger::sctp().debug("SCTP Shutdown Event received");
return sctp_handle_com_down(snp->sn_shutdown_event.sse_assoc_id);
break;
// return sctp_handle_com_down((sctp_assoc_id_t)
// snp->sn_shutdown_event.sse_assoc_id);
}
case SCTP_ASSOC_CHANGE: {
Logger::sctp().debug("SCTP Association Change event received");
......@@ -218,7 +217,8 @@ int sctp_server::sctp_read_from_socket(int sd, uint32_t ppid) {
//------------------------------------------------------------------------------
int sctp_server::sctp_handle_com_down(sctp_assoc_id_t assoc_id) {
return 0;
app_->handle_sctp_shutdown(assoc_id);
return 0;
}
//------------------------------------------------------------------------------
......
......@@ -83,8 +83,9 @@ class sctp_application {
sctp_stream_id_t instreams, sctp_stream_id_t outstreams) = 0;
virtual void handle_sctp_new_association(
sctp_assoc_id_t assoc_id, sctp_stream_id_t instreams,
sctp_stream_id_t outstreams) = 0;
virtual uint32_t getPpid() = 0;
sctp_stream_id_t outstreams) = 0;
virtual void handle_sctp_shutdown(sctp_assoc_id_t assoc_id) = 0;
virtual uint32_t getPpid() = 0;
};
class sctp_server {
......
......@@ -48,7 +48,7 @@ void display_backtrace(void) {
size = backtrace(array, 10);
strings = backtrace_symbols(array, size);
printf("Obtained %d stack frames.\n", size);
printf("Obtained %ld stack frames.\n", size);
for (i = 0; i < size; i++) printf("%s\n", strings[i]);
......
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