Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
OpenXG-AMF
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
1
Issues
1
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenXG
OpenXG-AMF
Commits
c509d831
Commit
c509d831
authored
Jan 20, 2022
by
Tien-Thinh Nguyen
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use ITTI to send N1 Message Notification message to AMF App to process
parent
f5e31641
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
235 additions
and
145 deletions
+235
-145
src/amf-app/amf_app.cpp
src/amf-app/amf_app.cpp
+205
-118
src/amf-app/amf_app.hpp
src/amf-app/amf_app.hpp
+1
-11
src/ngap/ngapIEs/GNB-ID.cpp
src/ngap/ngapIEs/GNB-ID.cpp
+12
-6
src/ngap/ngapIEs/GNB-ID.hpp
src/ngap/ngapIEs/GNB-ID.hpp
+3
-1
src/sbi/amf_server/impl/N1MessageNotifyApiImpl.cpp
src/sbi/amf_server/impl/N1MessageNotifyApiImpl.cpp
+14
-9
No files found.
src/amf-app/amf_app.cpp
View file @
c509d831
...
...
@@ -124,6 +124,13 @@ void amf_app_task(void*) {
amf_app_inst
->
handle_itti_message
(
ref
(
*
m
));
}
break
;
case
SBI_N1_MESSAGE_NOTIFICATION
:
{
Logger
::
amf_app
().
debug
(
"Received SBI_N1_MESSAGE_NOTIFICATION"
);
itti_sbi_n1_message_notification
*
m
=
dynamic_cast
<
itti_sbi_n1_message_notification
*>
(
msg
);
amf_app_inst
->
handle_itti_message
(
ref
(
*
m
));
}
break
;
case
TIME_OUT
:
{
if
(
itti_msg_timeout
*
to
=
dynamic_cast
<
itti_msg_timeout
*>
(
msg
))
{
switch
(
to
->
arg1_user
)
{
...
...
@@ -140,6 +147,7 @@ void amf_app_task(void*) {
}
}
}
break
;
case
TERMINATE
:
{
if
(
itti_msg_terminate
*
terminate
=
dynamic_cast
<
itti_msg_terminate
*>
(
msg
))
{
...
...
@@ -401,6 +409,203 @@ void amf_app::handle_itti_message(
}
}
//------------------------------------------------------------------------------
void
amf_app
::
handle_itti_message
(
itti_sbi_n1_message_notification
&
itti_msg
)
{
Logger
::
amf_app
().
info
(
"Handle a N1 Message Notification from the initial AMF"
);
// Step 1. Get UE, gNB related information
// Get NAS message (RegistrationRequest, this message included
// in N1 Message Notify is actually is RegistrationRequest from UE to the
// initial AMF)
bstring
n1sm
;
conv
::
msg_str_2_msg_hex
(
itti_msg
.
n1sm
,
n1sm
);
// get RegistrationContextContainer including gNB info
// UE context information, N1 message from UE, AN address
oai
::
amf
::
model
::
RegistrationContextContainer
registration_context
=
itti_msg
.
notification_msg
.
getRegistrationCtxtContainer
();
// UE Context
oai
::
amf
::
model
::
UeContext
ue_ctx
=
registration_context
.
getUeContext
();
std
::
string
supi
=
{};
std
::
shared_ptr
<
ue_context
>
uc
=
{};
if
(
ue_ctx
.
supiIsSet
())
{
supi
=
ue_ctx
.
getSupi
();
if
(
!
is_supi_2_ue_context
(
supi
))
{
// Create a new UE Context
Logger
::
amf_app
().
debug
(
"No existing UE Context, Create a new one with SUPI %s"
,
supi
.
c_str
());
uc
=
std
::
shared_ptr
<
ue_context
>
(
new
ue_context
());
uc
->
amf_ue_ngap_id
=
-
1
;
uc
->
supi
=
supi
;
set_supi_2_ue_context
(
supi
,
uc
);
}
else
{
// Update UE Context
uc
=
supi_2_ue_context
(
supi
);
}
}
// TODO: 5gMmCapability
// TODO: MmContext
// TODO: PduSessionContext
// GlobalRAN Node ID (~in NGSetupRequest)
oai
::
amf
::
model
::
GlobalRanNodeId
ran_node_id
=
registration_context
.
getRanNodeId
();
// RAN UE NGAP ID
uint32_t
ran_ue_ngap_id
=
registration_context
.
getAnN2ApId
();
// UserLocation getUserLocation()
// std::string getAnN2IPv4Addr()
// AllowedNssai getAllowedNssai()
// std::vector<ConfiguredSnssai>& getConfiguredNssai();
// rejectedNssaiInPlmn
// rejectedNssaiInTa
// std::string getInitialAmfName()
// Step 2. Create gNB context if necessary
// How to create gNB context without SCTP association?
// TODO: How to establish SCTP connection between the Target AMF and gNB?
std
::
shared_ptr
<
gnb_context
>
gc
=
{};
if
(
ran_node_id
.
gNbIdIsSet
())
{
oai
::
amf
::
model
::
GNbId
gnb_id_model
=
ran_node_id
.
getGNbId
();
uint32_t
gnb_id
=
{};
try
{
gnb_id
=
std
::
stoul
(
gnb_id_model
.
getGNBValue
(),
nullptr
,
10
);
}
catch
(
const
std
::
exception
&
e
)
{
Logger
::
amf_app
().
warn
(
"Error when converting from string to int for gNB Value: %s"
,
e
.
what
());
return
;
}
gc
->
globalRanNodeId
=
gnb_id
;
// TODO: gc->gnb_name
// TODO: DefaultPagingDRX
// TODO: Supported TA List
amf_n2_inst
->
set_gnb_id_2_gnb_context
(
gnb_id
,
gc
);
}
// Step 3. Create UE Context
/*
if (!is_supi_2_ue_context(itti_msg.ue_id)) {
// TODO: Create a new UE Context
} else { // Update UE Context
uc = supi_2_ue_context(itti_msg.ue_id);
}
*/
long
amf_ue_ngap_id
=
-
1
;
// Generate AMF UE NGAP ID if necessary
if
(
!
uc
.
get
())
{
// No UE context existed
amf_ue_ngap_id
=
generate_amf_ue_ngap_id
();
}
else
{
if
((
amf_ue_ngap_id
=
uc
->
amf_ue_ngap_id
)
==
-
1
)
{
amf_ue_ngap_id
=
generate_amf_ue_ngap_id
();
}
}
string
ue_context_key
=
"app_ue_ranid_"
+
to_string
(
ran_ue_ngap_id
)
+
":amfid_"
+
to_string
(
amf_ue_ngap_id
);
if
(
!
is_ran_amf_id_2_ue_context
(
ue_context_key
))
{
Logger
::
amf_app
().
debug
(
"No existing UE Context associated with UE Context Key %s"
,
ue_context_key
.
c_str
());
if
(
!
uc
.
get
())
{
// Create a new UE Context
Logger
::
amf_app
().
debug
(
"Create a new UE Context with UE Context Key"
,
ue_context_key
.
c_str
());
uc
=
std
::
shared_ptr
<
ue_context
>
(
new
ue_context
());
}
set_ran_amf_id_2_ue_context
(
ue_context_key
,
uc
);
}
else
{
uc
=
ran_amf_id_2_ue_context
(
ue_context_key
);
}
// Return if UE Context is still invalid
if
(
!
uc
.
get
())
{
Logger
::
amf_app
().
error
(
"Failed to get UE Context"
);
return
;
}
// Update info for UE context
uc
.
get
()
->
amf_ue_ngap_id
=
amf_ue_ngap_id
;
uc
.
get
()
->
ran_ue_ngap_id
=
ran_ue_ngap_id
;
// RrcEstCause
if
(
registration_context
.
rrcEstCauseIsSet
())
{
uint8_t
rrc_cause
=
{};
try
{
rrc_cause
=
std
::
stoul
(
registration_context
.
getRrcEstCause
(),
nullptr
,
10
);
}
catch
(
const
std
::
exception
&
e
)
{
Logger
::
amf_app
().
warn
(
"Error when converting from string to int for RrcEstCause: %s"
,
e
.
what
());
rrc_cause
=
0
;
}
uc
.
get
()
->
rrc_estb_cause
=
(
e_Ngap_RRCEstablishmentCause
)
rrc_cause
;
}
// ueContextRequest
uc
.
get
()
->
isUeContextRequest
=
registration_context
.
isUeContextRequest
();
// Step 4. Create UE NGAP Context if necessary
// Create/Update UE NGAP Context
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_app
().
debug
(
"Create a new UE NGAP context with ran_ue_ngap_id 0x%x"
,
ran_ue_ngap_id
);
unc
=
std
::
shared_ptr
<
ue_ngap_context
>
(
new
ue_ngap_context
());
amf_n2_inst
->
set_ran_ue_ngap_id_2_ue_ngap_context
(
ran_ue_ngap_id
,
unc
);
}
else
{
unc
=
amf_n2_inst
->
ran_ue_id_2_ue_ngap_context
(
ran_ue_ngap_id
);
if
(
!
unc
.
get
())
{
Logger
::
amf_app
().
error
(
"Failed to get UE NGAP context for ran_ue_ngap_id 0x%x"
,
ran_ue_ngap_id
);
return
;
}
}
// Store related information into UE NGAP context
unc
.
get
()
->
ran_ue_ngap_id
=
ran_ue_ngap_id
;
// TODO: unc.get()->sctp_stream_recv
// TODO: unc.get()->sctp_stream_send
// TODO: gc.get()->next_sctp_stream
// TODO: unc.get()->gnb_assoc_id
// TODO: unc.get()->tai
// Step 5. Trigger the procedure following RegistrationRequest
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
->
ran_ue_ngap_id
=
ran_ue_ngap_id
;
itti_n1_msg
->
is_nas_signalling_estab_req
=
true
;
itti_n1_msg
->
nas_msg
=
n1sm
;
itti_n1_msg
->
mcc
=
ran_node_id
.
getPlmnId
().
getMcc
();
itti_n1_msg
->
mnc
=
ran_node_id
.
getPlmnId
().
getMnc
();
;
itti_n1_msg
->
is_guti_valid
=
false
;
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
);
if
(
0
!=
ret
)
{
Logger
::
amf_app
().
error
(
"Could not send ITTI message %s to task TASK_AMF_N1"
,
i
->
get_msg_name
());
}
return
;
}
// AMF Client response handlers
//------------------------------------------------------------------------------
void
amf_app
::
handle_post_sm_context_response_error_400
()
{
...
...
@@ -494,124 +699,6 @@ bool amf_app::handle_nf_status_notification(
return
true
;
}
//------------------------------------------------------------------------------
bool
amf_app
::
handle_n1_message_notification
(
std
::
shared_ptr
<
itti_sbi_n1_message_notification
>&
msg
,
oai
::
amf
::
model
::
ProblemDetails
&
problem_details
,
uint32_t
&
http_code
)
{
Logger
::
amf_app
().
info
(
"Handle a N1 Message Notification from the initial AMF (HTTP version "
"%d)"
,
msg
->
http_version
);
// Step 1. Get UE, gNB related information
// Get NAS message (RegistrationRequest, this message included
// in N1 Message Notify is actually is RegistrationRequest from UE to the
// initial AMF)
bstring
n1sm
;
conv
::
msg_str_2_msg_hex
(
msg
->
n1sm
,
n1sm
);
// get RegistrationContextContainer including gNB info
// UE context information, N1 message from UE, AN address
oai
::
amf
::
model
::
RegistrationContextContainer
registration_context
=
msg
->
notification_msg
.
getRegistrationCtxtContainer
();
// UE context
// UeContext getUeContext()
// GlobalRAN Node ID (~in NGSetupRequest)
oai
::
amf
::
model
::
GlobalRanNodeId
ran_node_id
=
registration_context
.
getRanNodeId
();
// RAN UE NGAP ID
uint32_t
ran_ue_ngap_id
=
registration_context
.
getAnN2ApId
();
// UserLocation getUserLocation()
// std::string getAnN2IPv4Addr()
// AllowedNssai getAllowedNssai() const;
// std::vector<ConfiguredSnssai>& getConfiguredNssai();
// rejectedNssaiInPlmn
// rejectedNssaiInTa
// std::string getInitialAmfName()
// Step 2. Create gNB context if necessary
// How to create gNB context without SCTP association?
// TODO: How to establish SCTP connection between the Target AMF and gNB?
std
::
shared_ptr
<
gnb_context
>
gc
=
{};
// Step 3. Create UE Context
// TODO: to be verified since UE context is also bound with (AMF UE NGAP ID,
// RAN UE NGAP ID)
std
::
shared_ptr
<
ue_context
>
uc
=
{};
if
(
!
is_supi_2_ue_context
(
msg
->
ue_id
))
{
// TODO: Create a new UE Context
}
else
{
// Update UE Context
uc
=
supi_2_ue_context
(
msg
->
ue_id
);
}
if
(
registration_context
.
rrcEstCauseIsSet
())
{
// std::string getRrcEstCause()
// TODO: rrc_cause = registration_context.getRrcEstCause();
// TODO: uc.get()->rrc_estb_cause = (e_Ngap_RRCEstablishmentCause)
// rrc_cause;
}
// ueContextRequest
uc
.
get
()
->
isUeContextRequest
=
registration_context
.
isUeContextRequest
();
// Step 4. Create UE NGAP Context if necessary
long
amf_ue_ngap_id
=
0
;
// Check UE Context
// TODO: check UE context here or above based on SUPI
if
((
amf_ue_ngap_id
=
uc
->
amf_ue_ngap_id
)
==
-
1
)
{
amf_ue_ngap_id
=
generate_amf_ue_ngap_id
();
}
uc
.
get
()
->
amf_ue_ngap_id
=
amf_ue_ngap_id
;
string
ue_context_key
=
"app_ue_ranid_"
+
to_string
(
ran_ue_ngap_id
)
+
":amfid_"
+
to_string
(
amf_ue_ngap_id
);
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
());
uc
=
std
::
shared_ptr
<
ue_context
>
(
new
ue_context
());
set_ran_amf_id_2_ue_context
(
ue_context_key
,
uc
);
}
// Create/Update UE NGAP Context
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_app
().
debug
(
"Create a new UE NGAP context with ran_ue_ngap_id 0x%x"
,
ran_ue_ngap_id
);
unc
=
std
::
shared_ptr
<
ue_ngap_context
>
(
new
ue_ngap_context
());
amf_n2_inst
->
set_ran_ue_ngap_id_2_ue_ngap_context
(
ran_ue_ngap_id
,
unc
);
}
else
{
unc
=
amf_n2_inst
->
ran_ue_id_2_ue_ngap_context
(
ran_ue_ngap_id
);
if
(
!
unc
.
get
())
{
Logger
::
amf_app
().
error
(
"Failed to get UE NGAP context for ran_ue_ngap_id 0x%x"
,
ran_ue_ngap_id
);
return
false
;
}
}
// Store related information into UE NGAP context
unc
.
get
()
->
ran_ue_ngap_id
=
ran_ue_ngap_id
;
// TODO: unc.get()->sctp_stream_recv
// TODO: unc.get()->sctp_stream_send
// TODO: gc.get()->next_sctp_stream
// TODO: unc.get()->gnb_assoc_id
// TODO: unc.get()->tai
// Step 5. Trigger the procedure following RegistrationRequest
// TODO:
http_code
=
204
;
// HTTP_STATUS_CODE_204_NO_CONTENT;
return
true
;
}
//------------------------------------------------------------------------------
void
amf_app
::
generate_uuid
()
{
amf_instance_id
=
to_string
(
boost
::
uuids
::
random_generator
()());
...
...
src/amf-app/amf_app.hpp
View file @
c509d831
...
...
@@ -83,6 +83,7 @@ class amf_app {
// itti handlers
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_sbi_n1_message_notification
&
itti_msg
);
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
(
...
...
@@ -161,17 +162,6 @@ class amf_app {
std
::
shared_ptr
<
itti_sbi_notification_data
>&
msg
,
oai
::
amf
::
model
::
ProblemDetails
&
problem_details
,
uint32_t
&
http_code
);
/*
* Handle N1 Message Notification
* @param [std::shared_ptr<itti_sbi_n1_message_notification>& ] msg: message
* @param [oai::amf::model::ProblemDetails& ] problem_details
* @param [uint8_t&] http_code
* @return true if handle sucessfully, otherwise return false
*/
bool
handle_n1_message_notification
(
std
::
shared_ptr
<
itti_sbi_n1_message_notification
>&
msg
,
oai
::
amf
::
model
::
ProblemDetails
&
problem_details
,
uint32_t
&
http_code
);
/*
* Generate a random UUID for SMF instance
* @param [void]
...
...
src/ngap/ngapIEs/GNB-ID.cpp
View file @
c509d831
...
...
@@ -47,26 +47,32 @@ void GNB_ID::setValue(uint32_t gnbId) {
uint8_t
len
=
0
;
for
(
uint32_t
i
=
0x00000001
;
i
<=
0x00000400
;
i
=
i
<<
1
,
len
++
)
{
if
((
i
&
gnbId
))
{
gNBId
.
bit
eslen
=
32
-
len
;
gNBId
.
bit
_length
=
32
-
len
;
break
;
}
}
if
(
!
((
gNBId
.
bit
eslen
>=
22
)
&&
(
gNBId
.
biteslen
<=
32
)))
{
if
(
!
((
gNBId
.
bit
_length
>=
22
)
&&
(
gNBId
.
bit_length
<=
32
)))
{
cout
<<
"[warning][gNBID length out of range]"
<<
endl
;
}
}
//------------------------------------------------------------------------------
void
GNB_ID
::
setValue
(
uint32_t
id
,
uint8_t
bit_length
)
{
gNBId
.
id
=
id
;
gNBId
.
bit_length
=
bit_length
;
}
//------------------------------------------------------------------------------
bool
GNB_ID
::
encode2bitstring
(
Ngap_GNB_ID_t
&
gnbid
)
{
gnbid
.
present
=
Ngap_GNB_ID_PR_gNB_ID
;
if
(
!
(
gNBId
.
bit
eslen
%
8
))
gnbid
.
choice
.
gNB_ID
.
size
=
gNBId
.
bit
eslen
/
8
;
if
(
!
(
gNBId
.
bit
_length
%
8
))
gnbid
.
choice
.
gNB_ID
.
size
=
gNBId
.
bit
_length
/
8
;
else
gnbid
.
choice
.
gNB_ID
.
size
=
gNBId
.
bit
eslen
/
8
+
1
;
gnbid
.
choice
.
gNB_ID
.
size
=
gNBId
.
bit
_length
/
8
+
1
;
// printf("m_gNBId.size(%d)\n",m_gNBId.size);
gnbid
.
choice
.
gNB_ID
.
bits_unused
=
32
-
gNBId
.
bit
eslen
;
gnbid
.
choice
.
gNB_ID
.
bits_unused
=
32
-
gNBId
.
bit
_length
;
gnbid
.
choice
.
gNB_ID
.
buf
=
(
uint8_t
*
)
calloc
(
1
,
4
*
sizeof
(
uint8_t
));
if
(
!
gnbid
.
choice
.
gNB_ID
.
buf
)
return
false
;
gnbid
.
choice
.
gNB_ID
.
buf
[
3
]
=
gNBId
.
id
&
0x000000ff
;
...
...
src/ngap/ngapIEs/GNB-ID.hpp
View file @
c509d831
...
...
@@ -45,10 +45,12 @@ class GNB_ID {
void
setValue
(
uint32_t
gnbId
);
long
getValue
();
void
setValue
(
uint32_t
id
,
uint8_t
bit_length
);
private:
struct
gNBId_s
{
uint32_t
id
;
uint8_t
bit
eslen
;
uint8_t
bit
_length
;
}
gNBId
;
// 22bits to 32bits
};
...
...
src/sbi/amf_server/impl/N1MessageNotifyApiImpl.cpp
View file @
c509d831
...
...
@@ -14,8 +14,11 @@
#include "N1MessageNotifyApiImpl.h"
#include "itti_msg_sbi.hpp"
#include "conversions.hpp"
#include "itti.hpp"
using
namespace
amf_application
;
extern
itti_mw
*
itti_inst
;
namespace
oai
{
namespace
amf
{
namespace
api
{
...
...
@@ -47,15 +50,17 @@ void N1MessageNotifyApiImpl::receive_n1_message_notification(
oai
::
amf
::
model
::
ProblemDetails
problem_details
=
{};
uint32_t
http_code
=
{
0
};
if
(
m_amf_app
->
handle_n1_message_notification
(
itti_msg
,
problem_details
,
http_code
))
{
response
.
send
(
Pistache
::
Http
::
Code
(
http_code
));
}
else
{
response
.
headers
().
add
<
Pistache
::
Http
::
Header
::
ContentType
>
(
Pistache
::
Http
::
Mime
::
MediaType
(
"application/problem+json"
));
nlohmann
::
json
json_data
=
{};
to_json
(
json_data
,
problem_details
);
response
.
send
(
Pistache
::
Http
::
Code
(
http_code
),
json_data
.
dump
().
c_str
());
// Send response
response
.
send
(
Pistache
::
Http
::
Code
::
No_Content
);
// TODO: problem
// Process N1 Notification Message at AMF APP
int
ret
=
itti_inst
->
send_msg
(
itti_msg
);
if
(
0
!=
ret
)
{
Logger
::
amf_server
().
error
(
"Could not send ITTI message %s to task TASK_AMF_N2"
,
itti_msg
->
get_msg_name
());
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment